65c4d768f1
Changes are reformatting and using the nullable list element operator. Change-Id: Iea1f4d2fcb06056f14804c8fe8b33c0b4d9037f2 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/477561 Commit-Queue: Sigurd Meldgaard <sigurdm@google.com> Reviewed-by: Daco Harkes <dacoharkes@google.com>
317 lines
9.6 KiB
Dart
317 lines
9.6 KiB
Dart
// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
|
|
// for details. All rights reserved. Use of this source code is governed by a
|
|
// BSD-style license that can be found in the LICENSE file.
|
|
|
|
import 'dart:convert';
|
|
import 'dart:io' as io;
|
|
|
|
import 'package:code_assets/code_assets.dart' show OS;
|
|
import 'package:dartdev/src/sdk_cache.dart';
|
|
import 'package:file/file.dart';
|
|
import 'package:file/memory.dart';
|
|
import 'package:hooks_runner/hooks_runner.dart' show Target;
|
|
import 'package:http/http.dart' as http;
|
|
import 'package:http/testing.dart' as http;
|
|
import 'package:test/test.dart';
|
|
|
|
const dartArchiveUri = 'https://storage.googleapis.com/dart-archive';
|
|
|
|
void main() {
|
|
late SdkCache cache;
|
|
late FileSystem fs;
|
|
late StringBuffer stderr;
|
|
late Map<String, http.Response> expectedRequests;
|
|
late Map<String, io.ProcessResult> chmodRuns;
|
|
|
|
setUp(() {
|
|
// Make sure we support both path separators.
|
|
fs = MemoryFileSystem(
|
|
style: io.Platform.isWindows
|
|
? FileSystemStyle.windows
|
|
: FileSystemStyle.posix,
|
|
);
|
|
stderr = StringBuffer();
|
|
expectedRequests = <String, http.Response>{};
|
|
chmodRuns = <String, io.ProcessResult>{};
|
|
|
|
cache = SdkCache(
|
|
directory: fs.directory(Uri.file('/tmp/cache')).path,
|
|
stderr: stderr,
|
|
verbose: true,
|
|
fs: fs,
|
|
httpClient: http.MockClient((request) async {
|
|
final key = '${request.method.toUpperCase()} ${request.url}';
|
|
if (!expectedRequests.containsKey(key)) {
|
|
throw Exception('Unexpected request $key');
|
|
}
|
|
return expectedRequests[key]!;
|
|
}),
|
|
chmod: (path) => chmodRuns[path]!,
|
|
);
|
|
});
|
|
|
|
group('resolveStage', () {
|
|
test('Uses signed on macOS dev for executables', () {
|
|
expect(
|
|
SdkCache.resolveStage(
|
|
channel: Channel.dev,
|
|
isExecutable: true,
|
|
hostOS: OS.macOS,
|
|
),
|
|
Stage.signed,
|
|
);
|
|
});
|
|
|
|
test('Uses raw on macOS main for executables', () {
|
|
expect(
|
|
SdkCache.resolveStage(
|
|
channel: Channel.main,
|
|
isExecutable: true,
|
|
hostOS: OS.macOS,
|
|
),
|
|
Stage.raw,
|
|
);
|
|
});
|
|
|
|
test('Uses raw on macOS stable for non-executables', () {
|
|
expect(
|
|
SdkCache.resolveStage(
|
|
channel: Channel.stable,
|
|
isExecutable: false,
|
|
hostOS: OS.macOS,
|
|
),
|
|
Stage.raw,
|
|
);
|
|
});
|
|
});
|
|
|
|
group('resolveVersion', () {
|
|
test('Resolves release version', () async {
|
|
final version = '3.4.4';
|
|
final revision = '60465149414572c8ca189d8f65fdb39795c4b97d';
|
|
final folder = await cache.resolveVersion(
|
|
version: version,
|
|
revision: revision,
|
|
channelName: 'stable',
|
|
host: Target.linuxArm64,
|
|
);
|
|
expect(folder.version, version);
|
|
expect(folder.revision, revision);
|
|
expect(folder.channel, Channel.stable);
|
|
expect(
|
|
folder.fileUri('VERSION', stage: Stage.raw).toString(),
|
|
'$dartArchiveUri/channels/stable/raw/hash/$revision/VERSION',
|
|
);
|
|
});
|
|
|
|
test('Falls back to the latest on empty main revision', () async {
|
|
final version = '3.8.0';
|
|
final revision = '';
|
|
|
|
final latestVersion =
|
|
'3.8.0-edge.7ee7416a62efb7eb23eb2a87eb34d2895559ba06';
|
|
final latestRevision = '7ee7416a62efb7eb23eb2a87eb34d2895559ba06';
|
|
|
|
expectedRequests['GET $dartArchiveUri/channels/main/raw/latest/VERSION'] =
|
|
http.Response(
|
|
json.encode({'version': latestVersion, 'revision': latestRevision}),
|
|
io.HttpStatus.ok,
|
|
);
|
|
final folder = await cache.resolveVersion(
|
|
version: version,
|
|
revision: revision,
|
|
channelName: 'main',
|
|
host: Target.macOSArm64,
|
|
);
|
|
expect(folder.version, latestVersion);
|
|
expect(folder.revision, latestRevision);
|
|
expect(folder.channel, Channel.main);
|
|
});
|
|
|
|
test('Falls back to the latest on unknown main revision', () async {
|
|
final version = '3.8.0';
|
|
final revision = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa';
|
|
|
|
final latestVersion =
|
|
'3.8.0-edge.7ee7416a62efb7eb23eb2a87eb34d2895559ba06';
|
|
final latestRevision = '7ee7416a62efb7eb23eb2a87eb34d2895559ba06';
|
|
|
|
expectedRequests.addAll({
|
|
// Revision validation request.
|
|
'HEAD $dartArchiveUri/channels/main/raw/hash/$revision/VERSION':
|
|
http.Response('', io.HttpStatus.notFound),
|
|
// Revision resolution request.
|
|
'GET $dartArchiveUri/channels/main/raw/latest/VERSION': http.Response(
|
|
json.encode({'version': latestVersion, 'revision': latestRevision}),
|
|
io.HttpStatus.ok,
|
|
),
|
|
});
|
|
|
|
final folder = await cache.resolveVersion(
|
|
version: version,
|
|
revision: revision,
|
|
channelName: 'main',
|
|
host: Target.macOSArm64,
|
|
);
|
|
expect(folder.version, latestVersion);
|
|
expect(folder.revision, latestRevision);
|
|
expect(folder.channel, Channel.main);
|
|
});
|
|
|
|
test('Reports unknown channel', () async {
|
|
try {
|
|
await cache.resolveVersion(
|
|
channelName: 'wat',
|
|
host: Target.linuxArm64,
|
|
revision: '',
|
|
version: '4.0',
|
|
);
|
|
fail('expected to throw');
|
|
} on ArgumentError catch (e) {
|
|
expect(e.message, contains('Unsupported channel'));
|
|
}
|
|
});
|
|
});
|
|
|
|
group('ensureArtifact', () {
|
|
test('Skips download when file exists', () async {
|
|
final version = '3.4.4';
|
|
final revision = '60465149414572c8ca189d8f65fdb39795c4b97d';
|
|
|
|
final genSnapshotFile = fs.file(
|
|
Uri.file(
|
|
'/tmp/cache/$version/gen_snapshot_windows_arm64_linux_x64.exe',
|
|
),
|
|
);
|
|
genSnapshotFile.createSync(exclusive: true, recursive: true);
|
|
|
|
final path = await cache.ensureGenSnapshot(
|
|
archiveFolder: ArchiveFolder(
|
|
channel: Channel.stable,
|
|
version: version,
|
|
revision: revision,
|
|
),
|
|
host: Target.windowsArm64,
|
|
target: Target.linuxX64,
|
|
);
|
|
expect(path, genSnapshotFile.path);
|
|
});
|
|
|
|
test('Downloads signed gen_snapshot on macOS beta', () async {
|
|
final version = '3.8.0-171.2.beta';
|
|
final revision = '54cec4d7d36e7a5066770287998f425606a2f983';
|
|
|
|
final archiveFolder = ArchiveFolder(
|
|
channel: Channel.beta,
|
|
version: version,
|
|
revision: revision,
|
|
);
|
|
expectedRequests['GET $dartArchiveUri/channels/beta/signed/hash/'
|
|
'$revision/sdk/gen_snapshot_macos_arm64_linux_x64'] = http.Response(
|
|
'i am gen_snapshot',
|
|
io.HttpStatus.ok,
|
|
);
|
|
|
|
final path = await cache.ensureGenSnapshot(
|
|
archiveFolder: archiveFolder,
|
|
host: Target.macOSArm64,
|
|
target: Target.linuxX64,
|
|
);
|
|
|
|
expect(
|
|
path,
|
|
fs
|
|
.file(
|
|
Uri.file(
|
|
'/tmp/cache/$version/gen_snapshot_macos_arm64_linux_x64',
|
|
),
|
|
)
|
|
.path,
|
|
);
|
|
expect(fs.file(path).readAsStringSync(), 'i am gen_snapshot');
|
|
});
|
|
|
|
test('Downloads raw dartaotruntime on macOS beta', () async {
|
|
final version = '3.8.0-171.2.beta';
|
|
final revision = '54cec4d7d36e7a5066770287998f425606a2f983';
|
|
|
|
final archiveFolder = ArchiveFolder(
|
|
channel: Channel.beta,
|
|
version: version,
|
|
revision: revision,
|
|
);
|
|
expectedRequests['GET $dartArchiveUri/channels/beta/raw/hash/'
|
|
'$revision/sdk/dartaotruntime_linux_x64'] = http.Response(
|
|
'i am dartaotruntime',
|
|
io.HttpStatus.ok,
|
|
);
|
|
|
|
final path = await cache.ensureDartAotRuntime(
|
|
archiveFolder: archiveFolder,
|
|
host: Target.macOSArm64,
|
|
target: Target.linuxX64,
|
|
);
|
|
|
|
expect(
|
|
path,
|
|
fs.file(Uri.file('/tmp/cache/$version/dartaotruntime_linux_x64')).path,
|
|
);
|
|
expect(fs.file(path).readAsStringSync(), 'i am dartaotruntime');
|
|
});
|
|
|
|
test('Downloads gen_snapshot.exe on Windows stable', () async {
|
|
final version = '3.7.2';
|
|
final channel = Channel.stable;
|
|
final revision = '9594995093f642957b780603c6435d9e7a61b923';
|
|
final binary = 'gen_snapshot_windows_x64_linux_x64.exe';
|
|
|
|
final archiveFolder = ArchiveFolder(
|
|
channel: channel,
|
|
version: version,
|
|
revision: revision,
|
|
);
|
|
expectedRequests['GET $dartArchiveUri/channels/stable/raw/hash/'
|
|
'$revision/sdk/$binary'] = http.Response(
|
|
'i am gen_snapshot',
|
|
io.HttpStatus.ok,
|
|
);
|
|
|
|
final path = await cache.ensureGenSnapshot(
|
|
archiveFolder: archiveFolder,
|
|
host: Target.windowsX64,
|
|
target: Target.linuxX64,
|
|
);
|
|
|
|
expect(path, fs.file(Uri.file('/tmp/cache/$version/$binary')).path);
|
|
expect(fs.file(path).readAsStringSync(), 'i am gen_snapshot');
|
|
});
|
|
|
|
test('Downloads dartaotruntime on Windows stable', () async {
|
|
final version = '3.7.2';
|
|
final channel = Channel.stable;
|
|
final revision = '9594995093f642957b780603c6435d9e7a61b923';
|
|
final binary = 'dartaotruntime_linux_x64';
|
|
|
|
final archiveFolder = ArchiveFolder(
|
|
channel: channel,
|
|
version: version,
|
|
revision: revision,
|
|
);
|
|
expectedRequests['GET $dartArchiveUri/channels/stable/raw/hash/'
|
|
'$revision/sdk/$binary'] = http.Response(
|
|
'i am dartaotruntime',
|
|
io.HttpStatus.ok,
|
|
);
|
|
|
|
final path = await cache.ensureDartAotRuntime(
|
|
archiveFolder: archiveFolder,
|
|
host: Target.windowsX64,
|
|
target: Target.linuxX64,
|
|
);
|
|
|
|
expect(path, fs.file(Uri.file('/tmp/cache/$version/$binary')).path);
|
|
expect(fs.file(path).readAsStringSync(), 'i am dartaotruntime');
|
|
});
|
|
});
|
|
}
|