fix(relay): secure reconnect and room ownership
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:plezy/models/audio_quality_preset.dart';
|
||||
@@ -226,6 +228,40 @@ void main() {
|
||||
});
|
||||
});
|
||||
|
||||
group('SettingsService Watch Together relay', () {
|
||||
test('typed writes canonicalize valid bases and reject invalid replacement', () async {
|
||||
final settings = await SettingsService.getInstance();
|
||||
|
||||
await settings.write(SettingsService.customRelayUrl, ' HTTPS://Relay.Example.Test/path/// ');
|
||||
expect(settings.read(SettingsService.customRelayUrl), 'https://relay.example.test/path');
|
||||
|
||||
await expectLater(
|
||||
settings.write(SettingsService.customRelayUrl, 'ws://relay.example.test'),
|
||||
throwsFormatException,
|
||||
);
|
||||
expect(settings.read(SettingsService.customRelayUrl), 'https://relay.example.test/path');
|
||||
|
||||
await settings.write(SettingsService.customRelayUrl, ' ');
|
||||
expect(settings.read(SettingsService.customRelayUrl), isNull);
|
||||
});
|
||||
|
||||
test('startup canonicalizes valid history and removes invalid history', () async {
|
||||
resetSharedPreferencesForTest(
|
||||
initialAsync: {SettingsService.customRelayUrl.key: ' http://Relay.Example.Test:8080/prefix// '},
|
||||
);
|
||||
SettingsService.resetForTesting();
|
||||
var settings = await SettingsService.getInstance();
|
||||
expect(settings.read(SettingsService.customRelayUrl), 'http://relay.example.test:8080/prefix');
|
||||
|
||||
resetSharedPreferencesForTest(
|
||||
initialAsync: {SettingsService.customRelayUrl.key: 'https://relay.example.test/path?wrong=route'},
|
||||
);
|
||||
SettingsService.resetForTesting();
|
||||
settings = await SettingsService.getInstance();
|
||||
expect(settings.read(SettingsService.customRelayUrl), isNull);
|
||||
});
|
||||
});
|
||||
|
||||
group('SettingsService listenables', () {
|
||||
test('refreshListenables updates active prefs outside the resettable surface', () async {
|
||||
final settings = await SettingsService.getInstance();
|
||||
@@ -276,4 +312,48 @@ void main() {
|
||||
expect(settings.isLibraryAllowedForTracker(TrackerService.trakt, 'server:allowed'), isTrue);
|
||||
});
|
||||
});
|
||||
group('BaseSharedPreferencesService initialization generations', () {
|
||||
test('a reset-raced initialization resolves to the replacement backend', () async {
|
||||
resetSharedPreferencesForTest(initialAsync: const {'generation_marker': 'old'});
|
||||
final firstOnInit = Completer<void>();
|
||||
final firstStarted = Completer<void>();
|
||||
var constructions = 0;
|
||||
|
||||
final raced = BaseSharedPreferencesService.initializeInstance<_GenerationTestPreferences>(() {
|
||||
final construction = constructions++;
|
||||
return _GenerationTestPreferences(
|
||||
construction,
|
||||
onInitStarted: construction == 0 ? firstStarted : null,
|
||||
onInitGate: construction == 0 ? firstOnInit : null,
|
||||
);
|
||||
});
|
||||
await firstStarted.future;
|
||||
|
||||
resetSharedPreferencesForTest(initialAsync: const {'generation_marker': 'new'});
|
||||
final replacement = await BaseSharedPreferencesService.initializeInstance<_GenerationTestPreferences>(
|
||||
() => _GenerationTestPreferences(constructions++),
|
||||
);
|
||||
firstOnInit.complete();
|
||||
final recovered = await raced;
|
||||
|
||||
expect(recovered, same(replacement));
|
||||
expect(recovered.construction, 1);
|
||||
expect(recovered.readString('generation_marker'), 'new');
|
||||
expect(constructions, 2);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
class _GenerationTestPreferences extends BaseSharedPreferencesService {
|
||||
_GenerationTestPreferences(this.construction, {this.onInitStarted, this.onInitGate});
|
||||
|
||||
final int construction;
|
||||
final Completer<void>? onInitStarted;
|
||||
final Completer<void>? onInitGate;
|
||||
|
||||
@override
|
||||
Future<void> onInit() async {
|
||||
onInitStarted?.complete();
|
||||
await onInitGate?.future;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user