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 <gtest/gtest.h>
16
17#include "init_param.h"
18#include "init_utils.h"
19#include "param_stub.h"
20#include "param_init.h"
21
22using namespace std;
23using namespace testing::ext;
24
25static void ClientCheckParamValue(const char *name, const char *expectValue)
26{
27    char tmp[PARAM_BUFFER_SIZE] = {0};
28    u_int32_t len = sizeof(tmp);
29    int ret = SystemGetParameter(name, tmp, &len);
30    PARAM_LOGI("ClientCheckParamValue name %s value: \'%s\' expectValue:\'%s\' ", name, tmp, expectValue);
31    if (ret == 0 && len > 0) {
32        EXPECT_NE((int)strlen(tmp), 0);
33        if (expectValue != nullptr) {
34            EXPECT_EQ(strcmp(tmp, expectValue), 0);
35        }
36    }
37}
38
39// 多线程测试
40static void *TestSendParamSetMsg(void *args)
41{
42    if (args == nullptr) {
43        return nullptr;
44    }
45    std::string name = (char *)args;
46    PARAM_LOGI("TestSendParamSetMsg name :\'%s\' ", name.c_str());
47    int ret = SystemSetParameter(name.c_str(), name.c_str());
48    EXPECT_EQ(ret, 0);
49    return nullptr;
50}
51
52static void *TestSendParamWaitMsg(void *args)
53{
54    if (args == nullptr) {
55        return nullptr;
56    }
57    std::string name = "Wati.";
58    name = name + (char *)args;
59    PARAM_LOGI("TestSendParamWaitMsg name :\'%s\' \n", name.c_str());
60    int ret = SystemWaitParameter(name.c_str(), name.c_str(), 1);
61    EXPECT_GE(ret, 0);
62    return nullptr;
63}
64
65static void TestForMultiThread()
66{
67    static const int threadMaxNumer = 2;
68    PARAM_LOGI("TestForMultiThread \n");
69    pthread_t tids[threadMaxNumer + threadMaxNumer];
70    const char *names[] = {
71        "thread.1111.2222.3333.4444.5555",
72        "thread.2222.1111.2222.3333.4444",
73        "thread.3333.1111.2222.4444.5555",
74        "thread.4444.5555.1111.2222.3333",
75        "thread.5555.1111.2222.3333.4444"
76    };
77    for (size_t i = 0; i < threadMaxNumer; i++) {
78        pthread_create(&tids[i], nullptr, TestSendParamSetMsg,
79            reinterpret_cast<void *>(const_cast<char *>(names[i % ARRAY_LENGTH(names)])));
80    }
81    for (size_t i = threadMaxNumer; i < threadMaxNumer + threadMaxNumer; i++) {
82        pthread_create(&tids[i], nullptr, TestSendParamWaitMsg,
83            reinterpret_cast<void *>(const_cast<char *>(names[i % ARRAY_LENGTH(names)])));
84    }
85    for (size_t i = 0; i < threadMaxNumer + threadMaxNumer; i++) {
86        pthread_join(tids[i], nullptr);
87    }
88}
89
90static void TestParamTraversal()
91{
92    SystemTraversalParameter(
93        "",
94        [](ParamHandle handle, void *cookie) {
95            char value[PARAM_BUFFER_SIZE + PARAM_BUFFER_SIZE] = {0};
96            uint32_t commitId = 0;
97            int ret = SystemGetParameterCommitId(handle, &commitId);
98            EXPECT_EQ(ret, 0);
99            SystemGetParameterName(handle, value, PARAM_BUFFER_SIZE);
100            u_int32_t len = PARAM_BUFFER_SIZE;
101            SystemGetParameterValue(handle, ((char *)value) + PARAM_BUFFER_SIZE, &len);
102            printf("$$$$$$$$Param %s=%s \n", (char *)value, ((char *)value) + PARAM_BUFFER_SIZE);
103        },
104        nullptr);
105}
106
107static void TestPermission()
108{
109    const char *testName = "persist.111.ffff.bbbb.cccc.dddd.eeee.55555";
110    char tmp[PARAM_BUFFER_SIZE] = {0};
111    int ret;
112
113    ParamSecurityOps *paramSecurityOps = GetParamSecurityOps(0);
114    EXPECT_NE(paramSecurityOps, nullptr);
115    paramSecurityOps->securityCheckParamPermission = TestCheckParamPermission;
116    SetTestPermissionResult(DAC_RESULT_FORBIDED);
117    if ((GetParamSecurityLabel() != nullptr)) {
118        GetParamSecurityLabel()->flags[0] = LABEL_CHECK_IN_ALL_PROCESS;
119        ret = SystemSetParameter(testName, "22202");
120#ifdef __LITEOS_A__
121        EXPECT_EQ(ret, DAC_RESULT_FORBIDED);
122#else
123        EXPECT_EQ(ret, 0); // 本地不在校验
124#endif
125    }
126    paramSecurityOps->securityFreeLabel = TestFreeLocalSecurityLabel;
127    paramSecurityOps->securityCheckParamPermission = TestCheckParamPermission;
128    SetTestPermissionResult(0);
129    SystemWriteParam(testName, "22202");
130    ret = SystemSetParameter(testName, "22202");
131    ClientCheckParamValue(testName, "22202");
132
133    const int testResult = 201;
134    SetTestPermissionResult(testResult);
135    ret = SystemSetParameter(testName, "3333");
136#ifdef __LITEOS_A__
137    EXPECT_EQ(ret, testResult);
138#else
139    EXPECT_EQ(ret, 0); // 本地不在校验
140#endif
141
142    u_int32_t len = sizeof(tmp);
143    SetTestPermissionResult(DAC_RESULT_FORBIDED);
144    ret = SystemGetParameter(testName, tmp, &len);
145    EXPECT_EQ(ret, DAC_RESULT_FORBIDED);
146    RegisterSecurityOps(0);
147    SetTestPermissionResult(0); // recover testpermission result
148}
149
150void TestClientApi(char testBuffer[], uint32_t size, const char *name, const char *value)
151{
152    ParamHandle handle;
153    int ret = SystemFindParameter(name, &handle);
154    SystemWriteParam(name, value);
155    SystemSetParameter(name, value);
156    ret = SystemFindParameter(name, &handle);
157    EXPECT_EQ(ret, 0);
158    uint32_t commitId = 0;
159    ret = SystemGetParameterCommitId(handle, &commitId);
160    EXPECT_EQ(ret, 0);
161    ret = SystemGetParameterName(handle, testBuffer, size);
162    EXPECT_EQ(ret, 0);
163    EXPECT_EQ(strcmp(testBuffer, name), 0);
164    ret = SystemGetParameterValue(handle, testBuffer, &size);
165    EXPECT_EQ(ret, 0);
166    EXPECT_EQ(strcmp(testBuffer, value), 0);
167}
168
169namespace init_ut {
170class ClientUnitTest : public ::testing::Test {
171public:
172    ClientUnitTest() {}
173    virtual ~ClientUnitTest() {}
174    static void SetUpTestCase(void) {}
175    void SetUp(void)
176    {
177        if (GetParamSecurityLabel() != nullptr) {
178            GetParamSecurityLabel()->cred.uid = 1000;  // 1000 test uid
179            GetParamSecurityLabel()->cred.gid = 1000;  // 1000 test gid
180        }
181    }
182    void TearDown(void) {}
183    void TestBody(void) {}
184};
185
186HWTEST_F(ClientUnitTest, Init_TestClient_001, TestSize.Level0)
187{
188    const std::string name = "test.add.client.001.001";
189    const std::string value = "test.add.client.value.001.001";
190    // direct write
191    SystemWriteParam(name.c_str(), value.c_str());
192    SystemSetParameter(name.c_str(), value.c_str());
193    ClientCheckParamValue(name.c_str(), value.c_str());
194    SystemWaitParameter(name.c_str(), value.c_str(), 1);
195    // wait
196    SystemWaitParameter(name.c_str(), value.c_str(), 1);
197    SystemWaitParameter(name.c_str(), nullptr, 0);
198
199    // error
200    SystemWaitParameter(nullptr,  nullptr, 0);
201    SystemWaitParameter("@@@@", value.c_str(), 1);
202}
203
204HWTEST_F(ClientUnitTest, Init_TestParamValue_001, TestSize.Level0)
205{
206    // support empty string
207    const char *name = "test_readonly.dddddddddddddddddd.fffffffffffffffffff";
208    int ret = SystemSetParameter(name, "");
209    EXPECT_EQ(ret, 0);
210    ret = SystemSetParameter(name, "111111111");
211    EXPECT_EQ(ret, 0);
212    ret = SystemSetParameter(name, "");
213    EXPECT_EQ(ret, 0);
214}
215
216HWTEST_F(ClientUnitTest, Init_TestClient_002, TestSize.Level0)
217{
218    char testBuffer[PARAM_BUFFER_SIZE] = {0};
219    const std::string value = "test.add.client.value.001";
220    const std::string name = "test.add.client.001.003";
221    TestClientApi(testBuffer, PARAM_BUFFER_SIZE, name.c_str(), value.c_str());
222}
223
224HWTEST_F(ClientUnitTest, Init_TestClient_003, TestSize.Level0)
225{
226    // 3 Traversal test
227    TestParamTraversal();
228    SystemDumpParameters(1, -1, nullptr);
229}
230
231HWTEST_F(ClientUnitTest, Init_TestClient_004, TestSize.Level0)
232{
233    const std::string name = "test.add.client.001.004";
234    int ret = WatchParamCheck(name.c_str());
235#ifndef OHOS_LITE
236    EXPECT_EQ(ret, 0);
237#endif
238    ret = WatchParamCheck("&&&&&.test.tttt");
239    EXPECT_NE(ret, 0);
240
241    ret = WatchParamCheck(nullptr);
242#ifndef OHOS_LITE
243    EXPECT_EQ(ret, 100);
244#endif
245    // test permission
246    TestPermission();
247}
248
249HWTEST_F(ClientUnitTest, Init_TestClient_005, TestSize.Level0)
250{
251    TestForMultiThread();
252}
253
254HWTEST_F(ClientUnitTest, Init_TestClient_006, TestSize.Level0)
255{
256    int ret = SystemSetParameter("test.type.string.xxx", "xxxxxxx");
257    EXPECT_EQ(ret, 0);
258    ret = SystemSetParameter("test.type.string...xxx", "xxxxxxx");
259    EXPECT_EQ(ret, PARAM_CODE_INVALID_NAME);
260    ret = SystemSetParameter("test.type.string*xxx", "xxxxxxx");
261    EXPECT_EQ(ret, PARAM_CODE_INVALID_NAME);
262#if !(defined __LITEOS_A__ || defined __LITEOS_M__)
263    ret = SystemSetParameter("test.type.bool.xxx", "xxxxxxxxxxxxxxxx");
264    EXPECT_EQ(ret, PARAM_CODE_INVALID_VALUE);
265    char value[PARAM_VALUE_LEN_MAX] = {0};
266    u_int32_t len = sizeof(value);
267    ret = SystemGetParameter("test.permission.watcher.xxx", value, &len);
268    EXPECT_EQ(ret,  DAC_RESULT_FORBIDED);
269    ret = SystemGetParameter("test.type.xxx", value, &len);
270    EXPECT_EQ(ret, PARAM_CODE_NOT_FOUND);
271#endif
272}
273}  // namespace init_ut