mirror of
https://github.com/scratchfoundation/scratch-vm.git
synced 2024-12-25 07:22:33 -05:00
6320fd72c3
This new test verifies that clones and their associated threads are cleaned up properly by the `delete this clone` block. The clones run two stacks each: one which waits and then deletes the clone, and another which includes a `forever` loop: this is to verify that the thread running the `forever` loop is ended when the clone itself is deleted. The project does this with two batches of clones to ensure there are no problems with reusing array indices previously occupied by now-removed threads or clones.
96 lines
2.9 KiB
JavaScript
96 lines
2.9 KiB
JavaScript
const path = require('path');
|
|
const test = require('tap').test;
|
|
const attachTestStorage = require('../fixtures/attach-test-storage');
|
|
const extract = require('../fixtures/extract');
|
|
const VirtualMachine = require('../../src/index');
|
|
|
|
const projectUri = path.resolve(__dirname, '../fixtures/clone-cleanup.sb2');
|
|
const project = extract(projectUri);
|
|
|
|
test('clone-cleanup', t => {
|
|
const vm = new VirtualMachine();
|
|
attachTestStorage(vm);
|
|
|
|
/**
|
|
* Track which step of the project is currently under test.
|
|
* @type {number}
|
|
*/
|
|
let testStep = -1;
|
|
|
|
/**
|
|
* We test using setInterval; track the interval ID here so we can cancel it.
|
|
* @type {object}
|
|
*/
|
|
let testInterval = null;
|
|
|
|
const verifyCounts = (expectedClones, extraThreads) => {
|
|
// stage plus one sprite, plus clones
|
|
t.strictEqual(vm.runtime.targets.length, 2 + expectedClones,
|
|
`target count at step ${testStep}`);
|
|
|
|
// the stage should never have any clones
|
|
t.strictEqual(vm.runtime.targets[0].sprite.clones.length, 1,
|
|
`stage clone count at step ${testStep}`);
|
|
|
|
// check sprite clone count (+1 for original)
|
|
t.strictEqual(vm.runtime.targets[1].sprite.clones.length, 1 + expectedClones,
|
|
`sprite clone count at step ${testStep}`);
|
|
|
|
// thread count isn't directly tied to clone count since threads can end
|
|
t.strictEqual(vm.runtime.threads.length, extraThreads + (2 * expectedClones),
|
|
`thread count at step ${testStep}`);
|
|
};
|
|
|
|
const testNextStep = () => {
|
|
++testStep;
|
|
switch (testStep) {
|
|
case 0:
|
|
// Project has started, main thread running, no clones yet
|
|
verifyCounts(0, 1);
|
|
break;
|
|
|
|
case 1:
|
|
// 10 clones have been created, main thread still running
|
|
verifyCounts(10, 1);
|
|
break;
|
|
|
|
case 2:
|
|
// The first batch of clones has deleted themselves; main thread still running
|
|
verifyCounts(0, 1);
|
|
break;
|
|
|
|
case 3:
|
|
// The second batch of clones has been created and the main thread has ended
|
|
verifyCounts(10, 0);
|
|
break;
|
|
|
|
case 4:
|
|
// The second batch of clones has deleted themselves; everything is finished
|
|
verifyCounts(0, 0);
|
|
|
|
clearInterval(testInterval);
|
|
t.end();
|
|
process.nextTick(process.exit);
|
|
break;
|
|
}
|
|
};
|
|
|
|
// Start VM, load project, and run
|
|
t.doesNotThrow(() => {
|
|
vm.start();
|
|
vm.clear();
|
|
vm.setCompatibilityMode(false);
|
|
vm.setTurboMode(false);
|
|
vm.loadProject(project).then(() => {
|
|
|
|
// Verify initial state: no clones, nothing running ("step -1")
|
|
verifyCounts(0, 0);
|
|
|
|
vm.greenFlag();
|
|
|
|
// Every second, advance the testing step
|
|
testInterval = setInterval(testNextStep, 1000);
|
|
});
|
|
});
|
|
|
|
});
|