blob: e3571d9d86cf65e54718868e089bf976101d4929 [file] [log] [blame]
Luis Hector Chavez645501c2016-12-28 10:56:26 -08001// Copyright 2016 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 "base/files/file_path.h"
Jay Civellicfc1eaa2017-08-21 17:18:10 -07006#include "base/files/scoped_temp_dir.h"
7#include "base/memory/ptr_util.h"
Luis Hector Chavez645501c2016-12-28 10:56:26 -08008#include "base/message_loop/message_loop.h"
Jay Civellicfc1eaa2017-08-21 17:18:10 -07009#include "base/numerics/safe_math.h"
Luis Hector Chavez645501c2016-12-28 10:56:26 -080010#include "base/run_loop.h"
Jay Civellicfc1eaa2017-08-21 17:18:10 -070011#include "base/strings/utf_string_conversions.h"
Luis Hector Chavez645501c2016-12-28 10:56:26 -080012#include "base/values.h"
Luis Hector Chavez645501c2016-12-28 10:56:26 -080013#include "mojo/common/test_common_custom_types.mojom.h"
14#include "mojo/public/cpp/bindings/binding.h"
15#include "testing/gtest/include/gtest/gtest.h"
16
17namespace mojo {
18namespace common {
19namespace test {
20namespace {
21
22template <typename T>
23struct BounceTestTraits {
24 static void ExpectEquality(const T& a, const T& b) {
25 EXPECT_EQ(a, b);
26 }
27};
28
Jay Civellicfc1eaa2017-08-21 17:18:10 -070029template <typename T>
30struct PassTraits {
31 using Type = const T&;
Luis Hector Chavez645501c2016-12-28 10:56:26 -080032};
33
34template <>
Jay Civellicfc1eaa2017-08-21 17:18:10 -070035struct PassTraits<base::Time> {
36 using Type = base::Time;
37};
38
39template <>
40struct PassTraits<base::TimeDelta> {
41 using Type = base::TimeDelta;
42};
43
44template <>
45struct PassTraits<base::TimeTicks> {
46 using Type = base::TimeTicks;
Luis Hector Chavez645501c2016-12-28 10:56:26 -080047};
48
49template <typename T>
50void DoExpectResponse(T* expected_value,
51 const base::Closure& closure,
Jay Civellicfc1eaa2017-08-21 17:18:10 -070052 typename PassTraits<T>::Type value) {
Luis Hector Chavez645501c2016-12-28 10:56:26 -080053 BounceTestTraits<T>::ExpectEquality(*expected_value, value);
54 closure.Run();
55}
56
57template <typename T>
Jay Civellicfc1eaa2017-08-21 17:18:10 -070058base::Callback<void(typename PassTraits<T>::Type)> ExpectResponse(
59 T* expected_value,
60 const base::Closure& closure) {
Luis Hector Chavez645501c2016-12-28 10:56:26 -080061 return base::Bind(&DoExpectResponse<T>, expected_value, closure);
62}
63
64class TestFilePathImpl : public TestFilePath {
65 public:
66 explicit TestFilePathImpl(TestFilePathRequest request)
67 : binding_(this, std::move(request)) {}
68
69 // TestFilePath implementation:
70 void BounceFilePath(const base::FilePath& in,
71 const BounceFilePathCallback& callback) override {
72 callback.Run(in);
73 }
74
75 private:
76 mojo::Binding<TestFilePath> binding_;
77};
78
Jay Civellicfc1eaa2017-08-21 17:18:10 -070079class TestUnguessableTokenImpl : public TestUnguessableToken {
80 public:
81 explicit TestUnguessableTokenImpl(TestUnguessableTokenRequest request)
82 : binding_(this, std::move(request)) {}
83
84 // TestUnguessableToken implementation:
85 void BounceNonce(const base::UnguessableToken& in,
86 const BounceNonceCallback& callback) override {
87 callback.Run(in);
88 }
89
90 private:
91 mojo::Binding<TestUnguessableToken> binding_;
92};
93
Luis Hector Chavez645501c2016-12-28 10:56:26 -080094class TestTimeImpl : public TestTime {
95 public:
96 explicit TestTimeImpl(TestTimeRequest request)
97 : binding_(this, std::move(request)) {}
98
99 // TestTime implementation:
Jay Civellicfc1eaa2017-08-21 17:18:10 -0700100 void BounceTime(base::Time in, const BounceTimeCallback& callback) override {
Luis Hector Chavez645501c2016-12-28 10:56:26 -0800101 callback.Run(in);
102 }
103
Jay Civellicfc1eaa2017-08-21 17:18:10 -0700104 void BounceTimeDelta(base::TimeDelta in,
105 const BounceTimeDeltaCallback& callback) override {
Luis Hector Chavez645501c2016-12-28 10:56:26 -0800106 callback.Run(in);
107 }
108
Jay Civellicfc1eaa2017-08-21 17:18:10 -0700109 void BounceTimeTicks(base::TimeTicks in,
110 const BounceTimeTicksCallback& callback) override {
Luis Hector Chavez645501c2016-12-28 10:56:26 -0800111 callback.Run(in);
112 }
113
114 private:
115 mojo::Binding<TestTime> binding_;
116};
117
118class TestValueImpl : public TestValue {
119 public:
120 explicit TestValueImpl(TestValueRequest request)
121 : binding_(this, std::move(request)) {}
122
123 // TestValue implementation:
124 void BounceDictionaryValue(
Jay Civellicfc1eaa2017-08-21 17:18:10 -0700125 std::unique_ptr<base::DictionaryValue> in,
Luis Hector Chavez645501c2016-12-28 10:56:26 -0800126 const BounceDictionaryValueCallback& callback) override {
Jay Civellicfc1eaa2017-08-21 17:18:10 -0700127 callback.Run(std::move(in));
Luis Hector Chavez645501c2016-12-28 10:56:26 -0800128 }
Jay Civellicfc1eaa2017-08-21 17:18:10 -0700129
130 void BounceListValue(std::unique_ptr<base::ListValue> in,
Luis Hector Chavez645501c2016-12-28 10:56:26 -0800131 const BounceListValueCallback& callback) override {
Jay Civellicfc1eaa2017-08-21 17:18:10 -0700132 callback.Run(std::move(in));
133 }
134
135 void BounceValue(std::unique_ptr<base::Value> in,
136 const BounceValueCallback& callback) override {
137 callback.Run(std::move(in));
Luis Hector Chavez645501c2016-12-28 10:56:26 -0800138 }
139
140 private:
141 mojo::Binding<TestValue> binding_;
142};
143
Jay Civellicfc1eaa2017-08-21 17:18:10 -0700144class TestString16Impl : public TestString16 {
145 public:
146 explicit TestString16Impl(TestString16Request request)
147 : binding_(this, std::move(request)) {}
148
149 // TestString16 implementation:
150 void BounceString16(const base::string16& in,
151 const BounceString16Callback& callback) override {
152 callback.Run(in);
153 }
154
155 private:
156 mojo::Binding<TestString16> binding_;
157};
158
159class TestFileImpl : public TestFile {
160 public:
161 explicit TestFileImpl(TestFileRequest request)
162 : binding_(this, std::move(request)) {}
163
164 // TestFile implementation:
165 void BounceFile(base::File in, const BounceFileCallback& callback) override {
166 callback.Run(std::move(in));
167 }
168
169 private:
170 mojo::Binding<TestFile> binding_;
171};
172
173class TestTextDirectionImpl : public TestTextDirection {
174 public:
175 explicit TestTextDirectionImpl(TestTextDirectionRequest request)
176 : binding_(this, std::move(request)) {}
177
178 // TestTextDirection:
179 void BounceTextDirection(
180 base::i18n::TextDirection in,
181 const BounceTextDirectionCallback& callback) override {
182 callback.Run(in);
183 }
184
185 private:
186 mojo::Binding<TestTextDirection> binding_;
187};
188
Luis Hector Chavez645501c2016-12-28 10:56:26 -0800189class CommonCustomTypesTest : public testing::Test {
190 protected:
191 CommonCustomTypesTest() {}
192 ~CommonCustomTypesTest() override {}
193
194 private:
195 base::MessageLoop message_loop_;
196
197 DISALLOW_COPY_AND_ASSIGN(CommonCustomTypesTest);
198};
199
200} // namespace
201
202TEST_F(CommonCustomTypesTest, FilePath) {
203 base::RunLoop run_loop;
204
205 TestFilePathPtr ptr;
Jay Civellicfc1eaa2017-08-21 17:18:10 -0700206 TestFilePathImpl impl(MakeRequest(&ptr));
Luis Hector Chavez645501c2016-12-28 10:56:26 -0800207
208 base::FilePath dir(FILE_PATH_LITERAL("hello"));
209 base::FilePath file = dir.Append(FILE_PATH_LITERAL("world"));
210
211 ptr->BounceFilePath(file, ExpectResponse(&file, run_loop.QuitClosure()));
212
213 run_loop.Run();
214}
215
Jay Civellicfc1eaa2017-08-21 17:18:10 -0700216TEST_F(CommonCustomTypesTest, UnguessableToken) {
217 base::RunLoop run_loop;
218
219 TestUnguessableTokenPtr ptr;
220 TestUnguessableTokenImpl impl(MakeRequest(&ptr));
221
222 base::UnguessableToken token = base::UnguessableToken::Create();
223
224 ptr->BounceNonce(token, ExpectResponse(&token, run_loop.QuitClosure()));
225
226 run_loop.Run();
227}
228
Luis Hector Chavez645501c2016-12-28 10:56:26 -0800229TEST_F(CommonCustomTypesTest, Time) {
230 base::RunLoop run_loop;
231
232 TestTimePtr ptr;
Jay Civellicfc1eaa2017-08-21 17:18:10 -0700233 TestTimeImpl impl(MakeRequest(&ptr));
Luis Hector Chavez645501c2016-12-28 10:56:26 -0800234
235 base::Time t = base::Time::Now();
236
237 ptr->BounceTime(t, ExpectResponse(&t, run_loop.QuitClosure()));
238
239 run_loop.Run();
240}
241
242TEST_F(CommonCustomTypesTest, TimeDelta) {
243 base::RunLoop run_loop;
244
245 TestTimePtr ptr;
Jay Civellicfc1eaa2017-08-21 17:18:10 -0700246 TestTimeImpl impl(MakeRequest(&ptr));
Luis Hector Chavez645501c2016-12-28 10:56:26 -0800247
248 base::TimeDelta t = base::TimeDelta::FromDays(123);
249
250 ptr->BounceTimeDelta(t, ExpectResponse(&t, run_loop.QuitClosure()));
251
252 run_loop.Run();
253}
254
255TEST_F(CommonCustomTypesTest, TimeTicks) {
256 base::RunLoop run_loop;
257
258 TestTimePtr ptr;
Jay Civellicfc1eaa2017-08-21 17:18:10 -0700259 TestTimeImpl impl(MakeRequest(&ptr));
Luis Hector Chavez645501c2016-12-28 10:56:26 -0800260
261 base::TimeTicks t = base::TimeTicks::Now();
262
263 ptr->BounceTimeTicks(t, ExpectResponse(&t, run_loop.QuitClosure()));
264
265 run_loop.Run();
266}
267
268TEST_F(CommonCustomTypesTest, Value) {
269 TestValuePtr ptr;
Jay Civellicfc1eaa2017-08-21 17:18:10 -0700270 TestValueImpl impl(MakeRequest(&ptr));
Luis Hector Chavez645501c2016-12-28 10:56:26 -0800271
Jay Civellicfc1eaa2017-08-21 17:18:10 -0700272 std::unique_ptr<base::Value> output;
273
274 ASSERT_TRUE(ptr->BounceValue(nullptr, &output));
275 EXPECT_FALSE(output);
276
277 std::unique_ptr<base::Value> input = base::Value::CreateNullValue();
278 ASSERT_TRUE(ptr->BounceValue(input->CreateDeepCopy(), &output));
279 EXPECT_TRUE(base::Value::Equals(input.get(), output.get()));
280
281 input = base::MakeUnique<base::Value>(123);
282 ASSERT_TRUE(ptr->BounceValue(input->CreateDeepCopy(), &output));
283 EXPECT_TRUE(base::Value::Equals(input.get(), output.get()));
284
285 input = base::MakeUnique<base::Value>(1.23);
286 ASSERT_TRUE(ptr->BounceValue(input->CreateDeepCopy(), &output));
287 EXPECT_TRUE(base::Value::Equals(input.get(), output.get()));
288
289 input = base::MakeUnique<base::Value>(false);
290 ASSERT_TRUE(ptr->BounceValue(input->CreateDeepCopy(), &output));
291 EXPECT_TRUE(base::Value::Equals(input.get(), output.get()));
292
293 input = base::MakeUnique<base::Value>("test string");
294 ASSERT_TRUE(ptr->BounceValue(input->CreateDeepCopy(), &output));
295 EXPECT_TRUE(base::Value::Equals(input.get(), output.get()));
296
297 input = base::BinaryValue::CreateWithCopiedBuffer("mojo", 4);
298 ASSERT_TRUE(ptr->BounceValue(input->CreateDeepCopy(), &output));
299 EXPECT_TRUE(base::Value::Equals(input.get(), output.get()));
300
301 auto dict = base::MakeUnique<base::DictionaryValue>();
302 dict->SetBoolean("bool", false);
303 dict->SetInteger("int", 2);
304 dict->SetString("string", "some string");
305 dict->SetBoolean("nested.bool", true);
306 dict->SetInteger("nested.int", 9);
307 dict->Set("some_binary",
308 base::BinaryValue::CreateWithCopiedBuffer("mojo", 4));
309 dict->Set("null_value", base::Value::CreateNullValue());
310 dict->SetIntegerWithoutPathExpansion("non_nested.int", 10);
Luis Hector Chavez645501c2016-12-28 10:56:26 -0800311 {
312 std::unique_ptr<base::ListValue> dict_list(new base::ListValue());
313 dict_list->AppendString("string");
314 dict_list->AppendBoolean(true);
Jay Civellicfc1eaa2017-08-21 17:18:10 -0700315 dict->Set("list", std::move(dict_list));
Luis Hector Chavez645501c2016-12-28 10:56:26 -0800316 }
317
Jay Civellicfc1eaa2017-08-21 17:18:10 -0700318 std::unique_ptr<base::DictionaryValue> dict_output;
319 ASSERT_TRUE(ptr->BounceDictionaryValue(dict->CreateDeepCopy(), &dict_output));
320 EXPECT_TRUE(base::Value::Equals(dict.get(), dict_output.get()));
321
322 input = std::move(dict);
323 ASSERT_TRUE(ptr->BounceValue(input->CreateDeepCopy(), &output));
324 EXPECT_TRUE(base::Value::Equals(input.get(), output.get()));
325
326 auto list = base::MakeUnique<base::ListValue>();
327 list->AppendString("string");
328 list->AppendDouble(42.1);
329 list->AppendBoolean(true);
330 list->Append(base::BinaryValue::CreateWithCopiedBuffer("mojo", 4));
331 list->Append(base::Value::CreateNullValue());
Luis Hector Chavez645501c2016-12-28 10:56:26 -0800332 {
333 std::unique_ptr<base::DictionaryValue> list_dict(
334 new base::DictionaryValue());
335 list_dict->SetString("string", "str");
Jay Civellicfc1eaa2017-08-21 17:18:10 -0700336 list->Append(std::move(list_dict));
Luis Hector Chavez645501c2016-12-28 10:56:26 -0800337 }
Jay Civellicfc1eaa2017-08-21 17:18:10 -0700338 std::unique_ptr<base::ListValue> list_output;
339 ASSERT_TRUE(ptr->BounceListValue(list->CreateDeepCopy(), &list_output));
340 EXPECT_TRUE(base::Value::Equals(list.get(), list_output.get()));
341
342 input = std::move(list);
343 ASSERT_TRUE(ptr->BounceValue(input->CreateDeepCopy(), &output));
344 ASSERT_TRUE(base::Value::Equals(input.get(), output.get()));
345}
346
347TEST_F(CommonCustomTypesTest, String16) {
348 base::RunLoop run_loop;
349
350 TestString16Ptr ptr;
351 TestString16Impl impl(MakeRequest(&ptr));
352
353 base::string16 str16 = base::ASCIIToUTF16("hello world");
354
355 ptr->BounceString16(str16, ExpectResponse(&str16, run_loop.QuitClosure()));
356
357 run_loop.Run();
358}
359
360TEST_F(CommonCustomTypesTest, EmptyString16) {
361 base::RunLoop run_loop;
362
363 TestString16Ptr ptr;
364 TestString16Impl impl(MakeRequest(&ptr));
365
366 base::string16 str16;
367
368 ptr->BounceString16(str16, ExpectResponse(&str16, run_loop.QuitClosure()));
369
370 run_loop.Run();
371}
372
373TEST_F(CommonCustomTypesTest, File) {
374 base::ScopedTempDir temp_dir;
375 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
376
377 TestFilePtr ptr;
378 TestFileImpl impl(MakeRequest(&ptr));
379
380 base::File file(
381 temp_dir.GetPath().AppendASCII("test_file.txt"),
382 base::File::FLAG_CREATE | base::File::FLAG_WRITE | base::File::FLAG_READ);
383 const base::StringPiece test_content =
384 "A test string to be stored in a test file";
385 file.WriteAtCurrentPos(
386 test_content.data(),
387 base::CheckedNumeric<int>(test_content.size()).ValueOrDie());
388
389 base::File file_out;
390 ASSERT_TRUE(ptr->BounceFile(std::move(file), &file_out));
391 std::vector<char> content(test_content.size());
392 ASSERT_TRUE(file_out.IsValid());
393 ASSERT_EQ(static_cast<int>(test_content.size()),
394 file_out.Read(
395 0, content.data(),
396 base::CheckedNumeric<int>(test_content.size()).ValueOrDie()));
397 EXPECT_EQ(test_content,
398 base::StringPiece(content.data(), test_content.size()));
399}
400
401TEST_F(CommonCustomTypesTest, InvalidFile) {
402 TestFilePtr ptr;
403 TestFileImpl impl(MakeRequest(&ptr));
404
405 base::ScopedTempDir temp_dir;
406 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
407 // Test that |file_out| is set to an invalid file.
408 base::File file_out(
409 temp_dir.GetPath().AppendASCII("test_file.txt"),
410 base::File::FLAG_CREATE | base::File::FLAG_WRITE | base::File::FLAG_READ);
411
412 ASSERT_TRUE(ptr->BounceFile(base::File(), &file_out));
413 EXPECT_FALSE(file_out.IsValid());
414}
415
416TEST_F(CommonCustomTypesTest, TextDirection) {
417 base::i18n::TextDirection kTestDirections[] = {base::i18n::LEFT_TO_RIGHT,
418 base::i18n::RIGHT_TO_LEFT,
419 base::i18n::UNKNOWN_DIRECTION};
420
421 TestTextDirectionPtr ptr;
422 TestTextDirectionImpl impl(MakeRequest(&ptr));
423
424 for (size_t i = 0; i < arraysize(kTestDirections); i++) {
425 base::i18n::TextDirection direction_out;
426 ASSERT_TRUE(ptr->BounceTextDirection(kTestDirections[i], &direction_out));
427 EXPECT_EQ(kTestDirections[i], direction_out);
Luis Hector Chavez645501c2016-12-28 10:56:26 -0800428 }
429}
430
431} // namespace test
432} // namespace common
433} // namespace mojo