mirror of
https://github.com/flutter/packages.git
synced 2025-07-01 15:23:25 +08:00
[pigeon] Initial integration test setup (#2851)
* [pigeon] Initial integration test setup This sets up initial proof-of-concept integration tests using the new shared native test harness: - Integration tests on the Dart side for void->void and Everything->Everything calls. - macOS implementations in the test plugin on the native side. - A new test target in the test script to drive them via `flutter test`. - A minimal change to the example app so that `flutter run`-ing it will test that the void->void call is wired up. Since this simple initial test hit https://github.com/flutter/flutter/issues/111083, which caused the test to fail, this includes a fix for that. Short-term future work (by me): - Add integration test native setup and script targets for the other generators. This includes one just to keep the initial review scope smaller. - Update https://github.com/flutter/packages/pull/2816 to include the integration test since it's still blocked until I can address the CI issues. Medium-term future work (not all by me): - Remove the legacy iOS e2e test scaffold that is currently disabled. - Add significantly more integration test coverage (likely including https://github.com/flutter/flutter/issues/115168 to reduce redundant API setup), including Flutter API integration tests rather than just host API tests. Part of https://github.com/flutter/flutter/issues/111505 Fixes https://github.com/flutter/flutter/issues/111083 * Version bump for bugfix * Check in generated files needed for analysis * Add the actual integration test file, which was left out * Address review comments * Fix incorrect Swift unit test for void call fix * Analysis ignore * Autoformat
This commit is contained in:
@ -1,3 +1,7 @@
|
||||
## 4.2.7
|
||||
|
||||
* [swift] Fixes a bug when calling methods that return `void`.
|
||||
|
||||
## 4.2.6
|
||||
|
||||
* Fixes bug with parsing documentation comments that start with '/'.
|
||||
|
@ -9,7 +9,7 @@ import 'dart:mirrors';
|
||||
import 'ast.dart';
|
||||
|
||||
/// The current version of pigeon. This must match the version in pubspec.yaml.
|
||||
const String pigeonVersion = '4.2.6';
|
||||
const String pigeonVersion = '4.2.7';
|
||||
|
||||
/// Read all the content from [stdin] to a String.
|
||||
String readStdin() {
|
||||
|
@ -232,7 +232,7 @@ void _writeHostApi(Indent indent, Api api, Root root) {
|
||||
indent.write('$call ');
|
||||
if (method.returnType.isVoid) {
|
||||
indent.scoped('{', '}', () {
|
||||
indent.writeln('reply(nil)');
|
||||
indent.writeln('reply(wrapResult(nil))');
|
||||
});
|
||||
} else {
|
||||
indent.scoped('{ result in', '}', () {
|
||||
@ -242,7 +242,7 @@ void _writeHostApi(Indent indent, Api api, Root root) {
|
||||
} else {
|
||||
if (method.returnType.isVoid) {
|
||||
indent.writeln(call);
|
||||
indent.writeln('reply(nil)');
|
||||
indent.writeln('reply(wrapResult(nil))');
|
||||
} else {
|
||||
indent.writeln('let result = $call');
|
||||
indent.writeln('reply(wrapResult(result))');
|
||||
|
@ -0,0 +1,79 @@
|
||||
// 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.
|
||||
|
||||
// TODO(a14n): remove this import once Flutter 3.1 or later reaches stable (including flutter/flutter#104231)
|
||||
// ignore: unnecessary_import
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:integration_test/integration_test.dart';
|
||||
import 'package:test_plugin/all_datatypes.gen.dart';
|
||||
import 'package:test_plugin/all_void.gen.dart';
|
||||
|
||||
void main() {
|
||||
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
group('Host API tests', () {
|
||||
testWidgets('voidCallVoidReturn', (WidgetTester _) async {
|
||||
final AllVoidHostApi api = AllVoidHostApi();
|
||||
|
||||
expect(api.doit(), completes);
|
||||
});
|
||||
|
||||
testWidgets('allDataTypesEcho', (WidgetTester _) async {
|
||||
final HostEverything api = HostEverything();
|
||||
|
||||
final Everything sentObject = Everything(
|
||||
aBool: true,
|
||||
anInt: 42,
|
||||
aDouble: 3.14159,
|
||||
aString: 'Hello host!',
|
||||
aByteArray: Uint8List.fromList(<int>[1, 2, 3]),
|
||||
a4ByteArray: Int32List.fromList(<int>[4, 5, 6]),
|
||||
a8ByteArray: Int64List.fromList(<int>[7, 8, 9]),
|
||||
aFloatArray: Float64List.fromList(<double>[2.71828, 3.14159]),
|
||||
aList: <Object?>['Thing 1', 2],
|
||||
aMap: <Object?, Object?>{'a': 1, 'b': 2.0},
|
||||
nestedList: <List<bool>>[
|
||||
<bool>[true, false],
|
||||
<bool>[false, true]
|
||||
],
|
||||
);
|
||||
|
||||
final Everything echoObject = await api.echo(sentObject);
|
||||
expect(echoObject.aBool, sentObject.aBool);
|
||||
expect(echoObject.anInt, sentObject.anInt);
|
||||
expect(echoObject.aDouble, sentObject.aDouble);
|
||||
expect(echoObject.aString, sentObject.aString);
|
||||
// TODO(stuartmorgan): Enable these once they work for all generators;
|
||||
// currently at least Swift is broken.
|
||||
// See https://github.com/flutter/flutter/issues/115906
|
||||
//expect(echoObject.aByteArray, sentObject.aByteArray);
|
||||
//expect(echoObject.a4ByteArray, sentObject.a4ByteArray);
|
||||
//expect(echoObject.a8ByteArray, sentObject.a8ByteArray);
|
||||
//expect(echoObject.aFloatArray, sentObject.aFloatArray);
|
||||
expect(listEquals(echoObject.aList, sentObject.aList), true);
|
||||
expect(mapEquals(echoObject.aMap, sentObject.aMap), true);
|
||||
expect(echoObject.nestedList?.length, sentObject.nestedList?.length);
|
||||
// TODO(stuartmorgan): Enable this once the Dart types are fixed; see
|
||||
// https://github.com/flutter/flutter/issues/116117
|
||||
//for (int i = 0; i < echoObject.nestedList!.length; i++) {
|
||||
// expect(listEquals(echoObject.nestedList![i], sentObject.nestedList![i]),
|
||||
// true);
|
||||
//}
|
||||
expect(
|
||||
mapEquals(
|
||||
echoObject.mapWithAnnotations, sentObject.mapWithAnnotations),
|
||||
true);
|
||||
expect(
|
||||
mapEquals(echoObject.mapWithObject, sentObject.mapWithObject), true);
|
||||
});
|
||||
});
|
||||
|
||||
group('Flutter API tests', () {
|
||||
// TODO(stuartmorgan): Add Flutter API tests, driven by wrapper host APIs
|
||||
// that forward the arguments and return values in the opposite direction.
|
||||
});
|
||||
}
|
@ -44,7 +44,7 @@ class AsyncHandlersTest: XCTestCase {
|
||||
let expectation = XCTestExpectation(description: "voidvoid callback")
|
||||
binaryMessenger.handlers[channelName]?(nil) { data in
|
||||
let outputMap = binaryMessenger.codec.decode(data) as? [String: Any]
|
||||
XCTAssertNil(outputMap?["result"])
|
||||
XCTAssertEqual(outputMap?["result"] as! NSNull, NSNull())
|
||||
XCTAssertNil(outputMap?["error"])
|
||||
expectation.fulfill()
|
||||
}
|
||||
|
@ -5,6 +5,7 @@
|
||||
// ignore_for_file: public_member_api_docs
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:test_plugin/all_void.gen.dart';
|
||||
import 'package:test_plugin/test_plugin.dart';
|
||||
|
||||
void main() {
|
||||
@ -21,6 +22,8 @@ class MyApp extends StatefulWidget {
|
||||
class _MyAppState extends State<MyApp> {
|
||||
// ignore: unused_field
|
||||
final TestPlugin _testPlugin = TestPlugin();
|
||||
late final AllVoidHostApi api;
|
||||
String status = 'Calling...';
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
@ -29,9 +32,18 @@ class _MyAppState extends State<MyApp> {
|
||||
}
|
||||
|
||||
Future<void> initPlatformState() async {
|
||||
// TODO(tarrinneal): Call TestPlugin methods here for manual integration
|
||||
// testing, once they exist. See
|
||||
// https://github.com/flutter/flutter/issues/111505
|
||||
api = AllVoidHostApi();
|
||||
try {
|
||||
await api.doit();
|
||||
} catch (e) {
|
||||
setState(() {
|
||||
status = 'Failed: $e';
|
||||
});
|
||||
return;
|
||||
}
|
||||
setState(() {
|
||||
status = 'Success!';
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
@ -41,9 +53,8 @@ class _MyAppState extends State<MyApp> {
|
||||
appBar: AppBar(
|
||||
title: const Text('Pigeon integration tests'),
|
||||
),
|
||||
body: const Center(
|
||||
child: Text(
|
||||
'TODO, see https://github.com/flutter/flutter/issues/111505'),
|
||||
body: Center(
|
||||
child: Text(status),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
@ -14,6 +14,8 @@ dependencies:
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
integration_test:
|
||||
sdk: flutter
|
||||
|
||||
flutter:
|
||||
uses-material-design: true
|
||||
|
@ -2,8 +2,7 @@
|
||||
# changes on generated files. This will need a way to avoid unnecessary churn,
|
||||
# such as a flag to suppress version stamp generation.
|
||||
*.gen.dart
|
||||
# TODO(stuartmorgan): Add exceptions for specific files that are used in
|
||||
# integration tests, as they will need to be checked in to avoid analysis
|
||||
# failures. The exclusion of other files is to prevent having multiple
|
||||
# copies of all of the Dart output until more tests are restructured to
|
||||
# minimize duplication.
|
||||
# The following are files that are used in integration tests, which need to be
|
||||
# checked in to avoid analysis failures.
|
||||
!all_datatypes.gen.dart
|
||||
!all_void.gen.dart
|
||||
|
@ -0,0 +1,245 @@
|
||||
// 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.7), 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 Map<Object?, Object?> pigeonMap = <Object?, Object?>{};
|
||||
pigeonMap['aBool'] = aBool;
|
||||
pigeonMap['anInt'] = anInt;
|
||||
pigeonMap['aDouble'] = aDouble;
|
||||
pigeonMap['aString'] = aString;
|
||||
pigeonMap['aByteArray'] = aByteArray;
|
||||
pigeonMap['a4ByteArray'] = a4ByteArray;
|
||||
pigeonMap['a8ByteArray'] = a8ByteArray;
|
||||
pigeonMap['aFloatArray'] = aFloatArray;
|
||||
pigeonMap['aList'] = aList;
|
||||
pigeonMap['aMap'] = aMap;
|
||||
pigeonMap['nestedList'] = nestedList;
|
||||
pigeonMap['mapWithAnnotations'] = mapWithAnnotations;
|
||||
pigeonMap['mapWithObject'] = mapWithObject;
|
||||
return pigeonMap;
|
||||
}
|
||||
|
||||
static Everything decode(Object message) {
|
||||
final Map<Object?, Object?> pigeonMap = message as Map<Object?, Object?>;
|
||||
return Everything(
|
||||
aBool: pigeonMap['aBool'] as bool?,
|
||||
anInt: pigeonMap['anInt'] as int?,
|
||||
aDouble: pigeonMap['aDouble'] as double?,
|
||||
aString: pigeonMap['aString'] as String?,
|
||||
aByteArray: pigeonMap['aByteArray'] as Uint8List?,
|
||||
a4ByteArray: pigeonMap['a4ByteArray'] as Int32List?,
|
||||
a8ByteArray: pigeonMap['a8ByteArray'] as Int64List?,
|
||||
aFloatArray: pigeonMap['aFloatArray'] as Float64List?,
|
||||
aList: pigeonMap['aList'] as List<Object?>?,
|
||||
aMap: pigeonMap['aMap'] as Map<Object?, Object?>?,
|
||||
nestedList:
|
||||
(pigeonMap['nestedList'] as List<Object?>?)?.cast<List<bool?>?>(),
|
||||
mapWithAnnotations:
|
||||
(pigeonMap['mapWithAnnotations'] as Map<Object?, Object?>?)
|
||||
?.cast<String?, String?>(),
|
||||
mapWithObject: (pigeonMap['mapWithObject'] 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)!);
|
||||
|
||||
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 Map<Object?, Object?>? replyMap =
|
||||
await channel.send(null) as Map<Object?, Object?>?;
|
||||
if (replyMap == null) {
|
||||
throw PlatformException(
|
||||
code: 'channel-error',
|
||||
message: 'Unable to establish connection on channel.',
|
||||
);
|
||||
} else if (replyMap['error'] != null) {
|
||||
final Map<Object?, Object?> error =
|
||||
(replyMap['error'] as Map<Object?, Object?>?)!;
|
||||
throw PlatformException(
|
||||
code: (error['code'] as String?)!,
|
||||
message: error['message'] as String?,
|
||||
details: error['details'],
|
||||
);
|
||||
} else if (replyMap['result'] == null) {
|
||||
throw PlatformException(
|
||||
code: 'null-error',
|
||||
message: 'Host platform returned null value for non-null return value.',
|
||||
);
|
||||
} else {
|
||||
return (replyMap['result'] as Everything?)!;
|
||||
}
|
||||
}
|
||||
|
||||
Future<Everything> echo(Everything arg_everything) async {
|
||||
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
||||
'dev.flutter.pigeon.HostEverything.echo', codec,
|
||||
binaryMessenger: _binaryMessenger);
|
||||
final Map<Object?, Object?>? replyMap =
|
||||
await channel.send(<Object?>[arg_everything]) as Map<Object?, Object?>?;
|
||||
if (replyMap == null) {
|
||||
throw PlatformException(
|
||||
code: 'channel-error',
|
||||
message: 'Unable to establish connection on channel.',
|
||||
);
|
||||
} else if (replyMap['error'] != null) {
|
||||
final Map<Object?, Object?> error =
|
||||
(replyMap['error'] as Map<Object?, Object?>?)!;
|
||||
throw PlatformException(
|
||||
code: (error['code'] as String?)!,
|
||||
message: error['message'] as String?,
|
||||
details: error['details'],
|
||||
);
|
||||
} else if (replyMap['result'] == null) {
|
||||
throw PlatformException(
|
||||
code: 'null-error',
|
||||
message: 'Host platform returned null value for non-null return value.',
|
||||
);
|
||||
} else {
|
||||
return (replyMap['result'] 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)!);
|
||||
|
||||
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;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,70 @@
|
||||
// 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.7), 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';
|
||||
|
||||
abstract class AllVoidFlutterApi {
|
||||
static const MessageCodec<Object?> codec = StandardMessageCodec();
|
||||
|
||||
void doit();
|
||||
static void setup(AllVoidFlutterApi? api,
|
||||
{BinaryMessenger? binaryMessenger}) {
|
||||
{
|
||||
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
||||
'dev.flutter.pigeon.AllVoidFlutterApi.doit', codec,
|
||||
binaryMessenger: binaryMessenger);
|
||||
if (api == null) {
|
||||
channel.setMessageHandler(null);
|
||||
} else {
|
||||
channel.setMessageHandler((Object? message) async {
|
||||
// ignore message
|
||||
api.doit();
|
||||
return;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class AllVoidHostApi {
|
||||
/// Constructor for [AllVoidHostApi]. 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.
|
||||
AllVoidHostApi({BinaryMessenger? binaryMessenger})
|
||||
: _binaryMessenger = binaryMessenger;
|
||||
final BinaryMessenger? _binaryMessenger;
|
||||
|
||||
static const MessageCodec<Object?> codec = StandardMessageCodec();
|
||||
|
||||
Future<void> doit() async {
|
||||
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
||||
'dev.flutter.pigeon.AllVoidHostApi.doit', codec,
|
||||
binaryMessenger: _binaryMessenger);
|
||||
final Map<Object?, Object?>? replyMap =
|
||||
await channel.send(null) as Map<Object?, Object?>?;
|
||||
if (replyMap == null) {
|
||||
throw PlatformException(
|
||||
code: 'channel-error',
|
||||
message: 'Unable to establish connection on channel.',
|
||||
);
|
||||
} else if (replyMap['error'] != null) {
|
||||
final Map<Object?, Object?> error =
|
||||
(replyMap['error'] as Map<Object?, Object?>?)!;
|
||||
throw PlatformException(
|
||||
code: (error['code'] as String?)!,
|
||||
message: error['message'] as String?,
|
||||
details: error['details'],
|
||||
);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
@ -6,14 +6,30 @@ import Cocoa
|
||||
import FlutterMacOS
|
||||
|
||||
/**
|
||||
* This plugin is currently a no-op since only unit tests have been set up.
|
||||
* In the future, this will register Pigeon APIs used in integration tests.
|
||||
* This plugin handles the native side of the integration tests in
|
||||
* example/integration_test/.
|
||||
*/
|
||||
public class TestPlugin: NSObject, FlutterPlugin {
|
||||
public class TestPlugin: NSObject, FlutterPlugin, AllVoidHostApi, HostEverything {
|
||||
public static func register(with registrar: FlutterPluginRegistrar) {
|
||||
let plugin = TestPlugin()
|
||||
AllVoidHostApiSetup.setUp(binaryMessenger: registrar.messenger, api: plugin)
|
||||
HostEverythingSetup.setUp(binaryMessenger: registrar.messenger, api: plugin)
|
||||
}
|
||||
|
||||
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
|
||||
result(FlutterMethodNotImplemented)
|
||||
// MARK: AllVoidHostApi implementation
|
||||
|
||||
func doit() {
|
||||
// No-op
|
||||
}
|
||||
|
||||
// MARK: HostEverything implementation
|
||||
|
||||
func giveMeEverything() -> Everything {
|
||||
// Currently unused in integration tests, so just return an empty object.
|
||||
return Everything()
|
||||
}
|
||||
|
||||
func echo(everything: Everything) -> Everything {
|
||||
return everything
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ name: pigeon
|
||||
description: Code generator tool to make communication between Flutter and the host platform type-safe and easier.
|
||||
repository: https://github.com/flutter/packages/tree/main/packages/pigeon
|
||||
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3Apigeon
|
||||
version: 4.2.6 # This must match the version in lib/generator_tools.dart
|
||||
version: 4.2.7 # This must match the version in lib/generator_tools.dart
|
||||
|
||||
environment:
|
||||
sdk: ">=2.12.0 <3.0.0"
|
||||
|
@ -166,7 +166,11 @@ run_ios_swift_unittests() {
|
||||
}
|
||||
|
||||
run_macos_swift_unittests() {
|
||||
dart run tool/run_tests.dart -t mac_swift_unittests --skip-generation
|
||||
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() {
|
||||
@ -255,6 +259,7 @@ should_run_ios_unittests=true
|
||||
should_run_ios_swift_unittests=true
|
||||
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
|
||||
while getopts "t:l?h" opt; do
|
||||
case $opt in
|
||||
@ -268,6 +273,7 @@ while getopts "t:l?h" opt; do
|
||||
should_run_ios_swift_unittests=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
|
||||
case $OPTARG in
|
||||
# TODO(stuartmorgan): Rename to include "java".
|
||||
@ -281,6 +287,7 @@ while getopts "t:l?h" opt; do
|
||||
ios_swift_unittests) should_run_ios_swift_unittests=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 ;;
|
||||
*)
|
||||
echo "unrecognized test: $OPTARG"
|
||||
@ -300,6 +307,7 @@ while getopts "t:l?h" opt; do
|
||||
ios_swift_unittests - Unit tests on generated Swift code.
|
||||
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
|
||||
;;
|
||||
@ -356,6 +364,9 @@ 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
|
||||
|
@ -24,7 +24,8 @@ const String _testFlag = 'test';
|
||||
const String _listFlag = 'list';
|
||||
const String _skipGenerationFlag = 'skip-generation';
|
||||
|
||||
const String testPluginRelativePath = 'platform_tests/test_plugin';
|
||||
const String _testPluginRelativePath = 'platform_tests/test_plugin';
|
||||
const String _integrationTestFileRelativePath = 'integration_test/test.dart';
|
||||
|
||||
@immutable
|
||||
class _TestInfo {
|
||||
@ -52,18 +53,18 @@ const Map<String, _TestInfo> _tests = <String, _TestInfo>{
|
||||
'flutter_unittests': _TestInfo(
|
||||
function: _runFlutterUnitTests,
|
||||
description: 'Unit tests on generated Dart code.'),
|
||||
'ios_e2e_tests': _TestInfo(
|
||||
function: _runIosE2eTests,
|
||||
description: 'End-to-end Objective-C tests run on iOS Simulator'),
|
||||
'ios_unittests': _TestInfo(
|
||||
function: _runIosUnitTests,
|
||||
description: 'Unit tests on generated Objective-C code.'),
|
||||
'ios_swift_unittests': _TestInfo(
|
||||
function: _runIosSwiftUnitTests,
|
||||
description: 'Unit tests on generated Swift code.'),
|
||||
'mac_swift_unittests': _TestInfo(
|
||||
'macos_swift_unittests': _TestInfo(
|
||||
function: _runMacOSSwiftUnitTests,
|
||||
description: 'Unit tests on generated Swift code on macOS.'),
|
||||
'macos_swift_integration_tests': _TestInfo(
|
||||
function: _runMacOSSwiftIntegrationTests,
|
||||
description: 'Integration tests on generated Swift code on macOS.'),
|
||||
'mock_handler_tests': _TestInfo(
|
||||
function: _runMockHandlerTests,
|
||||
description: 'Unit tests on generated Dart mock handler code.'),
|
||||
@ -74,7 +75,7 @@ Future<int> _runAndroidUnitTests() async {
|
||||
}
|
||||
|
||||
Future<int> _runAndroidKotlinUnitTests() async {
|
||||
const String examplePath = './$testPluginRelativePath/example';
|
||||
const String examplePath = './$_testPluginRelativePath/example';
|
||||
const String androidProjectPath = '$examplePath/android';
|
||||
final File gradleFile = File(p.join(androidProjectPath, 'gradlew'));
|
||||
if (!gradleFile.existsSync()) {
|
||||
@ -179,16 +180,12 @@ Future<int> _runFlutterUnitTests() async {
|
||||
return 0;
|
||||
}
|
||||
|
||||
Future<int> _runIosE2eTests() async {
|
||||
throw UnimplementedError('See run_tests.sh.');
|
||||
}
|
||||
|
||||
Future<int> _runIosUnitTests() async {
|
||||
throw UnimplementedError('See run_tests.sh.');
|
||||
}
|
||||
|
||||
Future<int> _runMacOSSwiftUnitTests() async {
|
||||
const String examplePath = './$testPluginRelativePath/example';
|
||||
const String examplePath = './$_testPluginRelativePath/example';
|
||||
final int compileCode = await runFlutterBuild(examplePath, 'macos');
|
||||
if (compileCode != 0) {
|
||||
return compileCode;
|
||||
@ -200,8 +197,17 @@ Future<int> _runMacOSSwiftUnitTests() async {
|
||||
);
|
||||
}
|
||||
|
||||
Future<int> _runMacOSSwiftIntegrationTests() async {
|
||||
const String examplePath = './$_testPluginRelativePath/example';
|
||||
return runFlutterCommand(
|
||||
examplePath,
|
||||
'test',
|
||||
<String>[_integrationTestFileRelativePath, '-d', 'macos'],
|
||||
);
|
||||
}
|
||||
|
||||
Future<int> _runIosSwiftUnitTests() async {
|
||||
const String examplePath = './$testPluginRelativePath/example';
|
||||
const String examplePath = './$_testPluginRelativePath/example';
|
||||
final int compileCode = await runFlutterBuild(
|
||||
examplePath,
|
||||
'ios',
|
||||
@ -238,7 +244,7 @@ Future<int> _runMockHandlerTests() async {
|
||||
}
|
||||
|
||||
Future<int> _runWindowsUnitTests() async {
|
||||
const String examplePath = './$testPluginRelativePath/example';
|
||||
const String examplePath = './$_testPluginRelativePath/example';
|
||||
final int compileCode = await runFlutterBuild(examplePath, 'windows');
|
||||
if (compileCode != 0) {
|
||||
return compileCode;
|
||||
|
Reference in New Issue
Block a user