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