• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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 #include "ut_mod.h"
16 #include <openssl/evp.h>
17 #include <openssl/md5.h>
18 using namespace Hdc;
19 
20 namespace HdcTest {
TestBaseCommand(void * runtimePtr)21 bool TestBaseCommand(void *runtimePtr)
22 {
23     Runtime *rt = (Runtime *)runtimePtr;
24     uint8_t *bufPtr = nullptr;
25     int bytesIO = 0;
26     bool ret = false;
27     // test 'discover'
28     rt->InnerCall(UT_DISCOVER);
29     if ((bytesIO = Base::ReadBinFile((UT_TMP_PATH + "/base-discover.result").c_str(),
30                                      reinterpret_cast<void **>(&bufPtr), 0)) < 0) {
31         return false;
32     }
33     if (!strcmp("0", reinterpret_cast<char *>(bufPtr))) {
34         delete[] bufPtr;
35         bufPtr = nullptr;
36         return false;
37     }
38     delete[] bufPtr;
39     bufPtr = nullptr;
40     // test 'targets'
41     rt->InnerCall(UT_LIST_TARGETS);
42     constexpr int expert = 5;
43     if ((bytesIO = Base::ReadBinFile((UT_TMP_PATH + "/base-list.result").c_str(),
44                                      reinterpret_cast<void **>(&bufPtr), 0)) < expert) {
45         goto Finish;
46     }
47     if (strcmp(MESSAGE_SUCCESS.c_str(), reinterpret_cast<char *>(bufPtr))) {
48         goto Finish;
49     }
50     delete[] bufPtr;
51     bufPtr = nullptr;
52     // test 'any'
53     rt->InnerCall(UT_CONNECT_ANY);
54     if ((bytesIO = Base::ReadBinFile((UT_TMP_PATH + "/base-any.result").c_str(),
55                                      reinterpret_cast<void **>(&bufPtr), 0)) < 0) {
56         goto Finish;
57     }
58     if (strcmp(MESSAGE_SUCCESS.c_str(), reinterpret_cast<char *>(bufPtr))) {
59         goto Finish;
60     }
61     // all pass
62     ret = true;
63 
64 Finish:
65     if (bufPtr) {
66         delete[] bufPtr;
67         bufPtr = nullptr;
68     }
69     return ret;
70 }
71 
TestShellExecute(void * runtimePtr)72 bool TestShellExecute(void *runtimePtr)
73 {
74     Runtime *rt = (Runtime *)runtimePtr;
75     uint8_t *bufPtr = nullptr;
76     int bytesIO = 0;
77     bool ret = false;
78     char bufString[BUF_SIZE_DEFAULT4] = "";
79     string resultFile = "execute.result";
80     while (true) {
81         // test1
82         rt->InnerCall(UT_SHELL_BASIC);
83         constexpr int expert = 10;
84         if ((bytesIO = Base::ReadBinFile((UT_TMP_PATH + "/" + resultFile).c_str(),
85                                          reinterpret_cast<void **>(&bufPtr), 0)) < expert) {
86             break;
87         }
88         Base::RunPipeComand(const_cast<const char *>("id"), bufString, sizeof(bufString), false);
89         if (strcmp(bufString, reinterpret_cast<char *>(bufPtr))) {
90             break;
91         }
92         delete[] bufPtr;
93         bufPtr = nullptr;
94 
95         // test 2
96         rt->ResetUtTmpFile(resultFile);
97         rt->InnerCall(UT_SHELL_LIGHT);
98         if ((bytesIO = Base::ReadBinFile((UT_TMP_PATH + "/" + resultFile).c_str(),
99                                          reinterpret_cast<void **>(&bufPtr), 0)) < expert) {
100             break;
101         }
102         Base::RunPipeComand(const_cast<const char *>("cat /etc/passwd"), bufString, sizeof(bufString), false);
103         if (strcmp(bufString, reinterpret_cast<char *>(bufPtr))) {
104             break;
105         }
106         delete[] bufPtr;
107         bufPtr = nullptr;
108 
109         // all pass
110         ret = true;
111         break;
112     }
113     if (bufPtr) {
114         delete[] bufPtr;
115     }
116     return ret;
117 }
118 
Md5Sum(uint8_t * buf,int size)119 vector<uint8_t> Md5Sum(uint8_t *buf, int size)
120 {
121     vector<uint8_t> ret;
122     uint8_t md5Hash[MD5_DIGEST_LENGTH] = { 0 };
123     if (EVP_Digest(buf, size, md5Hash, NULL, EVP_md5(), NULL)) {
124         ret.insert(ret.begin(), md5Hash, md5Hash + sizeof(md5Hash));
125     }
126     return ret;
127 }
128 
129 // file send like recv in our code, so just test send is enough
TestFileCommand(void * runtimePtr)130 bool TestFileCommand(void *runtimePtr)
131 {
132     Runtime *rt = (Runtime *)runtimePtr;
133     bool ret = false;
134     char bufString[BUF_SIZE_DEFAULT] = "";
135     uint8_t *bufLocal = nullptr;
136     uint8_t *bufRemote = nullptr;
137     int sizeLocal = 0;
138     int sizeRemote = 0;
139     string localFile = Base::StringFormat("%s/file.local", UT_TMP_PATH.c_str());
140     string remoteFile = Base::StringFormat("%s/file.remote", UT_TMP_PATH.c_str());
141     do {
142         // to be use random buf, not bash result
143         string cmd = Base::StringFormat("find /usr > %s", localFile.c_str());
144         Base::RunPipeComand(cmd.c_str(), bufString, sizeof(bufString), false);
145         rt->InnerCall(UT_FILE_SEND);
146         if ((sizeLocal = Base::ReadBinFile(localFile.c_str(), reinterpret_cast<void **>(&bufLocal), 0)) < 0) {
147             break;
148         };
149         if ((sizeRemote = Base::ReadBinFile(remoteFile.c_str(), reinterpret_cast<void **>(&bufRemote), 0)) < 0) {
150             break;
151         };
152         auto localHash = Md5Sum(bufLocal, sizeLocal);
153         auto remoteHash = Md5Sum(bufRemote, sizeRemote);
154         if (memcmp(localHash.data(), remoteHash.data(), localHash.size())) {
155             break;
156         }
157         ret = true;
158     } while (false);
159 
160     if (bufLocal) {
161         delete[] bufLocal;
162     }
163     if (bufRemote) {
164         delete[] bufRemote;
165     }
166     return ret;
167 }
168 
UtForwardWaiter(uv_loop_t * loop,uv_tcp_t * server)169 void UtForwardWaiter(uv_loop_t *loop, uv_tcp_t *server)
170 {
171     auto funcOnNewConn = [](uv_stream_t *server, int status) -> void {
172         auto funcOnRead = [](uv_stream_t *client, ssize_t nread, const uv_buf_t *buf) -> void {
173             if (nread > 0 && !strcmp(buf->base, MESSAGE_SUCCESS.c_str())) {
174                 Base::WriteBinFile((UT_TMP_PATH + "/forward.result").c_str(),
175                                    reinterpret_cast<uint8_t *>(MESSAGE_SUCCESS.c_str()),
176                                    MESSAGE_SUCCESS.size(), true);
177             }
178             uv_close((uv_handle_t *)client, [](uv_handle_t *handle) { free(handle); });
179             free(buf->base);
180         };
181         if (status < 0) {
182             return;
183         }
184         uv_tcp_t *client = new uv_tcp_t();
185         uv_tcp_init(server->loop, client);
186         if (uv_accept(server, (uv_stream_t *)client) == 0) {
187             uv_read_start((uv_stream_t *)client,
188                           [](uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf) {
189                               buf->base = new char[suggested_size]();
190                               buf->len = suggested_size;
191                           },
192                           funcOnRead);
193         } else {
194             uv_close((uv_handle_t *)client, [](uv_handle_t *handle) { free(handle); });
195         }
196     };
197     const int utForwardTargetPort = 8082;
198     struct sockaddr_in addr;
199     if (uv_tcp_init(loop, server) || uv_ip4_addr("127.0.0.1", utForwardTargetPort, &addr)) {
200         return;
201     }
202     if (uv_tcp_bind(server, (const struct sockaddr *)&addr, 0) || uv_listen((uv_stream_t *)server, 5, funcOnNewConn)) {
203         return;
204     }
205     WRITE_LOG(LOG_DEBUG, "UtForwardWaiter listen on port:%d", utForwardTargetPort);
206 }
207 
UtForwardConnect(uv_loop_t * loop,uv_tcp_t * client,uv_tcp_t * server)208 bool UtForwardConnect(uv_loop_t *loop, uv_tcp_t *client, uv_tcp_t *server)
209 {
210     auto funcConn = [](uv_connect_t *req, int status) -> void {
211         uv_tcp_t *server = (uv_tcp_t *)req->data;
212         delete req;
213         if (status < 0) {
214             return;
215         }
216         Base::SendToStream((uv_stream_t *)req->handle, (uint8_t *)MESSAGE_SUCCESS.c_str(), MESSAGE_SUCCESS.size());
217         Base::DelayDoSimple(req->handle->loop, 3000, [=](const uint8_t flag, string &msg, const void *p) {
218             uv_close((uv_handle_t *)server, nullptr);  // notify UtForwardWaiter stop
219         });
220     };
221 
222     const int utForwardListenPort = 8081;
223     struct sockaddr_in addr;
224     bool ret = false;
225     uv_connect_t *connReq = new uv_connect_t();
226     connReq->data = server;
227     do {
228         if (uv_tcp_init(loop, client)) {
229             break;
230         }
231         uv_ip4_addr("127.0.0.1", utForwardListenPort, &addr);
232         if (uv_tcp_connect(connReq, client, (const struct sockaddr *)&addr, funcConn)) {
233             break;
234         }
235 
236         ret = true;
237     } while (false);
238     return ret;
239 }
240 
TestForwardExternThread(void * arg)241 void TestForwardExternThread(void *arg)
242 {
243     uv_loop_t loop;
244     uv_tcp_t server;
245     uv_tcp_t client;
246     const int clientForwardTimeout = 1000;
247     bool *clientOK = (bool *)arg;
248     auto funcDelayCallUtForwardConnect = [&](const uint8_t flag, string &msg, const void *p) -> void {
249         if (!*clientOK) {
250             // client create forward timeout
251             WRITE_LOG(LOG_WARN, "Client forward timeout");
252             uv_stop(&loop);
253         }
254         UtForwardConnect(&loop, &client, &server);
255     };
256 
257     uv_loop_init(&loop);
258     UtForwardWaiter(&loop, &server);
259     Base::DelayDoSimple(&loop, clientForwardTimeout, funcDelayCallUtForwardConnect);
260     uv_run(&loop, UV_RUN_DEFAULT);
261     uv_loop_close(&loop);
262 };
263 
TestForwardCommand(void * runtimePtr)264 bool TestForwardCommand(void *runtimePtr)
265 {
266     Runtime *rt = (Runtime *)runtimePtr;
267     uv_thread_t td;
268     char buf[BUF_SIZE_TINY] = "";
269     bool clientOK = false;
270     int sizeResult = 0;
271     uv_thread_create(&td, TestForwardExternThread, &clientOK);
272     rt->InnerCall(UT_FORWARD_TCP2TCP);
273     clientOK = true;
274     uv_thread_join(&td);
275     // all done, we will check result ok
276     string localFile = Base::StringFormat("%s/forward.result", UT_TMP_PATH.c_str());
277     if ((sizeResult = Base::ReadBinFile(localFile.c_str(), reinterpret_cast<void **>(buf), sizeof(buf))) < 0) {
278         return false;
279     };
280     if (strcmp(buf, MESSAGE_SUCCESS.c_str())) {
281         return false;
282     }
283     return true;
284 }
285 
TestAppCommand(void * runtimePtr)286 bool TestAppCommand(void *runtimePtr)
287 {
288     Runtime *rt = (Runtime *)runtimePtr;
289     char bufString[BUF_SIZE_DEFAULT] = "";
290     string localFile = Base::StringFormat("%s/app.hap", UT_TMP_PATH.c_str());
291     string cmd = Base::StringFormat("id --help > %s", localFile.c_str());  // I know it is a invalid hap file
292     Base::RunPipeComand(cmd.c_str(), bufString, sizeof(bufString), false);
293     rt->InnerCall(UT_APP_INSTALL);
294 
295     constexpr int expert = 5;
296     if (Base::ReadBinFile((UT_TMP_PATH + "/appinstall.result").c_str(), reinterpret_cast<void **>(&bufString),
297                           sizeof(bufString)) < expert) {
298         return false;
299     }
300     if (strcmp(MESSAGE_SUCCESS.c_str(), reinterpret_cast<char *>(bufString))) {
301         return false;
302     }
303     return true;
304 }
305 }  // namespace HdcTest