• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <gtest/gtest.h>
17 
18 #include "cloud/cloud_db_types.h"
19 #include "db_common.h"
20 #include "db_constant.h"
21 #include "distributeddb_data_generate_unit_test.h"
22 #include "distributeddb_tools_unit_test.h"
23 #include "relational_store_delegate_impl.h"
24 #include "relational_store_manager.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     constexpr const char *DB_SUFFIX = ".db";
34     constexpr const char *STORE_ID = "Relational_Store_ID";
35     std::string g_testDir;
36     std::string g_dbDir;
37     std::string g_storePath;
38     DistributedDB::RelationalStoreManager g_mgr(APP_ID, USER_ID);
39     RelationalStoreDelegate *g_delegate = nullptr;
40     VirtualCommunicatorAggregator *g_communicatorAggregator = nullptr;
41 
42     class DistributedDBCloudInterfacesReferenceTest : public testing::Test {
43     public:
44         static void SetUpTestCase(void);
45         static void TearDownTestCase(void);
46         void SetUp();
47         void TearDown();
48     };
49 
SetUpTestCase(void)50     void DistributedDBCloudInterfacesReferenceTest::SetUpTestCase(void)
51     {
52         DistributedDBToolsUnitTest::TestDirInit(g_testDir);
53         LOGD("Test dir is %s", g_testDir.c_str());
54         g_dbDir = g_testDir + "/";
55         g_storePath = g_dbDir + STORE_ID + DB_SUFFIX;
56         DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir);
57     }
58 
TearDownTestCase(void)59     void DistributedDBCloudInterfacesReferenceTest::TearDownTestCase(void)
60     {
61     }
62 
SetUp(void)63     void DistributedDBCloudInterfacesReferenceTest::SetUp(void)
64     {
65         g_communicatorAggregator = new (std::nothrow) VirtualCommunicatorAggregator();
66         ASSERT_TRUE(g_communicatorAggregator != nullptr);
67         RuntimeContext::GetInstance()->SetCommunicatorAggregator(g_communicatorAggregator);
68         sqlite3 *db = RelationalTestUtils::CreateDataBase(g_storePath);
69         ASSERT_NE(db, nullptr);
70         EXPECT_EQ(RelationalTestUtils::ExecSql(db, "PRAGMA journal_mode=WAL;"), SQLITE_OK);
71         EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK);
72 
73         DBStatus status = g_mgr.OpenStore(g_storePath, STORE_ID, {}, g_delegate);
74         EXPECT_EQ(status, OK);
75         ASSERT_NE(g_delegate, nullptr);
76     }
77 
TearDown(void)78     void DistributedDBCloudInterfacesReferenceTest::TearDown(void)
79     {
80         EXPECT_EQ(g_mgr.CloseStore(g_delegate), OK);
81         g_delegate = nullptr;
82         DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir);
83         RuntimeContext::GetInstance()->SetCommunicatorAggregator(nullptr);
84     }
85 
86     /**
87      * @tc.name: SetReferenceTest001
88      * @tc.desc: Test empty args for set reference interface
89      * @tc.type: FUNC
90      * @tc.require:
91      * @tc.author: zhangshjie
92      */
93     HWTEST_F(DistributedDBCloudInterfacesReferenceTest, SetReferenceTest001, TestSize.Level0)
94     {
95         /**
96          * @tc.steps:step1. call SetReference with empty TableReferenceProperty
97          * @tc.expected: step1. Return INVALID_ARGS.
98          */
99         EXPECT_EQ(g_delegate->SetReference({}), OK);
100         TableReferenceProperty tableReferenceProperty;
101         EXPECT_EQ(g_delegate->SetReference({tableReferenceProperty}), INVALID_ARGS);
102         std::string sourceTableName = "sourceTable";
103         std::string targetTableName = "targetTable";
104         tableReferenceProperty.sourceTableName = sourceTableName;
105         EXPECT_EQ(g_delegate->SetReference({tableReferenceProperty}), INVALID_ARGS);
106         tableReferenceProperty.sourceTableName = "";
107         tableReferenceProperty.targetTableName = targetTableName;
108         EXPECT_EQ(g_delegate->SetReference({tableReferenceProperty}), INVALID_ARGS);
109         tableReferenceProperty.targetTableName = "";
110         std::map<std::string, std::string> columns;
111         columns["col1"] = "col2";
112         tableReferenceProperty.columns = columns;
113         EXPECT_EQ(g_delegate->SetReference({tableReferenceProperty}), INVALID_ARGS);
114 
115         tableReferenceProperty.sourceTableName = sourceTableName;
116         tableReferenceProperty.targetTableName = targetTableName;
117         tableReferenceProperty.columns = {};
118         EXPECT_EQ(g_delegate->SetReference({tableReferenceProperty}), INVALID_ARGS);
119         tableReferenceProperty.sourceTableName = "";
120         tableReferenceProperty.targetTableName = targetTableName;
121         tableReferenceProperty.columns = columns;
122         EXPECT_EQ(g_delegate->SetReference({tableReferenceProperty}), INVALID_ARGS);
123         tableReferenceProperty.sourceTableName = sourceTableName;
124         tableReferenceProperty.targetTableName = "";
125         tableReferenceProperty.columns = columns;
126         EXPECT_EQ(g_delegate->SetReference({tableReferenceProperty}), INVALID_ARGS);
127     }
128 
129     /**
130      * @tc.name: SetReferenceTest002
131      * @tc.desc: Test set two reference for same two tables
132      * @tc.type: FUNC
133      * @tc.require:
134      * @tc.author: zhangshjie
135      */
136     HWTEST_F(DistributedDBCloudInterfacesReferenceTest, SetReferenceTest002, TestSize.Level0)
137     {
138         /**
139          * @tc.steps:step1. call SetReference with two TableReferenceProperty which sourceTableName and targetTableName
140          * are both same
141          * @tc.expected: step1. Return INVALID_ARGS.
142          */
143         TableReferenceProperty tableReferenceProperty;
144         std::string sourceTableName = "sourceTable";
145         std::string targetTableName = "targetTable";
146         tableReferenceProperty.sourceTableName = sourceTableName;
147         tableReferenceProperty.targetTableName = targetTableName;
148         std::map<std::string, std::string> columns;
149         columns["col1"] = "col2";
150         tableReferenceProperty.columns = columns;
151         EXPECT_EQ(g_delegate->SetReference({tableReferenceProperty, tableReferenceProperty}), INVALID_ARGS);
152 
153         TableReferenceProperty tableReferenceProperty2;
154         tableReferenceProperty2.sourceTableName = "sourceTableName1";
155         tableReferenceProperty2.targetTableName = targetTableName;
156         tableReferenceProperty2.columns = columns;
157         EXPECT_EQ(g_delegate->SetReference({tableReferenceProperty, tableReferenceProperty2, tableReferenceProperty}),
158             INVALID_ARGS);
159     }
160 
161     /**
162      * @tc.name: SetReferenceTest003
163      * @tc.desc: Test simple circular dependency
164      * @tc.type: FUNC
165      * @tc.require:
166      * @tc.author: zhangshjie
167      */
168     HWTEST_F(DistributedDBCloudInterfacesReferenceTest, SetReferenceTest003, TestSize.Level0)
169     {
170         /**
171          * @tc.steps:step1. call SetReference with circular dependency(A->B->A)
172          * @tc.expected: step1. Return INVALID_ARGS.
173          */
174         TableReferenceProperty referenceAB;
175         referenceAB.sourceTableName = "ta";
176         referenceAB.targetTableName = "tb";
177         std::map<std::string, std::string> columns;
178         columns["col1"] = "col2";
179         referenceAB.columns = columns;
180 
181         TableReferenceProperty referenceBA;
182         referenceBA.sourceTableName = "tb";
183         referenceBA.targetTableName = "ta";
184         referenceBA.columns = columns;
185         EXPECT_EQ(g_delegate->SetReference({referenceAB, referenceBA}), INVALID_ARGS);
186 
187         /**
188          * @tc.steps:step2. call SetReference with circular dependency(A->B->C->A)
189          * @tc.expected: step1. Return INVALID_ARGS.
190          */
191         TableReferenceProperty referenceBC;
192         referenceBC.sourceTableName = "tb";
193         referenceBC.targetTableName = "tc";
194         referenceBC.columns = columns;
195 
196         TableReferenceProperty referenceCA;
197         referenceCA.sourceTableName = "tc";
198         referenceCA.targetTableName = "ta";
199         referenceCA.columns = columns;
200 
201         EXPECT_EQ(g_delegate->SetReference({referenceAB, referenceBC, referenceCA}), INVALID_ARGS);
202         EXPECT_EQ(g_delegate->SetReference({referenceCA, referenceAB, referenceBC}), INVALID_ARGS);
203     }
204 
205     /**
206      * @tc.name: SetReferenceTest004
207      * @tc.desc: Test complicated circular dependency
208      * @tc.type: FUNC
209      * @tc.require:
210      * @tc.author: zhangshjie
211      */
212     HWTEST_F(DistributedDBCloudInterfacesReferenceTest, SetReferenceTest004, TestSize.Level0)
213     {
214         /**
215          * @tc.steps:step1. call SetReference with complicated dependency
216          * @tc.expected: step1. Return INVALID_ARGS.
217          */
218         TableReferenceProperty referenceAB;
219         referenceAB.sourceTableName = "ta";
220         referenceAB.targetTableName = "tb";
221         std::map<std::string, std::string> columns;
222         columns["col1"] = "col2";
223         referenceAB.columns = columns;
224 
225         TableReferenceProperty referenceDE;
226         referenceDE.sourceTableName = "td";
227         referenceDE.targetTableName = "te";
228         referenceDE.columns = columns;
229 
230         TableReferenceProperty referenceAC;
231         referenceAC.sourceTableName = "ta";
232         referenceAC.targetTableName = "tc";
233         referenceAC.columns = columns;
234 
235         TableReferenceProperty referenceEF;
236         referenceEF.sourceTableName = "te";
237         referenceEF.targetTableName = "tf";
238         referenceEF.columns = columns;
239 
240         TableReferenceProperty referenceBD;
241         referenceBD.sourceTableName = "tb";
242         referenceBD.targetTableName = "td";
243         referenceBD.columns = columns;
244 
245         TableReferenceProperty referenceFC;
246         referenceFC.sourceTableName = "tf";
247         referenceFC.targetTableName = "tc";
248         referenceFC.columns = columns;
249 
250         EXPECT_EQ(g_delegate->SetReference({referenceAB, referenceDE, referenceAC, referenceEF, referenceBD,
251             referenceFC}), DISTRIBUTED_SCHEMA_NOT_FOUND);
252 
253         TableReferenceProperty referenceFA;
254         referenceFA.sourceTableName = "tf";
255         referenceFA.targetTableName = "ta";
256         referenceFA.columns = columns;
257         EXPECT_EQ(g_delegate->SetReference(
258             {referenceAB, referenceDE, referenceAC, referenceEF, referenceBD, referenceFC, referenceFA}), INVALID_ARGS);
259     }
260 
261     /**
262      * @tc.name: SetReferenceTest005
263      * @tc.desc: Test table name is case insensitive
264      * @tc.type: FUNC
265      * @tc.require:
266      * @tc.author: zhangshjie
267      */
268     HWTEST_F(DistributedDBCloudInterfacesReferenceTest, SetReferenceTest005, TestSize.Level0)
269     {
270         /**
271          * @tc.steps:step1. call SetReference with two TableReferenceProperty which sourceTableName and targetTableName
272          * are both same
273          * @tc.expected: step1. Return INVALID_ARGS.
274          */
275         TableReferenceProperty tableReferenceProperty;
276         std::string sourceTableName = "sourceTable";
277         std::string targetTableName = "targetTable";
278         tableReferenceProperty.sourceTableName = sourceTableName;
279         tableReferenceProperty.targetTableName = targetTableName;
280         std::map<std::string, std::string> columns;
281         columns["col1"] = "col2";
282         tableReferenceProperty.columns = columns;
283 
284         TableReferenceProperty tableReferenceProperty2;
285         tableReferenceProperty2.sourceTableName = "SourCeTable";
286         tableReferenceProperty2.targetTableName = "TARGETTABLE";
287         tableReferenceProperty2.columns = columns;
288         EXPECT_EQ(g_delegate->SetReference({tableReferenceProperty, tableReferenceProperty2}), INVALID_ARGS);
289     }
290 
291     /**
292      * @tc.name: SetReferenceTest006
293      * @tc.desc: Test reference table doesn't create distributed table
294      * @tc.type: FUNC
295      * @tc.require:
296      * @tc.author: zhangshjie
297      */
298     HWTEST_F(DistributedDBCloudInterfacesReferenceTest, SetReferenceTest006, TestSize.Level0)
299     {
300         /**
301          * @tc.steps:step1. set reference with table doesn't exists
302          * @tc.expected: step1. Return DISTRIBUTED_SCHEMA_NOT_FOUND.
303          */
304         TableReferenceProperty tableReferenceProperty;
305         std::string sourceTableName = "sourceTable";
306         std::string targetTableName = "targetTable";
307         tableReferenceProperty.sourceTableName = sourceTableName;
308         tableReferenceProperty.targetTableName = targetTableName;
309         std::map<std::string, std::string> columns;
310         columns["col1"] = "col2";
311         tableReferenceProperty.columns = columns;
312         EXPECT_EQ(g_delegate->SetReference({tableReferenceProperty}), DISTRIBUTED_SCHEMA_NOT_FOUND);
313 
314         /**
315          * @tc.steps:step2. set reference with table doesn't create distributed table
316          * @tc.expected: step2. Return DISTRIBUTED_SCHEMA_NOT_FOUND.
317          */
318         sqlite3 *db = RelationalTestUtils::CreateDataBase(g_storePath);
319         ASSERT_NE(db, nullptr);
320         std::string sql = "create table " + sourceTableName + "(id int);create table " + targetTableName + "(id int);";
321         EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), SQLITE_OK);
322         EXPECT_EQ(g_delegate->SetReference({tableReferenceProperty}), DISTRIBUTED_SCHEMA_NOT_FOUND);
323 
324         /**
325          * @tc.steps:step3. set reference with one table doesn't create distributed table
326          * @tc.expected: step3. Return DISTRIBUTED_SCHEMA_NOT_FOUND.
327          */
328         EXPECT_EQ(g_delegate->CreateDistributedTable(sourceTableName), OK);
329         EXPECT_EQ(g_delegate->SetReference({tableReferenceProperty}), DISTRIBUTED_SCHEMA_NOT_FOUND);
330         EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK);
331     }
332 
333     /**
334      * @tc.name: SetReferenceTest007
335      * @tc.desc: Test reference table doesn't create cloud sync distributed table
336      * @tc.type: FUNC
337      * @tc.require:
338      * @tc.author: zhangshjie
339      */
340     HWTEST_F(DistributedDBCloudInterfacesReferenceTest, SetReferenceTest007, TestSize.Level0)
341     {
342         /**
343          * @tc.steps:step1. prepare table and distributed table in device mode
344          * @tc.expected: step1. ok.
345          */
346         std::string sourceTableName = "sourceTable";
347         std::string targetTableName = "targetTable";
348         sqlite3 *db = RelationalTestUtils::CreateDataBase(g_storePath);
349         ASSERT_NE(db, nullptr);
350         std::string sql = "create table " + sourceTableName + "(id int);create table " + targetTableName + "(id int);";
351         EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), SQLITE_OK);
352         EXPECT_EQ(g_delegate->CreateDistributedTable(sourceTableName), OK);
353         EXPECT_EQ(g_delegate->CreateDistributedTable(targetTableName), OK);
354 
355         /**
356          * @tc.steps:step2. set reference with column doesn't exists
357          * @tc.expected: step2. Return INVALID_ARGS.
358          */
359         TableReferenceProperty tableReferenceProperty;
360         tableReferenceProperty.sourceTableName = sourceTableName;
361         tableReferenceProperty.targetTableName = targetTableName;
362         std::map<std::string, std::string> columns;
363         columns["id"] = "id";
364         tableReferenceProperty.columns = columns;
365         EXPECT_EQ(g_delegate->SetReference({tableReferenceProperty}), DISTRIBUTED_SCHEMA_NOT_FOUND);
366 
367         EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK);
368     }
369 
370     /**
371      * @tc.name: SetReferenceTest008
372      * @tc.desc: Test reference col doesn't exists table
373      * @tc.type: FUNC
374      * @tc.require:
375      * @tc.author: zhangshjie
376      */
377     HWTEST_F(DistributedDBCloudInterfacesReferenceTest, SetReferenceTest008, TestSize.Level0)
378     {
379         /**
380          * @tc.steps:step1. prepare table and distributed table
381          * @tc.expected: step1. ok.
382          */
383         std::string sourceTableName = "sourceTable";
384         std::string targetTableName = "targetTable";
385         sqlite3 *db = RelationalTestUtils::CreateDataBase(g_storePath);
386         ASSERT_NE(db, nullptr);
387         std::string sql = "create table " + sourceTableName + "(id int);create table " + targetTableName + "(id int);";
388         EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), SQLITE_OK);
389         EXPECT_EQ(g_delegate->CreateDistributedTable(sourceTableName, DistributedDB::CLOUD_COOPERATION), OK);
390         EXPECT_EQ(g_delegate->CreateDistributedTable(targetTableName, DistributedDB::CLOUD_COOPERATION), OK);
391 
392         /**
393          * @tc.steps:step2. set reference with column doesn't exists
394          * @tc.expected: step2. Return INVALID_ARGS.
395          */
396         TableReferenceProperty tableReferenceProperty;
397         tableReferenceProperty.sourceTableName = sourceTableName;
398         tableReferenceProperty.targetTableName = targetTableName;
399         std::map<std::string, std::string> columns;
400         columns["col1"] = "col2";
401         tableReferenceProperty.columns = columns;
402         EXPECT_EQ(g_delegate->SetReference({tableReferenceProperty}), INVALID_ARGS);
403 
404         EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK);
405     }
406 
CheckResult(sqlite3 * db)407     void CheckResult(sqlite3 *db)
408     {
409         int count = 0;
410         std::function<int (sqlite3_stmt *)> bindCallback = [] (sqlite3_stmt *bindStmt) {
411             Key key;
412             DBCommon::StringToVector("relational_schema", key);
413             int errCode = SQLiteUtils::BindBlobToStatement(bindStmt, 1, key, false);
414             return errCode;
415         };
416         std::string sql = "select value from " + std::string(DBConstant::RELATIONAL_PREFIX) + "metadata where key = ?;";
417         int errCode = RelationalTestUtils::ExecSql(db, sql, bindCallback, [&count] (sqlite3_stmt *stmt) {
418             std::string schemaStr;
419             std::vector<uint8_t> value;
420             EXPECT_EQ(SQLiteUtils::GetColumnBlobValue(stmt, 0, value), E_OK);
421             DBCommon::VectorToString(value, schemaStr);
422             RelationalSchemaObject obj;
423             EXPECT_EQ(obj.ParseFromSchemaString(schemaStr), E_OK);
424             count++;
425             return E_OK;
426         });
427         EXPECT_EQ(errCode, E_OK);
428         EXPECT_EQ(count, 1);
429     }
430 
NormalSetReferenceTest(bool multipleTable)431     void NormalSetReferenceTest(bool multipleTable)
432     {
433         /**
434          * @tc.steps:step1. prepare table and distributed table
435          * @tc.expected: step1. ok.
436          */
437         std::string sourceTableName = "sourceTable";
438         std::string targetTableName = "targetTable";
439         sqlite3 *db = RelationalTestUtils::CreateDataBase(g_storePath);
440         ASSERT_NE(db, nullptr);
441         std::string sql = "create table " + sourceTableName + "(id int);create table " + targetTableName + "(id int);";
442         if (multipleTable) {
443             sql += "create table t3(key int, value int);create table t4(key int, value int);";
444         }
445         EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), SQLITE_OK);
446         EXPECT_EQ(g_delegate->CreateDistributedTable(sourceTableName, DistributedDB::CLOUD_COOPERATION), OK);
447         EXPECT_EQ(g_delegate->CreateDistributedTable(targetTableName, DistributedDB::CLOUD_COOPERATION), OK);
448         if (multipleTable) {
449             EXPECT_EQ(g_delegate->CreateDistributedTable("t3", DistributedDB::CLOUD_COOPERATION), OK);
450             EXPECT_EQ(g_delegate->CreateDistributedTable("t4", DistributedDB::CLOUD_COOPERATION), OK);
451         }
452 
453         /**
454          * @tc.steps:step2. set reference
455          * @tc.expected: step2. Return OK.
456          */
457         TableReferenceProperty tableReferenceProperty;
458         tableReferenceProperty.sourceTableName = sourceTableName;
459         tableReferenceProperty.targetTableName = targetTableName;
460         std::map<std::string, std::string> columns;
461         columns["id"] = "id";
462         tableReferenceProperty.columns = columns;
463         std::vector<TableReferenceProperty> vec;
464         vec.emplace_back(tableReferenceProperty);
465         if (multipleTable) {
466             TableReferenceProperty reference;
467             reference.sourceTableName = "t3";
468             reference.targetTableName = "t4";
469             reference.columns["key"] = "key";
470             reference.columns["value"] = "value";
471             vec.emplace_back(reference);
472         }
473         EXPECT_EQ(g_delegate->SetReference(vec), OK);
474 
475         /**
476          * @tc.steps:step3. parse schema in db
477          * @tc.expected: step3. Return OK.
478          */
479         CheckResult(db);
480 
481         EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK);
482     }
483 
484     /**
485      * @tc.name: SetReferenceTest009
486      * @tc.desc: Test normal function for SetReference interface with one table
487      * @tc.type: FUNC
488      * @tc.require:
489      * @tc.author: zhangshjie
490      */
491     HWTEST_F(DistributedDBCloudInterfacesReferenceTest, SetReferenceTest009, TestSize.Level0)
492     {
493         NormalSetReferenceTest(false);
494     }
495 
496     /**
497      * @tc.name: SetReferenceTest010
498      * @tc.desc: Test normal function for SetReference interface with two table
499      * @tc.type: FUNC
500      * @tc.require:
501      * @tc.author: zhangshjie
502      */
503     HWTEST_F(DistributedDBCloudInterfacesReferenceTest, SetReferenceTest010, TestSize.Level1)
504     {
505         NormalSetReferenceTest(true);
506     }
507 
ReferenceChangeTest(bool isTableEmpty)508     void ReferenceChangeTest(bool isTableEmpty)
509     {
510         /**
511          * @tc.steps:step1. prepare table and distributed table
512          * @tc.expected: step1. ok.
513          */
514         std::string sourceTableName = "sourceTable";
515         std::string targetTableName = "targetTable";
516         sqlite3 *db = RelationalTestUtils::CreateDataBase(g_storePath);
517         ASSERT_NE(db, nullptr);
518         std::string sql = "create table " + sourceTableName + "(id int, value text);create table " +
519             targetTableName + "(id int, value text);create table t3 (id int, value text);";
520         EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), SQLITE_OK);
521         EXPECT_EQ(g_delegate->CreateDistributedTable(sourceTableName, DistributedDB::CLOUD_COOPERATION), OK);
522         EXPECT_EQ(g_delegate->CreateDistributedTable(targetTableName, DistributedDB::CLOUD_COOPERATION), OK);
523         EXPECT_EQ(g_delegate->CreateDistributedTable("t3", DistributedDB::CLOUD_COOPERATION), OK);
524 
525         if (!isTableEmpty) {
526             sql = "insert into " + sourceTableName + " values(1, 'zhangsan');";
527             EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), SQLITE_OK);
528         }
529 
530         /**
531          * @tc.steps:step2. set reference
532          * @tc.expected: step2. Return OK or PROPERTY_CHANGED.
533          */
534         TableReferenceProperty tableReferenceProperty;
535         tableReferenceProperty.sourceTableName = sourceTableName;
536         tableReferenceProperty.targetTableName = targetTableName;
537         std::map<std::string, std::string> columns;
538         columns["id"] = "id";
539         tableReferenceProperty.columns = columns;
540         if (isTableEmpty) {
541             EXPECT_EQ(g_delegate->SetReference({tableReferenceProperty}), OK);
542         } else {
543             EXPECT_EQ(g_delegate->SetReference({tableReferenceProperty}), PROPERTY_CHANGED);
544         }
545 
546         /**
547          * @tc.steps:step3. set reference again with different table reference
548          * @tc.expected: step3. Return OK or PROPERTY_CHANGED.
549          */
550         tableReferenceProperty.targetTableName = "t3";
551         EXPECT_EQ(g_delegate->SetReference({tableReferenceProperty}), PROPERTY_CHANGED);
552 
553         /**
554          * @tc.steps:step4. set reference again with different column reference
555          * @tc.expected: step4. Return OK or PROPERTY_CHANGED.
556          */
557         columns["id"] = "value";
558         tableReferenceProperty.columns = columns;
559         EXPECT_EQ(g_delegate->SetReference({tableReferenceProperty}), PROPERTY_CHANGED);
560 
561         EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK);
562     }
563 
564     /**
565      * @tc.name: SetReferenceTest011
566      * @tc.desc: Test table reference change when table is empty
567      * @tc.type: FUNC
568      * @tc.require:
569      * @tc.author: zhangshjie
570      */
571     HWTEST_F(DistributedDBCloudInterfacesReferenceTest, SetReferenceTest011, TestSize.Level1)
572     {
573         ReferenceChangeTest(true);
574     }
575 
576     /**
577      * @tc.name: SetReferenceTest012
578      * @tc.desc: Test table reference change when table is not empty
579      * @tc.type: FUNC
580      * @tc.require:
581      * @tc.author: zhangshjie
582      */
583     HWTEST_F(DistributedDBCloudInterfacesReferenceTest, SetReferenceTest012, TestSize.Level1)
584     {
585         ReferenceChangeTest(false);
586     }
587 
588     /**
589      * @tc.name: SetReferenceTest013
590      * @tc.desc: Test table set reference is case insensitive
591      * @tc.type: FUNC
592      * @tc.require:
593      * @tc.author: zhangshjie
594      */
595     HWTEST_F(DistributedDBCloudInterfacesReferenceTest, SetReferenceTest013, TestSize.Level1)
596     {
597         /**
598          * @tc.steps:step1. prepare table and distributed table
599          * @tc.expected: step1. ok.
600          */
601         std::string sourceTableName = "sourceTable";
602         std::string targetTableName = "targetTable";
603         sqlite3 *db = RelationalTestUtils::CreateDataBase(g_storePath);
604         ASSERT_NE(db, nullptr);
605         std::string sql = "create table " + sourceTableName + "(id int, value text);create table " +
606             targetTableName + "(id int, value text);";
607         EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), SQLITE_OK);
608         EXPECT_EQ(g_delegate->CreateDistributedTable(sourceTableName, DistributedDB::CLOUD_COOPERATION), OK);
609         EXPECT_EQ(g_delegate->CreateDistributedTable(targetTableName, DistributedDB::CLOUD_COOPERATION), OK);
610         sql = "insert into " + sourceTableName + " values(1, 'zhangsan');";
611         EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), SQLITE_OK);
612         EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK);
613 
614         /**
615          * @tc.steps:step2. set reference
616          * @tc.expected: step2. Return PROPERTY_CHANGED.
617          */
618         TableReferenceProperty tableReferenceProperty;
619         tableReferenceProperty.sourceTableName = sourceTableName;
620         tableReferenceProperty.targetTableName = targetTableName;
621         std::map<std::string, std::string> columns;
622         columns["id"] = "id";
623         tableReferenceProperty.columns = columns;
624         EXPECT_EQ(g_delegate->SetReference({tableReferenceProperty}), PROPERTY_CHANGED);
625 
626         /**
627          * @tc.steps:step3. set reference with same table name, but case different
628          * @tc.expected: step3. Return OK.
629          */
630         tableReferenceProperty.sourceTableName = sourceTableName;
631         tableReferenceProperty.targetTableName = "Targettable";
632         tableReferenceProperty.columns = columns;
633         EXPECT_EQ(g_delegate->SetReference({tableReferenceProperty}), OK);
634 
635         /**
636          * @tc.steps:step4. set reference with same column name, but case different(value different)
637          * @tc.expected: step4. Return OK.
638          */
639         tableReferenceProperty.sourceTableName = sourceTableName;
640         tableReferenceProperty.targetTableName = targetTableName;
641         columns["id"] = "ID";
642         tableReferenceProperty.columns = columns;
643         EXPECT_EQ(g_delegate->SetReference({tableReferenceProperty}), OK);
644 
645         /**
646          * @tc.steps:step5. set reference with same column name, but case different(key different)
647          * @tc.expected: step5. Return OK.
648          */
649         std::map<std::string, std::string> columns2;
650         columns2["ID"] = "ID";
651         tableReferenceProperty.columns = columns2;
652         EXPECT_EQ(g_delegate->SetReference({tableReferenceProperty}), OK);
653 
654         /**
655          * @tc.steps:step6. set reference with column size not equal
656          * @tc.expected: step6. Return PROPERTY_CHANGED.
657          */
658         columns2["ID"] = "ID";
659         columns2["value"] = "value";
660         tableReferenceProperty.columns = columns2;
661         EXPECT_EQ(g_delegate->SetReference({tableReferenceProperty}), PROPERTY_CHANGED);
662     }
663 
664     /**
665     * @tc.name: SetReferenceTest014
666     * @tc.desc: Test table set reference with multi columns
667     * @tc.type: FUNC
668     * @tc.require:
669     * @tc.author: zhangshjie
670     */
671     HWTEST_F(DistributedDBCloudInterfacesReferenceTest, SetReferenceTest014, TestSize.Level1)
672     {
673         /**
674          * @tc.steps:step1. prepare table and distributed table
675          * @tc.expected: step1. ok.
676          */
677         std::string sourceTableName = "sourceTable";
678         std::string targetTableName = "targetTable";
679         sqlite3 *db = RelationalTestUtils::CreateDataBase(g_storePath);
680         ASSERT_NE(db, nullptr);
681         std::string sql = "create table " + sourceTableName + "(id int, value text, name text);create table " +
682             targetTableName + "(id int, value text, name text);create table t3 (id int, value text);";
683         EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), SQLITE_OK);
684         EXPECT_EQ(g_delegate->CreateDistributedTable(sourceTableName, DistributedDB::CLOUD_COOPERATION), OK);
685         EXPECT_EQ(g_delegate->CreateDistributedTable(targetTableName, DistributedDB::CLOUD_COOPERATION), OK);
686         EXPECT_EQ(g_delegate->CreateDistributedTable("t3", DistributedDB::CLOUD_COOPERATION), OK);
687         sql = "insert into " + sourceTableName + " values(1, 'zhangsan', 'test');insert into " + targetTableName +
688             " values(2, 'lisi', 'test2');insert into t3 values(3, 'wangwu');";
689         EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), SQLITE_OK);
690         EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK);
691 
692         /**
693          * @tc.steps:step2. set reference
694          * @tc.expected: step2. Return PROPERTY_CHANGED.
695          */
696         TableReferenceProperty tableReferenceProperty;
697         tableReferenceProperty.sourceTableName = sourceTableName;
698         tableReferenceProperty.targetTableName = targetTableName;
699         std::map<std::string, std::string> columns;
700         columns["id"] = "id";
701         columns["value"] = "value";
702         tableReferenceProperty.columns = columns;
703         EXPECT_EQ(g_delegate->SetReference({tableReferenceProperty}), PROPERTY_CHANGED);
704 
705         /**
706          * @tc.steps:step3. set reference with multi columns
707          * @tc.expected: step3. Return PROPERTY_CHANGED.
708          */
709         std::map<std::string, std::string> columns2;
710         columns2["id"] = "id";
711         columns2["name"] = "name";
712         tableReferenceProperty.columns = columns2;
713         EXPECT_EQ(g_delegate->SetReference({tableReferenceProperty}), PROPERTY_CHANGED);
714 
715         /**
716          * @tc.steps:step4. set reference with multi reference property
717          * @tc.expected: step4. Return PROPERTY_CHANGED.
718          */
719         TableReferenceProperty tableReferenceProperty2;
720         tableReferenceProperty2.sourceTableName = sourceTableName;
721         tableReferenceProperty2.targetTableName = "t3";
722         std::map<std::string, std::string> columns3;
723         columns3["id"] = "id";
724         tableReferenceProperty2.columns = columns3;
725         EXPECT_EQ(g_delegate->SetReference({tableReferenceProperty, tableReferenceProperty2}), PROPERTY_CHANGED);
726 
727         /**
728          * @tc.steps:step5. set reference with one reference property
729          * @tc.expected: step5. Return PROPERTY_CHANGED.
730          */
731         EXPECT_EQ(g_delegate->SetReference({tableReferenceProperty}), PROPERTY_CHANGED);
732     }
733 
SetCloudSchema(RelationalStoreDelegate * delegate)734     void SetCloudSchema(RelationalStoreDelegate *delegate)
735     {
736         TableSchema tableSchema;
737         Field field1 = { "id", TYPE_INDEX<int64_t>, true, false };
738         Field field2 = { "value", TYPE_INDEX<std::string>, false, true };
739         Field field3 = { "name", TYPE_INDEX<std::string>, false, true };
740 
741         tableSchema = { "sourceTable", "src_shared", { field1, field2, field3} };
742         DataBaseSchema dbSchema;
743         dbSchema.tables.push_back(tableSchema);
744         tableSchema = { "targetTable", "dst_shared", { field1, field2, field3} };
745         dbSchema.tables.push_back(tableSchema);
746 
747         EXPECT_EQ(delegate->SetCloudDbSchema(dbSchema), OK);
748     }
749 
750     /**
751     * @tc.name: SetReferenceTest015
752     * @tc.desc: Test reference change of shared table
753     * @tc.type: FUNC
754     * @tc.require:
755     * @tc.author: zhangshjie
756     */
757     HWTEST_F(DistributedDBCloudInterfacesReferenceTest, SetReferenceTest015, TestSize.Level1)
758     {
759         /**
760          * @tc.steps:step1. prepare table and distributed table
761          * @tc.expected: step1. ok.
762          */
763         std::string sourceTableName = "sourceTable";
764         std::string targetTableName = "targetTable";
765         sqlite3 *db = RelationalTestUtils::CreateDataBase(g_storePath);
766         ASSERT_NE(db, nullptr);
767         std::string sql = "create table " + sourceTableName + "(id int, value text, name text);create table " +
768             targetTableName + "(id int, value text, name text);";
769         EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), SQLITE_OK);
770         EXPECT_EQ(g_delegate->CreateDistributedTable(sourceTableName, DistributedDB::CLOUD_COOPERATION), OK);
771         EXPECT_EQ(g_delegate->CreateDistributedTable(targetTableName, DistributedDB::CLOUD_COOPERATION), OK);
772         TableReferenceProperty tableReferenceProperty;
773         tableReferenceProperty.sourceTableName = sourceTableName;
774         tableReferenceProperty.targetTableName = targetTableName;
775         std::map<std::string, std::string> columns;
776         columns["id"] = "id";
777         columns["value"] = "value";
778         tableReferenceProperty.columns = columns;
779         EXPECT_EQ(g_delegate->SetReference({tableReferenceProperty}), OK);
780 
781         /**
782          * @tc.steps:step2. set cloud db schema, insert data into shared table
783          * @tc.expected: step2. ok.
784          */
785         SetCloudSchema(g_delegate);
786         sql = "insert into src_shared values(1, 'zhangsan', 'test', 'aa', 'bb');";
787         EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), SQLITE_OK);
788         EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK);
789 
790         /**
791          * @tc.steps:step3. clear reference
792          * @tc.expected: step3. return PROPERTY_CHANGED.
793          */
794         EXPECT_EQ(g_delegate->SetReference({}), PROPERTY_CHANGED);
795     }
796 
797     /**
798     * @tc.name: SetReferenceTest016
799     * @tc.desc: Test set reference after some table was dropped
800     * @tc.type: FUNC
801     * @tc.require:
802     * @tc.author: zhangshjie
803     */
804     HWTEST_F(DistributedDBCloudInterfacesReferenceTest, SetReferenceTest016, TestSize.Level1)
805     {
806         /**
807          * @tc.steps:step1. prepare table and distributed table, then set reference t1->t2
808          * @tc.expected: step1. return ok.
809          */
810         sqlite3 *db = RelationalTestUtils::CreateDataBase(g_storePath);
811         ASSERT_NE(db, nullptr);
812         std::string sql = "create table t1(id int, value text);create table t2(id int, value text);" \
813             "create table t3(id int, value text);";
814         EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), SQLITE_OK);
815         EXPECT_EQ(g_delegate->CreateDistributedTable("t1", DistributedDB::CLOUD_COOPERATION), OK);
816         EXPECT_EQ(g_delegate->CreateDistributedTable("t2", DistributedDB::CLOUD_COOPERATION), OK);
817         EXPECT_EQ(g_delegate->CreateDistributedTable("t3", DistributedDB::CLOUD_COOPERATION), OK);
818         TableReferenceProperty tableReferenceProperty;
819         tableReferenceProperty.sourceTableName = "t1";
820         tableReferenceProperty.targetTableName = "t2";
821         std::map<std::string, std::string> columns;
822         columns["id"] = "id";
823         columns["value"] = "value";
824         tableReferenceProperty.columns = columns;
825         EXPECT_EQ(g_delegate->SetReference({tableReferenceProperty}), OK);
826 
827         /**
828          * @tc.steps:step2. drop table t1, then reopen store
829          * @tc.expected: step2. return ok.
830          */
831         sql = "drop table t1;";
832         EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), SQLITE_OK);
833         EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK);
834         EXPECT_EQ(g_mgr.CloseStore(g_delegate), OK);
835         g_delegate = nullptr;
836         EXPECT_EQ(g_mgr.OpenStore(g_storePath, STORE_ID, {}, g_delegate), OK);
837         ASSERT_NE(g_delegate, nullptr);
838 
839         /**
840          * @tc.steps:step3. set reference t2->t1
841          * @tc.expected: step3. return ok.
842          */
843         tableReferenceProperty.sourceTableName = "t2";
844         tableReferenceProperty.targetTableName = "t3";
845         EXPECT_EQ(g_delegate->SetReference({tableReferenceProperty}), PROPERTY_CHANGED);
846     }
847 
848     /**
849      * @tc.name: SetReferenceTest017
850      * @tc.desc: Test log table is case insensitive in set reference interface
851      * @tc.type: FUNC
852      * @tc.require:
853      * @tc.author: zhangshjie
854      */
855     HWTEST_F(DistributedDBCloudInterfacesReferenceTest, SetReferenceTest017, TestSize.Level1)
856     {
857         /**
858          * @tc.steps:step1. prepare table and distributed table
859          * @tc.expected: step1. ok.
860          */
861         std::string sourceTableName = "sourceTable";
862         std::string targetTableName = "targetTable";
863         sqlite3 *db = RelationalTestUtils::CreateDataBase(g_storePath);
864         ASSERT_NE(db, nullptr);
865         std::string sql = "create table " + sourceTableName + "(id int, value text);create table " +
866             targetTableName + "(id int, value text);";
867         EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), SQLITE_OK);
868         EXPECT_EQ(g_delegate->CreateDistributedTable(sourceTableName, DistributedDB::CLOUD_COOPERATION), OK);
869         EXPECT_EQ(g_delegate->CreateDistributedTable(targetTableName, DistributedDB::CLOUD_COOPERATION), OK);
870         sql = "insert into " + sourceTableName + " values(1, 'zhangsan');";
871         EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), SQLITE_OK);
872         EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK);
873 
874         /**
875          * @tc.steps:step2. set reference with same table name, but case mismatch
876          * @tc.expected: step2. Return PROPERTY_CHANGED.
877          */
878         TableReferenceProperty tableReferenceProperty;
879         tableReferenceProperty.sourceTableName = "SourceTable";
880         tableReferenceProperty.targetTableName = targetTableName;
881         std::map<std::string, std::string> columns;
882         columns["id"] = "id";
883         tableReferenceProperty.columns = columns;
884         EXPECT_EQ(g_delegate->SetReference({tableReferenceProperty}), PROPERTY_CHANGED);
885     }
886 
887     /**
888      * @tc.name: FuncExceptionTest001
889      * @tc.desc: Test the interception expection of the delegate interface when the conn is empty.
890      * @tc.type: FUNC
891      * @tc.require:
892      * @tc.author: bty
893      */
894     HWTEST_F(DistributedDBCloudInterfacesReferenceTest, FuncExceptionTest001, TestSize.Level1)
895     {
896         RelationalStoreConnection *iConn = nullptr;
897         std::string iPath = "";
898         auto iDelegate = std::make_shared<RelationalStoreDelegateImpl>(iConn, iPath);
899         EXPECT_EQ(iDelegate->SetStoreConfig({}), OK);
900         EXPECT_EQ(iDelegate->SetStoreConfig({DistributedTableMode::COLLABORATION}), DB_ERROR);
901 
902         ClearMetaDataOption iOption;
903         iOption.tableNameList.insert(STORE_ID);
904         #ifdef USE_DISTRIBUTEDDB_CLOUD
905         EXPECT_EQ(iDelegate->ClearMetaData(iOption), NOT_SUPPORT);
906         iOption.tableNameList.clear();
907         EXPECT_EQ(iDelegate->ClearMetaData(iOption), DB_ERROR);
908         #endif
909         iOption.mode = ClearMetaDataMode::BUTT;
910         EXPECT_EQ(iDelegate->ClearMetaData(iOption), INVALID_ARGS);
911 
912         EXPECT_EQ(iDelegate->GetDownloadingAssetsCount().first, DB_ERROR);
913         EXPECT_EQ(iDelegate->SetDistributedSchema({}, false), DB_ERROR);
914 
915         iDelegate->SetReleaseFlag(false);
916         iDelegate = nullptr;
917     }
918 }
919