Build Android (FCM) / build-android-fcm (push) Canceled after 0s
Build Android / build-android (push) Canceled after 0s
Build iOS / build-ios (push) Canceled after 0s
Build Linux / build-linux (push) Canceled after 0s
Build macOS / build-macos (push) Canceled after 0s
Build Windows / build-windows (push) Canceled after 0s
Release (main) / android (oneme) (push) Canceled after 0s
Release (main) / android (qlyra) (push) Canceled after 0s
Release (main) / windows (push) Canceled after 0s
Release (main) / linux (push) Canceled after 0s
Release (main) / macos (push) Canceled after 0s
Release (main) / ios (push) Canceled after 0s
Release (main) / release (push) Canceled after 0s
118 lines
3.4 KiB
Dart
118 lines
3.4 KiB
Dart
import 'dart:io';
|
|
|
|
import 'package:crypto/crypto.dart';
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:qlyra/core/utils/update_checker.dart';
|
|
import 'package:qlyra/core/utils/update_installer.dart';
|
|
|
|
void main() {
|
|
const qlyra = AppUpdateArtifact(
|
|
name: 'qlyra.apk',
|
|
url: 'https://example.test/qlyra.apk',
|
|
flavor: 'qlyra',
|
|
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.qlyra.app'), 'qlyra');
|
|
expect(UpdateChecker.manifestSlugForPackageName('ru.oneme.app'), 'oneme');
|
|
});
|
|
|
|
test('selects only an artifact for the installed flavor', () {
|
|
expect(
|
|
UpdateInstaller.selectArtifact(
|
|
[qlyra, onemeArm64, onemeUniversal],
|
|
'ru.qlyra.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: 'qlyra',
|
|
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: 'qlyra',
|
|
abi: 'universal',
|
|
sizeBytes: 4,
|
|
sha256:
|
|
'dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd',
|
|
);
|
|
|
|
await expectLater(
|
|
UpdateInstaller.verifyArtifact(file, artifact),
|
|
throwsA(isA<UpdateIntegrityException>()),
|
|
);
|
|
});
|
|
}
|