• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <gtest/gtest.h>
17 
18 #include <fstream>
19 #include <string>
20 #include <unistd.h>
21 #include <vector>
22 
23 #include "common.h"
24 #include "logger.h"
25 #include "rdb_errno.h"
26 #include "rdb_helper.h"
27 #include "rdb_open_callback.h"
28 
29 using namespace testing::ext;
30 using namespace OHOS::Rdb;
31 using namespace OHOS::NativeRdb;
32 
33 namespace Test {
34 
35 class RdbCorruptTest : public testing::Test {
36 public:
SetUpTestCase(void)37     static void SetUpTestCase(void) {}
TearDownTestCase(void)38     static void TearDownTestCase(void) {}
39     void SetUp();
40     void TearDown();
41     void GenerateData(int count);
42     static void DestroyDbFile(const std::string &filePath, size_t offset, size_t len, unsigned char ch);
43     static constexpr const char *DATABASE_NAME = "corrupt_test.db";
44     std::shared_ptr<RdbStore> store_;
45 };
46 
47 class CorruptTestOpenCallback : public RdbOpenCallback {
48 public:
49     int OnCreate(RdbStore &store) override;
50     int OnUpgrade(RdbStore &store, int oldVersion, int newVersion) override;
51     static constexpr const char *CREATE_TABLE_TEST = "CREATE TABLE IF NOT EXISTS test "
52                                                      "(id INTEGER PRIMARY KEY AUTOINCREMENT, "
53                                                      "name TEXT NOT NULL, age INTEGER, salary "
54                                                      "REAL, blobType BLOB)";
55 };
56 
OnCreate(RdbStore & store)57 int CorruptTestOpenCallback::OnCreate(RdbStore &store)
58 {
59     return store.ExecuteSql(CREATE_TABLE_TEST);
60 }
61 
OnUpgrade(RdbStore & store,int oldVersion,int newVersion)62 int CorruptTestOpenCallback::OnUpgrade(RdbStore &store, int oldVersion, int newVersion)
63 {
64     return E_OK;
65 }
66 
SetUp(void)67 void RdbCorruptTest::SetUp(void)
68 {
69     RdbHelper::ClearCache();
70     RdbHelper::DeleteRdbStore(RDB_TEST_PATH + DATABASE_NAME);
71     RdbStoreConfig sqliteSharedRstConfig(RDB_TEST_PATH + DATABASE_NAME);
72     CorruptTestOpenCallback openCallback;
73     int errCode = E_OK;
74     store_ = RdbHelper::GetRdbStore(sqliteSharedRstConfig, 1, openCallback, errCode);
75     EXPECT_NE(store_, nullptr);
76     EXPECT_EQ(errCode, E_OK);
77     // Preset 1000 entries into database file
78     GenerateData(1000);
79     store_ = nullptr;
80     RdbHelper::ClearCache();
81 }
82 
TearDown(void)83 void RdbCorruptTest::TearDown(void)
84 {
85     RdbHelper::ClearCache();
86     RdbHelper::DeleteRdbStore(RDB_TEST_PATH + DATABASE_NAME);
87 }
88 
GenerateData(int count)89 void RdbCorruptTest::GenerateData(int count)
90 {
91     for (int64_t i = 0; i < count; i++) {
92         // Preset data into database
93         RowData rowData = {1, "test", 18, 100.5, std::vector<uint8_t>{ 1, 2, 3 }};
94         rowData.id += i;
95         rowData.name += std::to_string(i + 1);
96         rowData.salary += i;
97         int64_t rowId = 0;
98         auto ret = store_->Insert(rowId, "test", UTUtils::SetRowData(rowData));
99         EXPECT_EQ(E_OK, ret);
100         EXPECT_EQ(i + 1, rowId);
101     }
102 }
103 
DestroyDbFile(const std::string & filePath,size_t offset,size_t len,unsigned char ch)104 void RdbCorruptTest::DestroyDbFile(const std::string &filePath, size_t offset, size_t len, unsigned char ch)
105 {
106     std::fstream f;
107     f.open(filePath.c_str());
108 
109     f.seekp(offset, std::ios::beg);
110     std::vector<char> buf(len, ch);
111     f.write(buf.data(), len);
112     f.close();
113 }
114 
115 /**
116  * @tc.name: RdbCorruptTest001
117  * @tc.desc: test Rdb corruption
118  * @tc.type: FUNC
119  */
120 HWTEST_F(RdbCorruptTest, RdbCorruptTest001, TestSize.Level2)
121 {
122     // Destroy database file, set 1st byte of 3rd page into undefined flag, which indicate the btree page type
123     RdbCorruptTest::DestroyDbFile(RDB_TEST_PATH + DATABASE_NAME, 8192, 1, 0xFF);
124 
125     // Get RDB store failed as database corrupted
126     CorruptTestOpenCallback sqliteCallback;
127     RdbStoreConfig sqliteConfig(RDB_TEST_PATH + DATABASE_NAME);
128     int errCode = E_OK;
129     store_ = RdbHelper::GetRdbStore(sqliteConfig, 1, sqliteCallback, errCode);
130     EXPECT_NE(store_, nullptr);
131     EXPECT_EQ(errCode, E_OK);
132 
133     std::shared_ptr<ResultSet> resultSet = store_->QueryByStep("SELECT * FROM test");
134     EXPECT_NE(resultSet, nullptr);
135 
136     while ((errCode = resultSet->GoToNextRow()) == E_OK) {
137     }
138     EXPECT_EQ(errCode, E_SQLITE_CORRUPT);
139 }
140 } // namespace Test