1// Copyright 2014 The Chromium OS 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 <brillo/dbus/dbus_param_reader.h>
6
7#include <string>
8
9#include <brillo/variant_dictionary.h>
10#include <gtest/gtest.h>
11
12using dbus::MessageReader;
13using dbus::MessageWriter;
14using dbus::Response;
15
16namespace brillo {
17namespace dbus_utils {
18
19TEST(DBusParamReader, NoArgs) {
20  std::unique_ptr<Response> message = Response::CreateEmpty();
21  MessageReader reader(message.get());
22  bool called = false;
23  auto callback = [&called]() { called = true; };
24  EXPECT_TRUE(DBusParamReader<false>::Invoke(callback, &reader, nullptr));
25  EXPECT_TRUE(called);
26}
27
28TEST(DBusParamReader, OneArg) {
29  std::unique_ptr<Response> message = Response::CreateEmpty();
30  MessageWriter writer(message.get());
31  AppendValueToWriter(&writer, 123);
32  MessageReader reader(message.get());
33  bool called = false;
34  auto callback = [&called](int param1) {
35    EXPECT_EQ(123, param1);
36    called = true;
37  };
38  EXPECT_TRUE(
39      (DBusParamReader<false, int>::Invoke(callback, &reader, nullptr)));
40  EXPECT_TRUE(called);
41}
42
43TEST(DBusParamReader, ManyArgs) {
44  std::unique_ptr<Response> message = Response::CreateEmpty();
45  MessageWriter writer(message.get());
46  AppendValueToWriter(&writer, true);
47  AppendValueToWriter(&writer, 1972);
48  AppendValueToWriter(&writer,
49                      VariantDictionary{{"key", std::string{"value"}}});
50  MessageReader reader(message.get());
51  bool called = false;
52  auto callback = [&called](bool p1, int p2, const VariantDictionary& p3) {
53    EXPECT_TRUE(p1);
54    EXPECT_EQ(1972, p2);
55    EXPECT_EQ(1, p3.size());
56    EXPECT_EQ("value", p3.find("key")->second.Get<std::string>());
57    called = true;
58  };
59  EXPECT_TRUE((DBusParamReader<false, bool, int, VariantDictionary>::Invoke(
60      callback, &reader, nullptr)));
61  EXPECT_TRUE(called);
62}
63
64TEST(DBusParamReader, TooManyArgs) {
65  std::unique_ptr<Response> message = Response::CreateEmpty();
66  MessageWriter writer(message.get());
67  AppendValueToWriter(&writer, true);
68  AppendValueToWriter(&writer, 1972);
69  AppendValueToWriter(&writer,
70                      VariantDictionary{{"key", std::string{"value"}}});
71  MessageReader reader(message.get());
72  bool called = false;
73  auto callback = [&called](bool param1, int param2) {
74    EXPECT_TRUE(param1);
75    EXPECT_EQ(1972, param2);
76    called = true;
77  };
78  ErrorPtr error;
79  EXPECT_FALSE(
80      (DBusParamReader<false, bool, int>::Invoke(callback, &reader, &error)));
81  EXPECT_FALSE(called);
82  EXPECT_EQ(errors::dbus::kDomain, error->GetDomain());
83  EXPECT_EQ(DBUS_ERROR_INVALID_ARGS, error->GetCode());
84  EXPECT_EQ("Too many parameters in a method call", error->GetMessage());
85}
86
87TEST(DBusParamReader, TooFewArgs) {
88  std::unique_ptr<Response> message = Response::CreateEmpty();
89  MessageWriter writer(message.get());
90  AppendValueToWriter(&writer, true);
91  MessageReader reader(message.get());
92  bool called = false;
93  auto callback = [&called](bool param1, int param2) {
94    EXPECT_TRUE(param1);
95    EXPECT_EQ(1972, param2);
96    called = true;
97  };
98  ErrorPtr error;
99  EXPECT_FALSE(
100      (DBusParamReader<false, bool, int>::Invoke(callback, &reader, &error)));
101  EXPECT_FALSE(called);
102  EXPECT_EQ(errors::dbus::kDomain, error->GetDomain());
103  EXPECT_EQ(DBUS_ERROR_INVALID_ARGS, error->GetCode());
104  EXPECT_EQ("Too few parameters in a method call", error->GetMessage());
105}
106
107TEST(DBusParamReader, TypeMismatch) {
108  std::unique_ptr<Response> message = Response::CreateEmpty();
109  MessageWriter writer(message.get());
110  AppendValueToWriter(&writer, true);
111  AppendValueToWriter(&writer, 1972);
112  MessageReader reader(message.get());
113  bool called = false;
114  auto callback = [&called](bool param1, double param2) {
115    EXPECT_TRUE(param1);
116    EXPECT_DOUBLE_EQ(1972.0, param2);
117    called = true;
118  };
119  ErrorPtr error;
120  EXPECT_FALSE((
121      DBusParamReader<false, bool, double>::Invoke(callback, &reader, &error)));
122  EXPECT_FALSE(called);
123  EXPECT_EQ(errors::dbus::kDomain, error->GetDomain());
124  EXPECT_EQ(DBUS_ERROR_INVALID_ARGS, error->GetCode());
125  EXPECT_EQ("Method parameter type mismatch", error->GetMessage());
126}
127
128TEST(DBusParamReader, NoArgs_With_OUT) {
129  std::unique_ptr<Response> message = Response::CreateEmpty();
130  MessageReader reader(message.get());
131  bool called = false;
132  auto callback = [&called](int* param1) {
133    EXPECT_EQ(0, *param1);
134    called = true;
135  };
136  EXPECT_TRUE(
137      (DBusParamReader<true, int*>::Invoke(callback, &reader, nullptr)));
138  EXPECT_TRUE(called);
139}
140
141TEST(DBusParamReader, OneArg_Before_OUT) {
142  std::unique_ptr<Response> message = Response::CreateEmpty();
143  MessageWriter writer(message.get());
144  AppendValueToWriter(&writer, 123);
145  MessageReader reader(message.get());
146  bool called = false;
147  auto callback = [&called](int param1, double* param2) {
148    EXPECT_EQ(123, param1);
149    EXPECT_DOUBLE_EQ(0.0, *param2);
150    called = true;
151  };
152  EXPECT_TRUE((
153      DBusParamReader<true, int, double*>::Invoke(callback, &reader, nullptr)));
154  EXPECT_TRUE(called);
155}
156
157TEST(DBusParamReader, OneArg_After_OUT) {
158  std::unique_ptr<Response> message = Response::CreateEmpty();
159  MessageWriter writer(message.get());
160  AppendValueToWriter(&writer, 123);
161  MessageReader reader(message.get());
162  bool called = false;
163  auto callback = [&called](double* param1, int param2) {
164    EXPECT_DOUBLE_EQ(0.0, *param1);
165    EXPECT_EQ(123, param2);
166    called = true;
167  };
168  EXPECT_TRUE((
169      DBusParamReader<true, double*, int>::Invoke(callback, &reader, nullptr)));
170  EXPECT_TRUE(called);
171}
172
173TEST(DBusParamReader, ManyArgs_With_OUT) {
174  std::unique_ptr<Response> message = Response::CreateEmpty();
175  MessageWriter writer(message.get());
176  AppendValueToWriter(&writer, true);
177  AppendValueToWriter(&writer, 1972);
178  AppendValueToWriter(&writer,
179                      VariantDictionary{{"key", std::string{"value"}}});
180  MessageReader reader(message.get());
181  bool called = false;
182  auto callback = [&called](bool p1,
183                            std::string* p2,
184                            int p3,
185                            int* p4,
186                            const VariantDictionary& p5,
187                            bool* p6) {
188    EXPECT_TRUE(p1);
189    EXPECT_EQ("", *p2);
190    EXPECT_EQ(1972, p3);
191    EXPECT_EQ(0, *p4);
192    EXPECT_EQ(1, p5.size());
193    EXPECT_EQ("value", p5.find("key")->second.Get<std::string>());
194    EXPECT_FALSE(*p6);
195    called = true;
196  };
197  EXPECT_TRUE((DBusParamReader<true,
198                               bool,
199                               std::string*,
200                               int,
201                               int*,
202                               VariantDictionary,
203                               bool*>::Invoke(callback, &reader, nullptr)));
204  EXPECT_TRUE(called);
205}
206
207TEST(DBusParamReader, TooManyArgs_With_OUT) {
208  std::unique_ptr<Response> message = Response::CreateEmpty();
209  MessageWriter writer(message.get());
210  AppendValueToWriter(&writer, true);
211  AppendValueToWriter(&writer, 1972);
212  AppendValueToWriter(&writer,
213                      VariantDictionary{{"key", std::string{"value"}}});
214  MessageReader reader(message.get());
215  bool called = false;
216  auto callback = [&called](bool param1, int param2, int* param3) {
217    EXPECT_TRUE(param1);
218    EXPECT_EQ(1972, param2);
219    EXPECT_EQ(0, *param3);
220    called = true;
221  };
222  ErrorPtr error;
223  EXPECT_FALSE((DBusParamReader<true, bool, int, int*>::Invoke(
224      callback, &reader, &error)));
225  EXPECT_FALSE(called);
226  EXPECT_EQ(errors::dbus::kDomain, error->GetDomain());
227  EXPECT_EQ(DBUS_ERROR_INVALID_ARGS, error->GetCode());
228  EXPECT_EQ("Too many parameters in a method call", error->GetMessage());
229}
230
231TEST(DBusParamReader, TooFewArgs_With_OUT) {
232  std::unique_ptr<Response> message = Response::CreateEmpty();
233  MessageWriter writer(message.get());
234  AppendValueToWriter(&writer, true);
235  MessageReader reader(message.get());
236  bool called = false;
237  auto callback = [&called](bool param1, int param2, int* param3) {
238    EXPECT_TRUE(param1);
239    EXPECT_EQ(1972, param2);
240    EXPECT_EQ(0, *param3);
241    called = true;
242  };
243  ErrorPtr error;
244  EXPECT_FALSE((DBusParamReader<true, bool, int, int*>::Invoke(
245      callback, &reader, &error)));
246  EXPECT_FALSE(called);
247  EXPECT_EQ(errors::dbus::kDomain, error->GetDomain());
248  EXPECT_EQ(DBUS_ERROR_INVALID_ARGS, error->GetCode());
249  EXPECT_EQ("Too few parameters in a method call", error->GetMessage());
250}
251
252}  // namespace dbus_utils
253}  // namespace brillo
254