1/* 2 * Copyright (c) 2024 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_memory.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(OH_PurgeableMemory *pdata, unsigned int loopCount); 46bool ReclaimPurgeable(void); 47void LoopReclaimPurgeable(unsigned int loopCount); 48void ModifyPurgMemByFunc(OH_PurgeableMemory *pdata, OH_PurgeableMemory_ModifyFunc Modfunc, void *param); 49 50class PurgeableMemoryTest : public testing::Test { 51public: 52 static void SetUpTestCase(); 53 static void TearDownTestCase(); 54 void SetUp(); 55 void TearDown(); 56}; 57 58void PurgeableMemoryTest::SetUpTestCase() 59{ 60} 61 62void PurgeableMemoryTest::TearDownTestCase() 63{ 64} 65 66void PurgeableMemoryTest::SetUp() 67{ 68} 69 70void PurgeableMemoryTest::TearDown() 71{ 72} 73 74HWTEST_F(PurgeableMemoryTest, MultiObjCreateTest, TestSize.Level1) 75{ 76 const char alphabetFinal[] = "BBCDEFGHIJKLMNOPQRSTUVWXYZ\0"; 77 struct AlphabetInitParam initPara = {'A', 'Z'}; 78 OH_PurgeableMemory *pobj1 = OH_PurgeableMemory_Create(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 if (OH_PurgeableMemory_BeginRead(pobj1)) { 86 ASSERT_STREQ(alphabetFinal, static_cast<char *>(OH_PurgeableMemory_GetContent(pobj1))); 87 OH_PurgeableMemory_EndRead(pobj1); 88 } 89 90 EXPECT_EQ(OH_PurgeableMemory_Destroy(pobj1), true); 91} 92 93 94HWTEST_F(PurgeableMemoryTest, WriteTest, TestSize.Level1) 95{ 96 const char alphabet[] = "CCCDEFGHIJKLMNOPQRSTUVWXYZ\0"; 97 struct AlphabetInitParam initPara = {'A', 'Z'}; 98 OH_PurgeableMemory *pobj = OH_PurgeableMemory_Create(27, InitAlphabet, &initPara); 99 LoopReclaimPurgeable(1); 100 101 struct AlphabetModifyParam a2b = {'A', 'B'}; 102 struct AlphabetModifyParam b2c = {'B', 'C'}; 103 ModifyPurgMemByFunc(pobj, ModifyAlphabetX2Y, static_cast<void *>(&a2b)); 104 ModifyPurgMemByFunc(pobj, ModifyAlphabetX2Y, static_cast<void *>(&b2c)); 105 106 if (OH_PurgeableMemory_BeginRead(pobj)) { 107 ASSERT_STREQ(alphabet, static_cast<char *>(OH_PurgeableMemory_GetContent(pobj))); 108 OH_PurgeableMemory_EndRead(pobj); 109 } else { 110 std::cout << __func__ << ": ERROR! BeginRead failed." << std::endl; 111 } 112 113 OH_PurgeableMemory_Destroy(pobj); 114 LoopReclaimPurgeable(3); 115} 116 117bool InitData(void *data, size_t size, char start, char end) 118{ 119 char *str = (char *)data; 120 size_t len = 0; 121 for (char ch = start; ch <= end && len < size; ch++) { 122 str[len++] = ch; 123 } 124 str[len] = 0; 125 return true; 126} 127 128bool InitAlphabet(void *data, size_t size, void *param) 129{ 130 struct AlphabetInitParam *para = (struct AlphabetInitParam *)param; 131 std::cout << "inter " << __func__ << std::endl; 132 bool ret = InitData(data, size, para->start, para->end); 133 std::cout << "quit " << __func__ << ": " << para->start << "-" << para->end << 134 ", data=[" << (char *)data << "]" << ", ret=" << (ret ? "true" : "false") << std::endl; 135 return ret; 136} 137 138bool ModifyData(void *data, size_t size, char src, char dst) 139{ 140 char *str = (char *)data; 141 size_t i = 0; 142 for (; i < size && str[i]; i++) { 143 if (str[i] == src) { 144 str[i] = dst; 145 } 146 } 147 str[i] = 0; 148 return true; 149} 150 151bool ModifyAlphabetX2Y(void *data, size_t size, void *param) 152{ 153 struct AlphabetModifyParam *para = (struct AlphabetModifyParam *)param; 154 std::cout << "inter " << __func__ << ": " << para->src << "->" << para->dst << 155 ", data=[" << (char *)data << "]" << std::endl; 156 bool ret = ModifyData(data, size, para->src, para->dst); 157 std::cout << "quit , data=[" << (char *)data << "]" << __func__ << 158 ", ret=" << (ret ? "true" : "false") << std::endl; 159 return ret; 160} 161 162void LoopPrintAlphabet(OH_PurgeableMemory *pdata, unsigned int loopCount) 163{ 164 std::cout << "inter " << __func__ << std::endl; 165 for (unsigned int i = 0; i < loopCount; i++) { 166 if (!OH_PurgeableMemory_BeginRead(pdata)) { 167 std::cout << __func__ << ": " << i << ". ERROR! BeginRead failed." << std::endl; 168 break; 169 } 170 std::cout << __func__ << ": " << i << ". data=[" << 171 (char *)OH_PurgeableMemory_GetContent(pdata) << "]" << std::endl; 172 OH_PurgeableMemory_EndRead(pdata); 173 std::this_thread::sleep_for(std::chrono::seconds(PRINT_INTERVAL_SECONDS)); 174 } 175 std::cout << "quit " << __func__ << std::endl; 176} 177 178bool ReclaimPurgeable(void) 179{ 180 FILE *f = fopen("/proc/sys/kernel/purgeable", "w"); 181 if (!f) { 182 std::cout << __func__ << ": open file failed" << std::endl; 183 return false; 184 } 185 bool succ = true; 186 if (fputs("1", f) == EOF) { 187 succ = false; 188 } 189 190 if (fclose(f) == EOF) { 191 std::cout << __func__ << ": close file failed" << std::endl; 192 } 193 194 return succ; 195} 196 197void LoopReclaimPurgeable(unsigned int loopCount) 198{ 199 bool ret = false; 200 std::cout << "inter " << __func__ << std::endl; 201 for (unsigned int i = 0; i < loopCount; i++) { 202 ret = ReclaimPurgeable(); 203 std::cout << __func__ << ": " << i << ". Reclaim result=" << (ret ? "succ" : "fail") << std::endl; 204 std::this_thread::sleep_for(std::chrono::seconds(RECLAIM_INTERVAL_SECONDS)); /* wait reclaim finish */ 205 } 206 std::cout << "quit " << __func__ << std::endl; 207} 208 209void ModifyPurgMemByFunc(OH_PurgeableMemory *pdata, OH_PurgeableMemory_ModifyFunc Modfunc, void *param) 210{ 211 if (OH_PurgeableMemory_BeginWrite(pdata)) { 212 std::this_thread::sleep_for(std::chrono::seconds(MODIFY_INTERVAL_SECONDS)); 213 OH_PurgeableMemory_AppendModify(pdata, Modfunc, param); 214 std::cout<< __func__ << " after mod data=[" << (char *)OH_PurgeableMemory_GetContent(pdata) << "]" << std::endl; 215 216 std::cout << __func__ << " data=[" << (char *)OH_PurgeableMemory_GetContent(pdata) << "]" << std::endl; 217 OH_PurgeableMemory_EndWrite(pdata); 218 } 219} 220} /* namespace */ 221