Files
IKAR/test/update_artifact_test.dart
T

118 lines
3.4 KiB
Dart

import 'dart:io';
import 'package:crypto/crypto.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:ikar/core/utils/update_checker.dart';
import 'package:ikar/core/utils/update_installer.dart';
void main() {
const qlyra = AppUpdateArtifact(
name: 'qlyra.apk',
url: 'https://example.test/qlyra.apk',
flavor: 'ikar',
abi: 'universal',
sizeBytes: 100,
sha256: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
);
const onemeArm64 = AppUpdateArtifact(
name: 'oneme-arm64.apk',
url: 'https://example.test/oneme-arm64.apk',
flavor: 'oneme',
abi: 'arm64-v8a',
sizeBytes: 100,
sha256: 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb',
);
const onemeUniversal = AppUpdateArtifact(
name: 'oneme.apk',
url: 'https://example.test/oneme.apk',
flavor: 'oneme',
abi: 'universal',
sizeBytes: 100,
sha256: 'cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc',
);
test('maps package identities to independent Argus slugs', () {
expect(UpdateChecker.manifestSlugForPackageName('ru.ikar.app'), 'ikar');
expect(UpdateChecker.manifestSlugForPackageName('ru.oneme.app'), 'oneme');
});
test('selects only an artifact for the installed flavor', () {
expect(
UpdateInstaller.selectArtifact(
[qlyra, onemeArm64, onemeUniversal],
'ru.ikar.app',
['arm64-v8a'],
),
same(qlyra),
);
expect(
UpdateInstaller.selectArtifact(
[qlyra, onemeArm64, onemeUniversal],
'ru.oneme.app',
['arm64-v8a'],
),
same(onemeArm64),
);
});
test('falls back to a universal artifact of the same flavor', () {
expect(
UpdateInstaller.selectArtifact(
[qlyra, onemeUniversal],
'ru.oneme.app',
['x86_64'],
),
same(onemeUniversal),
);
});
test('does not cross-install another flavor', () {
expect(
UpdateInstaller.selectArtifact([qlyra], 'ru.oneme.app', ['arm64-v8a']),
isNull,
);
});
test('verifies artifact size and SHA-256', () async {
final directory = await Directory.systemTemp.createTemp('qlyra-update-');
addTearDown(() => directory.delete(recursive: true));
final file = File('${directory.path}/update.apk');
final bytes = [1, 2, 3, 4];
await file.writeAsBytes(bytes);
final artifact = AppUpdateArtifact(
name: 'update.apk',
url: 'https://example.test/update.apk',
flavor: 'ikar',
abi: 'universal',
sizeBytes: bytes.length,
sha256: sha256.convert(bytes).toString(),
);
await expectLater(
UpdateInstaller.verifyArtifact(file, artifact),
completes,
);
});
test('rejects an artifact with a different digest', () async {
final directory = await Directory.systemTemp.createTemp('qlyra-update-');
addTearDown(() => directory.delete(recursive: true));
final file = File('${directory.path}/update.apk');
await file.writeAsBytes([1, 2, 3, 4]);
const artifact = AppUpdateArtifact(
name: 'update.apk',
url: 'https://example.test/update.apk',
flavor: 'ikar',
abi: 'universal',
sizeBytes: 4,
sha256:
'dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd',
);
await expectLater(
UpdateInstaller.verifyArtifact(file, artifact),
throwsA(isA<UpdateIntegrityException>()),
);
});
}