forked from Foxyz/sync_replay_project
Errors: refuse links the probe can't play (with Put it up anyway), plain error texts, and others see who can't play
report.error / state.members[].error (optional, no protocol bump): an errored member is out of the ready gate until its player opens the media or the media changes; others see "Bob can't play this: ..." and a mark on the avatar; your own pill offers Retry (reload). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
1b04e002c2
commit
d3be13ecda
21 files changed
+445
-72
No files matched your search
@@ -85,6 +85,52 @@ void main() {
|
||||
});
|
||||
});
|
||||
|
||||
group('player errors', () {
|
||||
void fail(String token, String error, {int? mediaId}) => engine.applyReport(
|
||||
token, engine.positionAt(), 0, engine.eventId,
|
||||
mediaId: mediaId ?? engine.mediaId, error: error);
|
||||
|
||||
test('an errored member leaves the gate; clearing puts it back', () {
|
||||
join('a', 'alice');
|
||||
join('b', 'bob');
|
||||
engine.applyReady('a', true);
|
||||
engine.applyReady('b', true);
|
||||
buffer('a', 4.0);
|
||||
expect(engine.transport, Transport.held, reason: 'bob has no buffer');
|
||||
fail('b', "Not allowed (403)");
|
||||
final b = engine.members['b']!;
|
||||
expect([b.error, b.inSet], ['Not allowed (403)', false]);
|
||||
expect(engine.transport, Transport.playing, reason: 'alice plays alone');
|
||||
final view = engine.broadcast().members;
|
||||
expect(view.last.toJson()['error'], 'Not allowed (403)');
|
||||
expect(view.first.toJson().containsKey('error'), isFalse);
|
||||
engine.applyReady('b', true);
|
||||
expect(b.inSet, isFalse, reason: 'ready does not bring it back while errored');
|
||||
// A report of another media does not set it; a clean one clears it.
|
||||
fail('b', 'x', mediaId: engine.mediaId - 1);
|
||||
expect(b.error, isEmpty);
|
||||
expect(b.inSet, isTrue, reason: 'ready and playing: back like a stale return');
|
||||
expect(engine.transport, Transport.held, reason: 'bob is buffering');
|
||||
});
|
||||
|
||||
test('a swap clears it; held, clearing puts it in the set', () {
|
||||
join('a', 'alice');
|
||||
join('b', 'bob');
|
||||
fail('b', 'Not found (404)');
|
||||
engine.applySwap('a', const HelloMedia(name: 'n', size: 1, duration: 0, url: 'u'));
|
||||
final b = engine.members['b']!;
|
||||
expect([b.error, b.inSet], ['', true]);
|
||||
fail('b', 'Not found (404)');
|
||||
expect(b.inSet, isFalse);
|
||||
buffer('b', 4.0);
|
||||
expect([b.error, b.inSet], ['', true]);
|
||||
expect(ReportMessage.fromJson({
|
||||
't': 'report', 'position': 0, 'buffered': 0, 'eventId': 0,
|
||||
'error': ' a\nb ${'x' * 200}'}).error.length,
|
||||
RelayConstants.maxMemberErrorLength);
|
||||
});
|
||||
});
|
||||
|
||||
group('membership + gate', () {
|
||||
test('join while held lands in the set, playback stays held', () {
|
||||
join('a', 'alice');
|
||||
|
||||
@@ -115,6 +115,24 @@ void main() {
|
||||
});
|
||||
});
|
||||
|
||||
test('play errors in plain words; a probe refuses unread pages and 4xx links', () {
|
||||
expect(playErrorText('[BiliBili] BV1x: Unable to download webpage: HTTP Error 412: Precondition Failed'),
|
||||
needsCookiesText);
|
||||
expect(playErrorText('Sign in to confirm your age'), needsCookiesText);
|
||||
expect(playErrorText('the video server answered HTTP error 403 Forbidden'), notAllowedText);
|
||||
expect(playErrorText('HTTP Error 404: Not Found'), notFoundText);
|
||||
expect(playErrorText('Unsupported URL: https://example.com/login/403'), unsupportedUrlText);
|
||||
expect(playErrorText('cannot open the link: SocketException: Failed host lookup'), unreachableText);
|
||||
expect(playErrorText('the video stream could not be opened'), 'the video stream could not be opened');
|
||||
expect(playErrorText(notAllowedText), notAllowedText);
|
||||
final u = Uri.parse('https://x/v.mp4');
|
||||
expect(LinkProbe.page(u, ytDlpError: 'HTTP Error 412: Precondition Failed').problem, needsCookiesText);
|
||||
expect(LinkProbe.page(u, ytDlpError: 'odd failure', status: 403).problem, notAllowedText);
|
||||
expect(LinkProbe.page(u, ytDlpError: 'odd failure').problem, 'odd failure');
|
||||
expect(LinkProbe.page(u, info: YtDlpInfo.parse({'title': 'x', 'formats': []}), status: 404).problem, isNull);
|
||||
expect(LinkProbe.file(u, 10).problem, isNull);
|
||||
});
|
||||
|
||||
test('viewer URL: one track plain, several an mpv EDL with %length% framing', () {
|
||||
expect(relayViewerUrl('http://h:1/r/default/t/3', 'a/b c'), 'http://h:1/r/default/t/3/a_b%20c');
|
||||
const v = 'http://h:1/r/default/t/3/0/x', a = 'http://h:1/r/default/t/3/1/x';
|
||||
|
||||
Reference in new issue
Block a user