blob: dd30f0e8f6a01bfa1573c80e4a21d2c9533aba21 [file] [log] [blame]
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "flutter/shell/platform/common/client_wrapper/include/flutter/standard_message_codec.h"
#include <map>
#include <vector>
#include "flutter/shell/platform/common/client_wrapper/testing/test_codec_extensions.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
namespace flutter {
namespace {
class MockStandardCodecSerializer : public StandardCodecSerializer {
public:
MOCK_CONST_METHOD2(WriteValue,
void(const EncodableValue& value,
ByteStreamWriter* stream));
MOCK_CONST_METHOD2(ReadValueOfType,
EncodableValue(uint8_t type, ByteStreamReader* stream));
};
} // namespace
// Validates round-trip encoding and decoding of |value|, and checks that the
// encoded value matches |expected_encoding|.
//
// If testing with CustomEncodableValues, |serializer| must be provided to
// handle the encoding/decoding, and |custom_comparator| must be provided to
// validate equality since CustomEncodableValue doesn't define a useful ==.
static void CheckEncodeDecode(
const EncodableValue& value,
const std::vector<uint8_t>& expected_encoding,
const StandardCodecSerializer* serializer = nullptr,
std::function<bool(const EncodableValue& a, const EncodableValue& b)>
custom_comparator = nullptr) {
const StandardMessageCodec& codec =
StandardMessageCodec::GetInstance(serializer);
auto encoded = codec.EncodeMessage(value);
ASSERT_TRUE(encoded);
EXPECT_EQ(*encoded, expected_encoding);
auto decoded = codec.DecodeMessage(*encoded);
if (custom_comparator) {
EXPECT_TRUE(custom_comparator(value, *decoded));
} else {
EXPECT_EQ(value, *decoded);
}
}
// Validates round-trip encoding and decoding of |value|, and checks that the
// encoded value has the given prefix and length.
//
// This should be used only for Map, where asserting the order of the elements
// in a test is undesirable.
static void CheckEncodeDecodeWithEncodePrefix(
const EncodableValue& value,
const std::vector<uint8_t>& expected_encoding_prefix,
size_t expected_encoding_length) {
EXPECT_TRUE(std::holds_alternative<EncodableMap>(value));
const StandardMessageCodec& codec = StandardMessageCodec::GetInstance();
auto encoded = codec.EncodeMessage(value);
ASSERT_TRUE(encoded);
EXPECT_EQ(encoded->size(), expected_encoding_length);
ASSERT_GT(encoded->size(), expected_encoding_prefix.size());
EXPECT_TRUE(std::equal(
encoded->begin(), encoded->begin() + expected_encoding_prefix.size(),
expected_encoding_prefix.begin(), expected_encoding_prefix.end()));
auto decoded = codec.DecodeMessage(*encoded);
EXPECT_EQ(value, *decoded);
}
TEST(StandardMessageCodec, GetInstanceCachesInstance) {
const StandardMessageCodec& codec_a =
StandardMessageCodec::GetInstance(nullptr);
const StandardMessageCodec& codec_b =
StandardMessageCodec::GetInstance(nullptr);
EXPECT_EQ(&codec_a, &codec_b);
}
TEST(StandardMessageCodec, CanEncodeAndDecodeNull) {
std::vector<uint8_t> bytes = {0x00};
CheckEncodeDecode(EncodableValue(), bytes);
}
TEST(StandardMessageCodec, CanDecodeEmptyBytesAsNullWithoutCallingSerializer) {
std::vector<uint8_t> bytes = {};
const MockStandardCodecSerializer serializer;
const StandardMessageCodec& codec =
StandardMessageCodec::GetInstance(&serializer);
auto decoded = codec.DecodeMessage(bytes);
EXPECT_EQ(EncodableValue(), *decoded);
EXPECT_CALL(serializer, ReadValueOfType(::testing::_, ::testing::_)).Times(0);
}
TEST(StandardMessageCodec, CanEncodeAndDecodeTrue) {
std::vector<uint8_t> bytes = {0x01};
CheckEncodeDecode(EncodableValue(true), bytes);
}
TEST(StandardMessageCodec, CanEncodeAndDecodeFalse) {
std::vector<uint8_t> bytes = {0x02};
CheckEncodeDecode(EncodableValue(false), bytes);
}
TEST(StandardMessageCodec, CanEncodeAndDecodeInt32) {
std::vector<uint8_t> bytes = {0x03, 0x78, 0x56, 0x34, 0x12};
CheckEncodeDecode(EncodableValue(0x12345678), bytes);
}
TEST(StandardMessageCodec, CanEncodeAndDecodeInt64) {
std::vector<uint8_t> bytes = {0x04, 0xef, 0xcd, 0xab, 0x90,
0x78, 0x56, 0x34, 0x12};
CheckEncodeDecode(EncodableValue(INT64_C(0x1234567890abcdef)), bytes);
}
TEST(StandardMessageCodec, CanEncodeAndDecodeDouble) {
std::vector<uint8_t> bytes = {0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x18, 0x2d, 0x44, 0x54, 0xfb, 0x21, 0x09, 0x40};
CheckEncodeDecode(EncodableValue(3.14159265358979311599796346854), bytes);
}
TEST(StandardMessageCodec, CanEncodeAndDecodeString) {
std::vector<uint8_t> bytes = {0x07, 0x0b, 0x68, 0x65, 0x6c, 0x6c, 0x6f,
0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64};
CheckEncodeDecode(EncodableValue(u8"hello world"), bytes);
}
TEST(StandardMessageCodec, CanEncodeAndDecodeStringWithNonAsciiCodePoint) {
std::vector<uint8_t> bytes = {0x07, 0x05, 0x68, 0xe2, 0x98, 0xba, 0x77};
CheckEncodeDecode(EncodableValue(u8"h\u263Aw"), bytes);
}
TEST(StandardMessageCodec, CanEncodeAndDecodeStringWithNonBMPCodePoint) {
std::vector<uint8_t> bytes = {0x07, 0x06, 0x68, 0xf0, 0x9f, 0x98, 0x82, 0x77};
CheckEncodeDecode(EncodableValue(u8"h\U0001F602w"), bytes);
}
TEST(StandardMessageCodec, CanEncodeAndDecodeEmptyString) {
std::vector<uint8_t> bytes = {0x07, 0x00};
CheckEncodeDecode(EncodableValue(u8""), bytes);
}
TEST(StandardMessageCodec, CanEncodeAndDecodeList) {
std::vector<uint8_t> bytes = {
0x0c, 0x05, 0x00, 0x07, 0x05, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x06,
0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x85, 0xeb, 0x51, 0xb8, 0x1e,
0x09, 0x40, 0x03, 0x2f, 0x00, 0x00, 0x00, 0x0c, 0x02, 0x03, 0x2a,
0x00, 0x00, 0x00, 0x07, 0x06, 0x6e, 0x65, 0x73, 0x74, 0x65, 0x64,
};
EncodableValue value(EncodableList{
EncodableValue(),
EncodableValue("hello"),
EncodableValue(3.14),
EncodableValue(47),
EncodableValue(EncodableList{
EncodableValue(42),
EncodableValue("nested"),
}),
});
CheckEncodeDecode(value, bytes);
}
TEST(StandardMessageCodec, CanEncodeAndDecodeEmptyList) {
std::vector<uint8_t> bytes = {0x0c, 0x00};
CheckEncodeDecode(EncodableValue(EncodableList{}), bytes);
}
TEST(StandardMessageCodec, CanEncodeAndDecodeMap) {
std::vector<uint8_t> bytes_prefix = {0x0d, 0x04};
EncodableValue value(EncodableMap{
{EncodableValue("a"), EncodableValue(3.14)},
{EncodableValue("b"), EncodableValue(47)},
{EncodableValue(), EncodableValue()},
{EncodableValue(3.14), EncodableValue(EncodableList{
EncodableValue("nested"),
})},
});
CheckEncodeDecodeWithEncodePrefix(value, bytes_prefix, 48);
}
TEST(StandardMessageCodec, CanEncodeAndDecodeByteArray) {
std::vector<uint8_t> bytes = {0x08, 0x04, 0xba, 0x5e, 0xba, 0x11};
EncodableValue value(std::vector<uint8_t>{0xba, 0x5e, 0xba, 0x11});
CheckEncodeDecode(value, bytes);
}
TEST(StandardMessageCodec, CanEncodeAndDecodeInt32Array) {
std::vector<uint8_t> bytes = {0x09, 0x03, 0x00, 0x00, 0x78, 0x56, 0x34, 0x12,
0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00};
EncodableValue value(std::vector<int32_t>{0x12345678, -1, 0});
CheckEncodeDecode(value, bytes);
}
TEST(StandardMessageCodec, CanEncodeAndDecodeInt64Array) {
std::vector<uint8_t> bytes = {0x0a, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xef, 0xcd, 0xab, 0x90, 0x78, 0x56, 0x34, 0x12,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
EncodableValue value(std::vector<int64_t>{0x1234567890abcdef, -1});
CheckEncodeDecode(value, bytes);
}
TEST(StandardMessageCodec, CanEncodeAndDecodeFloat32Array) {
std::vector<uint8_t> bytes = {0x0e, 0x02, 0x00, 0x00, 0xd8, 0x0f,
0x49, 0x40, 0x00, 0x00, 0x7a, 0x44};
EncodableValue value(std::vector<float>{3.1415920257568359375f, 1000.0f});
CheckEncodeDecode(value, bytes);
}
TEST(StandardMessageCodec, CanEncodeAndDecodeFloat64Array) {
std::vector<uint8_t> bytes = {0x0b, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x18, 0x2d, 0x44, 0x54, 0xfb, 0x21, 0x09, 0x40,
0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x8f, 0x40};
EncodableValue value(
std::vector<double>{3.14159265358979311599796346854, 1000.0});
CheckEncodeDecode(value, bytes);
}
TEST(StandardMessageCodec, CanEncodeAndDecodeSimpleCustomType) {
std::vector<uint8_t> bytes = {0x80, 0x09, 0x00, 0x00, 0x00,
0x10, 0x00, 0x00, 0x00};
auto point_comparator = [](const EncodableValue& a, const EncodableValue& b) {
const Point& a_point =
std::any_cast<Point>(std::get<CustomEncodableValue>(a));
const Point& b_point =
std::any_cast<Point>(std::get<CustomEncodableValue>(b));
return a_point == b_point;
};
CheckEncodeDecode(CustomEncodableValue(Point(9, 16)), bytes,
&PointExtensionSerializer::GetInstance(), point_comparator);
}
TEST(StandardMessageCodec, CanEncodeAndDecodeVariableLengthCustomType) {
std::vector<uint8_t> bytes = {
0x81, // custom type
0x06, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, // data
0x07, 0x04, // string type and length
0x74, 0x65, 0x73, 0x74 // string characters
};
auto some_data_comparator = [](const EncodableValue& a,
const EncodableValue& b) {
const SomeData& data_a =
std::any_cast<SomeData>(std::get<CustomEncodableValue>(a));
const SomeData& data_b =
std::any_cast<SomeData>(std::get<CustomEncodableValue>(b));
return data_a.data() == data_b.data() && data_a.label() == data_b.label();
};
CheckEncodeDecode(CustomEncodableValue(
SomeData("test", {0x00, 0x01, 0x02, 0x03, 0x04, 0x05})),
bytes, &SomeDataExtensionSerializer::GetInstance(),
some_data_comparator);
}
} // namespace flutter