[pigeon] Convert run_tests.sh to Dart (#3075)

* Remove test_pigeon_android, which is unused

* Update Dart unit test output names for consistency

* Simplify unit test generation

* Fold dart analysis tests into the dart unit test system, which already does analysis

* Move Java unit tests to Dart

* Remove more dead code, consolidate slightly

* Move legacy iOS unit tests to Dart

* Move command-line tests from bash to Dart

* Move default test set to Dart; eliminate sh

* Update docs reference to script

* Fix legacy iOS test

* Disable iOS integration tests
This commit is contained in:
stuartmorgan
2023-01-20 14:38:24 -08:00
committed by GitHub
parent 2b7c60ad58
commit 8fcd997345
11 changed files with 210 additions and 711 deletions

View File

@ -191,14 +191,12 @@ task:
CHANNEL: "stable"
<< : *INSTALL_CHROME_LINUX
local_tests_script:
# pigeon tests currently don't support Linux:
# https://github.com/flutter/flutter/issues/100386
# flutter_image
# https://github.com/flutter/flutter/issues/100387
- if [[ "$CHANNEL" == "master" ]]; then
- ./script/tool_runner.sh custom-test --exclude=pigeon
- ./script/tool_runner.sh custom-test
- else
- ./script/tool_runner.sh custom-test --exclude=pigeon,flutter_image
- ./script/tool_runner.sh custom-test --exclude=flutter_image
- fi
### Web tasks ###
- name: web-build_all_packages

View File

@ -34,7 +34,8 @@ generators with that AST.
## Testing Overview
Pigeon has 3 types of tests, you'll find them all in [run_tests.sh](./run_tests.sh).
Pigeon has 3 types of tests, you'll find them all in
[run_tests.dart](./tool/run_tests.dart).
* Unit tests - These are the fastest tests that are just typical unit tests,
they may be generating code and checking it against a regular expression to

View File

@ -0,0 +1,9 @@
# TODO(stuartmorgan) Remove this file when these are no longer generated;
# see the TODO in _runFlutterUnitTests in run_tests.dart
async_handlers.gen.dart
host2flutter.gen.dart
list.gen.dart
void_arg_flutter.gen.dart
void_arg_host.gen.dart
voidflutter.gen.dart
voidhost.gen.dart

View File

@ -1,252 +0,0 @@
// Copyright 2013 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.
//
// Autogenerated from Pigeon (v4.2.9), do not edit directly.
// See also: https://pub.dev/packages/pigeon
// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name, unnecessary_import
import 'dart:async';
import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List;
import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer;
import 'package:flutter/services.dart';
class Everything {
Everything({
this.aBool,
this.anInt,
this.aDouble,
this.aString,
this.aByteArray,
this.a4ByteArray,
this.a8ByteArray,
this.aFloatArray,
this.aList,
this.aMap,
this.nestedList,
this.mapWithAnnotations,
this.mapWithObject,
});
bool? aBool;
int? anInt;
double? aDouble;
String? aString;
Uint8List? aByteArray;
Int32List? a4ByteArray;
Int64List? a8ByteArray;
Float64List? aFloatArray;
List<Object?>? aList;
Map<Object?, Object?>? aMap;
List<List<bool?>?>? nestedList;
Map<String?, String?>? mapWithAnnotations;
Map<String?, Object?>? mapWithObject;
Object encode() {
final List<Object?> pigeonList = <Object?>[];
pigeonList.add(aBool);
pigeonList.add(anInt);
pigeonList.add(aDouble);
pigeonList.add(aString);
pigeonList.add(aByteArray);
pigeonList.add(a4ByteArray);
pigeonList.add(a8ByteArray);
pigeonList.add(aFloatArray);
pigeonList.add(aList);
pigeonList.add(aMap);
pigeonList.add(nestedList);
pigeonList.add(mapWithAnnotations);
pigeonList.add(mapWithObject);
return pigeonList;
}
static Everything decode(Object result) {
result as List<Object?>;
return Everything(
aBool: result[0] as bool?,
anInt: result[1] as int?,
aDouble: result[2] as double?,
aString: result[3] as String?,
aByteArray: result[4] as Uint8List?,
a4ByteArray: result[5] as Int32List?,
a8ByteArray: result[6] as Int64List?,
aFloatArray: result[7] as Float64List?,
aList: result[8] as List<Object?>?,
aMap: result[9] as Map<Object?, Object?>?,
nestedList: (result[10] as List<Object?>?)?.cast<List<bool?>?>(),
mapWithAnnotations:
(result[11] as Map<Object?, Object?>?)?.cast<String?, String?>(),
mapWithObject:
(result[12] as Map<Object?, Object?>?)?.cast<String?, Object?>(),
);
}
}
class _HostEverythingCodec extends StandardMessageCodec {
const _HostEverythingCodec();
@override
void writeValue(WriteBuffer buffer, Object? value) {
if (value is Everything) {
buffer.putUint8(128);
writeValue(buffer, value.encode());
} else {
super.writeValue(buffer, value);
}
}
@override
Object? readValueOfType(int type, ReadBuffer buffer) {
switch (type) {
case 128:
return Everything.decode(readValue(buffer)! as List<Object?>);
default:
return super.readValueOfType(type, buffer);
}
}
}
class HostEverything {
/// Constructor for [HostEverything]. The [binaryMessenger] named argument is
/// available for dependency injection. If it is left null, the default
/// BinaryMessenger will be used which routes to the host platform.
HostEverything({BinaryMessenger? binaryMessenger})
: _binaryMessenger = binaryMessenger;
final BinaryMessenger? _binaryMessenger;
static const MessageCodec<Object?> codec = _HostEverythingCodec();
Future<Everything> giveMeEverything() async {
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.HostEverything.giveMeEverything', codec,
binaryMessenger: _binaryMessenger);
final List<Object?>? replyList = await channel.send(null) as List<Object?>?;
if (replyList == null) {
throw PlatformException(
code: 'channel-error',
message: 'Unable to establish connection on channel.',
);
} else if (replyList.length > 1) {
throw PlatformException(
code: (replyList[0] as String?)!,
message: replyList[1] as String?,
details: replyList[2],
);
} else if (replyList[0] == null) {
throw PlatformException(
code: 'null-error',
message: 'Host platform returned null value for non-null return value.',
);
} else {
return (replyList[0] as Everything?)!;
}
}
Future<Everything> echo(Everything arg_everything) async {
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.HostEverything.echo', codec,
binaryMessenger: _binaryMessenger);
final List<Object?>? replyList =
await channel.send(<Object?>[arg_everything]) as List<Object?>?;
if (replyList == null) {
throw PlatformException(
code: 'channel-error',
message: 'Unable to establish connection on channel.',
);
} else if (replyList.length > 1) {
throw PlatformException(
code: (replyList[0] as String?)!,
message: replyList[1] as String?,
details: replyList[2],
);
} else if (replyList[0] == null) {
throw PlatformException(
code: 'null-error',
message: 'Host platform returned null value for non-null return value.',
);
} else {
return (replyList[0] as Everything?)!;
}
}
}
class _FlutterEverythingCodec extends StandardMessageCodec {
const _FlutterEverythingCodec();
@override
void writeValue(WriteBuffer buffer, Object? value) {
if (value is Everything) {
buffer.putUint8(128);
writeValue(buffer, value.encode());
} else {
super.writeValue(buffer, value);
}
}
@override
Object? readValueOfType(int type, ReadBuffer buffer) {
switch (type) {
case 128:
return Everything.decode(readValue(buffer)! as List<Object?>);
default:
return super.readValueOfType(type, buffer);
}
}
}
abstract class FlutterEverything {
static const MessageCodec<Object?> codec = _FlutterEverythingCodec();
Everything giveMeEverything();
Everything echo(Everything everything);
static void setup(FlutterEverything? api,
{BinaryMessenger? binaryMessenger}) {
{
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.FlutterEverything.giveMeEverything', codec,
binaryMessenger: binaryMessenger);
if (api == null) {
channel.setMessageHandler(null);
} else {
channel.setMessageHandler((Object? message) async {
// ignore message
final Everything output = api.giveMeEverything();
return output;
});
}
}
{
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.FlutterEverything.echo', codec,
binaryMessenger: binaryMessenger);
if (api == null) {
channel.setMessageHandler(null);
} else {
channel.setMessageHandler((Object? message) async {
assert(message != null,
'Argument for dev.flutter.pigeon.FlutterEverything.echo was null.');
final List<Object?> args = (message as List<Object?>?)!;
final Everything? arg_everything = (args[0] as Everything?);
assert(arg_everything != null,
'Argument for dev.flutter.pigeon.FlutterEverything.echo was null, expected non-null Everything.');
final Everything output = api.echo(arg_everything!);
return output;
});
}
}
}
}

View File

@ -6,7 +6,7 @@ import 'dart:async';
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter_unit_tests/null_safe_pigeon.dart';
import 'package:flutter_unit_tests/flutter_unittests.gen.dart';
import 'package:flutter_unit_tests/nullable_returns.gen.dart';
import 'package:mockito/annotations.dart';
import 'package:mockito/mockito.dart';

View File

@ -4,7 +4,7 @@
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter_unit_tests/primitive.dart';
import 'package:flutter_unit_tests/primitive.gen.dart';
import 'package:mockito/annotations.dart';
import 'package:mockito/mockito.dart';

View File

@ -7,7 +7,7 @@ import 'dart:typed_data' as _i2;
import 'dart:ui' as _i5;
import 'package:flutter/src/services/binary_messenger.dart' as _i3;
import 'package:flutter_unit_tests/primitive.dart' as _i6;
import 'package:flutter_unit_tests/primitive.gen.dart' as _i6;
import 'package:mockito/mockito.dart' as _i1;
// ignore_for_file: comment_references

View File

@ -1,405 +0,0 @@
#!/bin/bash
# Copyright 2013 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.
###############################################################################
# run_tests.sh
#
# This runs all the different types of tests for pigeon. It should be run from
# the directory that contains the script.
###############################################################################
# exit when any command fails
set -e
###############################################################################
# Variables
###############################################################################
flutter=$(which flutter)
flutter_bin=$(dirname $flutter)
framework_path="$flutter_bin/cache/artifacts/engine/ios/"
java_linter=checkstyle-8.41-all.jar
java_formatter=google-java-format-1.3-all-deps.jar
google_checks=google_checks.xml
google_checks_version=7190c47ca5515ad8cb827bc4065ae7664d2766c1
java_error_prone=error_prone_core-2.5.1-with-dependencies.jar
dataflow_shaded=dataflow-shaded-3.7.1.jar
jformat_string=jFormatString-3.0.0.jar
java_version=$(java -version 2>&1 | head -1 | cut -d'"' -f2 | sed '/^1\./s///' | cut -d'.' -f1)
javac_jar=javac-9+181-r4173-1.jar
if [ $java_version == "8" ]; then
javac_bootclasspath="-J-Xbootclasspath/p:ci/$javac_jar"
else
javac_bootclasspath=
fi
run_pigeon="dart bin/pigeon.dart.dill --copyright_header ./copyright_header.txt"
###############################################################################
# Helper Functions
###############################################################################
# Create a temporary directory in a way that works on both Linux and macOS.
#
# The mktemp commands have slighly semantics on the BSD systems vs GNU systems.
mktmpdir() {
mktemp -d flutter_pigeon.XXXXXX 2>/dev/null || mktemp -d -t flutter_pigeon.
}
# test_pigeon_android(<path to pigeon file>)
#
# Compiles the pigeon file to a temp directory and attempts to compile the java
# code.
# TODO(stuartmorgan): Remove this in favor of unit testing all files, which
# already includes compilation.
test_pigeon_android() {
echo "test_pigeon_android($1)"
temp_dir=$(mktmpdir)
$run_pigeon \
--input $1 \
--dart_out $temp_dir/pigeon.dart \
--java_out $temp_dir/Pigeon.java \
--java_package foo
java -jar ci/$java_formatter --replace "$temp_dir/Pigeon.java"
java -jar ci/$java_linter -c "ci/$google_checks" "$temp_dir/Pigeon.java"
if ! javac \
$javac_bootclasspath \
-XDcompilePolicy=simple \
-processorpath "ci/$java_error_prone:ci/$dataflow_shaded:ci/$jformat_string" \
'-Xplugin:ErrorProne -Xep:CatchingUnchecked:ERROR' \
-classpath "$flutter_bin/cache/artifacts/engine/android-x64/flutter.jar" \
$temp_dir/Pigeon.java; then
echo "javac $temp_dir/Pigeon.java failed"
exit 1
fi
rm -rf $temp_dir
}
# test_null_safe_dart(<path to pigeon file>)
#
# Compiles the pigeon file to a temp directory and attempts to run the dart
# analyzer on it.
# TODO(stuartmorgan): Remove this in favor of analyzing test_plugin.
test_pigeon_dart() {
echo "test_pigeon_dart($1, $2)"
local flutter_project_dir=$2
$run_pigeon \
--input $1 \
--dart_out $flutter_project_dir/lib/pigeon.dart
dart analyze $flutter_project_dir/lib/pigeon.dart --fatal-infos --fatal-warnings
rm $flutter_project_dir/lib/pigeon.dart
}
print_usage() {
echo "usage: ./run_tests.sh [-l] [-t test_name]
flags:
-t test_name: Run only specified test.
-l : List available tests.
"
}
###############################################################################
# Stages
###############################################################################
get_java_linter_formatter() {
if [ ! -f "ci/$java_linter" ]; then
curl -L https://github.com/checkstyle/checkstyle/releases/download/checkstyle-8.41/$java_linter >"ci/$java_linter"
fi
if [ ! -f "ci/$java_formatter" ]; then
curl -L https://github.com/google/google-java-format/releases/download/google-java-format-1.3/$java_formatter >"ci/$java_formatter"
fi
if [ ! -f "ci/$google_checks" ]; then
curl -L https://raw.githubusercontent.com/checkstyle/checkstyle/$google_checks_version/src/main/resources/$google_checks >"ci/$google_checks"
fi
if [ ! -f "ci/$java_error_prone" ]; then
curl https://repo1.maven.org/maven2/com/google/errorprone/error_prone_core/2.5.1/$java_error_prone >"ci/$java_error_prone"
fi
if [ ! -f "ci/$dataflow_shaded" ]; then
curl https://repo1.maven.org/maven2/org/checkerframework/dataflow-shaded/3.7.1/$dataflow_shaded >"ci/$dataflow_shaded"
fi
if [ ! -f "ci/$jformat_string" ]; then
curl https://repo1.maven.org/maven2/com/google/code/findbugs/jFormatString/3.0.0/$jformat_string >"ci/$jformat_string"
fi
if [ ! -f "ci/$javac_jar" ]; then
curl https://repo1.maven.org/maven2/com/google/errorprone/javac/9+181-r4173-1/$javac_jar >"ci/$javac_jar"
fi
}
run_dart_unittests() {
dart run tool/run_tests.dart -t dart_unittests --skip-generation
}
test_command_line() {
# Test with no arguments.
$run_pigeon 1>/dev/null
# Test one_language flag. With this flag specified, java_out can be generated
# without dart_out.
$run_pigeon \
--input pigeons/message.dart \
--one_language \
--java_out stdout \
| grep "public class Message">/dev/null
# Test dartOut in ConfigurePigeon overrides output.
$run_pigeon --input pigeons/configure_pigeon_dart_out.dart 1>/dev/null
# Make sure AST generation exits correctly.
$run_pigeon --input pigeons/message.dart --one_language --ast_out /dev/null
}
run_flutter_unittests() {
dart run tool/run_tests.dart -t flutter_unittests --skip-generation
}
run_mock_handler_tests() {
dart run tool/run_tests.dart -t mock_handler_tests --skip-generation
}
run_ios_swift_unittests() {
dart run tool/run_tests.dart -t ios_swift_unittests --skip-generation
}
run_ios_swift_e2e_tests() {
dart run tool/run_tests.dart -t ios_swift_integration_tests --skip-generation
}
run_macos_swift_unittests() {
dart run tool/run_tests.dart -t macos_swift_unittests --skip-generation
}
run_macos_swift_e2e_tests() {
dart run tool/run_tests.dart -t macos_swift_integration_tests --skip-generation
}
run_android_kotlin_unittests() {
dart run tool/run_tests.dart -t android_kotlin_unittests --skip-generation
}
run_android_kotlin_e2e_tests() {
dart run tool/run_tests.dart -t android_kotlin_integration_tests --skip-generation
}
run_dart_compilation_tests() {
local temp_dir=$(mktmpdir)
local flutter_project_dir=$temp_dir/project
flutter create --platforms="android" $flutter_project_dir 1> /dev/null
test_pigeon_dart ./pigeons/async_handlers.dart $flutter_project_dir
test_pigeon_dart ./pigeons/core_tests.dart $flutter_project_dir
test_pigeon_dart ./pigeons/host2flutter.dart $flutter_project_dir
test_pigeon_dart ./pigeons/list.dart $flutter_project_dir
test_pigeon_dart ./pigeons/message.dart $flutter_project_dir
test_pigeon_dart ./pigeons/void_arg_flutter.dart $flutter_project_dir
test_pigeon_dart ./pigeons/void_arg_host.dart $flutter_project_dir
test_pigeon_dart ./pigeons/voidflutter.dart $flutter_project_dir
test_pigeon_dart ./pigeons/voidhost.dart $flutter_project_dir
rm -rf $temp_dir
}
run_ios_objc_unittests() {
dart run tool/run_tests.dart -t ios_objc_unittests --skip-generation
}
# TODO(stuartmorgan): Remove once run_ios_objc_unittests works in CI; see
# related TODOs below.
run_ios_legacy_unittests() {
pushd $PWD
cd platform_tests/ios_unit_tests
flutter build ios --simulator
cd ios
xcodebuild \
-workspace Runner.xcworkspace \
-scheme RunnerTests \
-sdk iphonesimulator \
-destination 'platform=iOS Simulator,name=iPhone 8' \
test
popd
}
run_ios_objc_e2e_tests() {
dart run tool/run_tests.dart -t ios_objc_integration_tests --skip-generation
}
run_android_unittests() {
pushd $PWD
cd platform_tests/alternate_language_test_plugin/example
if [ ! -f "android/gradlew" ]; then
flutter build apk --debug
fi
cd android
./gradlew test
popd
}
run_android_java_e2e_tests() {
dart run tool/run_tests.dart -t android_java_integration_tests --skip-generation
}
###############################################################################
# main
###############################################################################
should_run_android_unittests=true
should_run_dart_compilation_tests=true
should_run_dart_unittests=true
should_run_flutter_unittests=true
# TODO(stuartmorgan): Enable by default once CI issues are solved; see
# https://github.com/flutter/packages/pull/2816.
should_run_ios_objc_e2e_tests=false
# TODO(stuartmorgan): Enable the new version by default and remove the legacy
# version once CI issues are solved; see
# https://github.com/flutter/packages/pull/2816.
should_run_ios_objc_unittests=false
should_run_ios_legacy_unittests=true
should_run_ios_swift_unittests=true
# Currently these are testing exactly the same thing as macos_swift_e2e_tests,
# so we don't need to run both by default. This should become `true` if any
# iOS-only tests are added (e.g., for a feature not supported by macOS).
should_run_ios_swift_e2e_tests=false
should_run_mock_handler_tests=true
should_run_macos_swift_unittests=true
should_run_macos_swift_e2e_tests=true
should_run_android_kotlin_unittests=true
# Default to false until there is CI support. See
# https://github.com/flutter/flutter/issues/111505
should_run_android_java_e2e_tests=false
should_run_android_kotlin_e2e_tests=false
while getopts "t:l?h" opt; do
case $opt in
t)
should_run_android_unittests=false
should_run_dart_compilation_tests=false
should_run_dart_unittests=false
should_run_flutter_unittests=false
should_run_ios_objc_unittests=false
should_run_ios_objc_e2e_tests=false
should_run_ios_legacy_unittests=false
should_run_ios_swift_unittests=false
should_run_ios_swift_e2e_tests=false
should_run_mock_handler_tests=false
should_run_macos_swift_unittests=false
should_run_macos_swift_e2e_tests=false
should_run_android_kotlin_unittests=false
should_run_android_java_e2e_tests=false
should_run_android_kotlin_e2e_tests=false
case $OPTARG in
# TODO(stuartmorgan): Rename to include "java".
android_unittests) should_run_android_unittests=true ;;
android_java_e2e_tests) should_run_android_java_e2e_tests=true ;;
dart_compilation_tests) should_run_dart_compilation_tests=true ;;
dart_unittests) should_run_dart_unittests=true ;;
flutter_unittests) should_run_flutter_unittests=true ;;
ios_objc_e2e_tests) should_run_ios_objc_e2e_tests=true ;;
ios_objc_unittests) should_run_ios_objc_unittests=true ;;
ios_unittests) should_run_ios_legacy_unittests=true ;;
ios_swift_unittests) should_run_ios_swift_unittests=true ;;
ios_swift_e2e_tests) should_run_ios_swift_e2e_tests=true ;;
mock_handler_tests) should_run_mock_handler_tests=true ;;
macos_swift_unittests) should_run_macos_swift_unittests=true ;;
macos_swift_e2e_tests) should_run_macos_swift_e2e_tests=true ;;
android_kotlin_unittests) should_run_android_kotlin_unittests=true ;;
android_kotlin_e2e_tests) should_run_android_kotlin_e2e_tests=true ;;
*)
echo "unrecognized test: $OPTARG"
exit 1
;;
esac
;;
l)
echo "available tests for -t:
android_unittests - Unit tests on generated Java code.
android_java_e2e_tests - Integration tests on generated Java code on Android.
android_kotlin_unittests - Unit tests on generated Kotlin code on Android.
android_kotlin_e2e_tests - Integration tests on generated Kotlin code on Android.
dart_compilation_tests - Compilation tests on generated Dart code.
dart_unittests - Unit tests on and analysis on Pigeon's implementation.
flutter_unittests - Unit tests on generated Dart code.
ios_objc_unittests - Unit tests on generated Obj-C code.
ios_unittests - Legacy unit tests on generated Obj-C code. Use ios_objc_unittests instead.
ios_objc_e2e_tests - Integration tests on generated Obj-C code.
ios_swift_unittests - Unit tests on generated Swift code.
ios_swift_e2e_tests - Integration tests on generated Swift code on iOS.
mock_handler_tests - Unit tests on generated Dart mock handler code.
macos_swift_unittests - Unit tests on generated Swift code on macOS.
macos_swift_e2e_tests - Integration tests on generated Swift code on macOS.
"
exit 1
;;
\h)
print_usage
exit 1
;;
\?)
print_usage
exit 1
;;
?)
print_usage
exit 1
;;
esac
done
##############################################################################
dart pub get
dart --snapshot-kind=kernel --snapshot=bin/pigeon.dart.dill bin/pigeon.dart
# Pre-generate platform_test output files, which most tests rely on existing.
dart run tool/generate.dart
if [ "$should_run_android_unittests" = true ]; then
get_java_linter_formatter
fi
test_command_line
if [ "$should_run_dart_unittests" = true ]; then
run_dart_unittests
fi
if [ "$should_run_flutter_unittests" = true ]; then
run_flutter_unittests
fi
if [ "$should_run_mock_handler_tests" = true ]; then
run_mock_handler_tests
fi
if [ "$should_run_dart_compilation_tests" = true ]; then
run_dart_compilation_tests
fi
if [ "$should_run_ios_objc_unittests" = true ]; then
run_ios_objc_unittests
fi
if [ "$should_run_ios_legacy_unittests" = true ]; then
run_ios_legacy_unittests
fi
if [ "$should_run_ios_swift_unittests" = true ]; then
run_ios_swift_unittests
fi
if [ "$should_run_ios_swift_e2e_tests" = true ]; then
run_ios_swift_e2e_tests
fi
if [ "$should_run_ios_objc_e2e_tests" = true ]; then
run_ios_objc_e2e_tests
fi
if [ "$should_run_android_unittests" = true ]; then
run_android_unittests
fi
if [ "$should_run_android_java_e2e_tests" = true ]; then
run_android_java_e2e_tests
fi
if [ "$should_run_macos_swift_unittests" = true ]; then
run_macos_swift_unittests
fi
if [ "$should_run_macos_swift_e2e_tests" = true ]; then
run_macos_swift_e2e_tests
fi
if [ "$should_run_android_kotlin_unittests" = true ]; then
run_android_kotlin_unittests
fi
if [ "$should_run_android_kotlin_e2e_tests" = true ]; then
run_android_kotlin_e2e_tests
fi

View File

@ -9,7 +9,7 @@
///
/// usage: dart run tool/run_tests.dart
////////////////////////////////////////////////////////////////////////////////
import 'dart:io' show File, Platform, exit;
import 'dart:io' show File, Directory, Platform, exit;
import 'dart:math';
import 'package:args/args.dart';
@ -39,59 +39,82 @@ class _TestInfo {
final String? description;
}
// Test suite names.
const String androidJavaUnitTests = 'android_java_unittests';
const String androidJavaIntegrationTests = 'android_java_integration_tests';
const String androidKotlinUnitTests = 'android_kotlin_unittests';
const String androidKotlinIntegrationTests = 'android_kotlin_integration_tests';
const String iOSObjCUnitTests = 'ios_objc_unittests';
const String iOSObjCUnitTestsLegacy = 'ios_objc_legacy_unittests';
const String iOSObjCIntegrationTests = 'ios_objc_integration_tests';
const String iOSSwiftUnitTests = 'ios_swift_unittests';
const String iOSSwiftIntegrationTests = 'ios_swift_integration_tests';
const String macOSSwiftUnitTests = 'macos_swift_unittests';
const String macOSSwiftIntegrationTests = 'macos_swift_integration_tests';
const String windowsUnitTests = 'windows_unittests';
const String windowsIntegrationTests = 'windows_integration_tests';
const String dartUnitTests = 'dart_unittests';
const String flutterUnitTests = 'flutter_unittests';
const String mockHandlerTests = 'mock_handler_tests';
const String commandLineTests = 'command_line_tests';
const Map<String, _TestInfo> _tests = <String, _TestInfo>{
'windows_unittests': _TestInfo(
windowsUnitTests: _TestInfo(
function: _runWindowsUnitTests,
description: 'Unit tests on generated Windows C++ code.'),
'windows_integration_tests': _TestInfo(
windowsIntegrationTests: _TestInfo(
function: _runWindowsIntegrationTests,
description: 'Integration tests on generated Windows C++ code.'),
'android_java_unittests': _TestInfo(
androidJavaUnitTests: _TestInfo(
function: _runAndroidJavaUnitTests,
description: 'Unit tests on generated Java code.'),
'android_java_integration_tests': _TestInfo(
androidJavaIntegrationTests: _TestInfo(
function: _runAndroidJavaIntegrationTests,
description: 'Integration tests on generated Java code.'),
'android_kotlin_unittests': _TestInfo(
androidKotlinUnitTests: _TestInfo(
function: _runAndroidKotlinUnitTests,
description: 'Unit tests on generated Kotlin code.'),
'android_kotlin_integration_tests': _TestInfo(
androidKotlinIntegrationTests: _TestInfo(
function: _runAndroidKotlinIntegrationTests,
description: 'Integration tests on generated Kotlin code.'),
'dart_compilation_tests': _TestInfo(
function: _runDartCompilationTests,
description: 'Compilation tests on generated Dart code.'),
'dart_unittests': _TestInfo(
dartUnitTests: _TestInfo(
function: _runDartUnitTests,
description: "Unit tests on and analysis on Pigeon's implementation."),
'flutter_unittests': _TestInfo(
flutterUnitTests: _TestInfo(
function: _runFlutterUnitTests,
description: 'Unit tests on generated Dart code.'),
'ios_objc_unittests': _TestInfo(
iOSObjCUnitTests: _TestInfo(
function: _runIOSObjCUnitTests,
description: 'Unit tests on generated Objective-C code.'),
'ios_objc_integration_tests': _TestInfo(
iOSObjCUnitTestsLegacy: _TestInfo(
function: _runIOSObjCLegacyUnitTests,
description:
'Unit tests on generated Objective-C code (legacy test harness).'),
iOSObjCIntegrationTests: _TestInfo(
function: _runIOSObjCIntegrationTests,
description: 'Integration tests on generated Objective-C code.'),
'ios_swift_unittests': _TestInfo(
iOSSwiftUnitTests: _TestInfo(
function: _runIOSSwiftUnitTests,
description: 'Unit tests on generated Swift code.'),
'ios_swift_integration_tests': _TestInfo(
iOSSwiftIntegrationTests: _TestInfo(
function: _runIOSSwiftIntegrationTests,
description: 'Integration tests on generated Swift code.'),
'macos_swift_unittests': _TestInfo(
macOSSwiftUnitTests: _TestInfo(
function: _runMacOSSwiftUnitTests,
description: 'Unit tests on generated Swift code on macOS.'),
'macos_swift_integration_tests': _TestInfo(
macOSSwiftIntegrationTests: _TestInfo(
function: _runMacOSSwiftIntegrationTests,
description: 'Integration tests on generated Swift code on macOS.'),
'mock_handler_tests': _TestInfo(
mockHandlerTests: _TestInfo(
function: _runMockHandlerTests,
description: 'Unit tests on generated Dart mock handler code.'),
commandLineTests: _TestInfo(
function: _runCommandLineTests,
description: 'Tests running pigeon with various command-line options.'),
};
Future<int> _runAndroidJavaUnitTests() async {
throw UnimplementedError('See run_tests.sh.');
return _runAndroidUnitTests(_alternateLanguageTestPluginRelativePath);
}
Future<int> _runAndroidJavaIntegrationTests() async {
@ -100,8 +123,12 @@ Future<int> _runAndroidJavaIntegrationTests() async {
}
Future<int> _runAndroidKotlinUnitTests() async {
const String examplePath = './$_testPluginRelativePath/example';
const String androidProjectPath = '$examplePath/android';
return _runAndroidUnitTests(_testPluginRelativePath);
}
Future<int> _runAndroidUnitTests(String testPluginPath) async {
final String examplePath = './$testPluginPath/example';
final String androidProjectPath = '$examplePath/android';
final File gradleFile = File(p.join(androidProjectPath, 'gradlew'));
if (!gradleFile.existsSync()) {
final int compileCode = await runFlutterBuild(examplePath, 'apk');
@ -134,10 +161,6 @@ Future<int> _runMobileIntegrationTests(
);
}
Future<int> _runDartCompilationTests() async {
throw UnimplementedError('See run_tests.sh.');
}
Future<int> _runDartUnitTests() async {
int exitCode = await runProcess('dart', <String>['analyze', 'bin']);
if (exitCode != 0) {
@ -195,19 +218,31 @@ Future<int> _runFlutterUnitTests() async {
// shared_test_plugin_code instead of having multiple copies of generation.
const String flutterUnitTestsPath =
'platform_tests/flutter_null_safe_unit_tests';
// Files from the pigeons/ directory to generate output for.
const List<String> inputPigeons = <String>[
'flutter_unittests',
'core_tests',
'primitive',
'multiple_arity',
'non_null_fields',
'null_fields',
'nullable_returns',
// TODO(stuartmorgan): Eliminate these files by ensuring that everything
// they are intended to cover is in core_tests.dart (or, if necessary in
// the short term due to limitations in non-Dart generators, a single other
// file). They aren't being unit tested, only analyzed.
'async_handlers',
'host2flutter',
'list',
'message',
'void_arg_flutter',
'void_arg_host',
'voidflutter',
'voidhost',
];
final int generateCode = await _generateDart(<String, String>{
'pigeons/flutter_unittests.dart':
'$flutterUnitTestsPath/lib/null_safe_pigeon.dart',
'pigeons/core_tests.dart': '$flutterUnitTestsPath/lib/core_tests.gen.dart',
'pigeons/primitive.dart': '$flutterUnitTestsPath/lib/primitive.dart',
'pigeons/multiple_arity.dart':
'$flutterUnitTestsPath/lib/multiple_arity.gen.dart',
'pigeons/non_null_fields.dart':
'$flutterUnitTestsPath/lib/non_null_fields.gen.dart',
'pigeons/null_fields.dart':
'$flutterUnitTestsPath/lib/null_fields.gen.dart',
'pigeons/nullable_returns.dart':
'$flutterUnitTestsPath/lib/nullable_returns.gen.dart',
for (final String name in inputPigeons)
'pigeons/$name.dart': '$flutterUnitTestsPath/lib/$name.gen.dart'
});
if (generateCode != 0) {
return generateCode;
@ -227,7 +262,14 @@ Future<int> _runFlutterUnitTests() async {
}
Future<int> _runIOSObjCUnitTests() async {
return _runIOSUnitTests(_alternateLanguageTestPluginRelativePath);
return _runIOSPluginUnitTests(_alternateLanguageTestPluginRelativePath);
}
// TODO(stuartmorgan): Remove this, and the ios_unit_tests directory, once
// _runIOSObjCUnitTests works in CI; see
// https://github.com/flutter/packages/pull/2816.
Future<int> _runIOSObjCLegacyUnitTests() async {
return _runIOSProjectUnitTests('platform_tests/ios_unit_tests');
}
Future<int> _runIOSObjCIntegrationTests() async {
@ -270,13 +312,17 @@ Future<int> _runMacOSSwiftIntegrationTests() async {
}
Future<int> _runIOSSwiftUnitTests() async {
return _runIOSUnitTests(_testPluginRelativePath);
return _runIOSPluginUnitTests(_testPluginRelativePath);
}
Future<int> _runIOSUnitTests(String testPluginPath) async {
Future<int> _runIOSPluginUnitTests(String testPluginPath) async {
final String examplePath = './$testPluginPath/example';
return _runIOSProjectUnitTests(examplePath);
}
Future<int> _runIOSProjectUnitTests(String testProjectPath) async {
final int compileCode = await runFlutterBuild(
examplePath,
testProjectPath,
'ios',
flags: <String>['--simulator', '--no-codesign'],
);
@ -285,7 +331,7 @@ Future<int> _runIOSUnitTests(String testPluginPath) async {
}
return runXcodeBuild(
'$examplePath/ios',
'$testProjectPath/ios',
sdk: 'iphonesimulator',
destination: 'platform=iOS Simulator,name=iPhone 8',
extraArguments: <String>['test'],
@ -335,6 +381,61 @@ Future<int> _runWindowsIntegrationTests() async {
);
}
Future<int> _runCommandLineTests() async {
final Directory tempDir = Directory.systemTemp.createTempSync('pigeon');
final String tempOutput = p.join(tempDir.path, 'pigeon_output');
const String pigeonScript = 'bin/pigeon.dart';
final String snapshot = p.join(tempDir.path, 'pigeon.dart.dill');
// Precompile to make the repeated calls faster.
if (await runProcess('dart', <String>[
'--snapshot-kind=kernel',
'--snapshot=$snapshot',
pigeonScript
]) !=
0) {
print('Unable to generate $snapshot from $pigeonScript');
return 1;
}
final List<List<String>> testArguments = <List<String>>[
// Test with no arguments.
<String>[],
// Test one_language flag. With this flag specified, java_out can be
// generated without dart_out.
<String>[
'--input',
'pigeons/message.dart',
'--one_language',
'--java_out',
tempOutput
],
// Test dartOut in ConfigurePigeon overrides output.
<String>['--input', 'pigeons/configure_pigeon_dart_out.dart'],
// Make sure AST generation exits correctly.
<String>[
'--input',
'pigeons/message.dart',
'--one_language',
'--ast_out',
tempOutput
],
];
int exitCode = 0;
for (final List<String> arguments in testArguments) {
print('Testing dart $pigeonScript ${arguments.join(', ')}');
exitCode = await runProcess('dart', <String>[snapshot, ...arguments],
streamOutput: false, logFailure: true);
if (exitCode != 0) {
break;
}
}
tempDir.deleteSync(recursive: true);
return exitCode;
}
Future<void> main(List<String> args) async {
final ArgParser parser = ArgParser()
..addMultiOption(_testFlag, abbr: 't', help: 'Only run specified tests.')
@ -385,10 +486,57 @@ ${parser.usage}''');
// If no tests are provided, run a default based on the host platform. This is
// the mode used by CI.
if (testsToRun.isEmpty) {
if (Platform.isWindows) {
testsToRun = <String>['windows_unittests', 'windows_integration_tests'];
const List<String> androidTests = <String>[
androidJavaUnitTests,
androidKotlinUnitTests,
// TODO(stuartmorgan): Include these once CI supports running simulator
// tests. Currently these tests aren't run in CI.
// See https://github.com/flutter/flutter/issues/111505.
// androidJavaIntegrationTests,
// androidKotlinIntegrationTests,
];
const List<String> macOSTests = <String>[
macOSSwiftUnitTests,
macOSSwiftIntegrationTests
];
const List<String> iOSTests = <String>[
// TODO(stuartmorgan): Replace this with iOSObjCUnitTests once the CI
// issues are resolved; see https://github.com/flutter/packages/pull/2816.
iOSObjCUnitTestsLegacy,
// TODO(stuartmorgan): Enable by default once CI issues are solved; see
// https://github.com/flutter/packages/pull/2816.
// iOSObjCIntegrationTests,
iOSSwiftUnitTests,
// Currently these are testing exactly the same thing as
// macos_swift_e2e_tests, so we don't need to run both by default. This
// should be enabled if any iOS-only tests are added (e.g., for a feature
// not supported by macOS).
// iOSSwiftIntegrationTests,
];
const List<String> windowsTests = <String>[
windowsUnitTests,
windowsIntegrationTests,
];
const List<String> dartTests = <String>[
dartUnitTests,
flutterUnitTests,
mockHandlerTests,
commandLineTests,
];
if (Platform.isMacOS) {
testsToRun = <String>[
...dartTests,
...androidTests,
...iOSTests,
...macOSTests,
];
} else if (Platform.isWindows) {
testsToRun = windowsTests;
} else {
// TODO(gaaclarke): migrate from run_tests.sh to this script.
// TODO(stuartmorgan): Make a new entrypoint for developers that runs
// all tests their host supports by default, and move some of the tests
// above here. See https://github.com/flutter/flutter/issues/115393
}
}