Remove legacy C++ EncodableValue (flutter/engine#21359)

When the EncodableValue implementation changed, the old version was
temporarily kept behind an #ifdef to allow temporarily using the old
version, so that the roll would not be blocked. All known existing
clients have migrated, so the legacy version is no longer necessary.
This commit is contained in:
stuartmorgan 2020-09-24 18:14:12 -04:00 committed by GitHub
parent c0a14ebec4
commit e44461bafa
5 changed files with 1 additions and 744 deletions

View File

@ -20,24 +20,6 @@ source_set("client_wrapper") {
[ "//flutter/shell/platform/common/cpp:relative_flutter_library_headers" ]
}
# Temporary test for the legacy EncodableValue implementation. Remove once the
# legacy version is removed.
source_set("client_wrapper_legacy_encodable_value") {
sources = core_cpp_client_wrapper_sources
public = core_cpp_client_wrapper_includes +
core_cpp_client_wrapper_internal_headers
deps = [ "//flutter/shell/platform/common/cpp:common_cpp_library_headers" ]
configs +=
[ "//flutter/shell/platform/common/cpp:desktop_library_implementation" ]
defines = [ "USE_LEGACY_ENCODABLE_VALUE" ]
public_configs =
[ "//flutter/shell/platform/common/cpp:relative_flutter_library_headers" ]
}
source_set("client_wrapper_library_stubs") {
sources = [
"testing/stub_flutter_api.cc",
@ -75,9 +57,6 @@ executable("client_wrapper_unittests") {
":client_wrapper",
":client_wrapper_fixtures",
":client_wrapper_library_stubs",
# Build the legacy version as well as a sanity check.
":client_wrapper_unittests_legacy_encodable_value",
"//flutter/testing",
# TODO(chunhtai): Consider refactoring flutter_root/testing so that there's a testing
@ -88,31 +67,3 @@ executable("client_wrapper_unittests") {
defines = [ "FLUTTER_DESKTOP_LIBRARY" ]
}
# Ensures that the legacy EncodableValue codepath still compiles.
executable("client_wrapper_unittests_legacy_encodable_value") {
testonly = true
sources = [
"encodable_value_unittests.cc",
"standard_message_codec_unittests.cc",
"testing/test_codec_extensions.h",
]
deps = [
":client_wrapper_fixtures",
":client_wrapper_legacy_encodable_value",
":client_wrapper_library_stubs",
"//flutter/testing",
# TODO(chunhtai): Consider refactoring flutter_root/testing so that there's a testing
# target that doesn't require a Dart runtime to be linked in.
# https://github.com/flutter/flutter/issues/41414.
"//third_party/dart/runtime:libdart_jit",
]
defines = [
"FLUTTER_DESKTOP_LIBRARY",
"USE_LEGACY_ENCODABLE_VALUE",
]
}

View File

@ -16,8 +16,6 @@ TEST(EncodableValueTest, Null) {
value.IsNull();
}
#ifndef USE_LEGACY_ENCODABLE_VALUE
TEST(EncodableValueTest, Bool) {
EncodableValue value(false);
@ -283,6 +281,4 @@ TEST(EncodableValueTest, DeepCopy) {
EXPECT_EQ(std::get<std::string>(innermost_map[EncodableValue("a")]), "b");
}
#endif // !LEGACY_ENCODABLE_VALUE
} // namespace flutter

View File

@ -35,13 +35,6 @@ namespace flutter {
static_assert(sizeof(double) == 8, "EncodableValue requires a 64-bit double");
// Defining USE_LEGACY_ENCODABLE_VALUE will use the original EncodableValue
// implementation. This is a temporary measure to minimize the impact of the
// breaking change; it will be removed in the future. If you set this, you
// should update your code as soon as possible to use the new std::variant
// version, or it will break when the legacy version is removed.
#ifndef USE_LEGACY_ENCODABLE_VALUE
// A container for arbitrary types in EncodableValue.
//
// This is used in conjunction with StandardCodecExtension to allow using other
@ -204,558 +197,6 @@ class EncodableValue : public internal::EncodableValueVariant {
}
};
#else
class EncodableValue;
// Convenience type aliases for list and map EncodableValue types.
using EncodableList = std::vector<EncodableValue>;
using EncodableMap = std::map<EncodableValue, EncodableValue>;
// An object that can contain any value or collection type supported by
// Flutter's standard method codec.
//
// For details, see:
// https://api.flutter.dev/flutter/services/StandardMessageCodec-class.html
//
// As an example, the following Dart structure:
// {
// 'flag': true,
// 'name': 'Thing',
// 'values': [1, 2.0, 4],
// }
// would correspond to:
// EncodableValue(EncodableMap{
// {EncodableValue("flag"), EncodableValue(true)},
// {EncodableValue("name"), EncodableValue("Thing")},
// {EncodableValue("values"), EncodableValue(EncodableList{
// EncodableValue(1),
// EncodableValue(2.0),
// EncodableValue(4),
// })},
// })
class EncodableValue {
public:
// Possible types for an EncodableValue to reperesent.
enum class Type {
kNull, // A null value.
kBool, // A boolean value.
kInt, // A 32-bit integer.
kLong, // A 64-bit integer.
kDouble, // A 64-bit floating point number.
kString, // A string.
kByteList, // A list of bytes.
kIntList, // A list of 32-bit integers.
kLongList, // A list of 64-bit integers.
kDoubleList, // A list of 64-bit floating point numbers.
kList, // A list of EncodableValues.
kMap, // A mapping from EncodableValues to EncodableValues.
};
// Creates an instance representing a null value.
EncodableValue() {}
// Creates an instance representing a bool value.
explicit EncodableValue(bool value) : bool_(value), type_(Type::kBool) {}
// Creates an instance representing a 32-bit integer value.
explicit EncodableValue(int32_t value) : int_(value), type_(Type::kInt) {}
// Creates an instance representing a 64-bit integer value.
explicit EncodableValue(int64_t value) : long_(value), type_(Type::kLong) {}
// Creates an instance representing a 64-bit floating point value.
explicit EncodableValue(double value)
: double_(value), type_(Type::kDouble) {}
// Creates an instance representing a string value.
explicit EncodableValue(const char* value)
: string_(new std::string(value)), type_(Type::kString) {}
// Creates an instance representing a string value.
explicit EncodableValue(const std::string& value)
: string_(new std::string(value)), type_(Type::kString) {}
// Creates an instance representing a list of bytes.
explicit EncodableValue(std::vector<uint8_t> list)
: byte_list_(new std::vector<uint8_t>(std::move(list))),
type_(Type::kByteList) {}
// Creates an instance representing a list of 32-bit integers.
explicit EncodableValue(std::vector<int32_t> list)
: int_list_(new std::vector<int32_t>(std::move(list))),
type_(Type::kIntList) {}
// Creates an instance representing a list of 64-bit integers.
explicit EncodableValue(std::vector<int64_t> list)
: long_list_(new std::vector<int64_t>(std::move(list))),
type_(Type::kLongList) {}
// Creates an instance representing a list of 64-bit floating point values.
explicit EncodableValue(std::vector<double> list)
: double_list_(new std::vector<double>(std::move(list))),
type_(Type::kDoubleList) {}
// Creates an instance representing a list of EncodableValues.
explicit EncodableValue(EncodableList list)
: list_(new EncodableList(std::move(list))), type_(Type::kList) {}
// Creates an instance representing a map from EncodableValues to
// EncodableValues.
explicit EncodableValue(EncodableMap map)
: map_(new EncodableMap(std::move(map))), type_(Type::kMap) {}
// Convience constructor for creating default value of the given type.
//
// Collections types will be empty, numeric types will be 0, strings will be
// empty, and booleans will be false. For non-collection types, prefer using
// the value-based constructor with an explicit value for clarity.
explicit EncodableValue(Type type) : type_(type) {
switch (type_) {
case Type::kNull:
break;
case Type::kBool:
bool_ = false;
break;
case Type::kInt:
int_ = 0;
break;
case Type::kLong:
long_ = 0;
break;
case Type::kDouble:
double_ = 0.0;
break;
case Type::kString:
string_ = new std::string();
break;
case Type::kByteList:
byte_list_ = new std::vector<uint8_t>();
break;
case Type::kIntList:
int_list_ = new std::vector<int32_t>();
break;
case Type::kLongList:
long_list_ = new std::vector<int64_t>();
break;
case Type::kDoubleList:
double_list_ = new std::vector<double>();
break;
case Type::kList:
list_ = new std::vector<EncodableValue>();
break;
case Type::kMap:
map_ = new std::map<EncodableValue, EncodableValue>();
break;
}
}
~EncodableValue() { DestroyValue(); }
EncodableValue(const EncodableValue& other) {
DestroyValue();
type_ = other.type_;
switch (type_) {
case Type::kNull:
break;
case Type::kBool:
bool_ = other.bool_;
break;
case Type::kInt:
int_ = other.int_;
break;
case Type::kLong:
long_ = other.long_;
break;
case Type::kDouble:
double_ = other.double_;
break;
case Type::kString:
string_ = new std::string(*other.string_);
break;
case Type::kByteList:
byte_list_ = new std::vector<uint8_t>(*other.byte_list_);
break;
case Type::kIntList:
int_list_ = new std::vector<int32_t>(*other.int_list_);
break;
case Type::kLongList:
long_list_ = new std::vector<int64_t>(*other.long_list_);
break;
case Type::kDoubleList:
double_list_ = new std::vector<double>(*other.double_list_);
break;
case Type::kList:
list_ = new std::vector<EncodableValue>(*other.list_);
break;
case Type::kMap:
map_ = new std::map<EncodableValue, EncodableValue>(*other.map_);
break;
}
}
EncodableValue(EncodableValue&& other) noexcept { *this = std::move(other); }
EncodableValue& operator=(const EncodableValue& other) {
if (&other == this) {
return *this;
}
using std::swap;
EncodableValue temp(other);
swap(*this, temp);
return *this;
}
EncodableValue& operator=(EncodableValue&& other) noexcept {
if (&other == this) {
return *this;
}
DestroyValue();
type_ = other.type_;
switch (type_) {
case Type::kNull:
break;
case Type::kBool:
bool_ = other.bool_;
break;
case Type::kInt:
int_ = other.int_;
break;
case Type::kLong:
long_ = other.long_;
break;
case Type::kDouble:
double_ = other.double_;
break;
case Type::kString:
string_ = other.string_;
break;
case Type::kByteList:
byte_list_ = other.byte_list_;
break;
case Type::kIntList:
int_list_ = other.int_list_;
break;
case Type::kLongList:
long_list_ = other.long_list_;
break;
case Type::kDoubleList:
double_list_ = other.double_list_;
break;
case Type::kList:
list_ = other.list_;
break;
case Type::kMap:
map_ = other.map_;
break;
}
// Ensure that destruction doesn't run on the source of the move.
other.type_ = Type::kNull;
return *this;
}
// Allow assigning any value type that can be used for a constructor.
template <typename T>
EncodableValue& operator=(const T& value) {
*this = EncodableValue(value);
return *this;
}
// This operator exists only to provide a stable ordering for use as a
// std::map key. It does not attempt to provide useful ordering semantics.
// Notably:
// - Numeric values are not guaranteed any ordering across numeric types.
// E.g., 1 as a Long may sort after 100 as an Int.
// - Collection types use pointer equality, rather than value. This means that
// multiple collections with the same values will end up as separate keys
// in a map (consistent with default Dart Map behavior).
bool operator<(const EncodableValue& other) const {
if (type_ != other.type_) {
return type_ < other.type_;
}
switch (type_) {
case Type::kNull:
return false;
case Type::kBool:
return bool_ < other.bool_;
case Type::kInt:
return int_ < other.int_;
case Type::kLong:
return long_ < other.long_;
case Type::kDouble:
return double_ < other.double_;
case Type::kString:
return *string_ < *other.string_;
case Type::kByteList:
case Type::kIntList:
case Type::kLongList:
case Type::kDoubleList:
case Type::kList:
case Type::kMap:
return this < &other;
}
assert(false);
return false;
}
// Returns the bool value this object represents.
//
// It is a programming error to call this unless IsBool() is true.
bool BoolValue() const {
assert(IsBool());
return bool_;
}
// Returns the 32-bit integer value this object represents.
//
// It is a programming error to call this unless IsInt() is true.
int32_t IntValue() const {
assert(IsInt());
return int_;
}
// Returns the 64-bit integer value this object represents.
//
// It is a programming error to call this unless IsLong() or IsInt() is true.
//
// Note that calling this function on an Int value is the only case where
// a *Value() function can be called without the corresponding Is*() being
// true. This is to simplify handling objects received from Flutter where the
// values may be larger than 32-bit, since they have the same type on the Dart
// side, but will be either 32-bit or 64-bit here depending on the value.
int64_t LongValue() const {
assert(IsLong() || IsInt());
if (IsLong()) {
return long_;
}
return int_;
}
// Returns the double value this object represents.
//
// It is a programming error to call this unless IsDouble() is true.
double DoubleValue() const {
assert(IsDouble());
return double_;
}
// Returns the string value this object represents.
//
// It is a programming error to call this unless IsString() is true.
const std::string& StringValue() const {
assert(IsString());
return *string_;
}
// Returns the byte list this object represents.
//
// It is a programming error to call this unless IsByteList() is true.
const std::vector<uint8_t>& ByteListValue() const {
assert(IsByteList());
return *byte_list_;
}
// Returns the byte list this object represents.
//
// It is a programming error to call this unless IsByteList() is true.
std::vector<uint8_t>& ByteListValue() {
assert(IsByteList());
return *byte_list_;
}
// Returns the 32-bit integer list this object represents.
//
// It is a programming error to call this unless IsIntList() is true.
const std::vector<int32_t>& IntListValue() const {
assert(IsIntList());
return *int_list_;
}
// Returns the 32-bit integer list this object represents.
//
// It is a programming error to call this unless IsIntList() is true.
std::vector<int32_t>& IntListValue() {
assert(IsIntList());
return *int_list_;
}
// Returns the 64-bit integer list this object represents.
//
// It is a programming error to call this unless IsLongList() is true.
const std::vector<int64_t>& LongListValue() const {
assert(IsLongList());
return *long_list_;
}
// Returns the 64-bit integer list this object represents.
//
// It is a programming error to call this unless IsLongList() is true.
std::vector<int64_t>& LongListValue() {
assert(IsLongList());
return *long_list_;
}
// Returns the double list this object represents.
//
// It is a programming error to call this unless IsDoubleList() is true.
const std::vector<double>& DoubleListValue() const {
assert(IsDoubleList());
return *double_list_;
}
// Returns the double list this object represents.
//
// It is a programming error to call this unless IsDoubleList() is true.
std::vector<double>& DoubleListValue() {
assert(IsDoubleList());
return *double_list_;
}
// Returns the list of EncodableValues this object represents.
//
// It is a programming error to call this unless IsList() is true.
const EncodableList& ListValue() const {
assert(IsList());
return *list_;
}
// Returns the list of EncodableValues this object represents.
//
// It is a programming error to call this unless IsList() is true.
EncodableList& ListValue() {
assert(IsList());
return *list_;
}
// Returns the map of EncodableValue : EncodableValue pairs this object
// represent.
//
// It is a programming error to call this unless IsMap() is true.
const EncodableMap& MapValue() const {
assert(IsMap());
return *map_;
}
// Returns the map of EncodableValue : EncodableValue pairs this object
// represent.
//
// It is a programming error to call this unless IsMap() is true.
EncodableMap& MapValue() {
assert(IsMap());
return *map_;
}
// Returns true if this represents a null value.
bool IsNull() const { return type_ == Type::kNull; }
// Returns true if this represents a bool value.
bool IsBool() const { return type_ == Type::kBool; }
// Returns true if this represents a 32-bit integer value.
bool IsInt() const { return type_ == Type::kInt; }
// Returns true if this represents a 64-bit integer value.
bool IsLong() const { return type_ == Type::kLong; }
// Returns true if this represents a double value.
bool IsDouble() const { return type_ == Type::kDouble; }
// Returns true if this represents a string value.
bool IsString() const { return type_ == Type::kString; }
// Returns true if this represents a list of bytes.
bool IsByteList() const { return type_ == Type::kByteList; }
// Returns true if this represents a list of 32-bit integers.
bool IsIntList() const { return type_ == Type::kIntList; }
// Returns true if this represents a list of 64-bit integers.
bool IsLongList() const { return type_ == Type::kLongList; }
// Returns true if this represents a list of doubles.
bool IsDoubleList() const { return type_ == Type::kDoubleList; }
// Returns true if this represents a list of EncodableValues.
bool IsList() const { return type_ == Type::kList; }
// Returns true if this represents a map of EncodableValue : EncodableValue
// pairs.
bool IsMap() const { return type_ == Type::kMap; }
// Returns the type this value represents.
//
// This is primarily intended for use with switch(); for individual checks,
// prefer an Is*() call.
Type type() const { return type_; }
private:
// Performs any cleanup necessary for the active union value. This must be
// called before assigning a new value, and on object destruction.
//
// After calling this, type_ will alway be kNull.
void DestroyValue() {
switch (type_) {
case Type::kNull:
case Type::kBool:
case Type::kInt:
case Type::kLong:
case Type::kDouble:
break;
case Type::kString:
delete string_;
break;
case Type::kByteList:
delete byte_list_;
break;
case Type::kIntList:
delete int_list_;
break;
case Type::kLongList:
delete long_list_;
break;
case Type::kDoubleList:
delete double_list_;
break;
case Type::kList:
delete list_;
break;
case Type::kMap:
delete map_;
break;
}
type_ = Type::kNull;
}
// The anonymous union that stores the represented value. Accessing any of
// these entries other than the one that corresponds to the current value of
// |type_| has undefined behavior.
//
// Pointers are used for the non-POD types to avoid making the overall size
// of the union unnecessarily large.
//
// TODO: Replace this with std::variant once c++17 is available.
union {
bool bool_;
int32_t int_;
int64_t long_;
double double_;
std::string* string_;
std::vector<uint8_t>* byte_list_;
std::vector<int32_t>* int_list_;
std::vector<int64_t>* long_list_;
std::vector<double>* double_list_;
std::vector<EncodableValue>* list_;
std::map<EncodableValue, EncodableValue>* map_;
};
// The currently active union entry.
Type type_ = Type::kNull;
};
#endif
} // namespace flutter
#endif // FLUTTER_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_FLUTTER_ENCODABLE_VALUE_H_

View File

@ -46,34 +46,6 @@ enum class EncodedType {
// Returns the encoded type that should be written when serializing |value|.
EncodedType EncodedTypeForValue(const EncodableValue& value) {
#ifdef USE_LEGACY_ENCODABLE_VALUE
switch (value.type()) {
case EncodableValue::Type::kNull:
return EncodedType::kNull;
case EncodableValue::Type::kBool:
return value.BoolValue() ? EncodedType::kTrue : EncodedType::kFalse;
case EncodableValue::Type::kInt:
return EncodedType::kInt32;
case EncodableValue::Type::kLong:
return EncodedType::kInt64;
case EncodableValue::Type::kDouble:
return EncodedType::kFloat64;
case EncodableValue::Type::kString:
return EncodedType::kString;
case EncodableValue::Type::kByteList:
return EncodedType::kUInt8List;
case EncodableValue::Type::kIntList:
return EncodedType::kInt32List;
case EncodableValue::Type::kLongList:
return EncodedType::kInt64List;
case EncodableValue::Type::kDoubleList:
return EncodedType::kFloat64List;
case EncodableValue::Type::kList:
return EncodedType::kList;
case EncodableValue::Type::kMap:
return EncodedType::kMap;
}
#else
switch (value.index()) {
case 0:
return EncodedType::kNull;
@ -100,7 +72,6 @@ EncodedType EncodedTypeForValue(const EncodableValue& value) {
case 11:
return EncodedType::kMap;
}
#endif
assert(false);
return EncodedType::kNull;
}
@ -125,59 +96,6 @@ EncodableValue StandardCodecSerializer::ReadValue(
void StandardCodecSerializer::WriteValue(const EncodableValue& value,
ByteStreamWriter* stream) const {
stream->WriteByte(static_cast<uint8_t>(EncodedTypeForValue(value)));
#ifdef USE_LEGACY_ENCODABLE_VALUE
switch (value.type()) {
case EncodableValue::Type::kNull:
case EncodableValue::Type::kBool:
// Null and bool are encoded directly in the type.
break;
case EncodableValue::Type::kInt:
stream->WriteInt32(value.IntValue());
break;
case EncodableValue::Type::kLong:
stream->WriteInt64(value.LongValue());
break;
case EncodableValue::Type::kDouble:
stream->WriteAlignment(8);
stream->WriteDouble(value.DoubleValue());
break;
case EncodableValue::Type::kString: {
const auto& string_value = value.StringValue();
size_t size = string_value.size();
WriteSize(size, stream);
if (size > 0) {
stream->WriteBytes(
reinterpret_cast<const uint8_t*>(string_value.data()), size);
}
break;
}
case EncodableValue::Type::kByteList:
WriteVector(value.ByteListValue(), stream);
break;
case EncodableValue::Type::kIntList:
WriteVector(value.IntListValue(), stream);
break;
case EncodableValue::Type::kLongList:
WriteVector(value.LongListValue(), stream);
break;
case EncodableValue::Type::kDoubleList:
WriteVector(value.DoubleListValue(), stream);
break;
case EncodableValue::Type::kList:
WriteSize(value.ListValue().size(), stream);
for (const auto& item : value.ListValue()) {
WriteValue(item, stream);
}
break;
case EncodableValue::Type::kMap:
WriteSize(value.MapValue().size(), stream);
for (const auto& pair : value.MapValue()) {
WriteValue(pair.first, stream);
WriteValue(pair.second, stream);
}
break;
}
#else
// TODO: Consider replacing this this with a std::visitor.
switch (value.index()) {
case 0:
@ -239,7 +157,6 @@ void StandardCodecSerializer::WriteValue(const EncodableValue& value,
<< "Custom types require codec extensions." << std::endl;
break;
}
#endif
}
EncodableValue StandardCodecSerializer::ReadValueOfType(
@ -437,18 +354,6 @@ std::unique_ptr<MethodCall<EncodableValue>>
StandardMethodCodec::DecodeMethodCallInternal(const uint8_t* message,
size_t message_size) const {
ByteBufferStreamReader stream(message, message_size);
#ifdef USE_LEGACY_ENCODABLE_VALUE
EncodableValue method_name = serializer_->ReadValue(&stream);
if (!method_name.IsString()) {
std::cerr << "Invalid method call; method name is not a string."
<< std::endl;
return nullptr;
}
auto arguments =
std::make_unique<EncodableValue>(serializer_->ReadValue(&stream));
return std::make_unique<MethodCall<EncodableValue>>(method_name.StringValue(),
std::move(arguments));
#else
EncodableValue method_name_value = serializer_->ReadValue(&stream);
const auto* method_name = std::get_if<std::string>(&method_name_value);
if (!method_name) {
@ -460,7 +365,6 @@ StandardMethodCodec::DecodeMethodCallInternal(const uint8_t* message,
std::make_unique<EncodableValue>(serializer_->ReadValue(&stream));
return std::make_unique<MethodCall<EncodableValue>>(*method_name,
std::move(arguments));
#endif
}
std::unique_ptr<std::vector<uint8_t>>
@ -533,15 +437,6 @@ bool StandardMethodCodec::DecodeAndProcessResponseEnvelopeInternal(
EncodableValue code = serializer_->ReadValue(&stream);
EncodableValue message = serializer_->ReadValue(&stream);
EncodableValue details = serializer_->ReadValue(&stream);
#ifdef USE_LEGACY_ENCODABLE_VALUE
if (details.IsNull()) {
result->Error(code.StringValue(),
message.IsNull() ? "" : message.StringValue());
} else {
result->Error(code.StringValue(),
message.IsNull() ? "" : message.StringValue(), details);
}
#else
const std::string& message_string =
message.IsNull() ? "" : std::get<std::string>(message);
if (details.IsNull()) {
@ -549,7 +444,6 @@ bool StandardMethodCodec::DecodeAndProcessResponseEnvelopeInternal(
} else {
result->Error(std::get<std::string>(code), message_string, details);
}
#endif
return true;
}
default:

View File

@ -7,11 +7,8 @@
#include <map>
#include <vector>
#include "gtest/gtest.h"
#ifndef USE_LEGACY_ENCODABLE_VALUE
#include "flutter/shell/platform/common/cpp/client_wrapper/testing/test_codec_extensions.h"
#endif
#include "gtest/gtest.h"
namespace flutter {
@ -34,21 +31,11 @@ static void CheckEncodeDecode(
EXPECT_EQ(*encoded, expected_encoding);
auto decoded = codec.DecodeMessage(*encoded);
#ifdef USE_LEGACY_ENCODABLE_VALUE
// Full equality isn't implemented for the legacy path; just do a sanity test
// of basic types.
if (value.IsNull() || value.IsBool() || value.IsInt() || value.IsLong() ||
value.IsDouble() || value.IsString()) {
EXPECT_FALSE(value < *decoded);
EXPECT_FALSE(*decoded < value);
}
#else
if (custom_comparator) {
EXPECT_TRUE(custom_comparator(value, *decoded));
} else {
EXPECT_EQ(value, *decoded);
}
#endif
}
// Validates round-trip encoding and decoding of |value|, and checks that the
@ -60,11 +47,7 @@ static void CheckEncodeDecodeWithEncodePrefix(
const EncodableValue& value,
const std::vector<uint8_t>& expected_encoding_prefix,
size_t expected_encoding_length) {
#ifdef USE_LEGACY_ENCODABLE_VALUE
EXPECT_TRUE(value.IsMap());
#else
EXPECT_TRUE(std::holds_alternative<EncodableMap>(value));
#endif
const StandardMessageCodec& codec = StandardMessageCodec::GetInstance();
auto encoded = codec.EncodeMessage(value);
ASSERT_TRUE(encoded);
@ -77,11 +60,7 @@ static void CheckEncodeDecodeWithEncodePrefix(
auto decoded = codec.DecodeMessage(*encoded);
#ifdef USE_LEGACY_ENCODABLE_VALUE
EXPECT_NE(decoded, nullptr);
#else
EXPECT_EQ(value, *decoded);
#endif
}
TEST(StandardMessageCodec, CanEncodeAndDecodeNull) {
@ -205,8 +184,6 @@ TEST(StandardMessageCodec, CanEncodeAndDecodeFloat64Array) {
CheckEncodeDecode(value, bytes);
}
#ifndef USE_LEGACY_ENCODABLE_VALUE
TEST(StandardMessageCodec, CanEncodeAndDecodeSimpleCustomType) {
std::vector<uint8_t> bytes = {0x80, 0x09, 0x00, 0x00, 0x00,
0x10, 0x00, 0x00, 0x00};
@ -242,6 +219,4 @@ TEST(StandardMessageCodec, CanEncodeAndDecodeVariableLengthCustomType) {
some_data_comparator);
}
#endif // !USE_LEGACY_ENCODABLE_VALUE
} // namespace flutter