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 #if !__has_feature(objc_arc)
6 #error ARC must be enabled!
7 #endif
8 
9 #import "flutter/shell/platform/darwin/common/framework/Headers/FlutterChannels.h"
10 
11 #import <OCMock/OCMock.h>
12 #import <XCTest/XCTest.h>
13 
14 @interface MockBinaryMessenger : NSObject <FlutterBinaryMessenger>
15 @property(nonatomic, copy) NSString* channel;
16 @property(nonatomic, strong) NSData* message;
17 @property(nonatomic, strong) NSMutableDictionary<NSString*, FlutterBinaryMessageHandler>* handlers;
18 @end
19 @implementation MockBinaryMessenger
20 - (instancetype)init {
21  self = [super init];
22  if (self) {
23  _handlers = [[NSMutableDictionary<NSString*, FlutterBinaryMessageHandler> alloc] init];
24  }
25  return self;
26 }
27 
28 - (void)sendOnChannel:(NSString*)channel message:(NSData* _Nullable)message {
29  [self sendOnChannel:channel message:message binaryReply:nil];
30 }
31 
32 - (void)sendOnChannel:(NSString*)channel
33  message:(NSData* _Nullable)message
34  binaryReply:(FlutterBinaryReply _Nullable)callback {
35  self.channel = channel;
36  self.message = message;
37 }
38 
39 - (FlutterBinaryMessengerConnection)setMessageHandlerOnChannel:(NSString*)channel
40  binaryMessageHandler:
41  (FlutterBinaryMessageHandler _Nullable)handler {
42  [self.handlers setObject:handler forKey:channel];
43  return 0;
44 }
45 
46 - (void)cleanupConnection:(FlutterBinaryMessengerConnection)connection {
47 }
48 
49 @end
50 
51 @interface FlutterChannelsTest : XCTestCase
52 @end
53 
54 @implementation FlutterChannelsTest
55 
56 - (void)testMethodInvoke {
57  NSString* channelName = @"foo";
58  id binaryMessenger = OCMProtocolMock(@protocol(FlutterBinaryMessenger));
59  id codec = OCMProtocolMock(@protocol(FlutterMethodCodec));
60  FlutterMethodChannel* channel = [[FlutterMethodChannel alloc] initWithName:channelName
61  binaryMessenger:binaryMessenger
62  codec:codec];
63  XCTAssertNotNil(channel);
64  NSData* encodedMethodCall = [@"hey" dataUsingEncoding:NSUTF8StringEncoding];
65  OCMStub([codec encodeMethodCall:[OCMArg any]]).andReturn(encodedMethodCall);
66  [channel invokeMethod:@"foo" arguments:@[ @(1) ]];
67  OCMVerify([binaryMessenger sendOnChannel:channelName message:encodedMethodCall]);
68 }
69 
70 - (void)testMethodInvokeWithReply {
71  NSString* channelName = @"foo";
72  id binaryMessenger = OCMProtocolMock(@protocol(FlutterBinaryMessenger));
73  id codec = OCMProtocolMock(@protocol(FlutterMethodCodec));
74  FlutterMethodChannel* channel = [[FlutterMethodChannel alloc] initWithName:channelName
75  binaryMessenger:binaryMessenger
76  codec:codec];
77  XCTAssertNotNil(channel);
78  NSData* encodedMethodCall = [@"hey" dataUsingEncoding:NSUTF8StringEncoding];
79  OCMStub([codec encodeMethodCall:[OCMArg any]]).andReturn(encodedMethodCall);
80  XCTestExpectation* didCallReply = [self expectationWithDescription:@"didCallReply"];
81  OCMExpect([binaryMessenger sendOnChannel:channelName
82  message:encodedMethodCall
83  binaryReply:[OCMArg checkWithBlock:^BOOL(id obj) {
84  FlutterBinaryReply reply = obj;
85  reply(nil);
86  return YES;
87  }]]);
88  [channel invokeMethod:@"foo"
89  arguments:@[ @1 ]
90  result:^(id _Nullable result) {
91  [didCallReply fulfill];
92  XCTAssertEqual(FlutterMethodNotImplemented, result);
93  }];
94  OCMVerifyAll(binaryMessenger);
95  [self waitForExpectationsWithTimeout:1.0 handler:nil];
96 }
97 
98 - (void)testMethodMessageHandler {
99  NSString* channelName = @"foo";
100  id binaryMessenger = OCMProtocolMock(@protocol(FlutterBinaryMessenger));
101  id codec = OCMProtocolMock(@protocol(FlutterMethodCodec));
102  FlutterMethodChannel* channel = [[FlutterMethodChannel alloc] initWithName:channelName
103  binaryMessenger:binaryMessenger
104  codec:codec];
105  XCTAssertNotNil(channel);
106 
107  NSData* encodedMethodCall = [@"hey" dataUsingEncoding:NSUTF8StringEncoding];
108  OCMStub([codec encodeMethodCall:[OCMArg any]]).andReturn(encodedMethodCall);
109  FlutterMethodCallHandler handler =
110  ^(FlutterMethodCall* _Nonnull call, FlutterResult _Nonnull result) {
111  NSLog(@"hey");
112  };
113  [channel setMethodCallHandler:handler];
114  OCMVerify([binaryMessenger setMessageHandlerOnChannel:channelName
115  binaryMessageHandler:[OCMArg isNotNil]]);
116 }
117 
118 - (void)testCallMethodHandler {
119  NSString* channelName = @"foo";
120  MockBinaryMessenger* binaryMessenger = [[MockBinaryMessenger alloc] init];
121  id codec = OCMProtocolMock(@protocol(FlutterMethodCodec));
122  FlutterMethodChannel* channel = [[FlutterMethodChannel alloc] initWithName:channelName
123  binaryMessenger:binaryMessenger
124  codec:codec];
125  XCTAssertNotNil(channel);
126 
127  NSData* encodedMethodCall = [@"encoded" dataUsingEncoding:NSUTF8StringEncoding];
128  NSData* replyData = [@"reply" dataUsingEncoding:NSUTF8StringEncoding];
129  NSData* replyEnvelopeData = [@"reply-envelope" dataUsingEncoding:NSUTF8StringEncoding];
130  FlutterMethodCall* methodCall = [[FlutterMethodCall alloc] init];
131  OCMStub([codec decodeMethodCall:encodedMethodCall]).andReturn(methodCall);
132  OCMStub([codec encodeSuccessEnvelope:replyData]).andReturn(replyEnvelopeData);
133  XCTestExpectation* didCallHandler = [self expectationWithDescription:@"didCallHandler"];
134  XCTestExpectation* didCallReply = [self expectationWithDescription:@"didCallReply"];
135  FlutterMethodCallHandler handler =
136  ^(FlutterMethodCall* _Nonnull call, FlutterResult _Nonnull result) {
137  XCTAssertEqual(methodCall, call);
138  [didCallHandler fulfill];
139  result(replyData);
140  };
141  [channel setMethodCallHandler:handler];
142  binaryMessenger.handlers[channelName](encodedMethodCall, ^(NSData* reply) {
143  [didCallReply fulfill];
144  XCTAssertEqual(replyEnvelopeData, reply);
145  });
146  [self waitForExpectationsWithTimeout:1.0 handler:nil];
147 }
148 
149 - (void)testResize {
150  NSString* channelName = @"foo";
151  id binaryMessenger = OCMStrictProtocolMock(@protocol(FlutterBinaryMessenger));
152  id codec = OCMProtocolMock(@protocol(FlutterMethodCodec));
154  [[FlutterBasicMessageChannel alloc] initWithName:channelName
155  binaryMessenger:binaryMessenger
156  codec:codec];
157  XCTAssertNotNil(channel);
158 
159  NSString* expectedMessageString =
160  [NSString stringWithFormat:@"resize\r%@\r%@", channelName, @100];
161  NSData* expectedMessage = [expectedMessageString dataUsingEncoding:NSUTF8StringEncoding];
162  OCMExpect([binaryMessenger sendOnChannel:@"dev.flutter/channel-buffers" message:expectedMessage]);
163  [channel resizeChannelBuffer:100];
164  OCMVerifyAll(binaryMessenger);
165  [binaryMessenger stopMocking];
166 }
167 
168 - (void)testBasicMessageChannelCleanup {
169  NSString* channelName = @"foo";
170  FlutterBinaryMessengerConnection connection = 123;
171  id binaryMessenger = OCMProtocolMock(@protocol(FlutterBinaryMessenger));
172  id codec = OCMProtocolMock(@protocol(FlutterMethodCodec));
174  [[FlutterBasicMessageChannel alloc] initWithName:channelName
175  binaryMessenger:binaryMessenger
176  codec:codec];
177  FlutterMessageHandler handler = ^(id _Nullable message, FlutterReply callback) {
178  NSLog(@"hey");
179  };
180  OCMStub([binaryMessenger setMessageHandlerOnChannel:channelName
181  binaryMessageHandler:[OCMArg any]])
182  .andReturn(connection);
183  [channel setMessageHandler:handler];
184  OCMVerify([binaryMessenger setMessageHandlerOnChannel:channelName
185  binaryMessageHandler:[OCMArg isNotNil]]);
186  [channel setMessageHandler:nil];
187  OCMVerify([binaryMessenger cleanupConnection:connection]);
188 }
189 
190 - (void)testMethodChannelCleanup {
191  NSString* channelName = @"foo";
192  FlutterBinaryMessengerConnection connection = 123;
193  id binaryMessenger = OCMProtocolMock(@protocol(FlutterBinaryMessenger));
194  id codec = OCMProtocolMock(@protocol(FlutterMethodCodec));
195  FlutterMethodChannel* channel = [[FlutterMethodChannel alloc] initWithName:channelName
196  binaryMessenger:binaryMessenger
197  codec:codec];
198  XCTAssertNotNil(channel);
199 
200  OCMStub([binaryMessenger setMessageHandlerOnChannel:channelName
201  binaryMessageHandler:[OCMArg any]])
202  .andReturn(connection);
203 
204  FlutterMethodCallHandler handler =
205  ^(FlutterMethodCall* _Nonnull call, FlutterResult _Nonnull result) {
206  };
207  [channel setMethodCallHandler:handler];
208  OCMVerify([binaryMessenger setMessageHandlerOnChannel:channelName
209  binaryMessageHandler:[OCMArg isNotNil]]);
210  [channel setMethodCallHandler:nil];
211  OCMVerify([binaryMessenger cleanupConnection:connection]);
212 }
213 
214 @end
void setMessageHandler:(FlutterMessageHandler _Nullable handler)
NS_ASSUME_NONNULL_BEGIN typedef void(^ FlutterBinaryReply)(NSData *_Nullable reply)
void(^ FlutterMethodCallHandler)(FlutterMethodCall *call, FlutterResult result)
void resizeChannelBuffer:(NSInteger newSize)
void(^ FlutterBinaryMessageHandler)(NSData *_Nullable message, FlutterBinaryReply reply)
void invokeMethod:arguments:result:(NSString *method, [arguments] id _Nullable arguments, [result] FlutterResult _Nullable callback)
void(^ FlutterMessageHandler)(id _Nullable message, FlutterReply callback)
void(^ FlutterResult)(id _Nullable result)
void invokeMethod:arguments:(NSString *method, [arguments] id _Nullable arguments)
NS_ASSUME_NONNULL_BEGIN typedef void(^ FlutterReply)(id _Nullable reply)
void setMethodCallHandler:(FlutterMethodCallHandler _Nullable handler)
NSMutableDictionary< NSString *, FlutterBinaryMessageHandler > * handlers
int64_t FlutterBinaryMessengerConnection