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 #ifdef RELATIONAL_STORE
16 #include <gtest/gtest.h>
17 #include "cloud_db_types.h"
18 #include "distributeddb_data_generate_unit_test.h"
19 #include "log_print.h"
20 #include "relational_store_delegate.h"
21 #include "relational_store_manager.h"
22 #include "runtime_config.h"
23 #include "virtual_asset_loader.h"
24 #include "virtual_cloud_data_translate.h"
25 #include "virtual_cloud_db.h"
26 namespace {
27 using namespace testing::ext;
28 using namespace DistributedDB;
29 using namespace DistributedDBUnitTest;
30 const char *g_createSQL =
31 "CREATE TABLE IF NOT EXISTS DistributedDBCloudCheckSyncTest(" \
32 "id TEXT PRIMARY KEY," \
33 "name TEXT," \
34 "height REAL ," \
35 "photo BLOB," \
36 "age INT);";
37 const int64_t g_syncWaitTime = 60;
38
CreateUserDBAndTable(sqlite3 * & db)39 void CreateUserDBAndTable(sqlite3 *&db)
40 {
41 EXPECT_EQ(RelationalTestUtils::ExecSql(db, "PRAGMA journal_mode=WAL;"), SQLITE_OK);
42 EXPECT_EQ(RelationalTestUtils::ExecSql(db, g_createSQL), SQLITE_OK);
43 }
44
BlockSync(const Query & query,RelationalStoreDelegate * delegate)45 void BlockSync(const Query &query, RelationalStoreDelegate *delegate)
46 {
47 std::mutex dataMutex;
48 std::condition_variable cv;
49 bool finish = false;
50 auto callback = [&cv, &dataMutex, &finish](const std::map<std::string, SyncProcess> &process) {
51 for (const auto &item: process) {
52 if (item.second.process == DistributedDB::FINISHED) {
53 {
54 std::lock_guard<std::mutex> autoLock(dataMutex);
55 finish = true;
56 }
57 cv.notify_one();
58 }
59 }
60 };
61 ASSERT_EQ(delegate->Sync({ "CLOUD" }, SYNC_MODE_CLOUD_MERGE, query, callback, g_syncWaitTime), OK);
62 std::unique_lock<std::mutex> uniqueLock(dataMutex);
63 cv.wait(uniqueLock, [&finish]() {
64 return finish;
65 });
66 }
67
68 class DistributedDBCloudCheckSyncTest : public testing::Test {
69 public:
70 static void SetUpTestCase();
71 static void TearDownTestCase();
72 void SetUp() override;
73 void TearDown() override;
74 protected:
75 void InitTestDir();
76 DataBaseSchema GetSchema();
77 void CloseDb();
78 void InsertUserTableRecord(int64_t recordCounts, int64_t begin = 0);
79 std::string testDir_;
80 std::string storePath_;
81 sqlite3 *db_ = nullptr;
82 RelationalStoreDelegate *delegate_ = nullptr;
83 std::shared_ptr<VirtualCloudDb> virtualCloudDb_ = nullptr;
84 std::shared_ptr<VirtualAssetLoader> virtualAssetLoader_ = nullptr;
85 std::shared_ptr<RelationalStoreManager> mgr_ = nullptr;
86 std::string tableName_ = "DistributedDBCloudCheckSyncTest";
87 };
88
SetUpTestCase()89 void DistributedDBCloudCheckSyncTest::SetUpTestCase()
90 {
91 RuntimeConfig::SetCloudTranslate(std::make_shared<VirtualCloudDataTranslate>());
92 }
93
TearDownTestCase()94 void DistributedDBCloudCheckSyncTest::TearDownTestCase()
95 {}
96
SetUp()97 void DistributedDBCloudCheckSyncTest::SetUp()
98 {
99 DistributedDBToolsUnitTest::PrintTestCaseInfo();
100 InitTestDir();
101 if (DistributedDBToolsUnitTest::RemoveTestDbFiles(testDir_) != 0) {
102 LOGE("rm test db files error.");
103 }
104 DistributedDBToolsUnitTest::PrintTestCaseInfo();
105 LOGD("Test dir is %s", testDir_.c_str());
106 db_ = RelationalTestUtils::CreateDataBase(storePath_);
107 ASSERT_NE(db_, nullptr);
108 CreateUserDBAndTable(db_);
109 mgr_ = std::make_shared<RelationalStoreManager>(APP_ID, USER_ID);
110 RelationalStoreDelegate::Option option;
111 ASSERT_EQ(mgr_->OpenStore(storePath_, STORE_ID_1, option, delegate_), DBStatus::OK);
112 ASSERT_NE(delegate_, nullptr);
113 ASSERT_EQ(delegate_->CreateDistributedTable(tableName_, CLOUD_COOPERATION), DBStatus::OK);
114 virtualCloudDb_ = std::make_shared<VirtualCloudDb>();
115 virtualAssetLoader_ = std::make_shared<VirtualAssetLoader>();
116 ASSERT_EQ(delegate_->SetCloudDB(virtualCloudDb_), DBStatus::OK);
117 ASSERT_EQ(delegate_->SetIAssetLoader(virtualAssetLoader_), DBStatus::OK);
118 DataBaseSchema dataBaseSchema = GetSchema();
119 ASSERT_EQ(delegate_->SetCloudDbSchema(dataBaseSchema), DBStatus::OK);
120 }
121
TearDown()122 void DistributedDBCloudCheckSyncTest::TearDown()
123 {
124 CloseDb();
125 EXPECT_EQ(sqlite3_close_v2(db_), SQLITE_OK);
126 if (DistributedDBToolsUnitTest::RemoveTestDbFiles(testDir_) != 0) {
127 LOGE("rm test db files error.");
128 }
129 }
130
InitTestDir()131 void DistributedDBCloudCheckSyncTest::InitTestDir()
132 {
133 if (!testDir_.empty()) {
134 return;
135 }
136 DistributedDBToolsUnitTest::TestDirInit(testDir_);
137 storePath_ = testDir_ + "/" + STORE_ID_1 + ".db";
138 LOGI("The test db is:%s", testDir_.c_str());
139 }
140
GetSchema()141 DataBaseSchema DistributedDBCloudCheckSyncTest::GetSchema()
142 {
143 DataBaseSchema schema;
144 TableSchema tableSchema;
145 tableSchema.name = tableName_;
146 tableSchema.fields = {
147 {"id", TYPE_INDEX<std::string>, true}, {"name", TYPE_INDEX<std::string>}, {"height", TYPE_INDEX<double>},
148 {"photo", TYPE_INDEX<Bytes>}, {"age", TYPE_INDEX<int64_t>}
149 };
150 schema.tables.push_back(tableSchema);
151 return schema;
152 }
153
CloseDb()154 void DistributedDBCloudCheckSyncTest::CloseDb()
155 {
156 virtualCloudDb_ = nullptr;
157 EXPECT_EQ(mgr_->CloseStore(delegate_), DBStatus::OK);
158 delegate_ = nullptr;
159 mgr_ = nullptr;
160 }
161
InsertUserTableRecord(int64_t recordCounts,int64_t begin)162 void DistributedDBCloudCheckSyncTest::InsertUserTableRecord(int64_t recordCounts, int64_t begin)
163 {
164 ASSERT_NE(db_, nullptr);
165 for (int64_t i = begin; i < recordCounts; ++i) {
166 string sql = "INSERT OR REPLACE INTO " + tableName_
167 + " (id, name, height, photo, age) VALUES ('" + std::to_string(i) + "', 'Local"
168 + std::to_string(i) + "', '155.10', 'text', '21');";
169 ASSERT_EQ(SQLiteUtils::ExecuteRawSQL(db_, sql), E_OK);
170 }
171 }
172
173 /**
174 * @tc.name: CloudSyncTest001
175 * @tc.desc: sync with device sync query
176 * @tc.type: FUNC
177 * @tc.require:
178 * @tc.author: zhangqiquan
179 */
180 HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest001, TestSize.Level0)
181 {
182 // prepare data
183 const int actualCount = 10;
184 InsertUserTableRecord(actualCount);
185 // sync twice
186 Query query = Query::Select().FromTable({ tableName_ });
187 BlockSync(query, delegate_);
188 BlockSync(query, delegate_);
189 // remove cloud data
190 delegate_->RemoveDeviceData("CLOUD", ClearMode::FLAG_AND_DATA);
191 // check local data
192 int dataCnt = -1;
193 std::string checkLogSql = "SELECT count(*) FROM " + tableName_;
__anon06c51c050402(sqlite3_stmt *stmt) 194 RelationalTestUtils::ExecSql(db_, checkLogSql, nullptr, [&dataCnt](sqlite3_stmt *stmt) {
195 dataCnt = sqlite3_column_int(stmt, 0);
196 return E_OK;
197 });
198 EXPECT_EQ(dataCnt, actualCount);
199 }
200 }
201 #endif