[pigeon] Eliminate some of the test pigeons (#3213)

* Fold in async_handlers.dart

* Remove some largely unused files

* Fold in the relevant parts of list.dart

* Remove java_double_host_api

* Remove unnecessary double-generation of messages.dart

* Remove enum_args

* Remove some unnecesasry/duplicate unit tests

* Eliminate android_unittest

* Format

* Remove build references on Windows
This commit is contained in:
stuartmorgan
2023-02-16 14:40:13 -08:00
committed by GitHub
parent 6c04c745b0
commit 763d025f84
33 changed files with 1832 additions and 420 deletions

View File

@ -1,23 +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.
import 'package:pigeon/pigeon.dart';
class Value {
int? number;
}
@HostApi()
abstract class Api2Host {
@async
Value calculate(Value value);
@async
void voidVoid();
}
@FlutterApi()
abstract class Api2Flutter {
@async
Value calculate(Value value);
}

View File

@ -538,10 +538,68 @@ abstract class FlutterIntegrationCoreApi {
@ObjCSelector('echoNullableMap:')
@SwiftFunction('echoNullable(_:)')
Map<String?, Object?>? echoNullableMap(Map<String?, Object?>? aMap);
// ========== Async tests ==========
// These are minimal since async FlutterApi only changes Dart generation.
// Currently they aren't integration tested, but having them here ensures
// analysis coverage.
/// A no-op function taking no arguments and returning no value, to sanity
/// test basic asynchronous calling.
@async
void noopAsync();
/// Returns the passed in generic Object asynchronously.
@async
@ObjCSelector('echoAsyncString:')
@SwiftFunction('echoAsync(_:)')
String echoAsyncString(String aString);
}
/// An API that can be implemented for minimal, compile-only tests.
//
// This is also here to test that multiple host APIs can be generated
// successfully in all languages (e.g., in Java where it requires having a
// wrapper class).
@HostApi()
abstract class HostTrivialApi {
void noop();
}
/// A simple API implemented in some unit tests.
//
// This is separate from HostIntegrationCoreApi to avoid having to update a
// lot of unit tests every time we add something to the integration test API.
// TODO(stuartmorgan): Restructure the unit tests to reduce the number of
// different APIs we define.
@HostApi()
abstract class HostSmallApi {
@async
@ObjCSelector('echoString:')
String echo(String aString);
@async
void voidVoid();
}
/// A simple API called in some unit tests.
//
// This is separate from FlutterIntegrationCoreApi to allow for incrementally
// moving from the previous fragmented unit test structure to something more
// unified.
// TODO(stuartmorgan): Restructure the unit tests to reduce the number of
// different APIs we define.
@FlutterApi()
abstract class FlutterSmallApi {
@ObjCSelector('echoWrappedList:')
@SwiftFunction('echo(_:)')
TestMessage echoWrappedList(TestMessage msg);
}
/// A data class containing a List, used in unit tests.
// TODO(stuartmorgan): Evaluate whether these unit tests are still useful; see
// TODOs above about restructring.
class TestMessage {
// ignore: always_specify_types, strict_raw_type
List? testList;
}

View File

@ -1,20 +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.
import 'package:pigeon/pigeon.dart';
enum EnumArgsState {
Pending,
Success,
Error,
}
class EnumArgsData {
EnumArgsState? state;
}
@HostApi()
abstract class EnumArgs2Host {
void foo(EnumArgsState state);
}

View File

@ -1,23 +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.
import 'package:pigeon/pigeon.dart';
@ConfigurePigeon(PigeonOptions(
objcOptions: ObjcOptions(
prefix: 'H2F',
),
))
class Host2FlutterSearchRequest {
String? query;
}
class Host2FlutterSearchReply {
String? result;
}
@FlutterApi()
abstract class H2FApi {
Host2FlutterSearchReply search(Host2FlutterSearchRequest request);
}

View File

@ -1,21 +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.
import 'package:pigeon/pigeon.dart';
class BridgeResponse {
int? result;
}
@HostApi()
abstract class BridgeApi1 {
@async
BridgeResponse call();
}
@HostApi()
abstract class BridgeApi2 {
@async
BridgeResponse call();
}

View File

@ -1,20 +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.
import 'package:pigeon/pigeon.dart';
class TestMessage {
// ignore: always_specify_types, strict_raw_type
List? testList;
}
@HostApi()
abstract class TestApi {
void test(TestMessage msg);
}
@FlutterApi()
abstract class EchoApi {
TestMessage echo(TestMessage msg);
}

View File

@ -1,14 +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.
import 'package:pigeon/pigeon.dart';
class VoidArgFlutterResult {
int? code;
}
@FlutterApi()
abstract class VoidArgApi {
VoidArgFlutterResult getCode();
}

View File

@ -1,14 +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.
import 'package:pigeon/pigeon.dart';
class VoidArgHostResult {
int? code;
}
@HostApi()
abstract class VoidArgHostApi {
VoidArgHostResult getCode();
}

View File

@ -1,14 +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.
import 'package:pigeon/pigeon.dart';
class VoidFlutterSetRequest {
int? value;
}
@FlutterApi()
abstract class VoidFlutterApi {
void setValue(VoidFlutterSetRequest request);
}

View File

@ -1,14 +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.
import 'package:pigeon/pigeon.dart';
class VoidHostSetRequest {
int? value;
}
@HostApi()
abstract class VoidHostApi {
void setValue(VoidHostSetRequest request);
}

View File

@ -708,6 +708,53 @@ public class CoreTests {
}
}
/**
* A data class containing a List, used in unit tests.
*
* <p>Generated class from Pigeon that represents data sent in messages.
*/
public static final class TestMessage {
private @Nullable List<Object> testList;
public @Nullable List<Object> getTestList() {
return testList;
}
public void setTestList(@Nullable List<Object> setterArg) {
this.testList = setterArg;
}
public static final class Builder {
private @Nullable List<Object> testList;
public @NonNull Builder setTestList(@Nullable List<Object> setterArg) {
this.testList = setterArg;
return this;
}
public @NonNull TestMessage build() {
TestMessage pigeonReturn = new TestMessage();
pigeonReturn.setTestList(testList);
return pigeonReturn;
}
}
@NonNull
ArrayList<Object> toList() {
ArrayList<Object> toListResult = new ArrayList<Object>(1);
toListResult.add(testList);
return toListResult;
}
static @NonNull TestMessage fromList(@NonNull ArrayList<Object> list) {
TestMessage pigeonResult = new TestMessage();
Object testList = list.get(0);
pigeonResult.setTestList((List<Object>) testList);
return pigeonResult;
}
}
public interface Result<T> {
void success(T result);
@ -728,6 +775,8 @@ public class CoreTests {
return AllNullableTypesWrapper.fromList((ArrayList<Object>) readValue(buffer));
case (byte) 130:
return AllTypes.fromList((ArrayList<Object>) readValue(buffer));
case (byte) 131:
return TestMessage.fromList((ArrayList<Object>) readValue(buffer));
default:
return super.readValueOfType(type, buffer);
}
@ -744,6 +793,9 @@ public class CoreTests {
} else if (value instanceof AllTypes) {
stream.write(130);
writeValue(stream, ((AllTypes) value).toList());
} else if (value instanceof TestMessage) {
stream.write(131);
writeValue(stream, ((TestMessage) value).toList());
} else {
super.writeValue(stream, value);
}
@ -3119,6 +3171,8 @@ public class CoreTests {
return AllNullableTypesWrapper.fromList((ArrayList<Object>) readValue(buffer));
case (byte) 130:
return AllTypes.fromList((ArrayList<Object>) readValue(buffer));
case (byte) 131:
return TestMessage.fromList((ArrayList<Object>) readValue(buffer));
default:
return super.readValueOfType(type, buffer);
}
@ -3135,6 +3189,9 @@ public class CoreTests {
} else if (value instanceof AllTypes) {
stream.write(130);
writeValue(stream, ((AllTypes) value).toList());
} else if (value instanceof TestMessage) {
stream.write(131);
writeValue(stream, ((TestMessage) value).toList());
} else {
super.writeValue(stream, value);
}
@ -3453,6 +3510,33 @@ public class CoreTests {
callback.reply(output);
});
}
/**
* A no-op function taking no arguments and returning no value, to sanity test basic
* asynchronous calling.
*/
public void noopAsync(Reply<Void> callback) {
BasicMessageChannel<Object> channel =
new BasicMessageChannel<>(
binaryMessenger,
"dev.flutter.pigeon.FlutterIntegrationCoreApi.noopAsync",
getCodec());
channel.send(null, channelReply -> callback.reply(null));
}
/** Returns the passed in generic Object asynchronously. */
public void echoAsyncString(@NonNull String aStringArg, Reply<String> callback) {
BasicMessageChannel<Object> channel =
new BasicMessageChannel<>(
binaryMessenger,
"dev.flutter.pigeon.FlutterIntegrationCoreApi.echoAsyncString",
getCodec());
channel.send(
new ArrayList<Object>(Collections.singletonList(aStringArg)),
channelReply -> {
@SuppressWarnings("ConstantConditions")
String output = (String) channelReply;
callback.reply(output);
});
}
}
/**
* An API that can be implemented for minimal, compile-only tests.
@ -3492,4 +3576,154 @@ public class CoreTests {
}
}
}
/**
* A simple API implemented in some unit tests.
*
* <p>Generated interface from Pigeon that represents a handler of messages from Flutter.
*/
public interface HostSmallApi {
void echo(@NonNull String aString, Result<String> result);
void voidVoid(Result<Void> result);
/** The codec used by HostSmallApi. */
static MessageCodec<Object> getCodec() {
return new StandardMessageCodec();
}
/** Sets up an instance of `HostSmallApi` to handle messages through the `binaryMessenger`. */
static void setup(BinaryMessenger binaryMessenger, HostSmallApi api) {
{
BasicMessageChannel<Object> channel =
new BasicMessageChannel<>(
binaryMessenger, "dev.flutter.pigeon.HostSmallApi.echo", getCodec());
if (api != null) {
channel.setMessageHandler(
(message, reply) -> {
ArrayList<Object> wrapped = new ArrayList<Object>();
try {
ArrayList<Object> args = (ArrayList<Object>) message;
assert args != null;
String aStringArg = (String) args.get(0);
if (aStringArg == null) {
throw new NullPointerException("aStringArg unexpectedly null.");
}
Result<String> resultCallback =
new Result<String>() {
public void success(String result) {
wrapped.add(0, result);
reply.reply(wrapped);
}
public void error(Throwable error) {
ArrayList<Object> wrappedError = wrapError(error);
reply.reply(wrappedError);
}
};
api.echo(aStringArg, resultCallback);
} catch (Error | RuntimeException exception) {
ArrayList<Object> wrappedError = wrapError(exception);
reply.reply(wrappedError);
}
});
} else {
channel.setMessageHandler(null);
}
}
{
BasicMessageChannel<Object> channel =
new BasicMessageChannel<>(
binaryMessenger, "dev.flutter.pigeon.HostSmallApi.voidVoid", getCodec());
if (api != null) {
channel.setMessageHandler(
(message, reply) -> {
ArrayList<Object> wrapped = new ArrayList<Object>();
try {
Result<Void> resultCallback =
new Result<Void>() {
public void success(Void result) {
wrapped.add(0, null);
reply.reply(wrapped);
}
public void error(Throwable error) {
ArrayList<Object> wrappedError = wrapError(error);
reply.reply(wrappedError);
}
};
api.voidVoid(resultCallback);
} catch (Error | RuntimeException exception) {
ArrayList<Object> wrappedError = wrapError(exception);
reply.reply(wrappedError);
}
});
} else {
channel.setMessageHandler(null);
}
}
}
}
private static class FlutterSmallApiCodec extends StandardMessageCodec {
public static final FlutterSmallApiCodec INSTANCE = new FlutterSmallApiCodec();
private FlutterSmallApiCodec() {}
@Override
protected Object readValueOfType(byte type, @NonNull ByteBuffer buffer) {
switch (type) {
case (byte) 128:
return TestMessage.fromList((ArrayList<Object>) readValue(buffer));
default:
return super.readValueOfType(type, buffer);
}
}
@Override
protected void writeValue(@NonNull ByteArrayOutputStream stream, Object value) {
if (value instanceof TestMessage) {
stream.write(128);
writeValue(stream, ((TestMessage) value).toList());
} else {
super.writeValue(stream, value);
}
}
}
/**
* A simple API called in some unit tests.
*
* <p>Generated class from Pigeon that represents Flutter messages that can be called from Java.
*/
public static class FlutterSmallApi {
private final BinaryMessenger binaryMessenger;
public FlutterSmallApi(BinaryMessenger argBinaryMessenger) {
this.binaryMessenger = argBinaryMessenger;
}
/** Public interface for sending reply. */
public interface Reply<T> {
void reply(T reply);
}
/** The codec used by FlutterSmallApi. */
static MessageCodec<Object> getCodec() {
return FlutterSmallApiCodec.INSTANCE;
}
public void echoWrappedList(@NonNull TestMessage msgArg, Reply<TestMessage> callback) {
BasicMessageChannel<Object> channel =
new BasicMessageChannel<>(
binaryMessenger, "dev.flutter.pigeon.FlutterSmallApi.echoWrappedList", getCodec());
channel.send(
new ArrayList<Object>(Collections.singletonList(msgArg)),
channelReply -> {
@SuppressWarnings("ConstantConditions")
TestMessage output = (TestMessage) channelReply;
callback.reply(output);
});
}
}
}

View File

@ -7,7 +7,8 @@ package com.example.alternate_language_test_plugin;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
import com.example.alternate_language_test_plugin.AsyncHandlers.*;
import androidx.annotation.NonNull;
import com.example.alternate_language_test_plugin.CoreTests.*;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugin.common.MessageCodec;
import java.nio.ByteBuffer;
@ -16,9 +17,9 @@ import org.junit.Test;
import org.mockito.ArgumentCaptor;
public class AsyncTest {
class Success implements Api2Host {
class Success implements HostSmallApi {
@Override
public void calculate(Value value, Result<Value> result) {
public void echo(@NonNull String value, Result<String> result) {
result.success(value);
}
@ -28,9 +29,9 @@ public class AsyncTest {
}
}
class Error implements Api2Host {
class Error implements HostSmallApi {
@Override
public void calculate(Value value, Result<Value> result) {
public void echo(@NonNull String value, Result<String> result) {
result.error(new Exception("error"));
}
@ -44,13 +45,13 @@ public class AsyncTest {
public void asyncSuccess() {
Success api = new Success();
BinaryMessenger binaryMessenger = mock(BinaryMessenger.class);
Api2Host.setup(binaryMessenger, api);
HostSmallApi.setup(binaryMessenger, api);
ArgumentCaptor<BinaryMessenger.BinaryMessageHandler> handler =
ArgumentCaptor.forClass(BinaryMessenger.BinaryMessageHandler.class);
verify(binaryMessenger).setMessageHandler(eq("dev.flutter.pigeon.Api2Host.calculate"), any());
verify(binaryMessenger).setMessageHandler(eq("dev.flutter.pigeon.HostSmallApi.echo"), any());
verify(binaryMessenger)
.setMessageHandler(eq("dev.flutter.pigeon.Api2Host.voidVoid"), handler.capture());
MessageCodec<Object> codec = Pigeon.AndroidApi.getCodec();
.setMessageHandler(eq("dev.flutter.pigeon.HostSmallApi.voidVoid"), handler.capture());
MessageCodec<Object> codec = HostSmallApi.getCodec();
ByteBuffer message = codec.encodeMessage(null);
Boolean[] didCall = {false};
handler
@ -71,13 +72,13 @@ public class AsyncTest {
public void asyncError() {
Error api = new Error();
BinaryMessenger binaryMessenger = mock(BinaryMessenger.class);
Api2Host.setup(binaryMessenger, api);
HostSmallApi.setup(binaryMessenger, api);
ArgumentCaptor<BinaryMessenger.BinaryMessageHandler> handler =
ArgumentCaptor.forClass(BinaryMessenger.BinaryMessageHandler.class);
verify(binaryMessenger).setMessageHandler(eq("dev.flutter.pigeon.Api2Host.calculate"), any());
verify(binaryMessenger).setMessageHandler(eq("dev.flutter.pigeon.HostSmallApi.echo"), any());
verify(binaryMessenger)
.setMessageHandler(eq("dev.flutter.pigeon.Api2Host.voidVoid"), handler.capture());
MessageCodec<Object> codec = Pigeon.AndroidApi.getCodec();
.setMessageHandler(eq("dev.flutter.pigeon.HostSmallApi.voidVoid"), handler.capture());
MessageCodec<Object> codec = HostSmallApi.getCodec();
ByteBuffer message = codec.encodeMessage(null);
Boolean[] didCall = {false};
handler

View File

@ -7,8 +7,8 @@ package com.example.alternate_language_test_plugin;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
import com.example.alternate_language_test_plugin.PigeonList.EchoApi;
import com.example.alternate_language_test_plugin.PigeonList.TestMessage;
import com.example.alternate_language_test_plugin.CoreTests.FlutterSmallApi;
import com.example.alternate_language_test_plugin.CoreTests.TestMessage;
import io.flutter.plugin.common.BinaryMessenger;
import java.nio.ByteBuffer;
import java.util.ArrayList;
@ -28,17 +28,17 @@ public class ListTest {
ByteBuffer message = invocation.getArgument(1);
BinaryMessenger.BinaryReply reply = invocation.getArgument(2);
message.position(0);
ArrayList args = (ArrayList) EchoApi.getCodec().decodeMessage(message);
ByteBuffer replyData = EchoApi.getCodec().encodeMessage(args.get(0));
ArrayList args = (ArrayList) FlutterSmallApi.getCodec().decodeMessage(message);
ByteBuffer replyData = FlutterSmallApi.getCodec().encodeMessage(args.get(0));
replyData.position(0);
reply.reply(replyData);
return null;
})
.when(binaryMessenger)
.send(anyString(), any(), any());
EchoApi api = new EchoApi(binaryMessenger);
FlutterSmallApi api = new FlutterSmallApi(binaryMessenger);
boolean[] didCall = {false};
api.echo(
api.echoWrappedList(
top,
(result) -> {
didCall[0] = true;

View File

@ -7,63 +7,40 @@ package com.example.alternate_language_test_plugin;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
import com.example.alternate_language_test_plugin.CoreTests.HostSmallApi;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugin.common.MessageCodec;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
public class PigeonTest {
@Test
public void toListAndBack() {
Pigeon.AndroidSetRequest request = new Pigeon.AndroidSetRequest();
request.setValue(1234l);
request.setState(Pigeon.AndroidLoadingState.COMPLETE);
ArrayList<Object> list = request.toList();
Pigeon.AndroidSetRequest readRequest = Pigeon.AndroidSetRequest.fromList(list);
assertEquals(request.getValue(), readRequest.getValue());
assertEquals(request.getState(), readRequest.getState());
}
@Test
public void toListAndBackNested() {
Pigeon.AndroidNestedRequest nested = new Pigeon.AndroidNestedRequest();
Pigeon.AndroidSetRequest request = new Pigeon.AndroidSetRequest();
request.setValue(1234l);
request.setState(Pigeon.AndroidLoadingState.COMPLETE);
nested.setRequest(request);
ArrayList<Object> list = nested.toList();
Pigeon.AndroidNestedRequest readNested = Pigeon.AndroidNestedRequest.fromList(list);
assertEquals(nested.getRequest().getValue(), readNested.getRequest().getValue());
assertEquals(nested.getRequest().getState(), readNested.getRequest().getState());
}
@Test
public void clearsHandler() {
Pigeon.AndroidApi mockApi = mock(Pigeon.AndroidApi.class);
HostSmallApi mockApi = mock(HostSmallApi.class);
BinaryMessenger binaryMessenger = mock(BinaryMessenger.class);
Pigeon.AndroidApi.setup(binaryMessenger, mockApi);
HostSmallApi.setup(binaryMessenger, mockApi);
ArgumentCaptor<String> channelName = ArgumentCaptor.forClass(String.class);
verify(binaryMessenger).setMessageHandler(channelName.capture(), isNotNull());
Pigeon.AndroidApi.setup(binaryMessenger, null);
verify(binaryMessenger).setMessageHandler(eq(channelName.getValue()), isNull());
verify(binaryMessenger, atLeast(1)).setMessageHandler(channelName.capture(), isNotNull());
HostSmallApi.setup(binaryMessenger, null);
verify(binaryMessenger, atLeast(1)).setMessageHandler(eq(channelName.getValue()), isNull());
}
/** Causes an exception in the handler by passing in null when a AndroidSetRequest is expected. */
/** Causes an exception in the handler by passing in null when a non-null value is expected. */
@Test
public void errorMessage() {
Pigeon.AndroidApi mockApi = mock(Pigeon.AndroidApi.class);
HostSmallApi mockApi = mock(HostSmallApi.class);
BinaryMessenger binaryMessenger = mock(BinaryMessenger.class);
Pigeon.AndroidApi.setup(binaryMessenger, mockApi);
HostSmallApi.setup(binaryMessenger, mockApi);
ArgumentCaptor<BinaryMessenger.BinaryMessageHandler> handler =
ArgumentCaptor.forClass(BinaryMessenger.BinaryMessageHandler.class);
verify(binaryMessenger).setMessageHandler(anyString(), handler.capture());
MessageCodec<Object> codec = Pigeon.AndroidApi.getCodec();
verify(binaryMessenger, atLeast(1)).setMessageHandler(anyString(), handler.capture());
MessageCodec<Object> codec = HostSmallApi.getCodec();
ByteBuffer message = codec.encodeMessage(null);
handler
.getValue()
.getAllValues()
.get(0) // "echo" is the first method.
.onMessage(
message,
(bytes) -> {
@ -77,44 +54,4 @@ public class PigeonTest {
assertTrue(details.contains("Stacktrace:"));
});
}
@Test
public void callsVoidMethod() {
Pigeon.AndroidApi mockApi = mock(Pigeon.AndroidApi.class);
BinaryMessenger binaryMessenger = mock(BinaryMessenger.class);
Pigeon.AndroidApi.setup(binaryMessenger, mockApi);
ArgumentCaptor<BinaryMessenger.BinaryMessageHandler> handler =
ArgumentCaptor.forClass(BinaryMessenger.BinaryMessageHandler.class);
verify(binaryMessenger).setMessageHandler(anyString(), handler.capture());
Pigeon.AndroidSetRequest request = new Pigeon.AndroidSetRequest();
request.setValue(1234l);
request.setState(Pigeon.AndroidLoadingState.COMPLETE);
MessageCodec<Object> codec = Pigeon.AndroidApi.getCodec();
ByteBuffer message = codec.encodeMessage(new ArrayList<Object>(Arrays.asList(request)));
message.rewind();
handler
.getValue()
.onMessage(
message,
(bytes) -> {
bytes.rewind();
@SuppressWarnings("unchecked")
ArrayList wrapped = (ArrayList) codec.decodeMessage(bytes);
assertTrue(wrapped.size() == 1);
assertNull(wrapped.get(0));
});
ArgumentCaptor<Pigeon.AndroidSetRequest> receivedRequest =
ArgumentCaptor.forClass(Pigeon.AndroidSetRequest.class);
verify(mockApi).setValue(receivedRequest.capture());
assertEquals(request.getValue(), receivedRequest.getValue().getValue());
}
@Test
public void encodeWithNullField() {
Pigeon.AndroidNestedRequest request = new Pigeon.AndroidNestedRequest();
request.setContext("hello");
MessageCodec<Object> codec = Pigeon.AndroidNestedApi.getCodec();
ByteBuffer message = codec.encodeMessage(request);
assertNotNull(message);
}
}

View File

@ -10,26 +10,18 @@
#import "MockBinaryMessenger.h"
///////////////////////////////////////////////////////////////////////////////////////////
@interface Value ()
+ (Value *)fromList:(NSArray *)list;
- (NSArray *)toList;
@end
///////////////////////////////////////////////////////////////////////////////////////////
@interface MockApi2Host : NSObject <Api2Host>
@property(nonatomic, copy) NSNumber *output;
@interface MockHostSmallApi : NSObject <HostSmallApi>
@property(nonatomic, copy) NSString *output;
@property(nonatomic, retain) FlutterError *voidVoidError;
@end
///////////////////////////////////////////////////////////////////////////////////////////
@implementation MockApi2Host
@implementation MockHostSmallApi
- (void)calculateValue:(Value *)input
completion:(nonnull void (^)(Value *_Nullable, FlutterError *_Nullable))completion {
- (void)echoString:(NSString *)value
completion:(nonnull void (^)(NSString *_Nullable, FlutterError *_Nullable))completion {
if (self.output) {
Value *output = [[Value alloc] init];
output.number = self.output;
completion(output, nil);
completion(self.output, nil);
} else {
completion(nil, [FlutterError errorWithCode:@"hey" message:@"ho" details:nil]);
}
@ -50,15 +42,15 @@
- (void)testAsyncHost2Flutter {
MockBinaryMessenger *binaryMessenger =
[[MockBinaryMessenger alloc] initWithCodec:Api2FlutterGetCodec()];
binaryMessenger.result = [Value makeWithNumber:@(2)];
Api2Flutter *api2Flutter = [[Api2Flutter alloc] initWithBinaryMessenger:binaryMessenger];
Value *input = [[Value alloc] init];
input.number = @(1);
XCTestExpectation *expectation = [self expectationWithDescription:@"calculate callback"];
[api2Flutter calculateValue:input
completion:^(Value *_Nonnull output, FlutterError *_Nullable error) {
XCTAssertEqual(output.number.intValue, 2);
[[MockBinaryMessenger alloc] initWithCodec:FlutterIntegrationCoreApiGetCodec()];
NSString *value = @"Test";
binaryMessenger.result = value;
FlutterIntegrationCoreApi *flutterApi =
[[FlutterIntegrationCoreApi alloc] initWithBinaryMessenger:binaryMessenger];
XCTestExpectation *expectation = [self expectationWithDescription:@"echo callback"];
[flutterApi echoAsyncString:value
completion:^(NSString *_Nonnull output, FlutterError *_Nullable error) {
XCTAssertEqualObjects(output, value);
[expectation fulfill];
}];
[self waitForExpectationsWithTimeout:1.0 handler:nil];
@ -66,11 +58,10 @@
- (void)testAsyncFlutter2HostVoidVoid {
MockBinaryMessenger *binaryMessenger =
[[MockBinaryMessenger alloc] initWithCodec:Api2HostGetCodec()];
MockApi2Host *mockApi2Host = [[MockApi2Host alloc] init];
mockApi2Host.output = @(2);
Api2HostSetup(binaryMessenger, mockApi2Host);
NSString *channelName = @"dev.flutter.pigeon.Api2Host.voidVoid";
[[MockBinaryMessenger alloc] initWithCodec:HostSmallApiGetCodec()];
MockHostSmallApi *mockHostSmallApi = [[MockHostSmallApi alloc] init];
HostSmallApiSetup(binaryMessenger, mockHostSmallApi);
NSString *channelName = @"dev.flutter.pigeon.HostSmallApi.voidVoid";
XCTAssertNotNil(binaryMessenger.handlers[channelName]);
XCTestExpectation *expectation = [self expectationWithDescription:@"voidvoid callback"];
@ -84,18 +75,20 @@
- (void)testAsyncFlutter2HostVoidVoidError {
MockBinaryMessenger *binaryMessenger =
[[MockBinaryMessenger alloc] initWithCodec:Api2HostGetCodec()];
MockApi2Host *mockApi2Host = [[MockApi2Host alloc] init];
mockApi2Host.voidVoidError = [FlutterError errorWithCode:@"code" message:@"message" details:nil];
Api2HostSetup(binaryMessenger, mockApi2Host);
NSString *channelName = @"dev.flutter.pigeon.Api2Host.voidVoid";
[[MockBinaryMessenger alloc] initWithCodec:HostSmallApiGetCodec()];
MockHostSmallApi *mockHostSmallApi = [[MockHostSmallApi alloc] init];
mockHostSmallApi.voidVoidError = [FlutterError errorWithCode:@"code"
message:@"message"
details:nil];
HostSmallApiSetup(binaryMessenger, mockHostSmallApi);
NSString *channelName = @"dev.flutter.pigeon.HostSmallApi.voidVoid";
XCTAssertNotNil(binaryMessenger.handlers[channelName]);
XCTestExpectation *expectation = [self expectationWithDescription:@"voidvoid callback"];
binaryMessenger.handlers[channelName](nil, ^(NSData *data) {
NSArray *outputList = [binaryMessenger.codec decode:data];
XCTAssertNotNil(outputList);
XCTAssertEqualObjects(outputList[0], mockApi2Host.voidVoidError.code);
XCTAssertEqualObjects(outputList[0], mockHostSmallApi.voidVoidError.code);
[expectation fulfill];
});
[self waitForExpectationsWithTimeout:1.0 handler:nil];
@ -103,21 +96,20 @@
- (void)testAsyncFlutter2Host {
MockBinaryMessenger *binaryMessenger =
[[MockBinaryMessenger alloc] initWithCodec:Api2HostGetCodec()];
MockApi2Host *mockApi2Host = [[MockApi2Host alloc] init];
mockApi2Host.output = @(2);
Api2HostSetup(binaryMessenger, mockApi2Host);
NSString *channelName = @"dev.flutter.pigeon.Api2Host.calculate";
[[MockBinaryMessenger alloc] initWithCodec:HostSmallApiGetCodec()];
MockHostSmallApi *mockHostSmallApi = [[MockHostSmallApi alloc] init];
NSString *value = @"Test";
mockHostSmallApi.output = value;
HostSmallApiSetup(binaryMessenger, mockHostSmallApi);
NSString *channelName = @"dev.flutter.pigeon.HostSmallApi.echo";
XCTAssertNotNil(binaryMessenger.handlers[channelName]);
Value *input = [[Value alloc] init];
input.number = @(1);
NSData *inputEncoded = [binaryMessenger.codec encode:@[ input ]];
XCTestExpectation *expectation = [self expectationWithDescription:@"calculate callback"];
NSData *inputEncoded = [binaryMessenger.codec encode:@[ value ]];
XCTestExpectation *expectation = [self expectationWithDescription:@"echo callback"];
binaryMessenger.handlers[channelName](inputEncoded, ^(NSData *data) {
NSArray *outputList = [binaryMessenger.codec decode:data];
Value *output = outputList[0];
XCTAssertEqual(output.number.intValue, 2);
NSString *output = outputList[0];
XCTAssertEqualObjects(output, value);
[expectation fulfill];
});
[self waitForExpectationsWithTimeout:1.0 handler:nil];
@ -125,16 +117,14 @@
- (void)testAsyncFlutter2HostError {
MockBinaryMessenger *binaryMessenger =
[[MockBinaryMessenger alloc] initWithCodec:Api2HostGetCodec()];
MockApi2Host *mockApi2Host = [[MockApi2Host alloc] init];
Api2HostSetup(binaryMessenger, mockApi2Host);
NSString *channelName = @"dev.flutter.pigeon.Api2Host.calculate";
[[MockBinaryMessenger alloc] initWithCodec:HostSmallApiGetCodec()];
MockHostSmallApi *mockHostSmallApi = [[MockHostSmallApi alloc] init];
HostSmallApiSetup(binaryMessenger, mockHostSmallApi);
NSString *channelName = @"dev.flutter.pigeon.HostSmallApi.echo";
XCTAssertNotNil(binaryMessenger.handlers[channelName]);
Value *input = [[Value alloc] init];
input.number = @(1);
NSData *inputEncoded = [binaryMessenger.codec encode:@[ [input toList] ]];
XCTestExpectation *expectation = [self expectationWithDescription:@"calculate callback"];
NSData *inputEncoded = [binaryMessenger.codec encode:@[ @"Test" ]];
XCTestExpectation *expectation = [self expectationWithDescription:@"echo callback"];
binaryMessenger.handlers[channelName](inputEncoded, ^(NSData *data) {
NSArray *outputList = [binaryMessenger.codec decode:data];
XCTAssertNotNil(outputList);

View File

@ -22,16 +22,16 @@
inside.testList = @[ @1, @2, @3 ];
top.testList = @[ inside ];
EchoBinaryMessenger *binaryMessenger =
[[EchoBinaryMessenger alloc] initWithCodec:EchoApiGetCodec()];
EchoApi *api = [[EchoApi alloc] initWithBinaryMessenger:binaryMessenger];
[[EchoBinaryMessenger alloc] initWithCodec:FlutterSmallApiGetCodec()];
FlutterSmallApi *api = [[FlutterSmallApi alloc] initWithBinaryMessenger:binaryMessenger];
XCTestExpectation *expectation = [self expectationWithDescription:@"callback"];
[api echoMsg:top
completion:^(TestMessage *_Nonnull result, FlutterError *_Nullable err) {
XCTAssertEqual(1u, result.testList.count);
XCTAssertTrue([result.testList[0] isKindOfClass:[TestMessage class]]);
XCTAssertEqualObjects(inside.testList, [result.testList[0] testList]);
[expectation fulfill];
}];
[api echoWrappedList:top
completion:^(TestMessage *_Nonnull result, FlutterError *_Nullable err) {
XCTAssertEqual(1u, result.testList.count);
XCTAssertTrue([result.testList[0] isKindOfClass:[TestMessage class]]);
XCTAssertEqualObjects(inside.testList, [result.testList[0] testList]);
[expectation fulfill];
}];
[self waitForExpectations:@[ expectation ] timeout:1.0];
}

View File

@ -23,6 +23,7 @@ typedef NS_ENUM(NSUInteger, AnEnum) {
@class AllTypes;
@class AllNullableTypes;
@class AllNullableTypesWrapper;
@class TestMessage;
@interface AllTypes : NSObject
/// `init` unavailable to enforce nonnull fields, see the `make` class method.
@ -91,6 +92,12 @@ typedef NS_ENUM(NSUInteger, AnEnum) {
@property(nonatomic, strong) AllNullableTypes *values;
@end
/// A data class containing a List, used in unit tests.
@interface TestMessage : NSObject
+ (instancetype)makeWithTestList:(nullable NSArray *)testList;
@property(nonatomic, strong, nullable) NSArray *testList;
@end
/// The codec used by HostIntegrationCoreApi.
NSObject<FlutterMessageCodec> *HostIntegrationCoreApiGetCodec(void);
@ -388,6 +395,12 @@ NSObject<FlutterMessageCodec> *FlutterIntegrationCoreApiGetCodec(void);
- (void)echoNullableMap:(nullable NSDictionary<NSString *, id> *)aMap
completion:(void (^)(NSDictionary<NSString *, id> *_Nullable,
FlutterError *_Nullable))completion;
/// A no-op function taking no arguments and returning no value, to sanity
/// test basic asynchronous calling.
- (void)noopAsyncWithCompletion:(void (^)(FlutterError *_Nullable))completion;
/// Returns the passed in generic Object asynchronously.
- (void)echoAsyncString:(NSString *)aString
completion:(void (^)(NSString *_Nullable, FlutterError *_Nullable))completion;
@end
/// The codec used by HostTrivialApi.
@ -401,4 +414,27 @@ NSObject<FlutterMessageCodec> *HostTrivialApiGetCodec(void);
extern void HostTrivialApiSetup(id<FlutterBinaryMessenger> binaryMessenger,
NSObject<HostTrivialApi> *_Nullable api);
/// The codec used by HostSmallApi.
NSObject<FlutterMessageCodec> *HostSmallApiGetCodec(void);
/// A simple API implemented in some unit tests.
@protocol HostSmallApi
- (void)echoString:(NSString *)aString
completion:(void (^)(NSString *_Nullable, FlutterError *_Nullable))completion;
- (void)voidVoidWithCompletion:(void (^)(FlutterError *_Nullable))completion;
@end
extern void HostSmallApiSetup(id<FlutterBinaryMessenger> binaryMessenger,
NSObject<HostSmallApi> *_Nullable api);
/// The codec used by FlutterSmallApi.
NSObject<FlutterMessageCodec> *FlutterSmallApiGetCodec(void);
/// A simple API called in some unit tests.
@interface FlutterSmallApi : NSObject
- (instancetype)initWithBinaryMessenger:(id<FlutterBinaryMessenger>)binaryMessenger;
- (void)echoWrappedList:(TestMessage *)msg
completion:(void (^)(TestMessage *_Nullable, FlutterError *_Nullable))completion;
@end
NS_ASSUME_NONNULL_END

View File

@ -43,6 +43,12 @@ static id GetNullableObjectAtIndex(NSArray *array, NSInteger key) {
- (NSArray *)toList;
@end
@interface TestMessage ()
+ (TestMessage *)fromList:(NSArray *)list;
+ (nullable TestMessage *)nullableFromList:(NSArray *)list;
- (NSArray *)toList;
@end
@implementation AllTypes
+ (instancetype)makeWithABool:(NSNumber *)aBool
anInt:(NSNumber *)anInt
@ -210,6 +216,27 @@ static id GetNullableObjectAtIndex(NSArray *array, NSInteger key) {
}
@end
@implementation TestMessage
+ (instancetype)makeWithTestList:(nullable NSArray *)testList {
TestMessage *pigeonResult = [[TestMessage alloc] init];
pigeonResult.testList = testList;
return pigeonResult;
}
+ (TestMessage *)fromList:(NSArray *)list {
TestMessage *pigeonResult = [[TestMessage alloc] init];
pigeonResult.testList = GetNullableObjectAtIndex(list, 0);
return pigeonResult;
}
+ (nullable TestMessage *)nullableFromList:(NSArray *)list {
return (list) ? [TestMessage fromList:list] : nil;
}
- (NSArray *)toList {
return @[
(self.testList ?: [NSNull null]),
];
}
@end
@interface HostIntegrationCoreApiCodecReader : FlutterStandardReader
@end
@implementation HostIntegrationCoreApiCodecReader
@ -221,6 +248,8 @@ static id GetNullableObjectAtIndex(NSArray *array, NSInteger key) {
return [AllNullableTypesWrapper fromList:[self readValue]];
case 130:
return [AllTypes fromList:[self readValue]];
case 131:
return [TestMessage fromList:[self readValue]];
default:
return [super readValueOfType:type];
}
@ -240,6 +269,9 @@ static id GetNullableObjectAtIndex(NSArray *array, NSInteger key) {
} else if ([value isKindOfClass:[AllTypes class]]) {
[self writeByte:130];
[self writeValue:[value toList]];
} else if ([value isKindOfClass:[TestMessage class]]) {
[self writeByte:131];
[self writeValue:[value toList]];
} else {
[super writeValue:value];
}
@ -1715,6 +1747,8 @@ void HostIntegrationCoreApiSetup(id<FlutterBinaryMessenger> binaryMessenger,
return [AllNullableTypesWrapper fromList:[self readValue]];
case 130:
return [AllTypes fromList:[self readValue]];
case 131:
return [TestMessage fromList:[self readValue]];
default:
return [super readValueOfType:type];
}
@ -1734,6 +1768,9 @@ void HostIntegrationCoreApiSetup(id<FlutterBinaryMessenger> binaryMessenger,
} else if ([value isKindOfClass:[AllTypes class]]) {
[self writeByte:130];
[self writeValue:[value toList]];
} else if ([value isKindOfClass:[TestMessage class]]) {
[self writeByte:131];
[self writeValue:[value toList]];
} else {
[super writeValue:value];
}
@ -2022,6 +2059,28 @@ NSObject<FlutterMessageCodec> *FlutterIntegrationCoreApiGetCodec() {
completion(output, nil);
}];
}
- (void)noopAsyncWithCompletion:(void (^)(FlutterError *_Nullable))completion {
FlutterBasicMessageChannel *channel = [FlutterBasicMessageChannel
messageChannelWithName:@"dev.flutter.pigeon.FlutterIntegrationCoreApi.noopAsync"
binaryMessenger:self.binaryMessenger
codec:FlutterIntegrationCoreApiGetCodec()];
[channel sendMessage:nil
reply:^(id reply) {
completion(nil);
}];
}
- (void)echoAsyncString:(NSString *)arg_aString
completion:(void (^)(NSString *_Nullable, FlutterError *_Nullable))completion {
FlutterBasicMessageChannel *channel = [FlutterBasicMessageChannel
messageChannelWithName:@"dev.flutter.pigeon.FlutterIntegrationCoreApi.echoAsyncString"
binaryMessenger:self.binaryMessenger
codec:FlutterIntegrationCoreApiGetCodec()];
[channel sendMessage:@[ arg_aString ?: [NSNull null] ]
reply:^(id reply) {
NSString *output = reply;
completion(output, nil);
}];
}
@end
NSObject<FlutterMessageCodec> *HostTrivialApiGetCodec() {
@ -2050,3 +2109,123 @@ void HostTrivialApiSetup(id<FlutterBinaryMessenger> binaryMessenger,
}
}
}
NSObject<FlutterMessageCodec> *HostSmallApiGetCodec() {
static FlutterStandardMessageCodec *sSharedObject = nil;
sSharedObject = [FlutterStandardMessageCodec sharedInstance];
return sSharedObject;
}
void HostSmallApiSetup(id<FlutterBinaryMessenger> binaryMessenger, NSObject<HostSmallApi> *api) {
{
FlutterBasicMessageChannel *channel =
[[FlutterBasicMessageChannel alloc] initWithName:@"dev.flutter.pigeon.HostSmallApi.echo"
binaryMessenger:binaryMessenger
codec:HostSmallApiGetCodec()];
if (api) {
NSCAssert([api respondsToSelector:@selector(echoString:completion:)],
@"HostSmallApi api (%@) doesn't respond to @selector(echoString:completion:)", api);
[channel setMessageHandler:^(id _Nullable message, FlutterReply callback) {
NSArray *args = message;
NSString *arg_aString = GetNullableObjectAtIndex(args, 0);
[api echoString:arg_aString
completion:^(NSString *_Nullable output, FlutterError *_Nullable error) {
callback(wrapResult(output, error));
}];
}];
} else {
[channel setMessageHandler:nil];
}
}
{
FlutterBasicMessageChannel *channel =
[[FlutterBasicMessageChannel alloc] initWithName:@"dev.flutter.pigeon.HostSmallApi.voidVoid"
binaryMessenger:binaryMessenger
codec:HostSmallApiGetCodec()];
if (api) {
NSCAssert([api respondsToSelector:@selector(voidVoidWithCompletion:)],
@"HostSmallApi api (%@) doesn't respond to @selector(voidVoidWithCompletion:)",
api);
[channel setMessageHandler:^(id _Nullable message, FlutterReply callback) {
[api voidVoidWithCompletion:^(FlutterError *_Nullable error) {
callback(wrapResult(nil, error));
}];
}];
} else {
[channel setMessageHandler:nil];
}
}
}
@interface FlutterSmallApiCodecReader : FlutterStandardReader
@end
@implementation FlutterSmallApiCodecReader
- (nullable id)readValueOfType:(UInt8)type {
switch (type) {
case 128:
return [TestMessage fromList:[self readValue]];
default:
return [super readValueOfType:type];
}
}
@end
@interface FlutterSmallApiCodecWriter : FlutterStandardWriter
@end
@implementation FlutterSmallApiCodecWriter
- (void)writeValue:(id)value {
if ([value isKindOfClass:[TestMessage class]]) {
[self writeByte:128];
[self writeValue:[value toList]];
} else {
[super writeValue:value];
}
}
@end
@interface FlutterSmallApiCodecReaderWriter : FlutterStandardReaderWriter
@end
@implementation FlutterSmallApiCodecReaderWriter
- (FlutterStandardWriter *)writerWithData:(NSMutableData *)data {
return [[FlutterSmallApiCodecWriter alloc] initWithData:data];
}
- (FlutterStandardReader *)readerWithData:(NSData *)data {
return [[FlutterSmallApiCodecReader alloc] initWithData:data];
}
@end
NSObject<FlutterMessageCodec> *FlutterSmallApiGetCodec() {
static FlutterStandardMessageCodec *sSharedObject = nil;
static dispatch_once_t sPred = 0;
dispatch_once(&sPred, ^{
FlutterSmallApiCodecReaderWriter *readerWriter =
[[FlutterSmallApiCodecReaderWriter alloc] init];
sSharedObject = [FlutterStandardMessageCodec codecWithReaderWriter:readerWriter];
});
return sSharedObject;
}
@interface FlutterSmallApi ()
@property(nonatomic, strong) NSObject<FlutterBinaryMessenger> *binaryMessenger;
@end
@implementation FlutterSmallApi
- (instancetype)initWithBinaryMessenger:(NSObject<FlutterBinaryMessenger> *)binaryMessenger {
self = [super init];
if (self) {
_binaryMessenger = binaryMessenger;
}
return self;
}
- (void)echoWrappedList:(TestMessage *)arg_msg
completion:(void (^)(TestMessage *_Nullable, FlutterError *_Nullable))completion {
FlutterBasicMessageChannel *channel = [FlutterBasicMessageChannel
messageChannelWithName:@"dev.flutter.pigeon.FlutterSmallApi.echoWrappedList"
binaryMessenger:self.binaryMessenger
codec:FlutterSmallApiGetCodec()];
[channel sendMessage:@[ arg_msg ?: [NSNull null] ]
reply:^(id reply) {
TestMessage *output = reply;
completion(output, nil);
}];
}
@end

View File

@ -199,6 +199,28 @@ class AllNullableTypesWrapper {
}
}
/// A data class containing a List, used in unit tests.
class TestMessage {
TestMessage({
this.testList,
});
List<Object?>? testList;
Object encode() {
return <Object?>[
testList,
];
}
static TestMessage decode(Object result) {
result as List<Object?>;
return TestMessage(
testList: result[0] as List<Object?>?,
);
}
}
class _HostIntegrationCoreApiCodec extends StandardMessageCodec {
const _HostIntegrationCoreApiCodec();
@override
@ -212,6 +234,9 @@ class _HostIntegrationCoreApiCodec extends StandardMessageCodec {
} else if (value is AllTypes) {
buffer.putUint8(130);
writeValue(buffer, value.encode());
} else if (value is TestMessage) {
buffer.putUint8(131);
writeValue(buffer, value.encode());
} else {
super.writeValue(buffer, value);
}
@ -226,6 +251,8 @@ class _HostIntegrationCoreApiCodec extends StandardMessageCodec {
return AllNullableTypesWrapper.decode(readValue(buffer)!);
case 130:
return AllTypes.decode(readValue(buffer)!);
case 131:
return TestMessage.decode(readValue(buffer)!);
default:
return super.readValueOfType(type, buffer);
}
@ -1897,6 +1924,9 @@ class _FlutterIntegrationCoreApiCodec extends StandardMessageCodec {
} else if (value is AllTypes) {
buffer.putUint8(130);
writeValue(buffer, value.encode());
} else if (value is TestMessage) {
buffer.putUint8(131);
writeValue(buffer, value.encode());
} else {
super.writeValue(buffer, value);
}
@ -1911,6 +1941,8 @@ class _FlutterIntegrationCoreApiCodec extends StandardMessageCodec {
return AllNullableTypesWrapper.decode(readValue(buffer)!);
case 130:
return AllTypes.decode(readValue(buffer)!);
case 131:
return TestMessage.decode(readValue(buffer)!);
default:
return super.readValueOfType(type, buffer);
}
@ -1986,6 +2018,13 @@ abstract class FlutterIntegrationCoreApi {
/// Returns the passed map, to test serialization and deserialization.
Map<String?, Object?>? echoNullableMap(Map<String?, Object?>? aMap);
/// A no-op function taking no arguments and returning no value, to sanity
/// test basic asynchronous calling.
Future<void> noopAsync();
/// Returns the passed in generic Object asynchronously.
Future<String> echoAsyncString(String aString);
static void setup(FlutterIntegrationCoreApi? api,
{BinaryMessenger? binaryMessenger}) {
{
@ -2354,6 +2393,39 @@ abstract class FlutterIntegrationCoreApi {
});
}
}
{
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.FlutterIntegrationCoreApi.noopAsync', codec,
binaryMessenger: binaryMessenger);
if (api == null) {
channel.setMessageHandler(null);
} else {
channel.setMessageHandler((Object? message) async {
// ignore message
await api.noopAsync();
return;
});
}
}
{
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.FlutterIntegrationCoreApi.echoAsyncString', codec,
binaryMessenger: binaryMessenger);
if (api == null) {
channel.setMessageHandler(null);
} else {
channel.setMessageHandler((Object? message) async {
assert(message != null,
'Argument for dev.flutter.pigeon.FlutterIntegrationCoreApi.echoAsyncString was null.');
final List<Object?> args = (message as List<Object?>?)!;
final String? arg_aString = (args[0] as String?);
assert(arg_aString != null,
'Argument for dev.flutter.pigeon.FlutterIntegrationCoreApi.echoAsyncString was null, expected non-null String.');
final String output = await api.echoAsyncString(arg_aString!);
return output;
});
}
}
}
}
@ -2389,3 +2461,115 @@ class HostTrivialApi {
}
}
}
/// A simple API implemented in some unit tests.
class HostSmallApi {
/// Constructor for [HostSmallApi]. 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.
HostSmallApi({BinaryMessenger? binaryMessenger})
: _binaryMessenger = binaryMessenger;
final BinaryMessenger? _binaryMessenger;
static const MessageCodec<Object?> codec = StandardMessageCodec();
Future<String> echo(String arg_aString) async {
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.HostSmallApi.echo', codec,
binaryMessenger: _binaryMessenger);
final List<Object?>? replyList =
await channel.send(<Object?>[arg_aString]) 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 String?)!;
}
}
Future<void> voidVoid() async {
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.HostSmallApi.voidVoid', 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 {
return;
}
}
}
class _FlutterSmallApiCodec extends StandardMessageCodec {
const _FlutterSmallApiCodec();
@override
void writeValue(WriteBuffer buffer, Object? value) {
if (value is TestMessage) {
buffer.putUint8(128);
writeValue(buffer, value.encode());
} else {
super.writeValue(buffer, value);
}
}
@override
Object? readValueOfType(int type, ReadBuffer buffer) {
switch (type) {
case 128:
return TestMessage.decode(readValue(buffer)!);
default:
return super.readValueOfType(type, buffer);
}
}
}
/// A simple API called in some unit tests.
abstract class FlutterSmallApi {
static const MessageCodec<Object?> codec = _FlutterSmallApiCodec();
TestMessage echoWrappedList(TestMessage msg);
static void setup(FlutterSmallApi? api, {BinaryMessenger? binaryMessenger}) {
{
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.FlutterSmallApi.echoWrappedList', codec,
binaryMessenger: binaryMessenger);
if (api == null) {
channel.setMessageHandler(null);
} else {
channel.setMessageHandler((Object? message) async {
assert(message != null,
'Argument for dev.flutter.pigeon.FlutterSmallApi.echoWrappedList was null.');
final List<Object?> args = (message as List<Object?>?)!;
final TestMessage? arg_msg = (args[0] as TestMessage?);
assert(arg_msg != null,
'Argument for dev.flutter.pigeon.FlutterSmallApi.echoWrappedList was null, expected non-null TestMessage.');
final TestMessage output = api.echoWrappedList(arg_msg!);
return output;
});
}
}
}
}

View File

@ -1368,4 +1368,12 @@ class _FlutterApiTestImplementation implements FlutterIntegrationCoreApi {
@override
Uint8List? echoNullableUint8List(Uint8List? aList) => aList;
@override
Future<void> noopAsync() async {}
@override
Future<String> echoAsyncString(String aString) async {
return aString;
}
}

View File

@ -199,6 +199,28 @@ class AllNullableTypesWrapper {
}
}
/// A data class containing a List, used in unit tests.
class TestMessage {
TestMessage({
this.testList,
});
List<Object?>? testList;
Object encode() {
return <Object?>[
testList,
];
}
static TestMessage decode(Object result) {
result as List<Object?>;
return TestMessage(
testList: result[0] as List<Object?>?,
);
}
}
class _HostIntegrationCoreApiCodec extends StandardMessageCodec {
const _HostIntegrationCoreApiCodec();
@override
@ -212,6 +234,9 @@ class _HostIntegrationCoreApiCodec extends StandardMessageCodec {
} else if (value is AllTypes) {
buffer.putUint8(130);
writeValue(buffer, value.encode());
} else if (value is TestMessage) {
buffer.putUint8(131);
writeValue(buffer, value.encode());
} else {
super.writeValue(buffer, value);
}
@ -226,6 +251,8 @@ class _HostIntegrationCoreApiCodec extends StandardMessageCodec {
return AllNullableTypesWrapper.decode(readValue(buffer)!);
case 130:
return AllTypes.decode(readValue(buffer)!);
case 131:
return TestMessage.decode(readValue(buffer)!);
default:
return super.readValueOfType(type, buffer);
}
@ -1897,6 +1924,9 @@ class _FlutterIntegrationCoreApiCodec extends StandardMessageCodec {
} else if (value is AllTypes) {
buffer.putUint8(130);
writeValue(buffer, value.encode());
} else if (value is TestMessage) {
buffer.putUint8(131);
writeValue(buffer, value.encode());
} else {
super.writeValue(buffer, value);
}
@ -1911,6 +1941,8 @@ class _FlutterIntegrationCoreApiCodec extends StandardMessageCodec {
return AllNullableTypesWrapper.decode(readValue(buffer)!);
case 130:
return AllTypes.decode(readValue(buffer)!);
case 131:
return TestMessage.decode(readValue(buffer)!);
default:
return super.readValueOfType(type, buffer);
}
@ -1986,6 +2018,13 @@ abstract class FlutterIntegrationCoreApi {
/// Returns the passed map, to test serialization and deserialization.
Map<String?, Object?>? echoNullableMap(Map<String?, Object?>? aMap);
/// A no-op function taking no arguments and returning no value, to sanity
/// test basic asynchronous calling.
Future<void> noopAsync();
/// Returns the passed in generic Object asynchronously.
Future<String> echoAsyncString(String aString);
static void setup(FlutterIntegrationCoreApi? api,
{BinaryMessenger? binaryMessenger}) {
{
@ -2354,6 +2393,39 @@ abstract class FlutterIntegrationCoreApi {
});
}
}
{
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.FlutterIntegrationCoreApi.noopAsync', codec,
binaryMessenger: binaryMessenger);
if (api == null) {
channel.setMessageHandler(null);
} else {
channel.setMessageHandler((Object? message) async {
// ignore message
await api.noopAsync();
return;
});
}
}
{
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.FlutterIntegrationCoreApi.echoAsyncString', codec,
binaryMessenger: binaryMessenger);
if (api == null) {
channel.setMessageHandler(null);
} else {
channel.setMessageHandler((Object? message) async {
assert(message != null,
'Argument for dev.flutter.pigeon.FlutterIntegrationCoreApi.echoAsyncString was null.');
final List<Object?> args = (message as List<Object?>?)!;
final String? arg_aString = (args[0] as String?);
assert(arg_aString != null,
'Argument for dev.flutter.pigeon.FlutterIntegrationCoreApi.echoAsyncString was null, expected non-null String.');
final String output = await api.echoAsyncString(arg_aString!);
return output;
});
}
}
}
}
@ -2389,3 +2461,115 @@ class HostTrivialApi {
}
}
}
/// A simple API implemented in some unit tests.
class HostSmallApi {
/// Constructor for [HostSmallApi]. 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.
HostSmallApi({BinaryMessenger? binaryMessenger})
: _binaryMessenger = binaryMessenger;
final BinaryMessenger? _binaryMessenger;
static const MessageCodec<Object?> codec = StandardMessageCodec();
Future<String> echo(String arg_aString) async {
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.HostSmallApi.echo', codec,
binaryMessenger: _binaryMessenger);
final List<Object?>? replyList =
await channel.send(<Object?>[arg_aString]) 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 String?)!;
}
}
Future<void> voidVoid() async {
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.HostSmallApi.voidVoid', 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 {
return;
}
}
}
class _FlutterSmallApiCodec extends StandardMessageCodec {
const _FlutterSmallApiCodec();
@override
void writeValue(WriteBuffer buffer, Object? value) {
if (value is TestMessage) {
buffer.putUint8(128);
writeValue(buffer, value.encode());
} else {
super.writeValue(buffer, value);
}
}
@override
Object? readValueOfType(int type, ReadBuffer buffer) {
switch (type) {
case 128:
return TestMessage.decode(readValue(buffer)!);
default:
return super.readValueOfType(type, buffer);
}
}
}
/// A simple API called in some unit tests.
abstract class FlutterSmallApi {
static const MessageCodec<Object?> codec = _FlutterSmallApiCodec();
TestMessage echoWrappedList(TestMessage msg);
static void setup(FlutterSmallApi? api, {BinaryMessenger? binaryMessenger}) {
{
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.FlutterSmallApi.echoWrappedList', codec,
binaryMessenger: binaryMessenger);
if (api == null) {
channel.setMessageHandler(null);
} else {
channel.setMessageHandler((Object? message) async {
assert(message != null,
'Argument for dev.flutter.pigeon.FlutterSmallApi.echoWrappedList was null.');
final List<Object?> args = (message as List<Object?>?)!;
final TestMessage? arg_msg = (args[0] as TestMessage?);
assert(arg_msg != null,
'Argument for dev.flutter.pigeon.FlutterSmallApi.echoWrappedList was null, expected non-null TestMessage.');
final TestMessage output = api.echoWrappedList(arg_msg!);
return output;
});
}
}
}
}

View File

@ -167,6 +167,29 @@ data class AllNullableTypesWrapper (
}
}
/**
* A data class containing a List, used in unit tests.
*
* Generated class from Pigeon that represents data sent in messages.
*/
data class TestMessage (
val testList: List<Any?>? = null
) {
companion object {
@Suppress("UNCHECKED_CAST")
fun fromList(list: List<Any?>): TestMessage {
val testList = list[0] as? List<Any?>
return TestMessage(testList)
}
}
fun toList(): List<Any?> {
return listOf<Any?>(
testList,
)
}
}
@Suppress("UNCHECKED_CAST")
private object HostIntegrationCoreApiCodec : StandardMessageCodec() {
override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? {
@ -186,6 +209,11 @@ private object HostIntegrationCoreApiCodec : StandardMessageCodec() {
AllTypes.fromList(it)
}
}
131.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
TestMessage.fromList(it)
}
}
else -> super.readValueOfType(type, buffer)
}
}
@ -203,6 +231,10 @@ private object HostIntegrationCoreApiCodec : StandardMessageCodec() {
stream.write(130)
writeValue(stream, value.toList())
}
is TestMessage -> {
stream.write(131)
writeValue(stream, value.toList())
}
else -> super.writeValue(stream, value)
}
}
@ -1623,6 +1655,11 @@ private object FlutterIntegrationCoreApiCodec : StandardMessageCodec() {
AllTypes.fromList(it)
}
}
131.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
TestMessage.fromList(it)
}
}
else -> super.readValueOfType(type, buffer)
}
}
@ -1640,6 +1677,10 @@ private object FlutterIntegrationCoreApiCodec : StandardMessageCodec() {
stream.write(130)
writeValue(stream, value.toList())
}
is TestMessage -> {
stream.write(131)
writeValue(stream, value.toList())
}
else -> super.writeValue(stream, value)
}
}
@ -1824,6 +1865,24 @@ class FlutterIntegrationCoreApi(private val binaryMessenger: BinaryMessenger) {
callback(result)
}
}
/**
* A no-op function taking no arguments and returning no value, to sanity
* test basic asynchronous calling.
*/
fun noopAsync(callback: () -> Unit) {
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.FlutterIntegrationCoreApi.noopAsync", codec)
channel.send(null) {
callback()
}
}
/** Returns the passed in generic Object asynchronously. */
fun echoAsyncString(aStringArg: String, callback: (String) -> Unit) {
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.FlutterIntegrationCoreApi.echoAsyncString", codec)
channel.send(listOf(aStringArg)) {
val result = it as String
callback(result)
}
}
}
/**
* An API that can be implemented for minimal, compile-only tests.
@ -1861,3 +1920,106 @@ interface HostTrivialApi {
}
}
}
/**
* A simple API implemented in some unit tests.
*
* Generated interface from Pigeon that represents a handler of messages from Flutter.
*/
interface HostSmallApi {
fun echo(aString: String, callback: (Result<String>) -> Unit)
fun voidVoid(callback: (Result<Unit>) -> Unit)
companion object {
/** The codec used by HostSmallApi. */
val codec: MessageCodec<Any?> by lazy {
StandardMessageCodec()
}
/** Sets up an instance of `HostSmallApi` to handle messages through the `binaryMessenger`. */
@Suppress("UNCHECKED_CAST")
fun setUp(binaryMessenger: BinaryMessenger, api: HostSmallApi?) {
run {
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.HostSmallApi.echo", codec)
if (api != null) {
channel.setMessageHandler { message, reply ->
var wrapped = listOf<Any?>()
val args = message as List<Any?>
val aStringArg = args[0] as String
api.echo(aStringArg) { result: Result<String> ->
val error = result.exceptionOrNull()
if (error != null) {
reply.reply(wrapError(error))
} else {
val data = result.getOrNull()
reply.reply(wrapResult(data))
}
}
}
} else {
channel.setMessageHandler(null)
}
}
run {
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.HostSmallApi.voidVoid", codec)
if (api != null) {
channel.setMessageHandler { _, reply ->
var wrapped = listOf<Any?>()
api.voidVoid() { result: Result<Unit> ->
val error = result.exceptionOrNull()
if (error != null) {
reply.reply(wrapError(error))
} else {
reply.reply(wrapResult(null))
}
}
}
} else {
channel.setMessageHandler(null)
}
}
}
}
}
@Suppress("UNCHECKED_CAST")
private object FlutterSmallApiCodec : StandardMessageCodec() {
override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? {
return when (type) {
128.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
TestMessage.fromList(it)
}
}
else -> super.readValueOfType(type, buffer)
}
}
override fun writeValue(stream: ByteArrayOutputStream, value: Any?) {
when (value) {
is TestMessage -> {
stream.write(128)
writeValue(stream, value.toList())
}
else -> super.writeValue(stream, value)
}
}
}
/**
* A simple API called in some unit tests.
*
* Generated class from Pigeon that represents Flutter messages that can be called from Kotlin.
*/
@Suppress("UNCHECKED_CAST")
class FlutterSmallApi(private val binaryMessenger: BinaryMessenger) {
companion object {
/** The codec used by FlutterSmallApi. */
val codec: MessageCodec<Any?> by lazy {
FlutterSmallApiCodec
}
}
fun echoWrappedList(msgArg: TestMessage, callback: (TestMessage) -> Unit) {
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.FlutterSmallApi.echoWrappedList", codec)
channel.send(listOf(msgArg)) {
val result = it as TestMessage
callback(result)
}
}
}

View File

@ -18,53 +18,60 @@ internal class AsyncHandlersTest: TestCase() {
@Test
fun testAsyncHost2Flutter() {
val binaryMessenger = mockk<BinaryMessenger>()
val api = Api2Flutter(binaryMessenger)
val api = FlutterIntegrationCoreApi(binaryMessenger)
val input = Value(1)
val output = Value(2)
val value = "Test"
every { binaryMessenger.send(any(), any(), any()) } answers {
val codec = Api2Flutter.codec
val codec = FlutterIntegrationCoreApi.codec
val message = arg<ByteBuffer>(1)
val reply = arg<BinaryMessenger.BinaryReply>(2)
message.position(0)
val replyData = codec.encodeMessage(output)
val replyData = codec.encodeMessage(value)
replyData?.position(0)
reply.reply(replyData)
}
var didCall = false
api.calculate(input) {
api.echoAsyncString(value) {
didCall = true
assertEquals(it, output)
assertEquals(it, value)
}
assertTrue(didCall)
verify { binaryMessenger.send("dev.flutter.pigeon.Api2Flutter.calculate", any(), any()) }
verify {
binaryMessenger.send(
"dev.flutter.pigeon.FlutterIntegrationCoreApi.echoAsyncString",
any(),
any()
)
}
}
@Test
fun testAsyncFlutter2HostCalculate() {
fun testAsyncFlutter2HostEcho() {
val binaryMessenger = mockk<BinaryMessenger>()
val api = mockk<Api2Host>()
val api = mockk<HostSmallApi>()
val handlerSlot = slot<BinaryMessenger.BinaryMessageHandler>()
val input = Value(1)
val output = Value(2)
val channelName = "dev.flutter.pigeon.Api2Host.calculate"
val input = "Test"
val output = input
val channelName = "dev.flutter.pigeon.HostSmallApi.echo"
every { binaryMessenger.setMessageHandler("dev.flutter.pigeon.Api2Host.voidVoid", any()) } returns Unit
every {
binaryMessenger.setMessageHandler("dev.flutter.pigeon.HostSmallApi.voidVoid", any())
} returns Unit
every { binaryMessenger.setMessageHandler(channelName, capture(handlerSlot)) } returns Unit
every { api.calculate(any(), any()) } answers {
val callback = arg<(Result<Value>) -> Unit>(1)
every { api.echo(any(), any()) } answers {
val callback = arg<(Result<String>) -> Unit>(1)
callback(Result.success(output))
}
Api2Host.setUp(binaryMessenger, api)
HostSmallApi.setUp(binaryMessenger, api)
val codec = Api2Host.codec
val codec = HostSmallApi.codec
val message = codec.encodeMessage(listOf(input))
message?.rewind()
handlerSlot.captured.onMessage(message) {
@ -79,28 +86,30 @@ internal class AsyncHandlersTest: TestCase() {
}
verify { binaryMessenger.setMessageHandler(channelName, handlerSlot.captured) }
verify { api.calculate(input, any()) }
verify { api.echo(input, any()) }
}
@Test
fun asyncFlutter2HostVoidVoid() {
val binaryMessenger = mockk<BinaryMessenger>()
val api = mockk<Api2Host>()
val api = mockk<HostSmallApi>()
val handlerSlot = slot<BinaryMessenger.BinaryMessageHandler>()
val channelName = "dev.flutter.pigeon.Api2Host.voidVoid"
val channelName = "dev.flutter.pigeon.HostSmallApi.voidVoid"
every { binaryMessenger.setMessageHandler(channelName, capture(handlerSlot)) } returns Unit
every { binaryMessenger.setMessageHandler("dev.flutter.pigeon.Api2Host.calculate", any()) } returns Unit
every {
binaryMessenger.setMessageHandler("dev.flutter.pigeon.HostSmallApi.echo", any())
} returns Unit
every { api.voidVoid(any()) } answers {
val callback = arg<() -> Unit>(0)
callback()
}
Api2Host.setUp(binaryMessenger, api)
HostSmallApi.setUp(binaryMessenger, api)
val codec = Api2Host.codec
val codec = HostSmallApi.codec
val message = codec.encodeMessage(null)
handlerSlot.captured.onMessage(message) {
it?.rewind()

View File

@ -16,13 +16,13 @@ class ListTest: TestCase() {
@Test
fun testListInList() {
val binaryMessenger = mockk<BinaryMessenger>()
val api = EchoApi(binaryMessenger)
val api = FlutterSmallApi(binaryMessenger)
val inside = TestMessage(listOf(1, 2, 3))
val input = TestMessage(listOf(inside))
every { binaryMessenger.send(any(), any(), any()) } answers {
val codec = EchoApi.codec
val codec = FlutterSmallApi.codec
val message = arg<ByteBuffer>(1)
val reply = arg<BinaryMessenger.BinaryReply>(2)
message.position(0)
@ -33,7 +33,7 @@ class ListTest: TestCase() {
}
var didCall = false
api.echo(input) {
api.echoWrappedList(input) {
didCall = true
assertEquals(input, it)
}

View File

@ -1,14 +1,15 @@
// 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.
import Flutter
import XCTest
@testable import test_plugin
class MockApi2Host: Api2Host {
var output: Int32?
class MockHostSmallApi: HostSmallApi {
var output: String?
func calculate(value: Value, completion: @escaping (Result<Value, Error>) -> Void) {
completion(.success(Value(number: output)))
func echo(aString: String, completion: @escaping (Result<String, Error>) -> Void) {
completion(.success(output!))
}
func voidVoid(completion: @escaping (Result<Void, Error>) -> Void) {
@ -19,25 +20,24 @@ class MockApi2Host: Api2Host {
class AsyncHandlersTest: XCTestCase {
func testAsyncHost2Flutter() throws {
let binaryMessenger = MockBinaryMessenger<Value>(codec: Api2FlutterCodec.shared)
binaryMessenger.result = Value(number: 2)
let api2Flutter = Api2Flutter(binaryMessenger: binaryMessenger)
let input = Value(number: 1)
let value = "Test"
let binaryMessenger = MockBinaryMessenger<String>(codec: FlutterIntegrationCoreApiCodec.shared)
binaryMessenger.result = value
let flutterApi = FlutterIntegrationCoreApi(binaryMessenger: binaryMessenger)
let expectation = XCTestExpectation(description: "calculate callback")
api2Flutter.calculate(value: input) { output in
XCTAssertEqual(output.number, 2)
let expectation = XCTestExpectation(description: "callback")
flutterApi.echo(value) { output in
XCTAssertEqual(output, value)
expectation.fulfill()
}
wait(for: [expectation], timeout: 1.0)
}
func testAsyncFlutter2HostVoidVoid() throws {
let binaryMessenger = MockBinaryMessenger<Value>(codec: Api2HostCodec.shared)
let mockApi2Host = MockApi2Host()
mockApi2Host.output = 2
Api2HostSetup.setUp(binaryMessenger: binaryMessenger, api: mockApi2Host)
let channelName = "dev.flutter.pigeon.Api2Host.voidVoid"
let binaryMessenger = MockBinaryMessenger<String>(codec: FlutterStandardMessageCodec.sharedInstance())
let mockHostSmallApi = MockHostSmallApi()
HostSmallApiSetup.setUp(binaryMessenger: binaryMessenger, api: mockHostSmallApi)
let channelName = "dev.flutter.pigeon.HostSmallApi.voidVoid"
XCTAssertNotNil(binaryMessenger.handlers[channelName])
let expectation = XCTestExpectation(description: "voidvoid callback")
@ -50,21 +50,21 @@ class AsyncHandlersTest: XCTestCase {
}
func testAsyncFlutter2Host() throws {
let binaryMessenger = MockBinaryMessenger<Value>(codec: Api2HostCodec.shared)
let mockApi2Host = MockApi2Host()
mockApi2Host.output = 2
Api2HostSetup.setUp(binaryMessenger: binaryMessenger, api: mockApi2Host)
let channelName = "dev.flutter.pigeon.Api2Host.calculate"
let binaryMessenger = MockBinaryMessenger<String>(codec: FlutterStandardMessageCodec.sharedInstance())
let mockHostSmallApi = MockHostSmallApi()
let value = "Test"
mockHostSmallApi.output = value
HostSmallApiSetup.setUp(binaryMessenger: binaryMessenger, api: mockHostSmallApi)
let channelName = "dev.flutter.pigeon.HostSmallApi.echo"
XCTAssertNotNil(binaryMessenger.handlers[channelName])
let input = Value(number: 1)
let inputEncoded = binaryMessenger.codec.encode([input])
let inputEncoded = binaryMessenger.codec.encode([value])
let expectation = XCTestExpectation(description: "calculate callback")
let expectation = XCTestExpectation(description: "echo callback")
binaryMessenger.handlers[channelName]?(inputEncoded) { data in
let outputList = binaryMessenger.codec.decode(data) as? [Any]
let output = outputList?.first as? Value
XCTAssertEqual(output?.number, 2)
let output = outputList?.first as? String
XCTAssertEqual(output, value)
expectation.fulfill()
}
wait(for: [expectation], timeout: 1.0)

View File

@ -10,11 +10,11 @@ class ListTests: XCTestCase {
func testListInList() throws {
let inside = TestMessage(testList: [1, 2, 3])
let top = TestMessage(testList: [inside])
let binaryMessenger = EchoBinaryMessenger(codec: EchoApiCodec.shared)
let api = EchoApi(binaryMessenger: binaryMessenger)
let binaryMessenger = EchoBinaryMessenger(codec: FlutterSmallApiCodec.shared)
let api = FlutterSmallApi(binaryMessenger: binaryMessenger)
let expectation = XCTestExpectation(description: "callback")
api.echo(msg: top) { result in
api.echo(top) { result in
XCTAssertEqual(1, result.testList?.count)
XCTAssertTrue(result.testList?[0] is TestMessage)
XCTAssert(equalsList(inside.testList, (result.testList?[0] as! TestMessage).testList))

View File

@ -190,6 +190,26 @@ struct AllNullableTypesWrapper {
}
}
/// A data class containing a List, used in unit tests.
///
/// Generated class from Pigeon that represents data sent in messages.
struct TestMessage {
var testList: [Any?]? = nil
static func fromList(_ list: [Any?]) -> TestMessage? {
let testList = list[0] as? [Any?]
return TestMessage(
testList: testList
)
}
func toList() -> [Any?] {
return [
testList,
]
}
}
private class HostIntegrationCoreApiCodecReader: FlutterStandardReader {
override func readValue(ofType type: UInt8) -> Any? {
switch type {
@ -199,6 +219,8 @@ private class HostIntegrationCoreApiCodecReader: FlutterStandardReader {
return AllNullableTypesWrapper.fromList(self.readValue() as! [Any])
case 130:
return AllTypes.fromList(self.readValue() as! [Any])
case 131:
return TestMessage.fromList(self.readValue() as! [Any])
default:
return super.readValue(ofType: type)
}
@ -216,6 +238,9 @@ private class HostIntegrationCoreApiCodecWriter: FlutterStandardWriter {
} else if let value = value as? AllTypes {
super.writeByte(130)
super.writeValue(value.toList())
} else if let value = value as? TestMessage {
super.writeByte(131)
super.writeValue(value.toList())
} else {
super.writeValue(value)
}
@ -1448,6 +1473,8 @@ private class FlutterIntegrationCoreApiCodecReader: FlutterStandardReader {
return AllNullableTypesWrapper.fromList(self.readValue() as! [Any])
case 130:
return AllTypes.fromList(self.readValue() as! [Any])
case 131:
return TestMessage.fromList(self.readValue() as! [Any])
default:
return super.readValue(ofType: type)
}
@ -1465,6 +1492,9 @@ private class FlutterIntegrationCoreApiCodecWriter: FlutterStandardWriter {
} else if let value = value as? AllTypes {
super.writeByte(130)
super.writeValue(value.toList())
} else if let value = value as? TestMessage {
super.writeByte(131)
super.writeValue(value.toList())
} else {
super.writeValue(value)
}
@ -1658,6 +1688,22 @@ class FlutterIntegrationCoreApi {
completion(result)
}
}
/// A no-op function taking no arguments and returning no value, to sanity
/// test basic asynchronous calling.
func noopAsync(completion: @escaping () -> Void) {
let channel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.FlutterIntegrationCoreApi.noopAsync", binaryMessenger: binaryMessenger, codec: codec)
channel.sendMessage(nil) { _ in
completion()
}
}
/// Returns the passed in generic Object asynchronously.
func echoAsync(_ aStringArg: String, completion: @escaping (String) -> Void) {
let channel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.FlutterIntegrationCoreApi.echoAsyncString", binaryMessenger: binaryMessenger, codec: codec)
channel.sendMessage([aStringArg] as [Any?]) { response in
let result = response as! String
completion(result)
}
}
}
/// An API that can be implemented for minimal, compile-only tests.
///
@ -1686,3 +1732,105 @@ class HostTrivialApiSetup {
}
}
}
/// A simple API implemented in some unit tests.
///
/// Generated protocol from Pigeon that represents a handler of messages from Flutter.
protocol HostSmallApi {
func echo(aString: String, completion: @escaping (Result<String, Error>) -> Void)
func voidVoid(completion: @escaping (Result<Void, Error>) -> Void)
}
/// Generated setup class from Pigeon to handle messages through the `binaryMessenger`.
class HostSmallApiSetup {
/// The codec used by HostSmallApi.
/// Sets up an instance of `HostSmallApi` to handle messages through the `binaryMessenger`.
static func setUp(binaryMessenger: FlutterBinaryMessenger, api: HostSmallApi?) {
let echoChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.HostSmallApi.echo", binaryMessenger: binaryMessenger)
if let api = api {
echoChannel.setMessageHandler { message, reply in
let args = message as! [Any?]
let aStringArg = args[0] as! String
api.echo(aString: aStringArg) { result in
switch result {
case .success(let res):
reply(wrapResult(res))
case .failure(let error):
reply(wrapError(error))
}
}
}
} else {
echoChannel.setMessageHandler(nil)
}
let voidVoidChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.HostSmallApi.voidVoid", binaryMessenger: binaryMessenger)
if let api = api {
voidVoidChannel.setMessageHandler { _, reply in
api.voidVoid() { result in
switch result {
case .success:
reply(wrapResult(nil))
case .failure(let error):
reply(wrapError(error))
}
}
}
} else {
voidVoidChannel.setMessageHandler(nil)
}
}
}
private class FlutterSmallApiCodecReader: FlutterStandardReader {
override func readValue(ofType type: UInt8) -> Any? {
switch type {
case 128:
return TestMessage.fromList(self.readValue() as! [Any])
default:
return super.readValue(ofType: type)
}
}
}
private class FlutterSmallApiCodecWriter: FlutterStandardWriter {
override func writeValue(_ value: Any) {
if let value = value as? TestMessage {
super.writeByte(128)
super.writeValue(value.toList())
} else {
super.writeValue(value)
}
}
}
private class FlutterSmallApiCodecReaderWriter: FlutterStandardReaderWriter {
override func reader(with data: Data) -> FlutterStandardReader {
return FlutterSmallApiCodecReader(data: data)
}
override func writer(with data: NSMutableData) -> FlutterStandardWriter {
return FlutterSmallApiCodecWriter(data: data)
}
}
class FlutterSmallApiCodec: FlutterStandardMessageCodec {
static let shared = FlutterSmallApiCodec(readerWriter: FlutterSmallApiCodecReaderWriter())
}
/// A simple API called in some unit tests.
///
/// Generated class from Pigeon that represents Flutter messages that can be called from Swift.
class FlutterSmallApi {
private let binaryMessenger: FlutterBinaryMessenger
init(binaryMessenger: FlutterBinaryMessenger){
self.binaryMessenger = binaryMessenger
}
var codec: FlutterStandardMessageCodec {
return FlutterSmallApiCodec.shared
}
func echo(_ msgArg: TestMessage, completion: @escaping (TestMessage) -> Void) {
let channel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.FlutterSmallApi.echoWrappedList", binaryMessenger: binaryMessenger, codec: codec)
channel.sendMessage([msgArg] as [Any?]) { response in
let result = response as! TestMessage
completion(result)
}
}
}

View File

@ -190,6 +190,26 @@ struct AllNullableTypesWrapper {
}
}
/// A data class containing a List, used in unit tests.
///
/// Generated class from Pigeon that represents data sent in messages.
struct TestMessage {
var testList: [Any?]? = nil
static func fromList(_ list: [Any?]) -> TestMessage? {
let testList = list[0] as? [Any?]
return TestMessage(
testList: testList
)
}
func toList() -> [Any?] {
return [
testList,
]
}
}
private class HostIntegrationCoreApiCodecReader: FlutterStandardReader {
override func readValue(ofType type: UInt8) -> Any? {
switch type {
@ -199,6 +219,8 @@ private class HostIntegrationCoreApiCodecReader: FlutterStandardReader {
return AllNullableTypesWrapper.fromList(self.readValue() as! [Any])
case 130:
return AllTypes.fromList(self.readValue() as! [Any])
case 131:
return TestMessage.fromList(self.readValue() as! [Any])
default:
return super.readValue(ofType: type)
}
@ -216,6 +238,9 @@ private class HostIntegrationCoreApiCodecWriter: FlutterStandardWriter {
} else if let value = value as? AllTypes {
super.writeByte(130)
super.writeValue(value.toList())
} else if let value = value as? TestMessage {
super.writeByte(131)
super.writeValue(value.toList())
} else {
super.writeValue(value)
}
@ -1448,6 +1473,8 @@ private class FlutterIntegrationCoreApiCodecReader: FlutterStandardReader {
return AllNullableTypesWrapper.fromList(self.readValue() as! [Any])
case 130:
return AllTypes.fromList(self.readValue() as! [Any])
case 131:
return TestMessage.fromList(self.readValue() as! [Any])
default:
return super.readValue(ofType: type)
}
@ -1465,6 +1492,9 @@ private class FlutterIntegrationCoreApiCodecWriter: FlutterStandardWriter {
} else if let value = value as? AllTypes {
super.writeByte(130)
super.writeValue(value.toList())
} else if let value = value as? TestMessage {
super.writeByte(131)
super.writeValue(value.toList())
} else {
super.writeValue(value)
}
@ -1658,6 +1688,22 @@ class FlutterIntegrationCoreApi {
completion(result)
}
}
/// A no-op function taking no arguments and returning no value, to sanity
/// test basic asynchronous calling.
func noopAsync(completion: @escaping () -> Void) {
let channel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.FlutterIntegrationCoreApi.noopAsync", binaryMessenger: binaryMessenger, codec: codec)
channel.sendMessage(nil) { _ in
completion()
}
}
/// Returns the passed in generic Object asynchronously.
func echoAsync(_ aStringArg: String, completion: @escaping (String) -> Void) {
let channel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.FlutterIntegrationCoreApi.echoAsyncString", binaryMessenger: binaryMessenger, codec: codec)
channel.sendMessage([aStringArg] as [Any?]) { response in
let result = response as! String
completion(result)
}
}
}
/// An API that can be implemented for minimal, compile-only tests.
///
@ -1686,3 +1732,105 @@ class HostTrivialApiSetup {
}
}
}
/// A simple API implemented in some unit tests.
///
/// Generated protocol from Pigeon that represents a handler of messages from Flutter.
protocol HostSmallApi {
func echo(aString: String, completion: @escaping (Result<String, Error>) -> Void)
func voidVoid(completion: @escaping (Result<Void, Error>) -> Void)
}
/// Generated setup class from Pigeon to handle messages through the `binaryMessenger`.
class HostSmallApiSetup {
/// The codec used by HostSmallApi.
/// Sets up an instance of `HostSmallApi` to handle messages through the `binaryMessenger`.
static func setUp(binaryMessenger: FlutterBinaryMessenger, api: HostSmallApi?) {
let echoChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.HostSmallApi.echo", binaryMessenger: binaryMessenger)
if let api = api {
echoChannel.setMessageHandler { message, reply in
let args = message as! [Any?]
let aStringArg = args[0] as! String
api.echo(aString: aStringArg) { result in
switch result {
case .success(let res):
reply(wrapResult(res))
case .failure(let error):
reply(wrapError(error))
}
}
}
} else {
echoChannel.setMessageHandler(nil)
}
let voidVoidChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.HostSmallApi.voidVoid", binaryMessenger: binaryMessenger)
if let api = api {
voidVoidChannel.setMessageHandler { _, reply in
api.voidVoid() { result in
switch result {
case .success:
reply(wrapResult(nil))
case .failure(let error):
reply(wrapError(error))
}
}
}
} else {
voidVoidChannel.setMessageHandler(nil)
}
}
}
private class FlutterSmallApiCodecReader: FlutterStandardReader {
override func readValue(ofType type: UInt8) -> Any? {
switch type {
case 128:
return TestMessage.fromList(self.readValue() as! [Any])
default:
return super.readValue(ofType: type)
}
}
}
private class FlutterSmallApiCodecWriter: FlutterStandardWriter {
override func writeValue(_ value: Any) {
if let value = value as? TestMessage {
super.writeByte(128)
super.writeValue(value.toList())
} else {
super.writeValue(value)
}
}
}
private class FlutterSmallApiCodecReaderWriter: FlutterStandardReaderWriter {
override func reader(with data: Data) -> FlutterStandardReader {
return FlutterSmallApiCodecReader(data: data)
}
override func writer(with data: NSMutableData) -> FlutterStandardWriter {
return FlutterSmallApiCodecWriter(data: data)
}
}
class FlutterSmallApiCodec: FlutterStandardMessageCodec {
static let shared = FlutterSmallApiCodec(readerWriter: FlutterSmallApiCodecReaderWriter())
}
/// A simple API called in some unit tests.
///
/// Generated class from Pigeon that represents Flutter messages that can be called from Swift.
class FlutterSmallApi {
private let binaryMessenger: FlutterBinaryMessenger
init(binaryMessenger: FlutterBinaryMessenger){
self.binaryMessenger = binaryMessenger
}
var codec: FlutterStandardMessageCodec {
return FlutterSmallApiCodec.shared
}
func echo(_ msgArg: TestMessage, completion: @escaping (TestMessage) -> Void) {
let channel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.FlutterSmallApi.echoWrappedList", binaryMessenger: binaryMessenger, codec: codec)
channel.sendMessage([msgArg] as [Any?]) { response in
let result = response as! TestMessage
completion(result)
}
}
}

View File

@ -17,16 +17,10 @@ list(APPEND PLUGIN_SOURCES
"test_plugin.cpp"
"test_plugin.h"
# Generated sources.
"pigeon/async_handlers.gen.cpp"
"pigeon/async_handlers.gen.h"
"pigeon/core_tests.gen.cpp"
"pigeon/core_tests.gen.h"
"pigeon/enum.gen.cpp"
"pigeon/enum.gen.h"
"pigeon/host2flutter.gen.cpp"
"pigeon/host2flutter.gen.h"
"pigeon/list.gen.cpp"
"pigeon/list.gen.h"
"pigeon/message.gen.cpp"
"pigeon/message.gen.h"
"pigeon/multiple_arity.gen.cpp"
@ -39,14 +33,6 @@ list(APPEND PLUGIN_SOURCES
"pigeon/nullable_returns.gen.h"
"pigeon/primitive.gen.cpp"
"pigeon/primitive.gen.h"
"pigeon/void_arg_flutter.gen.cpp"
"pigeon/void_arg_flutter.gen.h"
"pigeon/void_arg_host.gen.cpp"
"pigeon/void_arg_host.gen.h"
"pigeon/voidflutter.gen.cpp"
"pigeon/voidflutter.gen.h"
"pigeon/voidhost.gen.cpp"
"pigeon/voidhost.gen.h"
)
# Define the plugin library target. Its name must not be changed (see comment

View File

@ -473,6 +473,36 @@ AllNullableTypesWrapper::AllNullableTypesWrapper(const EncodableList& list) {
}
}
// TestMessage
const EncodableList* TestMessage::test_list() const {
return test_list_ ? &(*test_list_) : nullptr;
}
void TestMessage::set_test_list(const EncodableList* value_arg) {
test_list_ =
value_arg ? std::optional<EncodableList>(*value_arg) : std::nullopt;
}
void TestMessage::set_test_list(const EncodableList& value_arg) {
test_list_ = value_arg;
}
EncodableList TestMessage::ToEncodableList() const {
EncodableList list;
list.reserve(1);
list.push_back(test_list_ ? EncodableValue(*test_list_) : EncodableValue());
return list;
}
TestMessage::TestMessage() {}
TestMessage::TestMessage(const EncodableList& list) {
auto& encodable_test_list = list[0];
if (const EncodableList* pointer_test_list =
std::get_if<EncodableList>(&encodable_test_list)) {
test_list_ = *pointer_test_list;
}
}
HostIntegrationCoreApiCodecSerializer::HostIntegrationCoreApiCodecSerializer() {
}
EncodableValue HostIntegrationCoreApiCodecSerializer::ReadValueOfType(
@ -487,6 +517,9 @@ EncodableValue HostIntegrationCoreApiCodecSerializer::ReadValueOfType(
case 130:
return CustomEncodableValue(
AllTypes(std::get<EncodableList>(ReadValue(stream))));
case 131:
return CustomEncodableValue(
TestMessage(std::get<EncodableList>(ReadValue(stream))));
default:
return flutter::StandardCodecSerializer::ReadValueOfType(type, stream);
}
@ -519,6 +552,14 @@ void HostIntegrationCoreApiCodecSerializer::WriteValue(
stream);
return;
}
if (custom_value->type() == typeid(TestMessage)) {
stream->WriteByte(131);
WriteValue(
EncodableValue(
std::any_cast<TestMessage>(*custom_value).ToEncodableList()),
stream);
return;
}
}
flutter::StandardCodecSerializer::WriteValue(value, stream);
}
@ -2881,6 +2922,9 @@ EncodableValue FlutterIntegrationCoreApiCodecSerializer::ReadValueOfType(
case 130:
return CustomEncodableValue(
AllTypes(std::get<EncodableList>(ReadValue(stream))));
case 131:
return CustomEncodableValue(
TestMessage(std::get<EncodableList>(ReadValue(stream))));
default:
return flutter::StandardCodecSerializer::ReadValueOfType(type, stream);
}
@ -2913,6 +2957,14 @@ void FlutterIntegrationCoreApiCodecSerializer::WriteValue(
stream);
return;
}
if (custom_value->type() == typeid(TestMessage)) {
stream->WriteByte(131);
WriteValue(
EncodableValue(
std::any_cast<TestMessage>(*custom_value).ToEncodableList()),
stream);
return;
}
}
flutter::StandardCodecSerializer::WriteValue(value, stream);
}
@ -3355,6 +3407,41 @@ void FlutterIntegrationCoreApi::EchoNullableMap(
on_success(return_value);
});
}
void FlutterIntegrationCoreApi::NoopAsync(
std::function<void(void)>&& on_success,
std::function<void(const FlutterError&)>&& on_error) {
auto channel = std::make_unique<BasicMessageChannel<>>(
binary_messenger_,
"dev.flutter.pigeon.FlutterIntegrationCoreApi.noopAsync", &GetCodec());
EncodableValue encoded_api_arguments = EncodableValue();
channel->Send(
encoded_api_arguments,
[on_success = std::move(on_success), on_error = std::move(on_error)](
const uint8_t* reply, size_t reply_size) { on_success(); });
}
void FlutterIntegrationCoreApi::EchoAsyncString(
const std::string& a_string_arg,
std::function<void(const std::string&)>&& on_success,
std::function<void(const FlutterError&)>&& on_error) {
auto channel = std::make_unique<BasicMessageChannel<>>(
binary_messenger_,
"dev.flutter.pigeon.FlutterIntegrationCoreApi.echoAsyncString",
&GetCodec());
EncodableValue encoded_api_arguments = EncodableValue(EncodableList{
EncodableValue(a_string_arg),
});
channel->Send(
encoded_api_arguments,
[on_success = std::move(on_success), on_error = std::move(on_error)](
const uint8_t* reply, size_t reply_size) {
std::unique_ptr<EncodableValue> response =
GetCodec().DecodeMessage(reply, reply_size);
const auto& encodable_return_value = *response;
const auto& return_value =
std::get<std::string>(encodable_return_value);
on_success(return_value);
});
}
/// The codec used by HostTrivialApi.
const flutter::StandardMessageCodec& HostTrivialApi::GetCodec() {
return flutter::StandardMessageCodec::GetInstance(
@ -3403,4 +3490,148 @@ EncodableValue HostTrivialApi::WrapError(const FlutterError& error) {
error.details()});
}
/// The codec used by HostSmallApi.
const flutter::StandardMessageCodec& HostSmallApi::GetCodec() {
return flutter::StandardMessageCodec::GetInstance(
&flutter::StandardCodecSerializer::GetInstance());
}
// Sets up an instance of `HostSmallApi` to handle messages through the
// `binary_messenger`.
void HostSmallApi::SetUp(flutter::BinaryMessenger* binary_messenger,
HostSmallApi* api) {
{
auto channel = std::make_unique<BasicMessageChannel<>>(
binary_messenger, "dev.flutter.pigeon.HostSmallApi.echo", &GetCodec());
if (api != nullptr) {
channel->SetMessageHandler(
[api](const EncodableValue& message,
const flutter::MessageReply<EncodableValue>& reply) {
try {
const auto& args = std::get<EncodableList>(message);
const auto& encodable_a_string_arg = args.at(0);
if (encodable_a_string_arg.IsNull()) {
reply(WrapError("a_string_arg unexpectedly null."));
return;
}
const auto& a_string_arg =
std::get<std::string>(encodable_a_string_arg);
api->Echo(a_string_arg, [reply](ErrorOr<std::string>&& output) {
if (output.has_error()) {
reply(WrapError(output.error()));
return;
}
EncodableList wrapped;
wrapped.push_back(
EncodableValue(std::move(output).TakeValue()));
reply(EncodableValue(std::move(wrapped)));
});
} catch (const std::exception& exception) {
reply(WrapError(exception.what()));
}
});
} else {
channel->SetMessageHandler(nullptr);
}
}
{
auto channel = std::make_unique<BasicMessageChannel<>>(
binary_messenger, "dev.flutter.pigeon.HostSmallApi.voidVoid",
&GetCodec());
if (api != nullptr) {
channel->SetMessageHandler(
[api](const EncodableValue& message,
const flutter::MessageReply<EncodableValue>& reply) {
try {
api->VoidVoid([reply](std::optional<FlutterError>&& output) {
if (output.has_value()) {
reply(WrapError(output.value()));
return;
}
EncodableList wrapped;
wrapped.push_back(EncodableValue());
reply(EncodableValue(std::move(wrapped)));
});
} catch (const std::exception& exception) {
reply(WrapError(exception.what()));
}
});
} else {
channel->SetMessageHandler(nullptr);
}
}
}
EncodableValue HostSmallApi::WrapError(std::string_view error_message) {
return EncodableValue(
EncodableList{EncodableValue(std::string(error_message)),
EncodableValue("Error"), EncodableValue()});
}
EncodableValue HostSmallApi::WrapError(const FlutterError& error) {
return EncodableValue(EncodableList{EncodableValue(error.message()),
EncodableValue(error.code()),
error.details()});
}
FlutterSmallApiCodecSerializer::FlutterSmallApiCodecSerializer() {}
EncodableValue FlutterSmallApiCodecSerializer::ReadValueOfType(
uint8_t type, flutter::ByteStreamReader* stream) const {
switch (type) {
case 128:
return CustomEncodableValue(
TestMessage(std::get<EncodableList>(ReadValue(stream))));
default:
return flutter::StandardCodecSerializer::ReadValueOfType(type, stream);
}
}
void FlutterSmallApiCodecSerializer::WriteValue(
const EncodableValue& value, flutter::ByteStreamWriter* stream) const {
if (const CustomEncodableValue* custom_value =
std::get_if<CustomEncodableValue>(&value)) {
if (custom_value->type() == typeid(TestMessage)) {
stream->WriteByte(128);
WriteValue(
EncodableValue(
std::any_cast<TestMessage>(*custom_value).ToEncodableList()),
stream);
return;
}
}
flutter::StandardCodecSerializer::WriteValue(value, stream);
}
// Generated class from Pigeon that represents Flutter messages that can be
// called from C++.
FlutterSmallApi::FlutterSmallApi(flutter::BinaryMessenger* binary_messenger) {
this->binary_messenger_ = binary_messenger;
}
const flutter::StandardMessageCodec& FlutterSmallApi::GetCodec() {
return flutter::StandardMessageCodec::GetInstance(
&FlutterSmallApiCodecSerializer::GetInstance());
}
void FlutterSmallApi::EchoWrappedList(
const TestMessage& msg_arg,
std::function<void(const TestMessage&)>&& on_success,
std::function<void(const FlutterError&)>&& on_error) {
auto channel = std::make_unique<BasicMessageChannel<>>(
binary_messenger_, "dev.flutter.pigeon.FlutterSmallApi.echoWrappedList",
&GetCodec());
EncodableValue encoded_api_arguments = EncodableValue(EncodableList{
EncodableValue(msg_arg.ToEncodableList()),
});
channel->Send(
encoded_api_arguments,
[on_success = std::move(on_success), on_error = std::move(on_error)](
const uint8_t* reply, size_t reply_size) {
std::unique_ptr<EncodableValue> response =
GetCodec().DecodeMessage(reply, reply_size);
const auto& encodable_return_value = *response;
const auto& return_value = std::any_cast<const TestMessage&>(
std::get<CustomEncodableValue>(encodable_return_value));
on_success(return_value);
});
}
} // namespace core_tests_pigeontest

View File

@ -57,6 +57,8 @@ class ErrorOr {
friend class HostIntegrationCoreApi;
friend class FlutterIntegrationCoreApi;
friend class HostTrivialApi;
friend class HostSmallApi;
friend class FlutterSmallApi;
ErrorOr() = default;
T TakeValue() && { return std::get<T>(std::move(v_)); }
@ -111,6 +113,10 @@ class AllTypes {
friend class FlutterIntegrationCoreApiCodecSerializer;
friend class HostTrivialApi;
friend class HostTrivialApiCodecSerializer;
friend class HostSmallApi;
friend class HostSmallApiCodecSerializer;
friend class FlutterSmallApi;
friend class FlutterSmallApiCodecSerializer;
friend class CoreTestsTest;
bool a_bool_;
int64_t an_int_;
@ -197,6 +203,10 @@ class AllNullableTypes {
friend class FlutterIntegrationCoreApiCodecSerializer;
friend class HostTrivialApi;
friend class HostTrivialApiCodecSerializer;
friend class HostSmallApi;
friend class HostSmallApiCodecSerializer;
friend class FlutterSmallApi;
friend class FlutterSmallApiCodecSerializer;
friend class CoreTestsTest;
std::optional<bool> a_nullable_bool_;
std::optional<int64_t> a_nullable_int_;
@ -230,10 +240,41 @@ class AllNullableTypesWrapper {
friend class FlutterIntegrationCoreApiCodecSerializer;
friend class HostTrivialApi;
friend class HostTrivialApiCodecSerializer;
friend class HostSmallApi;
friend class HostSmallApiCodecSerializer;
friend class FlutterSmallApi;
friend class FlutterSmallApiCodecSerializer;
friend class CoreTestsTest;
AllNullableTypes values_;
};
// A data class containing a List, used in unit tests.
//
// Generated class from Pigeon that represents data sent in messages.
class TestMessage {
public:
TestMessage();
const flutter::EncodableList* test_list() const;
void set_test_list(const flutter::EncodableList* value_arg);
void set_test_list(const flutter::EncodableList& value_arg);
private:
TestMessage(const flutter::EncodableList& list);
flutter::EncodableList ToEncodableList() const;
friend class HostIntegrationCoreApi;
friend class HostIntegrationCoreApiCodecSerializer;
friend class FlutterIntegrationCoreApi;
friend class FlutterIntegrationCoreApiCodecSerializer;
friend class HostTrivialApi;
friend class HostTrivialApiCodecSerializer;
friend class HostSmallApi;
friend class HostSmallApiCodecSerializer;
friend class FlutterSmallApi;
friend class FlutterSmallApiCodecSerializer;
friend class CoreTestsTest;
std::optional<flutter::EncodableList> test_list_;
};
class HostIntegrationCoreApiCodecSerializer
: public flutter::StandardCodecSerializer {
public:
@ -607,6 +648,14 @@ class FlutterIntegrationCoreApi {
const flutter::EncodableMap* a_map,
std::function<void(const flutter::EncodableMap*)>&& on_success,
std::function<void(const FlutterError&)>&& on_error);
// A no-op function taking no arguments and returning no value, to sanity
// test basic asynchronous calling.
void NoopAsync(std::function<void(void)>&& on_success,
std::function<void(const FlutterError&)>&& on_error);
// Returns the passed in generic Object asynchronously.
void EchoAsyncString(const std::string& a_string,
std::function<void(const std::string&)>&& on_success,
std::function<void(const FlutterError&)>&& on_error);
};
// An API that can be implemented for minimal, compile-only tests.
@ -632,5 +681,65 @@ class HostTrivialApi {
protected:
HostTrivialApi() = default;
};
// A simple API implemented in some unit tests.
//
// Generated interface from Pigeon that represents a handler of messages from
// Flutter.
class HostSmallApi {
public:
HostSmallApi(const HostSmallApi&) = delete;
HostSmallApi& operator=(const HostSmallApi&) = delete;
virtual ~HostSmallApi() {}
virtual void Echo(const std::string& a_string,
std::function<void(ErrorOr<std::string> reply)> result) = 0;
virtual void VoidVoid(
std::function<void(std::optional<FlutterError> reply)> result) = 0;
// The codec used by HostSmallApi.
static const flutter::StandardMessageCodec& GetCodec();
// Sets up an instance of `HostSmallApi` to handle messages through the
// `binary_messenger`.
static void SetUp(flutter::BinaryMessenger* binary_messenger,
HostSmallApi* api);
static flutter::EncodableValue WrapError(std::string_view error_message);
static flutter::EncodableValue WrapError(const FlutterError& error);
protected:
HostSmallApi() = default;
};
class FlutterSmallApiCodecSerializer : public flutter::StandardCodecSerializer {
public:
inline static FlutterSmallApiCodecSerializer& GetInstance() {
static FlutterSmallApiCodecSerializer sInstance;
return sInstance;
}
FlutterSmallApiCodecSerializer();
public:
void WriteValue(const flutter::EncodableValue& value,
flutter::ByteStreamWriter* stream) const override;
protected:
flutter::EncodableValue ReadValueOfType(
uint8_t type, flutter::ByteStreamReader* stream) const override;
};
// A simple API called in some unit tests.
//
// Generated class from Pigeon that represents Flutter messages that can be
// called from C++.
class FlutterSmallApi {
private:
flutter::BinaryMessenger* binary_messenger_;
public:
FlutterSmallApi(flutter::BinaryMessenger* binary_messenger);
static const flutter::StandardMessageCodec& GetCodec();
void EchoWrappedList(const TestMessage& msg,
std::function<void(const TestMessage&)>&& on_success,
std::function<void(const FlutterError&)>&& on_error);
};
} // namespace core_tests_pigeontest
#endif // PIGEON_CORE_TESTS_GEN_H_

View File

@ -16,9 +16,7 @@ enum GeneratorLanguages {
// A map of pigeons/ files to the languages that they can't yet be generated
// for due to limitations of that generator.
const Map<String, Set<GeneratorLanguages>> _unsupportedFiles =
<String, Set<GeneratorLanguages>>{
'enum_args': <GeneratorLanguages>{GeneratorLanguages.cpp},
};
<String, Set<GeneratorLanguages>>{};
String _snakeToPascalCase(String snake) {
final List<String> parts = snake.split('_');
@ -37,12 +35,7 @@ String _snakeToPascalCase(String snake) {
// https://github.com/flutter/flutter/issues/115168.
String _javaFilenameForName(String inputName) {
const Map<String, String> specialCases = <String, String>{
'android_unittests': 'Pigeon',
'host2flutter': 'Host2Flutter',
'list': 'PigeonList',
'message': 'MessagePigeon',
'voidflutter': 'VoidFlutter',
'voidhost': 'VoidHost',
};
return specialCases[inputName] ?? _snakeToPascalCase(inputName);
}
@ -51,25 +44,15 @@ Future<int> generatePigeons({required String baseDir}) async {
// TODO(stuartmorgan): Make this dynamic rather than hard-coded. Or eliminate
// it entirely; see https://github.com/flutter/flutter/issues/115169.
const List<String> inputs = <String>[
'android_unittests',
'async_handlers',
'background_platform_channels',
'core_tests',
'enum_args',
'enum',
'host2flutter',
'java_double_host_api',
'list',
'message',
'multiple_arity',
'non_null_fields',
'null_fields',
'nullable_returns',
'primitive',
'void_arg_flutter',
'void_arg_host',
'voidflutter',
'voidhost',
];
final String outputBase = p.join(baseDir, 'platform_tests', 'test_plugin');

View File

@ -216,18 +216,6 @@ Future<int> _runFlutterUnitTests() async {
'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>{
for (final String name in inputPigeons)