rc-js-util
Version:
A collection of TS and C++ utilities to help writing performant and correct applications, achieved through strict typing and (removable) invariant checking.
84 lines (69 loc) • 3.81 kB
text/typescript
import { SanitizedEmscriptenTestModule } from "../emscripten/sanitized-emscripten-test-module.js";
import { SharedMemoryBlock } from "./shared-memory-block.js";
import utilTestModule from "../../external/test-module.mjs";
import { Test_setDefaultFlags } from "../../test-util/test_set-default-flags.js";
import { getTestModuleOptions, TestGarbageCollector } from "../../test-util/test-utils.js";
import { fpRunWithin } from "../../fp/impl/fp-run-within.js";
import { blockScope } from "../../lifecycle/block-scoped-lifecycle.js";
import { _Debug } from "../../debug/_debug.js";
describe("=> SharedMemoryBlock", () =>
{
const testModule = new SanitizedEmscriptenTestModule(utilTestModule, getTestModuleOptions());
beforeEach(async () =>
{
Test_setDefaultFlags();
await testModule.initialize();
});
afterEach(() =>
{
testModule.endEmscriptenProgram();
});
it("| creates, writes, reads and destroys without triggering the asan", fpRunWithin([blockScope], () =>
{
const smb = SharedMemoryBlock.createOne(testModule.wrapper, testModule.wrapper.rootNode, 128);
expect(smb.getDataView().byteLength).toEqual(128);
new Float32Array(smb.getDataView().buffer, smb.pointer, 4).set([1, 2, 3, 4]);
expect(smb.getDataView().getFloat32(0, true)).toEqual(1);
expect(smb.getDataView().getFloat32(Float32Array.BYTES_PER_ELEMENT, true)).toEqual(2);
expect(smb.getDataView().getFloat32(Float32Array.BYTES_PER_ELEMENT * 2, true)).toEqual(3);
expect(smb.getDataView().getFloat32(Float32Array.BYTES_PER_ELEMENT * 3, true)).toEqual(4);
testModule.wrapper.rootNode.getLinked().unlinkAll();
expect(smb.resourceHandle.getIsDestroyed()).toBeTrue();
}));
it("| invalidates dataView on memory resize", fpRunWithin([blockScope], () =>
{
const smb = SharedMemoryBlock.createOne(testModule.wrapper, testModule.wrapper.rootNode, 128);
const dataView = smb.getDataView();
const smb2 = SharedMemoryBlock.createOne(testModule.wrapper, testModule.wrapper.rootNode, 16777216);
expect(() => dataView.getFloat32(0)).toThrow();
testModule.wrapper.rootNode.getLinked().unlink(smb.resourceHandle);
testModule.wrapper.rootNode.getLinked().unlink(smb2.resourceHandle);
}));
it("| invalidates dataView on memory release", fpRunWithin([blockScope], () =>
{
const smb = SharedMemoryBlock.createOne(testModule.wrapper, testModule.wrapper.rootNode, 128);
testModule.wrapper.rootNode.getLinked().unlink(smb.resourceHandle);
expect(() => smb.getDataView().getFloat32(0)).toThrow();
}));
it("| updates the dataView on resize", fpRunWithin([blockScope], () =>
{
const smb = SharedMemoryBlock.createOne(testModule.wrapper, testModule.wrapper.rootNode, 128);
const smb2 = SharedMemoryBlock.createOne(testModule.wrapper, testModule.wrapper.rootNode, 8388608);
smb.getDataView().getFloat32(0);
testModule.wrapper.rootNode.getLinked().unlink(smb.resourceHandle);
testModule.wrapper.rootNode.getLinked().unlink(smb2.resourceHandle);
}));
it("| errors when not released", async () =>
{
if (!_BUILD.DEBUG || !TestGarbageCollector.isAvailable)
{
return pending("Test not available in this environment");
}
const spy = spyOn(_Debug, "error");
// "forget" to use the return
SharedMemoryBlock.createOne(testModule.wrapper, testModule.wrapper.rootNode, 128);
expect(await TestGarbageCollector.testFriendlyGc()).toBeGreaterThan(0);
expect(spy).toHaveBeenCalledWith(jasmine.stringMatching("A shared object was leaked"));
testModule.wrapper.rootNode.getLinked().unlinkAll();
});
});