Flutter Engine
The Flutter Engine
FlutterChannelsTest.m
Go to the documentation of this file.
1// Copyright 2013 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#import "flutter/shell/platform/darwin/common/framework/Headers/FlutterChannels.h"
6#import "flutter/shell/platform/darwin/ios/flutter_task_queue_dispatch.h"
7
8#import <OCMock/OCMock.h>
9#import <XCTest/XCTest.h>
10
12
14@property(nonatomic, copy) NSString* channel;
15@property(nonatomic, strong) NSData* message;
16@property(nonatomic, strong) NSMutableDictionary<NSString*, FlutterBinaryMessageHandler>* handlers;
17@end
18@implementation MockBinaryMessenger
19- (instancetype)init {
20 self = [super init];
21 if (self) {
22 _handlers = [[NSMutableDictionary<NSString*, FlutterBinaryMessageHandler> alloc] init];
23 }
24 return self;
25}
26
27- (void)sendOnChannel:(NSString*)channel message:(NSData* _Nullable)message {
28 [self sendOnChannel:channel message:message binaryReply:nil];
29}
30
31- (void)sendOnChannel:(NSString*)channel
32 message:(NSData* _Nullable)message
33 binaryReply:(FlutterBinaryReply _Nullable)callback {
34 self.channel = channel;
35 self.message = message;
36}
37
38- (FlutterBinaryMessengerConnection)setMessageHandlerOnChannel:(NSString*)channel
39 binaryMessageHandler:
40 (FlutterBinaryMessageHandler _Nullable)handler {
41 [self.handlers setObject:handler forKey:channel];
42 return 0;
43}
44
45- (void)cleanUpConnection:(FlutterBinaryMessengerConnection)connection {
46}
47
48@end
49
50@interface FlutterChannelsTest : XCTestCase
51@end
52
53@implementation FlutterChannelsTest
54
55- (void)testMethodInvoke {
56 NSString* channelName = @"foo";
57 id binaryMessenger = OCMProtocolMock(@protocol(FlutterBinaryMessenger));
58 id codec = OCMProtocolMock(@protocol(FlutterMethodCodec));
59 FlutterMethodChannel* channel = [[FlutterMethodChannel alloc] initWithName:channelName
60 binaryMessenger:binaryMessenger
61 codec:codec];
62 XCTAssertNotNil(channel);
63 NSData* encodedMethodCall = [@"hey" dataUsingEncoding:NSUTF8StringEncoding];
64 OCMStub([codec encodeMethodCall:[OCMArg any]]).andReturn(encodedMethodCall);
65 [channel invokeMethod:@"foo" arguments:@[ @(1) ]];
66 OCMVerify([binaryMessenger sendOnChannel:channelName message:encodedMethodCall]);
67}
68
70 NSString* channelName = @"foo";
71 id binaryMessenger = OCMProtocolMock(@protocol(FlutterBinaryMessenger));
72 id codec = OCMProtocolMock(@protocol(FlutterMethodCodec));
73 FlutterMethodChannel* channel = [[FlutterMethodChannel alloc] initWithName:channelName
74 binaryMessenger:binaryMessenger
75 codec:codec];
76 XCTAssertNotNil(channel);
77 NSData* encodedMethodCall = [@"hey" dataUsingEncoding:NSUTF8StringEncoding];
78 OCMStub([codec encodeMethodCall:[OCMArg any]]).andReturn(encodedMethodCall);
79 XCTestExpectation* didCallReply = [self expectationWithDescription:@"didCallReply"];
80 OCMExpect([binaryMessenger sendOnChannel:channelName
81 message:encodedMethodCall
82 binaryReply:[OCMArg checkWithBlock:^BOOL(id obj) {
83 FlutterBinaryReply reply = obj;
84 reply(nil);
85 return YES;
86 }]]);
87 [channel invokeMethod:@"foo"
88 arguments:@[ @1 ]
89 result:^(id _Nullable result) {
90 [didCallReply fulfill];
91 XCTAssertEqual(FlutterMethodNotImplemented, result);
92 }];
93 OCMVerifyAll(binaryMessenger);
94 [self waitForExpectationsWithTimeout:1.0 handler:nil];
95}
96
98 NSString* channelName = @"foo";
99 id binaryMessenger = OCMProtocolMock(@protocol(FlutterBinaryMessenger));
100 id codec = OCMProtocolMock(@protocol(FlutterMethodCodec));
101 FlutterMethodChannel* channel = [[FlutterMethodChannel alloc] initWithName:channelName
102 binaryMessenger:binaryMessenger
103 codec:codec];
104 XCTAssertNotNil(channel);
105
106 NSData* encodedMethodCall = [@"hey" dataUsingEncoding:NSUTF8StringEncoding];
107 OCMStub([codec encodeMethodCall:[OCMArg any]]).andReturn(encodedMethodCall);
109 ^(FlutterMethodCall* _Nonnull call, FlutterResult _Nonnull result) {
110 };
111 [channel setMethodCallHandler:handler];
112 OCMVerify([binaryMessenger setMessageHandlerOnChannel:channelName
113 binaryMessageHandler:[OCMArg isNotNil]]);
114}
115
116- (void)testCallMethodHandler {
117 NSString* channelName = @"foo";
118 MockBinaryMessenger* binaryMessenger = [[MockBinaryMessenger alloc] init];
119 id codec = OCMProtocolMock(@protocol(FlutterMethodCodec));
120 FlutterMethodChannel* channel = [[FlutterMethodChannel alloc] initWithName:channelName
121 binaryMessenger:binaryMessenger
122 codec:codec];
123 XCTAssertNotNil(channel);
124
125 NSData* encodedMethodCall = [@"encoded" dataUsingEncoding:NSUTF8StringEncoding];
126 NSData* replyData = [@"reply" dataUsingEncoding:NSUTF8StringEncoding];
127 NSData* replyEnvelopeData = [@"reply-envelope" dataUsingEncoding:NSUTF8StringEncoding];
128 FlutterMethodCall* methodCall = [[FlutterMethodCall alloc] init];
129 OCMStub([codec decodeMethodCall:encodedMethodCall]).andReturn(methodCall);
130 OCMStub([codec encodeSuccessEnvelope:replyData]).andReturn(replyEnvelopeData);
131 XCTestExpectation* didCallHandler = [self expectationWithDescription:@"didCallHandler"];
132 XCTestExpectation* didCallReply = [self expectationWithDescription:@"didCallReply"];
134 ^(FlutterMethodCall* _Nonnull call, FlutterResult _Nonnull result) {
135 XCTAssertEqual(methodCall, call);
136 [didCallHandler fulfill];
137 result(replyData);
138 };
139 [channel setMethodCallHandler:handler];
140 binaryMessenger.handlers[channelName](encodedMethodCall, ^(NSData* reply) {
141 [didCallReply fulfill];
142 XCTAssertEqual(replyEnvelopeData, reply);
143 });
144 [self waitForExpectationsWithTimeout:1.0 handler:nil];
145}
146
147- (void)testResize {
148 NSString* channelName = @"flutter/test";
149 id binaryMessenger = OCMStrictProtocolMock(@protocol(FlutterBinaryMessenger));
150 id codec = OCMProtocolMock(@protocol(FlutterMethodCodec));
152 [[FlutterBasicMessageChannel alloc] initWithName:channelName
153 binaryMessenger:binaryMessenger
154 codec:codec];
155 XCTAssertNotNil(channel);
156
157 // The expected content was created from the following Dart code:
158 // MethodCall call = MethodCall('resize', ['flutter/test',3]);
159 // StandardMethodCodec().encodeMethodCall(call).buffer.asUint8List();
160 const unsigned char bytes[] = {7, 6, 114, 101, 115, 105, 122, 101, 12, 2,
161 7, 12, 102, 108, 117, 116, 116, 101, 114, 47,
162 116, 101, 115, 116, 3, 3, 0, 0, 0};
163 NSData* expectedMessage = [NSData dataWithBytes:bytes length:sizeof(bytes)];
164
165 OCMExpect([binaryMessenger sendOnChannel:@"dev.flutter/channel-buffers" message:expectedMessage]);
166 [channel resizeChannelBuffer:3];
167 OCMVerifyAll(binaryMessenger);
168 [binaryMessenger stopMocking];
169}
170
172 NSString* channelName = @"flutter/test";
173 id binaryMessenger = OCMStrictProtocolMock(@protocol(FlutterBinaryMessenger));
174 id codec = OCMProtocolMock(@protocol(FlutterMethodCodec));
176 [[FlutterBasicMessageChannel alloc] initWithName:channelName
177 binaryMessenger:binaryMessenger
178 codec:codec];
179 XCTAssertNotNil(channel);
180
181 // The expected content was created from the following Dart code:
182 // MethodCall call = MethodCall('overflow',['flutter/test', true]);
183 // StandardMethodCodec().encodeMethodCall(call).buffer.asUint8List();
184 const unsigned char bytes[] = {7, 8, 111, 118, 101, 114, 102, 108, 111, 119, 12, 2, 7, 12,
185 102, 108, 117, 116, 116, 101, 114, 47, 116, 101, 115, 116, 1};
186 NSData* expectedMessage = [NSData dataWithBytes:bytes length:sizeof(bytes)];
187
188 OCMExpect([binaryMessenger sendOnChannel:@"dev.flutter/channel-buffers" message:expectedMessage]);
189 [channel setWarnsOnOverflow:NO];
190 OCMVerifyAll(binaryMessenger);
191 [binaryMessenger stopMocking];
192}
193
195 NSString* channelName = @"foo";
196 FlutterBinaryMessengerConnection connection = 123;
197 id binaryMessenger = OCMProtocolMock(@protocol(FlutterBinaryMessenger));
198 id codec = OCMProtocolMock(@protocol(FlutterMethodCodec));
200 [[FlutterBasicMessageChannel alloc] initWithName:channelName
201 binaryMessenger:binaryMessenger
202 codec:codec];
203 FlutterMessageHandler handler = ^(id _Nullable message, FlutterReply callback) {
204 };
205 OCMStub([binaryMessenger setMessageHandlerOnChannel:channelName
206 binaryMessageHandler:[OCMArg any]])
207 .andReturn(connection);
208 [channel setMessageHandler:handler];
209 OCMVerify([binaryMessenger setMessageHandlerOnChannel:channelName
210 binaryMessageHandler:[OCMArg isNotNil]]);
211 [channel setMessageHandler:nil];
212 OCMVerify([binaryMessenger cleanUpConnection:connection]);
213}
214
216 NSString* channelName = @"foo";
217 FlutterBinaryMessengerConnection connection = 123;
218 id binaryMessenger = OCMProtocolMock(@protocol(FlutterBinaryMessenger));
219 id codec = OCMProtocolMock(@protocol(FlutterMethodCodec));
220 FlutterMethodChannel* channel = [[FlutterMethodChannel alloc] initWithName:channelName
221 binaryMessenger:binaryMessenger
222 codec:codec];
223 XCTAssertNotNil(channel);
224
225 OCMStub([binaryMessenger setMessageHandlerOnChannel:channelName
226 binaryMessageHandler:[OCMArg any]])
227 .andReturn(connection);
228
230 ^(FlutterMethodCall* _Nonnull call, FlutterResult _Nonnull result) {
231 };
232 [channel setMethodCallHandler:handler];
233 OCMVerify([binaryMessenger setMessageHandlerOnChannel:channelName
234 binaryMessageHandler:[OCMArg isNotNil]]);
235 [channel setMethodCallHandler:nil];
236 OCMVerify([binaryMessenger cleanUpConnection:connection]);
237}
238
240 NSString* channelName = @"foo";
241 FlutterBinaryMessengerConnection connection = 123;
242 id binaryMessenger = OCMProtocolMock(@protocol(FlutterBinaryMessenger));
243 id codec = OCMProtocolMock(@protocol(FlutterMethodCodec));
244 id taskQueue = OCMProtocolMock(@protocol(FlutterTaskQueueDispatch));
246 [[FlutterBasicMessageChannel alloc] initWithName:channelName
247 binaryMessenger:binaryMessenger
248 codec:codec
249 taskQueue:taskQueue];
250 FlutterMessageHandler handler = ^(id _Nullable message, FlutterReply callback) {
251 };
252 OCMStub([binaryMessenger setMessageHandlerOnChannel:channelName
253 binaryMessageHandler:[OCMArg any]
254 taskQueue:taskQueue])
255 .andReturn(connection);
256 [channel setMessageHandler:handler];
257 OCMVerify([binaryMessenger setMessageHandlerOnChannel:channelName
258 binaryMessageHandler:[OCMArg isNotNil]
259 taskQueue:taskQueue]);
260 [channel setMessageHandler:nil];
261 OCMVerify([binaryMessenger cleanUpConnection:connection]);
262}
263
265 NSString* channelName = @"foo";
266 __block NSString* handlerMessage;
267 __block FlutterBinaryMessageHandler messageHandler;
268 @autoreleasepool {
269 FlutterBinaryMessengerConnection connection = 123;
270 id binaryMessenger = OCMProtocolMock(@protocol(FlutterBinaryMessenger));
271 id codec = OCMProtocolMock(@protocol(FlutterMessageCodec));
272 id taskQueue = OCMProtocolMock(@protocol(FlutterTaskQueueDispatch));
274 [[FlutterBasicMessageChannel alloc] initWithName:channelName
275 binaryMessenger:binaryMessenger
276 codec:codec
277 taskQueue:taskQueue];
278
279 FlutterMessageHandler handler = ^(id _Nullable message, FlutterReply callback) {
280 handlerMessage = message;
281 };
282 OCMStub([binaryMessenger
283 setMessageHandlerOnChannel:channelName
284 binaryMessageHandler:[OCMArg checkWithBlock:^BOOL(
286 messageHandler = handler;
287 return YES;
288 }]
289 taskQueue:taskQueue])
290 .andReturn(connection);
291 OCMStub([codec decode:[OCMArg any]]).andReturn(@"decoded message");
292 [channel setMessageHandler:handler];
293 }
294 // Channel is released, messageHandler should still retain the codec. The codec
295 // internally makes a `decode` call and updates the `handlerMessage` to "decoded message".
296 messageHandler([NSData data], ^(NSData* data){
297 });
298 XCTAssertEqualObjects(handlerMessage, @"decoded message");
299}
300
302 NSString* channelName = @"foo";
303 FlutterBinaryMessengerConnection connection = 123;
304 __block FlutterMethodCall* decodedMethodCall;
305 __block FlutterBinaryMessageHandler messageHandler;
306 @autoreleasepool {
307 id binaryMessenger = OCMProtocolMock(@protocol(FlutterBinaryMessenger));
308 id codec = OCMProtocolMock(@protocol(FlutterMethodCodec));
309 id taskQueue = OCMProtocolMock(@protocol(FlutterTaskQueueDispatch));
310 FlutterMethodChannel* channel = [[FlutterMethodChannel alloc] initWithName:channelName
311 binaryMessenger:binaryMessenger
312 codec:codec
313 taskQueue:taskQueue];
315 decodedMethodCall = call;
316 };
317 OCMStub([binaryMessenger
318 setMessageHandlerOnChannel:channelName
319 binaryMessageHandler:[OCMArg checkWithBlock:^BOOL(
321 messageHandler = handler;
322 return YES;
323 }]
324 taskQueue:taskQueue])
325 .andReturn(connection);
326 OCMStub([codec decodeMethodCall:[OCMArg any]])
327 .andReturn([FlutterMethodCall methodCallWithMethodName:@"decoded method call"
328 arguments:nil]);
329 [channel setMethodCallHandler:handler];
330 }
331 messageHandler([NSData data], ^(NSData* data){
332 });
333 XCTAssertEqualObjects(decodedMethodCall.method, @"decoded method call");
334}
335
337 NSString* channelName = @"foo";
338 FlutterBinaryMessengerConnection connection = 123;
339 id binaryMessenger = OCMProtocolMock(@protocol(FlutterBinaryMessenger));
340 id codec = OCMProtocolMock(@protocol(FlutterMethodCodec));
341 id taskQueue = OCMProtocolMock(@protocol(FlutterTaskQueueDispatch));
342 FlutterMethodChannel* channel = [[FlutterMethodChannel alloc] initWithName:channelName
343 binaryMessenger:binaryMessenger
344 codec:codec
345 taskQueue:taskQueue];
346 XCTAssertNotNil(channel);
348 };
349 OCMStub([binaryMessenger setMessageHandlerOnChannel:channelName
350 binaryMessageHandler:[OCMArg any]
351 taskQueue:taskQueue])
352 .andReturn(connection);
353 [channel setMethodCallHandler:handler];
354 OCMVerify([binaryMessenger setMessageHandlerOnChannel:channelName
355 binaryMessageHandler:[OCMArg isNotNil]
356 taskQueue:taskQueue]);
357 [channel setMethodCallHandler:nil];
358 OCMVerify([binaryMessenger cleanUpConnection:connection]);
359}
360
362 NSString* channelName = @"foo";
363 FlutterBinaryMessengerConnection connection = 123;
364 id binaryMessenger = OCMProtocolMock(@protocol(FlutterBinaryMessenger));
365 id codec = OCMProtocolMock(@protocol(FlutterMethodCodec));
366 id taskQueue = OCMProtocolMock(@protocol(FlutterTaskQueueDispatch));
367 id handler = OCMProtocolMock(@protocol(FlutterStreamHandler));
368 FlutterEventChannel* channel = [[FlutterEventChannel alloc] initWithName:channelName
369 binaryMessenger:binaryMessenger
370 codec:codec
371 taskQueue:taskQueue];
372 XCTAssertNotNil(channel);
373 OCMStub([binaryMessenger setMessageHandlerOnChannel:channelName
374 binaryMessageHandler:[OCMArg any]
375 taskQueue:taskQueue])
376 .andReturn(connection);
377 [channel setStreamHandler:handler];
378 OCMVerify([binaryMessenger setMessageHandlerOnChannel:channelName
379 binaryMessageHandler:[OCMArg isNotNil]
380 taskQueue:taskQueue]);
381 [channel setStreamHandler:nil];
382 OCMVerify([binaryMessenger cleanUpConnection:connection]);
383}
384
385@end
NS_ASSUME_NONNULL_BEGIN typedef void(^ FlutterBinaryReply)(NSData *_Nullable reply)
void(^ FlutterBinaryMessageHandler)(NSData *_Nullable message, FlutterBinaryReply reply)
int64_t FlutterBinaryMessengerConnection
void(^ FlutterResult)(id _Nullable result)
void(^ FlutterMethodCallHandler)(FlutterMethodCall *call, FlutterResult result)
void(^ FlutterMessageHandler)(id _Nullable message, FlutterReply callback)
NS_ASSUME_NONNULL_BEGIN typedef void(^ FlutterReply)(id _Nullable reply)
static void copy(void *dst, const uint8_t *src, int width, int bpp, int deltaSrc, int offset, const SkPMColor ctable[])
Definition: SkSwizzler.cpp:31
FlKeyEvent uint64_t FlKeyResponderAsyncCallback callback
GAsyncResult * result
void setMessageHandler:(FlutterMessageHandler _Nullable handler)
void setWarnsOnOverflow:(BOOL warns)
void resizeChannelBuffer:(NSInteger newSize)
void testBasicMessageChannelInvokeHandlerAfterChannelReleased()
void testMethodChannelInvokeHandlerAfterChannelReleased()
void setStreamHandler:(NSObject< FlutterStreamHandler > *_Nullable handler)
void setMethodCallHandler:(FlutterMethodCallHandler _Nullable handler)
void invokeMethod:arguments:(NSString *method,[arguments] id _Nullable arguments)
void invokeMethod:arguments:result:(NSString *method,[arguments] id _Nullable arguments,[result] FlutterResult _Nullable callback)
NSMutableDictionary< NSString *, FlutterBinaryMessageHandler > * handlers
def call(args)
Definition: dom.py:159
SIT bool any(const Vec< 1, T > &x)
Definition: SkVx.h:530
static DecodeResult decode(std::string path)
Definition: png_codec.cpp:124
std::shared_ptr< const fml::Mapping > data
Definition: texture_gles.cc:63
int BOOL
Definition: windows_types.h:37