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 "cloud_db_types.h"
19 #include "distributeddb_tools_unit_test.h"
20 #include "runtime_config.h"
21 #include "sqlite_relational_utils.h"
22 #include "virtual_cloud_data_translate.h"
23
24 using namespace testing::ext;
25 using namespace DistributedDB;
26 using namespace DistributedDBUnitTest;
27
28 namespace {
29 constexpr const char *CREATE_TABLE_SQL =
30 "CREATE TABLE IF NOT EXISTS worker1(" \
31 "id INT PRIMARY KEY,"
32 "name TEXT," \
33 "height REAL ," \
34 "married BOOLEAN ," \
35 "photo BLOB," \
36 "asset BLOB," \
37 "assets BLOB);";
38 const Asset g_localAsset = {
39 .version = 1, .name = "Phone", .assetId = "", .subpath = "/local/sync", .uri = "/local/sync",
40 .modifyTime = "123456", .createTime = "", .size = "256", .hash = "ASE"
41 };
42 std::string g_testDir;
43 std::string g_dbDir;
44 sqlite3 *g_db = nullptr;
45
46 class DistributedDBSqliteRelationalUtilsTest : public testing::Test {
47 public:
48 static void SetUpTestCase(void);
49 static void TearDownTestCase(void);
50 void SetUp();
51 void TearDown();
52 protected:
53 void CreateUserDBAndTable();
54 void PrepareStatement(const std::string &sql, sqlite3_stmt *&statement, bool hasCloudDataTranslate);
55 std::shared_ptr<VirtualCloudDataTranslate> virtualCloudDataTranslate_ = nullptr;
56 };
57
SetUpTestCase(void)58 void DistributedDBSqliteRelationalUtilsTest::SetUpTestCase(void)
59 {
60 DistributedDBToolsUnitTest::TestDirInit(g_testDir);
61 LOGI("The test db is:%s", g_testDir.c_str());
62 g_dbDir = g_testDir + "/";
63 }
64
TearDownTestCase(void)65 void DistributedDBSqliteRelationalUtilsTest::TearDownTestCase(void)
66 {
67 }
68
SetUp()69 void DistributedDBSqliteRelationalUtilsTest::SetUp()
70 {
71 DistributedDBToolsUnitTest::PrintTestCaseInfo();
72 g_db = RelationalTestUtils::CreateDataBase(g_dbDir + "test.db");
73 CreateUserDBAndTable();
74 }
75
TearDown()76 void DistributedDBSqliteRelationalUtilsTest::TearDown()
77 {
78 sqlite3_close_v2(g_db);
79 g_db = nullptr;
80 if (DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir) != 0) {
81 LOGE("rm test db files error.");
82 }
83 }
84
CreateUserDBAndTable()85 void DistributedDBSqliteRelationalUtilsTest::CreateUserDBAndTable()
86 {
87 ASSERT_EQ(RelationalTestUtils::ExecSql(g_db, "PRAGMA journal_mode=WAL;"), SQLITE_OK);
88 ASSERT_EQ(RelationalTestUtils::ExecSql(g_db, CREATE_TABLE_SQL), SQLITE_OK);
89 }
90
PrepareStatement(const std::string & sql,sqlite3_stmt * & statement,bool hasCloudDataTranslate)91 void DistributedDBSqliteRelationalUtilsTest::PrepareStatement(const std::string &sql, sqlite3_stmt *&statement,
92 bool hasCloudDataTranslate)
93 {
94 ASSERT_EQ(SQLiteUtils::GetStatement(g_db, sql, statement), E_OK);
95 VBucket data;
96 data.insert_or_assign("id", 1L);
97 data.insert_or_assign("name", "lihua");
98 data.insert_or_assign("height", 166.0); // 166.0 is random double value
99 data.insert_or_assign("married", true);
100 std::vector<uint8_t> photo(1, 'v');
101 data.insert_or_assign("photo", photo);
102 data.insert_or_assign("asset", g_localAsset);
103 Assets assets = { g_localAsset };
104 data.insert_or_assign("assets", assets);
105 EXPECT_EQ(SQLiteRelationalUtils::BindStatementByType(statement, 1, data["id"]), E_OK); // 1 is id cid
106 EXPECT_EQ(SQLiteRelationalUtils::BindStatementByType(statement, 2, data["name"]), E_OK); // 2 is name cid
107 EXPECT_EQ(SQLiteRelationalUtils::BindStatementByType(statement, 3, data["height"]), E_OK); // 3 is height cid
108 EXPECT_EQ(SQLiteRelationalUtils::BindStatementByType(statement, 4, data["married"]), E_OK); // 4 is married cid
109 EXPECT_EQ(SQLiteRelationalUtils::BindStatementByType(statement, 5, data["photo"]), E_OK); // 5 is photo cid
110 if (hasCloudDataTranslate) {
111 EXPECT_EQ(SQLiteRelationalUtils::BindStatementByType(statement, 6, data["asset"]), E_OK); // 6 is asset cid
112 EXPECT_EQ(SQLiteRelationalUtils::BindStatementByType(statement, 7, data["assets"]), E_OK); // 7 is assets cid
113 } else {
114 RuntimeConfig::SetCloudTranslate(nullptr);
115 EXPECT_EQ(SQLiteRelationalUtils::BindStatementByType(statement, 6, data["asset"]), -E_NOT_INIT); // 6 is asset
116 EXPECT_EQ(SQLiteRelationalUtils::BindStatementByType(statement, 7, data["assets"]), -E_NOT_INIT); // 7 is assets
117 }
118 }
119
120 /**
121 * @tc.name: SqliteRelationalUtilsTest001
122 * @tc.desc: Test interfaces when statement is nullptr
123 * @tc.type: FUNC
124 * @tc.require:
125 * @tc.author: chenchaohao
126 */
127 HWTEST_F(DistributedDBSqliteRelationalUtilsTest, SqliteRelationalUtilsTest001, TestSize.Level0)
128 {
129 /**
130 * @tc.steps:step1. statement is nullptr
131 * @tc.expected: step1. return OK
132 */
133 sqlite3_stmt *statement = nullptr;
134
135 /**
136 * @tc.steps:step2. test interface
137 * @tc.expected: step2. return OK
138 */
139 DataValue dataValue;
140 EXPECT_EQ(SQLiteRelationalUtils::GetDataValueByType(statement, 0, dataValue), -E_INVALID_ARGS);
141 Type typeValue;
142 EXPECT_EQ(SQLiteRelationalUtils::GetCloudValueByType(statement, TYPE_INDEX<Nil>, 0, typeValue), -E_INVALID_ARGS);
143 EXPECT_EQ(SQLiteUtils::StepNext(statement, false), -E_INVALID_ARGS);
144 std::string tableName = "worker1";
145 EXPECT_NE(SQLiteRelationalUtils::SelectServerObserver(g_db, tableName, false), E_OK);
146
147 /**
148 * @tc.steps:step3. close db and test interface
149 * @tc.expected: step3. return OK
150 */
151 sqlite3_close_v2(g_db);
152 g_db = nullptr;
153 std::string fileName = "";
154 EXPECT_FALSE(SQLiteRelationalUtils::GetDbFileName(g_db, fileName));
155 EXPECT_EQ(SQLiteRelationalUtils::SelectServerObserver(g_db, tableName, false), -E_INVALID_ARGS);
156 }
157
158 /**
159 * @tc.name: SqliteRelationalUtilsTest002
160 * @tc.desc: Test BindStatementByType if dataTranselate is nullptr
161 * @tc.type: FUNC
162 * @tc.require:
163 * @tc.author: chenchaohao
164 */
165 HWTEST_F(DistributedDBSqliteRelationalUtilsTest, SqliteRelationalUtilsTest002, TestSize.Level0)
166 {
167 /**
168 * @tc.steps:step1. prepare sql and bind statement
169 * @tc.expected: step1. return OK
170 */
171 std::string sql = "INSERT OR REPLACE INTO worker1(id, name, height, married, photo, asset, assets)" \
172 "VALUES (?,?,?,?,?,?,?);";
173 sqlite3_stmt *statement = nullptr;
174 PrepareStatement(sql, statement, false);
175 int errCode = E_OK;
176 SQLiteUtils::ResetStatement(statement, true, errCode);
177 ASSERT_EQ(statement, nullptr);
178 }
179
180 /**
181 * @tc.name: SqliteRelationalUtilsTest003
182 * @tc.desc: Test GetSelectVBucket
183 * @tc.type: FUNC
184 * @tc.require:
185 * @tc.author: chenchaohao
186 */
187 HWTEST_F(DistributedDBSqliteRelationalUtilsTest, SqliteRelationalUtilsTest003, TestSize.Level0)
188 {
189 /**
190 * @tc.steps:step1. set CloudDataTranslate
191 * @tc.expected: step1. return OK
192 */
193 virtualCloudDataTranslate_ = std::make_shared<VirtualCloudDataTranslate>();
194 RuntimeConfig::SetCloudTranslate(virtualCloudDataTranslate_);
195
196 /**
197 * @tc.steps:step2. insert data
198 * @tc.expected: step2. return OK
199 */
200 std::string sql = "INSERT OR REPLACE INTO worker1(id, name, height, married, photo, asset, assets)" \
201 "VALUES (?,?,?,?,?,?,?);";
202 sqlite3_stmt *statement = nullptr;
203 PrepareStatement(sql, statement, true);
204 EXPECT_EQ(SQLiteUtils::StepWithRetry(statement), SQLiteUtils::MapSQLiteErrno(SQLITE_DONE));
205 int errCode = E_OK;
206 SQLiteUtils::ResetStatement(statement, true, errCode);
207 ASSERT_EQ(statement, nullptr);
208
209 /**
210 * @tc.steps:step3. test GetSelectVBucket
211 * @tc.expected: step3. return OK
212 */
213 VBucket data;
214 ASSERT_EQ(SQLiteRelationalUtils::GetSelectVBucket(statement, data), -E_INVALID_ARGS);
215 sql = "SELECT id, name, height, married, photo, asset, assets from worker1;";
216 ASSERT_EQ(SQLiteUtils::GetStatement(g_db, sql, statement), E_OK);
217 EXPECT_EQ(SQLiteRelationalUtils::GetSelectVBucket(statement, data), E_OK);
218 SQLiteUtils::ResetStatement(statement, true, errCode);
219 ASSERT_EQ(statement, nullptr);
220 }
221 }