chore: bump dart sdk to 3.8 (#20355)

* chore: bump dart sdk to 3.8

* chore: make build

* make pigeon

* chore: format files

---------

Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
This commit is contained in:
shenlong
2025-07-29 00:34:03 +05:30
committed by GitHub
parent 9b3718120b
commit e52b9d15b5
643 changed files with 32561 additions and 35292 deletions
@@ -21,10 +21,7 @@ void main() {
late MockLocalAssetRepository mockAssetRepo;
late MockStorageRepository mockStorageRepo;
late MockNativeSyncApi mockNativeApi;
final sortBy = {
SortLocalAlbumsBy.backupSelection,
SortLocalAlbumsBy.isIosSharedAlbum,
};
final sortBy = {SortLocalAlbumsBy.backupSelection, SortLocalAlbumsBy.isIosSharedAlbum};
setUp(() {
mockAlbumRepo = MockLocalAlbumRepository();
@@ -47,9 +44,9 @@ void main() {
group('HashService hashAssets', () {
test('skips albums with no assets to hash', () async {
when(() => mockAlbumRepo.getAll(sortBy: sortBy)).thenAnswer(
(_) async => [LocalAlbumStub.recent.copyWith(assetCount: 0)],
);
when(
() => mockAlbumRepo.getAll(sortBy: sortBy),
).thenAnswer((_) async => [LocalAlbumStub.recent.copyWith(assetCount: 0)]);
when(() => mockAlbumRepo.getAssetsToHash(LocalAlbumStub.recent.id)).thenAnswer((_) async => []);
await sut.hashAssets();
@@ -84,9 +81,7 @@ void main() {
when(() => mockAlbumRepo.getAll(sortBy: sortBy)).thenAnswer((_) async => [album]);
when(() => mockAlbumRepo.getAssetsToHash(album.id)).thenAnswer((_) async => [asset]);
when(() => mockStorageRepo.getFileForAsset(asset.id)).thenAnswer((_) async => mockFile);
when(() => mockNativeApi.hashPaths(['image-path'])).thenAnswer(
(_) async => [hash],
);
when(() => mockNativeApi.hashPaths(['image-path'])).thenAnswer((_) async => [hash]);
await sut.hashAssets();
@@ -43,10 +43,7 @@ void main() {
when(() => mockLogRepo.insert(any())).thenAnswer((_) async => true);
when(() => mockLogRepo.insertAll(any())).thenAnswer((_) async => true);
sut = await LogService.create(
logRepository: mockLogRepo,
storeRepository: mockStoreRepo,
);
sut = await LogService.create(logRepository: mockLogRepo, storeRepository: mockStoreRepo);
});
tearDown(() async {
@@ -72,9 +69,7 @@ void main() {
});
test('Updates the log level in store', () {
final index = verify(
() => mockStoreRepo.insert<int>(StoreKey.logLevel, captureAny()),
).captured.firstOrNull;
final index = verify(() => mockStoreRepo.insert<int>(StoreKey.logLevel, captureAny())).captured.firstOrNull;
expect(index, LogLevel.shout.index);
});
@@ -86,11 +81,7 @@ void main() {
group("Log Service Buffer:", () {
test('Buffers logs until timer elapses', () {
TestUtils.fakeAsync((time) async {
sut = await LogService.create(
logRepository: mockLogRepo,
storeRepository: mockStoreRepo,
shouldBuffer: true,
);
sut = await LogService.create(logRepository: mockLogRepo, storeRepository: mockStoreRepo, shouldBuffer: true);
final logger = Logger(_kInfoLog.logger!);
logger.info(_kInfoLog.message);
@@ -104,11 +95,7 @@ void main() {
test('Batch inserts all logs on timer', () {
TestUtils.fakeAsync((time) async {
sut = await LogService.create(
logRepository: mockLogRepo,
storeRepository: mockStoreRepo,
shouldBuffer: true,
);
sut = await LogService.create(logRepository: mockLogRepo, storeRepository: mockStoreRepo, shouldBuffer: true);
final logger = Logger(_kInfoLog.logger!);
logger.info(_kInfoLog.message);
@@ -125,11 +112,7 @@ void main() {
test('Does not buffer when off', () {
TestUtils.fakeAsync((time) async {
sut = await LogService.create(
logRepository: mockLogRepo,
storeRepository: mockStoreRepo,
shouldBuffer: false,
);
sut = await LogService.create(logRepository: mockLogRepo, storeRepository: mockStoreRepo, shouldBuffer: false);
final logger = Logger(_kInfoLog.logger!);
logger.info(_kInfoLog.message);
@@ -159,11 +142,7 @@ void main() {
test('Combines result from both DB + Buffer', () {
TestUtils.fakeAsync((time) async {
sut = await LogService.create(
logRepository: mockLogRepo,
storeRepository: mockStoreRepo,
shouldBuffer: true,
);
sut = await LogService.create(logRepository: mockLogRepo, storeRepository: mockStoreRepo, shouldBuffer: true);
final logger = Logger(_kWarnLog.logger!);
logger.warning(_kWarnLog.message);
@@ -73,10 +73,7 @@ void main() {
});
test('Throws StoreKeyNotFoundException for nonexistent keys', () {
expect(
() => sut.get(StoreKey.currentUser),
throwsA(isA<StoreKeyNotFoundException>()),
);
expect(() => sut.get(StoreKey.currentUser), throwsA(isA<StoreKeyNotFoundException>()));
});
test('Returns the stored value for the given key or the defaultValue', () {
@@ -91,17 +88,13 @@ void main() {
test('Skip insert when value is not modified', () async {
await sut.put(StoreKey.accessToken, _kAccessToken);
verifyNever(
() => mockStoreRepo.insert<String>(StoreKey.accessToken, any()),
);
verifyNever(() => mockStoreRepo.insert<String>(StoreKey.accessToken, any()));
});
test('Insert value when modified', () async {
final newAccessToken = _kAccessToken.toUpperCase();
await sut.put(StoreKey.accessToken, newAccessToken);
verify(
() => mockStoreRepo.insert<String>(StoreKey.accessToken, newAccessToken),
).called(1);
verify(() => mockStoreRepo.insert<String>(StoreKey.accessToken, newAccessToken)).called(1);
expect(sut.tryGet(StoreKey.accessToken), newAccessToken);
});
});
@@ -120,12 +113,7 @@ void main() {
test('Watches a specific key for changes', () async {
final stream = sut.watch(StoreKey.accessToken);
final events = <String?>[
_kAccessToken,
_kAccessToken.toUpperCase(),
null,
_kAccessToken.toLowerCase(),
];
final events = <String?>[_kAccessToken, _kAccessToken.toUpperCase(), null, _kAccessToken.toLowerCase()];
expectLater(stream, emitsInOrder(events));
@@ -54,40 +54,25 @@ void main() {
when(() => mockSyncStreamRepo.deletePartnerV1(any())).thenAnswer(successHandler);
when(() => mockSyncStreamRepo.updateAssetsV1(any())).thenAnswer(successHandler);
when(
() => mockSyncStreamRepo.updateAssetsV1(
any(),
debugLabel: any(named: 'debugLabel'),
),
() => mockSyncStreamRepo.updateAssetsV1(any(), debugLabel: any(named: 'debugLabel')),
).thenAnswer(successHandler);
when(() => mockSyncStreamRepo.deleteAssetsV1(any())).thenAnswer(successHandler);
when(
() => mockSyncStreamRepo.deleteAssetsV1(
any(),
debugLabel: any(named: 'debugLabel'),
),
() => mockSyncStreamRepo.deleteAssetsV1(any(), debugLabel: any(named: 'debugLabel')),
).thenAnswer(successHandler);
when(() => mockSyncStreamRepo.updateAssetsExifV1(any())).thenAnswer(successHandler);
when(
() => mockSyncStreamRepo.updateAssetsExifV1(
any(),
debugLabel: any(named: 'debugLabel'),
),
() => mockSyncStreamRepo.updateAssetsExifV1(any(), debugLabel: any(named: 'debugLabel')),
).thenAnswer(successHandler);
when(() => mockSyncStreamRepo.updateMemoriesV1(any())).thenAnswer(successHandler);
when(() => mockSyncStreamRepo.deleteMemoriesV1(any())).thenAnswer(successHandler);
when(() => mockSyncStreamRepo.updateMemoryAssetsV1(any())).thenAnswer(successHandler);
when(() => mockSyncStreamRepo.deleteMemoryAssetsV1(any())).thenAnswer(successHandler);
when(
() => mockSyncStreamRepo.updateStacksV1(
any(),
debugLabel: any(named: 'debugLabel'),
),
() => mockSyncStreamRepo.updateStacksV1(any(), debugLabel: any(named: 'debugLabel')),
).thenAnswer(successHandler);
when(
() => mockSyncStreamRepo.deleteStacksV1(
any(),
debugLabel: any(named: 'debugLabel'),
),
() => mockSyncStreamRepo.deleteStacksV1(any(), debugLabel: any(named: 'debugLabel')),
).thenAnswer(successHandler);
when(() => mockSyncStreamRepo.updateUserMetadatasV1(any())).thenAnswer(successHandler);
when(() => mockSyncStreamRepo.deleteUserMetadatasV1(any())).thenAnswer(successHandler);
@@ -96,10 +81,7 @@ void main() {
when(() => mockSyncStreamRepo.updateAssetFacesV1(any())).thenAnswer(successHandler);
when(() => mockSyncStreamRepo.deleteAssetFacesV1(any())).thenAnswer(successHandler);
sut = SyncStreamService(
syncApiRepository: mockSyncApiRepo,
syncStreamRepository: mockSyncStreamRepo,
);
sut = SyncStreamService(syncApiRepository: mockSyncApiRepo, syncStreamRepository: mockSyncStreamRepo);
});
Future<void> simulateEvents(List<SyncEvent> events) async {
@@ -108,41 +90,35 @@ void main() {
}
group("SyncStreamService - _handleEvents", () {
test(
"processes events and acks successfully when handlers succeed",
() async {
final events = [
SyncStreamStub.userDeleteV1,
SyncStreamStub.userV1Admin,
SyncStreamStub.userV1User,
SyncStreamStub.partnerDeleteV1,
SyncStreamStub.partnerV1,
];
await simulateEvents(events);
verifyInOrder([
() => mockSyncStreamRepo.deleteUsersV1(any()),
() => mockSyncApiRepo.ack(["2"]),
() => mockSyncStreamRepo.updateUsersV1(any()),
() => mockSyncApiRepo.ack(["5"]),
() => mockSyncStreamRepo.deletePartnerV1(any()),
() => mockSyncApiRepo.ack(["4"]),
() => mockSyncStreamRepo.updatePartnerV1(any()),
() => mockSyncApiRepo.ack(["3"]),
]);
verifyNever(() => mockAbortCallbackWrapper());
},
);
test("processes final batch correctly", () async {
test("processes events and acks successfully when handlers succeed", () async {
final events = [
SyncStreamStub.userDeleteV1,
SyncStreamStub.userV1Admin,
SyncStreamStub.userV1User,
SyncStreamStub.partnerDeleteV1,
SyncStreamStub.partnerV1,
];
await simulateEvents(events);
verifyInOrder([
() => mockSyncStreamRepo.deleteUsersV1(any()),
() => mockSyncApiRepo.ack(["2"]),
() => mockSyncStreamRepo.updateUsersV1(any()),
() => mockSyncApiRepo.ack(["5"]),
() => mockSyncStreamRepo.deletePartnerV1(any()),
() => mockSyncApiRepo.ack(["4"]),
() => mockSyncStreamRepo.updatePartnerV1(any()),
() => mockSyncApiRepo.ack(["3"]),
]);
verifyNever(() => mockAbortCallbackWrapper());
});
test("processes final batch correctly", () async {
final events = [SyncStreamStub.userDeleteV1, SyncStreamStub.userV1Admin];
await simulateEvents(events);
verifyInOrder([
() => mockSyncStreamRepo.deleteUsersV1(any()),
() => mockSyncApiRepo.ack(["2"]),
@@ -174,11 +150,7 @@ void main() {
);
await sut.sync();
final events = [
SyncStreamStub.userDeleteV1,
SyncStreamStub.userV1Admin,
SyncStreamStub.partnerDeleteV1,
];
final events = [SyncStreamStub.userDeleteV1, SyncStreamStub.userV1Admin, SyncStreamStub.partnerDeleteV1];
when(() => mockSyncStreamRepo.deleteUsersV1(any())).thenAnswer((_) async {
when(() => cancellationChecker()).thenReturn(true);
@@ -195,50 +167,43 @@ void main() {
verify(() => mockSyncApiRepo.ack(["2"])).called(1);
});
test(
"aborts and stops processing if cancelled before processing batch",
() async {
final cancellationChecker = _MockCancellationWrapper();
when(() => cancellationChecker()).thenReturn(false);
test("aborts and stops processing if cancelled before processing batch", () async {
final cancellationChecker = _MockCancellationWrapper();
when(() => cancellationChecker()).thenReturn(false);
final processingCompleter = Completer<void>();
bool handler1Started = false;
when(() => mockSyncStreamRepo.deleteUsersV1(any())).thenAnswer((_) async {
handler1Started = true;
return processingCompleter.future;
});
final processingCompleter = Completer<void>();
bool handler1Started = false;
when(() => mockSyncStreamRepo.deleteUsersV1(any())).thenAnswer((_) async {
handler1Started = true;
return processingCompleter.future;
});
sut = SyncStreamService(
syncApiRepository: mockSyncApiRepo,
syncStreamRepository: mockSyncStreamRepo,
cancelChecker: cancellationChecker.call,
);
sut = SyncStreamService(
syncApiRepository: mockSyncApiRepo,
syncStreamRepository: mockSyncStreamRepo,
cancelChecker: cancellationChecker.call,
);
await sut.sync();
await sut.sync();
final events = [
SyncStreamStub.userDeleteV1,
SyncStreamStub.userV1Admin,
SyncStreamStub.partnerDeleteV1,
];
final events = [SyncStreamStub.userDeleteV1, SyncStreamStub.userV1Admin, SyncStreamStub.partnerDeleteV1];
final processingFuture = handleEventsCallback(events, mockAbortCallbackWrapper.call);
await pumpEventQueue();
final processingFuture = handleEventsCallback(events, mockAbortCallbackWrapper.call);
await pumpEventQueue();
expect(handler1Started, isTrue);
expect(handler1Started, isTrue);
// Signal cancellation while handler 1 is waiting
when(() => cancellationChecker()).thenReturn(true);
await pumpEventQueue();
// Signal cancellation while handler 1 is waiting
when(() => cancellationChecker()).thenReturn(true);
await pumpEventQueue();
processingCompleter.complete();
await processingFuture;
processingCompleter.complete();
await processingFuture;
verifyNever(() => mockSyncStreamRepo.updateUsersV1(any()));
verifyNever(() => mockSyncStreamRepo.updateUsersV1(any()));
verify(() => mockSyncApiRepo.ack(["2"])).called(1);
},
);
verify(() => mockSyncApiRepo.ack(["2"])).called(1);
});
test("processes memory sync events successfully", () async {
final events = [
@@ -289,15 +254,9 @@ void main() {
test("handles memory sync failure gracefully", () async {
when(() => mockSyncStreamRepo.updateMemoriesV1(any())).thenThrow(Exception("Memory sync failed"));
final events = [
SyncStreamStub.memoryV1,
SyncStreamStub.userV1Admin,
];
final events = [SyncStreamStub.memoryV1, SyncStreamStub.userV1Admin];
expect(
() async => await simulateEvents(events),
throwsA(isA<Exception>()),
);
expect(() async => await simulateEvents(events), throwsA(isA<Exception>()));
});
test("processes memory asset events with correct data types", () async {
@@ -89,9 +89,7 @@ void main() {
when(() => mockUserApiRepo.getMyUser()).thenAnswer((_) async => null);
final result = await sut.refreshMyUser();
verifyNever(
() => mockStoreService.put(StoreKey.currentUser, UserStub.admin),
);
verifyNever(() => mockStoreService.put(StoreKey.currentUser, UserStub.admin));
verifyNever(() => mockUserRepo.update(UserStub.admin));
expect(result, isNull);
});
@@ -103,10 +101,7 @@ void main() {
final updatedUser = UserStub.admin.copyWith(profileImagePath: profileImagePath);
when(
() => mockUserApiRepo.createProfileImage(
name: profileImagePath,
data: Uint8List(0),
),
() => mockUserApiRepo.createProfileImage(name: profileImagePath, data: Uint8List(0)),
).thenAnswer((_) async => profileImagePath);
when(() => mockStoreService.put(StoreKey.currentUser, updatedUser)).thenAnswer((_) async => true);
when(() => mockUserRepo.update(updatedUser)).thenAnswer((_) async => UserStub.admin);
@@ -123,16 +118,11 @@ void main() {
final updatedUser = UserStub.admin.copyWith(profileImagePath: profileImagePath);
when(
() => mockUserApiRepo.createProfileImage(
name: profileImagePath,
data: Uint8List(0),
),
() => mockUserApiRepo.createProfileImage(name: profileImagePath, data: Uint8List(0)),
).thenThrow(Exception('Failed to create profile image'));
final result = await sut.createProfileImage(profileImagePath, Uint8List(0));
verifyNever(
() => mockStoreService.put(StoreKey.currentUser, updatedUser),
);
verifyNever(() => mockStoreService.put(StoreKey.currentUser, updatedUser));
verifyNever(() => mockUserRepo.update(updatedUser));
expect(result, isNull);
});