1 /*
2  * Copyright (c) 2021 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 <fcntl.h>
17 #include <gtest/gtest.h>
18 #include <sys/stat.h>
19 #include <sys/types.h>
20 
21 #include <iostream>
22 #include <string>
23 
24 #include "rdb_errno.h"
25 #include "rdb_helper.h"
26 #include "rdb_open_callback.h"
27 
28 using namespace testing::ext;
29 using namespace OHOS::NativeRdb;
30 
31 static std::shared_ptr<RdbStore> rdbStore;
32 
33 class RdbStoreDistributedTest : public testing::Test {
34 public:
35     static void SetUpTestCase();
36     static void TearDownTestCase();
37     void SetUp();
TearDown()38     void TearDown()
39     {
40     }
41 
42     void InsertValue(std::shared_ptr<RdbStore> &store);
43     void CheckResultSet(std::shared_ptr<RdbStore> &store);
44 
45     static constexpr int ddmsGroupId_ = 1000;
46     static const std::string DRDB_NAME;
47     static const std::string DRDB_PATH;
48 };
49 
50 const std::string RdbStoreDistributedTest::DRDB_NAME = "distributed_rdb.db";
51 const std::string RdbStoreDistributedTest::DRDB_PATH = "/data/test/";
52 
53 class TestOpenCallback : public RdbOpenCallback {
54 public:
OnCreate(RdbStore & store)55     int OnCreate(RdbStore &store) override
56     {
57         std::string sql = "CREATE TABLE IF NOT EXISTS employee ("
58                           "id INTEGER PRIMARY KEY AUTOINCREMENT,"
59                           "name TEXT NOT NULL,"
60                           "age INTEGER,"
61                           "salary REAL,"
62                           "data BLOB)";
63         store.ExecuteSql(sql);
64         return 0;
65     }
66 
OnOpen(RdbStore & store)67     int OnOpen(RdbStore &store) override
68     {
69         return 0;
70     }
71 
OnUpgrade(RdbStore & store,int currentVersion,int targetVersion)72     int OnUpgrade(RdbStore &store, int currentVersion, int targetVersion) override
73     {
74         return 0;
75     }
76 };
77 
SetUpTestCase()78 void RdbStoreDistributedTest::SetUpTestCase()
79 {
80     int errCode = 0;
81     std::string path = RdbStoreDistributedTest::DRDB_PATH + RdbStoreDistributedTest::DRDB_NAME;
82     RdbHelper::DeleteRdbStore(path);
83     int fd = open(path.c_str(), O_CREAT, S_IRWXU | S_IRWXG);
84     if (fd < 0) {
85         return;
86     }
87     if (fd > 0) {
88         close(fd);
89     }
90     chown(path.c_str(), 0, ddmsGroupId_);
91 
92     RdbStoreConfig config(path);
93     config.SetBundleName("com.example.distributed.rdb");
94     config.SetName(RdbStoreDistributedTest::DRDB_NAME);
95     TestOpenCallback callback;
96     rdbStore = RdbHelper::GetRdbStore(config, 1, callback, errCode);
97     EXPECT_NE(nullptr, rdbStore);
98 }
99 
TearDownTestCase()100 void RdbStoreDistributedTest::TearDownTestCase()
101 {
102     RdbHelper::DeleteRdbStore(RdbStoreDistributedTest::DRDB_PATH + RdbStoreDistributedTest::DRDB_NAME);
103 }
104 
SetUp()105 void RdbStoreDistributedTest::SetUp()
106 {
107     EXPECT_NE(nullptr, rdbStore);
108     rdbStore->ExecuteSql("DELETE FROM test");
109 }
110 
InsertValue(std::shared_ptr<RdbStore> & store)111 void RdbStoreDistributedTest::InsertValue(std::shared_ptr<RdbStore> &store)
112 {
113     int64_t id;
114     ValuesBucket values;
115 
116     values.PutInt("id", 1);
117     values.PutString("name", std::string("zhangsan"));
118     values.PutInt("age", 18);          // 18 age
119     values.PutDouble("salary", 100.5); // 100.5
120     values.PutBlob("data", std::vector<uint8_t>{ 1, 2, 3 });
121     EXPECT_EQ(E_OK, store->Insert(id, "employee", values));
122     EXPECT_EQ(1, id);
123 }
124 
CheckResultSet(std::shared_ptr<RdbStore> & store)125 void RdbStoreDistributedTest::CheckResultSet(std::shared_ptr<RdbStore> &store)
126 {
127     std::shared_ptr<ResultSet> resultSet =
128         store->QuerySql("SELECT * FROM employee WHERE name = ?", std::vector<std::string>{ "zhangsan" });
129     EXPECT_NE(nullptr, resultSet);
130 
131     int columnIndex;
132     int intVal;
133     std::string strVal;
134     ColumnType columnType;
135     int position;
136     int ret = resultSet->GetRowIndex(position);
137     EXPECT_EQ(E_OK, ret);
138     EXPECT_EQ(-1, position);
139 
140     ret = resultSet->GetColumnType(0, columnType);
141     EXPECT_EQ(E_ROW_OUT_RANGE, ret);
142 
143     ret = resultSet->GoToFirstRow();
144     EXPECT_EQ(E_OK, ret);
145 
146     ret = resultSet->GetColumnIndex("id", columnIndex);
147     EXPECT_EQ(E_OK, ret);
148     EXPECT_EQ(0, columnIndex);
149     ret = resultSet->GetColumnType(columnIndex, columnType);
150     EXPECT_EQ(E_OK, ret);
151     EXPECT_EQ(columnType, ColumnType::TYPE_INTEGER);
152     ret = resultSet->GetInt(columnIndex, intVal);
153     EXPECT_EQ(E_OK, ret);
154     EXPECT_EQ(1, intVal);
155 
156     ret = resultSet->GetColumnIndex("name", columnIndex);
157     EXPECT_EQ(E_OK, ret);
158     ret = resultSet->GetColumnType(columnIndex, columnType);
159     EXPECT_EQ(E_OK, ret);
160     EXPECT_EQ(ColumnType::TYPE_STRING, columnType);
161     ret = resultSet->GetString(columnIndex, strVal);
162     EXPECT_EQ(E_OK, ret);
163     EXPECT_EQ("zhangsan", strVal);
164 }
165 
166 /**
167  * @tc.name: RdbStore_Distributed_Test_001
168  * @tc.desc: test RdbStore set distributed tables
169  * @tc.type: FUNC
170  */
171 HWTEST_F(RdbStoreDistributedTest, RdbStore_Distributed_001, TestSize.Level1)
172 {
173     EXPECT_NE(nullptr, rdbStore);
174     InsertValue(rdbStore);
175     CheckResultSet(rdbStore);
176 }
177 
178 /**
179  * @tc.name: RdbStore_Distributed_Test_002
180  * @tc.desc: Abnormal testCase of ObtainDistributedTableName, if networkId is ""
181  * @tc.type: FUNC
182  */
183 HWTEST_F(RdbStoreDistributedTest, RdbStore_Distributed_002, TestSize.Level2)
184 {
185     EXPECT_NE(nullptr, rdbStore);
186     int errCode;
187     EXPECT_EQ("", rdbStore->ObtainDistributedTableName("", "employee", errCode));
188     EXPECT_EQ(-1, errCode);
189 }
190 
191 /**
192  * @tc.name: RdbStore_Distributed_Test_003
193  * @tc.desc: Abnormal testCase of ObtainDistributedTableName, if networkId is invalid
194  * @tc.type: FUNC
195  */
196 HWTEST_F(RdbStoreDistributedTest, RdbStore_Distributed_003, TestSize.Level2)
197 {
198     EXPECT_NE(nullptr, rdbStore);
199     int errCode;
200     EXPECT_EQ("", rdbStore->ObtainDistributedTableName("123456", "employee", errCode));
201     EXPECT_EQ(-1, errCode);
202 }
203 
204 /**
205  * @tc.name: RdbStore_Distributed_Test_004
206  * @tc.desc: Abnormal testCase of SetDistributedTables
207  * @tc.type: FUNC
208  */
209 HWTEST_F(RdbStoreDistributedTest, RdbStore_Distributed_Test_004, TestSize.Level2)
210 {
211     int errCode;
212     std::vector<std::string> tables;
213     OHOS::DistributedRdb::DistributedConfig distributedConfig;
214 
215     // if tabels empty, return ok
216     errCode = rdbStore->SetDistributedTables(tables, 1, distributedConfig);
217     EXPECT_EQ(E_OK, errCode);
218 
219     // if tabels not empty, IPC_SEND failed
220     tables.push_back("employee");
221     errCode = rdbStore->SetDistributedTables(tables, 1, distributedConfig);
222     EXPECT_NE(E_OK, errCode);
223 
224     std::string path = RdbStoreDistributedTest::DRDB_PATH + "test.db";
225     RdbStoreConfig config(path);
226     TestOpenCallback callback;
227     std::shared_ptr<RdbStore> store = RdbHelper::GetRdbStore(config, 1, callback, errCode);
228     EXPECT_NE(nullptr, store);
229 
230     // if tabels not empty, bundleName empty
231     errCode = store->SetDistributedTables(tables, 1, distributedConfig);
232     EXPECT_EQ(E_INVALID_ARGS, errCode);
233 
234     RdbHelper::DeleteRdbStore(path);
235 }
236 
237 /**
238  * @tc.name: RdbStore_Distributed_Test_005
239  * @tc.desc: Normal testCase of Sync
240  * @tc.type: FUNC
241  */
242 HWTEST_F(RdbStoreDistributedTest, RdbStore_Distributed_Test_005, TestSize.Level2)
243 {
244     int errCode;
245     OHOS::DistributedRdb::SyncOption option = { OHOS::DistributedRdb::TIME_FIRST, false };
246     AbsRdbPredicates predicate("employee");
247     std::vector<std::string> tables;
248 
249     // get rdb service succeeded, if configuration file has already been configured
250     errCode = rdbStore->Sync(option, predicate, OHOS::DistributedRdb::AsyncBrief());
251     EXPECT_EQ(E_OK, errCode);
252 
253     errCode = rdbStore->Sync(option, tables, OHOS::DistributedRdb::AsyncDetail());
254     EXPECT_EQ(E_OK, errCode);
255 
256     errCode = rdbStore->Sync(option, predicate, OHOS::DistributedRdb::AsyncDetail());
257     EXPECT_EQ(E_OK, errCode);
258 
259     std::string path = RdbStoreDistributedTest::DRDB_PATH + "test.db";
260     RdbStoreConfig config(path);
261     TestOpenCallback callback;
262     std::shared_ptr<RdbStore> store = RdbHelper::GetRdbStore(config, 1, callback, errCode);
263     EXPECT_NE(nullptr, store);
264 
265     // get rdb service failed, if not configured
266     errCode = store->Sync(option, predicate, OHOS::DistributedRdb::AsyncBrief());
267     EXPECT_EQ(E_INVALID_ARGS, errCode);
268     errCode = store->Sync(option, tables, nullptr);
269     EXPECT_EQ(E_INVALID_ARGS, errCode);
270 
271     RdbHelper::DeleteRdbStore(path);
272 }