• 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 #include <gtest/gtest.h>
16 #include <variant>
17 
18 #include "cloud_db_sync_utils_test.h"
19 #include "distributeddb_data_generate_unit_test.h"
20 #include "distributeddb_tools_unit_test.h"
21 #include "rdb_data_generator.h"
22 #include "relational_store_client.h"
23 #include "relational_store_manager.h"
24 #include "relational_virtual_device.h"
25 #include "virtual_communicator_aggregator.h"
26 
27 using namespace testing::ext;
28 using namespace DistributedDB;
29 using namespace DistributedDBUnitTest;
30 using namespace std;
31 
32 namespace {
33 string g_testDir;
34 
35 class DistributedDBRDBCollaborationTest : public testing::Test {
36 public:
37     static void SetUpTestCase();
38     static void TearDownTestCase();
39     void SetUp() override;
40     void TearDown() override;
41 protected:
42     static DataBaseSchema GetSchema();
43     static TableSchema GetTableSchema(bool upgrade = false, bool pkInStr = false);
44     void InitStore();
45     void InitDelegate(DistributedTableMode mode = DistributedTableMode::COLLABORATION);
46     void CloseDb();
47     std::string storePath_;
48     sqlite3 *db_ = nullptr;
49     RelationalStoreDelegate *delegate_ = nullptr;
50     VirtualCommunicatorAggregator *communicatorAggregator_ = nullptr;
51     RelationalVirtualDevice *deviceB_ = nullptr;
52     RelationalStoreObserverUnitTest *delegateObserver_ = nullptr;
53 
54     static constexpr const char *DEVICE_SYNC_TABLE = "DEVICE_SYNC_TABLE";
55     static constexpr const char *DEVICE_SYNC_TABLE_UPGRADE = "DEVICE_SYNC_TABLE_UPGRADE";
56     static constexpr const char *DEVICE_SYNC_TABLE_AUTOINCREMENT = "DEVICE_SYNC_TABLE_AUTOINCREMENT";
57     static constexpr const char *CLOUD_SYNC_TABLE = "CLOUD_SYNC_TABLE";
58     static constexpr const char *BIG_COLUMNS_TABLE = "BIG_COLUMNS_TABLE";
59     static constexpr const char *INVALID_TABLE = "INVALID_TABLE";
60 };
61 
SetUpTestCase()62 void DistributedDBRDBCollaborationTest::SetUpTestCase()
63 {
64     DistributedDBToolsUnitTest::TestDirInit(g_testDir);
65     if (DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir) != 0) {
66         LOGE("rm test db files error!");
67     }
68 }
69 
TearDownTestCase()70 void DistributedDBRDBCollaborationTest::TearDownTestCase()
71 {
72     if (DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir) != 0) {
73         LOGE("rm test db files error!");
74     }
75 }
76 
SetUp()77 void DistributedDBRDBCollaborationTest::SetUp()
78 {
79     DistributedDBToolsUnitTest::PrintTestCaseInfo();
80     InitStore();
81     communicatorAggregator_ = new (std::nothrow) VirtualCommunicatorAggregator();
82     ASSERT_TRUE(communicatorAggregator_ != nullptr);
83     RuntimeContext::GetInstance()->SetCommunicatorAggregator(communicatorAggregator_);
84 
85     deviceB_ = new (std::nothrow) RelationalVirtualDevice(UnitTestCommonConstant::DEVICE_B);
86     ASSERT_NE(deviceB_, nullptr);
87     auto syncInterfaceB = new (std::nothrow) VirtualRelationalVerSyncDBInterface();
88     ASSERT_NE(syncInterfaceB, nullptr);
89     ASSERT_EQ(deviceB_->Initialize(communicatorAggregator_, syncInterfaceB), E_OK);
90 }
91 
TearDown()92 void DistributedDBRDBCollaborationTest::TearDown()
93 {
94     CloseDb();
95     if (deviceB_ != nullptr) {
96         delete deviceB_;
97         deviceB_ = nullptr;
98     }
99     if (delegateObserver_ != nullptr) {
100         delete delegateObserver_;
101         delegateObserver_ = nullptr;
102     }
103     if (DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir) != 0) {
104         LOGE("rm test db files error.");
105     }
106     RuntimeContext::GetInstance()->SetCommunicatorAggregator(nullptr);
107     communicatorAggregator_ = nullptr;
108 }
109 
GetSchema()110 DataBaseSchema DistributedDBRDBCollaborationTest::GetSchema()
111 {
112     DataBaseSchema schema;
113     auto table = GetTableSchema();
114     schema.tables.push_back(table);
115     table.name = CLOUD_SYNC_TABLE;
116     schema.tables.push_back(table);
117     schema.tables.push_back(GetTableSchema(true));
118     return schema;
119 }
120 
GetTableSchema(bool upgrade,bool pkInStr)121 TableSchema DistributedDBRDBCollaborationTest::GetTableSchema(bool upgrade, bool pkInStr)
122 {
123     TableSchema tableSchema;
124     tableSchema.name = upgrade ? DEVICE_SYNC_TABLE_UPGRADE : DEVICE_SYNC_TABLE;
125     Field field;
126     if (!pkInStr) {
127         field.primary = true;
128     }
129     field.type = TYPE_INDEX<int64_t>;
130     field.colName = "pk";
131     tableSchema.fields.push_back(field);
132     field.primary = false;
133     field.colName = "int_field1";
134     tableSchema.fields.push_back(field);
135     field.colName = "int_field2";
136     tableSchema.fields.push_back(field);
137     field.colName = "123";
138     field.type = TYPE_INDEX<std::string>;
139     if (pkInStr) {
140         field.primary = true;
141     }
142     tableSchema.fields.push_back(field);
143     if (upgrade) {
144         field.primary = false;
145         field.colName = "int_field_upgrade";
146         field.type = TYPE_INDEX<int64_t>;
147         tableSchema.fields.push_back(field);
148     }
149     return tableSchema;
150 }
151 
InitStore()152 void DistributedDBRDBCollaborationTest::InitStore()
153 {
154     if (storePath_.empty()) {
155         storePath_ = g_testDir + "/" + STORE_ID_1 + ".db";
156     }
157     db_ = RelationalTestUtils::CreateDataBase(storePath_);
158     ASSERT_NE(db_, nullptr);
159     auto schema = GetSchema();
160     EXPECT_EQ(RDBDataGenerator::InitDatabase(schema, *db_), SQLITE_OK);
161 }
162 
InitDelegate(DistributedTableMode mode)163 void DistributedDBRDBCollaborationTest::InitDelegate(DistributedTableMode mode)
164 {
165     if (delegateObserver_ == nullptr) {
166         delegateObserver_ = new (std::nothrow) RelationalStoreObserverUnitTest();
167         ASSERT_NE(delegateObserver_, nullptr);
168         delegateObserver_->SetCallbackDetailsType(static_cast<uint32_t>(CallbackDetailsType::DETAILED));
169     }
170     RelationalStoreManager mgr(APP_ID, USER_ID);
171     RelationalStoreDelegate::Option option;
172     option.tableMode = mode;
173     option.observer = delegateObserver_;
174     ASSERT_EQ(mgr.OpenStore(storePath_, STORE_ID_1, option, delegate_), OK);
175     ASSERT_NE(delegate_, nullptr);
176 }
177 
CloseDb()178 void DistributedDBRDBCollaborationTest::CloseDb()
179 {
180     if (db_ != nullptr) {
181         sqlite3_close_v2(db_);
182         db_ = nullptr;
183     }
184     if (delegate_ != nullptr) {
185         RelationalStoreManager mgr(APP_ID, USER_ID);
186         EXPECT_EQ(mgr.CloseStore(delegate_), OK);
187         delegate_ = nullptr;
188     }
189 }
190 
191 /**
192  * @tc.name: SetSchema001
193  * @tc.desc: Test set distributed schema.
194  * @tc.type: FUNC
195  * @tc.require:
196  * @tc.author: zqq
197  */
198 HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema001, TestSize.Level1)
199 {
200     /**
201      * @tc.steps: step1. Create device table and cloud table in COLLABORATION
202      * @tc.expected: step1.ok
203      */
204     ASSERT_NO_FATAL_FAILURE(InitDelegate());
205     auto schema = GetSchema();
206     EXPECT_EQ(delegate_->CreateDistributedTable(DEVICE_SYNC_TABLE, TableSyncType::DEVICE_COOPERATION), OK);
207     LOGI("[DistributedDBCloudAsyncDownloadAssetsTest] CreateDistributedTable %s", DEVICE_SYNC_TABLE);
208     EXPECT_EQ(delegate_->CreateDistributedTable(CLOUD_SYNC_TABLE, TableSyncType::CLOUD_COOPERATION), OK);
209     LOGI("[DistributedDBCloudAsyncDownloadAssetsTest] CreateDistributedTable %s", CLOUD_SYNC_TABLE);
210     auto distributedSchema = RDBDataGenerator::ParseSchema(schema);
211     for (auto &table : distributedSchema.tables) {
212         for (auto &field : table.fields) {
213             field.isSpecified = false;
214         }
215     }
216     EXPECT_EQ(delegate_->SetDistributedSchema(distributedSchema), OK);
217     /**
218      * @tc.steps: step2. Insert update delete local
219      * @tc.expected: step2.ok
220      */
221     EXPECT_EQ(RDBDataGenerator::InsertLocalDBData(0, 1, db_, GetTableSchema()), E_OK);
__anond430f6f20202(ClientChangedData &changedData) 222     EXPECT_EQ(RegisterClientObserver(db_, [](ClientChangedData &changedData) {
223         for (const auto &table : changedData.tableData) {
224             EXPECT_FALSE(table.second.isTrackedDataChange);
225             EXPECT_TRUE(table.second.isP2pSyncDataChange);
226             EXPECT_FALSE(table.second.isCloudSyncDataChange);
227         }
228     }), OK);
229     EXPECT_EQ(RDBDataGenerator::UpdateLocalDBData(0, 1, db_, GetTableSchema()), E_OK);
230     UnRegisterClientObserver(db_);
231 }
232 
233 /**
234  * @tc.name: SetSchema002
235  * @tc.desc: Test upgrade table mode.
236  * @tc.type: FUNC
237  * @tc.require:
238  * @tc.author: zqq
239  */
240 HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema002, TestSize.Level1)
241 {
242     /**
243      * @tc.steps: step1. Create cloud table in SPLIT_BY_DEVICE
244      * @tc.expected: step1.ok
245      */
246     ASSERT_NO_FATAL_FAILURE(InitDelegate(DistributedTableMode::SPLIT_BY_DEVICE));
247     EXPECT_EQ(delegate_->CreateDistributedTable(CLOUD_SYNC_TABLE, TableSyncType::CLOUD_COOPERATION), OK);
248     LOGI("[DistributedDBCloudAsyncDownloadAssetsTest] CreateDistributedTable %s", CLOUD_SYNC_TABLE);
249     CloseDb();
250     /**
251      * @tc.steps: step2. Create device table in COLLABORATION
252      * @tc.expected: step2.ok
253      */
254     ASSERT_NO_FATAL_FAILURE(InitDelegate());
255     auto schema = GetSchema();
256     EXPECT_EQ(delegate_->CreateDistributedTable(DEVICE_SYNC_TABLE, TableSyncType::DEVICE_COOPERATION), OK);
257     EXPECT_EQ(delegate_->SetDistributedSchema(RDBDataGenerator::ParseSchema(schema)), OK);
258     LOGI("[DistributedDBCloudAsyncDownloadAssetsTest] CreateDistributedTable %s", DEVICE_SYNC_TABLE);
259     CloseDb();
260 }
261 
262 /**
263  * @tc.name: SetSchema003
264  * @tc.desc: Test set distributed schema.
265  * @tc.type: FUNC
266  * @tc.require:
267  * @tc.author: zqq
268  */
269 HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema003, TestSize.Level1)
270 {
271     /**
272      * @tc.steps: step1. Create device table and cloud table in COLLABORATION
273      * @tc.expected: step1.ok
274      */
275     ASSERT_NO_FATAL_FAILURE(InitDelegate());
276     auto schema = GetSchema();
277     EXPECT_EQ(delegate_->CreateDistributedTable(DEVICE_SYNC_TABLE, TableSyncType::DEVICE_COOPERATION), OK);
278     LOGI("[DistributedDBCloudAsyncDownloadAssetsTest] CreateDistributedTable %s", DEVICE_SYNC_TABLE);
279     EXPECT_EQ(delegate_->SetDistributedSchema(RDBDataGenerator::ParseSchema(schema, true)), OK);
280     /**
281      * @tc.steps: step2. Insert update delete local
282      * @tc.expected: step2.ok
283      */
284     EXPECT_EQ(RDBDataGenerator::InsertLocalDBData(0, 1, db_, GetTableSchema()), E_OK);
__anond430f6f20302(ClientChangedData &changedData) 285     EXPECT_EQ(RegisterClientObserver(db_, [](ClientChangedData &changedData) {
286         for (const auto &table : changedData.tableData) {
287             EXPECT_FALSE(table.second.isTrackedDataChange);
288             EXPECT_FALSE(table.second.isP2pSyncDataChange);
289             EXPECT_FALSE(table.second.isCloudSyncDataChange);
290         }
291     }), OK);
292     EXPECT_EQ(RDBDataGenerator::UpdateLocalDBData(0, 1, db_, GetTableSchema()), E_OK);
293     UnRegisterClientObserver(db_);
294 }
295 
296 /**
297  * @tc.name: SetSchema004
298  * @tc.desc: Test create distributed table without schema.
299  * @tc.type: FUNC
300  * @tc.require:
301  * @tc.author: zqq
302  */
303 HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema004, TestSize.Level0)
304 {
305     /**
306      * @tc.steps: step1. Create device table and cloud table in COLLABORATION
307      * @tc.expected: step1.ok
308      */
309     ASSERT_NO_FATAL_FAILURE(InitDelegate());
310     EXPECT_EQ(delegate_->CreateDistributedTable(DEVICE_SYNC_TABLE, TableSyncType::DEVICE_COOPERATION), OK);
311 }
312 
GetDistributedSchema(const std::string & tableName,const std::vector<std::string> & fields)313 DistributedSchema GetDistributedSchema(const std::string &tableName, const std::vector<std::string> &fields)
314 {
315     DistributedTable table;
316     table.tableName = tableName;
317     for (const auto &fieldName : fields) {
318         DistributedField field;
319         field.isP2pSync = true;
320         field.colName = fieldName;
321         table.fields.push_back(field);
322     }
323     DistributedSchema schema;
324     schema.tables.push_back(table);
325     return schema;
326 }
327 
328 /**
329  * @tc.name: SetSchema005
330  * @tc.desc: Test set distributed schema with invalid schema
331  * @tc.type: FUNC
332  * @tc.require:
333  * @tc.author: liaoyonghuang
334  */
335 HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema005, TestSize.Level0)
336 {
337     /**
338      * @tc.steps: step1. Prepare db
339      * @tc.expected: step1.ok
340      */
341     ASSERT_NO_FATAL_FAILURE(InitDelegate(DistributedTableMode::COLLABORATION));
342     EXPECT_EQ(delegate_->CreateDistributedTable(DEVICE_SYNC_TABLE, TableSyncType::DEVICE_COOPERATION), OK);
343     /**
344      * @tc.steps: step2. Test set distributed schema with invalid table name
345      * @tc.expected: step2. return SCHEMA_MISMATCH
346      */
347     DistributedSchema schema1 = GetDistributedSchema("", {});
348     EXPECT_EQ(delegate_->SetDistributedSchema(schema1), SCHEMA_MISMATCH);
349     DistributedSchema schema2 = GetDistributedSchema("xxx", {});
350     EXPECT_EQ(delegate_->SetDistributedSchema(schema2), SCHEMA_MISMATCH);
351     /**
352      * @tc.steps: step3. Test set distributed schema with invalid fields
353      * @tc.expected: step3. return SCHEMA_MISMATCH OR DISTRIBUTED_FIELD_DECREASE
354      */
355     DistributedSchema schema3 = GetDistributedSchema(DEVICE_SYNC_TABLE, {});
356     EXPECT_EQ(delegate_->SetDistributedSchema(schema3), SCHEMA_MISMATCH);
357     DistributedSchema schema4 = GetDistributedSchema(DEVICE_SYNC_TABLE, {"xxx"});
358     EXPECT_EQ(delegate_->SetDistributedSchema(schema4), SCHEMA_MISMATCH);
359     DistributedSchema schema5 = GetDistributedSchema(DEVICE_SYNC_TABLE, {"pk", "int_field1"});
360     EXPECT_EQ(delegate_->SetDistributedSchema(schema5), OK);
361     DistributedSchema schema6 = GetDistributedSchema(DEVICE_SYNC_TABLE, {"pk"});
362     EXPECT_EQ(delegate_->SetDistributedSchema(schema6), DISTRIBUTED_FIELD_DECREASE);
363 
364     /**
365      * @tc.steps: step4. Test set distributed schema with int_field1 but isP2pSync is false
366      * @tc.expected: step4. return DISTRIBUTED_FIELD_DECREASE
367      */
368     DistributedSchema distributedSchema1 = {0, {{DEVICE_SYNC_TABLE, {{"int_field1", false}}}}};
369     EXPECT_EQ(delegate_->SetDistributedSchema(distributedSchema1), DISTRIBUTED_FIELD_DECREASE);
370 }
371 
372 /**
373  * @tc.name: SetSchema006
374  * @tc.desc: Test register client observer
375  * @tc.type: FUNC
376  * @tc.require:
377  * @tc.author: liaoyonghuang
378  */
379 HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema006, TestSize.Level1)
380 {
381     /**
382      * @tc.steps: step1. Create device table and cloud table in COLLABORATION
383      * @tc.expected: step1.ok
384      */
385     ASSERT_NO_FATAL_FAILURE(InitDelegate());
386     DistributedSchema distributedSchema = GetDistributedSchema(DEVICE_SYNC_TABLE, {"pk", "int_field1"});
387     EXPECT_EQ(delegate_->CreateDistributedTable(DEVICE_SYNC_TABLE, TableSyncType::DEVICE_COOPERATION), OK);
388     EXPECT_EQ(delegate_->SetDistributedSchema(distributedSchema), OK);
389     EXPECT_EQ(delegate_->CreateDistributedTable(DEVICE_SYNC_TABLE, TableSyncType::DEVICE_COOPERATION), OK);
390     TrackerSchema trackerSchema = {
391         .tableName = DEVICE_SYNC_TABLE, .extendColNames = {"int_field1"}, .trackerColNames = {"int_field1"}
392     };
393     EXPECT_EQ(delegate_->SetTrackerTable(trackerSchema), OK);
394     /**
395      * @tc.steps: step2. Insert update local
396      * @tc.expected: step2.ok
397      */
__anond430f6f20402(ClientChangedData &changedData) 398     EXPECT_EQ(RegisterClientObserver(db_, [](ClientChangedData &changedData) {
399         for (const auto &table : changedData.tableData) {
400             EXPECT_TRUE(table.second.isTrackedDataChange);
401             EXPECT_TRUE(table.second.isP2pSyncDataChange);
402             EXPECT_FALSE(table.second.isCloudSyncDataChange);
403         }
404     }), OK);
405     EXPECT_EQ(RDBDataGenerator::InsertLocalDBData(0, 1, db_, GetTableSchema()), E_OK);
406     std::string sql = "update " + std::string(DEVICE_SYNC_TABLE) + " set int_field1 = int_field1 + 1 where pk = 0";
407     EXPECT_EQ(SQLiteUtils::ExecuteRawSQL(db_, sql), E_OK);
408 
409     /**
410      * @tc.steps: step3. Insert data that pk = 0 and sync to real device
411      * @tc.expected: step3.ok
412      */
413     auto schema = GetSchema();
414     deviceB_->SetDistributedSchema(distributedSchema);
415     auto tableSchema = GetTableSchema();
416     ASSERT_EQ(RDBDataGenerator::InsertVirtualLocalDBData(0, 1, deviceB_, tableSchema), E_OK);
417     ASSERT_EQ(RDBDataGenerator::PrepareVirtualDeviceEnv(tableSchema.name, db_, deviceB_), E_OK);
418     Query query = Query::Select(tableSchema.name);
419     DistributedDBToolsUnitTest::BlockSync(*delegate_, query, SYNC_MODE_PULL_ONLY, OK, {deviceB_->GetDeviceId()});
420 
421     /**
422      * @tc.steps: step4. Check extend_field
423      * @tc.expected: step4.ok
424      */
425     sql = "select count(*) from " + std::string(DBConstant::RELATIONAL_PREFIX) + std::string(DEVICE_SYNC_TABLE) + "_log"
426         " where json_extract(extend_field, '$.int_field1')=0";
427     EXPECT_EQ(sqlite3_exec(db_, sql.c_str(), CloudDBSyncUtilsTest::QueryCountCallback,
428         reinterpret_cast<void *>(1u), nullptr), SQLITE_OK);
429     UnRegisterClientObserver(db_);
430 }
431 
GetTriggerSql(const std::string & tableName,const std::string & triggerTypeName,sqlite3 * db)432 std::string GetTriggerSql(const std::string &tableName, const std::string &triggerTypeName, sqlite3 *db) {
433     if (db == nullptr) {
434         return "";
435     }
436     std::string sql = "select sql from sqlite_master where type = 'trigger' and tbl_name = '" + tableName +
437         "' and name = 'naturalbase_rdb_" + tableName + "_ON_" + triggerTypeName + "';";
438     sqlite3_stmt *stmt = nullptr;
439     int errCode = SQLiteUtils::GetStatement(db, sql, stmt);
440     if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_OK)) {
441         LOGE("[GetTriggerSql] prepare statement failed(%d), sys(%d), errmsg(%s)", errCode, errno, sqlite3_errmsg(db));
442         return "";
443     }
444     errCode = SQLiteUtils::StepWithRetry(stmt);
445     if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) {
446         LOGE("[GetTriggerSql] execute statement failed(%d), sys(%d), errmsg(%s)", errCode, errno, sqlite3_errmsg(db));
447         return "";
448     }
449     const std::string triggerSql = std::string(reinterpret_cast<const char *>(sqlite3_column_text(stmt, 0)));
450     int ret = E_OK;
451     SQLiteUtils::ResetStatement(stmt, true, ret);
452     return triggerSql;
453 }
454 
455 /**
456  * @tc.name: SetSchema007
457  * @tc.desc: Test whether setting the schema multiple times will refresh the trigger
458  * @tc.type: FUNC
459  * @tc.require:
460  * @tc.author: liaoyonghuang
461  */
462 HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema007, TestSize.Level1)
463 {
464     /**
465      * @tc.steps: step1. Prepare db
466      * @tc.expected: step1.ok
467      */
468     ASSERT_NO_FATAL_FAILURE(InitDelegate(DistributedTableMode::COLLABORATION));
469     EXPECT_EQ(delegate_->CreateDistributedTable(DEVICE_SYNC_TABLE, TableSyncType::DEVICE_COOPERATION), OK);
470     DistributedSchema schema1 = GetDistributedSchema(DEVICE_SYNC_TABLE, {"pk"});
471     EXPECT_EQ(delegate_->SetDistributedSchema(schema1), OK);
472     /**
473      * @tc.steps:step2. delete triggers
474      * @tc.expected: step2. Return OK.
475      */
476     std::string oldInsertTriggerSql = GetTriggerSql(DEVICE_SYNC_TABLE, "INSERT", db_);
477     std::string oldUpdateTriggerSql = GetTriggerSql(DEVICE_SYNC_TABLE, "UPDATE", db_);
478     std::string oldDeleteTriggerSql = GetTriggerSql(DEVICE_SYNC_TABLE, "DELETE", db_);
479     EXPECT_FALSE(oldInsertTriggerSql.empty() || oldUpdateTriggerSql.empty() || oldDeleteTriggerSql.empty());
480     std::vector<std::string> triggerTypes = {"INSERT", "UPDATE", "DELETE"};
481     for (const auto &triggerType : triggerTypes) {
482         std::string sql = "DROP TRIGGER IF EXISTS naturalbase_rdb_" + std::string(DEVICE_SYNC_TABLE) + "_ON_" +
483             triggerType;
484         SQLiteUtils::ExecuteRawSQL(db_, sql);
485     }
486     /**
487      * @tc.steps:step3. Set distributed schema and check if the trigger exists
488      * @tc.expected: step3. Check OK.
489      */
490     DistributedSchema schema2 = GetDistributedSchema(DEVICE_SYNC_TABLE, {"pk", "int_field1"});
491     EXPECT_EQ(delegate_->SetDistributedSchema(schema2), OK);
492     for (const auto &triggerType : triggerTypes) {
493         std::string sql = "select count(*) from sqlite_master where type = 'trigger' and tbl_name = '" +
494             std::string(DEVICE_SYNC_TABLE) + "' and name = 'naturalbase_rdb_" + std::string(DEVICE_SYNC_TABLE) +
495             "_ON_" + triggerType + "';";
496         int count = 0;
497         EXPECT_EQ(SQLiteUtils::GetCountBySql(db_, sql, count), E_OK);
498         EXPECT_EQ(count, 1);
499     }
500     std::string newInsertTriggerSql = GetTriggerSql(DEVICE_SYNC_TABLE, "INSERT", db_);
501     std::string newUpdateTriggerSql = GetTriggerSql(DEVICE_SYNC_TABLE, "UPDATE", db_);
502     std::string newDeleteTriggerSql = GetTriggerSql(DEVICE_SYNC_TABLE, "DELETE", db_);
503     EXPECT_FALSE(newInsertTriggerSql.empty() || newUpdateTriggerSql.empty() || newDeleteTriggerSql.empty());
504     EXPECT_TRUE(oldInsertTriggerSql == newInsertTriggerSql);
505     EXPECT_TRUE(oldUpdateTriggerSql != newUpdateTriggerSql);
506     EXPECT_TRUE(oldDeleteTriggerSql == newDeleteTriggerSql);
507 }
508 
509 /**
510  * @tc.name: SetSchema008
511  * @tc.desc: Test set distributed schema with pk but pk isP2pSync is false
512  * @tc.type: FUNC
513  * @tc.require:
514  * @tc.author: tankaisheng
515  */
516 HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema008, TestSize.Level1)
517 {
518     /**
519      * @tc.steps: step1. Prepare db
520      * @tc.expected: step1.ok
521      */
522     ASSERT_NO_FATAL_FAILURE(InitDelegate(DistributedTableMode::COLLABORATION));
523     EXPECT_EQ(delegate_->CreateDistributedTable(DEVICE_SYNC_TABLE, TableSyncType::DEVICE_COOPERATION), OK);
524     /**
525      * @tc.steps: step2. Test set distributed schema without pk
526      * @tc.expected: step2. return OK
527      */
528     DistributedSchema distributedSchema = {0, {{DEVICE_SYNC_TABLE, {{"int_field1", true}}}}};
529     EXPECT_EQ(delegate_->SetDistributedSchema(distributedSchema), OK);
530     /**
531      * @tc.steps: step3. Test set distributed schema with pk but pk isP2pSync is false
532      * @tc.expected: step3. return SCHEMA_MISMATCH
533      */
534     DistributedSchema distributedSchema1 = {0, {{DEVICE_SYNC_TABLE, {{"pk", false}}}}};
535     EXPECT_EQ(delegate_->SetDistributedSchema(distributedSchema1), SCHEMA_MISMATCH);
536     /**
537      * @tc.steps: step4. Test set same distributed schema
538      * @tc.expected: step4. return OK
539      */
540     EXPECT_EQ(delegate_->SetDistributedSchema(distributedSchema), OK);
541 }
542 
543 /**
544  * @tc.name: SetSchema009
545  * @tc.desc: Test tableMode is SPLIT_BY_DEVICE then SetDistributedSchema.
546  * @tc.type: FUNC
547  * @tc.require:
548  * @tc.author: tankaisheng
549  */
550 HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema009, TestSize.Level0)
551 {
552     /**
553      * @tc.steps: step1. Prepare db, tableMode is SPLIT_BY_DEVICE
554      * @tc.expected: step1.ok
555      */
556     ASSERT_NO_FATAL_FAILURE(InitDelegate(DistributedTableMode::SPLIT_BY_DEVICE));
557     EXPECT_EQ(delegate_->CreateDistributedTable(DEVICE_SYNC_TABLE, TableSyncType::DEVICE_COOPERATION), OK);
558     /**
559      * @tc.steps: step2. Test set distributed schema without pk
560      * @tc.expected: step2. return NOT_SUPPORT
561      */
562     DistributedSchema distributedSchema = {0, {{DEVICE_SYNC_TABLE, {{"int_field1", true}}}}};
563     EXPECT_EQ(delegate_->SetDistributedSchema(distributedSchema), NOT_SUPPORT);
564 }
565 
566 /**
567  * @tc.name: SetSchema010
568  * @tc.desc: Test create distributed table without communicator.
569  * @tc.type: FUNC
570  * @tc.require:
571  * @tc.author: zqq
572  */
573 HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema010, TestSize.Level0)
574 {
575     if (deviceB_ != nullptr) {
576         delete deviceB_;
577         deviceB_ = nullptr;
578     }
579     RuntimeContext::GetInstance()->SetCommunicatorAggregator(nullptr);
580     ASSERT_NO_FATAL_FAILURE(InitDelegate());
581     EXPECT_EQ(delegate_->CreateDistributedTable(DEVICE_SYNC_TABLE, TableSyncType::DEVICE_COOPERATION), OK);
582 }
583 
584 /**
585  * @tc.name: SetSchema011
586  * @tc.desc: Test set schema with not null field but isP2pSync is false
587  * @tc.type: FUNC
588  * @tc.require:
589  * @tc.author: liaoyonghuang
590  */
591 HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema011, TestSize.Level0)
592 {
593     /**
594      * @tc.steps: step1. Prepare db
595      * @tc.expected: step1.ok
596      */
597     ASSERT_NO_FATAL_FAILURE(InitDelegate(DistributedTableMode::COLLABORATION));
598     EXPECT_EQ(delegate_->CreateDistributedTable(DEVICE_SYNC_TABLE, TableSyncType::DEVICE_COOPERATION), OK);
599     /**
600      * @tc.steps: step2. Test set distributed schema
601      * @tc.expected: step2. return SCHEMA_MISMATCH
602      */
603     DistributedSchema schema1 = GetDistributedSchema(DEVICE_SYNC_TABLE, {"pk"});
604     DistributedField &field1 = schema1.tables.front().fields.front();
605     field1.isP2pSync = false;
606     EXPECT_EQ(delegate_->SetDistributedSchema(schema1), SCHEMA_MISMATCH);
607 }
608 
609 /**
610  * @tc.name: SetSchema012
611  * @tc.desc: Test call SetDistributedSchema with empty tables
612  * @tc.type: FUNC
613  * @tc.require:
614  * @tc.author: liuhongyang
615  */
616 HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema012, TestSize.Level0)
617 {
618     /**
619      * @tc.steps: step1. Prepare db, tableMode is SPLIT_BY_DEVICE
620      * @tc.expected: step1.ok
621      */
622     ASSERT_NO_FATAL_FAILURE(InitDelegate(DistributedTableMode::SPLIT_BY_DEVICE));
623     EXPECT_EQ(delegate_->CreateDistributedTable(DEVICE_SYNC_TABLE, TableSyncType::DEVICE_COOPERATION), OK);
624     /**
625      * @tc.steps: step2. Test set schema with empty tables vector
626      * @tc.expected: step2. return SCHEMA_MISMATCH
627      */
628     DistributedSchema distributedSchema = {0, {}};
629     EXPECT_EQ(delegate_->SetDistributedSchema(distributedSchema), SCHEMA_MISMATCH);
630     /**
631      * @tc.steps: step3. Test set schema with a list of empty tables
632      * @tc.expected: step3. return SCHEMA_MISMATCH
633      */
634     distributedSchema = {0, {{}, {}, {}}};
635     EXPECT_EQ(delegate_->SetDistributedSchema(distributedSchema), SCHEMA_MISMATCH);
636     /**
637      * @tc.steps: step4. Test set schema with a mix of empty and non-empty tables
638      * @tc.expected: step4. return SCHEMA_MISMATCH
639      */
640     distributedSchema = {0, {{DEVICE_SYNC_TABLE, {{"int_field1", true}}}, {}}};
641     EXPECT_EQ(delegate_->SetDistributedSchema(distributedSchema), SCHEMA_MISMATCH);
642 }
643 
644 /**
645  * @tc.name: SetSchema013
646  * @tc.desc: Test set tracker table for device table and check if timestamp has changed
647  * @tc.type: FUNC
648  * @tc.require:
649  * @tc.author: bty
650  */
651 HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema013, TestSize.Level1)
652 {
653     /**
654      * @tc.steps: step1. Create device table
655      * @tc.expected: step1.ok
656      */
657     ASSERT_NO_FATAL_FAILURE(InitDelegate());
658     DistributedSchema distributedSchema = GetDistributedSchema(DEVICE_SYNC_TABLE, {"pk", "int_field1"});
659     EXPECT_EQ(delegate_->CreateDistributedTable(DEVICE_SYNC_TABLE, TableSyncType::DEVICE_COOPERATION), OK);
660     EXPECT_EQ(delegate_->SetDistributedSchema(distributedSchema), OK);
661     TrackerSchema trackerSchema = {
662         .tableName = DEVICE_SYNC_TABLE, .extendColNames = {"int_field1"}, .trackerColNames = {"int_field1"}
663     };
664     /**
665      * @tc.steps: step2. Insert one data and query timestamp
666      * @tc.expected: step2.ok
667      */
668     EXPECT_EQ(RDBDataGenerator::InsertLocalDBData(0, 1, db_, GetTableSchema()), E_OK);
669     sqlite3_stmt *stmt = nullptr;
670     std::string sql = "select timestamp from " + DBCommon::GetLogTableName(DEVICE_SYNC_TABLE) +
671         " where data_key=0";
672     EXPECT_EQ(SQLiteUtils::GetStatement(db_, sql, stmt), E_OK);
673     EXPECT_EQ(SQLiteUtils::StepWithRetry(stmt), SQLiteUtils::MapSQLiteErrno(SQLITE_ROW));
674     int64_t timestamp1 = static_cast<int64_t>(sqlite3_column_int64(stmt, 0));
675     int ret = E_OK;
676     SQLiteUtils::ResetStatement(stmt, true, ret);
677     /**
678      * @tc.steps: step3. Set tracker table and query timestamp
679      * @tc.expected: step3.Equal
680      */
681     EXPECT_EQ(delegate_->SetTrackerTable(trackerSchema), WITH_INVENTORY_DATA);
682     EXPECT_EQ(SQLiteUtils::GetStatement(db_, sql, stmt), E_OK);
683     EXPECT_EQ(SQLiteUtils::StepWithRetry(stmt), SQLiteUtils::MapSQLiteErrno(SQLITE_ROW));
684     int64_t timestamp2 = static_cast<int64_t>(sqlite3_column_int64(stmt, 0));
685     SQLiteUtils::ResetStatement(stmt, true, ret);
686     EXPECT_EQ(timestamp1, timestamp2);
687 }
688 
689 /**
690  * @tc.name: SetSchema014
691  * @tc.desc: Test set tracker table for device table and check if timestamp has changed
692  * @tc.type: FUNC
693  * @tc.require:
694  * @tc.author: zqq
695  */
696 HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema014, TestSize.Level1)
697 {
698     /**
699      * @tc.steps: step1. Create auto increment table and specified pk, distributed schema without not null field
700      * @tc.expected: step1. create distributed table ok but set schema failed
701      */
702     auto tableSchema = GetTableSchema();
703     tableSchema.name = DEVICE_SYNC_TABLE_AUTOINCREMENT;
704     ASSERT_EQ(RDBDataGenerator::InitTable(tableSchema, true, true, *db_), E_OK);
705     ASSERT_NO_FATAL_FAILURE(InitDelegate());
706     DistributedSchema distributedSchema;
707     DistributedTable distributedTable;
708     distributedTable.tableName = tableSchema.name;
709     DistributedField distributedField;
710     distributedField.colName = "pk";
711     distributedField.isSpecified = true;
712     distributedField.isP2pSync = true;
713     distributedTable.fields.push_back(distributedField);
714     distributedSchema.tables.push_back(distributedTable);
715     EXPECT_EQ(delegate_->CreateDistributedTable(tableSchema.name, TableSyncType::DEVICE_COOPERATION), OK);
716     EXPECT_EQ(delegate_->SetDistributedSchema(distributedSchema), SCHEMA_MISMATCH);
717     /**
718      * @tc.steps: step2. Distributed schema with not null field
719      * @tc.expected: step2. ok
720      */
721     distributedSchema.tables.clear();
722     distributedField.colName = "123";
723     distributedField.isSpecified = false;
724     distributedTable.fields.push_back(distributedField);
725     distributedSchema.tables.push_back(distributedTable);
726     EXPECT_EQ(delegate_->SetDistributedSchema(distributedSchema), OK);
727     /**
728      * @tc.steps: step3. Distributed schema with error specified
729      * @tc.expected: step3. SCHEMA_MISMATCH
730      */
731     distributedSchema.tables.clear();
732     distributedField.colName = "123";
733     distributedField.isSpecified = true;
734     distributedTable.fields.push_back(distributedField);
735     distributedField.colName = "pk";
736     distributedField.isP2pSync = false;
737     distributedTable.fields.push_back(distributedField);
738     distributedSchema.tables.push_back(distributedTable);
739     EXPECT_EQ(delegate_->SetDistributedSchema(distributedSchema), SCHEMA_MISMATCH);
740 }
741 
742 /**
743  * @tc.name: SetSchema015
744  * @tc.desc: Test call SetDistributedSchema with mark more than one unique col isSpecified true
745  * @tc.type: FUNC
746  * @tc.require:
747  * @tc.author: tankaisheng
748  */
749 HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema015, TestSize.Level1)
750 {
751     /**
752      * @tc.steps: step1. Prepare db, tableMode is COLLABORATION
753      * @tc.expected: step1.ok
754      */
755     ASSERT_NO_FATAL_FAILURE(InitDelegate(DistributedTableMode::COLLABORATION));
756     std::string createSql = "CREATE TABLE IF NOT EXISTS table_pk_int(integer_field INTEGER PRIMARY KEY AUTOINCREMENT,"
757                  "int_field INT, char_field CHARACTER(20) UNIQUE, clob_field CLOB UNIQUE, UNIQUE(char_field, clob_field));";
758     ASSERT_EQ(SQLiteUtils::ExecuteRawSQL(db_, createSql), E_OK);
759     EXPECT_EQ(delegate_->CreateDistributedTable("table_pk_int", TableSyncType::DEVICE_COOPERATION), OK);
760 
761     /**
762      * @tc.steps: step2. Test mark more than one unique col isSpecified true
763      * @tc.expected: step2. return SCHEMA_MISMATCH
764      */
765     DistributedSchema distributedSchema = {0, {{"table_pk_int", {
766                                                     {"integer_field", false, false},
767                                                     {"int_field", true, false},
768                                                     {"char_field", true, true},
769                                                     {"clob_field", true, true}}}}};
770     EXPECT_EQ(delegate_->SetDistributedSchema(distributedSchema), SCHEMA_MISMATCH);
771 }
772 
773 /**
774  * @tc.name: SetSchema016
775  * @tc.desc: Test set isSpecified to false after isSpecified was set to true
776  * @tc.type: FUNC
777  * @tc.require:
778  * @tc.author: liaoyonghuang
779  */
780 HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema016, TestSize.Level0)
781 {
782     /**
783      * @tc.steps: step1. Prepare db
784      * @tc.expected: step1.ok
785      */
786     ASSERT_NO_FATAL_FAILURE(InitDelegate(DistributedTableMode::COLLABORATION));
787     std::string tableName = "multiPriKeyTable";
788     std::string sql = "CREATE TABLE IF NOT EXISTS " + tableName +
789         "(pk1 INTEGER, pk2 INT, PRIMARY KEY (pk1, pk2));";
790     ASSERT_EQ(SQLiteUtils::ExecuteRawSQL(db_, sql), E_OK);
791     EXPECT_EQ(delegate_->CreateDistributedTable(tableName, TableSyncType::DEVICE_COOPERATION), OK);
792     /**
793      * @tc.steps: step2. Test set distributed schema
794      * @tc.expected: step2. return OK
795      */
796     DistributedSchema schema1 = GetDistributedSchema(tableName, {"pk1", "pk2"});
797     EXPECT_EQ(delegate_->SetDistributedSchema(schema1), OK);
798     /**
799      * @tc.steps: step3. Test set distributed schema
800      * @tc.expected: step3. return SCHEMA_MISMATCH
801      */
802     DistributedSchema schema2 = GetDistributedSchema(tableName, {"pk1", "pk2"});
803     DistributedField &field2 = schema2.tables.front().fields.front();
804     field2.isSpecified = true;
805     EXPECT_EQ(delegate_->SetDistributedSchema(schema2), SCHEMA_MISMATCH);
806 }
807 
GetHashKey(sqlite3 * db,const std::string & tableName,std::vector<std::string> & hashKeys)808 int GetHashKey(sqlite3 *db, const std::string &tableName, std::vector<std::string> &hashKeys) {
809     if (db == nullptr) {
810         return -E_INVALID_DB;
811     }
812 
813     std::string sql = "select cast(hash_key as text) from " + DBCommon::GetLogTableName(tableName) +
814         " order by timestamp;";
815     sqlite3_stmt *stmt = nullptr;
816     int errCode = SQLiteUtils::GetStatement(db, sql, stmt);
817     if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_OK)) {
818         LOGE("prepare statement failed(%d), sys(%d), msg(%s)", errCode, errno, sqlite3_errmsg(db));
819         return errCode;
820     }
821 
822     do {
823         errCode = SQLiteUtils::StepWithRetry(stmt);
824         if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) {
825             errCode = E_OK;
826         } else if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) {
827             LOGE("[SQLiteUtils][ExecuteSQL] execute statement failed(%d), sys(%d), msg(%s)",
828                 errCode, errno, sqlite3_errmsg(db));
829         } else {
830             const unsigned char *result = sqlite3_column_text(stmt, 0);
831             hashKeys.push_back(reinterpret_cast<const std::string::value_type *>(result));
832         }
833     } while (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW));
834 
835     int ret = E_OK;
836     SQLiteUtils::ResetStatement(stmt, true, ret);
837     return errCode;
838 }
839 
840 /**
841  * @tc.name: SetSchema017
842  * @tc.desc: Test whether to update hash_key after setting up distributed schema
843  * @tc.type: FUNC
844  * @tc.require:
845  * @tc.author: liaoyonghuang
846  */
847 HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema017, TestSize.Level1)
848 {
849     /**
850      * @tc.steps: step1. Prepare db
851      * @tc.expected: step1.ok
852      */
853     ASSERT_NO_FATAL_FAILURE(InitDelegate(DistributedTableMode::COLLABORATION));
854     std::string tableName = "multiPriKeyTable";
855     std::string sql = "CREATE TABLE IF NOT EXISTS " + tableName +
856         "(pk1 INTEGER PRIMARY KEY AUTOINCREMENT, pk2 INT UNIQUE);";
857     ASSERT_EQ(SQLiteUtils::ExecuteRawSQL(db_, sql), E_OK);
858     EXPECT_EQ(delegate_->CreateDistributedTable(tableName, TableSyncType::DEVICE_COOPERATION), OK);
859     /**
860      * @tc.steps: step2. Insert a record and get hash_key
861      * @tc.expected: step2.ok
862      */
863     int dataCount = 10;
864     for (int i = 0; i < dataCount; i++) {
865         sql = "insert into " + tableName + " values (" + std::to_string(i) + ", " + std::to_string(i + 1) + ");";
866         EXPECT_EQ(SQLiteUtils::ExecuteRawSQL(db_, sql), E_OK);
867     }
868     std::vector<std::string> oldHashKeys;
869     EXPECT_EQ(GetHashKey(db_, tableName, oldHashKeys), E_OK);
870     ASSERT_EQ(oldHashKeys.size(), static_cast<size_t>(dataCount));
871     /**
872      * @tc.steps: step3. Set distributed schema and get old hash_key
873      * @tc.expected: step3.ok
874      */
875     DistributedSchema schema1 = GetDistributedSchema(tableName, {"pk1", "pk2"});
876     EXPECT_EQ(delegate_->SetDistributedSchema(schema1), OK);
877     std::vector<std::string> newHashKeys1;
878     EXPECT_EQ(GetHashKey(db_, tableName, newHashKeys1), E_OK);
879     ASSERT_EQ(newHashKeys1.size(), static_cast<size_t>(dataCount));
880     for (int i = 0; i < dataCount; i++) {
881         EXPECT_EQ(oldHashKeys[i], newHashKeys1[i]);
882     }
883     /**
884      * @tc.steps: step4. Set another distributed schema and get old hash_key
885      * @tc.expected: step4.ok
886      */
887     DistributedSchema schema2 = {0, {{"multiPriKeyTable", {
888         {"pk1", false, false},
889         {"pk2", true, true}}}}};
890     EXPECT_EQ(delegate_->SetDistributedSchema(schema2, true), OK);
891     std::vector<std::string> newHashKeys2;
892     EXPECT_EQ(GetHashKey(db_, tableName, newHashKeys2), E_OK);
893     ASSERT_EQ(newHashKeys2.size(), static_cast<size_t>(dataCount));
894     for (int i = 0; i < dataCount; i++) {
895         EXPECT_NE(newHashKeys1[i], newHashKeys2[i]);
896     }
897     EXPECT_NE(newHashKeys2, oldHashKeys);
898 }
899 
900 /**
901  * @tc.name: SetSchema018
902  * @tc.desc: Test no primary key table setting isSpecified
903  * @tc.type: FUNC
904  * @tc.require:
905  * @tc.author: liaoyonghuang
906  */
907 HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema018, TestSize.Level0)
908 {
909     /**
910      * @tc.steps: step1. Prepare db
911      * @tc.expected: step1.ok
912      */
913     ASSERT_NO_FATAL_FAILURE(InitDelegate(DistributedTableMode::COLLABORATION));
914     std::string tableName = "noPriKeyTable";
915     std::string sql = "CREATE TABLE IF NOT EXISTS " + tableName +
916                       "(field_int1 INTEGER, field_int2 INT);";
917     ASSERT_EQ(SQLiteUtils::ExecuteRawSQL(db_, sql), E_OK);
918     EXPECT_EQ(delegate_->CreateDistributedTable(tableName, TableSyncType::DEVICE_COOPERATION), OK);
919     /**
920      * @tc.steps: step2. Test set distributed schema
921      * @tc.expected: step2. return SCHEMA_MISMATCH
922      */
923     DistributedSchema schema = GetDistributedSchema(tableName, {"field_int1"});
924     DistributedField &field = schema.tables.front().fields.front();
925     field.isSpecified = true;
926     EXPECT_EQ(delegate_->SetDistributedSchema(schema), SCHEMA_MISMATCH);
927 }
928 
929 /**
930  * @tc.name: SetSchema019
931  * @tc.desc: Test call SetDistributedSchema when unique col not set isP2pSync
932  * @tc.type: FUNC
933  * @tc.require:
934  * @tc.author: tankaisheng
935  */
936 HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema019, TestSize.Level0)
937 {
938     /**
939      * @tc.steps: step1. Prepare db, tableMode is COLLABORATION
940      * @tc.expected: step1.ok
941      */
942     ASSERT_NO_FATAL_FAILURE(InitDelegate(DistributedTableMode::COLLABORATION));
943     std::string createSql = "CREATE TABLE IF NOT EXISTS table_pk_integer(integer_field INTEGER UNIQUE,"
944                  "int_field INT, char_field CHARACTER(20), clob_field CLOB);";
945     ASSERT_EQ(SQLiteUtils::ExecuteRawSQL(db_, createSql), E_OK);
946     EXPECT_EQ(delegate_->CreateDistributedTable("table_pk_integer", TableSyncType::DEVICE_COOPERATION), OK);
947 
948     /**
949      * @tc.steps: step2. Test mark unique col isP2pSync true
950      * @tc.expected: step2. return SCHEMA_MISMATCH
951      */
952     DistributedSchema distributedSchema = {1, {{"table_pk_integer", {
953                                                     {"int_field", true},
954                                                     {"char_field", true},
955                                                     {"clob_field", true}}}}};
956     EXPECT_EQ(delegate_->SetDistributedSchema(distributedSchema), SCHEMA_MISMATCH);
957 }
958 
959 /**
960  * @tc.name: SetSchema020
961  * @tc.desc: Test call SetDistributedSchema when unique col and pk isP2pSync
962  * @tc.type: FUNC
963  * @tc.require:
964  * @tc.author: zqq
965  */
966 HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema020, TestSize.Level0)
967 {
968 
969     /**
970      * @tc.steps: step1. Prepare db, tableMode is COLLABORATION
971      * @tc.expected: step1.ok
972      */
973     ASSERT_NO_FATAL_FAILURE(InitDelegate(DistributedTableMode::COLLABORATION));
974     std::string createSql = "CREATE TABLE IF NOT EXISTS table_pk_int(integer_field INTEGER PRIMARY KEY AUTOINCREMENT,"
975         "int_field INT UNIQUE, char_field CHARACTER(20), clob_field CLOB);";
976     ASSERT_EQ(SQLiteUtils::ExecuteRawSQL(db_, createSql), E_OK);
977     EXPECT_EQ(delegate_->CreateDistributedTable("table_pk_int", TableSyncType::DEVICE_COOPERATION), OK);
978 
979     /**
980      * @tc.steps: step2. Test mark unique col and pk isP2pSync true, specified unique col
981      * @tc.expected: step2. return NOT_SUPPORT
982      */
983     DistributedSchema distributedSchema = {1, {
984         {"table_pk_int", {
985             {"integer_field", true},
986             {"int_field", true, true},
987             {"char_field", true},
988             {"clob_field", true}
989         }}}
990     };
991     EXPECT_EQ(delegate_->SetDistributedSchema(distributedSchema), NOT_SUPPORT);
992 }
993 
994 /**
995  * @tc.name: SetSchema021
996  * @tc.desc: Test call SetDistributedSchema when table contains 1000 columns
997  * @tc.type: FUNC
998  * @tc.require:
999  * @tc.author: suyue
1000  */
1001 HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema021, TestSize.Level1)
1002 {
1003     /**
1004      * @tc.steps: step1. create table which contains 1000 columns
1005      * @tc.expected: step1. create table ok
1006      */
1007     TableSchema tableSchema;
1008     tableSchema.name = BIG_COLUMNS_TABLE;
1009     Field field;
1010     field.primary = true;
1011     field.type = TYPE_INDEX<int64_t>;
1012     field.colName = "pk";
1013     tableSchema.fields.push_back(field);
1014     field.primary = false;
1015     field.colName = "123";
1016     field.type = TYPE_INDEX<std::string>;
1017     tableSchema.fields.push_back(field);
1018     const uint16_t fieldNum = 1000;
1019     for (int i = 0; i < fieldNum; i++) {
1020         field.colName = "field" + to_string(i);
1021         tableSchema.fields.push_back(field);
1022     }
1023     ASSERT_EQ(RDBDataGenerator::InitTable(tableSchema, true, true, *db_), E_OK);
1024     ASSERT_NO_FATAL_FAILURE(InitDelegate());
1025     EXPECT_EQ(delegate_->CreateDistributedTable(tableSchema.name, TableSyncType::DEVICE_COOPERATION), OK);
1026 
1027     /**
1028      * @tc.steps: step2. set schema
1029      * @tc.expected: step2. ok
1030      */
1031     DistributedSchema distributedSchema;
1032     DistributedTable distributedTable;
1033     distributedTable.tableName = tableSchema.name;
1034     DistributedField distributedField;
1035     distributedField.isP2pSync = true;
1036     distributedField.colName = "123";
1037     distributedField.isSpecified = false;
1038     distributedTable.fields.push_back(distributedField);
1039     for (int i = 0; i < fieldNum; i++) {
1040         distributedField.colName = "field" + to_string(i);
1041         distributedTable.fields.push_back(distributedField);
1042     }
1043     distributedSchema.tables.push_back(distributedTable);
1044     EXPECT_EQ(delegate_->SetDistributedSchema(distributedSchema), OK);
1045 }
1046 
1047 /**
1048  * @tc.name: SetSchema022
1049  * @tc.desc: Test setting the distributed schema with table names named keywords.
1050  * @tc.type: FUNC
1051  * @tc.require:
1052  * @tc.author: liaoyonghuang
1053  */
1054 HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema022, TestSize.Level1)
1055 {
1056     /**
1057      * @tc.steps: step1. Create device table named keywords.
1058      * @tc.expected: step1.ok
1059      */
1060     ASSERT_NO_FATAL_FAILURE(InitDelegate());
1061     std::string tableName = "except";
1062     std::string sql = "CREATE TABLE IF NOT EXISTS '" + tableName + "'(field1 INTEGER, field2 INT);";
1063     ASSERT_EQ(SQLiteUtils::ExecuteRawSQL(db_, sql), E_OK);
1064     /**
1065      * @tc.steps: step2. Create distributed table and set distributed schema
1066      * @tc.expected: step2.ok
1067      */
1068     auto distributedSchema = GetDistributedSchema(tableName, {"field1", "field2"});
1069     deviceB_->SetDistributedSchema(distributedSchema);
1070     EXPECT_EQ(delegate_->CreateDistributedTable(tableName, TableSyncType::DEVICE_COOPERATION), OK);
1071     EXPECT_EQ(delegate_->SetDistributedSchema(distributedSchema), OK);
1072 }
1073 
1074 /**
1075  * @tc.name: SetSchema023
1076  * @tc.desc: Test SetDistributedSchema interface when tables decrease.
1077  * @tc.type: FUNC
1078  * @tc.require:
1079  * @tc.author: suyue
1080  */
1081 HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema023, TestSize.Level0)
1082 {
1083     /**
1084      * @tc.steps: step1. set distributed schema for the first time
1085      * @tc.expected: step1. return OK
1086      */
1087     ASSERT_NO_FATAL_FAILURE(InitDelegate());
1088     DistributedSchema distributedSchema = {1, {{DEVICE_SYNC_TABLE, {{"pk", true}, {"int_field1", true}}},
1089                                                {CLOUD_SYNC_TABLE, {{"pk", true}, {"int_field2", false}}}}};
1090     EXPECT_EQ(delegate_->SetDistributedSchema(distributedSchema), OK);
1091 
1092     /**
1093      * @tc.steps: step2. decrease tables of input parameter to set distributed schema
1094      * @tc.expected: step2. return OK
1095      */
1096     distributedSchema = {2, {{CLOUD_SYNC_TABLE, {{"pk", true}, {"int_field2", false}}}}};
1097     EXPECT_EQ(delegate_->SetDistributedSchema(distributedSchema), OK);
1098     distributedSchema = {3, {{DEVICE_SYNC_TABLE, {{"pk", true}, {"int_field1", true}}},
1099                              {DEVICE_SYNC_TABLE_UPGRADE, {{"pk", true}, {"int_field2", false}}}}};
1100     EXPECT_EQ(delegate_->SetDistributedSchema(distributedSchema), OK);
1101 }
1102 
1103 /**
1104  * @tc.name: SetSchema024
1105  * @tc.desc: Test SetDistributedSchema out of max schema size limit.
1106  * @tc.type: FUNC
1107  * @tc.require:
1108  * @tc.author: zqq
1109  */
1110 HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema024, TestSize.Level1)
1111 {
1112     /**
1113      * @tc.steps: step1. set distributed schema for the first time
1114      * @tc.expected: step1. return OK
1115      */
1116     ASSERT_NO_FATAL_FAILURE(InitDelegate());
1117     /**
1118      * @tc.steps: step2. generate 32 tables with 1000 field
1119      * @tc.expected: step2. return OK
1120      */
1121     auto basicSchema = GetTableSchema();
1122     const int fieldCount = 1000;
1123     Field basicField;
1124     basicField.type = TYPE_INDEX<int64_t>;
1125     basicField.colName = "generate_field_";
1126     for (int i = 0; i < fieldCount; ++i) {
1127         Field field = basicField;
1128         field.colName  += std::to_string(i);
1129         basicSchema.fields.push_back(field);
1130     }
1131     /**
1132      * @tc.steps: step3. create distributed table
1133      * @tc.expected: step3. return OVER_MAX_LIMITS at last
1134      */
1135     const int tableCount = 32;
1136     DBStatus res = OK;
1137     for (int i = 0; i < tableCount; ++i) {
1138         TableSchema table = basicSchema;
1139         table.name += std::to_string(i);
1140         RDBDataGenerator::InitTable(table, false, *db_);
1141         res = delegate_->CreateDistributedTable(table.name);
1142         if (res != OK) {
1143             break;
1144         }
1145     }
1146     EXPECT_EQ(res, OVER_MAX_LIMITS);
1147 }
1148 
1149 /**
1150  * @tc.name: SetSchema025
1151  * @tc.desc: Test SetDistributedSchema with isForceUpgrade.
1152  * @tc.type: FUNC
1153  * @tc.require:
1154  * @tc.author: liaoyonghuang
1155  */
1156 HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema025, TestSize.Level0)
1157 {
1158     /**
1159      * @tc.steps: step1. Create device table and cloud table in COLLABORATION
1160      * @tc.expected: step1.ok
1161      */
1162     ASSERT_NO_FATAL_FAILURE(InitDelegate());
1163     EXPECT_EQ(delegate_->CreateDistributedTable(DEVICE_SYNC_TABLE, TableSyncType::DEVICE_COOPERATION), OK);
1164     DistributedSchema distributedSchema1 = {1, {{DEVICE_SYNC_TABLE, {{"pk", true}, {"int_field1", true}}}}};
1165     EXPECT_EQ(delegate_->SetDistributedSchema(distributedSchema1), OK);
1166     /**
1167      * @tc.steps: step2. Set distributed schema with isForceUpgrade
1168      * @tc.expected: step2.ok
1169      */
1170     DistributedSchema distributedSchema2 = {2, {{DEVICE_SYNC_TABLE, {{"pk", true}}}}};
1171     EXPECT_EQ(delegate_->SetDistributedSchema(distributedSchema2, true), OK);
1172 }
1173 
1174 /**
1175  * @tc.name: SetSchema026
1176  * @tc.desc: Test SetDistributedSchema with conflict log.
1177  * @tc.type: FUNC
1178  * @tc.require:
1179  * @tc.author: zqq
1180  */
1181 HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema026, TestSize.Level0)
1182 {
1183     /**
1184      * @tc.steps: step1. Prepare db, tableMode is COLLABORATION
1185      * @tc.expected: step1.ok
1186      */
1187     ASSERT_NO_FATAL_FAILURE(InitDelegate(DistributedTableMode::COLLABORATION));
1188     std::string createSql = "CREATE TABLE IF NOT EXISTS table_pk_int(integer_field INTEGER PRIMARY KEY AUTOINCREMENT,"
1189         "int_field INT UNIQUE);";
1190     ASSERT_EQ(SQLiteUtils::ExecuteRawSQL(db_, createSql), E_OK);
1191     EXPECT_EQ(delegate_->CreateDistributedTable("table_pk_int", TableSyncType::DEVICE_COOPERATION), OK);
1192     /**
1193      * @tc.steps: step2. Set Distributed Schema
1194      * @tc.expected: step2. return OK
1195      */
1196     DistributedSchema distributedSchema = {1, {
1197         {"table_pk_int", {
1198             {"integer_field", true},
1199             {"int_field", true}
1200         }}}
1201     };
1202     EXPECT_EQ(delegate_->SetDistributedSchema(distributedSchema), OK);
1203     /**
1204      * @tc.steps: step3. Local insert (1, 2), (2, 1) and delete (1, 2)
1205      * @tc.expected: step3. return OK
1206      */
1207     ASSERT_EQ(SQLiteUtils::ExecuteRawSQL(db_, "INSERT INTO table_pk_int VALUES(1, 2)"), E_OK);
1208     ASSERT_EQ(SQLiteUtils::ExecuteRawSQL(db_, "INSERT INTO table_pk_int VALUES(2, 1)"), E_OK);
1209     ASSERT_EQ(SQLiteUtils::ExecuteRawSQL(db_, "DELETE FROM table_pk_int WHERE integer_field = 1"), E_OK);
1210     /**
1211      * @tc.steps: step4. Upgrade Distributed Schema and mark int_field specified
1212      * @tc.expected: step4. return OK
1213      */
1214     distributedSchema = {2, {
1215             {"table_pk_int", {
1216                     {"integer_field", false},
1217                     {"int_field", true, true}
1218             }}}
1219     };
1220     EXPECT_EQ(delegate_->SetDistributedSchema(distributedSchema, true), OK);
1221 }
1222 
1223 /**
1224  * @tc.name: SetSchema027
1225  * @tc.desc: Test two table create distributed table.
1226  * @tc.type: FUNC
1227  * @tc.require:
1228  * @tc.author: zqq
1229  */
1230 HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema027, TestSize.Level0)
1231 {
1232     /**
1233      * @tc.steps: step1. Prepare db create two table
1234      * @tc.expected: step1.ok
1235      */
1236     ASSERT_NO_FATAL_FAILURE(InitDelegate(DistributedTableMode::COLLABORATION));
1237     std::string createSql = "CREATE TABLE IF NOT EXISTS table1(integer_field INTEGER PRIMARY KEY AUTOINCREMENT,"
1238         "int_field INT UNIQUE);";
1239     ASSERT_EQ(SQLiteUtils::ExecuteRawSQL(db_, createSql), E_OK);
1240     EXPECT_EQ(delegate_->CreateDistributedTable("table1", TableSyncType::DEVICE_COOPERATION), OK);
1241     createSql = "CREATE TABLE IF NOT EXISTS table2(integer_field INTEGER PRIMARY KEY AUTOINCREMENT,"
1242         "int_field INT UNIQUE);";
1243     ASSERT_EQ(SQLiteUtils::ExecuteRawSQL(db_, createSql), E_OK);
1244     EXPECT_EQ(delegate_->CreateDistributedTable("table2", TableSyncType::DEVICE_COOPERATION), OK);
1245     auto table1 = std::string(DBConstant::RELATIONAL_PREFIX).append("table1_log");
1246     auto table2 = std::string(DBConstant::RELATIONAL_PREFIX).append("table2_log");
1247     RelationalTestUtils::CheckIndexCount(db_, table1, 3u); // 3 is index count
1248     RelationalTestUtils::CheckIndexCount(db_, table2, 3u); // 3 is index count
1249 }
1250 
1251 /**
1252  * @tc.name: NormalSync001
1253  * @tc.desc: Test set distributed schema and sync.
1254  * @tc.type: FUNC
1255  * @tc.require:
1256  * @tc.author: zqq
1257  */
1258 HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync001, TestSize.Level1)
1259 {
1260     /**
1261      * @tc.steps: step1. Create device table and cloud table in COLLABORATION
1262      * @tc.expected: step1.ok
1263      */
1264     ASSERT_NO_FATAL_FAILURE(InitDelegate());
1265     auto schema = GetSchema();
1266     auto distributedSchema = RDBDataGenerator::ParseSchema(schema, true);
1267     deviceB_->SetDistributedSchema(distributedSchema);
1268     EXPECT_EQ(delegate_->CreateDistributedTable(DEVICE_SYNC_TABLE, TableSyncType::DEVICE_COOPERATION), OK);
1269     EXPECT_EQ(delegate_->SetDistributedSchema(distributedSchema), OK);
1270     LOGI("[DistributedDBCloudAsyncDownloadAssetsTest] CreateDistributedTable %s", DEVICE_SYNC_TABLE);
1271     /**
1272      * @tc.steps: step2. Insert one data
1273      * @tc.expected: step2.ok
1274      */
1275     auto tableSchema = GetTableSchema();
1276     ASSERT_EQ(RDBDataGenerator::InsertVirtualLocalDBData(0, 10, deviceB_, tableSchema), E_OK);
1277     ASSERT_EQ(RDBDataGenerator::PrepareVirtualDeviceEnv(tableSchema.name, db_, deviceB_), E_OK);
1278     /**
1279      * @tc.steps: step3. Sync to real device
1280      * @tc.expected: step3.ok
1281      */
1282     Query query = Query::Select(tableSchema.name);
1283     DistributedDBToolsUnitTest::BlockSync(*delegate_, query, SYNC_MODE_PULL_ONLY, OK, {deviceB_->GetDeviceId()});
1284 }
1285 
1286 /**
1287  * @tc.name: NormalSync002
1288  * @tc.desc: Test sync with diff distributed schema [high version -> low version].
1289  * @tc.type: FUNC
1290  * @tc.require:
1291  * @tc.author: zqq
1292  */
1293 HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync002, TestSize.Level1)
1294 {
1295     /**
1296      * @tc.steps: step1. Create device table and cloud table in COLLABORATION
1297      * @tc.expected: step1.ok
1298      */
1299     ASSERT_NO_FATAL_FAILURE(InitDelegate());
1300     /**
1301      * @tc.steps: step2. DeviceB set schema [pk, int_field1, int_field2, int_field_upgrade]
1302      * @tc.expected: step2.ok
1303      */
1304     DataBaseSchema virtualSchema;
1305     auto tableSchema = GetTableSchema(true);
1306     tableSchema.name = DEVICE_SYNC_TABLE;
1307     virtualSchema.tables.push_back(tableSchema);
1308     auto distributedSchema = RDBDataGenerator::ParseSchema(virtualSchema);
1309     deviceB_->SetDistributedSchema(distributedSchema);
1310     /**
1311      * @tc.steps: step3. Real device set schema [pk, int_field1, int_field2]
1312      * @tc.expected: step3.ok
1313      */
1314     EXPECT_EQ(delegate_->CreateDistributedTable(DEVICE_SYNC_TABLE, TableSyncType::DEVICE_COOPERATION), OK);
1315     LOGI("[DistributedDBCloudAsyncDownloadAssetsTest] CreateDistributedTable %s", DEVICE_SYNC_TABLE);
1316     EXPECT_EQ(delegate_->SetDistributedSchema(RDBDataGenerator::ParseSchema(GetSchema())), OK);
1317     /**
1318      * @tc.steps: step4. Insert table info and virtual data into deviceB
1319      * @tc.expected: step4.ok
1320      */
1321     ASSERT_EQ(RDBDataGenerator::InsertVirtualLocalDBData(0, 10, deviceB_, tableSchema), E_OK);
1322     ASSERT_EQ(RDBDataGenerator::PrepareVirtualDeviceEnv(DEVICE_SYNC_TABLE_UPGRADE, DEVICE_SYNC_TABLE, db_, deviceB_),
1323         E_OK);
1324     /**
1325      * @tc.steps: step5. Sync to real device
1326      * @tc.expected: step5.ok
1327      */
1328     Query query = Query::Select(tableSchema.name);
1329     EXPECT_EQ(deviceB_->GenericVirtualDevice::Sync(SYNC_MODE_PUSH_ONLY, query, true), E_OK);
1330 }
1331 
1332 /**
1333  * @tc.name: NormalSync003
1334  * @tc.desc: Test sync with diff distributed schema [low version -> high version].
1335  * @tc.type: FUNC
1336  * @tc.require:
1337  * @tc.author: zqq
1338  */
1339 HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync003, TestSize.Level1)
1340 {
1341     /**
1342      * @tc.steps: step1. Create device table and cloud table in COLLABORATION
1343      * @tc.expected: step1.ok
1344      */
1345     ASSERT_NO_FATAL_FAILURE(InitDelegate());
1346     /**
1347      * @tc.steps: step2. DeviceB set schema [pk, int_field1, int_field2]
1348      * @tc.expected: step2.ok
1349      */
1350     DataBaseSchema virtualSchema;
1351     auto tableSchema = GetTableSchema();
1352     tableSchema.name = DEVICE_SYNC_TABLE_UPGRADE;
1353     virtualSchema.tables.push_back(tableSchema);
1354     auto distributedSchema = RDBDataGenerator::ParseSchema(virtualSchema);
1355     deviceB_->SetDistributedSchema(distributedSchema);
1356     /**
1357      * @tc.steps: step3. Real device set schema [pk, int_field1, int_field2, int_field_upgrade]
1358      * @tc.expected: step3.ok
1359      */
1360     EXPECT_EQ(delegate_->CreateDistributedTable(DEVICE_SYNC_TABLE_UPGRADE, TableSyncType::DEVICE_COOPERATION), OK);
1361     LOGI("[DistributedDBCloudAsyncDownloadAssetsTest] CreateDistributedTable %s", DEVICE_SYNC_TABLE);
1362     EXPECT_EQ(delegate_->SetDistributedSchema(RDBDataGenerator::ParseSchema(GetSchema())), OK);
1363     /**
1364      * @tc.steps: step4. Insert table info and virtual data into deviceB
1365      * @tc.expected: step4.ok
1366      */
1367     ASSERT_EQ(RDBDataGenerator::InsertVirtualLocalDBData(0, 10, deviceB_, tableSchema), E_OK);
1368     ASSERT_EQ(RDBDataGenerator::PrepareVirtualDeviceEnv(DEVICE_SYNC_TABLE, DEVICE_SYNC_TABLE_UPGRADE, db_, deviceB_),
1369         E_OK);
1370     /**
1371      * @tc.steps: step5. Sync to real device
1372      * @tc.expected: step5.ok
1373      */
1374     Query query = Query::Select(tableSchema.name);
1375     EXPECT_EQ(deviceB_->GenericVirtualDevice::Sync(SYNC_MODE_PUSH_ONLY, query, true), E_OK);
1376 }
1377 
1378 /**
1379  * @tc.name: NormalSync004
1380  * @tc.desc: Test sync when distributed schema was not set.
1381  * @tc.type: FUNC
1382  * @tc.require:
1383  * @tc.author: liaoyonghuang
1384  */
1385 HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync004, TestSize.Level0)
1386 {
1387     /**
1388      * @tc.steps: step1. Create device table and cloud table in COLLABORATION
1389      * @tc.expected: step1.ok
1390      */
1391     ASSERT_NO_FATAL_FAILURE(InitDelegate());
1392     auto tableSchema = GetTableSchema();
1393     ASSERT_EQ(RDBDataGenerator::PrepareVirtualDeviceEnv(tableSchema.name, db_, deviceB_), E_OK);
1394     EXPECT_EQ(delegate_->CreateDistributedTable(DEVICE_SYNC_TABLE, TableSyncType::DEVICE_COOPERATION), OK);
1395     /**
1396      * @tc.steps: step2. Sync to real device
1397      * @tc.expected: step2. return SCHEMA_MISMATCH.
1398      */
1399     Query query = Query::Select(tableSchema.name);
1400     DBStatus status = delegate_->Sync({UnitTestCommonConstant::DEVICE_B}, SYNC_MODE_PUSH_ONLY, query, nullptr, true);
1401     EXPECT_EQ(status, SCHEMA_MISMATCH);
1402 }
1403 
1404 /**
1405  * @tc.name: NormalSync005
1406  * @tc.desc: Test sync with specified columns
1407  * @tc.type: FUNC
1408  * @tc.require:
1409  * @tc.author: liaoyonghuang
1410  */
1411 HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync005, TestSize.Level1)
1412 {
1413     /**
1414      * @tc.steps: step1. Create device table and cloud table in COLLABORATION
1415      * @tc.expected: step1.ok
1416      */
1417     ASSERT_NO_FATAL_FAILURE(InitDelegate(DistributedTableMode::COLLABORATION));
1418     DistributedSchema schema = GetDistributedSchema(DEVICE_SYNC_TABLE, {"pk", "int_field1"});
1419     EXPECT_EQ(delegate_->CreateDistributedTable(DEVICE_SYNC_TABLE, TableSyncType::DEVICE_COOPERATION), OK);
1420     deviceB_->SetDistributedSchema(schema);
1421     EXPECT_EQ(delegate_->SetDistributedSchema(schema), OK);
1422     /**
1423      * @tc.steps: step2. Init some data
1424      * @tc.expected: step2.ok
1425      */
1426     int64_t dataNum = 10;
1427     EXPECT_EQ(RDBDataGenerator::InsertLocalDBData(0, dataNum / 2, db_, GetTableSchema()), E_OK);
1428     std::string sql = "update " + std::string(DEVICE_SYNC_TABLE) + " set int_field1 = 1, int_field2 = 2 where pk >= 0";
1429     ASSERT_EQ(SQLiteUtils::ExecuteRawSQL(db_, sql), E_OK);
1430     auto tableSchema = GetTableSchema();
1431     std::this_thread::sleep_for(std::chrono::seconds(1));
1432     ASSERT_EQ(RDBDataGenerator::InsertVirtualLocalDBData(0, dataNum, deviceB_, tableSchema), E_OK);
1433     ASSERT_EQ(RDBDataGenerator::PrepareVirtualDeviceEnv(tableSchema.name, db_, deviceB_), E_OK);
1434     /**
1435      * @tc.steps: step3. Sync to real device and check data
1436      * @tc.expected: step3.ok
1437      */
1438     Query query = Query::Select(tableSchema.name);
1439     EXPECT_EQ(deviceB_->GenericVirtualDevice::Sync(SYNC_MODE_PUSH_PULL, query, true), E_OK);
1440     sql = "select int_field1, int_field2 from " + std::string(DEVICE_SYNC_TABLE) + " order by pk;";
1441     sqlite3_stmt *stmt = nullptr;
1442     ASSERT_EQ(SQLiteUtils::GetStatement(db_, sql, stmt), E_OK);
1443     int dataIndex = 0;
1444     while (SQLiteUtils::StepWithRetry(stmt) == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) {
1445         int64_t intField1Value = sqlite3_column_int64(stmt, 0);
1446         int64_t intField2Value = sqlite3_column_int64(stmt, 1);
1447         EXPECT_EQ(intField1Value, dataIndex);
1448         dataIndex++;
1449         if (dataIndex <= dataNum / 2) {
1450             EXPECT_EQ(intField2Value, 2);
1451         } else {
1452             EXPECT_EQ(intField2Value, 0);
1453         }
1454     }
1455     EXPECT_EQ(dataIndex, dataNum);
1456     int errCode;
1457     SQLiteUtils::ResetStatement(stmt, true, errCode);
1458 }
1459 
1460 /**
1461  * @tc.name: NormalSync006
1462  * @tc.desc: Test set distributed schema and sync.
1463  * @tc.type: FUNC
1464  * @tc.require:
1465  * @tc.author: zqq
1466  */
1467 HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync006, TestSize.Level1)
1468 {
1469     /**
1470      * @tc.steps: step1. Create device table and cloud table in COLLABORATION
1471      * @tc.expected: step1.ok
1472      */
1473     ASSERT_NO_FATAL_FAILURE(InitDelegate());
1474     auto schema = GetSchema();
1475     auto distributedSchema = RDBDataGenerator::ParseSchema(schema, true);
1476     EXPECT_EQ(delegate_->CreateDistributedTable(DEVICE_SYNC_TABLE, TableSyncType::DEVICE_COOPERATION), OK);
1477     LOGI("[DistributedDBCloudAsyncDownloadAssetsTest] CreateDistributedTable %s", DEVICE_SYNC_TABLE);
1478     deviceB_->SetDistributedSchema(distributedSchema);
1479     EXPECT_EQ(delegate_->SetDistributedSchema(distributedSchema), OK);
1480     /**
1481      * @tc.steps: step2. Insert one data
1482      * @tc.expected: step2.ok
1483      */
1484     auto tableSchema = GetTableSchema();
1485     EXPECT_EQ(RDBDataGenerator::InsertLocalDBData(0, 1, db_, GetTableSchema()), E_OK);
1486     ASSERT_EQ(RDBDataGenerator::PrepareVirtualDeviceEnv(tableSchema.name, db_, deviceB_), E_OK);
1487     /**
1488      * @tc.steps: step3. Sync to real device
1489      * @tc.expected: step3.ok
1490      */
1491     Query query = Query::Select(tableSchema.name);
1492     DistributedDBToolsUnitTest::BlockSync(*delegate_, query, SYNC_MODE_PUSH_ONLY, OK, {deviceB_->GetDeviceId()});
1493     /**
1494      * @tc.steps: step4. Change schema to non-existent table name, then sync
1495      * @tc.expected: step4.SCHEMA_MISMATCH
1496      */
1497     tableSchema.name = "not_config_table";
1498     ASSERT_EQ(RDBDataGenerator::InitTable(tableSchema, true, *db_), SQLITE_OK);
1499     ASSERT_EQ(delegate_->CreateDistributedTable(tableSchema.name), OK);
1500     Query query2 = Query::Select(tableSchema.name);
1501     std::map<std::string, std::vector<TableStatus>> statusMap;
1502     SyncStatusCallback callBack2;
1503     DBStatus callStatus = delegate_->Sync({deviceB_->GetDeviceId()}, SYNC_MODE_PUSH_ONLY, query2, callBack2, true);
1504     EXPECT_EQ(callStatus, SCHEMA_MISMATCH);
1505 }
1506 
1507 /**
1508  * @tc.name: NormalSync007
1509  * @tc.desc: Test change distributed schema and sync.
1510  * @tc.type: FUNC
1511  * @tc.require:
1512  * @tc.author: zqq
1513  */
1514 HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync007, TestSize.Level1)
1515 {
1516     /**
1517      * @tc.steps: step1. Create device table and cloud table in COLLABORATION
1518      * @tc.expected: step1.ok
1519      */
1520     ASSERT_NO_FATAL_FAILURE(InitDelegate());
1521     auto schema = GetSchema();
1522     auto distributedSchema = RDBDataGenerator::ParseSchema(schema, true);
1523     EXPECT_EQ(delegate_->CreateDistributedTable(DEVICE_SYNC_TABLE, TableSyncType::DEVICE_COOPERATION), OK);
1524     LOGI("[DistributedDBCloudAsyncDownloadAssetsTest] CreateDistributedTable %s", DEVICE_SYNC_TABLE);
1525     deviceB_->SetDistributedSchema(distributedSchema);
1526     EXPECT_EQ(delegate_->SetDistributedSchema(distributedSchema), OK);
1527     /**
1528      * @tc.steps: step2. Insert one data
1529      * @tc.expected: step2.ok
1530      */
1531     auto tableSchema = GetTableSchema();
1532     ASSERT_EQ(RDBDataGenerator::InsertVirtualLocalDBData(0, 1, deviceB_, tableSchema), E_OK);
1533     ASSERT_EQ(RDBDataGenerator::PrepareVirtualDeviceEnv(tableSchema.name, db_, deviceB_), E_OK);
1534     /**
1535      * @tc.steps: step3. Sync to real device
1536      * @tc.expected: step3.ok
1537      */
1538     Query query = Query::Select(tableSchema.name);
1539     DistributedDBToolsUnitTest::BlockSync(*delegate_, query, SYNC_MODE_PULL_ONLY, OK, {deviceB_->GetDeviceId()});
1540     std::string sql = std::string("select count(*) from ").append(DEVICE_SYNC_TABLE)
1541             .append(" where pk=0 and int_field1 is null and int_field2 is null");
1542     int count = 0;
1543     EXPECT_EQ(SQLiteUtils::GetCountBySql(db_, sql, count), E_OK);
1544     EXPECT_EQ(count, 1);
1545     /**
1546      * @tc.steps: step4. Change schema and sync again
1547      * @tc.expected: step4.ok
1548      */
1549     distributedSchema = RDBDataGenerator::ParseSchema(schema);
1550     EXPECT_EQ(delegate_->SetDistributedSchema(distributedSchema), OK);
1551     DistributedDBToolsUnitTest::BlockSync(*delegate_, query, SYNC_MODE_PULL_ONLY, OK, {deviceB_->GetDeviceId()});
1552     sql = std::string("select count(*) from ").append(DEVICE_SYNC_TABLE)
1553         .append(" where pk=0 and int_field1=0 and int_field2=0");
1554     count = 0;
1555     EXPECT_EQ(SQLiteUtils::GetCountBySql(db_, sql, count), E_OK);
1556     EXPECT_EQ(count, 1);
1557     auto changeData = delegateObserver_->GetSavedChangedData()[std::string(DEVICE_SYNC_TABLE)];
1558     EXPECT_TRUE(changeData.properties.isP2pSyncDataChange);
1559 }
1560 
1561 /**
1562  * @tc.name: NormalSync008
1563  * @tc.desc: Test set distributed schema and sync with diff sort.
1564  * @tc.type: FUNC
1565  * @tc.require:
1566  * @tc.author: zqq
1567  */
1568 HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync008, TestSize.Level1)
1569 {
1570     /**
1571      * @tc.steps: step1. Create device table and cloud table in COLLABORATION
1572      * @tc.expected: step1.ok
1573      */
1574     ASSERT_NO_FATAL_FAILURE(InitDelegate());
1575     auto schema = GetSchema();
1576     auto distributedSchema = RDBDataGenerator::ParseSchema(schema);
1577     EXPECT_EQ(delegate_->CreateDistributedTable(DEVICE_SYNC_TABLE, TableSyncType::DEVICE_COOPERATION), OK);
1578     LOGI("[DistributedDBCloudAsyncDownloadAssetsTest] CreateDistributedTable %s", DEVICE_SYNC_TABLE);
1579     deviceB_->SetDistributedSchema(distributedSchema);
1580     EXPECT_EQ(delegate_->SetDistributedSchema(distributedSchema), OK);
1581     /**
1582      * @tc.steps: step2. Insert one data with diff sort col
1583      * @tc.expected: step2.ok
1584      */
1585     auto tableSchema = GetTableSchema();
1586     ASSERT_EQ(RDBDataGenerator::InsertVirtualLocalDBData(0, 1, deviceB_,
1587         RDBDataGenerator::FlipTableSchema(tableSchema)), E_OK);
1588     ASSERT_EQ(RDBDataGenerator::PrepareVirtualDeviceEnv(tableSchema.name, db_, deviceB_), E_OK);
1589     /**
1590      * @tc.steps: step3. Sync to real device
1591      * @tc.expected: step3.ok
1592      */
1593     Query query = Query::Select(tableSchema.name);
1594     DistributedDBToolsUnitTest::BlockSync(*delegate_, query, SYNC_MODE_PULL_ONLY, OK, {deviceB_->GetDeviceId()});
1595     std::string sql = std::string("select count(*) from ").append(DEVICE_SYNC_TABLE).append(" where pk=0;");
1596     int count = 0;
1597     EXPECT_EQ(SQLiteUtils::GetCountBySql(db_, sql, count), E_OK);
1598     EXPECT_EQ(count, 1);
1599     sql = std::string("select count(*) from ")
1600         .append(RelationalStoreManager::GetDistributedLogTableName(DEVICE_SYNC_TABLE))
1601         .append(" where data_key=0 and cursor=1;");
1602     count = 0;
1603     EXPECT_EQ(SQLiteUtils::GetCountBySql(db_, sql, count), E_OK);
1604     EXPECT_EQ(count, 1);
1605 }
1606 
1607 /**
1608  * @tc.name: NormalSync009
1609  * @tc.desc: Test if distributed table will be created when sync with COLLABORATION mode.
1610  * @tc.type: FUNC
1611  * @tc.require:
1612  * @tc.author: liaoyonghuang
1613  */
1614 HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync009, TestSize.Level1)
1615 {
1616     /**
1617      * @tc.steps: step1. Create device table and cloud table in COLLABORATION
1618      * @tc.expected: step1.ok
1619      */
1620     ASSERT_NO_FATAL_FAILURE(InitDelegate());
1621     auto schema = GetSchema();
1622     auto distributedSchema = RDBDataGenerator::ParseSchema(schema, true);
1623     deviceB_->SetDistributedSchema(distributedSchema);
1624     EXPECT_EQ(delegate_->CreateDistributedTable(DEVICE_SYNC_TABLE, TableSyncType::DEVICE_COOPERATION), OK);
1625     EXPECT_EQ(delegate_->SetDistributedSchema(distributedSchema), OK);
1626     LOGI("[DistributedDBCloudAsyncDownloadAssetsTest] CreateDistributedTable %s", DEVICE_SYNC_TABLE);
1627     /**
1628      * @tc.steps: step2. Insert one data
1629      * @tc.expected: step2.ok
1630      */
1631     auto tableSchema = GetTableSchema();
1632     ASSERT_EQ(RDBDataGenerator::InsertVirtualLocalDBData(0, 10, deviceB_, tableSchema), E_OK);
1633     ASSERT_EQ(RDBDataGenerator::PrepareVirtualDeviceEnv(tableSchema.name, db_, deviceB_), E_OK);
1634     /**
1635      * @tc.steps: step3. Sync to real device
1636      * @tc.expected: step3.ok
1637      */
1638     std::string checkSql = "select count(*) from sqlite_master where type='table' and name != '" +
1639         DBCommon::GetLogTableName(DEVICE_SYNC_TABLE) + "' and name like 'naturalbase_rdb_aux_" +
1640         std::string(DEVICE_SYNC_TABLE) + "_%'";
1641     int count = 0;
1642     EXPECT_EQ(SQLiteUtils::GetCountBySql(db_, checkSql, count), E_OK);
1643     EXPECT_EQ(count, 0);
1644     Query query = Query::Select(tableSchema.name);
1645     DistributedDBToolsUnitTest::BlockSync(*delegate_, query, SYNC_MODE_PULL_ONLY, OK, {deviceB_->GetDeviceId()});
1646     /**
1647      * @tc.steps: step4. Check if the distributed table exists
1648      * @tc.expected: step4.ok
1649      */
1650     count = 0;
1651     EXPECT_EQ(SQLiteUtils::GetCountBySql(db_, checkSql, count), E_OK);
1652     EXPECT_EQ(count, 0);
1653 }
1654 
1655 /**
1656  * @tc.name: NormalSync010
1657  * @tc.desc: Test sync without not null col.
1658  * @tc.type: FUNC
1659  * @tc.require:
1660  * @tc.author: zqq
1661  */
1662 HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync010, TestSize.Level0)
1663 {
1664     /**
1665      * @tc.steps: step1. Recreate not null table
1666      * @tc.expected: step1.ok
1667      */
1668     std::string sql = std::string("DROP TABLE ").append(DEVICE_SYNC_TABLE);
1669     ASSERT_EQ(SQLiteUtils::ExecuteRawSQL(db_, sql), E_OK);
1670     auto tableSchema = GetTableSchema();
1671     ASSERT_EQ(RDBDataGenerator::InitTable(tableSchema, true, *db_), E_OK);
1672     ASSERT_NO_FATAL_FAILURE(InitDelegate());
1673     auto schema = GetSchema();
1674     auto distributedSchema = RDBDataGenerator::ParseSchema(schema, true);
1675     deviceB_->SetDistributedSchema(distributedSchema);
1676     EXPECT_EQ(delegate_->CreateDistributedTable(DEVICE_SYNC_TABLE, TableSyncType::DEVICE_COOPERATION), OK);
1677     EXPECT_EQ(delegate_->SetDistributedSchema(distributedSchema), SCHEMA_MISMATCH);
1678     /**
1679      * @tc.steps: step2. Insert one data
1680      * @tc.expected: step2.ok
1681      */
1682     ASSERT_EQ(RDBDataGenerator::InsertVirtualLocalDBData(0, 1, deviceB_, tableSchema), E_OK);
1683     ASSERT_EQ(RDBDataGenerator::PrepareVirtualDeviceEnv(tableSchema.name, db_, deviceB_), E_OK);
1684     /**
1685      * @tc.steps: step3. Sync without str col
1686      * @tc.expected: step3.ok
1687      */
1688     Query query = Query::Select(tableSchema.name);
1689     DBStatus callStatus = delegate_->Sync({deviceB_->GetDeviceId()}, SYNC_MODE_PULL_ONLY, query, nullptr, true);
1690     EXPECT_EQ(callStatus, SCHEMA_MISMATCH);
1691     /**
1692      * @tc.steps: step4. Check if the distributed table exists
1693      * @tc.expected: step4.ok
1694      */
1695     int count = 0;
1696     sql = std::string("select count(*) from ")
1697             .append(RelationalStoreManager::GetDistributedLogTableName(DEVICE_SYNC_TABLE));
1698     EXPECT_EQ(SQLiteUtils::GetCountBySql(db_, sql, count), E_OK);
1699     EXPECT_EQ(count, 0);
1700 }
1701 
1702 /**
1703  * @tc.name: NormalSync011
1704  * @tc.desc: Test set the distributed schema first then sync.
1705  * @tc.type: FUNC
1706  * @tc.require:
1707  * @tc.author: bty
1708  */
1709 HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync011, TestSize.Level1)
1710 {
1711     /**
1712      * @tc.steps: step1. Create device table and cloud table in COLLABORATION
1713      * @tc.expected: step1.ok
1714      */
1715     ASSERT_NO_FATAL_FAILURE(InitDelegate());
1716     auto schema = GetSchema();
1717     auto distributedSchema = RDBDataGenerator::ParseSchema(schema, true);
1718     deviceB_->SetDistributedSchema(distributedSchema);
1719     EXPECT_EQ(delegate_->SetDistributedSchema(distributedSchema), OK);
1720     EXPECT_EQ(delegate_->CreateDistributedTable(DEVICE_SYNC_TABLE, TableSyncType::DEVICE_COOPERATION), OK);
1721     LOGI("[DistributedDBCloudAsyncDownloadAssetsTest] CreateDistributedTable %s", DEVICE_SYNC_TABLE);
1722     /**
1723      * @tc.steps: step2. Insert one data
1724      * @tc.expected: step2.ok
1725      */
1726     auto tableSchema = GetTableSchema();
1727     EXPECT_EQ(RDBDataGenerator::InsertLocalDBData(0, 1, db_, GetTableSchema()), E_OK);
1728     ASSERT_EQ(RDBDataGenerator::PrepareVirtualDeviceEnv(tableSchema.name, db_, deviceB_), E_OK);
1729     /**
1730      * @tc.steps: step3. Sync to real device
1731      * @tc.expected: step3.ok
1732      */
1733     Query query = Query::Select().FromTable({tableSchema.name});
1734     DistributedDBToolsUnitTest::BlockSync(*delegate_, query, SYNC_MODE_PUSH_ONLY, OK, {deviceB_->GetDeviceId()});
1735 }
1736 
1737 /**
1738  * @tc.name: NormalSync012
1739  * @tc.desc: Test sync with autoincrement table.
1740  * @tc.type: FUNC
1741  * @tc.require:
1742  * @tc.author: zqq
1743  */
1744 HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync012, TestSize.Level0)
1745 {
1746     /**
1747      * @tc.steps: step1. Create auto increment table and unique index
1748      * @tc.expected: step1.ok
1749      */
1750     auto tableSchema = GetTableSchema();
1751     tableSchema.name = DEVICE_SYNC_TABLE_AUTOINCREMENT;
1752     ASSERT_EQ(RDBDataGenerator::InitTable(tableSchema, true, true, *db_), E_OK);
1753     ASSERT_NO_FATAL_FAILURE(InitDelegate());
1754     tableSchema = GetTableSchema(false, true);
1755     tableSchema.name = DEVICE_SYNC_TABLE_AUTOINCREMENT;
1756     auto schema = GetSchema();
1757     schema.tables.push_back(tableSchema);
1758     DistributedSchema distributedSchema = {0, {{tableSchema.name, {
1759         {"pk", false, false},
1760         {"int_field1", true, false},
1761         {"int_field2", true, false},
1762         {"123", true, true}}}}};
1763     deviceB_->SetDistributedSchema(distributedSchema);
1764     int errCode = SQLiteUtils::ExecuteRawSQL(db_, std::string("CREATE UNIQUE INDEX U_INDEX ON ")
1765         .append(tableSchema.name).append("('123')"));
1766     ASSERT_EQ(errCode, E_OK);
1767     EXPECT_EQ(delegate_->CreateDistributedTable(tableSchema.name, TableSyncType::DEVICE_COOPERATION), OK);
1768     EXPECT_EQ(delegate_->SetDistributedSchema(distributedSchema), OK);
1769     /**
1770      * @tc.steps: step2. Insert one data
1771      * @tc.expected: step2.ok
1772      */
1773     ASSERT_EQ(RDBDataGenerator::InsertLocalDBData(0, 1, db_, tableSchema), E_OK);
1774     std::this_thread::sleep_for(std::chrono::milliseconds(100)); // sleep 100 ms
1775     ASSERT_EQ(RDBDataGenerator::InsertVirtualLocalDBData(0, 2, deviceB_, tableSchema), E_OK);
1776     ASSERT_EQ(RDBDataGenerator::PrepareVirtualDeviceEnv(tableSchema.name, db_, deviceB_), E_OK);
1777     /**
1778      * @tc.steps: step3. Sync to real device
1779      * @tc.expected: step3.ok
1780      */
1781     Query query = Query::Select(tableSchema.name);
1782     DistributedDBToolsUnitTest::BlockSync(*delegate_, query, SYNC_MODE_PULL_ONLY, OK, {deviceB_->GetDeviceId()});
1783     std::string sql = std::string("select count(*) from ").append(tableSchema.name);
1784     int count = 0;
1785     EXPECT_EQ(SQLiteUtils::GetCountBySql(db_, sql, count), E_OK);
1786     EXPECT_EQ(count, 2);
1787     /**
1788      * @tc.steps: step4. Update date and sync again
1789      * @tc.expected: step4.ok
1790      */
1791     ASSERT_EQ(RDBDataGenerator::InsertVirtualLocalDBData(0, 1, deviceB_, tableSchema), E_OK);
1792     DistributedDBToolsUnitTest::BlockSync(*delegate_, query, SYNC_MODE_PULL_ONLY, OK, {deviceB_->GetDeviceId()});
1793     sql = std::string("select count(*) from ").append(tableSchema.name);
1794     count = 0;
1795     EXPECT_EQ(SQLiteUtils::GetCountBySql(db_, sql, count), E_OK);
1796     EXPECT_EQ(count, 2);
1797 }
1798 
1799 /**
1800  * @tc.name: NormalSync013
1801  * @tc.desc: Test chanage data after sync.
1802  * @tc.type: FUNC
1803  * @tc.require:
1804  * @tc.author: lg
1805  */
1806 HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync013, TestSize.Level1)
1807 {
1808     /**
1809      * @tc.steps: step1. Create device table and cloud table in COLLABORATION
1810      * @tc.expected: step1.ok
1811      */
1812     ASSERT_NO_FATAL_FAILURE(InitDelegate());
1813     auto schema = GetSchema();
1814     auto distributedSchema = RDBDataGenerator::ParseSchema(schema, true);
1815     deviceB_->SetDistributedSchema(distributedSchema);
1816     EXPECT_EQ(delegate_->CreateDistributedTable(DEVICE_SYNC_TABLE, TableSyncType::DEVICE_COOPERATION), OK);
1817     EXPECT_EQ(delegate_->SetDistributedSchema(distributedSchema), OK);
1818     LOGI("[DistributedDBCloudAsyncDownloadAssetsTest] CreateDistributedTable %s", DEVICE_SYNC_TABLE);
1819     /**
1820      * @tc.steps: step2. Insert one data
1821      * @tc.expected: step2.ok
1822      */
1823     auto tableSchema = GetTableSchema();
1824     ASSERT_EQ(RDBDataGenerator::InsertVirtualLocalDBData(0, 10, deviceB_, tableSchema), E_OK);
1825     ASSERT_EQ(RDBDataGenerator::PrepareVirtualDeviceEnv(tableSchema.name, db_, deviceB_), E_OK);
1826     /**
1827      * @tc.steps: step3. Sync to real device
1828      * @tc.expected: step3.ok
1829      */
1830     Query query = Query::Select(tableSchema.name);
1831     DistributedDBToolsUnitTest::BlockSync(*delegate_, query, SYNC_MODE_PULL_ONLY, OK, {deviceB_->GetDeviceId()});
1832     /**
1833      * @tc.steps: step4. check changData
1834      * @tc.expected: step4.ok
1835      */
1836     auto changeData = delegateObserver_->GetSavedChangedData();
1837     EXPECT_EQ(changeData[tableSchema.name].primaryData[0].size(), 10u);
1838     EXPECT_EQ(changeData[tableSchema.name].field.size(), 1u);
1839     /**
1840      * @tc.steps: step5. Remove the last item and a cloud-only item, then check changeData
1841      * @tc.expected: step5. Only the last item is in changeData and field is primary key
1842      */
1843     delegateObserver_->ClearChangedData();
1844     ASSERT_EQ(RDBDataGenerator::InsertVirtualLocalDBData(9, 11, deviceB_, tableSchema, true), E_OK);
1845     DistributedDBToolsUnitTest::BlockSync(*delegate_, query, SYNC_MODE_PULL_ONLY, OK, {deviceB_->GetDeviceId()});
1846     changeData = delegateObserver_->GetSavedChangedData();
1847     ASSERT_EQ(changeData[tableSchema.name].primaryData[OP_DELETE].size(), 1u);
1848     EXPECT_EQ(changeData[tableSchema.name].primaryData[OP_DELETE][0].size(), 1u);
1849     ASSERT_EQ(changeData[tableSchema.name].field.size(), 1u);
1850     EXPECT_EQ(changeData[tableSchema.name].field[0], "pk");
1851 }
1852 
1853 /**
1854  * @tc.name: NormalSync014
1855  * @tc.desc: Test chanage data after sync.
1856  * @tc.type: FUNC
1857  * @tc.require:
1858  * @tc.author: tankaisheng
1859  */
1860 HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync014, TestSize.Level1)
1861 {
1862     /**
1863      * @tc.steps: step1. Create device table and cloud table in COLLABORATION
1864      * @tc.expected: step1.ok
1865      */
1866     ASSERT_NO_FATAL_FAILURE(InitDelegate());
1867     auto schema = GetSchema();
1868     auto distributedSchema = RDBDataGenerator::ParseSchema(schema, true);
1869     deviceB_->SetDistributedSchema(distributedSchema);
1870     EXPECT_EQ(delegate_->CreateDistributedTable(DEVICE_SYNC_TABLE, TableSyncType::DEVICE_COOPERATION), OK);
1871     DistributedSchema schema1 = GetDistributedSchema(DEVICE_SYNC_TABLE, {"int_field1"});
1872     EXPECT_EQ(delegate_->SetDistributedSchema(schema1), OK);
1873     LOGI("[DistributedDBCloudAsyncDownloadAssetsTest] CreateDistributedTable %s", DEVICE_COOPERATION);
1874     /**
1875      * @tc.steps: step2. Insert data
1876      * @tc.expected: step2.ok
1877      */
1878     auto tableSchema = GetTableSchema();
1879     ASSERT_EQ(RDBDataGenerator::InsertVirtualLocalDBData(0, 10, deviceB_, tableSchema), E_OK);
1880     ASSERT_EQ(RDBDataGenerator::PrepareVirtualDeviceEnv(tableSchema.name, db_, deviceB_), E_OK);
1881     /**
1882      * @tc.steps: step3. Sync to real device
1883      * @tc.expected: step3.ok
1884      */
1885     Query query = Query::Select(tableSchema.name);
1886     DistributedDBToolsUnitTest::BlockSync(*delegate_, query, SYNC_MODE_PULL_ONLY, OK, {deviceB_->GetDeviceId()});
1887     /**
1888      * @tc.steps: step4. check changData
1889      * @tc.expected: step4.ok
1890      */
1891     auto changeData = delegateObserver_->GetSavedChangedData();
1892     EXPECT_EQ(changeData[tableSchema.name].primaryData[0].size(), 10u);
1893     EXPECT_EQ(changeData[tableSchema.name].field.size(), 1u);
1894     /**
1895      * @tc.steps: step5. SetDistributedSchema again
1896      * @tc.expected: step5.ok
1897      */
1898     DistributedSchema schema2 = GetDistributedSchema(DEVICE_SYNC_TABLE, {"int_field1", "int_field2"});
1899     EXPECT_EQ(delegate_->SetDistributedSchema(schema2), OK);
1900     /**
1901      * @tc.steps: step6. Sync to real device
1902      * @tc.expected: step6.ok
1903      */
1904     DistributedDBToolsUnitTest::BlockSync(*delegate_, query, SYNC_MODE_PULL_ONLY, OK, {deviceB_->GetDeviceId()});
1905     /**
1906      * @tc.steps: step7. check changData
1907      * @tc.expected: step7.ok
1908      */
1909     changeData = delegateObserver_->GetSavedChangedData();
1910     EXPECT_EQ(changeData[tableSchema.name].primaryData[1].size(), 10u);
1911     EXPECT_EQ(changeData[tableSchema.name].field.size(), 1u);
1912 }
1913 
1914 /**
1915  * @tc.name: NormalSync015
1916  * @tc.desc: Test sync with multi primary key table.
1917  * @tc.type: FUNC
1918  * @tc.require:
1919  * @tc.author: liaoyonghuang
1920  */
1921 HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync015, TestSize.Level1)
1922 {
1923     /**
1924      * @tc.steps: step1. Create device table and cloud table in COLLABORATION
1925      * @tc.expected: step1.ok
1926      */
1927     ASSERT_NO_FATAL_FAILURE(InitDelegate());
1928     std::string tableName = "multiPriKeyTable";
1929     std::string sql = "CREATE TABLE IF NOT EXISTS " + tableName +
1930         "(pk1 INTEGER, pk2 INT, PRIMARY KEY (pk1, pk2));";
1931     ASSERT_EQ(SQLiteUtils::ExecuteRawSQL(db_, sql), E_OK);
1932     /**
1933      * @tc.steps: step2. Create distributed table and set distributed schema
1934      * @tc.expected: step2.ok
1935      */
1936     auto distributedSchema = GetDistributedSchema(tableName, {"pk1", "pk2"});
1937     deviceB_->SetDistributedSchema(distributedSchema);
1938     EXPECT_EQ(delegate_->CreateDistributedTable(tableName, TableSyncType::DEVICE_COOPERATION), OK);
1939     EXPECT_EQ(delegate_->SetDistributedSchema(distributedSchema), OK);
1940     /**
1941      * @tc.steps: step3. Init data and sync to real device
1942      * @tc.expected: step3.ok
1943      */
1944     TableSchema tableSchema;
1945     tableSchema.name = tableName;
1946     Field field;
1947     field.primary = true;
1948     field.type = TYPE_INDEX<int64_t>;
1949     field.colName = "pk1";
1950     tableSchema.fields.push_back(field);
1951     field.colName = "pk2";
1952     tableSchema.fields.push_back(field);
1953     uint32_t dataCount = 10;
1954     ASSERT_EQ(RDBDataGenerator::InsertVirtualLocalDBData(0, dataCount, deviceB_, tableSchema), E_OK);
1955     ASSERT_EQ(RDBDataGenerator::PrepareVirtualDeviceEnv(tableName, db_, deviceB_), E_OK);
1956     Query query = Query::Select(tableName);
1957     DistributedDBToolsUnitTest::BlockSync(*delegate_, query, SYNC_MODE_PULL_ONLY, OK, {deviceB_->GetDeviceId()});
1958     /**
1959      * @tc.steps: step4. check changData
1960      * @tc.expected: step4.ok
1961      */
1962     auto changeData = delegateObserver_->GetSavedChangedData();
1963     ASSERT_EQ(changeData[tableName].primaryData[OP_INSERT].size(), dataCount);
1964     for (uint32_t i = 0; i < dataCount; i++) {
1965         EXPECT_EQ(changeData[tableName].primaryData[OP_INSERT][i].size(), 3u); // primary key (pk1, pk2) and rowid
1966     }
1967     EXPECT_EQ(changeData[tableName].field.size(), 3u); // primary key (pk1, pk2) and rowid
1968     /**
1969      * @tc.steps: step5. Remove the last item and a cloud-only item, then check changeData
1970      * @tc.expected: step5. Only the last item is in changeData and field is key (pk1, pk2) and rowid
1971      */
1972     delegateObserver_->ClearChangedData();
1973     ASSERT_EQ(RDBDataGenerator::InsertVirtualLocalDBData(dataCount - 1, dataCount + 1, deviceB_, tableSchema, true),
1974         E_OK);
1975     DistributedDBToolsUnitTest::BlockSync(*delegate_, query, SYNC_MODE_PULL_ONLY, OK, {deviceB_->GetDeviceId()});
1976     changeData = delegateObserver_->GetSavedChangedData();
1977     ASSERT_EQ(changeData[tableName].primaryData[OP_DELETE].size(), 1u);
1978     EXPECT_EQ(changeData[tableName].primaryData[OP_DELETE][0].size(), 3u); // primary key (pk1, pk2) and rowid
1979     EXPECT_EQ(changeData[tableName].field.size(), 3u); // primary key (pk1, pk2) and rowid
1980 }
1981 
1982 /**
1983  * @tc.name: NormalSync016
1984  * @tc.desc: Test sync with diff specified field.
1985  * @tc.type: FUNC
1986  * @tc.require:
1987  * @tc.author: zqq
1988  */
1989 HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync016, TestSize.Level1)
1990 {
1991     /**
1992      * @tc.steps: step1. Prepare db, tableMode is COLLABORATION
1993      * @tc.expected: step1.ok
1994      */
1995     ASSERT_NO_FATAL_FAILURE(InitDelegate(DistributedTableMode::COLLABORATION));
1996     std::string createSql = "CREATE TABLE IF NOT EXISTS table_int(integer_field INTEGER PRIMARY KEY AUTOINCREMENT,"
1997         "int_field1 INT UNIQUE, int_field2 INT UNIQUE);";
1998     ASSERT_EQ(SQLiteUtils::ExecuteRawSQL(db_, createSql), E_OK);
1999     EXPECT_EQ(delegate_->CreateDistributedTable("table_int", TableSyncType::DEVICE_COOPERATION), OK);
2000 
2001     /**
2002      * @tc.steps: step2. Test mark one specified one is field1 another is field2
2003      * @tc.expected: step2. sync return SCHEMA_MISMATCH
2004      */
2005     DistributedSchema distributedSchema = {0, {{"table_int", {
2006         {"integer_field", false, false},
2007         {"int_field1", true, false},
2008         {"int_field2", true, true}}}}};
2009     EXPECT_EQ(delegate_->SetDistributedSchema(distributedSchema), OK);
2010     distributedSchema = {0, {{"table_int", {
2011         {"integer_field", false, false},
2012         {"int_field1", true, true},
2013         {"int_field2", true, false}}}}};
2014     deviceB_->SetDistributedSchema(distributedSchema);
2015     ASSERT_EQ(RDBDataGenerator::PrepareVirtualDeviceEnv("table_int", db_, deviceB_), E_OK);
2016     Query query = Query::Select("table_int");
2017     DistributedDBToolsUnitTest::BlockSync(*delegate_, query, SYNC_MODE_PULL_ONLY, SCHEMA_MISMATCH,
2018         {deviceB_->GetDeviceId()});
2019     DistributedDBToolsUnitTest::BlockSync(*delegate_, query, SYNC_MODE_PUSH_ONLY, SCHEMA_MISMATCH,
2020         {deviceB_->GetDeviceId()});
2021 }
2022 
2023 /**
2024  * @tc.name: NormalSync017
2025  * @tc.desc: Test delete other device's data and sync
2026  * @tc.type: FUNC
2027  * @tc.require:
2028  * @tc.author: liaoyonghuang
2029  */
2030 HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync017, TestSize.Level1)
2031 {
2032     /**
2033      * @tc.steps: step1. Create device table and cloud table in COLLABORATION
2034      * @tc.expected: step1.ok
2035      */
2036     ASSERT_NO_FATAL_FAILURE(InitDelegate());
2037     auto schema = GetSchema();
2038     auto distributedSchema = RDBDataGenerator::ParseSchema(schema, true);
2039     EXPECT_EQ(delegate_->CreateDistributedTable(DEVICE_SYNC_TABLE, TableSyncType::DEVICE_COOPERATION), OK);
2040     deviceB_->SetDistributedSchema(distributedSchema);
2041     EXPECT_EQ(delegate_->SetDistributedSchema(distributedSchema), OK);
2042     /**
2043      * @tc.steps: step2. Insert one data
2044      * @tc.expected: step2.ok
2045      */
2046     auto tableSchema = GetTableSchema();
2047     ASSERT_EQ(RDBDataGenerator::InsertVirtualLocalDBData(0, 1, deviceB_, tableSchema), E_OK);
2048     ASSERT_EQ(RDBDataGenerator::PrepareVirtualDeviceEnv(tableSchema.name, db_, deviceB_), E_OK);
2049     /**
2050      * @tc.steps: step3. Sync to real device
2051      * @tc.expected: step3.ok
2052      */
2053     Query query = Query::Select(tableSchema.name);
2054     DistributedDBToolsUnitTest::BlockSync(*delegate_, query, SYNC_MODE_PULL_ONLY, OK, {deviceB_->GetDeviceId()});
2055     std::string sql = std::string("select count(*) from ").append(DEVICE_SYNC_TABLE);
2056     int count = 0;
2057     EXPECT_EQ(SQLiteUtils::GetCountBySql(db_, sql, count), E_OK);
2058     EXPECT_EQ(count, 1);
2059     /**
2060      * @tc.steps: step4. Delete data and sync again
2061      * @tc.expected: step4.ok
2062      */
2063     EXPECT_EQ(RDBDataGenerator::InsertVirtualLocalDBData(0, 1, deviceB_, tableSchema), E_OK);
2064     std::this_thread::sleep_for(std::chrono::milliseconds(100)); // sleep 100 ms
2065     sql = std::string("delete from ").append(DEVICE_SYNC_TABLE).append(" where 0 = 0");
2066     EXPECT_EQ(SQLiteUtils::ExecuteRawSQL(db_, sql), E_OK);
2067     DistributedDBToolsUnitTest::BlockSync(*delegate_, query, SYNC_MODE_PULL_ONLY, OK, {deviceB_->GetDeviceId()});
2068     sql = std::string("select count(*) from ").append(DEVICE_SYNC_TABLE);
2069     count = 0;
2070     EXPECT_EQ(SQLiteUtils::GetCountBySql(db_, sql, count), E_OK);
2071     EXPECT_EQ(count, 0);
2072     auto changeData = delegateObserver_->GetSavedChangedData()[std::string(DEVICE_SYNC_TABLE)];
2073     EXPECT_TRUE(changeData.properties.isP2pSyncDataChange);
2074 }
2075 
2076 /**
2077  * @tc.name: NormalSync018
2078  * @tc.desc: Test sync with no primary key table.
2079  * @tc.type: FUNC
2080  * @tc.require:
2081  * @tc.author: liaoyonghuang
2082  */
2083 HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync018, TestSize.Level1)
2084 {
2085     /**
2086      * @tc.steps: step1. Create device table and cloud table in COLLABORATION
2087      * @tc.expected: step1.ok
2088      */
2089     ASSERT_NO_FATAL_FAILURE(InitDelegate());
2090     std::string tableName = "noPriKeyTable";
2091     std::string sql = "CREATE TABLE IF NOT EXISTS " + tableName + "(pk1 INTEGER, pk2 INT);";
2092     ASSERT_EQ(SQLiteUtils::ExecuteRawSQL(db_, sql), E_OK);
2093     /**
2094      * @tc.steps: step2. Create distributed table and set distributed schema
2095      * @tc.expected: step2.ok
2096      */
2097     auto distributedSchema = GetDistributedSchema(tableName, {"pk1", "pk2"});
2098     deviceB_->SetDistributedSchema(distributedSchema);
2099     EXPECT_EQ(delegate_->CreateDistributedTable(tableName, TableSyncType::DEVICE_COOPERATION), OK);
2100     EXPECT_EQ(delegate_->SetDistributedSchema(distributedSchema), OK);
2101     /**
2102      * @tc.steps: step3. Init data and sync to real device
2103      * @tc.expected: step3.ok
2104      */
2105     TableSchema tableSchema;
2106     tableSchema.name = tableName;
2107     Field field;
2108     field.primary = true;
2109     field.type = TYPE_INDEX<int64_t>;
2110     field.colName = "pk1";
2111     tableSchema.fields.push_back(field);
2112     field.colName = "pk2";
2113     tableSchema.fields.push_back(field);
2114     uint32_t dataCount = 10;
2115     ASSERT_EQ(RDBDataGenerator::InsertVirtualLocalDBData(0, dataCount, deviceB_, tableSchema), E_OK);
2116     ASSERT_EQ(RDBDataGenerator::PrepareVirtualDeviceEnv(tableName, db_, deviceB_), E_OK);
2117     Query query = Query::Select(tableName);
2118     DistributedDBToolsUnitTest::BlockSync(*delegate_, query, SYNC_MODE_PULL_ONLY, OK, {deviceB_->GetDeviceId()});
2119     /**
2120      * @tc.steps: step4. check changData
2121      * @tc.expected: step4.ok
2122      */
2123     auto changeData = delegateObserver_->GetSavedChangedData();
2124     ASSERT_EQ(changeData[tableName].primaryData[OP_INSERT].size(), dataCount);
2125     for (uint32_t i = 0; i < dataCount; i++) {
2126         EXPECT_EQ(changeData[tableName].primaryData[OP_INSERT][i].size(), 1u); // rowid
2127     }
2128     EXPECT_EQ(changeData[tableName].field.size(), 1u); // rowid
2129 }
2130 
2131 /**
2132  * @tc.name: NormalSync019
2133  * @tc.desc: Test whether there is an observer notification when local win.
2134  * @tc.type: FUNC
2135  * @tc.require:
2136  * @tc.author: liaoyonghuang
2137  */
2138 HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync019, TestSize.Level1)
2139 {
2140     /**
2141      * @tc.steps: step1. Create device table and cloud table in COLLABORATION
2142      * @tc.expected: step1.ok
2143      */
2144     ASSERT_NO_FATAL_FAILURE(InitDelegate());
2145     auto schema = GetSchema();
2146     auto distributedSchema = RDBDataGenerator::ParseSchema(schema, true);
2147     EXPECT_EQ(delegate_->CreateDistributedTable(DEVICE_SYNC_TABLE, TableSyncType::DEVICE_COOPERATION), OK);
2148     deviceB_->SetDistributedSchema(distributedSchema);
2149     EXPECT_EQ(delegate_->SetDistributedSchema(distributedSchema), OK);
2150     /**
2151      * @tc.steps: step2. Insert a piece of data from the other end and then locally insert the same data.
2152      * @tc.expected: step2.ok
2153      */
2154     auto tableSchema = GetTableSchema();
2155     ASSERT_EQ(RDBDataGenerator::InsertVirtualLocalDBData(0, 1, deviceB_, tableSchema), E_OK);
2156     ASSERT_EQ(RDBDataGenerator::PrepareVirtualDeviceEnv(tableSchema.name, db_, deviceB_), E_OK);
2157     std::string sql = std::string("insert into ").append(DEVICE_SYNC_TABLE).append("(pk) values (0)");
2158     EXPECT_EQ(SQLiteUtils::ExecuteRawSQL(db_, sql), E_OK);
2159     /**
2160      * @tc.steps: step3. Sync to real device
2161      * @tc.expected: step3.ok
2162      */
2163     Query query = Query::Select(tableSchema.name);
2164     DistributedDBToolsUnitTest::BlockSync(*delegate_, query, SYNC_MODE_PULL_ONLY, OK, {deviceB_->GetDeviceId()});
2165     /**
2166      * @tc.steps: step4. Check observer
2167      * @tc.expected: step4.No data change notification
2168      */
2169     auto onChangeCallCount = delegateObserver_->GetCloudCallCount();
2170     EXPECT_EQ(onChangeCallCount, 0u);
2171 }
2172 
2173 /**
2174  * @tc.name: NormalSync020
2175  * @tc.desc: Test set distributed schema after recreating the table.
2176  * @tc.type: FUNC
2177  * @tc.require:
2178  * @tc.author: liaoyonghuang
2179  */
2180 HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync020, TestSize.Level1)
2181 {
2182     /**
2183      * @tc.steps: step1. Create device table and cloud table in COLLABORATION
2184      * @tc.expected: step1.ok
2185      */
2186     ASSERT_NO_FATAL_FAILURE(InitDelegate());
2187     auto schema = GetSchema();
2188     auto distributedSchema = RDBDataGenerator::ParseSchema(schema, true);
2189     EXPECT_EQ(delegate_->CreateDistributedTable(DEVICE_SYNC_TABLE, TableSyncType::DEVICE_COOPERATION), OK);
2190     deviceB_->SetDistributedSchema(distributedSchema);
2191     EXPECT_EQ(delegate_->SetDistributedSchema(distributedSchema), OK);
2192     /**
2193      * @tc.steps: step2. Sync a piece of data
2194      * @tc.expected: step2.ok
2195      */
2196     auto tableSchema = GetTableSchema();
2197     ASSERT_EQ(RDBDataGenerator::InsertVirtualLocalDBData(0, 1, deviceB_, tableSchema), E_OK);
2198     ASSERT_EQ(RDBDataGenerator::PrepareVirtualDeviceEnv(tableSchema.name, db_, deviceB_), E_OK);
2199     Query query = Query::Select(tableSchema.name);
2200     DistributedDBToolsUnitTest::BlockSync(*delegate_, query, SYNC_MODE_PULL_ONLY, OK, {deviceB_->GetDeviceId()});
2201     /**
2202      * @tc.steps: step3. Recreate table and set distributed schema.
2203      * @tc.expected: step3.ok
2204      */
2205     std::string sql = std::string("drop table ").append(DEVICE_SYNC_TABLE);
2206     EXPECT_EQ(SQLiteUtils::ExecuteRawSQL(db_, sql), E_OK);
2207     RDBDataGenerator::InitTable(schema.tables.front(), false, *db_);
2208     EXPECT_EQ(delegate_->CreateDistributedTable(DEVICE_SYNC_TABLE, TableSyncType::DEVICE_COOPERATION), OK);
2209     EXPECT_EQ(delegate_->SetDistributedSchema(distributedSchema), OK);
2210 }
2211 
2212 /**
2213  * @tc.name: NormalSync021
2214  * @tc.desc: Test sync multi table.
2215  * @tc.type: FUNC
2216  * @tc.require:
2217  * @tc.author: liaoyonghuang
2218  */
2219 HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync021, TestSize.Level1)
2220 {
2221     /**
2222      * @tc.steps: step1. Create device table and cloud table in COLLABORATION
2223      * @tc.expected: step1.ok
2224      */
2225     ASSERT_NO_FATAL_FAILURE(InitDelegate());
2226     auto schema = GetSchema();
2227     auto distributedSchema = RDBDataGenerator::ParseSchema(schema, true);
2228     deviceB_->SetDistributedSchema(distributedSchema);
2229     EXPECT_EQ(delegate_->SetDistributedSchema(distributedSchema), OK);
2230     EXPECT_EQ(delegate_->CreateDistributedTable(DEVICE_SYNC_TABLE, TableSyncType::DEVICE_COOPERATION), OK);
2231     EXPECT_EQ(delegate_->CreateDistributedTable(DEVICE_SYNC_TABLE_UPGRADE, TableSyncType::DEVICE_COOPERATION), OK);
2232     /**
2233      * @tc.steps: step2. Insert 10 data
2234      * @tc.expected: step2.ok
2235      */
2236     int dataCount = 10;
2237     auto tableSchema = GetTableSchema();
2238     ASSERT_EQ(RDBDataGenerator::InsertVirtualLocalDBData(0, dataCount, deviceB_, tableSchema), E_OK);
2239     ASSERT_EQ(RDBDataGenerator::PrepareVirtualDeviceEnv(tableSchema.name, db_, deviceB_), E_OK);
2240     tableSchema = GetTableSchema(true);
2241     ASSERT_EQ(RDBDataGenerator::InsertVirtualLocalDBData(0, dataCount, deviceB_, tableSchema), E_OK);
2242     ASSERT_EQ(RDBDataGenerator::PrepareVirtualDeviceEnv(tableSchema.name, db_, deviceB_), E_OK);
2243     /**
2244      * @tc.steps: step3. Sync to real device and check data
2245      * @tc.expected: step3.ok
2246      */
2247     Query query = Query::Select().FromTable({DEVICE_SYNC_TABLE, DEVICE_SYNC_TABLE_UPGRADE});
2248     DistributedDBToolsUnitTest::BlockSync(*delegate_, query, SYNC_MODE_PULL_ONLY, OK, {deviceB_->GetDeviceId()});
2249     std::string sql = std::string("select count(*) from ").append(DEVICE_SYNC_TABLE);
2250     int actualCount = 0;
2251     SQLiteUtils::GetCountBySql(db_, sql, actualCount);
2252     EXPECT_EQ(actualCount, dataCount);
2253     sql = std::string("select count(*) from ").append(DEVICE_SYNC_TABLE_UPGRADE);
2254     actualCount = 0;
2255     SQLiteUtils::GetCountBySql(db_, sql, actualCount);
2256     EXPECT_EQ(actualCount, dataCount);
2257     /**
2258      * @tc.steps: step4. Sync with invalid args
2259      * @tc.expected: step4.invalid args
2260      */
2261     query.And();
2262     DBStatus callStatus = delegate_->Sync({deviceB_->GetDeviceId()}, SYNC_MODE_PUSH_ONLY, query, nullptr, true);
2263     EXPECT_EQ(callStatus, NOT_SUPPORT);
2264 }
2265 
2266 /**
2267  * @tc.name: NormalSync022
2268  * @tc.desc: Test drop table after sync.
2269  * @tc.type: FUNC
2270  * @tc.require:
2271  * @tc.author: liaoyonghuang
2272  */
2273 HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync022, TestSize.Level1)
2274 {
2275     /**
2276      * @tc.steps: step1. Create device table and cloud table in COLLABORATION
2277      * @tc.expected: step1.ok
2278      */
2279     ASSERT_NO_FATAL_FAILURE(InitDelegate());
2280     std::string tableName = "noPriKeyTable";
2281     std::string sql = "CREATE TABLE IF NOT EXISTS " + tableName + "(field1 INTEGER, field2 INT);";
2282     ASSERT_EQ(SQLiteUtils::ExecuteRawSQL(db_, sql), E_OK);
2283     auto distributedSchema = GetDistributedSchema(tableName, {"field1", "field2"});
2284     deviceB_->SetDistributedSchema(distributedSchema);
2285     EXPECT_EQ(delegate_->CreateDistributedTable(tableName, TableSyncType::DEVICE_COOPERATION), OK);
2286     EXPECT_EQ(delegate_->SetDistributedSchema(distributedSchema), OK);
2287     /**
2288      * @tc.steps: step2. Insert one piece of data at each end
2289      * @tc.expected: step2.ok
2290      */
2291     TableSchema tableSchema = {tableName, "", {{"field1", TYPE_INDEX<int64_t>}, {"field2", TYPE_INDEX<int64_t>}}};
2292     ASSERT_EQ(RDBDataGenerator::InsertVirtualLocalDBData(0, 1, deviceB_, tableSchema), E_OK);
2293     ASSERT_EQ(RDBDataGenerator::PrepareVirtualDeviceEnv(tableSchema.name, db_, deviceB_), E_OK);
2294     sql = "insert into " + tableName + " values(1, 1)";
2295     EXPECT_EQ(SQLiteUtils::ExecuteRawSQL(db_, sql), E_OK);
2296     std::string checkLogCountSql = "select count(*) from " + DBCommon::GetLogTableName(tableName);
2297     std::string checkDataCountSql = "select count(*) from " + tableName;
2298     int logCount = 0;
2299     int dataCount = 0;
2300     EXPECT_EQ(SQLiteUtils::GetCountBySql(db_, checkLogCountSql, logCount), E_OK);
2301     EXPECT_EQ(SQLiteUtils::GetCountBySql(db_, checkDataCountSql, dataCount), E_OK);
2302     EXPECT_EQ(logCount, 1);
2303     EXPECT_EQ(dataCount, 1);
2304     /**
2305      * @tc.steps: step3. Sync a piece of data
2306      * @tc.expected: step3.ok
2307      */
2308     Query query = Query::Select(tableSchema.name);
2309     DistributedDBToolsUnitTest::BlockSync(*delegate_, query, SYNC_MODE_PULL_ONLY, OK, {deviceB_->GetDeviceId()});
2310     EXPECT_EQ(SQLiteUtils::GetCountBySql(db_, checkLogCountSql, logCount), E_OK);
2311     EXPECT_EQ(SQLiteUtils::GetCountBySql(db_, checkDataCountSql, dataCount), E_OK);
2312     EXPECT_EQ(dataCount, 2);
2313     EXPECT_EQ(logCount, 2);
2314     /**
2315      * @tc.steps: step4. Drop table and check log count
2316      * @tc.expected: step4.ok
2317      */
2318     checkLogCountSql.append(" where data_key = -1 and flag&0x01 = 0x1;");
2319     EXPECT_EQ(SQLiteUtils::GetCountBySql(db_, checkLogCountSql, logCount), E_OK);
2320     EXPECT_EQ(logCount, 0);
2321     std::string dropTableSql = "drop table " + tableName;
2322     EXPECT_EQ(SQLiteUtils::ExecuteRawSQL(db_, dropTableSql), E_OK);
2323     EXPECT_EQ(SQLiteUtils::GetCountBySql(db_, checkLogCountSql, logCount), E_OK);
2324     EXPECT_EQ(logCount, 2);
2325 }
2326 
2327 /**
2328  * @tc.name: NormalSync023
2329  * @tc.desc: Test synchronization of autoIncremental primary key table with observer notices.
2330  * @tc.type: FUNC
2331  * @tc.require:
2332  * @tc.author: liaoyonghuang
2333  */
2334 HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync023, TestSize.Level1)
2335 {
2336     /**
2337      * @tc.steps: step1. Create device table and cloud table in COLLABORATION
2338      * @tc.expected: step1.ok
2339      */
2340     ASSERT_NO_FATAL_FAILURE(InitDelegate());
2341     std::string tableName = "autoIncPriKeyTable";
2342     std::string sql = "CREATE TABLE IF NOT EXISTS " + tableName +
2343         "(pk INTEGER PRIMARY KEY AUTOINCREMENT, field1 INT UNIQUE);";
2344     ASSERT_EQ(SQLiteUtils::ExecuteRawSQL(db_, sql), E_OK);
2345     DistributedSchema distributedSchema = {0u, {{tableName, {{"pk", false, false}, {"field1", true, true}}}}};
2346     deviceB_->SetDistributedSchema(distributedSchema);
2347     EXPECT_EQ(delegate_->CreateDistributedTable(tableName, TableSyncType::DEVICE_COOPERATION), OK);
2348     EXPECT_EQ(delegate_->SetDistributedSchema(distributedSchema), OK);
2349     /**
2350      * @tc.steps: step2. Insert data
2351      * @tc.expected: step2.ok
2352      */
2353     uint32_t dataCount = 10;
2354     TableSchema tableSchema = {tableName, "", {{"pk", TYPE_INDEX<int64_t>, true}, {"field1", TYPE_INDEX<int64_t>}}};
2355     ASSERT_EQ(RDBDataGenerator::InsertVirtualLocalDBData(0, dataCount, deviceB_, tableSchema), E_OK);
2356     ASSERT_EQ(RDBDataGenerator::PrepareVirtualDeviceEnv(tableSchema.name, db_, deviceB_), E_OK);
2357     /**
2358      * @tc.steps: step3. Sync to real device and check data
2359      * @tc.expected: step3.ok
2360      */
2361     Query query = Query::Select(tableName);
2362     DistributedDBToolsUnitTest::BlockSync(*delegate_, query, SYNC_MODE_PULL_ONLY, OK, {deviceB_->GetDeviceId()});
2363     /**
2364      * @tc.steps: step4. check changData
2365      * @tc.expected: step4.ok
2366      */
2367     auto changeData = delegateObserver_->GetSavedChangedData();
2368     ASSERT_EQ(changeData[tableName].primaryData[OP_INSERT].size(), dataCount);
2369     for (uint32_t i = 0; i < changeData[tableName].primaryData[OP_INSERT].size(); i++) {
2370         auto *data = std::get_if<int64_t>(&changeData[tableName].primaryData[OP_INSERT][i].front());
2371         ASSERT_NE(data, nullptr);
2372         EXPECT_EQ(static_cast<uint32_t>(*data), i + 1);
2373     }
2374     ASSERT_EQ(changeData[tableName].field.size(), 1u);
2375     EXPECT_EQ(changeData[tableName].field.front(), "pk");
2376 }
2377 
2378 /**
2379  * @tc.name: NormalSync024
2380  * @tc.desc: Test set tracker table and sync.
2381  * @tc.type: FUNC
2382  * @tc.require:
2383  * @tc.author: lg
2384  */
2385 HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync024, TestSize.Level1)
2386 {
2387     /**
2388      * @tc.steps: step1. Create device table and cloud table in COLLABORATION
2389      * @tc.expected: step1.ok
2390      */
2391     ASSERT_NO_FATAL_FAILURE(InitDelegate());
2392     auto schema = GetSchema();
2393     auto distributedSchema = RDBDataGenerator::ParseSchema(schema, true);
2394     deviceB_->SetDistributedSchema(distributedSchema);
2395     EXPECT_EQ(delegate_->SetDistributedSchema(distributedSchema), OK);
2396     EXPECT_EQ(delegate_->CreateDistributedTable(DEVICE_SYNC_TABLE, TableSyncType::DEVICE_COOPERATION), OK);
2397     EXPECT_EQ(delegate_->CreateDistributedTable(DEVICE_SYNC_TABLE_UPGRADE, TableSyncType::DEVICE_COOPERATION), OK);
2398 
2399     TrackerSchema trackerSchema = {
2400         .tableName = DEVICE_SYNC_TABLE, .extendColNames = {"int_field1"}, .trackerColNames = {"int_field1"}};
2401     delegate_->SetTrackerTable(trackerSchema);
2402 
2403     /**
2404      * @tc.steps: step2. close deviceA and reopen it
2405      * @tc.expected: step2.ok
2406      */
2407     RelationalStoreManager mgr(APP_ID, USER_ID);
2408     EXPECT_EQ(mgr.CloseStore(delegate_), OK);
2409     delegate_ = nullptr;
2410     RelationalStoreDelegate::Option option;
2411     option.tableMode = DistributedTableMode::COLLABORATION;
2412     option.observer = delegateObserver_;
2413     ASSERT_EQ(mgr.OpenStore(storePath_, STORE_ID_1, option, delegate_), OK);
2414     ASSERT_NE(delegate_, nullptr);
2415 
2416     /**
2417      * @tc.steps: step3. Insert 10 data
2418      * @tc.expected: step3.ok
2419      */
2420     int dataCount = 10;
2421     auto tableSchema = GetTableSchema();
2422     ASSERT_EQ(RDBDataGenerator::InsertVirtualLocalDBData(0, dataCount, deviceB_, tableSchema), E_OK);
2423     ASSERT_EQ(RDBDataGenerator::PrepareVirtualDeviceEnv(tableSchema.name, db_, deviceB_), E_OK);
2424     tableSchema = GetTableSchema(true);
2425     ASSERT_EQ(RDBDataGenerator::InsertVirtualLocalDBData(0, dataCount, deviceB_, tableSchema), E_OK);
2426     ASSERT_EQ(RDBDataGenerator::PrepareVirtualDeviceEnv(tableSchema.name, db_, deviceB_), E_OK);
2427     /**
2428      * @tc.steps: step4. Sync to real device and check data
2429      * @tc.expected: step4.ok
2430      */
2431     Query query = Query::Select().FromTable({DEVICE_SYNC_TABLE, DEVICE_SYNC_TABLE_UPGRADE});
2432     DistributedDBToolsUnitTest::BlockSync(*delegate_, query, SYNC_MODE_PULL_ONLY, OK, {deviceB_->GetDeviceId()});
2433     std::string checkLogCountSql = std::string("SELECT COUNT(*) FROM ") + DBCommon::GetLogTableName(DEVICE_SYNC_TABLE) +
2434                                    " AS a LEFT JOIN " + DEVICE_SYNC_TABLE +
2435                                    " AS b  ON (a.data_key = b._rowid_) WHERE a.data_key = b._rowid_;";
2436     int logCount = 0;
2437     EXPECT_EQ(SQLiteUtils::GetCountBySql(db_, checkLogCountSql, logCount), E_OK);
2438     EXPECT_EQ(logCount, 10);
2439 }
2440 
2441 /**
2442  * @tc.name: NormalSync025
2443  * @tc.desc: Test drop table in split_by_device mode will only mark local data as delete in log table
2444  * @tc.type: FUNC
2445  * @tc.require:
2446  * @tc.author: liuhongyang
2447  */
2448 HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync025, TestSize.Level1)
2449 {
2450     /**
2451      * @tc.steps: step1. Create SPLIT_BY_DEVICE tables
2452      * @tc.expected: step1. Ok
2453      */
2454     ASSERT_NO_FATAL_FAILURE(InitDelegate(DistributedTableMode::SPLIT_BY_DEVICE));
2455     std::string tableName = "noPKTable025";
2456     std::string createTableSql = "CREATE TABLE IF NOT EXISTS " + tableName + "(field1 INTEGER, field2 INT);";
2457     ASSERT_EQ(SQLiteUtils::ExecuteRawSQL(db_, createTableSql), E_OK);
2458     EXPECT_EQ(delegate_->CreateDistributedTable(tableName, TableSyncType::DEVICE_COOPERATION), OK);
2459     /**
2460      * @tc.steps: step2. Insert one piece of data at each end
2461      * @tc.expected: step2. Ok
2462      */
2463     TableSchema tableSchema = {tableName, "", {{"field1", TYPE_INDEX<int64_t>}, {"field2", TYPE_INDEX<int64_t>}}};
2464     ASSERT_EQ(RDBDataGenerator::InsertVirtualLocalDBData(0, 1, deviceB_, tableSchema), E_OK);
2465     ASSERT_EQ(RDBDataGenerator::PrepareVirtualDeviceEnv(tableSchema.name, db_, deviceB_), E_OK);
2466     std::string sql = "insert into " + tableName + " values(1, 1)";
2467     EXPECT_EQ(SQLiteUtils::ExecuteRawSQL(db_, sql), E_OK);
2468     std::string checkLogCountSql = "select count(*) from " + DBCommon::GetLogTableName(tableName);
2469     std::string checkDataCountSql = "select count(*) from " + tableName;
2470     int logCount = 0;
2471     int dataCount = 0;
2472     EXPECT_EQ(SQLiteUtils::GetCountBySql(db_, checkLogCountSql, logCount), E_OK);
2473     EXPECT_EQ(SQLiteUtils::GetCountBySql(db_, checkDataCountSql, dataCount), E_OK);
2474     EXPECT_EQ(logCount, 1);
2475     EXPECT_EQ(dataCount, 1);
2476     /**
2477      * @tc.steps: step3. Sync to pull deviceB_ data
2478      * @tc.expected: step3. One data in device table and one data in local table
2479      */
2480     Query query = Query::Select(tableSchema.name);
2481     DistributedDBToolsUnitTest::BlockSync(*delegate_, query, SYNC_MODE_PULL_ONLY, OK, {deviceB_->GetDeviceId()});
2482     EXPECT_EQ(SQLiteUtils::GetCountBySql(db_, checkLogCountSql, logCount), E_OK);
2483     EXPECT_EQ(SQLiteUtils::GetCountBySql(db_, checkDataCountSql, dataCount), E_OK);
2484     EXPECT_EQ(dataCount, 1);
2485     EXPECT_EQ(logCount, 2);
2486     std::string checkDeviceTableCountSql = "select count(*) from " +
2487         DBCommon::GetDistributedTableName(deviceB_->GetDeviceId(), tableName);
2488     int deviceDataCount = 0;
2489     EXPECT_EQ(SQLiteUtils::GetCountBySql(db_, checkDeviceTableCountSql, deviceDataCount), E_OK);
2490     EXPECT_EQ(deviceDataCount, 1);
2491     /**
2492      * @tc.steps: step4. Check delete count in log table before drop
2493      * @tc.expected: step4. No deleted records
2494      */
2495     checkLogCountSql.append(" where data_key = -1 and flag&0x01 = 0x1;");
2496     EXPECT_EQ(SQLiteUtils::GetCountBySql(db_, checkLogCountSql, logCount), E_OK);
2497     EXPECT_EQ(logCount, 0);
2498     /**
2499      * @tc.steps: step5. Drop table and recreate
2500      * @tc.expected: step5. Ok
2501      */
2502     std::string dropTableSql = "drop table " + tableName;
2503     EXPECT_EQ(SQLiteUtils::ExecuteRawSQL(db_, dropTableSql), E_OK);
2504     ASSERT_EQ(SQLiteUtils::ExecuteRawSQL(db_, createTableSql), E_OK);
2505     EXPECT_EQ(delegate_->CreateDistributedTable(tableName, TableSyncType::DEVICE_COOPERATION), OK);
2506     /**
2507      * @tc.steps: step6. Check count
2508      * @tc.expected: step6. only the local record is marked as deleted
2509      */
2510     EXPECT_EQ(SQLiteUtils::GetCountBySql(db_, checkLogCountSql, logCount), E_OK);
2511     EXPECT_EQ(SQLiteUtils::GetCountBySql(db_, checkDataCountSql, dataCount), E_OK);
2512     EXPECT_EQ(SQLiteUtils::GetCountBySql(db_, checkDeviceTableCountSql, deviceDataCount), E_OK);
2513     EXPECT_EQ(logCount, 1);
2514     EXPECT_EQ(dataCount, 0);
2515     EXPECT_EQ(deviceDataCount, 1);
2516 }
2517 
2518 /**
2519  * @tc.name: SetStoreConfig001
2520  * @tc.desc: Test set store config.
2521  * @tc.type: FUNC
2522  * @tc.require:
2523  * @tc.author: liaoyonghuang
2524  */
2525 HWTEST_F(DistributedDBRDBCollaborationTest, SetStoreConfig001, TestSize.Level1)
2526 {
2527     /**
2528      * @tc.steps: step1. Create device table and cloud table in SPLIT_BY_DEVICE
2529      * @tc.expected: step1.ok
2530      */
2531     ASSERT_NO_FATAL_FAILURE(InitDelegate(DistributedTableMode::SPLIT_BY_DEVICE));
2532     /**
2533      * @tc.steps: step2. Set store config.
2534      * @tc.expected: step2.ok
2535      */
2536     EXPECT_EQ(delegate_->SetStoreConfig({DistributedTableMode::COLLABORATION}), OK);
2537     auto schema = GetSchema();
2538     auto distributedSchema = RDBDataGenerator::ParseSchema(schema, true);
2539     deviceB_->SetDistributedSchema(distributedSchema);
2540     EXPECT_EQ(delegate_->CreateDistributedTable(DEVICE_SYNC_TABLE, TableSyncType::DEVICE_COOPERATION), OK);
2541     EXPECT_EQ(delegate_->SetDistributedSchema(distributedSchema), OK);
2542     /**
2543      * @tc.steps: step3. Sync to real device
2544      * @tc.expected: step3.ok
2545      */
2546     auto tableSchema = GetTableSchema();
2547     ASSERT_EQ(RDBDataGenerator::InsertVirtualLocalDBData(0, 10, deviceB_, tableSchema), E_OK);
2548     ASSERT_EQ(RDBDataGenerator::PrepareVirtualDeviceEnv(tableSchema.name, db_, deviceB_), E_OK);
2549     Query query = Query::Select(tableSchema.name);
2550     DistributedDBToolsUnitTest::BlockSync(*delegate_, query, SYNC_MODE_PULL_ONLY, OK, {deviceB_->GetDeviceId()});
2551 }
2552 
2553 /**
2554  * @tc.name: SetStoreConfig002
2555  * @tc.desc: Test set store config after create distributed table.
2556  * @tc.type: FUNC
2557  * @tc.require:
2558  * @tc.author: liaoyonghuang
2559  */
2560 HWTEST_F(DistributedDBRDBCollaborationTest, SetStoreConfig002, TestSize.Level0)
2561 {
2562     /**
2563      * @tc.steps: step1. Create device table and cloud table in SPLIT_BY_DEVICE
2564      * @tc.expected: step1.ok
2565      */
2566     ASSERT_NO_FATAL_FAILURE(InitDelegate(DistributedTableMode::SPLIT_BY_DEVICE));
2567     EXPECT_EQ(delegate_->CreateDistributedTable(DEVICE_SYNC_TABLE, TableSyncType::DEVICE_COOPERATION), OK);
2568     /**
2569      * @tc.steps: step2. Set store config.
2570      * @tc.expected: step2. return not support
2571      */
2572     EXPECT_EQ(delegate_->SetStoreConfig({DistributedTableMode::COLLABORATION}), NOT_SUPPORT);
2573 }
2574 
2575 /**
2576  * @tc.name: SetStoreConfig003
2577  * @tc.desc: Test set store config after create distributed table.
2578  * @tc.type: FUNC
2579  * @tc.require:
2580  * @tc.author: lg
2581  */
2582 HWTEST_F(DistributedDBRDBCollaborationTest, SetStoreConfig003, TestSize.Level0)
2583 {
2584     /**
2585      * @tc.steps: step1. Create device table and cloud table in COLLABORATION
2586      * @tc.expected: step1.ok
2587      */
2588     ASSERT_NO_FATAL_FAILURE(InitDelegate(DistributedTableMode::COLLABORATION));
2589     EXPECT_EQ(delegate_->CreateDistributedTable(DEVICE_SYNC_TABLE, TableSyncType::DEVICE_COOPERATION), OK);
2590     /**
2591      * @tc.steps: step2. Set store config.
2592      * @tc.expected: step2. return not support
2593      */
2594     EXPECT_EQ(delegate_->SetStoreConfig({DistributedTableMode::SPLIT_BY_DEVICE}), NOT_SUPPORT);
2595 }
2596 
2597 /**
2598  * @tc.name: SetStoreConfig004
2599  * @tc.desc: Test properties for concurrent get and set operations
2600  * @tc.type: FUNC
2601  * @tc.require:
2602  * @tc.author: bty
2603  */
2604 HWTEST_F(DistributedDBRDBCollaborationTest, SetStoreConfig004, TestSize.Level2)
2605 {
2606     /**
2607      * @tc.steps: step1. Create device table and cloud table in SPLIT_BY_DEVICE
2608      * @tc.expected: step1.ok
2609      */
2610     ASSERT_NO_FATAL_FAILURE(InitDelegate(DistributedTableMode::SPLIT_BY_DEVICE));
2611     /**
2612      * @tc.steps: step2. Set store config.
2613      * @tc.expected: step2.ok
2614      */
2615     EXPECT_EQ(delegate_->SetStoreConfig({DistributedTableMode::COLLABORATION}), OK);
2616     auto schema = GetSchema();
2617     auto distributedSchema = RDBDataGenerator::ParseSchema(schema, true);
2618     deviceB_->SetDistributedSchema(distributedSchema);
2619     EXPECT_EQ(delegate_->CreateDistributedTable(DEVICE_SYNC_TABLE, TableSyncType::DEVICE_COOPERATION), OK);
2620     EXPECT_EQ(delegate_->SetDistributedSchema(distributedSchema), OK);
2621     /**
2622      * @tc.steps: step3. check for concurrent interface calls
2623      * @tc.expected: step3.ok
2624      */
__anond430f6f20502() 2625     std::thread t1([this, distributedSchema]() {
2626         for (size_t i = 0; i < 10000; i++) {
2627             EXPECT_EQ(delegate_->SetDistributedSchema(distributedSchema), OK);
2628         }
2629     });
__anond430f6f20602() 2630     std::thread t2([this, distributedSchema]() {
2631         for (size_t i = 0; i < 10000; i++) {
2632             EXPECT_EQ(delegate_->SetStoreConfig({DistributedTableMode::COLLABORATION}), OK);
2633         }
2634     });
2635     t1.join();
2636     t2.join();
2637 }
2638 
2639 /**
2640  * @tc.name: InvalidSync001
2641  * @tc.desc: Test remote set empty distributed schema and sync.
2642  * @tc.type: FUNC
2643  * @tc.require:
2644  * @tc.author: bty
2645  */
2646 HWTEST_F(DistributedDBRDBCollaborationTest, InvalidSync001, TestSize.Level1)
2647 {
2648     /**
2649      * @tc.steps: step1. Remote device set empty distributed schema
2650      * @tc.expected: step1.ok
2651      */
2652     ASSERT_NO_FATAL_FAILURE(InitDelegate());
2653     auto schema = GetSchema();
2654     auto distributedSchema = RDBDataGenerator::ParseSchema(schema, true);
2655     EXPECT_EQ(delegate_->CreateDistributedTable(DEVICE_SYNC_TABLE, TableSyncType::DEVICE_COOPERATION), OK);
2656     LOGI("[DistributedDBCloudAsyncDownloadAssetsTest] CreateDistributedTable %s", DEVICE_SYNC_TABLE);
2657     DistributedSchema emptySchema;
2658     deviceB_->SetDistributedSchema(emptySchema);
2659     EXPECT_EQ(delegate_->SetDistributedSchema(distributedSchema), OK);
2660     /**
2661      * @tc.steps: step2. Insert one data
2662      * @tc.expected: step2.ok
2663      */
2664     auto tableSchema = GetTableSchema();
2665     EXPECT_EQ(RDBDataGenerator::InsertLocalDBData(0, 1, db_, GetTableSchema()), E_OK);
2666     ASSERT_EQ(RDBDataGenerator::PrepareVirtualDeviceEnv(tableSchema.name, db_, deviceB_), E_OK);
2667     /**
2668      * @tc.steps: step3. Sync to real device
2669      * @tc.expected: step3.SCHEMA_MISMATCH
2670      */
2671     Query query = Query::Select(tableSchema.name);
2672     DistributedDBToolsUnitTest::BlockSync(*delegate_, query, SYNC_MODE_PUSH_ONLY, SCHEMA_MISMATCH,
2673         {deviceB_->GetDeviceId()});
2674     /**
2675      * @tc.steps: step4. Remove device data
2676      * @tc.expected: step4. NOT_SUPPORT
2677      */
2678     EXPECT_EQ(delegate_->RemoveDeviceData("dev", DEVICE_SYNC_TABLE), NOT_SUPPORT);
2679     EXPECT_EQ(delegate_->RemoveDeviceData(), NOT_SUPPORT);
2680     EXPECT_EQ(delegate_->RemoveDeviceData("dev", ClearMode::DEFAULT), NOT_SUPPORT);
2681 }
2682 
2683 /**
2684  * @tc.name: InvalidSync002
2685  * @tc.desc: Test remote set distributed schema but table is not exist then sync.
2686  * @tc.type: FUNC
2687  * @tc.require:
2688  * @tc.author: tankaisheng
2689  */
2690 HWTEST_F(DistributedDBRDBCollaborationTest, InvalidSync002, TestSize.Level0)
2691 {
2692     /**
2693      * @tc.steps: step1. Remote device set distributed schema but table is not exist
2694      * @tc.expected: step1.ok
2695      */
2696     ASSERT_NO_FATAL_FAILURE(InitDelegate());
2697     auto schema = GetSchema();
2698     auto distributedSchema = RDBDataGenerator::ParseSchema(schema, true);
2699     EXPECT_EQ(delegate_->CreateDistributedTable(DEVICE_SYNC_TABLE, TableSyncType::DEVICE_COOPERATION), OK);
2700     LOGI("[DistributedDBCloudAsyncDownloadAssetsTest] CreateDistributedTable %s", DEVICE_SYNC_TABLE);
2701     EXPECT_EQ(delegate_->SetDistributedSchema(distributedSchema), OK);
2702     DistributedSchema distributedSchema1;
2703     deviceB_->SetDistributedSchema(distributedSchema1);
2704     /**
2705      * @tc.steps: step2. Insert one data
2706      * @tc.expected: step2.ok
2707      */
2708     auto tableSchema = GetTableSchema();
2709     EXPECT_EQ(RDBDataGenerator::InsertLocalDBData(0, 1, db_, GetTableSchema()), E_OK);
2710     ASSERT_EQ(RDBDataGenerator::PrepareVirtualDeviceEnv(tableSchema.name, db_, deviceB_), E_OK);
2711     /**
2712      * @tc.steps: step3. Sync to real device
2713      * @tc.expected: step3.SCHEMA_MISMATCH
2714      */
2715     Query query = Query::Select(DEVICE_SYNC_TABLE);
2716     DistributedDBToolsUnitTest::BlockSync(*delegate_, query, SYNC_MODE_PUSH_ONLY, SCHEMA_MISMATCH,
2717         {deviceB_->GetDeviceId()});
2718 }
2719 
2720 /**
2721  * @tc.name: InvalidSync003
2722  * @tc.desc: Test sync of deletion when the deleted data has log locally but not found in the actual data table
2723  * @tc.type: FUNC
2724  * @tc.require:
2725  * @tc.author: liuhongyang
2726  */
2727 HWTEST_F(DistributedDBRDBCollaborationTest, InvalidSync003, TestSize.Level0)
2728 {
2729     /**
2730      * @tc.steps: step1. Create device table and cloud table in COLLABORATION
2731      * @tc.expected: step1.ok
2732      */
2733     ASSERT_NO_FATAL_FAILURE(InitDelegate());
2734     auto schema = GetSchema();
2735     auto distributedSchema = RDBDataGenerator::ParseSchema(schema, true);
2736     deviceB_->SetDistributedSchema(distributedSchema);
2737     EXPECT_EQ(delegate_->CreateDistributedTable(DEVICE_SYNC_TABLE, TableSyncType::DEVICE_COOPERATION), OK);
2738     EXPECT_EQ(delegate_->SetDistributedSchema(distributedSchema), OK);
2739     LOGI("[DistributedDBCloudAsyncDownloadAssetsTest] CreateDistributedTable %s", DEVICE_SYNC_TABLE);
2740     /**
2741      * @tc.steps: step2. Insert 10 data
2742      * @tc.expected: step2.ok
2743      */
2744     auto tableSchema = GetTableSchema();
2745     ASSERT_EQ(RDBDataGenerator::InsertVirtualLocalDBData(0, 10, deviceB_, tableSchema), E_OK);
2746     ASSERT_EQ(RDBDataGenerator::PrepareVirtualDeviceEnv(tableSchema.name, db_, deviceB_), E_OK);
2747     /**
2748      * @tc.steps: step3. Sync to real device to make data consistent
2749      * @tc.expected: step3.ok
2750      */
2751     Query query = Query::Select(tableSchema.name);
2752     DistributedDBToolsUnitTest::BlockSync(*delegate_, query, SYNC_MODE_PULL_ONLY, OK, {deviceB_->GetDeviceId()});
2753     /**
2754      * @tc.steps: step4. Stop writing into log table and remove the first record locally
2755      * @tc.expected: step4. ok and the target scenario is created
2756      */
2757     std::string sql = "INSERT OR REPLACE INTO " + std::string(DBConstant::RELATIONAL_PREFIX) + "metadata" +
2758         " VALUES ('log_trigger_switch', 'false');";
2759     EXPECT_EQ(SQLiteUtils::ExecuteRawSQL(db_, sql), E_OK);
2760     sql = "DELETE FROM " + std::string(DEVICE_SYNC_TABLE) + " WHERE pk = 0;";
2761     EXPECT_EQ(SQLiteUtils::ExecuteRawSQL(db_, sql), E_OK);
2762     sql = "INSERT OR REPLACE INTO " + std::string(DBConstant::RELATIONAL_PREFIX) + "metadata" +
2763         " VALUES ('log_trigger_switch', 'true');";
2764     EXPECT_EQ(SQLiteUtils::ExecuteRawSQL(db_, sql), E_OK);
2765     /**
2766      * @tc.steps: step5. Delete the first data in virtual device and sync to deviceB_
2767      * @tc.expected: step5. ok
2768      */
2769     delegateObserver_->ClearChangedData();
2770     ASSERT_EQ(RDBDataGenerator::InsertVirtualLocalDBData(0, 1, deviceB_, tableSchema, true), E_OK);
2771     DistributedDBToolsUnitTest::BlockSync(*delegate_, query, SYNC_MODE_PULL_ONLY, OK, {deviceB_->GetDeviceId()});
2772     /**
2773      * @tc.steps: step6. check changeData
2774      * @tc.expected: step6. OP_DELETE has one record but the record is empty
2775      */
2776     auto changeData = delegateObserver_->GetSavedChangedData();
2777     ASSERT_EQ(changeData[tableSchema.name].primaryData[OP_DELETE].size(), 1u);
2778     EXPECT_EQ(changeData[tableSchema.name].primaryData[OP_DELETE][0].size(), 0u);
2779     ASSERT_EQ(changeData[tableSchema.name].field.size(), 1u);
2780     EXPECT_EQ(changeData[tableSchema.name].field[0], "pk");
2781 }
2782 
2783 /**
2784  * @tc.name: InvalidSync004
2785  * @tc.desc: Test sync with empty tables
2786  * @tc.type: FUNC
2787  * @tc.require:
2788  * @tc.author: liaoyonghuang
2789  */
2790 HWTEST_F(DistributedDBRDBCollaborationTest, InvalidSync004, TestSize.Level0)
2791 {
2792     ASSERT_NO_FATAL_FAILURE(InitDelegate());
2793     Query query = Query::Select().FromTable({});
2794     DBStatus callStatus = delegate_->Sync({deviceB_->GetDeviceId()}, SYNC_MODE_PUSH_ONLY, query, nullptr, true);
2795     EXPECT_EQ(callStatus, INVALID_ARGS);
2796 }
2797 
2798 /**
2799  * @tc.name: InvalidSync005
2800  * @tc.desc: Test error returned by the other end during sync
2801  * @tc.type: FUNC
2802  * @tc.require:
2803  * @tc.author: liaoyonghuang
2804  */
2805 HWTEST_F(DistributedDBRDBCollaborationTest, InvalidSync005, TestSize.Level1)
2806 {
2807     /**
2808      * @tc.steps: step1. Create device table and cloud table in COLLABORATION
2809      * @tc.expected: step1.ok
2810      */
2811     ASSERT_NO_FATAL_FAILURE(InitDelegate());
2812     auto schema = GetSchema();
2813     auto distributedSchema = RDBDataGenerator::ParseSchema(schema, true);
2814     deviceB_->SetDistributedSchema(distributedSchema);
2815     EXPECT_EQ(delegate_->SetDistributedSchema(distributedSchema), OK);
2816     EXPECT_EQ(delegate_->CreateDistributedTable(DEVICE_SYNC_TABLE, TableSyncType::DEVICE_COOPERATION), OK);
2817     /**
2818      * @tc.steps: step2. Prepare device B
2819      * @tc.expected: step2.ok
2820      */
2821     int dataCount = 10;
2822     auto tableSchema = GetTableSchema();
2823     ASSERT_EQ(RDBDataGenerator::InsertVirtualLocalDBData(0, dataCount, deviceB_, tableSchema), E_OK);
2824     ASSERT_EQ(RDBDataGenerator::PrepareVirtualDeviceEnv(tableSchema.name, db_, deviceB_), E_OK);
2825     /**
2826      * @tc.steps: step3. Set return E_DISTRIBUTED_SCHEMA_NOT_FOUND when get sync data in device B
2827      * @tc.expected: step3.ok
2828      */
2829     deviceB_->SetGetSyncDataResult(-E_DISTRIBUTED_SCHEMA_NOT_FOUND);
2830     /**
2831      * @tc.steps: step4. Sync
2832      * @tc.expected: step4. return SCHEMA_MISMATCH
2833      */
2834     Query query = Query::Select().FromTable({DEVICE_SYNC_TABLE});
2835     DistributedDBToolsUnitTest::BlockSync(*delegate_, query, SYNC_MODE_PULL_ONLY, SCHEMA_MISMATCH,
2836         {deviceB_->GetDeviceId()});
2837 }
2838 
2839 /**
2840  * @tc.name: InvalidSync006
2841  * @tc.desc: Test FromTable and other predicates are combined when sync
2842  * @tc.type: FUNC
2843  * @tc.require:
2844  * @tc.author: liaoyonghuang
2845  */
2846 HWTEST_F(DistributedDBRDBCollaborationTest, InvalidSync006, TestSize.Level0)
2847 {
2848     /**
2849      * @tc.steps: step1. Create device table and cloud table in COLLABORATION
2850      * @tc.expected: step1.ok
2851      */
2852     ASSERT_NO_FATAL_FAILURE(InitDelegate());
2853     auto schema = GetSchema();
2854     auto distributedSchema = RDBDataGenerator::ParseSchema(schema, true);
2855     deviceB_->SetDistributedSchema(distributedSchema);
2856     EXPECT_EQ(delegate_->SetDistributedSchema(distributedSchema), OK);
2857     EXPECT_EQ(delegate_->CreateDistributedTable(DEVICE_SYNC_TABLE, TableSyncType::DEVICE_COOPERATION), OK);
2858     /**
2859      * @tc.steps: step2. Prepare device B
2860      * @tc.expected: step2.ok
2861      */
2862     int dataCount = 10;
2863     auto tableSchema = GetTableSchema();
2864     ASSERT_EQ(RDBDataGenerator::InsertVirtualLocalDBData(0, dataCount, deviceB_, tableSchema), E_OK);
2865     ASSERT_EQ(RDBDataGenerator::PrepareVirtualDeviceEnv(tableSchema.name, db_, deviceB_), E_OK);
2866     /**
2867      * @tc.steps: step3. Prepare query list
2868      * @tc.expected: step3.ok
2869      */
2870     std::set<Key> keys = {{1}, {2}, {3}};
2871     std::vector<int> values = {1, 2, 3};
2872     std::vector<Query> queryList = {
2873         Query::Select().FromTable({DEVICE_SYNC_TABLE}).BeginGroup().EqualTo("pk", 1),
2874         Query::Select().FromTable({DEVICE_SYNC_TABLE}).EqualTo("pk", 1),
2875         Query::Select().FromTable({DEVICE_SYNC_TABLE}).GreaterThan("pk", 1),
2876         Query::Select().FromTable({DEVICE_SYNC_TABLE}).GreaterThanOrEqualTo("pk", 1),
2877         Query::Select().FromTable({DEVICE_SYNC_TABLE}).In("pk", values),
2878         Query::Select().FromTable({DEVICE_SYNC_TABLE}).NotIn("pk", values),
2879         Query::Select().FromTable({DEVICE_SYNC_TABLE}).IsNotNull("pk"),
2880         Query::Select().FromTable({DEVICE_SYNC_TABLE}).LessThan("pk", 1),
2881         Query::Select().FromTable({DEVICE_SYNC_TABLE}).LessThanOrEqualTo("pk", 1),
2882         Query::Select().FromTable({DEVICE_SYNC_TABLE}).Like("pk", "abc"),
2883         Query::Select().FromTable({DEVICE_SYNC_TABLE}).NotLike("pk", "abc"),
2884         Query::Select().FromTable({DEVICE_SYNC_TABLE}).OrderByWriteTime(false),
2885         Query::Select().FromTable({DEVICE_SYNC_TABLE}).SuggestIndex("pk"),
2886         Query::Select().FromTable({DEVICE_SYNC_TABLE}).PrefixKey({1, 2, 3}),
2887         Query::Select().FromTable({DEVICE_SYNC_TABLE}).InKeys(keys)
2888     };
2889     /**
2890      * @tc.steps: step4. Sync
2891      * @tc.expected: step4. return NOT_SUPPORT
2892      */
2893     for (const auto &query : queryList) {
2894         DBStatus callStatus = delegate_->Sync({deviceB_->GetDeviceId()}, SYNC_MODE_PUSH_ONLY, query, nullptr, true);
2895         EXPECT_EQ(callStatus, NOT_SUPPORT);
2896     }
2897 }
2898 }