1 /*
2 * Copyright (c) 2025 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 #include "cloud_sync_log_table_manager.h"
18 #include "distributeddb_tools_unit_test.h"
19 #include "rdb_data_generator.h"
20 #include "relational_store_client.h"
21 #include "sqlite_relational_utils.h"
22 #include "table_info.h"
23
24 using namespace testing::ext;
25 using namespace DistributedDB;
26 using namespace DistributedDBUnitTest;
27
28 namespace {
29 constexpr const char *DB_SUFFIX = ".db";
30 constexpr const char *STORE_ID = "Relational_Store_ID";
31 std::string g_dbDir;
32 std::string g_testDir;
33 }
34
35 namespace {
36 class DistributedDBRDBKnowledgeClientTest : public testing::Test {
37 public:
38 static void SetUpTestCase(void);
39 static void TearDownTestCase(void);
40 void SetUp() override;
41 void TearDown() override;
42 protected:
43 static UtTableSchemaInfo GetTableSchema(const std::string &table);
44 static void SaveSchemaToMetaTable(sqlite3 *db, const std::string tableName, const TableInfo &tableInfo);
45 static void CreateDistributedTable(const std::vector<std::string> &tableNames,
46 DistributedDB::TableSyncType tableSyncType);
47 static constexpr const char *KNOWLEDGE_TABLE = "KNOWLEDGE_TABLE";
48 static constexpr const char *SYNC_TABLE = "SYNC_TABLE";
49 };
50
51
SetUpTestCase(void)52 void DistributedDBRDBKnowledgeClientTest::SetUpTestCase(void)
53 {
54 DistributedDBToolsUnitTest::TestDirInit(g_testDir);
55 LOGD("Test dir is %s", g_testDir.c_str());
56 g_dbDir = g_testDir + "/";
57 DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir);
58 }
59
TearDownTestCase(void)60 void DistributedDBRDBKnowledgeClientTest::TearDownTestCase(void)
61 {
62 }
63
SetUp()64 void DistributedDBRDBKnowledgeClientTest::SetUp()
65 {
66 }
67
TearDown()68 void DistributedDBRDBKnowledgeClientTest::TearDown()
69 {
70 DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir);
71 }
72
GetTableSchema(const std::string & table)73 UtTableSchemaInfo DistributedDBRDBKnowledgeClientTest::GetTableSchema(const std::string &table)
74 {
75 UtTableSchemaInfo tableSchema;
76 tableSchema.name = table;
77 UtFieldInfo field;
78 field.field.colName = "id";
79 field.field.type = TYPE_INDEX<int64_t>;
80 field.field.primary = true;
81 tableSchema.fieldInfo.push_back(field);
82 field.field.primary = false;
83 field.field.colName = "int_field1";
84 tableSchema.fieldInfo.push_back(field);
85 field.field.colName = "int_field2";
86 tableSchema.fieldInfo.push_back(field);
87 field.field.colName = "int_field3";
88 tableSchema.fieldInfo.push_back(field);
89 return tableSchema;
90 }
91
SaveSchemaToMetaTable(sqlite3 * db,const std::string tableName,const TableInfo & tableInfo)92 void DistributedDBRDBKnowledgeClientTest::SaveSchemaToMetaTable(sqlite3 *db, const std::string tableName,
93 const TableInfo &tableInfo)
94 {
95 RelationalSchemaObject schema;
96 schema.SetTableMode(DistributedDB::DistributedTableMode::SPLIT_BY_DEVICE);
97 schema.RemoveRelationalTable(tableName);
98 schema.AddRelationalTable(tableInfo);
99
100 const Key schemaKey(DBConstant::RELATIONAL_SCHEMA_KEY,
101 DBConstant::RELATIONAL_SCHEMA_KEY + strlen(DBConstant::RELATIONAL_SCHEMA_KEY));
102 Value schemaVal;
103 auto schemaStr = schema.ToSchemaString();
104 EXPECT_FALSE(schemaStr.size() > SchemaConstant::SCHEMA_STRING_SIZE_LIMIT);
105 DBCommon::StringToVector(schemaStr, schemaVal);
106 EXPECT_EQ(SQLiteRelationalUtils::PutKvData(db, false, schemaKey, schemaVal), E_OK);
107 }
108
CreateDistributedTable(const std::vector<std::string> & tableNames,DistributedDB::TableSyncType tableSyncType)109 void DistributedDBRDBKnowledgeClientTest::CreateDistributedTable(const std::vector<std::string> &tableNames,
110 DistributedDB::TableSyncType tableSyncType)
111 {
112 sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX);
113 EXPECT_NE(db, nullptr);
114 for (const auto &tableName : tableNames) {
115 TableInfo tableInfo;
116 tableInfo.SetTableName(tableName);
117 tableInfo.SetTableSyncType(tableSyncType);
118 TrackerTable table111;
119 tableInfo.SetTrackerTable(table111);
120 DistributedTable distributedTable;
121 distributedTable.tableName = tableName;
122 tableInfo.SetDistributedTable(distributedTable);
123 std::unique_ptr<SqliteLogTableManager> tableManager = std::make_unique<CloudSyncLogTableManager>();
124 EXPECT_NE(tableManager, nullptr);
125 EXPECT_EQ(SQLiteUtils::AnalysisSchema(db, tableName, tableInfo), E_OK);
126 std::vector<FieldInfo> fieldInfos = tableInfo.GetFieldInfos();
127 EXPECT_EQ(SQLiteRelationalUtils::CreateRelationalMetaTable(db), E_OK);
128 EXPECT_EQ(SQLiteRelationalUtils::InitCursorToMeta(db, false, tableName), E_OK);
129 EXPECT_EQ(tableManager->CreateRelationalLogTable(db, tableInfo), E_OK);
130 EXPECT_EQ(tableManager->AddRelationalLogTableTrigger(db, tableInfo, ""), E_OK);
131 SQLiteRelationalUtils::SetLogTriggerStatus(db, true);
132 SaveSchemaToMetaTable(db, tableName, tableInfo);
133 }
134 EXPECT_EQ(sqlite3_close_v2(db), E_OK);
135 }
136
InsertDBData(const std::string & tableName,int count,sqlite3 * db)137 void InsertDBData(const std::string &tableName, int count, sqlite3 *db)
138 {
139 for (int i = 1; i <= count; i++) {
140 std::string sql = "INSERT INTO " + tableName + " VALUES(" + std::to_string(i) + ',' + std::to_string(i) + ',' +
141 std::to_string(i) + ',' + std::to_string(i) + ");";
142 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
143 }
144 }
145
146 /**
147 * @tc.name: SetKnowledge001
148 * @tc.desc: Test set knowledge schema.
149 * @tc.type: FUNC
150 * @tc.require:
151 * @tc.author: zqq
152 */
153 HWTEST_F(DistributedDBRDBKnowledgeClientTest, SetKnowledge001, TestSize.Level0)
154 {
155 /**
156 * @tc.steps: step1. Set knowledge source schema and clean deleted data.
157 * @tc.expected: step1. Ok
158 */
159 UtTableSchemaInfo tableInfo = GetTableSchema(KNOWLEDGE_TABLE);
160 sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX);
161 EXPECT_NE(db, nullptr);
162 RDBDataGenerator::InitTableWithSchemaInfo(tableInfo, *db);
163 KnowledgeSourceSchema schema;
164 schema.tableName = KNOWLEDGE_TABLE;
165 schema.extendColNames.insert("id");
166 schema.knowledgeColNames.insert("int_field1");
167 schema.knowledgeColNames.insert("int_field2");
168 EXPECT_EQ(SetKnowledgeSourceSchema(db, schema), OK);
169 EXPECT_EQ(CleanDeletedData(db, schema.tableName, 0u), OK);
170 /**
171 * @tc.steps: step2. Clean deleted data after insert one data.
172 * @tc.expected: step2. Ok
173 */
174 InsertDBData(schema.tableName, 1, db);
175 EXPECT_EQ(CleanDeletedData(db, schema.tableName, 0u), OK);
176 /**
177 * @tc.steps: step3. Clean deleted data after delete one data.
178 * @tc.expected: step3. Ok
179 */
180 std::string sql = std::string("DELETE FROM ").append(KNOWLEDGE_TABLE).append(" WHERE 1=1");
181 EXPECT_EQ(SQLiteUtils::ExecuteRawSQL(db, sql), E_OK);
182 EXPECT_EQ(CleanDeletedData(db, schema.tableName, 10u), OK); // delete which cursor less than 10
183
184 EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK);
185 }
186
187 /**
188 * @tc.name: SetKnowledge002
189 * @tc.desc: Test set knowledge schema with invalid args.
190 * @tc.type: FUNC
191 * @tc.require:
192 * @tc.author: zqq
193 */
194 HWTEST_F(DistributedDBRDBKnowledgeClientTest, SetKnowledge002, TestSize.Level0)
195 {
196 /**
197 * @tc.steps: step1. Set knowledge source schema and clean deleted data with null db.
198 * @tc.expected: step1. INVALID_ARGS
199 */
200 KnowledgeSourceSchema schema;
201 schema.tableName = KNOWLEDGE_TABLE;
202 schema.extendColNames.insert("id");
203 schema.knowledgeColNames.insert("int_field1");
204 schema.knowledgeColNames.insert("int_field2");
205 EXPECT_EQ(SetKnowledgeSourceSchema(nullptr, schema), INVALID_ARGS);
206 EXPECT_EQ(CleanDeletedData(nullptr, schema.tableName, 0u), INVALID_ARGS);
207 /**
208 * @tc.steps: step2. Set knowledge source schema and clean deleted data with null db.
209 * @tc.expected: step2. INVALID_ARGS
210 */
211 sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX);
212 ASSERT_NE(db, nullptr);
213 schema.tableName = "UNKNOWN_TABLE";
214 EXPECT_EQ(SetKnowledgeSourceSchema(db, schema), INVALID_ARGS);
215 EXPECT_EQ(CleanDeletedData(db, schema.tableName, 0u), OK);
216
217 EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK);
218 }
219
220 /**
221 * @tc.name: SetKnowledge003
222 * @tc.desc: Test set knowledge schema after create distributed table.
223 * @tc.type: FUNC
224 * @tc.require:
225 * @tc.author: zqq
226 */
227 HWTEST_F(DistributedDBRDBKnowledgeClientTest, SetKnowledge003, TestSize.Level0)
228 {
229 /**
230 * @tc.steps: step1. Create distributed table.
231 * @tc.expected: step1. Ok
232 */
233 UtTableSchemaInfo tableInfo1 = GetTableSchema(KNOWLEDGE_TABLE);
234 sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX);
235 EXPECT_NE(db, nullptr);
236 RDBDataGenerator::InitTableWithSchemaInfo(tableInfo1, *db);
237 UtTableSchemaInfo tableInfo2 = GetTableSchema(SYNC_TABLE);
238 RDBDataGenerator::InitTableWithSchemaInfo(tableInfo2, *db);
239 CreateDistributedTable({SYNC_TABLE}, DistributedDB::CLOUD_COOPERATION);
240
241 /**
242 * @tc.steps: step2. Set knowledge source schema.
243 * @tc.expected: step2. INVALID_ARGS
244 */
245 KnowledgeSourceSchema schema;
246 schema.tableName = KNOWLEDGE_TABLE;
247 schema.extendColNames.insert("id");
248 schema.knowledgeColNames.insert("int_field1");
249 schema.knowledgeColNames.insert("int_field2");
250 schema.tableName = SYNC_TABLE;
251 EXPECT_EQ(SetKnowledgeSourceSchema(db, schema), INVALID_ARGS);
252
253 EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK);
254 }
255 }
256