Skip to content

Commit

Permalink
Handle non-serializable expected and actual values in parallel mode
Browse files Browse the repository at this point in the history
Fixes #212
  • Loading branch information
sgravrock committed Oct 3, 2024
1 parent 7c31381 commit 12fd347
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 2 deletions.
39 changes: 37 additions & 2 deletions lib/parallel_worker.js
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ function forwardingReporter(clusterWorker) {

for (const eventName of eventNames) {
reporter[eventName] = function (payload) {
sendIfConnected(clusterWorker, {
const msg = {
type: 'reporterEvent',
eventName,
payload: {
Expand All @@ -157,7 +157,18 @@ function forwardingReporter(clusterWorker) {
// Make them globally unique by prepending the worker ID.
id: `${clusterWorker.id}-${payload.id}`
}
});
};

try {
sendIfConnected(clusterWorker, msg);
} catch (e) {
if (e instanceof TypeError) {
msg.payload = fixNonSerializableReporterEvent(payload);
sendIfConnected(clusterWorker, msg);
} else {
throw e;
}
}
};
}

Expand All @@ -181,5 +192,29 @@ function sendIfConnected(clusterWorker, msg) {
return false;
}

function fixNonSerializableReporterEvent(payload) {
payload = {...payload};

for (const ak of ['passedExpectations', 'failedExpectations']) {
if (payload[ak]) {
payload[ak] = payload[ak].map(function(expectation) {
expectation = {...expectation};

for (const vk of ['expected', 'actual']) {
try {
JSON.stringify(expectation[vk]);
} catch (ex) {
expectation[vk] = '<not serializable>';
}
}

return expectation;
});
}
}

return payload;
}


module.exports = ParallelWorker;
44 changes: 44 additions & 0 deletions spec/parallel_worker_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -620,6 +620,50 @@ describe('ParallelWorker', function() {
expect(this.clusterWorker.send).toHaveBeenCalledOnceWith({type: 'booted'});
});
}

for (const eventName of ['specDone', 'suiteDone']) {
it(`handles non-serializable expected values in ${eventName}`, async function() {
const env = jasmine.createSpyObj(
'env', ['execute', 'parallelReset', 'addReporter']
);
const loader = jasmine.createSpyObj('loader', ['load']);
loader.load.withArgs('jasmine-core')
.and.returnValue(Promise.resolve(dummyCore(env)));
const jasmineWorker = new ParallelWorker({
loader,
clusterWorker: this.clusterWorker,
process: stubProcess()
});

this.clusterWorker.emit('message', {
type: 'configure',
configuration: {
helpers: [],
}
});
await jasmineWorker.envPromise_;

this.clusterWorker.send.calls.reset();
this.clusterWorker.send.and.callFake(function(msg) {
// Throw if msg is not serializable
JSON.stringify(msg);
});
const notSerializable = BigInt(0);
dispatchRepoterEvent(env, eventName, {
failedExpectations: [{expected: 'ok', actual: notSerializable}],
passedExpectations: [{expected: notSerializable, actual: 'ok'}],
});

expect(this.clusterWorker.send).toHaveBeenCalledWith({
type: 'reporterEvent',
eventName,
payload: jasmine.objectContaining({
failedExpectations: [{expected: 'ok', actual: '<not serializable>'}],
passedExpectations: [{expected: '<not serializable>', actual: 'ok'}],
})
});
});
}
});

it('reports unhandled exceptions that occur between batches', async function() {
Expand Down

0 comments on commit 12fd347

Please sign in to comment.