Release Multi-Hoster Uploader 3.3.108
This commit is contained in:
@@ -0,0 +1,132 @@
|
||||
const test = require('node:test');
|
||||
const assert = require('node:assert');
|
||||
const {
|
||||
summarizePerHoster,
|
||||
classifyErrorCategory,
|
||||
summarizeBatchErrors,
|
||||
isRetryableCategory
|
||||
} = require('../lib/stats');
|
||||
|
||||
function makeBatch(timestamp, results) {
|
||||
return {
|
||||
id: 'b-' + timestamp,
|
||||
timestamp: new Date(timestamp).toISOString(),
|
||||
files: [{ name: 'foo.mp4', size: 1, results }]
|
||||
};
|
||||
}
|
||||
|
||||
test('summarizePerHoster counts ok and fail per hoster across all batches', () => {
|
||||
const history = [
|
||||
makeBatch(1, [
|
||||
{ hoster: 'voe.sx', status: 'done' },
|
||||
{ hoster: 'byse.sx', status: 'error', error: 'Not video file format' }
|
||||
]),
|
||||
makeBatch(2, [
|
||||
{ hoster: 'voe.sx', status: 'done' },
|
||||
{ hoster: 'voe.sx', status: 'error', error: 'CSRF' },
|
||||
{ hoster: 'byse.sx', status: 'done' }
|
||||
])
|
||||
];
|
||||
const s = summarizePerHoster(history);
|
||||
assert.strictEqual(s['voe.sx'].ok, 2);
|
||||
assert.strictEqual(s['voe.sx'].fail, 1);
|
||||
assert.strictEqual(s['voe.sx'].total, 3);
|
||||
assert.strictEqual(Math.round(s['voe.sx'].rate * 100), 67);
|
||||
assert.strictEqual(s['byse.sx'].ok, 1);
|
||||
assert.strictEqual(s['byse.sx'].fail, 1);
|
||||
assert.strictEqual(s['byse.sx'].rate, 0.5);
|
||||
});
|
||||
|
||||
test('summarizePerHoster honors sinceMs cutoff', () => {
|
||||
const history = [
|
||||
makeBatch(1000, [{ hoster: 'voe.sx', status: 'done' }]),
|
||||
makeBatch(5000, [{ hoster: 'voe.sx', status: 'error', error: 'x' }])
|
||||
];
|
||||
const s = summarizePerHoster(history, { sinceMs: 3000 });
|
||||
assert.strictEqual(s['voe.sx'].ok, 0);
|
||||
assert.strictEqual(s['voe.sx'].fail, 1);
|
||||
});
|
||||
|
||||
test('summarizePerHoster honors lastNBatches (newest first)', () => {
|
||||
const history = [
|
||||
makeBatch(1000, [{ hoster: 'voe.sx', status: 'done' }]),
|
||||
makeBatch(2000, [{ hoster: 'voe.sx', status: 'done' }]),
|
||||
makeBatch(3000, [{ hoster: 'voe.sx', status: 'error', error: 'x' }])
|
||||
];
|
||||
const s = summarizePerHoster(history, { lastNBatches: 1 });
|
||||
assert.strictEqual(s['voe.sx'].ok, 0);
|
||||
assert.strictEqual(s['voe.sx'].fail, 1);
|
||||
});
|
||||
|
||||
test('summarizePerHoster handles empty / malformed input', () => {
|
||||
assert.deepStrictEqual(summarizePerHoster(null), {});
|
||||
assert.deepStrictEqual(summarizePerHoster([]), {});
|
||||
assert.deepStrictEqual(summarizePerHoster([{ id: 'x', files: null }]), {});
|
||||
});
|
||||
|
||||
test('classifyErrorCategory: file-rejected phrases', () => {
|
||||
assert.strictEqual(classifyErrorCategory('Byse lehnte Datei ab: Not video file format'), 'file-rejected');
|
||||
assert.strictEqual(classifyErrorCategory('Duplicate file already exists'), 'file-rejected');
|
||||
assert.strictEqual(classifyErrorCategory('Datei zu groß (Max: 5 GB)'), 'file-rejected');
|
||||
});
|
||||
|
||||
test('classifyErrorCategory: account-error phrases', () => {
|
||||
assert.strictEqual(classifyErrorCategory('Quota exceeded'), 'account-error');
|
||||
assert.strictEqual(classifyErrorCategory('account banned'), 'account-error');
|
||||
assert.strictEqual(classifyErrorCategory('not enough disk space'), 'account-error');
|
||||
});
|
||||
|
||||
test('classifyErrorCategory: hoster-transient phrases', () => {
|
||||
assert.strictEqual(classifyErrorCategory('CSRF-Token nicht gefunden'), 'hoster-transient');
|
||||
assert.strictEqual(classifyErrorCategory('Kein Upload-Server erhalten: server busy'), 'hoster-transient');
|
||||
assert.strictEqual(classifyErrorCategory('Kein Filecode'), 'hoster-transient');
|
||||
});
|
||||
|
||||
test('classifyErrorCategory: network phrases', () => {
|
||||
assert.strictEqual(classifyErrorCategory('socket hang up'), 'network');
|
||||
assert.strictEqual(classifyErrorCategory('fetch failed'), 'network');
|
||||
assert.strictEqual(classifyErrorCategory('Timeout while reading'), 'network');
|
||||
});
|
||||
|
||||
test('classifyErrorCategory: aborted is its own bucket (not retryable)', () => {
|
||||
assert.strictEqual(classifyErrorCategory('Abgebrochen'), 'aborted');
|
||||
assert.strictEqual(isRetryableCategory('aborted'), false);
|
||||
});
|
||||
|
||||
test('classifyErrorCategory: unknown for everything else', () => {
|
||||
assert.strictEqual(classifyErrorCategory(''), 'unknown');
|
||||
assert.strictEqual(classifyErrorCategory(null), 'unknown');
|
||||
assert.strictEqual(classifyErrorCategory('Some weird thing'), 'unknown');
|
||||
});
|
||||
|
||||
test('summarizeBatchErrors buckets results by category', () => {
|
||||
const summary = {
|
||||
files: [
|
||||
{ name: 'a.mp4', results: [
|
||||
{ hoster: 'voe.sx', status: 'done' },
|
||||
{ hoster: 'byse.sx', status: 'error', error: 'Not video file format' }
|
||||
] },
|
||||
{ name: 'b.mp4', results: [
|
||||
{ hoster: 'voe.sx', status: 'error', error: 'CSRF' },
|
||||
{ hoster: 'doodstream.com', status: 'error', error: 'socket hang up' }
|
||||
] }
|
||||
]
|
||||
};
|
||||
const buckets = summarizeBatchErrors(summary);
|
||||
assert.strictEqual(buckets['file-rejected'].length, 1);
|
||||
assert.strictEqual(buckets['file-rejected'][0].hoster, 'byse.sx');
|
||||
assert.strictEqual(buckets['hoster-transient'].length, 1);
|
||||
assert.strictEqual(buckets['hoster-transient'][0].hoster, 'voe.sx');
|
||||
assert.strictEqual(buckets['network'].length, 1);
|
||||
assert.strictEqual(buckets['network'][0].hoster, 'doodstream.com');
|
||||
assert.strictEqual(buckets['account-error'].length, 0);
|
||||
});
|
||||
|
||||
test('isRetryableCategory: only transient + network + unknown retry-worthy', () => {
|
||||
assert.strictEqual(isRetryableCategory('hoster-transient'), true);
|
||||
assert.strictEqual(isRetryableCategory('network'), true);
|
||||
assert.strictEqual(isRetryableCategory('unknown'), true);
|
||||
assert.strictEqual(isRetryableCategory('file-rejected'), false);
|
||||
assert.strictEqual(isRetryableCategory('account-error'), false);
|
||||
assert.strictEqual(isRetryableCategory('aborted'), false);
|
||||
});
|
||||
Reference in New Issue
Block a user