-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Add tests for unsafe-heap.ts * Add tests for unsafe-heap.ts * Add tests for constant-pool.ts * Add tests for constant-pool.ts * Add tests for thread.ts * Add tests for AbstractClassLoader.ts and BootstrapClassLoader.ts * Add tests for threadpool.ts * Add tests for threadpool.ts
- Loading branch information
Showing
8 changed files
with
531 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
import { JvmObject } from '../../types/reference/Object' | ||
import AbstractSystem from '../../utils/AbstractSystem' | ||
import AbstractClassLoader, { ApplicationClassLoader } from '../../ClassLoader/AbstractClassLoader' | ||
import { TestClassLoader } from '../__utils__/test-utils' | ||
|
||
describe('AbstractClassLoader', () => { | ||
test('Should properly delegate primitive class loading to the parent loader', () => { | ||
const mockParentLoader = { | ||
getPrimitiveClass: jest.fn().mockReturnValue({ | ||
getName: () => 'int', | ||
checkPrimitive: () => true | ||
}) | ||
} | ||
|
||
const mockSystem = {} as AbstractSystem | ||
const testLoader = new TestClassLoader(mockSystem, '/test/path', mockParentLoader as unknown as AbstractClassLoader) | ||
|
||
const result = testLoader.getPrimitiveClass("I") | ||
|
||
expect(result.getName()).toBe("int") | ||
expect(result.checkPrimitive()).toBe(true) | ||
}) | ||
|
||
test('Should properly set and return the Java object representing the ApplicationClassLoader', () => { | ||
const mockParentLoader = { | ||
getPrimitiveClass: jest.fn().mockReturnValue({ | ||
getName: () => 'int', | ||
checkPrimitive: () => true | ||
}) | ||
} | ||
|
||
const mockSystem = {} as AbstractSystem | ||
const testLoader = new ApplicationClassLoader(mockSystem, '/test/path', mockParentLoader as unknown as AbstractClassLoader) | ||
|
||
expect(testLoader.getJavaObject()).toBeNull() | ||
|
||
const mockJavaObject = {} as JvmObject | ||
testLoader._setJavaClassLoader(mockJavaObject) | ||
|
||
expect(testLoader.getJavaObject()).toBe(mockJavaObject) | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
// import { ErrorResult, ResultType } from '../../types/Result' | ||
import { PrimitiveClassData } from '../../types/class/ClassData' | ||
import AbstractSystem from '../../utils/AbstractSystem' | ||
import BootstrapClassLoader from '../../ClassLoader/BootstrapClassLoader' | ||
import { setupTest } from '../__utils__/test-utils' | ||
import AbstractClassLoader from '../../ClassLoader/AbstractClassLoader' | ||
|
||
// let testLoader: AbstractClassLoader | ||
let bootstrapLoader: BootstrapClassLoader | ||
let mockSystem: AbstractSystem | ||
|
||
beforeEach(() => { | ||
const setup = setupTest() | ||
// testLoader = setup.testLoader | ||
mockSystem = setup.testSystem | ||
bootstrapLoader = new BootstrapClassLoader(mockSystem, 'test/path') | ||
}) | ||
|
||
describe('BootstrapClassLoader', () => { | ||
test('Should create a BootstrapClassLoader instance with correct parameters', () => { | ||
const mockSystem = {} as AbstractSystem | ||
const classPath = 'test/path' | ||
const bootstrapLoader = new BootstrapClassLoader(mockSystem, classPath) | ||
|
||
expect(bootstrapLoader).toBeInstanceOf(BootstrapClassLoader) | ||
expect(bootstrapLoader).toBeInstanceOf(AbstractClassLoader) | ||
expect(bootstrapLoader['nativeSystem']).toBe(mockSystem) | ||
expect(bootstrapLoader['classPath']).toBe(classPath) | ||
expect(bootstrapLoader['primitiveClasses']).toEqual({}) | ||
}) | ||
|
||
// test('Should return an error result when loading an array class fails', () => { | ||
// const mockComponentClass: ClassData = {} as ClassData | ||
// const mockErrorCallback = jest.fn() | ||
// jest.spyOn(ArrayClassData.prototype, 'constructor').mockImplementation( | ||
// (_, __, ___, ____, errorCallback) => { | ||
// errorCallback({ status: ResultType.ERROR, msg: 'Mock error' }) | ||
// return {} as ArrayClassData | ||
// } | ||
// ) | ||
// | ||
// const result = bootstrapLoader['_loadArrayClass']('TestArray', mockComponentClass) as ErrorResult | ||
// | ||
// expect(result.status).toBe(ResultType.ERROR) | ||
// expect(result.msg).toBe('Mock error') | ||
// expect(mockErrorCallback).not.toHaveBeenCalled() | ||
// }) | ||
|
||
test('Should throw an error for invalid primitive class names', () => { | ||
expect(() => { | ||
bootstrapLoader.getPrimitiveClass('invalid_primitive') | ||
}).toThrow('Invalid primitive class name: invalid_primitive') | ||
|
||
expect(() => { | ||
bootstrapLoader.getPrimitiveClass('Object') | ||
}).toThrow('Invalid primitive class name: Object') | ||
|
||
expect(() => { | ||
bootstrapLoader.getPrimitiveClass('') | ||
}).toThrow('Invalid primitive class name: ') | ||
}) | ||
|
||
test('Should return a primitive class instance for valid primitive class names', () => { | ||
const primitiveClass = bootstrapLoader.getPrimitiveClass('I') | ||
|
||
expect(primitiveClass).toBeInstanceOf(PrimitiveClassData) | ||
expect(primitiveClass.getDescriptor()).toBe('I') | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
import { CONSTANT_TAG } from '../../ClassFile/constants/constants' | ||
import { ConstantInfo } from '../../ClassFile/types/constants' | ||
import { ClassData } from '../types/class/ClassData' | ||
import { | ||
// Constant, | ||
ConstantInteger, | ||
ConstantFloat, | ||
ConstantLong, | ||
ConstantDouble, | ||
ConstantUtf8, | ||
ConstantString, | ||
ConstantNameAndType, | ||
ConstantMethodType, | ||
ConstantClass, | ||
ConstantInvokeDynamic, | ||
ConstantFieldref, | ||
ConstantMethodref, | ||
ConstantInterfaceMethodref, | ||
ConstantMethodHandle | ||
} from '../types/class/Constants' | ||
// import { JvmArray } from '../types/reference/Array' | ||
import { ConstantPool } from '../constant-pool' | ||
import { setupTest } from './__utils__/test-utils' | ||
|
||
// let testLoader: TestClassLoader | ||
let classData: ClassData | ||
let constantInfos: ConstantInfo[] | ||
let constantPool: ConstantPool | ||
|
||
beforeEach(() => { | ||
const setup = setupTest() | ||
// testLoader = setup.testLoader | ||
classData = setup.classes.testClass | ||
constantInfos = [ | ||
{ tag: CONSTANT_TAG.Integer, value: 0 }, | ||
{ tag: CONSTANT_TAG.Integer, value: 42 }, | ||
{ tag: CONSTANT_TAG.Float, value: 3.14 }, | ||
{ tag: CONSTANT_TAG.Long, value: BigInt(1234567890) }, | ||
{ tag: CONSTANT_TAG.Double, value: 2.71828 }, | ||
{ tag: CONSTANT_TAG.Utf8, length: 13, value: 'Hello, World!' }, | ||
{ tag: CONSTANT_TAG.String, stringIndex: 5 }, | ||
{ tag: CONSTANT_TAG.NameAndType, nameIndex: 5, descriptorIndex: 5 }, | ||
{ tag: CONSTANT_TAG.MethodType, descriptorIndex: 5 }, | ||
{ tag: CONSTANT_TAG.Class, nameIndex: 5 }, | ||
{ tag: CONSTANT_TAG.InvokeDynamic, bootstrapMethodAttrIndex: 1, nameAndTypeIndex: 7 }, | ||
{ tag: CONSTANT_TAG.Fieldref, classIndex: 9, nameAndTypeIndex: 7 }, | ||
{ tag: CONSTANT_TAG.Methodref, classIndex: 9, nameAndTypeIndex: 7 }, | ||
{ tag: CONSTANT_TAG.InterfaceMethodref, classIndex: 9, nameAndTypeIndex: 7 }, | ||
{ tag: CONSTANT_TAG.MethodHandle, referenceKind: 1, referenceIndex: 12 } | ||
] | ||
|
||
constantPool = new ConstantPool(classData, constantInfos) | ||
}) | ||
|
||
describe('ConstantPool', () => { | ||
test('Should correctly initialize the constant pool with all provided constant types', () => { | ||
expect(constantPool.size()).toBe(15) | ||
expect(constantPool.get(1)).toBeInstanceOf(ConstantInteger) | ||
expect(constantPool.get(2)).toBeInstanceOf(ConstantFloat) | ||
expect(constantPool.get(3)).toBeInstanceOf(ConstantLong) | ||
expect(constantPool.get(4)).toBeInstanceOf(ConstantDouble) | ||
expect(constantPool.get(5)).toBeInstanceOf(ConstantUtf8) | ||
expect(constantPool.get(6)).toBeInstanceOf(ConstantString) | ||
expect(constantPool.get(7)).toBeInstanceOf(ConstantNameAndType) | ||
expect(constantPool.get(8)).toBeInstanceOf(ConstantMethodType) | ||
expect(constantPool.get(9)).toBeInstanceOf(ConstantClass) | ||
expect(constantPool.get(10)).toBeInstanceOf(ConstantInvokeDynamic) | ||
expect(constantPool.get(11)).toBeInstanceOf(ConstantFieldref) | ||
expect(constantPool.get(12)).toBeInstanceOf(ConstantMethodref) | ||
expect(constantPool.get(13)).toBeInstanceOf(ConstantInterfaceMethodref) | ||
expect(constantPool.get(14)).toBeInstanceOf(ConstantMethodHandle) | ||
|
||
expect((constantPool.get(1) as ConstantInteger).get()).toBe(42) | ||
expect((constantPool.get(2) as ConstantFloat).get()).toBe(3.14) | ||
expect((constantPool.get(3) as ConstantLong).get()).toBe(BigInt(1234567890)) | ||
expect((constantPool.get(4) as ConstantDouble).get()).toBe(2.71828) | ||
expect((constantPool.get(5) as ConstantUtf8).get()).toBe('Hello, World!') | ||
}) | ||
|
||
test('Should throw an error when get method is called with an invalid index', () => { | ||
const constantPool = new ConstantPool(classData, [ | ||
{ tag: CONSTANT_TAG.Utf8, length: 5, value: 'Test' } | ||
]) | ||
|
||
expect(constantPool.get(-1)).toBe(undefined) | ||
expect(constantPool.get(16)).toBe(undefined) | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
import { ThreadStatus } from '../constants' | ||
import { ThreadPool } from '../threadpool' | ||
import { ReferenceClassData } from '../types/class/ClassData' | ||
import { JvmObject } from '../types/reference/Object' | ||
import Thread from '../../jvm/thread' | ||
import JVM from '../../jvm/jvm' | ||
import { setupTest, TestThreadPool } from './__utils__/test-utils' | ||
|
||
let thread: Thread | ||
let threadClass: ReferenceClassData | ||
// let testLoader: TestClassLoader | ||
let jvm: JVM | ||
let threadPool: ThreadPool | ||
|
||
beforeEach(() => { | ||
const setup = setupTest() | ||
thread = setup.thread | ||
threadClass = setup.classes.threadClass | ||
// testLoader = setup.testLoader | ||
threadPool = new TestThreadPool(() => {}) | ||
}) | ||
|
||
describe('Thread', () => { | ||
test('should initialize a new thread with correct default values', () => { | ||
const threadObj = {} as JvmObject | ||
|
||
thread = new Thread(threadClass, jvm, threadPool, threadObj) | ||
|
||
expect(thread.getStatus()).toBe(ThreadStatus.NEW) | ||
expect(thread.getFrames()).toEqual([]) | ||
expect(thread.getJavaObject()).toBe(threadObj) | ||
expect(thread.getThreadPool()).toBe(threadPool) | ||
expect(thread.getJVM()).toBe(jvm) | ||
expect(thread.getThreadId()).toBe(1) | ||
expect(thread.isStackEmpty()).toBe(true) | ||
}) | ||
|
||
test('should correctly handle synchronized methods and monitor entering/exiting', () => { | ||
// TODO | ||
}); | ||
|
||
test('should properly manage thread status transitions', () => { | ||
const threadObj = new JvmObject(threadClass) | ||
thread = new Thread(threadClass, jvm, threadPool, threadObj) | ||
threadPool.updateStatus = jest.fn(); | ||
|
||
expect(thread.getStatus()).toBe(ThreadStatus.NEW) | ||
|
||
thread.setStatus(ThreadStatus.RUNNABLE) | ||
expect(thread.getStatus()).toBe(ThreadStatus.RUNNABLE) | ||
|
||
thread.setStatus(ThreadStatus.BLOCKED) | ||
expect(thread.getStatus()).toBe(ThreadStatus.BLOCKED) | ||
|
||
thread.setStatus(ThreadStatus.WAITING) | ||
expect(thread.getStatus()).toBe(ThreadStatus.WAITING) | ||
|
||
thread.setStatus(ThreadStatus.TIMED_WAITING) | ||
expect(thread.getStatus()).toBe(ThreadStatus.TIMED_WAITING) | ||
|
||
thread.setStatus(ThreadStatus.TERMINATED) | ||
expect(thread.getStatus()).toBe(ThreadStatus.TERMINATED) | ||
|
||
expect(threadPool.updateStatus).toHaveBeenCalledTimes(5) | ||
}) | ||
|
||
test('should manage wide (64-bit) values on the operand stack correctly', () => { | ||
// TODO | ||
}) | ||
}) |
Oops, something went wrong.
f5a4095
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Coverage report
Test suite run success
1120 tests passing in 63 suites.
Report generated by 🧪jest coverage report action from f5a4095