1 /**
2 * (c) 2019 by Mega Limited, Wellsford, New Zealand
3 *
4 * This file is part of the MEGA SDK - Client Access Engine.
5 *
6 * Applications using the MEGA API must present a valid application key
7 * and comply with the the rules set forth in the Terms of Service.
8 *
9 * The MEGA SDK is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 *
13 * @copyright Simplified (2-clause) BSD License.
14 *
15 * You should have received a copy of the license along with this
16 * program.
17 */
18
19 #include <memory>
20
21 #include <gtest/gtest.h>
22
23 #include <mega/command.h>
24 #include <mega/json.h>
25 #include <mega/megaapp.h>
26 #include <mega/megaclient.h>
27 #include <mega/types.h>
28
29 using namespace std;
30 using namespace mega;
31
32 namespace {
33
34 class MockApp_CommandGetRegisteredContacts : public MegaApp
35 {
36 public:
37 using DataType = vector<tuple<string, string, string>>;
38
39 int mCallCount = 0;
40 ErrorCodes mLastError = ErrorCodes::API_EINTERNAL;
41 std::unique_ptr<DataType> mRegisteredContacts;
42
getregisteredcontacts_result(const ErrorCodes e,DataType * const data)43 void getregisteredcontacts_result(const ErrorCodes e, DataType* const data) override
44 {
45 ++mCallCount;
46 mLastError = e;
47 if (data)
48 {
49 mRegisteredContacts = std::unique_ptr<DataType>{new DataType{*data}};
50 }
51 else
52 {
53 assert(e != ErrorCodes::API_OK);
54 }
55 }
56 };
57
58 } // anonymous
59
TEST(Commands,CommandGetRegisteredContacts_processResult_happyPath)60 TEST(Commands, CommandGetRegisteredContacts_processResult_happyPath)
61 {
62 MockApp_CommandGetRegisteredContacts app;
63
64 JSON json;
65 json.pos = R"({"eud":"Zm9vQG1lZ2EuY28ubno","id":"13","ud":"Zm9vQG1lZ2EuY28ubno"},{"eud":"KzY0MjcxMjM0NTY3","id":"42","ud":"KzY0IDI3IDEyMyA0NTY3"})";
66 const auto jsonBegin = json.pos;
67 const auto jsonLength = strlen(json.pos);
68
69 CommandGetRegisteredContacts::processResult(app, json);
70
71 const vector<tuple<string, string, string>> expected{
72 {"foo@mega.co.nz", "13", "foo@mega.co.nz"},
73 {"+64271234567", "42", "+64 27 123 4567"},
74 };
75
76 ASSERT_EQ(1, app.mCallCount);
77 ASSERT_EQ(API_OK, app.mLastError);
78 ASSERT_NE(nullptr, app.mRegisteredContacts);
79 ASSERT_EQ(expected, *app.mRegisteredContacts);
80 ASSERT_EQ((long)jsonLength, std::distance(jsonBegin, json.pos)); // assert json has been parsed all the way
81 }
82
TEST(Commands,CommandGetRegisteredContacts_processResult_onlyOneContact)83 TEST(Commands, CommandGetRegisteredContacts_processResult_onlyOneContact)
84 {
85 MockApp_CommandGetRegisteredContacts app;
86
87 JSON json;
88 json.pos = R"({"eud":"Zm9vQG1lZ2EuY28ubno","id":"13","ud":"Zm9vQG1lZ2EuY28ubno"})";
89 const auto jsonBegin = json.pos;
90 const auto jsonLength = strlen(json.pos);
91
92 CommandGetRegisteredContacts::processResult(app, json);
93
94 const vector<tuple<string, string, string>> expected{
95 {"foo@mega.co.nz", "13", "foo@mega.co.nz"},
96 };
97
98 ASSERT_EQ(1, app.mCallCount);
99 ASSERT_EQ(API_OK, app.mLastError);
100 ASSERT_NE(nullptr, app.mRegisteredContacts);
101 ASSERT_EQ(expected, *app.mRegisteredContacts);
102 ASSERT_EQ(ptrdiff_t(jsonLength), std::distance(jsonBegin, json.pos)); // assert json has been parsed all the way
103 }
104
TEST(Commands,CommandGetRegisteredContacts_processResult_extraFieldShouldBeIgnored)105 TEST(Commands, CommandGetRegisteredContacts_processResult_extraFieldShouldBeIgnored)
106 {
107 MockApp_CommandGetRegisteredContacts app;
108
109 JSON json;
110 json.pos = R"({"eud":"Zm9vQG1lZ2EuY28ubno","id":"13","ud":"Zm9vQG1lZ2EuY28ubno","YmxhaA":"42"})";
111 const auto jsonBegin = json.pos;
112 const auto jsonLength = strlen(json.pos);
113
114 CommandGetRegisteredContacts::processResult(app, json);
115
116 const vector<tuple<string, string, string>> expected{
117 {"foo@mega.co.nz", "13", "foo@mega.co.nz"},
118 };
119
120 ASSERT_EQ(1, app.mCallCount);
121 ASSERT_EQ(API_OK, app.mLastError);
122 ASSERT_NE(nullptr, app.mRegisteredContacts);
123 ASSERT_EQ(expected, *app.mRegisteredContacts);
124 ASSERT_EQ(ptrdiff_t(jsonLength), std::distance(jsonBegin, json.pos)); // assert json has been parsed all the way
125 }
126
TEST(Commands,CommandGetRegisteredContacts_processResult_invalidResponse)127 TEST(Commands, CommandGetRegisteredContacts_processResult_invalidResponse)
128 {
129 MockApp_CommandGetRegisteredContacts app;
130
131 JSON json;
132 json.pos = R"({"eud":"Zm9vQG1lZ2EuY28ubno","id":"13","YmxhaA":"42"})";
133 const auto jsonBegin = json.pos;
134 const auto jsonLength = strlen(json.pos);
135
136 CommandGetRegisteredContacts::processResult(app, json);
137
138 ASSERT_EQ(1, app.mCallCount);
139 ASSERT_EQ(API_EINTERNAL, app.mLastError);
140 ASSERT_EQ(nullptr, app.mRegisteredContacts);
141 ASSERT_EQ(ptrdiff_t(jsonLength), std::distance(jsonBegin, json.pos)); // assert json has been parsed all the way
142 }
143
144 namespace {
145
146 class MockApp_CommandGetCountryCallingCodes : public MegaApp
147 {
148 public:
149 using DataType = map<string, vector<string>>;
150
151 int mCallCount = 0;
152 ErrorCodes mLastError = ErrorCodes::API_EINTERNAL;
153 std::unique_ptr<DataType> mCountryCallingCodes;
154
getcountrycallingcodes_result(const ErrorCodes e,DataType * const data)155 void getcountrycallingcodes_result(const ErrorCodes e, DataType* const data) override
156 {
157 ++mCallCount;
158 mLastError = e;
159 if (data)
160 {
161 mCountryCallingCodes = std::unique_ptr<DataType>{new DataType{*data}};
162 }
163 else
164 {
165 assert(e != ErrorCodes::API_OK);
166 }
167 }
168 };
169
170 } // anonymous
171
TEST(Commands,CommandGetCountryCallingCodes_processResult_happyPath)172 TEST(Commands, CommandGetCountryCallingCodes_processResult_happyPath)
173 {
174 MockApp_CommandGetCountryCallingCodes app;
175
176 JSON json;
177 json.pos = R"({"cc":"AD","l":[376]},{"cc":"AE","l":[971,13]},{"cc":"AF","l":[93,13,42]})";
178 const auto jsonBegin = json.pos;
179 const auto jsonLength = strlen(json.pos);
180
181 CommandGetCountryCallingCodes::processResult(app, json);
182
183 const map<string, vector<string>> expected{
184 {"AD", {"376"}},
185 {"AE", {"971", "13"}},
186 {"AF", {"93", "13", "42"}},
187 };
188
189 ASSERT_EQ(1, app.mCallCount);
190 ASSERT_EQ(API_OK, app.mLastError);
191 ASSERT_NE(nullptr, app.mCountryCallingCodes);
192 ASSERT_EQ(expected, *app.mCountryCallingCodes);
193 ASSERT_EQ(ptrdiff_t(jsonLength), std::distance(jsonBegin, json.pos)); // assert json has been parsed all the way
194 }
195
TEST(Commands,CommandGetCountryCallingCodes_processResult_onlyOneCountry)196 TEST(Commands, CommandGetCountryCallingCodes_processResult_onlyOneCountry)
197 {
198 MockApp_CommandGetCountryCallingCodes app;
199
200 JSON json;
201 json.pos = R"({"cc":"AD","l":[12,376]})";
202 const auto jsonBegin = json.pos;
203 const auto jsonLength = strlen(json.pos);
204
205 CommandGetCountryCallingCodes::processResult(app, json);
206
207 const map<string, vector<string>> expected{
208 {"AD", {"12", "376"}},
209 };
210
211 ASSERT_EQ(1, app.mCallCount);
212 ASSERT_EQ(API_OK, app.mLastError);
213 ASSERT_NE(nullptr, app.mCountryCallingCodes);
214 ASSERT_EQ(expected, *app.mCountryCallingCodes);
215 ASSERT_EQ(ptrdiff_t(jsonLength), std::distance(jsonBegin, json.pos)); // assert json has been parsed all the way
216 }
217
TEST(Commands,CommandGetCountryCallingCodes_processResult_extraFieldShouldBeIgnored)218 TEST(Commands, CommandGetCountryCallingCodes_processResult_extraFieldShouldBeIgnored)
219 {
220 MockApp_CommandGetCountryCallingCodes app;
221
222 JSON json;
223 json.pos = R"({"cc":"AD","l":[12,376],"blah":"42"})";
224 const auto jsonBegin = json.pos;
225 const auto jsonLength = strlen(json.pos);
226
227 CommandGetCountryCallingCodes::processResult(app, json);
228
229 const map<string, vector<string>> expected{
230 {"AD", {"12", "376"}},
231 };
232
233 ASSERT_EQ(1, app.mCallCount);
234 ASSERT_EQ(API_OK, app.mLastError);
235 ASSERT_NE(nullptr, app.mCountryCallingCodes);
236 ASSERT_EQ(expected, *app.mCountryCallingCodes);
237 ASSERT_EQ(ptrdiff_t(jsonLength), std::distance(jsonBegin, json.pos)); // assert json has been parsed all the way
238 }
239
TEST(Commands,CommandGetCountryCallingCodes_processResult_invalidResponse)240 TEST(Commands, CommandGetCountryCallingCodes_processResult_invalidResponse)
241 {
242 MockApp_CommandGetCountryCallingCodes app;
243
244 JSON json;
245 json.pos = R"({"cc":"AD","blah":[12,376]})";
246 const auto jsonBegin = json.pos;
247 const auto jsonLength = strlen(json.pos);
248
249 CommandGetCountryCallingCodes::processResult(app, json);
250
251 ASSERT_EQ(1, app.mCallCount);
252 ASSERT_EQ(API_EINTERNAL, app.mLastError);
253 ASSERT_EQ(nullptr, app.mCountryCallingCodes);
254 ASSERT_EQ(ptrdiff_t(jsonLength), std::distance(jsonBegin, json.pos)); // assert json has been parsed all the way
255 }
256