Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(53)

Unified Diff: test/unittests/value-serializer-unittest.cc

Issue 2245753002: Blink-compatible serialization of strings. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@vs2
Patch Set: explicit cast to actually make it an unsigned comparison Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/value-serializer.cc ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: test/unittests/value-serializer-unittest.cc
diff --git a/test/unittests/value-serializer-unittest.cc b/test/unittests/value-serializer-unittest.cc
index 696f90466a6e383abb3571b23a08ce3ca21a7706..c48961fb6cddbb61ac4c2fa464af29ab925e0062 100644
--- a/test/unittests/value-serializer-unittest.cc
+++ b/test/unittests/value-serializer-unittest.cc
@@ -4,6 +4,9 @@
#include "src/value-serializer.h"
+#include <algorithm>
+#include <string>
+
#include "include/v8.h"
#include "src/api.h"
#include "src/base/build_config.h"
@@ -29,22 +32,27 @@ class ValueSerializerTest : public TestWithIsolate {
template <typename InputFunctor, typename OutputFunctor>
void RoundTripTest(const InputFunctor& input_functor,
const OutputFunctor& output_functor) {
- std::vector<uint8_t> data;
- {
- Context::Scope scope(serialization_context());
- TryCatch try_catch(isolate());
- // TODO(jbroman): Use the public API once it exists.
- Local<Value> input_value = input_functor();
- i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate());
- i::HandleScope handle_scope(internal_isolate);
- i::ValueSerializer serializer;
- serializer.WriteHeader();
- ASSERT_TRUE(serializer.WriteObject(Utils::OpenHandle(*input_value))
- .FromMaybe(false));
- ASSERT_FALSE(try_catch.HasCaught());
- data = serializer.ReleaseBuffer();
- }
- DecodeTest(data, output_functor);
+ EncodeTest(input_functor,
+ [this, &output_functor](const std::vector<uint8_t>& data) {
+ DecodeTest(data, output_functor);
+ });
+ }
+
+ template <typename InputFunctor, typename EncodedDataFunctor>
+ void EncodeTest(const InputFunctor& input_functor,
+ const EncodedDataFunctor& encoded_data_functor) {
+ Context::Scope scope(serialization_context());
+ TryCatch try_catch(isolate());
+ // TODO(jbroman): Use the public API once it exists.
+ Local<Value> input_value = input_functor();
+ i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate());
+ i::HandleScope handle_scope(internal_isolate);
+ i::ValueSerializer serializer;
+ serializer.WriteHeader();
+ ASSERT_TRUE(serializer.WriteObject(Utils::OpenHandle(*input_value))
+ .FromMaybe(false));
+ ASSERT_FALSE(try_catch.HasCaught());
+ encoded_data_functor(serializer.ReleaseBuffer());
}
template <typename OutputFunctor>
@@ -106,6 +114,11 @@ class ValueSerializerTest : public TestWithIsolate {
.ToLocalChecked();
}
+ static std::string Utf8Value(Local<Value> value) {
+ String::Utf8Value utf8(value);
+ return std::string(*utf8, utf8.length());
+ }
+
private:
Local<Context> serialization_context_;
Local<Context> deserialization_context_;
@@ -248,5 +261,132 @@ TEST_F(ValueSerializerTest, DecodeNumber) {
// TODO(jbroman): Equivalent test for big-endian machines.
}
+// String constants (in UTF-8) used for string encoding tests.
+static const char kHelloString[] = "Hello";
+static const char kQuebecString[] = "\x51\x75\xC3\xA9\x62\x65\x63";
+static const char kEmojiString[] = "\xF0\x9F\x91\x8A";
+
+TEST_F(ValueSerializerTest, RoundTripString) {
+ RoundTripTest([this]() { return String::Empty(isolate()); },
+ [](Local<Value> value) {
+ ASSERT_TRUE(value->IsString());
+ EXPECT_EQ(0, String::Cast(*value)->Length());
+ });
+ // Inside ASCII.
+ RoundTripTest([this]() { return StringFromUtf8(kHelloString); },
+ [](Local<Value> value) {
+ ASSERT_TRUE(value->IsString());
+ EXPECT_EQ(5, String::Cast(*value)->Length());
+ EXPECT_EQ(kHelloString, Utf8Value(value));
+ });
+ // Inside Latin-1 (i.e. one-byte string), but not ASCII.
+ RoundTripTest([this]() { return StringFromUtf8(kQuebecString); },
+ [](Local<Value> value) {
+ ASSERT_TRUE(value->IsString());
+ EXPECT_EQ(6, String::Cast(*value)->Length());
+ EXPECT_EQ(kQuebecString, Utf8Value(value));
+ });
+ // An emoji (decodes to two 16-bit chars).
+ RoundTripTest([this]() { return StringFromUtf8(kEmojiString); },
+ [](Local<Value> value) {
+ ASSERT_TRUE(value->IsString());
+ EXPECT_EQ(2, String::Cast(*value)->Length());
+ EXPECT_EQ(kEmojiString, Utf8Value(value));
+ });
+}
+
+TEST_F(ValueSerializerTest, DecodeString) {
+ // Decoding the strings above from UTF-8.
+ DecodeTest({0xff, 0x09, 0x53, 0x00},
+ [](Local<Value> value) {
+ ASSERT_TRUE(value->IsString());
+ EXPECT_EQ(0, String::Cast(*value)->Length());
+ });
+ DecodeTest({0xff, 0x09, 0x53, 0x05, 'H', 'e', 'l', 'l', 'o'},
+ [](Local<Value> value) {
+ ASSERT_TRUE(value->IsString());
+ EXPECT_EQ(5, String::Cast(*value)->Length());
+ EXPECT_EQ(kHelloString, Utf8Value(value));
+ });
+ DecodeTest({0xff, 0x09, 0x53, 0x07, 'Q', 'u', 0xc3, 0xa9, 'b', 'e', 'c'},
+ [](Local<Value> value) {
+ ASSERT_TRUE(value->IsString());
+ EXPECT_EQ(6, String::Cast(*value)->Length());
+ EXPECT_EQ(kQuebecString, Utf8Value(value));
+ });
+ DecodeTest({0xff, 0x09, 0x53, 0x04, 0xf0, 0x9f, 0x91, 0x8a},
+ [](Local<Value> value) {
+ ASSERT_TRUE(value->IsString());
+ EXPECT_EQ(2, String::Cast(*value)->Length());
+ EXPECT_EQ(kEmojiString, Utf8Value(value));
+ });
+
+// And from two-byte strings (endianness dependent).
+#if defined(V8_TARGET_LITTLE_ENDIAN)
+ DecodeTest({0xff, 0x09, 0x63, 0x00},
+ [](Local<Value> value) {
+ ASSERT_TRUE(value->IsString());
+ EXPECT_EQ(0, String::Cast(*value)->Length());
+ });
+ DecodeTest({0xff, 0x09, 0x63, 0x0a, 'H', '\0', 'e', '\0', 'l', '\0', 'l',
+ '\0', 'o', '\0'},
+ [](Local<Value> value) {
+ ASSERT_TRUE(value->IsString());
+ EXPECT_EQ(5, String::Cast(*value)->Length());
+ EXPECT_EQ(kHelloString, Utf8Value(value));
+ });
+ DecodeTest({0xff, 0x09, 0x63, 0x0c, 'Q', '\0', 'u', '\0', 0xe9, '\0', 'b',
+ '\0', 'e', '\0', 'c', '\0'},
+ [](Local<Value> value) {
+ ASSERT_TRUE(value->IsString());
+ EXPECT_EQ(6, String::Cast(*value)->Length());
+ EXPECT_EQ(kQuebecString, Utf8Value(value));
+ });
+ DecodeTest({0xff, 0x09, 0x63, 0x04, 0x3d, 0xd8, 0x4a, 0xdc},
+ [](Local<Value> value) {
+ ASSERT_TRUE(value->IsString());
+ EXPECT_EQ(2, String::Cast(*value)->Length());
+ EXPECT_EQ(kEmojiString, Utf8Value(value));
+ });
+#endif
+ // TODO(jbroman): The same for big-endian systems.
+}
+
+TEST_F(ValueSerializerTest, DecodeInvalidString) {
+ // UTF-8 string with too few bytes available.
+ InvalidDecodeTest({0xff, 0x09, 0x53, 0x10, 'v', '8'});
+#if defined(V8_TARGET_LITTLE_ENDIAN)
+ // Two-byte string with too few bytes available.
+ InvalidDecodeTest({0xff, 0x09, 0x63, 0x10, 'v', '\0', '8', '\0'});
+ // Two-byte string with an odd byte length.
+ InvalidDecodeTest({0xff, 0x09, 0x63, 0x03, 'v', '\0', '8'});
+#endif
+ // TODO(jbroman): The same for big-endian systems.
+}
+
+TEST_F(ValueSerializerTest, EncodeTwoByteStringUsesPadding) {
+ // As long as the output has a version that Blink expects to be able to read,
+ // we must respect its alignment requirements. It requires that two-byte
+ // characters be aligned.
+ EncodeTest(
+ [this]() {
+ // We need a string whose length will take two bytes to encode, so that
+ // a padding byte is needed to keep the characters aligned. The string
+ // must also have a two-byte character, so that it gets the two-byte
+ // encoding.
+ std::string string(200, ' ');
+ string += kEmojiString;
+ return StringFromUtf8(string.c_str());
+ },
+ [](const std::vector<uint8_t>& data) {
+ // This is a sufficient but not necessary condition to be aligned.
+ // Note that the third byte (0x00) is padding.
+ const uint8_t expected_prefix[] = {0xff, 0x09, 0x00, 0x63, 0x94, 0x03};
+ ASSERT_GT(data.size(), sizeof(expected_prefix) / sizeof(uint8_t));
+ EXPECT_TRUE(std::equal(std::begin(expected_prefix),
+ std::end(expected_prefix), data.begin()));
+ });
+}
+
} // namespace
} // namespace v8
« no previous file with comments | « src/value-serializer.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698