import 'package:flutter_test/flutter_test.dart'; import 'package:jj_mkvmaker/app/master_lock.dart'; import 'support/flaky_secret_store.dart'; /// M0 약속: 안전 저장소를 읽지 못하면 마스터 잠금은 '알 수 없음' - 문을 열지 않고 (한 번 다시 읽어 봄), 마스터 · 최상 · 묻는 때를 바꾸지 않는다. /// 다시 읽히면 평소대로 (마스터가 있으면 묻는다) void main() { late FlakySecretStore store; late int asked; setUp(() async { store = FlakySecretStore(); // 마스터가 정해진 기기 final setup = MasterLock(store); await setup.load(); await setup.setMaster('right-pass'); asked = 0; MasterLock.prompt = (_) async { asked++; return true; }; }); tearDown(() => MasterLock.prompt = null); test('읽지 못하면 문을 열지 않는다 (예전: 마스터가 없는 것으로 보여 열렸다)', () async { store.failRead = true; final lock = MasterLock(store); await lock.load(); // 예외를 내지 않는다 - 앱은 켜진다 expect([lock.storeUnreadable, lock.hasMaster], [true, false]); expect(await lock.ensure(), isFalse); expect(await lock.ensure(force: true), isFalse, reason: '사용자가 직접 눌러도 열지 않는다'); expect(asked, 0, reason: '알 수 없는 마스터를 묻지도 않는다'); }); test('알 수 없는 동안 마스터 · 최상 · 묻는 때를 바꾸지 않는다 (진짜 마스터를 덮어쓰지 않게)', () async { final before = Map.of(store.values); store.failRead = true; final lock = MasterLock(store); await lock.load(); await expectLater(lock.setMaster('new-pass'), throwsA(isA())); await expectLater(lock.setSuper('s'), throwsA(isA())); await expectLater(lock.clearMaster(), throwsA(isA())); await expectLater(lock.setAsk('never'), throwsA(isA())); expect(store.values, before); }); test('다시 읽히면 평소대로: 문을 열 때 한 번 다시 읽고, 마스터가 있으면 묻는다', () async { store.failRead = true; final lock = MasterLock(store); await lock.load(); store.failRead = false; expect(await lock.ensure(), isTrue); expect([lock.storeUnreadable, lock.hasMaster, asked], [false, true, 1]); }); test('reload: 읽혔는지 돌려준다', () async { store.failRead = true; final lock = MasterLock(store); await lock.load(); expect(await lock.reload(), isFalse); store.failRead = false; expect(await lock.reload(), isTrue); expect(lock.hasMaster, isTrue); }); }