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 <iostream>
19 #include <string>
20 #include <string_view>
21
22 #include "../common.h"
23 #include "block_data.h"
24 #include "executor_pool.h"
25 #include "rdb_errno.h"
26 #include "rdb_helper.h"
27 #include "rdb_open_callback.h"
28 #include "shared_block.h"
29 #include "sqlite_shared_result_set.h"
30 #include "step_result_set.h"
31
32 using namespace testing::ext;
33 using namespace OHOS;
34 using namespace OHOS::NativeRdb;
35 class RdbMultiThreadConnectionTest : public testing::Test {
36 public:
37 static void SetUpTestCase(void);
38 static void TearDownTestCase(void);
39 void SetUp();
40 void TearDown();
41 void GenerateData();
42
43 protected:
44 class Callback : public RdbOpenCallback {
45 public:
46 int OnCreate(RdbStore &rdbStore) override;
47 int OnUpgrade(RdbStore &rdbStore, int oldVersion, int newVersion) override;
48 };
49
50 static constexpr const char *DATABASE_NAME = "connection_test.db";
51 static constexpr const char *CREATE_TABLE_SQL = "CREATE TABLE test (id INTEGER PRIMARY KEY AUTOINCREMENT, name "
52 "TEXT NOT NULL, age INTEGER, salary REAL, blobType BLOB)";
53 static constexpr int32_t MAX_THREAD = 5;
54 static constexpr int32_t MIN_THREAD = 0;
55
56 std::shared_ptr<RdbStore> store_;
57 std::shared_ptr<ExecutorPool> executors_;
58 };
59
OnCreate(RdbStore & rdbStore)60 int RdbMultiThreadConnectionTest::Callback::OnCreate(RdbStore &rdbStore)
61 {
62 return E_OK;
63 }
64
OnUpgrade(RdbStore & rdbStore,int oldVersion,int newVersion)65 int RdbMultiThreadConnectionTest::Callback::OnUpgrade(RdbStore &rdbStore, int oldVersion, int newVersion)
66 {
67 return E_OK;
68 }
69
SetUpTestCase(void)70 void RdbMultiThreadConnectionTest::SetUpTestCase(void)
71 {
72 }
73
TearDownTestCase(void)74 void RdbMultiThreadConnectionTest::TearDownTestCase(void)
75 {
76 }
77
SetUp()78 void RdbMultiThreadConnectionTest::SetUp()
79 {
80 executors_ = std::make_shared<ExecutorPool>(MAX_THREAD, MIN_THREAD);
81 store_ = nullptr;
82 RdbHelper::DeleteRdbStore(RDB_TEST_PATH + DATABASE_NAME);
83 RdbStoreConfig sqliteSharedRstConfig(RDB_TEST_PATH + DATABASE_NAME);
84 RdbMultiThreadConnectionTest::Callback sqliteSharedRstHelper;
85 int errCode = E_OK;
86 store_ = RdbHelper::GetRdbStore(sqliteSharedRstConfig, 1, sqliteSharedRstHelper, errCode);
87 EXPECT_NE(store_, nullptr);
88
89 auto ret = store_->ExecuteSql(CREATE_TABLE_SQL);
90 EXPECT_EQ(ret, E_OK);
91 GenerateData();
92 }
93
TearDown()94 void RdbMultiThreadConnectionTest::TearDown()
95 {
96 executors_ = nullptr;
97 store_ = nullptr;
98 RdbHelper::DeleteRdbStore(RDB_TEST_PATH + DATABASE_NAME);
99 }
100
GenerateData()101 void RdbMultiThreadConnectionTest::GenerateData()
102 {
103 int64_t id;
104 // 0 represent that get first data
105 auto ret = store_->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0]));
106 EXPECT_EQ(E_OK, ret);
107 // id is 1
108 EXPECT_EQ(1, id);
109
110 // 1 represent that get second data
111 ret = store_->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[1]));
112 EXPECT_EQ(E_OK, ret);
113 // id is 2
114 EXPECT_EQ(2, id);
115
116 // 2 represent that get third data
117 ret = store_->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[2]));
118 EXPECT_EQ(E_OK, ret);
119 // id is 3
120 EXPECT_EQ(3, id);
121 }
122
123 /**
124 * @tc.name: MultiThread_Connection_0001
125 * if connect is not nullptr when query by calling function querySql while creating table.
126 * @tc.desc: 1.thread 1: query
127 * 2.thread 2: create table
128 * @tc.type: FUNC
129 * @tc.author: leiyanbo
130 */
131 HWTEST_F(RdbMultiThreadConnectionTest, MultiThread_Connection_0001, TestSize.Level2)
132 {
133 std::shared_ptr<BlockData<int32_t>> block1 = std::make_shared<BlockData<int32_t>>(3, false);
__anon0c485b230102() 134 auto taskId1 = executors_->Execute([store = store_, block1]() {
135 constexpr const char *createTable = "CREATE TABLE test";
136 constexpr const char *createTableColumn = " (id INTEGER PRIMARY KEY AUTOINCREMENT, "
137 "name TEXT NOT NULL, age INTEGER, salary REAL, "
138 "blobType BLOB)";
139 int32_t errCode = E_ERROR;
140 for (uint32_t i = 0; i < 2000; i++) {
141 errCode = store->ExecuteSql(createTable + std::to_string(i) + createTableColumn);
142 if (errCode != E_OK) {
143 break;
144 }
145 }
146 block1->SetValue(errCode);
147 });
148
149 std::shared_ptr<BlockData<int32_t>> block2 = std::make_shared<BlockData<int32_t>>(3, false);
__anon0c485b230202() 150 auto taskId2 = executors_->Execute([store = store_, block2]() {
151 int32_t errCode = E_ERROR;
152 for (uint32_t i = 0; i < 2000; i++) {
153 auto resultSet = store->QuerySql("SELECT * FROM test");
154 int rowCount = -1;
155 errCode = resultSet->GetRowCount(rowCount);
156 resultSet->Close();
157 if (errCode != E_OK && errCode != E_SQLITE_SCHEMA) {
158 break;
159 }
160 }
161 auto code = (errCode == E_OK || errCode == E_SQLITE_SCHEMA) ? E_OK : errCode;
162 block2->SetValue(code);
163 });
164
165 EXPECT_EQ(block1->GetValue(), E_OK);
166 EXPECT_EQ(block2->GetValue(), E_OK);
167 EXPECT_NE(taskId1, taskId2);
168 }
169
170 /**
171 * @tc.name: MultiThread_Connection_0002
172 * if connect is not nullptr when query by calling function queryByStep while creating table.
173 * @tc.desc: 1.thread 1: query
174 * 2.thread 2: create table
175 * @tc.type: FUNC
176 * @tc.author: leiyanbo
177 */
178 HWTEST_F(RdbMultiThreadConnectionTest, MultiThread_Connection_0002, TestSize.Level2)
179 {
180 std::shared_ptr<BlockData<int32_t>> block1 = std::make_shared<BlockData<int32_t>>(3, false);
__anon0c485b230302() 181 auto taskId1 = executors_->Execute([store = store_, block1]() {
182 constexpr const char *createTable = "CREATE TABLE test";
183 constexpr const char *createTableColumn = " (id INTEGER PRIMARY KEY AUTOINCREMENT, "
184 "name TEXT NOT NULL, age INTEGER, salary REAL, "
185 "blobType BLOB)";
186 int32_t errCode = E_ERROR;
187 for (uint32_t i = 0; i < 2000; i++) {
188 errCode = store->ExecuteSql(createTable + std::to_string(i) + createTableColumn);
189 if (errCode != E_OK) {
190 break;
191 }
192 }
193 block1->SetValue(errCode);
194 });
195
196 std::shared_ptr<BlockData<int32_t>> block2 = std::make_shared<BlockData<int32_t>>(3, false);
__anon0c485b230402() 197 auto taskId2 = executors_->Execute([store = store_, block2]() {
198 int32_t errCode = E_ERROR;
199 for (uint32_t i = 0; i < 2000; i++) {
200 auto resultSet = store->QueryByStep("SELECT * FROM test");
201 int rowCount = -1;
202 errCode = resultSet->GetRowCount(rowCount);
203 resultSet->Close();
204 if (errCode != E_OK && errCode != E_SQLITE_SCHEMA) {
205 break;
206 }
207 }
208 auto code = (errCode == E_OK || errCode == E_SQLITE_SCHEMA) ? E_OK : errCode;
209 block2->SetValue(code);
210 });
211
212 EXPECT_EQ(block1->GetValue(), E_OK);
213 EXPECT_EQ(block2->GetValue(), E_OK);
214 EXPECT_NE(taskId1, taskId2);
215 }
216