Upload upstream chromium 85.0.4183.84
[platform/framework/web/chromium-efl.git] / gin / converter_unittest.cc
1 // Copyright 2013 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
5 #include "gin/converter.h"
6
7 #include <limits.h>
8 #include <stddef.h>
9 #include <stdint.h>
10
11 #include "base/compiler_specific.h"
12 #include "base/stl_util.h"
13 #include "base/strings/string16.h"
14 #include "base/strings/utf_string_conversions.h"
15 #include "gin/function_template.h"
16 #include "gin/handle.h"
17 #include "gin/public/isolate_holder.h"
18 #include "gin/test/v8_test.h"
19 #include "gin/wrappable.h"
20 #include "testing/gmock/include/gmock/gmock.h"
21 #include "testing/gtest/include/gtest/gtest.h"
22 #include "v8/include/v8.h"
23
24 namespace gin {
25
26 using v8::Array;
27 using v8::Boolean;
28 using v8::HandleScope;
29 using v8::Integer;
30 using v8::Local;
31 using v8::Null;
32 using v8::Number;
33 using v8::Object;
34 using v8::String;
35 using v8::Undefined;
36 using v8::Value;
37
38 typedef V8Test ConverterTest;
39
40 TEST_F(ConverterTest, Bool) {
41   HandleScope handle_scope(instance_->isolate());
42
43   EXPECT_TRUE(Converter<bool>::ToV8(instance_->isolate(), true)->StrictEquals(
44       Boolean::New(instance_->isolate(), true)));
45   EXPECT_TRUE(Converter<bool>::ToV8(instance_->isolate(), false)->StrictEquals(
46       Boolean::New(instance_->isolate(), false)));
47
48   struct {
49     Local<Value> input;
50     bool expected;
51   } test_data[] = {
52       {Boolean::New(instance_->isolate(), false).As<Value>(), false},
53       {Boolean::New(instance_->isolate(), true).As<Value>(), true},
54       {Number::New(instance_->isolate(), 0).As<Value>(), false},
55       {Number::New(instance_->isolate(), 1).As<Value>(), true},
56       {Number::New(instance_->isolate(), -1).As<Value>(), true},
57       {Number::New(instance_->isolate(), 0.1).As<Value>(), true},
58       {String::NewFromUtf8(instance_->isolate(), "", v8::NewStringType::kNormal)
59            .ToLocalChecked()
60            .As<Value>(),
61        false},
62       {String::NewFromUtf8(instance_->isolate(), "foo",
63                            v8::NewStringType::kNormal)
64            .ToLocalChecked()
65            .As<Value>(),
66        true},
67       {Object::New(instance_->isolate()).As<Value>(), true},
68       {Null(instance_->isolate()).As<Value>(), false},
69       {Undefined(instance_->isolate()).As<Value>(), false},
70   };
71
72   for (size_t i = 0; i < base::size(test_data); ++i) {
73     bool result = false;
74     EXPECT_TRUE(Converter<bool>::FromV8(instance_->isolate(),
75                                         test_data[i].input, &result));
76     EXPECT_EQ(test_data[i].expected, result);
77
78     result = true;
79     EXPECT_TRUE(Converter<bool>::FromV8(instance_->isolate(),
80                                         test_data[i].input, &result));
81     EXPECT_EQ(test_data[i].expected, result);
82   }
83 }
84
85 TEST_F(ConverterTest, String16) {
86   v8::Isolate* isolate = instance_->isolate();
87
88   HandleScope handle_scope(isolate);
89
90   EXPECT_TRUE(Converter<base::string16>::ToV8(isolate, base::ASCIIToUTF16(""))
91                   ->StrictEquals(StringToV8(isolate, "")));
92   EXPECT_TRUE(
93       Converter<base::string16>::ToV8(isolate, base::ASCIIToUTF16("hello"))
94           ->StrictEquals(StringToV8(isolate, "hello")));
95
96   base::string16 result;
97
98   ASSERT_FALSE(
99       Converter<base::string16>::FromV8(isolate, v8::False(isolate), &result));
100   ASSERT_FALSE(
101       Converter<base::string16>::FromV8(isolate, v8::True(isolate), &result));
102   ASSERT_TRUE(Converter<base::string16>::FromV8(
103       isolate, v8::String::Empty(isolate), &result));
104   EXPECT_EQ(result, base::string16());
105   ASSERT_TRUE(Converter<base::string16>::FromV8(
106       isolate, StringToV8(isolate, "hello"), &result));
107   EXPECT_EQ(result, base::ASCIIToUTF16("hello"));
108 }
109
110 TEST_F(ConverterTest, Int32) {
111   HandleScope handle_scope(instance_->isolate());
112
113   int test_data_to[] = {-1, 0, 1};
114   for (size_t i = 0; i < base::size(test_data_to); ++i) {
115     EXPECT_TRUE(Converter<int32_t>::ToV8(instance_->isolate(), test_data_to[i])
116                     ->StrictEquals(
117                           Integer::New(instance_->isolate(), test_data_to[i])));
118   }
119
120   struct {
121     v8::Local<v8::Value> input;
122     bool expect_success;
123     int expected_result;
124   } test_data_from[] = {
125       {Boolean::New(instance_->isolate(), false).As<Value>(), false, 0},
126       {Boolean::New(instance_->isolate(), true).As<Value>(), false, 0},
127       {Integer::New(instance_->isolate(), -1).As<Value>(), true, -1},
128       {Integer::New(instance_->isolate(), 0).As<Value>(), true, 0},
129       {Integer::New(instance_->isolate(), 1).As<Value>(), true, 1},
130       {Number::New(instance_->isolate(), -1).As<Value>(), true, -1},
131       {Number::New(instance_->isolate(), 1.1).As<Value>(), false, 0},
132       {String::NewFromUtf8(instance_->isolate(), "42",
133                            v8::NewStringType::kNormal)
134            .ToLocalChecked()
135            .As<Value>(),
136        false, 0},
137       {String::NewFromUtf8(instance_->isolate(), "foo",
138                            v8::NewStringType::kNormal)
139            .ToLocalChecked()
140            .As<Value>(),
141        false, 0},
142       {Object::New(instance_->isolate()).As<Value>(), false, 0},
143       {Array::New(instance_->isolate()).As<Value>(), false, 0},
144       {v8::Null(instance_->isolate()).As<Value>(), false, 0},
145       {v8::Undefined(instance_->isolate()).As<Value>(), false, 0},
146   };
147
148   for (size_t i = 0; i < base::size(test_data_from); ++i) {
149     int32_t result = std::numeric_limits<int32_t>::min();
150     bool success = Converter<int32_t>::FromV8(instance_->isolate(),
151                                               test_data_from[i].input, &result);
152     EXPECT_EQ(test_data_from[i].expect_success, success) << i;
153     if (success)
154       EXPECT_EQ(test_data_from[i].expected_result, result) << i;
155   }
156 }
157
158 TEST_F(ConverterTest, Vector) {
159   HandleScope handle_scope(instance_->isolate());
160
161   std::vector<int> expected;
162   expected.push_back(-1);
163   expected.push_back(0);
164   expected.push_back(1);
165
166   auto js_array =
167       Converter<std::vector<int>>::ToV8(instance_->isolate(), expected)
168           .As<Array>();
169   EXPECT_EQ(3u, js_array->Length());
170   v8::Local<v8::Context> context = instance_->isolate()->GetCurrentContext();
171   for (size_t i = 0; i < expected.size(); ++i) {
172     EXPECT_TRUE(
173         Integer::New(instance_->isolate(), expected[i])
174             ->StrictEquals(
175                 js_array->Get(context, static_cast<int>(i)).ToLocalChecked()));
176   }
177 }
178
179 TEST_F(ConverterTest, VectorOfVectors) {
180   HandleScope handle_scope(instance_->isolate());
181
182   std::vector<std::vector<int>> vector_of_vectors = {
183       {1, 2, 3}, {4, 5, 6},
184   };
185
186   v8::Local<v8::Value> v8_value =
187       ConvertToV8(instance_->isolate(), vector_of_vectors);
188   std::vector<std::vector<int>> out_value;
189   ASSERT_TRUE(ConvertFromV8(instance_->isolate(), v8_value, &out_value));
190   EXPECT_THAT(out_value, testing::ContainerEq(vector_of_vectors));
191 }
192
193 namespace {
194
195 class MyObject : public Wrappable<MyObject> {
196  public:
197   static WrapperInfo kWrapperInfo;
198
199   static gin::Handle<MyObject> Create(v8::Isolate* isolate) {
200     return CreateHandle(isolate, new MyObject());
201   }
202 };
203
204 WrapperInfo MyObject::kWrapperInfo = {kEmbedderNativeGin};
205
206 }  // namespace
207
208 TEST_F(ConverterTest, VectorOfWrappables) {
209   v8::Isolate* isolate = instance_->isolate();
210   v8::HandleScope handle_scope(isolate);
211
212   Handle<MyObject> obj = MyObject::Create(isolate);
213   std::vector<MyObject*> vector = {obj.get()};
214   v8::MaybeLocal<v8::Value> maybe = ConvertToV8(isolate, vector);
215   v8::Local<v8::Value> array;
216   ASSERT_TRUE(maybe.ToLocal(&array));
217   v8::Local<v8::Value> array2;
218   ASSERT_TRUE(TryConvertToV8(isolate, vector, &array2));
219
220   std::vector<MyObject*> out_value;
221   ASSERT_TRUE(ConvertFromV8(isolate, array, &out_value));
222   EXPECT_THAT(out_value, testing::ContainerEq(vector));
223   std::vector<MyObject*> out_value2;
224   ASSERT_TRUE(ConvertFromV8(isolate, array2, &out_value2));
225   EXPECT_THAT(out_value2, testing::ContainerEq(vector));
226 }
227
228 namespace {
229
230 class MoveOnlyObject {
231  public:
232   MoveOnlyObject() = default;
233   MoveOnlyObject(const MoveOnlyObject&) = delete;
234   MoveOnlyObject& operator=(const MoveOnlyObject&) = delete;
235
236   MoveOnlyObject(MoveOnlyObject&&) noexcept = default;
237   MoveOnlyObject& operator=(MoveOnlyObject&&) noexcept = default;
238 };
239
240 }  // namespace
241
242 template <>
243 struct Converter<MoveOnlyObject> {
244   static v8::Local<v8::Value> ToV8(v8::Isolate* isolate, MoveOnlyObject in) {
245     return v8::Undefined(isolate);
246   }
247   static bool FromV8(v8::Isolate* isolate,
248                      v8::Local<v8::Value> val,
249                      MoveOnlyObject* out) {
250     *out = MoveOnlyObject();
251     return true;
252   }
253 };
254
255 TEST_F(ConverterTest, MoveOnlyParameters) {
256   v8::Isolate* isolate = instance_->isolate();
257   v8::HandleScope handle_scope(isolate);
258
259   auto receives_move_only_obj = [](MoveOnlyObject obj) {};
260   auto func_templ = gin::CreateFunctionTemplate(
261       isolate, base::BindRepeating(receives_move_only_obj));
262
263   v8::Local<v8::Context> context = instance_->isolate()->GetCurrentContext();
264   auto func = func_templ->GetFunction(context).ToLocalChecked();
265   v8::Local<v8::Value> argv[] = {v8::Undefined(isolate)};
266   func->Call(context, v8::Undefined(isolate), 1, argv).ToLocalChecked();
267 }
268
269 }  // namespace gin