1 /*
2  * Copyright (c) 2022 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 #ifdef RELATIONAL_STORE
17 #include <gtest/gtest.h>
18 
19 #include "distributeddb_tools_unit_test.h"
20 #include "relational_sync_able_storage.h"
21 #include "sqlite_single_relational_storage_engine.h"
22 #include "sqlite_utils.h"
23 
24 using namespace testing::ext;
25 using namespace DistributedDB;
26 using namespace DistributedDBUnitTest;
27 using namespace std;
28 
29 namespace {
30 constexpr const char* DB_SUFFIX = ".db";
31 constexpr const char* STORE_ID = "Relational_Store_ID";
32 std::string g_testDir;
33 std::string g_dbDir;
34 
35 const std::string NORMAL_CREATE_TABLE_SQL = "CREATE TABLE IF NOT EXISTS sync_data(" \
36     "key         BLOB NOT NULL UNIQUE," \
37     "value       BLOB," \
38     "timestamp   INT  NOT NULL," \
39     "flag        INT  NOT NULL," \
40     "device      BLOB," \
41     "ori_device  BLOB," \
42     "hash_key    BLOB PRIMARY KEY NOT NULL," \
43     "w_timestamp INT," \
44     "UNIQUE(device, ori_device));" \
45     "CREATE INDEX key_index ON sync_data (key, flag);";
46 }
47 
48 class DistributedDBRelationalSyncableStorageTest : public testing::Test {
49 public:
50     static void SetUpTestCase(void);
51     static void TearDownTestCase(void);
52     void SetUp();
53     void TearDown();
54 };
55 
56 
SetUpTestCase(void)57 void DistributedDBRelationalSyncableStorageTest::SetUpTestCase(void)
58 {}
59 
TearDownTestCase(void)60 void DistributedDBRelationalSyncableStorageTest::TearDownTestCase(void)
61 {}
62 
SetUp(void)63 void DistributedDBRelationalSyncableStorageTest::SetUp(void)
64 {
65     DistributedDBToolsUnitTest::PrintTestCaseInfo();
66     DistributedDBToolsUnitTest::TestDirInit(g_testDir);
67     LOGD("Test dir is %s", g_testDir.c_str());
68     g_dbDir = g_testDir + "/";
69 }
70 
TearDown(void)71 void DistributedDBRelationalSyncableStorageTest::TearDown(void)
72 {
73     DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir);
74 }
75 
76 /**
77  * @tc.name: SchemaRefTest001
78  * @tc.desc: Test sync interface get schema
79  * @tc.type: FUNC
80  * @tc.require:
81  * @tc.author: xulianhui
82   */
83 HWTEST_F(DistributedDBRelationalSyncableStorageTest, SchemaRefTest001, TestSize.Level1)
84 {
85     sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX);
86     ASSERT_NE(db, nullptr);
87     EXPECT_EQ(RelationalTestUtils::ExecSql(db, "PRAGMA journal_mode=WAL;"), SQLITE_OK);
88 
89     RelationalDBProperties properties;
90     auto sqliteStorageEngine = std::make_shared<SQLiteSingleRelationalStorageEngine>(properties);
91     RelationalSyncAbleStorage *syncAbleStorage = new RelationalSyncAbleStorage(sqliteStorageEngine);
92 
93     static std::atomic<bool> isFinish(false);
94     int getCount = 0;
__anon97c14e970202() 95     std::thread th([syncAbleStorage, &getCount]() {
96         while (!isFinish.load()) {
97             RelationalSchemaObject schema = syncAbleStorage->GetSchemaInfo();
98             (void)schema.ToSchemaString();
99             getCount++;
100         }
101     });
102 
103     RelationalSchemaObject schema;
104     EXPECT_EQ(RelationalTestUtils::ExecSql(db, NORMAL_CREATE_TABLE_SQL), SQLITE_OK);
105     TableInfo table;
106     SQLiteUtils::AnalysisSchema(db, "sync_data", table);
107     schema.AddRelationalTable(table);
108 
109     int setCount = 0;
110     for (; setCount < 1000; setCount++) { // 1000: run times
111         RelationalSchemaObject tmpSchema = schema;
112         sqliteStorageEngine->SetSchema(tmpSchema);
113     }
114 
115     isFinish.store(true);
116     th.join();
117 
118     LOGD("run round set: %d, get: %d", getCount, setCount);
119 
120     RefObject::DecObjRef(syncAbleStorage);
121     EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK);
122 }
123 #endif // RELATIONAL_STORE
124