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