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#include "flutter/shell/platform/darwin/common/framework/Headers/FlutterCodecs.h" 6#include "gtest/gtest.h" 7 8void checkEncodeDecode(id value, NSData* expectedEncoding) { 9 FlutterStandardMessageCodec* codec = [FlutterStandardMessageCodec sharedInstance]; 10 NSData* encoded = [codec encode:value]; 11 if (expectedEncoding == nil) 12 ASSERT_TRUE(encoded == nil); 13 else 14 ASSERT_TRUE([encoded isEqual:expectedEncoding]); 15 id decoded = [codec decode:encoded]; 16 if (value == nil || value == [NSNull null]) 17 ASSERT_TRUE(decoded == nil); 18 else 19 ASSERT_TRUE([value isEqual:decoded]); 20} 21 22void checkEncodeDecode(id value) { 23 FlutterStandardMessageCodec* codec = [FlutterStandardMessageCodec sharedInstance]; 24 NSData* encoded = [codec encode:value]; 25 id decoded = [codec decode:encoded]; 26 if (value == nil || value == [NSNull null]) 27 ASSERT_TRUE(decoded == nil); 28 else 29 ASSERT_TRUE([value isEqual:decoded]); 30} 31 32TEST(FlutterStandardCodec, CanEncodeAndDecodeNil) { 33 checkEncodeDecode(nil, nil); 34} 35 36TEST(FlutterStandardCodec, CanEncodeAndDecodeNSNull) { 37 uint8_t bytes[1] = {0x00}; 38 checkEncodeDecode([NSNull null], [NSData dataWithBytes:bytes length:1]); 39} 40 41TEST(FlutterStandardCodec, CanEncodeAndDecodeYes) { 42 uint8_t bytes[1] = {0x01}; 43 checkEncodeDecode(@YES, [NSData dataWithBytes:bytes length:1]); 44} 45 46TEST(FlutterStandardCodec, CanEncodeAndDecodeNo) { 47 uint8_t bytes[1] = {0x02}; 48 checkEncodeDecode(@NO, [NSData dataWithBytes:bytes length:1]); 49} 50 51TEST(FlutterStandardCodec, CanEncodeAndDecodeUInt8) { 52 uint8_t bytes[5] = {0x03, 0xfe, 0x00, 0x00, 0x00}; 53 UInt8 value = 0xfe; 54 checkEncodeDecode(@(value), [NSData dataWithBytes:bytes length:5]); 55} 56 57TEST(FlutterStandardCodec, CanEncodeAndDecodeUInt16) { 58 uint8_t bytes[5] = {0x03, 0xdc, 0xfe, 0x00, 0x00}; 59 UInt16 value = 0xfedc; 60 checkEncodeDecode(@(value), [NSData dataWithBytes:bytes length:5]); 61} 62 63TEST(FlutterStandardCodec, CanEncodeAndDecodeUInt32) { 64 uint8_t bytes[9] = {0x04, 0x09, 0xba, 0xdc, 0xfe, 0x00, 0x00, 0x00, 0x00}; 65 UInt32 value = 0xfedcba09; 66 checkEncodeDecode(@(value), [NSData dataWithBytes:bytes length:9]); 67} 68 69TEST(FlutterStandardCodec, CanEncodeUInt64) { 70 FlutterStandardMessageCodec* codec = [FlutterStandardMessageCodec sharedInstance]; 71 UInt64 u64 = 0xfffffffffffffffa; 72 uint8_t bytes[9] = {0x04, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; 73 NSData* encoded = [codec encode:@(u64)]; 74 ASSERT_TRUE([encoded isEqual:[NSData dataWithBytes:bytes length:9]]); 75} 76 77TEST(FlutterStandardCodec, CanEncodeAndDecodeSInt8) { 78 uint8_t bytes[5] = {0x03, 0xfe, 0xff, 0xff, 0xff}; 79 SInt8 value = 0xfe; 80 checkEncodeDecode(@(value), [NSData dataWithBytes:bytes length:5]); 81} 82 83TEST(FlutterStandardCodec, CanEncodeAndDecodeSInt16) { 84 uint8_t bytes[5] = {0x03, 0xdc, 0xfe, 0xff, 0xff}; 85 SInt16 value = 0xfedc; 86 checkEncodeDecode(@(value), [NSData dataWithBytes:bytes length:5]); 87} 88 89TEST(FlutterStandardCodec, CanEncodeAndDecodeSInt32) { 90 uint8_t bytes[5] = {0x03, 0x78, 0x56, 0x34, 0x12}; 91 checkEncodeDecode(@(0x12345678), [NSData dataWithBytes:bytes length:5]); 92} 93 94TEST(FlutterStandardCodec, CanEncodeAndDecodeSInt64) { 95 uint8_t bytes[9] = {0x04, 0xef, 0xcd, 0xab, 0x90, 0x78, 0x56, 0x34, 0x12}; 96 checkEncodeDecode(@(0x1234567890abcdef), [NSData dataWithBytes:bytes length:9]); 97} 98 99TEST(FlutterStandardCodec, CanEncodeAndDecodeFloat32) { 100 uint8_t bytes[16] = {0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 101 0x00, 0x00, 0x00, 0x60, 0xfb, 0x21, 0x09, 0x40}; 102 checkEncodeDecode(@3.1415927f, [NSData dataWithBytes:bytes length:16]); 103} 104 105TEST(FlutterStandardCodec, CanEncodeAndDecodeFloat64) { 106 uint8_t bytes[16] = {0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 107 0x18, 0x2d, 0x44, 0x54, 0xfb, 0x21, 0x09, 0x40}; 108 checkEncodeDecode(@3.14159265358979311599796346854, [NSData dataWithBytes:bytes length:16]); 109} 110 111TEST(FlutterStandardCodec, CanEncodeAndDecodeString) { 112 uint8_t bytes[13] = {0x07, 0x0b, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 113 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64}; 114 checkEncodeDecode(@"hello world", [NSData dataWithBytes:bytes length:13]); 115} 116 117TEST(FlutterStandardCodec, CanEncodeAndDecodeStringWithNonAsciiCodePoint) { 118 uint8_t bytes[7] = {0x07, 0x05, 0x68, 0xe2, 0x98, 0xba, 0x77}; 119 checkEncodeDecode(@"h\u263Aw", [NSData dataWithBytes:bytes length:7]); 120} 121 122TEST(FlutterStandardCodec, CanEncodeAndDecodeStringWithNonBMPCodePoint) { 123 uint8_t bytes[8] = {0x07, 0x06, 0x68, 0xf0, 0x9f, 0x98, 0x82, 0x77}; 124 checkEncodeDecode(@"h\U0001F602w", [NSData dataWithBytes:bytes length:8]); 125} 126 127TEST(FlutterStandardCodec, CanEncodeAndDecodeArray) { 128 NSArray* value = @[ [NSNull null], @"hello", @3.14, @47, @{@42 : @"nested"} ]; 129 checkEncodeDecode(value); 130} 131 132TEST(FlutterStandardCodec, CanEncodeAndDecodeDictionary) { 133 NSDictionary* value = 134 @{@"a" : @3.14, 135 @"b" : @47, 136 [NSNull null] : [NSNull null], 137 @3.14 : @[ @"nested" ]}; 138 checkEncodeDecode(value); 139} 140 141TEST(FlutterStandardCodec, CanEncodeAndDecodeByteArray) { 142 uint8_t bytes[4] = {0xBA, 0x5E, 0xBA, 0x11}; 143 NSData* data = [NSData dataWithBytes:bytes length:4]; 144 FlutterStandardTypedData* value = [FlutterStandardTypedData typedDataWithBytes:data]; 145 checkEncodeDecode(value); 146} 147 148TEST(FlutterStandardCodec, CanEncodeAndDecodeNSData) { 149 FlutterStandardMessageCodec* codec = [FlutterStandardMessageCodec sharedInstance]; 150 uint8_t bytes[4] = {0xBA, 0x5E, 0xBA, 0x11}; 151 NSData* data = [NSData dataWithBytes:bytes length:4]; 152 FlutterStandardTypedData* standardData = [FlutterStandardTypedData typedDataWithBytes:data]; 153 154 NSData* encoded = [codec encode:data]; 155 ASSERT_TRUE([encoded isEqual:[codec encode:standardData]]); 156} 157 158TEST(FlutterStandardCodec, CanEncodeAndDecodeInt32Array) { 159 uint8_t bytes[8] = {0xBA, 0x5E, 0xBA, 0x11, 0xff, 0xff, 0xff, 0xff}; 160 NSData* data = [NSData dataWithBytes:bytes length:8]; 161 FlutterStandardTypedData* value = [FlutterStandardTypedData typedDataWithInt32:data]; 162 checkEncodeDecode(value); 163} 164 165TEST(FlutterStandardCodec, CanEncodeAndDecodeInt64Array) { 166 uint8_t bytes[8] = {0xBA, 0x5E, 0xBA, 0x11, 0xff, 0xff, 0xff, 0xff}; 167 NSData* data = [NSData dataWithBytes:bytes length:8]; 168 FlutterStandardTypedData* value = [FlutterStandardTypedData typedDataWithInt64:data]; 169 checkEncodeDecode(value); 170} 171 172TEST(FlutterStandardCodec, CanEncodeAndDecodeFloat64Array) { 173 uint8_t bytes[16] = {0xBA, 0x5E, 0xBA, 0x11, 0xff, 0xff, 0xff, 0xff, 174 0xBA, 0x5E, 0xBA, 0x11, 0xff, 0xff, 0xff, 0xff}; 175 NSData* data = [NSData dataWithBytes:bytes length:16]; 176 FlutterStandardTypedData* value = [FlutterStandardTypedData typedDataWithFloat64:data]; 177 checkEncodeDecode(value); 178} 179 180TEST(FlutterStandardCodec, HandlesMethodCallsWithNilArguments) { 181 FlutterStandardMethodCodec* codec = [FlutterStandardMethodCodec sharedInstance]; 182 FlutterMethodCall* call = [FlutterMethodCall methodCallWithMethodName:@"hello" arguments:nil]; 183 NSData* encoded = [codec encodeMethodCall:call]; 184 FlutterMethodCall* decoded = [codec decodeMethodCall:encoded]; 185 ASSERT_TRUE([decoded isEqual:call]); 186} 187 188TEST(FlutterStandardCodec, HandlesMethodCallsWithSingleArgument) { 189 FlutterStandardMethodCodec* codec = [FlutterStandardMethodCodec sharedInstance]; 190 FlutterMethodCall* call = [FlutterMethodCall methodCallWithMethodName:@"hello" arguments:@42]; 191 NSData* encoded = [codec encodeMethodCall:call]; 192 FlutterMethodCall* decoded = [codec decodeMethodCall:encoded]; 193 ASSERT_TRUE([decoded isEqual:call]); 194} 195 196TEST(FlutterStandardCodec, HandlesMethodCallsWithArgumentList) { 197 FlutterStandardMethodCodec* codec = [FlutterStandardMethodCodec sharedInstance]; 198 NSArray* arguments = @[ @42, @"world" ]; 199 FlutterMethodCall* call = [FlutterMethodCall methodCallWithMethodName:@"hello" 200 arguments:arguments]; 201 NSData* encoded = [codec encodeMethodCall:call]; 202 FlutterMethodCall* decoded = [codec decodeMethodCall:encoded]; 203 ASSERT_TRUE([decoded isEqual:call]); 204} 205 206TEST(FlutterStandardCodec, HandlesSuccessEnvelopesWithNilResult) { 207 FlutterStandardMethodCodec* codec = [FlutterStandardMethodCodec sharedInstance]; 208 NSData* encoded = [codec encodeSuccessEnvelope:nil]; 209 id decoded = [codec decodeEnvelope:encoded]; 210 ASSERT_TRUE(decoded == nil); 211} 212 213TEST(FlutterStandardCodec, HandlesSuccessEnvelopesWithSingleResult) { 214 FlutterStandardMethodCodec* codec = [FlutterStandardMethodCodec sharedInstance]; 215 NSData* encoded = [codec encodeSuccessEnvelope:@42]; 216 id decoded = [codec decodeEnvelope:encoded]; 217 ASSERT_TRUE([decoded isEqual:@42]); 218} 219 220TEST(FlutterStandardCodec, HandlesSuccessEnvelopesWithResultMap) { 221 FlutterStandardMethodCodec* codec = [FlutterStandardMethodCodec sharedInstance]; 222 NSDictionary* result = @{@"a" : @42, @42 : @"a"}; 223 NSData* encoded = [codec encodeSuccessEnvelope:result]; 224 id decoded = [codec decodeEnvelope:encoded]; 225 ASSERT_TRUE([decoded isEqual:result]); 226} 227 228TEST(FlutterStandardCodec, HandlesErrorEnvelopes) { 229 FlutterStandardMethodCodec* codec = [FlutterStandardMethodCodec sharedInstance]; 230 NSDictionary* details = @{@"a" : @42, @42 : @"a"}; 231 FlutterError* error = [FlutterError errorWithCode:@"errorCode" 232 message:@"something failed" 233 details:details]; 234 NSData* encoded = [codec encodeErrorEnvelope:error]; 235 id decoded = [codec decodeEnvelope:encoded]; 236 ASSERT_TRUE([decoded isEqual:error]); 237} 238