1 /*
2 * Copyright (c) 2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "rdb_general_ut.h"
17
18 namespace DistributedDB {
19 using namespace testing::ext;
20 using namespace DistributedDB;
21 using namespace DistributedDBUnitTest;
22
23 class DistributedDBRDBMultiUserSyncTest : public RDBGeneralUt {
24 public:
25 void SetUp() override;
26 protected:
27 static constexpr const char *DEVICE_SYNC_TABLE = "DEVICE_SYNC_TABLE";
28 static constexpr const char *DEVICE_A = "DEVICE_A";
29 static constexpr const char *DEVICE_B = "DEVICE_B";
30 static constexpr const char *USER_ID_1 = "userId1";
31 static constexpr const char *USER_ID_2 = "userId2";
32 static UtDateBaseSchemaInfo GetDefaultSchema();
33 static UtTableSchemaInfo GetTableSchema(const std::string &table, bool noPk = false);
34 static void SetTargetUserId(const std::string &deviceId, const std::string &userId);
35 };
36
SetUp()37 void DistributedDBRDBMultiUserSyncTest::SetUp()
38 {
39 RDBGeneralUt::SetUp();
40 RelationalStoreDelegate::Option option;
41 option.syncDualTupleMode = true;
42 option.tableMode = DistributedTableMode::COLLABORATION;
43 SetOption(option);
44 }
45
GetDefaultSchema()46 UtDateBaseSchemaInfo DistributedDBRDBMultiUserSyncTest::GetDefaultSchema()
47 {
48 UtDateBaseSchemaInfo info;
49 info.tablesInfo.push_back(GetTableSchema(DEVICE_SYNC_TABLE));
50 return info;
51 }
52
GetTableSchema(const std::string & table,bool noPk)53 UtTableSchemaInfo DistributedDBRDBMultiUserSyncTest::GetTableSchema(const std::string &table, bool noPk)
54 {
55 UtTableSchemaInfo tableSchema;
56 tableSchema.name = table;
57 UtFieldInfo fieldId;
58 fieldId.field.colName = "id";
59 fieldId.field.type = TYPE_INDEX<int64_t>;
60 if (!noPk) {
61 fieldId.field.primary = true;
62 }
63 tableSchema.fieldInfo.push_back(fieldId);
64 UtFieldInfo fieldName;
65 fieldName.field.colName = "name";
66 fieldName.field.type = TYPE_INDEX<std::string>;
67 tableSchema.fieldInfo.push_back(fieldName);
68 return tableSchema;
69 }
70
SetTargetUserId(const std::string & deviceId,const std::string & userId)71 void DistributedDBRDBMultiUserSyncTest::SetTargetUserId(const std::string &deviceId, const std::string &userId)
72 {
73 ICommunicatorAggregator *communicatorAggregator = nullptr;
74 RuntimeContext::GetInstance()->GetCommunicatorAggregator(communicatorAggregator);
75 ASSERT_NE(communicatorAggregator, nullptr);
76 auto virtualCommunicatorAggregator = static_cast<VirtualCommunicatorAggregator*>(communicatorAggregator);
77 auto communicator = static_cast<VirtualCommunicator*>(virtualCommunicatorAggregator->GetCommunicator(deviceId));
78 ASSERT_NE(communicator, nullptr);
79 communicator->SetTargetUserId(userId);
80 }
81
82 HWTEST_F(DistributedDBRDBMultiUserSyncTest, NormalSyncTest001, TestSize.Level0)
83 {
84 /**
85 * @tc.steps: step1. Prepare db and data.
86 * @tc.expected: step1. Ok
87 */
88 StoreInfo deviceAStore1 = {USER_ID_1, APP_ID, STORE_ID_1};
89 StoreInfo deviceAStore2 = {USER_ID_2, APP_ID, STORE_ID_2};
90 StoreInfo deviceBStore = {USER_ID_1, APP_ID, STORE_ID_3};
91
92 SetSchemaInfo(deviceAStore1, GetDefaultSchema());
93 SetSchemaInfo(deviceAStore2, GetDefaultSchema());
94 SetSchemaInfo(deviceBStore, GetDefaultSchema());
95
96 ASSERT_EQ(BasicUnitTest::InitDelegate(deviceAStore1, DEVICE_A), E_OK);
97 ASSERT_EQ(BasicUnitTest::InitDelegate(deviceAStore2, DEVICE_A), E_OK);
98 ASSERT_EQ(BasicUnitTest::InitDelegate(deviceBStore, DEVICE_B), E_OK);
99
100 ASSERT_EQ(SetDistributedTables(deviceAStore1, {DEVICE_SYNC_TABLE}), E_OK);
101 ASSERT_EQ(SetDistributedTables(deviceAStore2, {DEVICE_SYNC_TABLE}), E_OK);
102 ASSERT_EQ(SetDistributedTables(deviceBStore, {DEVICE_SYNC_TABLE}), E_OK);
103
104 InsertLocalDBData(0, 1, deviceAStore1);
105 InsertLocalDBData(0, 1, deviceAStore2);
106 sqlite3 *dbA2 = GetSqliteHandle(deviceAStore2);
107 std::string updateSql = "update " + std::string(DEVICE_SYNC_TABLE) + " set name = 'new_name' where id = 0;";
108 ASSERT_EQ(SQLiteUtils::ExecuteRawSQL(dbA2, updateSql), E_OK);
109
110 ASSERT_EQ(RDBGeneralUt::CloseDelegate(deviceAStore1), OK);
111 ASSERT_EQ(RDBGeneralUt::CloseDelegate(deviceAStore2), OK);
112 /**
113 * @tc.steps: step2. Sync from db2 of deviceA to deviceB.
114 * @tc.expected: step2. Ok
115 */
116 ASSERT_EQ(BasicUnitTest::InitDelegate(deviceAStore2, DEVICE_A), E_OK);
117 SetTargetUserId(DEVICE_A, USER_ID_1);
118 SetTargetUserId(DEVICE_B, USER_ID_2);
119 BlockPush(deviceAStore2, deviceBStore, DEVICE_SYNC_TABLE);
120 ASSERT_EQ(RDBGeneralUt::CloseDelegate(deviceAStore2), OK);
121 /**
122 * @tc.steps: step3. Sync from db1 of deviceA to deviceB.
123 * @tc.expected: step3. Ok
124 */
125 ASSERT_EQ(BasicUnitTest::InitDelegate(deviceAStore1, DEVICE_A), E_OK);
126 SetTargetUserId(DEVICE_A, USER_ID_1);
127 SetTargetUserId(DEVICE_B, USER_ID_1);
128 BlockPush(deviceAStore1, deviceBStore, DEVICE_SYNC_TABLE);
129 ASSERT_EQ(RDBGeneralUt::CloseDelegate(deviceAStore1), OK);
130 /**
131 * @tc.steps: step4. Check data in deviceB.
132 * @tc.expected: step4. Ok
133 */
134 std::string checkSql = "select count(*) from " + std::string(DEVICE_SYNC_TABLE) + " where name = 'new_name';";
135 sqlite3 *dbB = GetSqliteHandle(deviceBStore);
136 int actualCount = 0;
137 ASSERT_EQ(SQLiteUtils::GetCountBySql(dbB, checkSql, actualCount), E_OK);
138 EXPECT_EQ(actualCount, 1);
139 ASSERT_EQ(RDBGeneralUt::CloseDelegate(deviceBStore), OK);
140 }
141 }