1// 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"
6#include "base/message_loop/message_loop.h"
7#include "base/run_loop.h"
8#include "base/values.h"
9#include "mojo/common/common_custom_types.mojom.h"
10#include "mojo/common/test_common_custom_types.mojom.h"
11#include "mojo/public/cpp/bindings/binding.h"
12#include "testing/gtest/include/gtest/gtest.h"
13
14namespace mojo {
15namespace common {
16namespace test {
17namespace {
18
19template <typename T>
20struct BounceTestTraits {
21  static void ExpectEquality(const T& a, const T& b) {
22    EXPECT_EQ(a, b);
23  }
24};
25
26template <>
27struct BounceTestTraits<base::DictionaryValue> {
28  static void ExpectEquality(const base::DictionaryValue& a,
29                             const base::DictionaryValue& b) {
30    EXPECT_TRUE(a.Equals(&b));
31  }
32};
33
34template <>
35struct BounceTestTraits<base::ListValue> {
36  static void ExpectEquality(const base::ListValue& a,
37                             const base::ListValue& b) {
38    EXPECT_TRUE(a.Equals(&b));
39  }
40};
41
42template <typename T>
43void DoExpectResponse(T* expected_value,
44                      const base::Closure& closure,
45                      const T& value) {
46  BounceTestTraits<T>::ExpectEquality(*expected_value, value);
47  closure.Run();
48}
49
50template <typename T>
51base::Callback<void(const T&)> ExpectResponse(T* expected_value,
52                                              const base::Closure& closure) {
53  return base::Bind(&DoExpectResponse<T>, expected_value, closure);
54}
55
56class TestFilePathImpl : public TestFilePath {
57 public:
58  explicit TestFilePathImpl(TestFilePathRequest request)
59      : binding_(this, std::move(request)) {}
60
61  // TestFilePath implementation:
62  void BounceFilePath(const base::FilePath& in,
63                      const BounceFilePathCallback& callback) override {
64    callback.Run(in);
65  }
66
67 private:
68  mojo::Binding<TestFilePath> binding_;
69};
70
71class TestTimeImpl : public TestTime {
72 public:
73  explicit TestTimeImpl(TestTimeRequest request)
74      : binding_(this, std::move(request)) {}
75
76  // TestTime implementation:
77  void BounceTime(const base::Time& in,
78                  const BounceTimeCallback& callback) override {
79    callback.Run(in);
80  }
81
82  void BounceTimeDelta(const base::TimeDelta& in,
83                  const BounceTimeDeltaCallback& callback) override {
84    callback.Run(in);
85  }
86
87  void BounceTimeTicks(const base::TimeTicks& in,
88                  const BounceTimeTicksCallback& callback) override {
89    callback.Run(in);
90  }
91
92 private:
93  mojo::Binding<TestTime> binding_;
94};
95
96class TestValueImpl : public TestValue {
97 public:
98  explicit TestValueImpl(TestValueRequest request)
99      : binding_(this, std::move(request)) {}
100
101  // TestValue implementation:
102  void BounceDictionaryValue(
103      const base::DictionaryValue& in,
104      const BounceDictionaryValueCallback& callback) override {
105    callback.Run(in);
106  }
107  void BounceListValue(const base::ListValue& in,
108                       const BounceListValueCallback& callback) override {
109    callback.Run(in);
110  }
111
112 private:
113  mojo::Binding<TestValue> binding_;
114};
115
116class CommonCustomTypesTest : public testing::Test {
117 protected:
118  CommonCustomTypesTest() {}
119  ~CommonCustomTypesTest() override {}
120
121 private:
122  base::MessageLoop message_loop_;
123
124  DISALLOW_COPY_AND_ASSIGN(CommonCustomTypesTest);
125};
126
127}  // namespace
128
129TEST_F(CommonCustomTypesTest, FilePath) {
130  base::RunLoop run_loop;
131
132  TestFilePathPtr ptr;
133  TestFilePathImpl impl(GetProxy(&ptr));
134
135  base::FilePath dir(FILE_PATH_LITERAL("hello"));
136  base::FilePath file = dir.Append(FILE_PATH_LITERAL("world"));
137
138  ptr->BounceFilePath(file, ExpectResponse(&file, run_loop.QuitClosure()));
139
140  run_loop.Run();
141}
142
143TEST_F(CommonCustomTypesTest, Time) {
144  base::RunLoop run_loop;
145
146  TestTimePtr ptr;
147  TestTimeImpl impl(GetProxy(&ptr));
148
149  base::Time t = base::Time::Now();
150
151  ptr->BounceTime(t, ExpectResponse(&t, run_loop.QuitClosure()));
152
153  run_loop.Run();
154}
155
156TEST_F(CommonCustomTypesTest, TimeDelta) {
157  base::RunLoop run_loop;
158
159  TestTimePtr ptr;
160  TestTimeImpl impl(GetProxy(&ptr));
161
162  base::TimeDelta t = base::TimeDelta::FromDays(123);
163
164  ptr->BounceTimeDelta(t, ExpectResponse(&t, run_loop.QuitClosure()));
165
166  run_loop.Run();
167}
168
169TEST_F(CommonCustomTypesTest, TimeTicks) {
170  base::RunLoop run_loop;
171
172  TestTimePtr ptr;
173  TestTimeImpl impl(GetProxy(&ptr));
174
175  base::TimeTicks t = base::TimeTicks::Now();
176
177  ptr->BounceTimeTicks(t, ExpectResponse(&t, run_loop.QuitClosure()));
178
179  run_loop.Run();
180}
181
182TEST_F(CommonCustomTypesTest, Value) {
183  TestValuePtr ptr;
184  TestValueImpl impl(GetProxy(&ptr));
185
186  base::DictionaryValue dict;
187  dict.SetBoolean("bool", false);
188  dict.SetInteger("int", 2);
189  dict.SetString("string", "some string");
190  dict.SetBoolean("nested.bool", true);
191  dict.SetInteger("nested.int", 9);
192  dict.Set("some_binary", base::BinaryValue::CreateWithCopiedBuffer("mojo", 4));
193  {
194    std::unique_ptr<base::ListValue> dict_list(new base::ListValue());
195    dict_list->AppendString("string");
196    dict_list->AppendBoolean(true);
197    dict.Set("list", std::move(dict_list));
198  }
199  {
200    base::RunLoop run_loop;
201    ptr->BounceDictionaryValue(
202        dict, ExpectResponse(&dict, run_loop.QuitClosure()));
203    run_loop.Run();
204  }
205
206  base::ListValue list;
207  list.AppendString("string");
208  list.AppendDouble(42.1);
209  list.AppendBoolean(true);
210  list.Append(base::BinaryValue::CreateWithCopiedBuffer("mojo", 4));
211  {
212    std::unique_ptr<base::DictionaryValue> list_dict(
213        new base::DictionaryValue());
214    list_dict->SetString("string", "str");
215    list.Append(std::move(list_dict));
216  }
217  {
218    base::RunLoop run_loop;
219    ptr->BounceListValue(list, ExpectResponse(&list, run_loop.QuitClosure()));
220    run_loop.Run();
221  }
222}
223
224}  // namespace test
225}  // namespace common
226}  // namespace mojo
227