/* * Copyright (c) 2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include #include #include #include #include #include #include #include #include "common.h" #include "sqlite3sym.h" using namespace testing::ext; using namespace UnitTest::SQLiteTest; #define TEST_DIR "./sqlitecksumtest" #define TEST_DB (TEST_DIR "/test.db") #define TEST_PRESET_TABLE_COUNT 20 #define TEST_PRESET_DATA_COUNT 1000 #define TEST_DATA_REAL (16.1) namespace Test { class SQLiteCksumTest : public testing::Test { public: static void SetUpTestCase(void); static void TearDownTestCase(void); void SetUp(); void TearDown(); static void UtSqliteLogPrint(void *data, int err, const char *msg); static void UtBackupDatabase(sqlite3 *srcDb, sqlite3 *destDb); static void UtPresetDb(const std::string &dbFile, const std::string &vfsStr); static int UtSqliteExecCallback(void *data, int argc, char **argv, char **azColName); static bool IsSupportPageCheck(void); static int hitCksmFault_; }; int SQLiteCksumTest::hitCksmFault_ = 0; void SQLiteCksumTest::SetUpTestCase(void) { Common::RemoveDir(TEST_DIR); Common::MakeDir(TEST_DIR); } void SQLiteCksumTest::TearDownTestCase(void) { } void SQLiteCksumTest::SetUp(void) { sqlite3_config(SQLITE_CONFIG_LOG, &SQLiteCksumTest::UtSqliteLogPrint, nullptr); EXPECT_EQ(sqlite3_register_cksumvfs(NULL), SQLITE_OK); } void SQLiteCksumTest::TearDown(void) { EXPECT_EQ(sqlite3_unregister_cksumvfs(), SQLITE_OK); sqlite3_config(SQLITE_CONFIG_LOG, NULL, NULL); } void SQLiteCksumTest::UtSqliteLogPrint(void *data, int err, const char *msg) { std::string errStr = msg; if (errStr.find("checksum fault") != std::string::npos) { std::cout << "Hit checksum fault!!!" << std::endl; hitCksmFault_++; } std::cout << "SQLiteCksumTest xLog err:" << err << ", msg:" << msg << std::endl; } int SQLiteCksumTest::UtSqliteExecCallback(void *data, int argc, char **argv, char **azColName) { std::cout << (const char *)data << " result:" << std::endl; for (int i = 0; i < argc; i++) { std::cout << azColName[i] << " = " << (argv[i] ? argv[i] : "NULL") << std::endl; } std::cout <(data); *static_cast(data) = count + 1; // 2 means 2 fields, entryId, entryName EXPECT_EQ(argc, 2); return SQLITE_OK; } static void UtDestroyFile(const std::string &dbPath, int offset, const std::string replaceStr) { int fd = open(dbPath.c_str(), O_WRONLY | O_CREAT); lseek(fd, offset, SEEK_SET); write(fd, replaceStr.c_str(), replaceStr.size()); close(fd); } /** * @tc.name: CksumTest002 * @tc.desc: Test to enable cksum on compress db * @tc.type: FUNC */ HWTEST_F(SQLiteCksumTest, CksumTest002, TestSize.Level0) { if (!IsSupportPageCheck()) { GTEST_SKIP() << "Current testcase is not compatible"; } /** * @tc.steps: step1. Create a new db as main, enable compress * @tc.expected: step1. Execute successfully */ std::string dbPath = TEST_DIR "/test002.db"; UtPresetDb(dbPath, "compressvfs"); /** * @tc.steps: step2. Destory the db file to simulate corrupted * @tc.expected: step2. Execute successfully */ // 2 * 4096 + 512 means the corrupted position, which locate on the third page, 512 bytes offset UtDestroyFile(dbPath, 2 * 4096 + 512, "123"); /** * @tc.steps: step3. Reverse the table to get the info, check log info, should print "checksum fault" * @tc.expected: step3. Execute successfully */ hitCksmFault_ = 0; sqlite3 *db = nullptr; EXPECT_EQ(sqlite3_open_v2(dbPath.c_str(), &db, SQLITE_OPEN_READWRITE, "compressvfs"), SQLITE_OK); int count = 0; EXPECT_EQ(sqlite3_exec(db, "SELECT entryId, entryName FROM salary;", UtQueryResult, &count, nullptr), SQLITE_OK); EXPECT_EQ(hitCksmFault_, 1); EXPECT_EQ(count, TEST_PRESET_DATA_COUNT); sqlite3_close_v2(db); } } // namespace Test