• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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 <cstdio>
17 #include <climits>
18 #include <thread>
19 
20 #include "gtest/gtest.h"
21 #include "purgeable_mem_c.h"
22 
23 namespace {
24 using namespace testing;
25 using namespace testing::ext;
26 
27 struct AlphabetInitParam {
28     char start;
29     char end;
30 };
31 
32 struct AlphabetModifyParam {
33     char src;
34     char dst;
35 };
36 
37 static constexpr int PRINT_INTERVAL_SECONDS = 1;
38 static constexpr int RECLAIM_INTERVAL_SECONDS = 1;
39 static constexpr int MODIFY_INTERVAL_SECONDS = 2;
40 
41 bool InitData_(void *data, size_t size, char start, char end);
42 bool ModifyData_(void *data, size_t size, char src, char dst);
43 bool InitAlphabet(void *data, size_t size, void *param);
44 bool ModifyAlphabetX2Y(void *data, size_t size, void *param);
45 void LoopPrintAlphabet(struct PurgMem *pdata, unsigned int loopCount);
46 bool ReclaimPurgeable(void);
47 void LoopReclaimPurgeable(unsigned int loopCount);
48 void ModifyPurgMemByFunc(struct PurgMem *pdata, PurgMemModifyFunc Modfunc, void *param);
49 
50 class PurgeableCTest : public testing::Test {
51 public:
52     static void SetUpTestCase();
53     static void TearDownTestCase();
54     void SetUp();
55     void TearDown();
56 };
57 
SetUpTestCase()58 void PurgeableCTest::SetUpTestCase()
59 {
60 }
61 
TearDownTestCase()62 void PurgeableCTest::TearDownTestCase()
63 {
64 }
65 
SetUp()66 void PurgeableCTest::SetUp()
67 {
68 }
69 
TearDown()70 void PurgeableCTest::TearDown()
71 {
72 }
73 
74 HWTEST_F(PurgeableCTest, MultiObjCreateTest, TestSize.Level1)
75 {
76     const char alphabetFinal[] = "BBCDEFGHIJKLMNOPQRSTUVWXYZ\0";
77     struct AlphabetInitParam initPara = {'A', 'Z'};
78     struct PurgMem *pobj1 = PurgMemCreate(27, InitAlphabet, &initPara);
79     LoopPrintAlphabet(pobj1, 1);
80     struct AlphabetModifyParam a2b = {'A', 'B'};
81     ModifyPurgMemByFunc(pobj1, ModifyAlphabetX2Y, static_cast<void *>(&a2b));
82     LoopPrintAlphabet(pobj1, 1);
83     LoopReclaimPurgeable(1);
84 
85     struct PurgMem *pobj2 = PurgMemCreate(27, InitAlphabet, &initPara);
86     LoopPrintAlphabet(pobj2, 1);
87     ModifyPurgMemByFunc(pobj2, ModifyAlphabetX2Y, static_cast<void *>(&a2b));
88     LoopPrintAlphabet(pobj2, 1);
89 
90     if (PurgMemBeginRead(pobj1)) {
91         ASSERT_STREQ(alphabetFinal, static_cast<char *>(PurgMemGetContent(pobj1)));
92         PurgMemEndRead(pobj1);
93     } else {
94         std::cout << __func__ << ": ERROR! BeginRead failed." << std::endl;
95     }
96 
97     if (PurgMemBeginRead(pobj2)) {
98         ASSERT_STREQ(alphabetFinal, static_cast<char *>(PurgMemGetContent(pobj2)));
99         PurgMemEndRead(pobj2);
100     } else {
101         std::cout << __func__ << ": ERROR! BeginRead failed." << std::endl;
102     }
103 
104     PurgMemDestroy(pobj2);
105     PurgMemDestroy(pobj1);
106 }
107 
108 HWTEST_F(PurgeableCTest, ReadTest, TestSize.Level1)
109 {
110     const char alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ\0";
111     struct AlphabetInitParam initPara = {'A', 'Z'};
112     struct PurgMem *pobj = PurgMemCreate(27, InitAlphabet, &initPara);
113     LoopReclaimPurgeable(1);
114 
115     unsigned int loopCount = 3;
116     /* loop read content */
117     for (unsigned int i = 0; i < loopCount; i++) {
118         if (!PurgMemBeginRead(pobj)) {
119             std::cout << __func__ << ": ERROR! BeginRead failed." << std::endl;
120             continue;
121         }
122         ASSERT_STREQ(alphabet, static_cast<char *>(PurgMemGetContent(pobj)));
123         PurgMemEndRead(pobj);
124     }
125 
126     PurgMemDestroy(pobj);
127 }
128 
129 HWTEST_F(PurgeableCTest, WriteTest, TestSize.Level1)
130 {
131     const char alphabet[] = "CCCDEFGHIJKLMNOPQRSTUVWXYZ\0";
132     struct AlphabetInitParam initPara = {'A', 'Z'};
133     struct PurgMem *pobj = PurgMemCreate(27, InitAlphabet, &initPara);
134     LoopReclaimPurgeable(1);
135 
136     struct AlphabetModifyParam a2b = {'A', 'B'};
137     struct AlphabetModifyParam b2c = {'B', 'C'};
138     ModifyPurgMemByFunc(pobj, ModifyAlphabetX2Y, static_cast<void *>(&a2b));
139     ModifyPurgMemByFunc(pobj, ModifyAlphabetX2Y, static_cast<void *>(&b2c));
140 
141     if (PurgMemBeginRead(pobj)) {
142         ASSERT_STREQ(alphabet, static_cast<char *>(PurgMemGetContent(pobj)));
143         PurgMemEndRead(pobj);
144     } else {
145         std::cout << __func__ << ": ERROR! BeginRead failed." << std::endl;
146     }
147 
148     PurgMemDestroy(pobj);
149     LoopReclaimPurgeable(3);
150 }
151 
152 HWTEST_F(PurgeableCTest, ReadWriteTest, TestSize.Level1)
153 {
154     const char alphabet[] = "DDDDEFGHIJKLMNOPQRSTUVWXYZ\0";
155     struct AlphabetInitParam initPara = {'A', 'Z'};
156     struct PurgMem *pobj = PurgMemCreate(27, InitAlphabet, &initPara);
157     LoopReclaimPurgeable(1);
158     LoopPrintAlphabet(pobj, 1);
159 
160     struct AlphabetModifyParam a2b = {'A', 'B'};
161     struct AlphabetModifyParam b2c = {'B', 'C'};
162     struct AlphabetModifyParam c2d = {'C', 'D'};
163     ModifyPurgMemByFunc(pobj, ModifyAlphabetX2Y, static_cast<void *>(&a2b));
164     ModifyPurgMemByFunc(pobj, ModifyAlphabetX2Y, static_cast<void *>(&b2c));
165     ModifyPurgMemByFunc(pobj, ModifyAlphabetX2Y, static_cast<void *>(&c2d));
166 
167     if (PurgMemBeginRead(pobj)) {
168         ASSERT_STREQ(alphabet, static_cast<char *>(PurgMemGetContent(pobj)));
169         PurgMemEndRead(pobj);
170     } else {
171         std::cout << __func__ << ": ERROR! BeginRead failed." << std::endl;
172     }
173 
174     PurgMemDestroy(pobj);
175 }
176 
InitData_(void * data,size_t size,char start,char end)177 bool InitData_(void *data, size_t size, char start, char end)
178 {
179     char *str = (char *)data;
180     size_t len = 0;
181     for (char ch = start; ch <= end && len < size; ch++) {
182         str[len++] = ch;
183     }
184     str[len] = 0;
185     return true;
186 }
187 
InitAlphabet(void * data,size_t size,void * param)188 bool InitAlphabet(void *data, size_t size, void *param)
189 {
190     struct AlphabetInitParam *para = (struct AlphabetInitParam *)param;
191     std::cout << "inter " << __func__ << std::endl;
192     bool ret = InitData_(data, size, para->start, para->end);
193     std::cout << "quit " << __func__ << ": " << para->start << "-" << para->end <<
194         ", data=[" << (char *)data << "]" << ", ret=" << (ret ? "true" : "false") << std::endl;
195     return ret;
196 }
197 
ModifyData_(void * data,size_t size,char src,char dst)198 bool ModifyData_(void *data, size_t size, char src, char dst)
199 {
200     char *str = (char *)data;
201     size_t i = 0;
202     for (; i < size && str[i]; i++) {
203         if (str[i] == src) {
204             str[i] = dst;
205         }
206     }
207     str[i] = 0;
208     return true;
209 }
210 
ModifyAlphabetX2Y(void * data,size_t size,void * param)211 bool ModifyAlphabetX2Y(void *data, size_t size, void *param)
212 {
213     struct AlphabetModifyParam *para = (struct AlphabetModifyParam *)param;
214     std::cout << "inter " << __func__ << ": " << para->src << "->" << para->dst <<
215         ", data=[" << (char *)data << "]" << std::endl;
216     bool ret = ModifyData_(data, size, para->src, para->dst);
217     std::cout << "quit , data=[" << (char *)data << "]" << __func__ <<
218         ", ret=" << (ret ? "true" : "false") << std::endl;
219     return ret;
220 }
221 
LoopPrintAlphabet(struct PurgMem * pdata,unsigned int loopCount)222 void LoopPrintAlphabet(struct PurgMem *pdata, unsigned int loopCount)
223 {
224     std::cout << "inter " << __func__ << std::endl;
225     for (unsigned int i = 0; i < loopCount; i++) {
226         if (!PurgMemBeginRead(pdata)) {
227             std::cout << __func__ << ": " << i << ". ERROR! BeginRead failed." << std::endl;
228             break;
229         }
230         std::cout << __func__ << ": " << i << ". data=[" <<
231             (char *)PurgMemGetContent(pdata) << "]" << std::endl;
232         PurgMemEndRead(pdata);
233         std::this_thread::sleep_for(std::chrono::seconds(PRINT_INTERVAL_SECONDS));
234     }
235     std::cout << "quit " << __func__ << std::endl;
236 }
237 
ReclaimPurgeable(void)238 bool ReclaimPurgeable(void)
239 {
240     FILE *f = fopen("/proc/sys/kernel/purgeable", "w");
241     if (!f) {
242         std::cout << __func__ << ": open file failed" << std::endl;
243         return false;
244     }
245     bool succ = true;
246     if (fputs("1", f) == EOF) {
247         succ = false;
248     }
249 
250     if (fclose(f) == EOF) {
251         std::cout << __func__ << ": close file failed" << std::endl;
252     }
253 
254     return succ;
255 }
256 
LoopReclaimPurgeable(unsigned int loopCount)257 void LoopReclaimPurgeable(unsigned int loopCount)
258 {
259     bool ret = false;
260     std::cout << "inter " << __func__ << std::endl;
261     for (unsigned int i = 0; i < loopCount; i++) {
262         ret = ReclaimPurgeable();
263         std::cout << __func__ << ": " << i << ". Reclaim result=" << (ret ? "succ" : "fail") << std::endl;
264         std::this_thread::sleep_for(std::chrono::seconds(RECLAIM_INTERVAL_SECONDS)); /* wait reclaim finish */
265     }
266     std::cout << "quit " << __func__ << std::endl;
267 }
268 
ModifyPurgMemByFunc(struct PurgMem * pdata,PurgMemModifyFunc Modfunc,void * param)269 void ModifyPurgMemByFunc(struct PurgMem *pdata, PurgMemModifyFunc Modfunc, void *param)
270 {
271     if (!PurgMemBeginWrite(pdata)) {
272         std::cout << __func__ << ": ERROR! BeginWrite failed." << std::endl;
273         return;
274     }
275     std::this_thread::sleep_for(std::chrono::seconds(MODIFY_INTERVAL_SECONDS));
276     std::cout << __func__ << " before mod data=[" << (char *)PurgMemGetContent(pdata) << "]" << std::endl;
277     PurgMemAppendModify(pdata, Modfunc, param);
278     std::cout<< __func__ << " after mod data=[" << (char *)PurgMemGetContent(pdata) << "]" << std::endl;
279 
280     std::cout << __func__ << " data=[" << (char *)PurgMemGetContent(pdata) << "]" << std::endl;
281     PurgMemEndWrite(pdata);
282 }
283 } /* namespace */
284