test: cover backpressured release uploads
This commit is contained in:
parent
1371ec9aa9
commit
8293c83531
1 changed files with 47 additions and 2 deletions
|
|
@ -180,6 +180,51 @@ test('release upload resolves the tag once and applies a single asset name overr
|
|||
}
|
||||
});
|
||||
|
||||
test('release upload streams a large asset through receiver backpressure', async () => {
|
||||
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'stoke-release-large-upload-'));
|
||||
const cfg = path.join(dir, 'config.json');
|
||||
const asset = path.join(dir, 'large.bin');
|
||||
const assetSize = 8 * 1024 * 1024;
|
||||
fs.writeFileSync(asset, Buffer.alloc(assetSize, 0x61));
|
||||
let uploadedBytes = 0;
|
||||
let paused = false;
|
||||
const server = http.createServer((req, res) => {
|
||||
if (req.method === 'GET') {
|
||||
res.writeHead(200, { 'Content-Type': 'application/json' });
|
||||
res.end(JSON.stringify({ id: 7, tag_name: 'v1' }));
|
||||
return;
|
||||
}
|
||||
req.on('data', (chunk) => {
|
||||
uploadedBytes += chunk.length;
|
||||
if (!paused) {
|
||||
paused = true;
|
||||
req.pause();
|
||||
setTimeout(() => req.resume(), 100);
|
||||
}
|
||||
});
|
||||
req.on('end', () => {
|
||||
res.writeHead(201, { 'Content-Type': 'application/json' });
|
||||
res.end(JSON.stringify({ id: 8, name: 'large.bin' }));
|
||||
});
|
||||
});
|
||||
await new Promise((resolve) => server.listen(0, '127.0.0.1', resolve));
|
||||
fs.writeFileSync(cfg, JSON.stringify({ url: `http://127.0.0.1:${server.address().port}`, token: 'tok' }));
|
||||
|
||||
try {
|
||||
const result = await spawnAsync(
|
||||
['release', 'upload', '-o', 'o', '-r', 'r', '--tag', 'v1', '--asset', asset],
|
||||
{ STOKE_CONFIG_FILE: cfg },
|
||||
);
|
||||
assert.equal(result.status, 0, result.stderr);
|
||||
assert.equal(paused, true);
|
||||
assert.ok(uploadedBytes > assetSize, `multipart body ${uploadedBytes} did not include ${assetSize} asset bytes`);
|
||||
assert.match(result.stdout, /Asset uploaded: large\.bin/);
|
||||
} finally {
|
||||
await new Promise((resolve) => server.close(resolve));
|
||||
fs.rmSync(dir, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
test('release create keeps the release and reports landed and failed assets', async () => {
|
||||
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'stoke-release-partial-'));
|
||||
const cfg = path.join(dir, 'config.json');
|
||||
|
|
@ -211,7 +256,7 @@ test('release create keeps the release and reports landed and failed assets', as
|
|||
try {
|
||||
const result = await spawnAsync([
|
||||
'release', 'create', '-o', 'o', '-r', 'r', '--tag', 'v1',
|
||||
'--asset', good, '--asset', bad,
|
||||
'--asset', bad, '--asset', good,
|
||||
], { STOKE_CONFIG_FILE: cfg });
|
||||
assert.equal(result.status, 1);
|
||||
assert.match(result.stdout, /Release id: 42/i);
|
||||
|
|
@ -220,8 +265,8 @@ test('release create keeps the release and reports landed and failed assets', as
|
|||
assert.match(result.stderr, /release was kept/i);
|
||||
assert.deepEqual(requests.map(({ url }) => url), [
|
||||
'/api/v1/repos/o/r/releases',
|
||||
'/api/v1/repos/o/r/releases/42/assets?name=good.bin',
|
||||
'/api/v1/repos/o/r/releases/42/assets?name=bad.bin',
|
||||
'/api/v1/repos/o/r/releases/42/assets?name=good.bin',
|
||||
]);
|
||||
} finally {
|
||||
await new Promise((resolve) => server.close(resolve));
|
||||
|
|
|
|||
Loading…
Reference in a new issue