feat(shorebird_cli): support using linker from local engine (#1550)

This commit is contained in:
Felix Angelov
2023-12-06 12:04:13 -06:00
committed by GitHub
parent bce214e856
commit b7cd3a67a4
15 changed files with 402 additions and 210 deletions
+2 -2
View File
@@ -10,13 +10,13 @@ import 'package:shorebird_cli/src/code_push_client_wrapper.dart';
import 'package:shorebird_cli/src/command_runner.dart';
import 'package:shorebird_cli/src/doctor.dart';
import 'package:shorebird_cli/src/executables/executables.dart';
import 'package:shorebird_cli/src/flutter_artifacts.dart';
import 'package:shorebird_cli/src/http_client/http_client.dart';
import 'package:shorebird_cli/src/logger.dart';
import 'package:shorebird_cli/src/os/os.dart';
import 'package:shorebird_cli/src/patch_diff_checker.dart';
import 'package:shorebird_cli/src/platform.dart';
import 'package:shorebird_cli/src/process.dart';
import 'package:shorebird_cli/src/shorebird_artifacts.dart';
import 'package:shorebird_cli/src/shorebird_env.dart';
import 'package:shorebird_cli/src/shorebird_flutter.dart';
import 'package:shorebird_cli/src/shorebird_validator.dart';
@@ -39,7 +39,6 @@ Future<void> main(List<String> args) async {
devicectlRef,
doctorRef,
engineConfigRef,
flutterArtifactsRef,
gitRef,
gradlewRef,
httpClientRef,
@@ -51,6 +50,7 @@ Future<void> main(List<String> args) async {
patchDiffCheckerRef,
platformRef,
processRef,
shorebirdArtifactsRef,
shorebirdEnvRef,
shorebirdFlutterRef,
shorebirdValidatorRef,
@@ -10,6 +10,7 @@ import 'package:shorebird_cli/src/http_client/http_client.dart';
import 'package:shorebird_cli/src/logger.dart';
import 'package:shorebird_cli/src/platform.dart';
import 'package:shorebird_cli/src/process.dart';
import 'package:shorebird_cli/src/shorebird_artifacts.dart';
import 'package:shorebird_cli/src/shorebird_env.dart';
/// {@template cache_update_failure}
@@ -47,6 +48,13 @@ final cacheRef = create(Cache.new);
// The [Cache] instance available in the current zone.
Cache get cache => read(cacheRef);
/// {@template cache}
/// A class that manages the artifacts cached by Shorebird.
/// This class handles fetching and unpacking artifacts from various sources.
///
/// To access specific artifacts, it's generally recommended to use
/// [ShorebirdArtifacts] since uses the current Shorebird environment.
/// {@endtemplate}
class Cache {
Cache({this.extractArchive = _defaultArchiveExtractor}) {
registerArtifact(PatchArtifact(cache: this, platform: platform));
@@ -6,10 +6,10 @@ import 'package:cli_completion/cli_completion.dart';
import 'package:mason_logger/mason_logger.dart';
import 'package:scoped/scoped.dart';
import 'package:shorebird_cli/src/commands/commands.dart';
import 'package:shorebird_cli/src/flutter_artifacts.dart';
import 'package:shorebird_cli/src/logger.dart';
import 'package:shorebird_cli/src/platform.dart';
import 'package:shorebird_cli/src/process.dart';
import 'package:shorebird_cli/src/shorebird_artifacts.dart';
import 'package:shorebird_cli/src/shorebird_env.dart';
import 'package:shorebird_cli/src/shorebird_flutter.dart';
import 'package:shorebird_cli/src/shorebird_version.dart';
@@ -87,16 +87,15 @@ class ShorebirdCliCommandRunner extends CompletionCommandRunner<int> {
localEngine: topLevelResults['local-engine'] as String?,
);
final process = ShorebirdProcess(engineConfig: engineConfig);
final flutterArtifacts = engineConfig.localEngineSrcPath != null
? const FlutterLocalEngineArtifacts()
: const FlutterCachedArtifacts();
final shorebirdArtifacts = engineConfig.localEngineSrcPath != null
? const ShorebirdLocalEngineArtifacts()
: const ShorebirdCachedArtifacts();
return await runScoped<Future<int?>>(
() => runCommand(topLevelResults),
values: {
engineConfigRef.overrideWith(() => engineConfig),
processRef.overrideWith(() => process),
flutterArtifactsRef.overrideWith(() => flutterArtifacts),
shorebirdArtifactsRef.overrideWith(() => shorebirdArtifacts),
},
) ??
ExitCode.success.code;
@@ -14,12 +14,12 @@ import 'package:shorebird_cli/src/config/config.dart';
import 'package:shorebird_cli/src/deployment_track.dart';
import 'package:shorebird_cli/src/doctor.dart';
import 'package:shorebird_cli/src/executables/executables.dart';
import 'package:shorebird_cli/src/flutter_artifacts.dart';
import 'package:shorebird_cli/src/formatters/file_size_formatter.dart';
import 'package:shorebird_cli/src/ios.dart';
import 'package:shorebird_cli/src/logger.dart';
import 'package:shorebird_cli/src/patch_diff_checker.dart';
import 'package:shorebird_cli/src/shorebird_artifact_mixin.dart';
import 'package:shorebird_cli/src/shorebird_artifacts.dart';
import 'package:shorebird_cli/src/shorebird_build_mixin.dart';
import 'package:shorebird_cli/src/shorebird_env.dart';
import 'package:shorebird_cli/src/shorebird_flutter.dart';
@@ -392,8 +392,8 @@ ${summary.join('\n')}
}
final analyzeSnapshot = File(
flutterArtifacts.getArtifactPath(
artifact: FlutterArtifact.analyzeSnapshot,
shorebirdArtifacts.getArtifactPath(
artifact: ShorebirdArtifact.analyzeSnapshot,
),
);
@@ -2,6 +2,8 @@ import 'package:path/path.dart' as p;
import 'package:scoped/scoped.dart';
import 'package:shorebird_cli/src/cache.dart';
import 'package:shorebird_cli/src/process.dart';
import 'package:shorebird_cli/src/shorebird_artifacts.dart';
import 'package:shorebird_cli/src/shorebird_env.dart';
/// A reference to a [AotTools] instance.
final aotToolsRef = create(AotTools.new);
@@ -11,18 +13,23 @@ AotTools get aotTools => read(aotToolsRef);
/// Wrapper around the shorebird `aot-tools` executable.
class AotTools {
static const executableName = 'aot-tools';
Future<ShorebirdProcessResult> _exec(
List<String> command, {
String? workingDirectory,
}) async {
await cache.updateAll();
final executable = p.join(
cache.getArtifactDirectory(executableName).path,
executableName,
final executable = shorebirdArtifacts.getArtifactPath(
artifact: ShorebirdArtifact.aotTools,
);
if (p.extension(executable) == '.dart') {
return process.run(
shorebirdEnv.dartBinaryFile.path,
[executable, ...command],
workingDirectory: workingDirectory,
);
}
return process.run(executable, command, workingDirectory: workingDirectory);
}
@@ -1,123 +0,0 @@
// ignore_for_file: one_member_abstracts
import 'dart:io';
import 'package:path/path.dart' as p;
import 'package:scoped/scoped.dart';
import 'package:shorebird_cli/src/process.dart';
import 'package:shorebird_cli/src/shorebird_env.dart';
/// All Flutter artifacts used explicitly by Shorebird.
enum FlutterArtifact {
/// The gen_snapshot executable.
genSnapshot,
/// The analyze_snapshot executable.
analyzeSnapshot,
}
/// A reference to a [FlutterArtifacts] instance.
final flutterArtifactsRef = create<FlutterArtifacts>(
FlutterCachedArtifacts.new,
);
/// The [FlutterArtifacts] instance available in the current zone.
FlutterArtifacts get flutterArtifacts => read(flutterArtifactsRef);
/// {@template flutter_artifacts}
/// A class that provides access to Flutter artifacts.
/// {@endtemplate}
abstract class FlutterArtifacts {
/// Returns the path to the given [artifact].
String getArtifactPath({required FlutterArtifact artifact});
}
/// {@template flutter_cached_artifacts}
/// A class that provides access to cached Flutter artifacts.
/// {@endtemplate}
class FlutterCachedArtifacts implements FlutterArtifacts {
/// {@macro flutter_cached_artifacts}
const FlutterCachedArtifacts();
@override
String getArtifactPath({
required FlutterArtifact artifact,
}) {
switch (artifact) {
case FlutterArtifact.genSnapshot:
return _genSnapshotFile.path;
case FlutterArtifact.analyzeSnapshot:
return _analyzeSnapshotFile.path;
}
}
File get _genSnapshotFile {
return File(
p.join(
shorebirdEnv.flutterDirectory.path,
'bin',
'cache',
'artifacts',
'engine',
'ios-release',
'gen_snapshot_arm64',
),
);
}
File get _analyzeSnapshotFile {
return File(
p.join(
shorebirdEnv.flutterDirectory.path,
'bin',
'cache',
'artifacts',
'engine',
'ios-release',
'analyze_snapshot_arm64',
),
);
}
}
/// {@template flutter_local_engine_artifacts}
/// A class that provides access to locally built Flutter artifacts.
/// {@endtemplate}
class FlutterLocalEngineArtifacts implements FlutterArtifacts {
/// {@macro flutter_local_engine_artifacts}
const FlutterLocalEngineArtifacts();
@override
String getArtifactPath({required FlutterArtifact artifact}) {
switch (artifact) {
case FlutterArtifact.genSnapshot:
return _genSnapshotFile.path;
case FlutterArtifact.analyzeSnapshot:
return _analyzeSnapshotFile.path;
}
}
File get _genSnapshotFile {
return File(
p.join(
engineConfig.localEngineSrcPath!,
'out',
'ios_release',
'clang_x64',
'gen_snapshot_arm64',
),
);
}
File get _analyzeSnapshotFile {
return File(
p.join(
engineConfig.localEngineSrcPath!,
'out',
'ios_release',
'clang_x64',
'analyze_snapshot_arm64',
),
);
}
}
@@ -0,0 +1,156 @@
// ignore_for_file: one_member_abstracts
import 'dart:io';
import 'package:path/path.dart' as p;
import 'package:scoped/scoped.dart';
import 'package:shorebird_cli/src/cache.dart';
import 'package:shorebird_cli/src/process.dart';
import 'package:shorebird_cli/src/shorebird_env.dart';
/// All Shorebird artifacts used explicitly by Shorebird.
enum ShorebirdArtifact {
/// The analyze_snapshot executable.
analyzeSnapshot,
/// The aot_tools executable.
aotTools,
/// The gen_snapshot executable.
genSnapshot,
}
/// A reference to a [ShorebirdArtifacts] instance.
final shorebirdArtifactsRef = create<ShorebirdArtifacts>(
ShorebirdCachedArtifacts.new,
);
/// The [ShorebirdArtifacts] instance available in the current zone.
ShorebirdArtifacts get shorebirdArtifacts => read(shorebirdArtifactsRef);
/// {@template shorebird_artifacts}
/// A class that provides access to Shorebird artifacts.
/// {@endtemplate}
abstract class ShorebirdArtifacts {
/// Returns the path to the given [artifact].
String getArtifactPath({required ShorebirdArtifact artifact});
}
/// {@template shorebird_cached_artifacts}
/// A class that provides access to cached Shorebird artifacts.
/// {@endtemplate}
class ShorebirdCachedArtifacts implements ShorebirdArtifacts {
/// {@macro shorebird_cached_artifacts}
const ShorebirdCachedArtifacts();
@override
String getArtifactPath({
required ShorebirdArtifact artifact,
}) {
switch (artifact) {
case ShorebirdArtifact.analyzeSnapshot:
return _analyzeSnapshotFile.path;
case ShorebirdArtifact.aotTools:
return _aotToolsFile.path;
case ShorebirdArtifact.genSnapshot:
return _genSnapshotFile.path;
}
}
File get _analyzeSnapshotFile {
return File(
p.join(
shorebirdEnv.flutterDirectory.path,
'bin',
'cache',
'artifacts',
'engine',
'ios-release',
'darwin-x64',
'analyze_snapshot',
),
);
}
File get _aotToolsFile {
const executableName = 'aot-tools';
return File(
p.join(
cache.getArtifactDirectory(executableName).path,
executableName,
),
);
}
File get _genSnapshotFile {
return File(
p.join(
shorebirdEnv.flutterDirectory.path,
'bin',
'cache',
'artifacts',
'engine',
'ios-release',
'gen_snapshot_arm64',
),
);
}
}
/// {@template shorebird_local_engine_artifacts}
/// A class that provides access to locally built Shorebird artifacts.
/// {@endtemplate}
class ShorebirdLocalEngineArtifacts implements ShorebirdArtifacts {
/// {@macro shorebird_local_engine_artifacts}
const ShorebirdLocalEngineArtifacts();
@override
String getArtifactPath({required ShorebirdArtifact artifact}) {
switch (artifact) {
case ShorebirdArtifact.analyzeSnapshot:
return _analyzeSnapshotFile.path;
case ShorebirdArtifact.aotTools:
return _aotToolsFile.path;
case ShorebirdArtifact.genSnapshot:
return _genSnapshotFile.path;
}
}
File get _analyzeSnapshotFile {
return File(
p.join(
engineConfig.localEngineSrcPath!,
'out',
'ios_release',
'clang_x64',
'analyze_snapshot_arm64',
),
);
}
File get _aotToolsFile {
return File(
p.join(
engineConfig.localEngineSrcPath!,
'third_party',
'dart',
'pkg',
'aot_tools',
'bin',
'aot_tools.dart',
),
);
}
File get _genSnapshotFile {
return File(
p.join(
engineConfig.localEngineSrcPath!,
'out',
'ios_release',
'clang_x64',
'gen_snapshot_arm64',
),
);
}
}
@@ -3,10 +3,10 @@ import 'dart:io';
import 'package:collection/collection.dart';
import 'package:mason_logger/mason_logger.dart';
import 'package:shorebird_cli/src/command.dart';
import 'package:shorebird_cli/src/flutter_artifacts.dart';
import 'package:shorebird_cli/src/logger.dart';
import 'package:shorebird_cli/src/os/operating_system_interface.dart';
import 'package:shorebird_cli/src/process.dart';
import 'package:shorebird_cli/src/shorebird_artifacts.dart';
enum Arch {
arm64,
@@ -347,7 +347,9 @@ Either run `flutter pub get` manually, or follow the steps in ${link(uri: Uri.pa
];
final result = await process.run(
flutterArtifacts.getArtifactPath(artifact: FlutterArtifact.genSnapshot),
shorebirdArtifacts.getArtifactPath(
artifact: ShorebirdArtifact.genSnapshot,
),
arguments,
);
@@ -78,6 +78,11 @@ class ShorebirdEnv {
return File(p.join(flutterDirectory.path, 'bin', 'flutter'));
}
/// The Shorebird-vended Dart binary.
File get dartBinaryFile {
return File(p.join(flutterDirectory.path, 'bin', 'dart'));
}
/// The `shorebird.yaml` file for this project.
File getShorebirdYamlFile({required Directory cwd}) {
return File(p.join(cwd.path, 'shorebird.yaml'));
@@ -17,12 +17,12 @@ import 'package:shorebird_cli/src/config/config.dart';
import 'package:shorebird_cli/src/deployment_track.dart';
import 'package:shorebird_cli/src/doctor.dart';
import 'package:shorebird_cli/src/executables/aot_tools.dart';
import 'package:shorebird_cli/src/flutter_artifacts.dart';
import 'package:shorebird_cli/src/logger.dart';
import 'package:shorebird_cli/src/os/operating_system_interface.dart';
import 'package:shorebird_cli/src/patch_diff_checker.dart';
import 'package:shorebird_cli/src/platform.dart';
import 'package:shorebird_cli/src/process.dart';
import 'package:shorebird_cli/src/shorebird_artifacts.dart';
import 'package:shorebird_cli/src/shorebird_env.dart';
import 'package:shorebird_cli/src/shorebird_flutter.dart';
import 'package:shorebird_cli/src/shorebird_validator.dart';
@@ -137,7 +137,7 @@ flutter:
late File genSnapshotFile;
late File analyzeSnapshotFile;
late File releaseArtifactFile;
late FlutterArtifacts flutterArtifacts;
late ShorebirdArtifacts shorebirdArtifacts;
late Doctor doctor;
late IosArchiveDiffer archiveDiffer;
late Progress progress;
@@ -165,7 +165,7 @@ flutter:
authRef.overrideWith(() => auth),
codePushClientWrapperRef.overrideWith(() => codePushClientWrapper),
doctorRef.overrideWith(() => doctor),
flutterArtifactsRef.overrideWith(() => flutterArtifacts),
shorebirdArtifactsRef.overrideWith(() => shorebirdArtifacts),
loggerRef.overrideWith(() => logger),
osInterfaceRef.overrideWith(() => operatingSystemInterface),
patchDiffCheckerRef.overrideWith(() => patchDiffChecker),
@@ -255,7 +255,7 @@ flutter:
auth = MockAuth();
codePushClientWrapper = MockCodePushClientWrapper();
doctor = MockDoctor();
flutterArtifacts = MockFlutterArtifacts();
shorebirdArtifacts = MockShorebirdArtifacts();
shorebirdRoot = Directory.systemTemp.createTempSync();
projectRoot = Directory.systemTemp.createTempSync();
flutterDirectory = Directory(
@@ -371,13 +371,13 @@ flutter:
).thenReturn(projectRoot);
when(() => shorebirdEnv.flutterDirectory).thenReturn(flutterDirectory);
when(
() => flutterArtifacts.getArtifactPath(
artifact: FlutterArtifact.genSnapshot,
() => shorebirdArtifacts.getArtifactPath(
artifact: ShorebirdArtifact.genSnapshot,
),
).thenReturn(genSnapshotFile.path);
when(
() => flutterArtifacts.getArtifactPath(
artifact: FlutterArtifact.analyzeSnapshot,
() => shorebirdArtifacts.getArtifactPath(
artifact: ShorebirdArtifact.analyzeSnapshot,
),
).thenReturn(analyzeSnapshotFile.path);
when(() => shorebirdEnv.flutterRevision).thenReturn(flutterRevision);
@@ -14,12 +14,12 @@ import 'package:shorebird_cli/src/commands/patch/patch.dart';
import 'package:shorebird_cli/src/config/config.dart';
import 'package:shorebird_cli/src/deployment_track.dart';
import 'package:shorebird_cli/src/doctor.dart';
import 'package:shorebird_cli/src/flutter_artifacts.dart';
import 'package:shorebird_cli/src/logger.dart';
import 'package:shorebird_cli/src/os/operating_system_interface.dart';
import 'package:shorebird_cli/src/patch_diff_checker.dart';
import 'package:shorebird_cli/src/platform.dart';
import 'package:shorebird_cli/src/process.dart';
import 'package:shorebird_cli/src/shorebird_artifacts.dart';
import 'package:shorebird_cli/src/shorebird_env.dart';
import 'package:shorebird_cli/src/shorebird_flutter.dart';
import 'package:shorebird_cli/src/shorebird_validator.dart';
@@ -84,7 +84,7 @@ flutter:
late Directory projectRoot;
late Directory flutterDirectory;
late File genSnapshotFile;
late FlutterArtifacts flutterArtifacts;
late ShorebirdArtifacts shorebirdArtifacts;
late Doctor doctor;
late IosArchiveDiffer archiveDiffer;
late PatchDiffChecker patchDiffChecker;
@@ -111,7 +111,7 @@ flutter:
authRef.overrideWith(() => auth),
codePushClientWrapperRef.overrideWith(() => codePushClientWrapper),
doctorRef.overrideWith(() => doctor),
flutterArtifactsRef.overrideWith(() => flutterArtifacts),
shorebirdArtifactsRef.overrideWith(() => shorebirdArtifacts),
loggerRef.overrideWith(() => logger),
osInterfaceRef.overrideWith(() => operatingSystemInterface),
patchDiffCheckerRef.overrideWith(() => patchDiffChecker),
@@ -179,7 +179,7 @@ flutter:
artifactManager = MockArtifactManager();
codePushClientWrapper = MockCodePushClientWrapper();
doctor = MockDoctor();
flutterArtifacts = MockFlutterArtifacts();
shorebirdArtifacts = MockShorebirdArtifacts();
patchDiffChecker = MockPatchDiffChecker();
platform = MockPlatform();
shorebirdRoot = Directory.systemTemp.createTempSync();
@@ -255,8 +255,8 @@ flutter:
).thenReturn(projectRoot);
when(() => shorebirdEnv.flutterDirectory).thenReturn(flutterDirectory);
when(
() => flutterArtifacts.getArtifactPath(
artifact: FlutterArtifact.genSnapshot,
() => shorebirdArtifacts.getArtifactPath(
artifact: ShorebirdArtifact.genSnapshot,
),
).thenReturn(genSnapshotFile.path);
when(() => shorebirdEnv.flutterRevision).thenReturn(flutterRevision);
@@ -5,6 +5,8 @@ import 'package:scoped/scoped.dart';
import 'package:shorebird_cli/src/cache.dart';
import 'package:shorebird_cli/src/executables/executables.dart';
import 'package:shorebird_cli/src/process.dart';
import 'package:shorebird_cli/src/shorebird_artifacts.dart';
import 'package:shorebird_cli/src/shorebird_env.dart';
import 'package:test/test.dart';
import '../mocks.dart';
@@ -12,8 +14,11 @@ import '../mocks.dart';
void main() {
group(AotTools, () {
late Cache cache;
late ShorebirdArtifacts shorebirdArtifacts;
late ShorebirdProcess process;
late ShorebirdEnv shorebirdEnv;
late Directory workingDirectory;
late File dartBinaryFile;
late AotTools aotTools;
R runWithOverrides<R>(R Function() body) {
@@ -22,6 +27,8 @@ void main() {
values: {
cacheRef.overrideWith(() => cache),
processRef.overrideWith(() => process),
shorebirdArtifactsRef.overrideWith(() => shorebirdArtifacts),
shorebirdEnvRef.overrideWith(() => shorebirdEnv),
},
);
}
@@ -29,13 +36,14 @@ void main() {
setUp(() {
cache = MockCache();
process = MockShorebirdProcess();
workingDirectory = Directory.systemTemp.createTempSync('aot-tool test');
shorebirdArtifacts = MockShorebirdArtifacts();
shorebirdEnv = MockShorebirdEnv();
dartBinaryFile = File('dart');
workingDirectory = Directory('aot-tools test');
aotTools = AotTools();
when(() => cache.updateAll()).thenAnswer((_) async {});
when(
() => cache.getArtifactDirectory(any()),
).thenReturn(workingDirectory);
when(() => shorebirdEnv.dartBinaryFile).thenReturn(dartBinaryFile);
});
group('link', () {
@@ -44,6 +52,11 @@ void main() {
const analyzeSnapshot = './path/to/analyze_snapshot.aot';
test('throws Exception when process exits with non-zero code', () async {
when(
() => shorebirdArtifacts.getArtifactPath(
artifact: ShorebirdArtifact.aotTools,
),
).thenReturn('aot-tools');
when(
() => process.run(
any(),
@@ -75,43 +88,107 @@ void main() {
);
});
test('completes when linking exits with code: 0', () async {
when(
() => process.run(
any(),
any(),
workingDirectory: any(named: 'workingDirectory'),
),
).thenAnswer(
(_) async => const ShorebirdProcessResult(
exitCode: 0,
stdout: '',
stderr: '',
),
);
await expectLater(
runWithOverrides(
() => aotTools.link(
base: base,
patch: patch,
analyzeSnapshot: analyzeSnapshot,
workingDirectory: workingDirectory.path,
group('when using cached aot tools', () {
const aotToolsPath = 'aot-tools';
setUp(() {
when(
() => shorebirdArtifacts.getArtifactPath(
artifact: ShorebirdArtifact.aotTools,
),
),
completes,
);
verify(
() => process.run(
any(that: endsWith(AotTools.executableName)),
[
'link',
'--base=$base',
'--patch=$patch',
'--analyze-snapshot=$analyzeSnapshot',
],
workingDirectory: any(named: 'workingDirectory'),
),
).called(1);
).thenReturn(aotToolsPath);
});
test('completes when linking exits with code 0', () async {
when(
() => process.run(
any(),
any(),
workingDirectory: any(named: 'workingDirectory'),
),
).thenAnswer(
(_) async => const ShorebirdProcessResult(
exitCode: 0,
stdout: '',
stderr: '',
),
);
await expectLater(
runWithOverrides(
() => aotTools.link(
base: base,
patch: patch,
analyzeSnapshot: analyzeSnapshot,
workingDirectory: workingDirectory.path,
),
),
completes,
);
verify(
() => process.run(
any(that: endsWith('aot-tools')),
[
'link',
'--base=$base',
'--patch=$patch',
'--analyze-snapshot=$analyzeSnapshot',
],
workingDirectory: any(named: 'workingDirectory'),
),
).called(1);
});
});
group('when using local aot_tools', () {
const aotToolsPath = 'aot_tools.dart';
setUp(() {
when(
() => shorebirdArtifacts.getArtifactPath(
artifact: ShorebirdArtifact.aotTools,
),
).thenReturn(aotToolsPath);
});
test('completes when linking exits with code 0', () async {
when(
() => process.run(
any(),
any(),
workingDirectory: any(named: 'workingDirectory'),
),
).thenAnswer(
(_) async => const ShorebirdProcessResult(
exitCode: 0,
stdout: '',
stderr: '',
),
);
await expectLater(
runWithOverrides(
() => aotTools.link(
base: base,
patch: patch,
analyzeSnapshot: analyzeSnapshot,
workingDirectory: workingDirectory.path,
),
),
completes,
);
verify(
() => process.run(
dartBinaryFile.path,
[
aotToolsPath,
'link',
'--base=$base',
'--patch=$patch',
'--analyze-snapshot=$analyzeSnapshot',
],
workingDirectory: any(named: 'workingDirectory'),
),
).called(1);
});
});
});
});
+3 -3
View File
@@ -18,10 +18,10 @@ import 'package:shorebird_cli/src/config/config.dart';
import 'package:shorebird_cli/src/doctor.dart';
import 'package:shorebird_cli/src/executables/devicectl/apple_device.dart';
import 'package:shorebird_cli/src/executables/executables.dart';
import 'package:shorebird_cli/src/flutter_artifacts.dart';
import 'package:shorebird_cli/src/os/os.dart';
import 'package:shorebird_cli/src/patch_diff_checker.dart';
import 'package:shorebird_cli/src/process.dart';
import 'package:shorebird_cli/src/shorebird_artifacts.dart';
import 'package:shorebird_cli/src/shorebird_env.dart';
import 'package:shorebird_cli/src/shorebird_flutter.dart';
import 'package:shorebird_cli/src/shorebird_validator.dart';
@@ -73,8 +73,6 @@ class MockFile extends Mock implements File {}
class MockFileSetDiff extends Mock implements FileSetDiff {}
class MockFlutterArtifacts extends Mock implements FlutterArtifacts {}
class MockGit extends Mock implements Git {}
class MockGradlew extends Mock implements Gradlew {}
@@ -114,6 +112,8 @@ class MockRelease extends Mock implements Release {}
class MockReleaseArtifact extends Mock implements ReleaseArtifact {}
class MockShorebirdArtifacts extends Mock implements ShorebirdArtifacts {}
class MockShorebirdEnv extends Mock implements ShorebirdEnv {}
class MockShorebirdFlutter extends Mock implements ShorebirdFlutter {}
@@ -3,42 +3,62 @@ import 'dart:io';
import 'package:mocktail/mocktail.dart';
import 'package:path/path.dart' as p;
import 'package:scoped/scoped.dart';
import 'package:shorebird_cli/src/flutter_artifacts.dart';
import 'package:shorebird_cli/src/cache.dart';
import 'package:shorebird_cli/src/process.dart';
import 'package:shorebird_cli/src/shorebird_artifacts.dart';
import 'package:shorebird_cli/src/shorebird_env.dart';
import 'package:test/test.dart';
import 'mocks.dart';
void main() {
group(FlutterCachedArtifacts, () {
group(ShorebirdCachedArtifacts, () {
late Cache cache;
late Directory flutterDirectory;
late Directory artifactDirectory;
late ShorebirdEnv shorebirdEnv;
late FlutterCachedArtifacts artifacts;
late ShorebirdCachedArtifacts artifacts;
R runWithOverrides<R>(R Function() body) {
return runScoped(
() => body(),
values: {
cacheRef.overrideWith(() => cache),
shorebirdEnvRef.overrideWith(() => shorebirdEnv),
},
);
}
setUp(() {
cache = MockCache();
flutterDirectory = Directory('flutter');
artifactDirectory = Directory('artifacts');
shorebirdEnv = MockShorebirdEnv();
artifacts = const FlutterCachedArtifacts();
artifacts = const ShorebirdCachedArtifacts();
when(
() => cache.getArtifactDirectory(any()),
).thenReturn(artifactDirectory);
when(() => shorebirdEnv.flutterDirectory).thenReturn(flutterDirectory);
});
group('getArtifactPath', () {
test('returns correct path for aot tools', () {
expect(
runWithOverrides(
() => artifacts.getArtifactPath(
artifact: ShorebirdArtifact.aotTools,
),
),
equals(p.join(artifactDirectory.path, 'aot-tools')),
);
});
test('returns correct path for gen_snapshot', () {
expect(
runWithOverrides(
() => artifacts.getArtifactPath(
artifact: FlutterArtifact.genSnapshot,
artifact: ShorebirdArtifact.genSnapshot,
),
),
equals(
@@ -59,7 +79,7 @@ void main() {
expect(
runWithOverrides(
() => artifacts.getArtifactPath(
artifact: FlutterArtifact.analyzeSnapshot,
artifact: ShorebirdArtifact.analyzeSnapshot,
),
),
equals(
@@ -70,7 +90,8 @@ void main() {
'artifacts',
'engine',
'ios-release',
'analyze_snapshot_arm64',
'darwin-x64',
'analyze_snapshot',
),
),
);
@@ -78,10 +99,10 @@ void main() {
});
});
group(FlutterLocalEngineArtifacts, () {
group(ShorebirdLocalEngineArtifacts, () {
late String localEngineSrcPath;
late EngineConfig engineConfig;
late FlutterLocalEngineArtifacts artifacts;
late ShorebirdLocalEngineArtifacts artifacts;
R runWithOverrides<R>(R Function() body) {
return runScoped(
@@ -95,7 +116,7 @@ void main() {
setUp(() {
localEngineSrcPath = 'local_engine_src_path';
engineConfig = MockEngineConfig();
artifacts = const FlutterLocalEngineArtifacts();
artifacts = const ShorebirdLocalEngineArtifacts();
when(
() => engineConfig.localEngineSrcPath,
@@ -103,11 +124,32 @@ void main() {
});
group('getArtifactPath', () {
test('returns correct path for aot tools', () {
expect(
runWithOverrides(
() => artifacts.getArtifactPath(
artifact: ShorebirdArtifact.aotTools,
),
),
equals(
p.join(
localEngineSrcPath,
'third_party',
'dart',
'pkg',
'aot_tools',
'bin',
'aot_tools.dart',
),
),
);
});
test('returns correct path for gen_snapshot', () {
expect(
runWithOverrides(
() => artifacts.getArtifactPath(
artifact: FlutterArtifact.genSnapshot,
artifact: ShorebirdArtifact.genSnapshot,
),
),
equals(
@@ -126,7 +168,7 @@ void main() {
expect(
runWithOverrides(
() => artifacts.getArtifactPath(
artifact: FlutterArtifact.analyzeSnapshot,
artifact: ShorebirdArtifact.analyzeSnapshot,
),
),
equals(
@@ -142,6 +142,25 @@ void main() {
});
});
group('dartBinaryFile', () {
test('returns correct path', () {
expect(
runWithOverrides(() => shorebirdEnv.dartBinaryFile.path),
equals(
p.join(
shorebirdRoot.path,
'bin',
'cache',
'flutter',
flutterRevision,
'bin',
'dart',
),
),
);
});
});
group('flutterBinaryFile', () {
test('returns correct path', () {
expect(