1// Copyright 2017 The Chromium 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 5import 'dart:async'; 6import 'dart:typed_data'; 7import 'package:flutter/services.dart'; 8import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer; 9import 'pair.dart'; 10import 'test_step.dart'; 11 12class ExtendedStandardMessageCodec extends StandardMessageCodec { 13 const ExtendedStandardMessageCodec(); 14 15 static const int _dateTime = 128; 16 static const int _pair = 129; 17 18 @override 19 void writeValue(WriteBuffer buffer, dynamic value) { 20 if (value is DateTime) { 21 buffer.putUint8(_dateTime); 22 buffer.putInt64(value.millisecondsSinceEpoch); 23 } else if (value is Pair) { 24 buffer.putUint8(_pair); 25 writeValue(buffer, value.left); 26 writeValue(buffer, value.right); 27 } else { 28 super.writeValue(buffer, value); 29 } 30 } 31 32 @override 33 dynamic readValueOfType(int type, ReadBuffer buffer) { 34 switch (type) { 35 case _dateTime: 36 return DateTime.fromMillisecondsSinceEpoch(buffer.getInt64()); 37 case _pair: 38 return Pair(readValue(buffer), readValue(buffer)); 39 default: return super.readValueOfType(type, buffer); 40 } 41 } 42} 43 44Future<TestStepResult> basicBinaryHandshake(ByteData message) async { 45 const BasicMessageChannel<ByteData> channel = 46 BasicMessageChannel<ByteData>( 47 'binary-msg', 48 BinaryCodec(), 49 ); 50 return _basicMessageHandshake<ByteData>( 51 'Binary >${toString(message)}<', channel, message); 52} 53 54Future<TestStepResult> basicStringHandshake(String message) async { 55 const BasicMessageChannel<String> channel = BasicMessageChannel<String>( 56 'string-msg', 57 StringCodec(), 58 ); 59 return _basicMessageHandshake<String>('String >$message<', channel, message); 60} 61 62Future<TestStepResult> basicJsonHandshake(dynamic message) async { 63 const BasicMessageChannel<dynamic> channel = 64 BasicMessageChannel<dynamic>( 65 'json-msg', 66 JSONMessageCodec(), 67 ); 68 return _basicMessageHandshake<dynamic>('JSON >$message<', channel, message); 69} 70 71Future<TestStepResult> basicStandardHandshake(dynamic message) async { 72 const BasicMessageChannel<dynamic> channel = 73 BasicMessageChannel<dynamic>( 74 'std-msg', 75 ExtendedStandardMessageCodec(), 76 ); 77 return _basicMessageHandshake<dynamic>( 78 'Standard >${toString(message)}<', channel, message); 79} 80 81Future<TestStepResult> basicBinaryMessageToUnknownChannel() async { 82 const BasicMessageChannel<ByteData> channel = 83 BasicMessageChannel<ByteData>( 84 'binary-unknown', 85 BinaryCodec(), 86 ); 87 return _basicMessageToUnknownChannel<ByteData>('Binary', channel); 88} 89 90Future<TestStepResult> basicStringMessageToUnknownChannel() async { 91 const BasicMessageChannel<String> channel = BasicMessageChannel<String>( 92 'string-unknown', 93 StringCodec(), 94 ); 95 return _basicMessageToUnknownChannel<String>('String', channel); 96} 97 98Future<TestStepResult> basicJsonMessageToUnknownChannel() async { 99 const BasicMessageChannel<dynamic> channel = 100 BasicMessageChannel<dynamic>( 101 'json-unknown', 102 JSONMessageCodec(), 103 ); 104 return _basicMessageToUnknownChannel<dynamic>('JSON', channel); 105} 106 107Future<TestStepResult> basicStandardMessageToUnknownChannel() async { 108 const BasicMessageChannel<dynamic> channel = 109 BasicMessageChannel<dynamic>( 110 'std-unknown', 111 ExtendedStandardMessageCodec(), 112 ); 113 return _basicMessageToUnknownChannel<dynamic>('Standard', channel); 114} 115 116/// Sends the specified message to the platform, doing a 117/// receive message/send reply/receive reply echo handshake initiated by the 118/// platform, then expecting a reply echo to the original message. 119/// 120/// Fails, if an error occurs, or if any message seen is not deeply equal to 121/// the original message. 122Future<TestStepResult> _basicMessageHandshake<T>( 123 String description, 124 BasicMessageChannel<T> channel, 125 T message, 126) async { 127 final List<dynamic> received = <dynamic>[]; 128 channel.setMessageHandler((T message) async { 129 received.add(message); 130 return message; 131 }); 132 dynamic messageEcho = nothing; 133 dynamic error = nothing; 134 try { 135 messageEcho = await channel.send(message); 136 } catch (e) { 137 error = e; 138 } 139 return resultOfHandshake( 140 'Basic message handshake', 141 description, 142 message, 143 received, 144 messageEcho, 145 error, 146 ); 147} 148 149/// Sends a message on a channel that no one listens on. 150Future<TestStepResult> _basicMessageToUnknownChannel<T>( 151 String description, 152 BasicMessageChannel<T> channel, 153) async { 154 dynamic messageEcho = nothing; 155 dynamic error = nothing; 156 try { 157 messageEcho = await channel.send(null); 158 } catch (e) { 159 error = e; 160 } 161 return resultOfHandshake( 162 'Message on unknown channel', 163 description, 164 null, 165 <dynamic>[null, null], 166 messageEcho, 167 error, 168 ); 169} 170 171String toString(dynamic message) { 172 if (message is ByteData) 173 return message.buffer 174 .asUint8List(message.offsetInBytes, message.lengthInBytes) 175 .toString(); 176 else 177 return '$message'; 178} 179