• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <utility>
17 
18 #include "gtest/gtest.h"
19 #include "extern_api.h"
20 #include "widget_selector.h"
21 
22 using namespace OHOS::uitest;
23 using namespace std;
24 using namespace nlohmann;
25 
26 // test fixture
27 class ExternApiTest : public testing::Test {
28 public:
29     ~ExternApiTest() override = default;
30 };
31 
32 class DummyApi : public ExternApi<TypeId::BY> {
33 public:
DummyApi(string_view val)34     explicit DummyApi(string_view val) : value_(val) {};
35 
36     ~ DummyApi() = default;
37 
WriteIntoParcel(json & data) const38     void WriteIntoParcel(json &data) const override
39     {
40         data["value"] = value_;
41     }
42 
ReadFromParcel(const json & data)43     void ReadFromParcel(const json &data) override
44     {
45         value_ = data["value"];
46     }
47 
48     string value_;
49 };
50 
TEST_F(ExternApiTest,readWriteParcelable)51 TEST_F(ExternApiTest, readWriteParcelable)
52 {
53     json container;
54     // write
55     PushBackValueItemIntoJson<string>("wyz", container);
56     PushBackValueItemIntoJson<int32_t>(666, container);
57     PushBackValueItemIntoJson<float>(0.2f, container);
58     PushBackValueItemIntoJson<bool>(true, container);
59     auto obj = DummyApi("zl");
60     PushBackValueItemIntoJson<DummyApi>(obj, container);
61     // read
62     auto val0 = GetItemValueFromJson<string>(container, 0);
63     auto val1 = GetItemValueFromJson<int32_t>(container, 1);
64     auto val2 = GetItemValueFromJson<float>(container, 2);
65     auto val3 = GetItemValueFromJson<bool>(container, 3);
66     auto val4 = GetItemValueFromJson<json>(container, 4);
67     // verify
68     ASSERT_EQ("wyz", val0);
69     ASSERT_EQ(666, val1);
70     ASSERT_EQ(0.2f, val2);
71     ASSERT_EQ(true, val3);
72     ASSERT_EQ("zl", val4["value"]);
73 }
74 
GenerateUniqueId()75 static string GenerateUniqueId()
76 {
77     return to_string(GetCurrentMicroseconds());
78 }
79 
TEST_F(ExternApiTest,noInvocationHandler)80 TEST_F(ExternApiTest, noInvocationHandler)
81 {
82     static auto apiId = GenerateUniqueId();
83     auto& server = ExternApiServer::Get();
84     json caller;
85     auto in = json::array();
86     auto out = json::array();
87     auto err = ApiCallErr(NO_ERROR);
88     server.Call(apiId, caller, in, out, err);
89     ASSERT_EQ(INTERNAL_ERROR, err.code_);
90     ASSERT_TRUE(err.message_.find("No handler found") != string::npos);
91 }
92 
TEST_F(ExternApiTest,addRemoveHandler)93 TEST_F(ExternApiTest, addRemoveHandler)
94 {
95     static auto apiId = GenerateUniqueId();
96     auto &server = ExternApiServer::Get();
97     auto handler = [](string_view fun, json &caller, const json &in, json &out, ApiCallErr &err) {
98         if (fun == apiId) {
99             return true;
100         }
101         return false;
102     };
103     server.AddHandler(handler);
104 
105     json caller;
106     auto in = json::array();
107     auto out = json::array();
108     auto err = ApiCallErr(NO_ERROR);
109     server.Call(apiId, caller, in, out, err);
110     ASSERT_EQ(NO_ERROR, err.code_);
111 
112     server.RemoveHandler(handler);
113     server.Call(apiId, caller, in, out, err);
114     ASSERT_EQ(INTERNAL_ERROR, err.code_) << "The handler should be unavailable after been removed";
115 }
116 
TEST_F(ExternApiTest,inOutObjectsTransfer)117 TEST_F(ExternApiTest, inOutObjectsTransfer)
118 {
119     static auto apiId = GenerateUniqueId();
120     auto& server = ExternApiServer::Get();
121     auto handler = [](string_view fun, json &caller, const json &in, json &out, ApiCallErr &err) {
122         if (fun == apiId) {
123             // write back the parameter value
124             PushBackValueItemIntoJson<int32_t>(GetItemValueFromJson<int32_t>(in, 0), out);
125             return true;
126         }
127         return false;
128     };
129     server.AddHandler(handler);
130 
131     json caller;
132     auto in0 = json::array();
133     auto in1 = json::array();
134     auto out0 = json::array();
135     auto out1 = json::array();
136     auto err = ApiCallErr(NO_ERROR);
137     PushBackValueItemIntoJson<int32_t>(0, in0);
138     PushBackValueItemIntoJson<int32_t>(1, in1);
139     server.Call(apiId, caller, in0, out0, err);
140     // api request should be handled and get correct return value
141     ASSERT_EQ(NO_ERROR, err.code_);std::cout<<out0.dump()<<std::endl;
142     ASSERT_EQ(0, GetItemValueFromJson<int32_t>(out0, 0));
143     server.Call(apiId, caller, in1, out1, err);
144     ASSERT_EQ(NO_ERROR, err.code_);
145     ASSERT_EQ(1, GetItemValueFromJson<int32_t>(out1, 0));
146 }
147 
TEST_F(ExternApiTest,jsonExceptionDefance)148 TEST_F(ExternApiTest, jsonExceptionDefance)
149 {
150     static auto apiId = GenerateUniqueId();
151     auto& server = ExternApiServer::Get();
152     auto handler = [](string_view fun, json &caller, const json &in, json &out, ApiCallErr &err) {
153         if (fun == apiId) {
154             // this statement will cause out-of-index exception
155             int32_t val0 = in.at(100);
156             return val0 > 0;
157         }
158         return false;
159     };
160     server.AddHandler(handler);
161 
162     json caller;
163     auto in = json::array();
164     auto out = json::array();
165     auto err = ApiCallErr(NO_ERROR);
166     server.Call(apiId, caller, in, out, err);
167     // json exception should be caught and reported properly
168     ASSERT_EQ(INTERNAL_ERROR, err.code_);
169     ASSERT_TRUE(err.message_.find("Exception raised") != string::npos);
170     ASSERT_TRUE(err.message_.find("json.exception.out_of_range") != string::npos);
171 }
172 
TEST_F(ExternApiTest,apiErrorDeliver)173 TEST_F(ExternApiTest, apiErrorDeliver)
174 {
175     static auto apiId = GenerateUniqueId();
176     auto& server = ExternApiServer::Get();
177     auto handler = [](string_view fun, json &caller, const json &in, json &out, ApiCallErr &err) {
178         if (fun == apiId) {
179             // this statement will cause out-of-index exception
180             int32_t val0 = GetItemValueFromJson<int32_t>(in, 0);
181             if (val0 == 0) {
182                 err = ApiCallErr(NO_ERROR);
183             } else {
184                 err = ApiCallErr(INTERNAL_ERROR, "dummy_error");
185             }
186             return true;
187         }
188         return false;
189     };
190     server.AddHandler(handler);
191 
192     json caller;
193     auto in0 = json::array();
194     PushBackValueItemIntoJson<int32_t>(0, in0);
195     auto in1 = json::array();
196     PushBackValueItemIntoJson<int32_t>(1, in1);
197     auto out = json::array();
198     auto err = ApiCallErr(NO_ERROR);
199 
200     server.Call(apiId, caller, in0, out, err);
201     ASSERT_EQ(NO_ERROR, err.code_) << err.message_;
202     server.Call(apiId, caller, in1, out, err);
203     // api error should be delivered out to caller
204     ASSERT_EQ(INTERNAL_ERROR, err.code_);
205     ASSERT_TRUE(err.message_.find("dummy_error") != string::npos);
206 }
207 
TEST_F(ExternApiTest,stopDispatchingToRestHandlersAfterHandled)208 TEST_F(ExternApiTest, stopDispatchingToRestHandlersAfterHandled)
209 {
210     auto& server = ExternApiServer::Get();
211     auto handler0 = [](string_view fun, json &caller, const json &in, json &out, ApiCallErr &err) {
212         PushBackValueItemIntoJson<int32_t>(0, out);
213         if (fun != "api0") {
214             return false;
215         }
216         return true;
217     };
218     auto handler1 = [](string_view fun, json &caller, const json &in, json &out, ApiCallErr &err) {
219         PushBackValueItemIntoJson<int32_t>(1, out);
220         if (fun != "api1") {
221             return false;
222         }
223         auto param0 = GetItemValueFromJson<string>(in, 0);
224         if (param0 == "good") {
225             err = ApiCallErr(NO_ERROR);
226         } else {
227             err = ApiCallErr(INTERNAL_ERROR, "not good");
228         }
229         return true;
230     };
231     auto handler2 = [](string_view fun, json &caller, const json &in, json &out, ApiCallErr &err) {
232         PushBackValueItemIntoJson<int32_t>(2, out);
233         return fun == "api2";
234     };
235     server.AddHandler(handler0);
236     server.AddHandler(handler1);
237     server.AddHandler(handler2);
238 
239     json caller;
240     auto in = json::array();
241     auto out = json::array();
242     auto err = ApiCallErr(NO_ERROR);
243     PushBackValueItemIntoJson<string>("good", in);
244     server.Call("api1", caller, in, out, err);
245     // Request should not be dispatched to handler2, since its served with by handler1
246     ASSERT_EQ(2, out.size());
247     ASSERT_EQ(NO_ERROR, err.code_);
248     ASSERT_EQ(0, GetItemValueFromJson<int32_t>(out, 0));
249     ASSERT_EQ(1, GetItemValueFromJson<int32_t>(out, 1));
250     in.clear();
251     out.clear();
252     PushBackValueItemIntoJson<string>("bad", in);
253     server.Call("api1", caller, in, out, err);
254     // Request should not be dispatched to handler2, since its served with by handler1, even though error happened
255     ASSERT_EQ(2, out.size());
256     ASSERT_EQ(INTERNAL_ERROR, err.code_);
257     ASSERT_EQ(0, GetItemValueFromJson<int32_t>(out, 0));
258     ASSERT_EQ(1, GetItemValueFromJson<int32_t>(out, 1));
259 }
260 
TEST_F(ExternApiTest,apiTransactE2E)261 TEST_F(ExternApiTest, apiTransactE2E)
262 {
263     static auto apiId = GenerateUniqueId();
264     auto& server = ExternApiServer::Get();
265     auto handler = [](string_view fun, json &caller, const json &in, json &out, ApiCallErr &err) {
266         if (fun != apiId) {
267             return false;
268         }
269         PushBackValueItemIntoJson<int32_t>(0, out);
270         return true;
271     };
272     server.AddHandler(handler);
273 
274     string resultStr = ApiTransact(apiId, "{}", "[]");
275     auto result = json::parse(resultStr);
276     ASSERT_FALSE(result.contains("exception"));
277     ASSERT_TRUE(result.contains("result_values"));
278     ASSERT_NE(0, result["result_values"].size()) << resultStr; // should have result values
279 }
280 
TEST_F(ExternApiTest,apiTransactE2EFailure)281 TEST_F(ExternApiTest, apiTransactE2EFailure)
282 {
283     static auto apiId = GenerateUniqueId();
284     auto &server = ExternApiServer::Get();
285     auto handler = [](string_view fun, json &caller, const json &in, json &out, ApiCallErr &err) {
286         if (fun != apiId) {
287             return false;
288         }
289         PushBackValueItemIntoJson<int32_t>(0, out);
290         return true;
291     };
292     server.AddHandler(handler);
293 
294     string resultStr = ApiTransact("foo", "{}", "[]"); // api not-found
295     auto result = json::parse(resultStr);
296     ASSERT_TRUE(result.contains("exception")) << "Transact failure should be delivered in the results";
297 }