import 'dart:async'; import 'package:flutter_test/flutter_test.dart'; import 'package:pj_supermarket_cloud/common/utils/app/face_readiness_cache.dart'; void main() { test('已就绪的重复读取直接使用缓存,不再次加载', () async { final cache = FaceReadinessCache(); var calls = 0; Future load() async { calls++; return 'ready'; } expect(await cache.read(load, canCache: (_) => true), 'ready'); expect(await cache.read(load, canCache: (_) => true), 'ready'); expect(cache.value, 'ready'); expect(calls, 1); }); test('同一代次的并发读取只发起一次加载', () async { final cache = FaceReadinessCache(); final source = Completer(); var calls = 0; Future load() { calls++; return source.future; } final first = cache.read(load, canCache: (_) => true); final second = cache.read(load, canCache: (_) => true); expect(identical(first, second), isTrue); expect(calls, 1); source.complete('ready'); expect(await Future.wait([first, second]), ['ready', 'ready']); expect(cache.value, 'ready'); }); test('相同数量的样本替换仍会在失效后重新检查', () async { final cache = FaceReadinessCache>(); var sampleIds = [1, 2]; var calls = 0; Future> load() async { calls++; return List.unmodifiable(sampleIds); } expect(await cache.read(load, canCache: (_) => true), [1, 2]); sampleIds = [1, 3]; cache.invalidate(); expect(cache.value, isNull); expect(await cache.read(load, canCache: (_) => true), [1, 3]); expect(calls, 2); }); test('查询中失效会创建新查询,旧查询完成不能清除新查询', () async { final cache = FaceReadinessCache(); final oldSource = Completer(); final newSource = Completer(); var calls = 0; Future load() { calls++; return calls == 1 ? oldSource.future : newSource.future; } final oldRead = cache.read(load, canCache: (_) => true); cache.invalidate(); final newRead = cache.read(load, canCache: (_) => true); expect(identical(oldRead, newRead), isFalse); expect(calls, 2); oldSource.complete('old'); expect(await oldRead, 'old'); expect(cache.value, isNull); final joined = cache.read(load, canCache: (_) => true); expect(identical(joined, newRead), isTrue); expect(calls, 2); newSource.complete('new'); expect(await newRead, 'new'); expect(await joined, 'new'); expect(cache.value, 'new'); }); test('旧查询晚于新查询完成时不能覆盖新缓存', () async { final cache = FaceReadinessCache(); final oldSource = Completer(); final oldRead = cache.read(() => oldSource.future, canCache: (_) => true); cache.invalidate(); expect(await cache.read(() async => 'new', canCache: (_) => true), 'new'); oldSource.complete('old'); expect(await oldRead, 'old'); expect(cache.value, 'new'); }); test('嵌套变更全部结束后才允许缓存,中途读到就绪也不缓存', () async { final cache = FaceReadinessCache(); var calls = 0; Future load() async { calls++; return 'ready'; } await cache.read(load, canCache: (_) => true); cache.beginMutation(); cache.beginMutation(); expect(cache.mutationDepth, 2); expect(cache.value, isNull); expect(await cache.read(load, canCache: (_) => true), 'ready'); expect(cache.value, isNull); cache.endMutation(); expect(cache.mutationDepth, 1); expect(await cache.read(load, canCache: (_) => true), 'ready'); expect(cache.value, isNull); cache.endMutation(); expect(cache.mutationDepth, 0); expect(await cache.read(load, canCache: (_) => true), 'ready'); expect(cache.value, 'ready'); expect(calls, 4); expect(cache.endMutation, throwsStateError); expect(cache.mutationDepth, 0); }); test('变更期间发起的查询在变更结束后完成也不能缓存', () async { final cache = FaceReadinessCache(); cache.beginMutation(); final source = Completer(); final duringMutation = cache.read(() => source.future, canCache: (_) => true); cache.endMutation(); source.complete('ready'); expect(await duringMutation, 'ready'); expect(cache.value, isNull); expect(await cache.read(() async => 'checked', canCache: (_) => true), 'checked'); expect(cache.value, 'checked'); }); test('加载失败不缓存失败结果,下一次读取可以重试', () async { final cache = FaceReadinessCache(); var calls = 0; Future load() async { calls++; if (calls == 1) throw StateError('sdk unavailable'); return 'ready'; } await expectLater( cache.read(load, canCache: (_) => true), throwsStateError); expect(cache.value, isNull); expect(await cache.read(load, canCache: (_) => true), 'ready'); expect(calls, 2); }); test('未就绪的正常结果不缓存,后续就绪结果才会缓存', () async { final cache = FaceReadinessCache(); var calls = 0; Future load() async => ++calls > 1; expect(await cache.read(load, canCache: (ready) => ready), isFalse); expect(cache.value, isNull); expect(await cache.read(load, canCache: (ready) => ready), isTrue); expect(await cache.read(load, canCache: (ready) => ready), isTrue); expect(cache.value, isTrue); expect(calls, 2); }); }