Files
ReelShort/test/playback/playback_position_cache_test.dart
T
Vicky 0f777b19f2 perf(player): 限制雪碧图与海报预缓存内存并给播放位置缓存加容量上限
雪碧图解码从 2048 降到 1024、缓存从 8 张降到 3 张,避免擦洗预览驻留十几 MB 位图;
相邻集海报预缓存改用 ResizeImage 按 360/720 宽解码,不再缓存整张原图;
播放位置缓存按写入时间淘汰,最多保留 100 条,长会话不再只增不减;
观看记录详情失败日志加 kDebugMode 保护,release 下不再逐条打堆栈。
2026-10-29 11:25:47 +08:00

125 lines
3.7 KiB
Dart

// Author: fruit.com.cn
import 'package:flutter_test/flutter_test.dart';
import 'package:fruitshorts/core/data/services/playback_position_cache.dart';
void main() {
test('should_clamp_invalid_or_out_of_range_position_when_caching', () {
expect(
clampPlaybackPosition(
const Duration(seconds: -1),
const Duration(seconds: 10),
),
Duration.zero,
);
expect(
clampPlaybackPosition(
const Duration(seconds: 12),
const Duration(seconds: 10),
),
const Duration(seconds: 10),
);
expect(
clampPlaybackPosition(
const Duration(seconds: 5),
const Duration(seconds: 10),
),
const Duration(seconds: 5),
);
final cache = PlaybackPositionCache();
cache.save(
episodeId: 'episode-3',
dramaId: 'drama-a',
position: const Duration(minutes: 4),
duration: const Duration(minutes: 3),
);
expect(
cache.read('episode-3', dramaId: 'drama-a')?.position,
const Duration(minutes: 3),
);
});
test('should_store_and_read_recent_position_when_drama_matches', () {
final now = DateTime(2026, 10, 22, 12);
final cache = PlaybackPositionCache(now: () => now);
cache.save(
episodeId: 'episode-3',
dramaId: 'drama-a',
position: const Duration(minutes: 1, seconds: 20),
duration: const Duration(minutes: 3),
);
final entry = cache.read('episode-3', dramaId: 'drama-a');
expect(entry, isNotNull);
expect(entry!.position, const Duration(minutes: 1, seconds: 20));
expect(entry.duration, const Duration(minutes: 3));
expect(entry.updatedAt, now);
});
test('should_reject_cached_position_when_drama_does_not_match', () {
final cache = PlaybackPositionCache();
cache.save(
episodeId: 'episode-3',
dramaId: 'drama-a',
position: const Duration(seconds: 80),
duration: const Duration(minutes: 3),
);
expect(cache.read('episode-3', dramaId: 'drama-b'), isNull);
});
test('should_use_latest_saved_episode_when_timestamps_match', () {
final now = DateTime(2026, 10, 22, 12);
final cache = PlaybackPositionCache(now: () => now);
cache.save(
episodeId: 'episode-1',
dramaId: 'drama-a',
position: const Duration(seconds: 30),
duration: const Duration(minutes: 3),
);
cache.save(
episodeId: 'episode-2',
dramaId: 'drama-a',
position: const Duration(seconds: 45),
duration: const Duration(minutes: 3),
);
expect(cache.latestForDrama('drama-a')?.episodeId, 'episode-2');
});
test('should_evict_oldest_entry_when_capacity_exceeded', () {
var now = DateTime(2026, 10, 22, 12);
final cache = PlaybackPositionCache(now: () => now, maxEntries: 2);
for (final episodeId in ['episode-1', 'episode-2', 'episode-3']) {
cache.save(
episodeId: episodeId,
dramaId: 'drama-a',
position: const Duration(seconds: 30),
duration: const Duration(minutes: 3),
);
now = now.add(const Duration(minutes: 1));
}
expect(cache.read('episode-1', dramaId: 'drama-a'), isNull);
expect(cache.read('episode-2', dramaId: 'drama-a'), isNotNull);
expect(cache.read('episode-3', dramaId: 'drama-a'), isNotNull);
});
test('should_reject_expired_cached_position', () {
var now = DateTime(2026, 10, 22, 12);
final cache = PlaybackPositionCache(now: () => now);
cache.save(
episodeId: 'episode-3',
dramaId: 'drama-a',
position: const Duration(seconds: 80),
duration: const Duration(minutes: 3),
);
now = now.add(const Duration(days: 1));
expect(cache.read('episode-3', dramaId: 'drama-a'), isNull);
});
}