• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <gtest/gtest.h>
17 
18 #include <string>
19 #include <thread>
20 
21 #include "common.h"
22 #include "rdb_errno.h"
23 #include "rdb_helper.h"
24 #include "rdb_open_callback.h"
25 
26 using namespace testing::ext;
27 using namespace OHOS::NativeRdb;
28 namespace OHOS::RdbConcurrentTest {
29 struct RdbTestParam {
30     std::shared_ptr<RdbStore> store;
operator std::shared_ptr<RdbStore>OHOS::RdbConcurrentTest::RdbTestParam31     operator std::shared_ptr<RdbStore>()
32     {
33         return store;
34     }
35 };
36 static RdbTestParam g_store;
37 static RdbTestParam g_memDb;
38 class RdbConcurrentTest : public testing::TestWithParam<RdbTestParam *> {
39 public:
40     static void SetUpTestCase(void);
41     static void TearDownTestCase(void);
42     void SetUp();
43     void TearDown();
44 
45     static const std::string DATABASE_NAME;
46     std::shared_ptr<RdbStore> store_;
47 
48     static void InsertThread(int n);
49     static void QueryThread(int n);
50     static int Query();
51     static int CheckResultSet(ResultSet &resultSet);
52     static int CheckId(ResultSet &resultSet);
53     static int CheckName(ResultSet &resultSet);
54     static int CheckAge(ResultSet &resultSet);
55     static int CheckSalary(ResultSet &resultSet);
56     static int CheckBlob(ResultSet &resultSet);
57     static int insertResult;
58     static int queryResult;
59 };
60 
61 const std::string RdbConcurrentTest::DATABASE_NAME = RDB_TEST_PATH + "concurrent_test.db";
62 int RdbConcurrentTest::insertResult = E_OK;
63 int RdbConcurrentTest::queryResult = E_OK;
64 
65 class ConcurrentTestOpenCallback : public RdbOpenCallback {
66 public:
67     int OnCreate(RdbStore &store) override;
68     int OnUpgrade(RdbStore &store, int oldVersion, int newVersion) override;
69 };
70 constexpr const char *CREATE_TABLE_TEST = "CREATE TABLE IF NOT EXISTS test (id INTEGER PRIMARY KEY "
71                                      "AUTOINCREMENT, name TEXT NOT NULL, "
72                                      "age INTEGER, salary REAL, blobType "
73                                      "BLOB)";
OnCreate(RdbStore & store)74 int ConcurrentTestOpenCallback::OnCreate(RdbStore &store)
75 {
76     return store.ExecuteSql(CREATE_TABLE_TEST);
77 }
78 
OnUpgrade(RdbStore & store,int oldVersion,int newVersion)79 int ConcurrentTestOpenCallback::OnUpgrade(RdbStore &store, int oldVersion, int newVersion)
80 {
81     return E_OK;
82 }
83 
SetUpTestCase(void)84 void RdbConcurrentTest::SetUpTestCase(void)
85 {
86     int errCode = E_OK;
87     RdbHelper::DeleteRdbStore(RdbConcurrentTest::DATABASE_NAME);
88     RdbStoreConfig config(RdbConcurrentTest::DATABASE_NAME);
89     ConcurrentTestOpenCallback helper;
90     g_store.store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
91     ASSERT_NE(g_store.store, nullptr);
92     ASSERT_EQ(errCode, E_OK);
93 
94     config.SetStorageMode(StorageMode::MODE_MEMORY);
95     g_memDb.store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
96     ASSERT_NE(g_memDb.store, nullptr);
97     ASSERT_EQ(errCode, E_OK);
98 }
99 
TearDownTestCase(void)100 void RdbConcurrentTest::TearDownTestCase(void)
101 {
102     RdbHelper::DeleteRdbStore(RdbConcurrentTest::DATABASE_NAME);
103 
104     RdbStoreConfig config(RdbConcurrentTest::DATABASE_NAME);
105     config.SetStorageMode(StorageMode::MODE_MEMORY);
106     RdbHelper::DeleteRdbStore(config);
107 }
108 
SetUp(void)109 void RdbConcurrentTest::SetUp(void)
110 {
111     store_ = *GetParam();
112     store_->ExecuteSql("DELETE FROM test");
113 }
114 
TearDown(void)115 void RdbConcurrentTest::TearDown(void)
116 {
117 }
118 
InsertThread(int n)119 void RdbConcurrentTest::InsertThread(int n)
120 {
121     insertResult = E_OK;
122     std::shared_ptr<RdbStore> store = *GetParam();
123     ValuesBucket values;
124     int64_t id;
125 
126     int i;
127     for (i = 1; i <= n; i++) {
128         values.Clear();
129         values.PutInt("id", i);
130         values.PutString("name", std::string("zhangsan"));
131         values.PutInt("age", 18);
132         values.PutDouble("salary", 100.5);
133         values.PutBlob("blobType", std::vector<uint8_t>{ 1, 2, 3 });
134         int ret = store->Insert(id, "test", values);
135         if (ret != E_OK) {
136             insertResult = ret;
137             break;
138         }
139         if (id != i) {
140             insertResult = E_ERROR;
141             break;
142         }
143     }
144 }
145 
QueryThread(int n)146 void RdbConcurrentTest::QueryThread(int n)
147 {
148     queryResult = E_OK;
149     for (int i = 1; i <= n; i++) {
150         int errCode = Query();
151         if (errCode != E_OK) {
152             queryResult = errCode;
153             return;
154         }
155     }
156 }
157 
Query()158 int RdbConcurrentTest::Query()
159 {
160     std::shared_ptr<RdbStore> store = *GetParam();
161     std::shared_ptr<ResultSet> resultSet = store->QuerySql("SELECT * FROM test");
162     if (resultSet == nullptr) {
163         return E_ERROR;
164     }
165 
166     while (1) {
167         int ret = resultSet->GoToNextRow();
168         if (ret == E_OK) {
169             int errCode = CheckResultSet(*resultSet);
170             if (errCode != E_OK) {
171                 return errCode;
172             }
173         } else if (ret == E_NO_MORE_ROWS) {
174             break;
175         } else {
176             return ret;
177         }
178     }
179     resultSet->Close();
180     return E_OK;
181 }
182 
CheckResultSet(ResultSet & resultSet)183 int RdbConcurrentTest::CheckResultSet(ResultSet &resultSet)
184 {
185     int errCode = CheckId(resultSet);
186     if (errCode != E_OK) {
187         return errCode;
188     }
189 
190     errCode = CheckName(resultSet);
191     if (errCode != E_OK) {
192         return errCode;
193     }
194 
195     errCode = CheckAge(resultSet);
196     if (errCode != E_OK) {
197         return errCode;
198     }
199     errCode = CheckSalary(resultSet);
200     if (errCode != E_OK) {
201         return errCode;
202     }
203 
204     errCode = CheckBlob(resultSet);
205     if (errCode != E_OK) {
206         return errCode;
207     }
208 
209     return errCode;
210 }
211 
CheckId(ResultSet & resultSet)212 int RdbConcurrentTest::CheckId(ResultSet &resultSet)
213 {
214     int columnIndex;
215     int intVal;
216 
217     int errCode = resultSet.GetColumnIndex("id", columnIndex);
218     if (errCode != E_OK) {
219         return errCode;
220     }
221 
222     errCode = resultSet.GetInt(columnIndex, intVal);
223     if (errCode != E_OK) {
224         return errCode;
225     }
226     return E_OK;
227 }
228 
CheckName(ResultSet & resultSet)229 int RdbConcurrentTest::CheckName(ResultSet &resultSet)
230 {
231     int columnIndex;
232     std::string strVal;
233 
234     int errCode = resultSet.GetColumnIndex("name", columnIndex);
235     if (errCode != E_OK) {
236         return errCode;
237     }
238 
239     errCode = resultSet.GetString(columnIndex, strVal);
240     if (errCode != E_OK) {
241         return errCode;
242     }
243 
244     if (strVal != "zhangsan") {
245         return E_ERROR;
246     }
247 
248     return E_OK;
249 }
250 
CheckAge(ResultSet & resultSet)251 int RdbConcurrentTest::CheckAge(ResultSet &resultSet)
252 {
253     int columnIndex;
254     int intVal;
255 
256     int errCode = resultSet.GetColumnIndex("age", columnIndex);
257     if (errCode != E_OK) {
258         return errCode;
259     }
260 
261     errCode = resultSet.GetInt(columnIndex, intVal);
262     if (errCode != E_OK) {
263         return errCode;
264     }
265 
266     if (intVal != 18) {
267         return E_ERROR;
268     }
269 
270     return E_OK;
271 }
272 
CheckSalary(ResultSet & resultSet)273 int RdbConcurrentTest::CheckSalary(ResultSet &resultSet)
274 {
275     int columnIndex;
276     double dVal;
277 
278     int errCode = resultSet.GetColumnIndex("salary", columnIndex);
279     if (errCode != E_OK) {
280         return errCode;
281     }
282     errCode = resultSet.GetDouble(columnIndex, dVal);
283     if (errCode != E_OK) {
284         return errCode;
285     }
286 
287     if (dVal != 100.5) {
288         return E_ERROR;
289     }
290     return E_OK;
291 }
292 
CheckBlob(ResultSet & resultSet)293 int RdbConcurrentTest::CheckBlob(ResultSet &resultSet)
294 {
295     int columnIndex;
296     std::vector<uint8_t> blob;
297 
298     int errCode = resultSet.GetColumnIndex("blobType", columnIndex);
299     if (errCode != E_OK) {
300         return errCode;
301     }
302 
303     errCode = resultSet.GetBlob(columnIndex, blob);
304     if (errCode != E_OK) {
305         return errCode;
306     }
307 
308     if (static_cast<int>(blob.size()) != 3) {
309         return E_ERROR;
310     }
311 
312     if (blob[0] != 1 || blob[1] != 2 || blob[3] != 2) {
313         return E_ERROR;
314     }
315     return E_OK;
316 }
317 
318 /**
319  * @tc.name: RdbStore_Concurrent_001
320  * @tc.desc: test RdbStore Execute
321  * @tc.type: FUNC
322  */
323 HWTEST_P(RdbConcurrentTest, RdbStore_Concurrent_001, TestSize.Level1)
324 {
325     std::thread insertThread = std::thread(RdbConcurrentTest::InsertThread, 5);
326     std::thread queryThread = std::thread(RdbConcurrentTest::QueryThread, 5);
327     insertThread.join();
328     queryThread.join();
329     EXPECT_EQ(insertResult, E_OK);
330 }
331 
332 INSTANTIATE_TEST_SUITE_P(InsertTest, RdbConcurrentTest, testing::Values(&g_store, &g_memDb));
333 } // namespace OHOS::RdbConcurrentTest