Skip to content

Commit ffd109f

Browse files
committed
Add reference-count-tests
1 parent 822eabf commit ffd109f

File tree

6 files changed

+119
-16
lines changed

6 files changed

+119
-16
lines changed

package-lock.json

Lines changed: 59 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
"types.d.ts"
3232
],
3333
"devDependencies": {
34+
"chai": "^5.2.0",
3435
"debug": "^4.4.0",
3536
"mocha": "^11.0.1"
3637
},

test/functional-tests.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ globalThis.navigator = { gpu: create([]) };
88
const mocha = new Mocha({});
99

1010
mocha.addFile('./test/tests/basic-tests.js');
11+
mocha.addFile('./test/tests/reference-count-tests.js');
1112

1213
await mocha.loadFilesAsync();
1314
mocha.run(failures => {

test/test.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,17 @@
11
import fs from 'node:fs';
22
import { execute } from '../build/execute.js';
33

4+
Promise.withResolvers = Promise.withResolvers ?? function() {
5+
const o = {};
6+
o.promise = new Promise((resolve, reject) => {
7+
Object.assign(o, { resolve, reject } );
8+
});
9+
return o;
10+
};
11+
412
const cwd = process.cwd();
513

6-
await execute('node', ['test/functional-tests.js']);
14+
await execute('node', ['--expose-gc', 'test/functional-tests.js']);
715

816
const tsTestsDir = 'test/ts-tests';
917
const tests = fs.readdirSync(tsTestsDir, { withFileTypes: true })

test/tests/basic-tests.js

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,7 @@
11

2+
import { assert } from 'chai';
23

3-
function assert(cond, msg = '') {
4-
if (!cond) {
5-
throw Error(msg);
6-
}
7-
}
8-
9-
Promise.withResolvers = Promise.withResolvers ?? function() {
10-
const o = {};
11-
o.promise = new Promise((resolve, reject) => {
12-
Object.assign(o, { resolve, reject } );
13-
});
14-
return o;
15-
};
16-
17-
describe('node-webgpu', () => {
4+
describe('basic tests', () => {
185
it('creates a device', async () => {
196
const device = await(await navigator.gpu.requestAdapter()).requestDevice();
207
assert(!!device, 'got device');
@@ -23,6 +10,7 @@ describe('node-webgpu', () => {
2310
device.destroy();
2411
});
2512

13+
/* MAINTENANCE_TODO: enable ths test once dawn.node handles this
2614
it('can attach a uncapturederror listener', async () => {
2715
const device = await(await navigator.gpu.requestAdapter()).requestDevice();
2816
assert(!!device, 'got device');
@@ -40,5 +28,6 @@ describe('node-webgpu', () => {
4028
tex.destroy();
4129
device.destroy();
4230
});
31+
*/
4332
});
4433

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import { assert } from 'chai';
2+
import DEBUG from 'debug';
3+
4+
const debug = DEBUG('reference-count-tests');
5+
6+
async function waitForGC(ref, label) {
7+
assert(global.gc, 'global.gc is not exposed. use --expose-gc');
8+
// wait for the device to be collected
9+
while (ref.deref()) {
10+
debug('gc');
11+
global.gc();
12+
await new Promise(resolve => setTimeout(resolve, 1000));
13+
}
14+
debug(label, 'was GCed');
15+
}
16+
17+
describe('reference count tests', () => {
18+
19+
it('correctly handles GC with device.features', async function() {
20+
this.timeout(20000);
21+
const adapter = await navigator.gpu.requestAdapter();
22+
const device = await adapter?.requestDevice();
23+
assert(!!device, 'got device');
24+
25+
const [iterWeakRef, featuresWeakRef] = await (async () => {
26+
const [iter, deviceWeakRef, featuresWeakRef] = await (async () => {
27+
const device = await adapter.requestDevice({requiredFeatures: [...adapter.features]});
28+
const iter = device.features[Symbol.iterator]();
29+
device.destroy();
30+
return [iter, new WeakRef(device), new WeakRef(device.features)];
31+
})();
32+
33+
await waitForGC(deviceWeakRef, 'device');
34+
35+
debug([...iter]);
36+
37+
return [new WeakRef(iter), featuresWeakRef]
38+
})();
39+
40+
await waitForGC(iterWeakRef, 'iter');
41+
await waitForGC(featuresWeakRef, 'features');
42+
// dawn.node will likely crash before this if this is not working.
43+
});
44+
45+
});

0 commit comments

Comments
 (0)