172 lines
5.5 KiB
Dart
172 lines
5.5 KiB
Dart
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<String>();
|
|
var calls = 0;
|
|
Future<String> 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<String>();
|
|
final source = Completer<String>();
|
|
var calls = 0;
|
|
Future<String> 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<List<int>>();
|
|
var sampleIds = <int>[1, 2];
|
|
var calls = 0;
|
|
Future<List<int>> 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<String>();
|
|
final oldSource = Completer<String>();
|
|
final newSource = Completer<String>();
|
|
var calls = 0;
|
|
Future<String> 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<String>();
|
|
final oldSource = Completer<String>();
|
|
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<String>();
|
|
var calls = 0;
|
|
Future<String> 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<String>();
|
|
cache.beginMutation();
|
|
final source = Completer<String>();
|
|
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<String>();
|
|
var calls = 0;
|
|
Future<String> 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<bool>();
|
|
var calls = 0;
|
|
Future<bool> 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);
|
|
});
|
|
}
|