Victoria Ashworth ae455b9fca
Revert "Separate copying dsym into its own target (#178261)" (#178545)
This reverts commit b1d5f03351590a0954d19c7584186f0722323169.

Turns out this isn't needed for
https://github.com/flutter/flutter/issues/166489 after all. It appeared
that SwiftPM wasn't copying the dSYM, but I now think I had my build
modes mixed up (since dSYMs are only relevant to release mode).

## Pre-launch Checklist

- [x] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [x] I read the [Tree Hygiene] wiki page, which explains my
responsibilities.
- [x] I read and followed the [Flutter Style Guide], including [Features
we expect every widget to implement].
- [x] I signed the [CLA].
- [ ] I listed at least one issue that this PR fixes in the description
above.
- [x] I updated/added relevant documentation (doc comments with `///`).
- [x] I added new tests to check the change I am making, or this PR is
[test-exempt].
- [x] I followed the [breaking change policy] and added [Data Driven
Fixes] where supported.
- [x] All existing and new tests are passing.

If you need help, consider asking for advice on the #hackers-new channel
on [Discord].

**Note**: The Flutter team is currently trialing the use of [Gemini Code
Assist for
GitHub](https://developers.google.com/gemini-code-assist/docs/review-github-code).
Comments from the `gemini-code-assist` bot should not be taken as
authoritative feedback from the Flutter team. If you find its comments
useful you can update your code accordingly, but if you are unsure or
disagree with the feedback, please feel free to wait for a Flutter team
member's review for guidance on which automated comments should be
addressed.

<!-- Links -->
[Contributor Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview
[Tree Hygiene]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md
[test-exempt]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests
[Flutter Style Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md
[Features we expect every widget to implement]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement
[CLA]: https://cla.developers.google.com/
[flutter/tests]: https://github.com/flutter/tests
[breaking change policy]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes
[Discord]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md
[Data Driven Fixes]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
2025-11-17 15:48:50 +00:00

206 lines
6.8 KiB
Dart

// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:file/file.dart';
import 'package:file/local.dart';
import 'package:flutter_tools/src/base/io.dart';
import 'package:flutter_tools/src/base/platform.dart';
import 'package:process/process.dart';
import 'package:vm_service/vm_service.dart';
import '../src/common.dart';
import 'test_driver.dart';
/// The [FileSystem] for the integration test environment.
const FileSystem fileSystem = LocalFileSystem();
/// The (real) `flutter` binary (i.e. `{ROOT}/bin/flutter`) to execute in tests.
final String flutterBin = fileSystem.path.join(
getFlutterRoot(),
'bin',
platform.isWindows ? 'flutter.bat' : 'flutter',
);
/// The [Platform] for the integration test environment.
const Platform platform = LocalPlatform();
/// The [ProcessManager] for the integration test environment.
const ProcessManager processManager = LocalProcessManager();
/// Creates a temporary directory but resolves any symlinks to return the real
/// underlying path to avoid issues with breakpoints/hot reload.
/// https://github.com/flutter/flutter/pull/21741
Directory createResolvedTempDirectorySync(String prefix) {
assert(prefix.endsWith('.'));
final Directory tempDirectory = fileSystem.systemTempDirectory.createTempSync('flutter_$prefix');
return fileSystem.directory(tempDirectory.resolveSymbolicLinksSync());
}
void writeFile(String path, String content, {bool writeFutureModifiedDate = false}) {
final File file = fileSystem.file(path)
..createSync(recursive: true)
..writeAsStringSync(content, flush: true);
// Some integration tests on Windows to not see this file as being modified
// recently enough for the hot reload to pick this change up unless the
// modified time is written in the future.
if (writeFutureModifiedDate) {
file.setLastModifiedSync(DateTime.now().add(const Duration(seconds: 5)));
}
}
void writeBytesFile(String path, List<int> content) {
fileSystem.file(path)
..createSync(recursive: true)
..writeAsBytesSync(content, flush: true);
}
Future<void> getPackages(String folder) async {
final command = <String>[fileSystem.path.join(getFlutterRoot(), 'bin', 'flutter'), 'pub', 'get'];
final ProcessResult result = await processManager.run(command, workingDirectory: folder);
if (result.exitCode != 0) {
throw Exception('flutter pub get failed: ${result.stderr}\n${result.stdout}');
}
}
const kLocalEngineEnvironment = 'FLUTTER_LOCAL_ENGINE';
const kLocalEngineHostEnvironment = 'FLUTTER_LOCAL_ENGINE_HOST';
const kLocalEngineLocation = 'FLUTTER_LOCAL_ENGINE_SRC_PATH';
List<String> getLocalEngineArguments() {
return <String>[
if (platform.environment.containsKey(kLocalEngineEnvironment))
'--local-engine=${platform.environment[kLocalEngineEnvironment]}',
if (platform.environment.containsKey(kLocalEngineLocation))
'--local-engine-src-path=${platform.environment[kLocalEngineLocation]}',
if (platform.environment.containsKey(kLocalEngineHostEnvironment))
'--local-engine-host=${platform.environment[kLocalEngineHostEnvironment]}',
];
}
Future<void> pollForServiceExtensionValue<T>({
required FlutterTestDriver testDriver,
required String extension,
required T continuePollingValue,
required Matcher matches,
String valueKey = 'value',
}) async {
for (var i = 0; i < 10; i++) {
final Response response = await testDriver.callServiceExtension(extension);
if (response.json?[valueKey] as T == continuePollingValue) {
await Future<void>.delayed(const Duration(seconds: 1));
} else {
expect(response.json?[valueKey] as T, matches);
return;
}
}
fail(
"Did not find expected value for service extension '$extension'. All call"
" attempts responded with '$continuePollingValue'.",
);
}
abstract final class AppleTestUtils {
static const requiredSymbols = <String>[
'_kDartIsolateSnapshotData',
'_kDartIsolateSnapshotInstructions',
'_kDartVmSnapshotData',
'_kDartVmSnapshotInstructions',
];
static List<String> getExportedSymbols(String dwarfPath) {
final ProcessResult nm = processManager.runSync(<String>[
'nm',
'--debug-syms', // nm docs: 'Show all symbols, even debugger only'
'--defined-only',
'--just-symbol-name',
dwarfPath,
'-arch',
'arm64',
]);
final String nmOutput = (nm.stdout as String).trim();
return nmOutput.isEmpty ? const <String>[] : nmOutput.split('\n');
}
}
/// Matcher to be used for [ProcessResult] returned
/// from a process run
///
/// The default for [exitCode] will be 0 while
/// [stdoutPattern] and [stderrPattern] are both optional
class ProcessResultMatcher extends Matcher {
const ProcessResultMatcher({this.exitCode = 0, this.stdoutPattern, this.stderrPattern});
/// The expected exit code to get returned from a process run
final int exitCode;
/// Substring to find in the process's stdout
final Pattern? stdoutPattern;
/// Substring to find in the process's stderr
final Pattern? stderrPattern;
@override
Description describe(Description description) {
description.add('a process with exit code $exitCode');
if (stdoutPattern != null) {
description.add(' and stdout: "$stdoutPattern"');
}
if (stderrPattern != null) {
description.add(' and stderr: "$stderrPattern"');
}
return description;
}
@override
bool matches(dynamic item, Map<dynamic, dynamic> matchState) {
final result = item as ProcessResult;
var foundStdout = true;
var foundStderr = true;
final stdout = result.stdout as String;
final stderr = result.stderr as String;
if (stdoutPattern != null) {
foundStdout = stdout.contains(stdoutPattern!);
matchState['stdout'] = stdout;
} else if (stdout.isNotEmpty) {
// even if we were not asserting on stdout, show stdout for debug purposes
matchState['stdout'] = stdout;
}
if (stderrPattern != null) {
foundStderr = stderr.contains(stderrPattern!);
matchState['stderr'] = stderr;
} else if (stderr.isNotEmpty) {
matchState['stderr'] = stderr;
}
return result.exitCode == exitCode && foundStdout && foundStderr;
}
@override
Description describeMismatch(
Object? item,
Description mismatchDescription,
Map<dynamic, dynamic> matchState,
bool verbose,
) {
final result = item! as ProcessResult;
if (result.exitCode != exitCode) {
mismatchDescription.add('Actual exitCode was ${result.exitCode}\n');
}
if (matchState.containsKey('stdout')) {
mismatchDescription.add('Actual stdout:\n${matchState["stdout"]}\n');
}
if (matchState.containsKey('stderr')) {
mismatchDescription.add('Actual stderr:\n${matchState["stderr"]}\n');
}
return mismatchDescription;
}
}