| // Copyright 2017 The Chromium 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 'dart:async'; | |
| import 'dart:typed_data'; | |
| import 'package:flutter/services.dart'; | |
| import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer; | |
| import 'pair.dart'; | |
| import 'test_step.dart'; | |
| class ExtendedStandardMessageCodec extends StandardMessageCodec { | |
| const ExtendedStandardMessageCodec(); | |
| static const int _dateTime = 128; | |
| static const int _pair = 129; | |
| @override | |
| void writeValue(WriteBuffer buffer, dynamic value) { | |
| if (value is DateTime) { | |
| buffer.putUint8(_dateTime); | |
| buffer.putInt64(value.millisecondsSinceEpoch); | |
| } else if (value is Pair) { | |
| buffer.putUint8(_pair); | |
| writeValue(buffer, value.left); | |
| writeValue(buffer, value.right); | |
| } else { | |
| super.writeValue(buffer, value); | |
| } | |
| } | |
| @override | |
| dynamic readValueOfType(int type, ReadBuffer buffer) { | |
| switch (type) { | |
| case _dateTime: | |
| return DateTime.fromMillisecondsSinceEpoch(buffer.getInt64()); | |
| case _pair: | |
| return Pair(readValue(buffer), readValue(buffer)); | |
| default: return super.readValueOfType(type, buffer); | |
| } | |
| } | |
| } | |
| Future<TestStepResult> basicBinaryHandshake(ByteData message) async { | |
| const BasicMessageChannel<ByteData> channel = | |
| BasicMessageChannel<ByteData>( | |
| 'binary-msg', | |
| BinaryCodec(), | |
| ); | |
| return _basicMessageHandshake<ByteData>( | |
| 'Binary >${toString(message)}<', channel, message); | |
| } | |
| Future<TestStepResult> basicStringHandshake(String message) async { | |
| const BasicMessageChannel<String> channel = BasicMessageChannel<String>( | |
| 'string-msg', | |
| StringCodec(), | |
| ); | |
| return _basicMessageHandshake<String>('String >$message<', channel, message); | |
| } | |
| Future<TestStepResult> basicJsonHandshake(dynamic message) async { | |
| const BasicMessageChannel<dynamic> channel = | |
| BasicMessageChannel<dynamic>( | |
| 'json-msg', | |
| JSONMessageCodec(), | |
| ); | |
| return _basicMessageHandshake<dynamic>('JSON >$message<', channel, message); | |
| } | |
| Future<TestStepResult> basicStandardHandshake(dynamic message) async { | |
| const BasicMessageChannel<dynamic> channel = | |
| BasicMessageChannel<dynamic>( | |
| 'std-msg', | |
| ExtendedStandardMessageCodec(), | |
| ); | |
| return _basicMessageHandshake<dynamic>( | |
| 'Standard >${toString(message)}<', channel, message); | |
| } | |
| Future<TestStepResult> basicBinaryMessageToUnknownChannel() async { | |
| const BasicMessageChannel<ByteData> channel = | |
| BasicMessageChannel<ByteData>( | |
| 'binary-unknown', | |
| BinaryCodec(), | |
| ); | |
| return _basicMessageToUnknownChannel<ByteData>('Binary', channel); | |
| } | |
| Future<TestStepResult> basicStringMessageToUnknownChannel() async { | |
| const BasicMessageChannel<String> channel = BasicMessageChannel<String>( | |
| 'string-unknown', | |
| StringCodec(), | |
| ); | |
| return _basicMessageToUnknownChannel<String>('String', channel); | |
| } | |
| Future<TestStepResult> basicJsonMessageToUnknownChannel() async { | |
| const BasicMessageChannel<dynamic> channel = | |
| BasicMessageChannel<dynamic>( | |
| 'json-unknown', | |
| JSONMessageCodec(), | |
| ); | |
| return _basicMessageToUnknownChannel<dynamic>('JSON', channel); | |
| } | |
| Future<TestStepResult> basicStandardMessageToUnknownChannel() async { | |
| const BasicMessageChannel<dynamic> channel = | |
| BasicMessageChannel<dynamic>( | |
| 'std-unknown', | |
| ExtendedStandardMessageCodec(), | |
| ); | |
| return _basicMessageToUnknownChannel<dynamic>('Standard', channel); | |
| } | |
| /// Sends the specified message to the platform, doing a | |
| /// receive message/send reply/receive reply echo handshake initiated by the | |
| /// platform, then expecting a reply echo to the original message. | |
| /// | |
| /// Fails, if an error occurs, or if any message seen is not deeply equal to | |
| /// the original message. | |
| Future<TestStepResult> _basicMessageHandshake<T>( | |
| String description, | |
| BasicMessageChannel<T> channel, | |
| T message, | |
| ) async { | |
| final List<dynamic> received = <dynamic>[]; | |
| channel.setMessageHandler((T message) async { | |
| received.add(message); | |
| return message; | |
| }); | |
| dynamic messageEcho = nothing; | |
| dynamic error = nothing; | |
| try { | |
| messageEcho = await channel.send(message); | |
| } catch (e) { | |
| error = e; | |
| } | |
| return resultOfHandshake( | |
| 'Basic message handshake', | |
| description, | |
| message, | |
| received, | |
| messageEcho, | |
| error, | |
| ); | |
| } | |
| /// Sends a message on a channel that no one listens on. | |
| Future<TestStepResult> _basicMessageToUnknownChannel<T>( | |
| String description, | |
| BasicMessageChannel<T> channel, | |
| ) async { | |
| dynamic messageEcho = nothing; | |
| dynamic error = nothing; | |
| try { | |
| messageEcho = await channel.send(null); | |
| } catch (e) { | |
| error = e; | |
| } | |
| return resultOfHandshake( | |
| 'Message on unknown channel', | |
| description, | |
| null, | |
| <dynamic>[null, null], | |
| messageEcho, | |
| error, | |
| ); | |
| } | |
| String toString(dynamic message) { | |
| if (message is ByteData) | |
| return message.buffer | |
| .asUint8List(message.offsetInBytes, message.lengthInBytes) | |
| .toString(); | |
| else | |
| return '$message'; | |
| } |