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