feat: verify embedded backup media checksums
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@ -2359,6 +2359,8 @@ void main() {
|
||||
fileName: 'media-1.png',
|
||||
mimeType: 'image/png',
|
||||
sizeBytes: 4,
|
||||
sha256:
|
||||
'9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08',
|
||||
base64: 'dGVzdA==',
|
||||
),
|
||||
],
|
||||
@ -2444,6 +2446,8 @@ void main() {
|
||||
fileName: 'media-1.png',
|
||||
mimeType: 'image/png',
|
||||
sizeBytes: 4,
|
||||
sha256:
|
||||
'9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08',
|
||||
base64: 'dGVzdA==',
|
||||
),
|
||||
],
|
||||
@ -2485,71 +2489,65 @@ void main() {
|
||||
expect(repository.appliedModes, isEmpty);
|
||||
});
|
||||
|
||||
test(
|
||||
'Data import use case restores media and applies selected mode',
|
||||
() async {
|
||||
final repository = _FakeLocalDataBackupRepository();
|
||||
final mediaStore = _FakeLocalBackupMediaStore(
|
||||
restored: const {
|
||||
'media-1': RestoredMediaFile(
|
||||
mediaAssetId: 'media-1',
|
||||
localUri: 'file:///restored/media-1.png',
|
||||
sizeBytes: 4,
|
||||
),
|
||||
},
|
||||
);
|
||||
final useCase = DataImportUseCase(
|
||||
repository: repository,
|
||||
mediaStore: mediaStore,
|
||||
clock: _FakeClock(DateTime.utc(2026, 7, 22, 12)),
|
||||
);
|
||||
final bytes = const LocalBackupCodec().encode(
|
||||
_backupSnapshot(
|
||||
mediaAssets: [
|
||||
_backupResource(
|
||||
id: 'media-1',
|
||||
updatedAt: DateTime.utc(2026, 7, 22, 10),
|
||||
payload: {
|
||||
'id': 'media-1',
|
||||
'metadata': _backupMetadata(
|
||||
'media-1',
|
||||
DateTime.utc(2026, 7, 22, 10),
|
||||
),
|
||||
'localUri': 'file:///old/media-1.png',
|
||||
},
|
||||
),
|
||||
],
|
||||
mediaFiles: const [
|
||||
EmbeddedBackupMediaFile(
|
||||
mediaAssetId: 'media-1',
|
||||
role: 'original',
|
||||
fileName: 'media-1.png',
|
||||
mimeType: 'image/png',
|
||||
sizeBytes: 4,
|
||||
base64: 'dGVzdA==',
|
||||
),
|
||||
],
|
||||
test('Data import use case restores media and applies selected mode', () async {
|
||||
final repository = _FakeLocalDataBackupRepository();
|
||||
final mediaStore = _FakeLocalBackupMediaStore(
|
||||
restored: const {
|
||||
'media-1': RestoredMediaFile(
|
||||
mediaAssetId: 'media-1',
|
||||
localUri: 'file:///restored/media-1.png',
|
||||
sizeBytes: 4,
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
final useCase = DataImportUseCase(
|
||||
repository: repository,
|
||||
mediaStore: mediaStore,
|
||||
clock: _FakeClock(DateTime.utc(2026, 7, 22, 12)),
|
||||
);
|
||||
final bytes = const LocalBackupCodec().encode(
|
||||
_backupSnapshot(
|
||||
mediaAssets: [
|
||||
_backupResource(
|
||||
id: 'media-1',
|
||||
updatedAt: DateTime.utc(2026, 7, 22, 10),
|
||||
payload: {
|
||||
'id': 'media-1',
|
||||
'metadata': _backupMetadata(
|
||||
'media-1',
|
||||
DateTime.utc(2026, 7, 22, 10),
|
||||
),
|
||||
'localUri': 'file:///old/media-1.png',
|
||||
},
|
||||
),
|
||||
],
|
||||
mediaFiles: const [
|
||||
EmbeddedBackupMediaFile(
|
||||
mediaAssetId: 'media-1',
|
||||
role: 'original',
|
||||
fileName: 'media-1.png',
|
||||
mimeType: 'image/png',
|
||||
sizeBytes: 4,
|
||||
sha256:
|
||||
'9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08',
|
||||
base64: 'dGVzdA==',
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
final result = await useCase.importFrom(
|
||||
bytes,
|
||||
mode: LocalBackupImportMode.replaceAll,
|
||||
);
|
||||
final result = await useCase.importFrom(
|
||||
bytes,
|
||||
mode: LocalBackupImportMode.replaceAll,
|
||||
);
|
||||
|
||||
expect(result.insertedCount, 0);
|
||||
expect(repository.appliedModes, [LocalBackupImportMode.replaceAll]);
|
||||
expect(
|
||||
repository
|
||||
.appliedSnapshots
|
||||
.single
|
||||
.mediaAssets
|
||||
.single
|
||||
.payload['localUri'],
|
||||
'file:///restored/media-1.png',
|
||||
);
|
||||
},
|
||||
);
|
||||
expect(result.insertedCount, 0);
|
||||
expect(repository.appliedModes, [LocalBackupImportMode.replaceAll]);
|
||||
expect(
|
||||
repository.appliedSnapshots.single.mediaAssets.single.payload['localUri'],
|
||||
'file:///restored/media-1.png',
|
||||
);
|
||||
});
|
||||
|
||||
test('Program use case duplicates deeply with copy name conflicts', () async {
|
||||
final programRepository = _FakeProgramRepository();
|
||||
|
||||
Reference in New Issue
Block a user