Skip to content

Commit c384e9a

Browse files
authored
Fix encoding of large snapshot data
* Encode snapshot data asynchronously, fixes #2932 * Async I/O when saving snapshots
1 parent 9bc615e commit c384e9a

File tree

9 files changed

+41
-14
lines changed

9 files changed

+41
-14
lines changed

lib/runner.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -224,8 +224,8 @@ export default class Runner extends Emittery {
224224
return this.snapshots.skipSnapshot(options);
225225
}
226226

227-
saveSnapshotState() {
228-
return {touchedFiles: this.snapshots.save()};
227+
async saveSnapshotState() {
228+
return {touchedFiles: await this.snapshots.save()};
229229
}
230230

231231
onRun(runnable) {

lib/snapshot-manager.js

+9-7
Original file line numberDiff line numberDiff line change
@@ -182,8 +182,8 @@ function sortBlocks(blocksByTitle, blockIndices) {
182182
);
183183
}
184184

185-
function encodeSnapshots(snapshotData) {
186-
const encoded = cbor.encodeOne(snapshotData, {
185+
async function encodeSnapshots(snapshotData) {
186+
const encoded = await cbor.encodeAsync(snapshotData, {
187187
omitUndefinedProperties: true,
188188
canonical: true,
189189
});
@@ -351,7 +351,7 @@ class Manager {
351351
this.recordSerialized({belongsTo, index, ...snapshot});
352352
}
353353

354-
save() {
354+
async save() {
355355
const {dir, relFile, snapFile, snapPath, reportPath} = this;
356356

357357
if (this.updating && this.newBlocksByTitle.size === 0) {
@@ -371,15 +371,17 @@ class Manager {
371371
),
372372
};
373373

374-
const buffer = encodeSnapshots(snapshots);
374+
const buffer = await encodeSnapshots(snapshots);
375375
const reportBuffer = generateReport(relFile, snapFile, snapshots);
376376

377-
fs.mkdirSync(dir, {recursive: true});
377+
await fs.promises.mkdir(dir, {recursive: true});
378378

379379
const temporaryFiles = [];
380380
const tmpfileCreated = file => temporaryFiles.push(file);
381-
writeFileAtomic.sync(snapPath, buffer, {tmpfileCreated});
382-
writeFileAtomic.sync(reportPath, reportBuffer, {tmpfileCreated});
381+
await Promise.all([
382+
writeFileAtomic(snapPath, buffer, {tmpfileCreated}),
383+
writeFileAtomic(reportPath, reportBuffer, {tmpfileCreated}),
384+
]);
383385
return {
384386
changedFiles: [snapPath, reportPath],
385387
temporaryFiles,

lib/worker/base.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ const run = async options => {
8181

8282
runner.on('finish', async () => {
8383
try {
84-
const {touchedFiles} = runner.saveSnapshotState();
84+
const {touchedFiles} = await runner.saveSnapshotState();
8585
if (touchedFiles) {
8686
channel.send({type: 'touched-files', files: touchedFiles});
8787
}

test-tap/assert.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -1303,7 +1303,7 @@ test('.notThrowsAsync() fails if passed a bad value', t => {
13031303
t.end();
13041304
});
13051305

1306-
test('.snapshot()', t => {
1306+
test('.snapshot()', async t => {
13071307
// Set to `true` to update the snapshot, then run:
13081308
// npx tap test-tap/assert.js
13091309
//
@@ -1411,7 +1411,7 @@ test('.snapshot()', t => {
14111411
});
14121412
}
14131413

1414-
manager.save();
1414+
await manager.save();
14151415
t.end();
14161416
});
14171417

test-tap/try-snapshot.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -84,5 +84,5 @@ test(async t => {
8484
t.equal(result.error.name, 'Error');
8585
});
8686

87-
manager.save();
87+
await manager.save();
8888
});

test/snapshot-regenerate-report/test.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ test('snapshot report can be regenerated from .snap file', async t => {
3838

3939
// Regenerate report
4040
snapshots.hasChanges = true; // Force.
41-
snapshots.save();
41+
await snapshots.save();
4242

4343
// Assert that reports match
4444
t.is(await fs.readFile(reportPath, 'utf8'), report);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
const {Buffer} = require('buffer');
2+
3+
const test = require(process.env.TEST_AVA_IMPORT_FROM);
4+
5+
for (let i = 0; i < 2; i++) {
6+
test(`large snapshot ${i}`, t => {
7+
t.snapshot(Buffer.alloc(1024 * 16));
8+
});
9+
}

test/snapshot-tests/large.js

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import test from '@ava/test';
2+
3+
import {cwd, fixture} from '../helpers/exec.js';
4+
import {withTemporaryFixture} from '../helpers/with-temporary-fixture.js';
5+
6+
// Reproduction for https://github.com/avajs/ava/issues/2932.
7+
test('can encode and decode large snapshots', async t => {
8+
await withTemporaryFixture(cwd('large'), async cwd => {
9+
const env = {
10+
AVA_FORCE_CI: 'not-ci',
11+
};
12+
await fixture(['--update-snapshots'], {cwd, env});
13+
await t.notThrowsAsync(fixture([], {cwd, env}));
14+
});
15+
});

0 commit comments

Comments
 (0)