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 () => {
|
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 dir = fs.mkdtempSync(path.join(os.tmpdir(), 'stoke-release-partial-'));
|
||||||
const cfg = path.join(dir, 'config.json');
|
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 {
|
try {
|
||||||
const result = await spawnAsync([
|
const result = await spawnAsync([
|
||||||
'release', 'create', '-o', 'o', '-r', 'r', '--tag', 'v1',
|
'release', 'create', '-o', 'o', '-r', 'r', '--tag', 'v1',
|
||||||
'--asset', good, '--asset', bad,
|
'--asset', bad, '--asset', good,
|
||||||
], { STOKE_CONFIG_FILE: cfg });
|
], { STOKE_CONFIG_FILE: cfg });
|
||||||
assert.equal(result.status, 1);
|
assert.equal(result.status, 1);
|
||||||
assert.match(result.stdout, /Release id: 42/i);
|
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.match(result.stderr, /release was kept/i);
|
||||||
assert.deepEqual(requests.map(({ url }) => url), [
|
assert.deepEqual(requests.map(({ url }) => url), [
|
||||||
'/api/v1/repos/o/r/releases',
|
'/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=bad.bin',
|
||||||
|
'/api/v1/repos/o/r/releases/42/assets?name=good.bin',
|
||||||
]);
|
]);
|
||||||
} finally {
|
} finally {
|
||||||
await new Promise((resolve) => server.close(resolve));
|
await new Promise((resolve) => server.close(resolve));
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue