• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 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 #include <gtest/gtest.h>
16 #include <gtest/hwext/gtest-multithread.h>
17 #include <sys/types.h>
18 
19 #include <chrono>
20 #include <cstdint>
21 #include <future>
22 #include <map>
23 #include <memory>
24 #include <ostream>
25 #include <string>
26 #include <thread>
27 
28 #include "../common.h"
29 #include "rdb_errno.h"
30 #include "rdb_helper.h"
31 #include "rdb_open_callback.h"
32 #include "rdb_store.h"
33 #include "rdb_store_impl.h"
34 
35 using namespace testing::ext;
36 using namespace testing::mt;
37 using namespace OHOS::NativeRdb;
38 
39 class RdbMultiProcessCreateDBTest : public testing::Test {
40 public:
SetUpTestCase()41     static void SetUpTestCase(){};
TearDownTestCase()42     static void TearDownTestCase(){};
SetUp()43     void SetUp(){};
TearDown()44     void TearDown(){};
45     static const std::string databaseName;
46     static const std::string createTabSql;
47     static void Create();
48 
49     class Callback : public RdbOpenCallback {
50     public:
51         int OnCreate(RdbStore &rdbStore) override;
52         int OnUpgrade(RdbStore &rdbStore, int oldVersion, int newVersion) override;
53     };
54 };
55 const std::string RdbMultiProcessCreateDBTest::databaseName = "multi_process_create_test.db";
56 const std::string RdbMultiProcessCreateDBTest::createTabSql =
57     "CREATE TABLE IF NOT EXISTS test "
58     "(id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, age INTEGER, salary REAL, blobType BLOB)";
59 
60 static constexpr uint32_t RETRY_COUNT = 2;
61 static constexpr int32_t SLEEP_TIME = 500;
62 
OnCreate(RdbStore & store)63 int RdbMultiProcessCreateDBTest::Callback::OnCreate(RdbStore &store)
64 {
65     return store.ExecuteSql(createTabSql);
66 }
67 
OnUpgrade(RdbStore & store,int oldVersion,int newVersion)68 int RdbMultiProcessCreateDBTest::Callback::OnUpgrade(RdbStore &store, int oldVersion, int newVersion)
69 {
70     return E_OK;
71 }
72 
CheckAge(std::shared_ptr<ResultSet> & resultSet)73 void CheckAge(std::shared_ptr<ResultSet> &resultSet)
74 {
75     int columnIndex;
76     int intVal;
77     ColumnType columnType;
78     int ret = resultSet->GetColumnIndex("age", columnIndex);
79     EXPECT_EQ(ret, E_OK);
80     ret = resultSet->GetColumnType(columnIndex, columnType);
81     EXPECT_EQ(ret, E_OK);
82     EXPECT_EQ(columnType, ColumnType::TYPE_INTEGER);
83     ret = resultSet->GetInt(columnIndex, intVal);
84     EXPECT_EQ(ret, E_OK);
85     // 18: age is 18
86     EXPECT_EQ(18, intVal);
87 }
88 
CheckSalary(std::shared_ptr<ResultSet> & resultSet)89 void CheckSalary(std::shared_ptr<ResultSet> &resultSet)
90 {
91     int columnIndex;
92     double dVal;
93     ColumnType columnType;
94     int ret = resultSet->GetColumnIndex("salary", columnIndex);
95     EXPECT_EQ(ret, E_OK);
96     ret = resultSet->GetColumnType(columnIndex, columnType);
97     EXPECT_EQ(ret, E_OK);
98     EXPECT_EQ(columnType, ColumnType::TYPE_FLOAT);
99     ret = resultSet->GetDouble(columnIndex, dVal);
100     EXPECT_EQ(ret, E_OK);
101     // 100.5: salary is 100.5
102     EXPECT_EQ(100.5, dVal);
103 }
104 
CheckBlob(std::shared_ptr<ResultSet> & resultSet)105 void CheckBlob(std::shared_ptr<ResultSet> &resultSet)
106 {
107     int columnIndex;
108     std::vector<uint8_t> blob;
109     ColumnType columnType;
110     int ret = resultSet->GetColumnIndex("blobType", columnIndex);
111     EXPECT_EQ(ret, E_OK);
112     ret = resultSet->GetColumnType(columnIndex, columnType);
113     EXPECT_EQ(ret, E_OK);
114     EXPECT_EQ(columnType, ColumnType::TYPE_BLOB);
115     ret = resultSet->GetBlob(columnIndex, blob);
116     EXPECT_EQ(ret, E_OK);
117     // 3: blob size
118     EXPECT_EQ(3, static_cast<int>(blob.size()));
119     // 1: blob[0] is 1
120     EXPECT_EQ(1, blob[0]);
121     // 2: blob[1] is 2
122     EXPECT_EQ(2, blob[1]);
123     // 3: blob[2] is 3
124     EXPECT_EQ(3, blob[2]);
125 }
126 
CheckResultSet(std::shared_ptr<RdbStore> & store)127 void CheckResultSet(std::shared_ptr<RdbStore> &store)
128 {
129     std::shared_ptr<ResultSet> resultSet =
130         store->QuerySql("SELECT * FROM test WHERE name = ?", std::vector<std::string>{ "zhangsan" });
131     EXPECT_NE(resultSet, nullptr);
132 
133     int columnIndex;
134     int intVal;
135     std::string strVal;
136     ColumnType columnType;
137     int position;
138     int ret = resultSet->GetRowIndex(position);
139     EXPECT_EQ(ret, E_OK);
140     EXPECT_EQ(position, -1);
141 
142     ret = resultSet->GetColumnType(0, columnType);
143     EXPECT_EQ(ret, E_ROW_OUT_RANGE);
144 
145     ret = resultSet->GoToFirstRow();
146     EXPECT_EQ(ret, E_OK);
147 
148     ret = resultSet->GetColumnIndex("id", columnIndex);
149     EXPECT_EQ(ret, E_OK);
150     EXPECT_EQ(columnIndex, 0);
151     ret = resultSet->GetColumnType(columnIndex, columnType);
152     EXPECT_EQ(ret, E_OK);
153     EXPECT_EQ(columnType, ColumnType::TYPE_INTEGER);
154     ret = resultSet->GetInt(columnIndex, intVal);
155     EXPECT_EQ(ret, E_OK);
156     EXPECT_EQ(1, intVal);
157 
158     ret = resultSet->GetColumnIndex("name", columnIndex);
159     EXPECT_EQ(ret, E_OK);
160     ret = resultSet->GetColumnType(columnIndex, columnType);
161     EXPECT_EQ(ret, E_OK);
162     EXPECT_EQ(columnType, ColumnType::TYPE_STRING);
163     ret = resultSet->GetString(columnIndex, strVal);
164     EXPECT_EQ(ret, E_OK);
165     EXPECT_EQ("zhangsan", strVal);
166 
167     CheckAge(resultSet);
168     CheckSalary(resultSet);
169     CheckBlob(resultSet);
170 
171     ret = resultSet->Close();
172     EXPECT_EQ(ret, E_OK);
173 }
174 
Create()175 void RdbMultiProcessCreateDBTest::Create()
176 {
177     int errCode = E_OK;
178     RdbStoreConfig config(RDB_TEST_PATH + RdbMultiProcessCreateDBTest::databaseName);
179     config.SetEncryptStatus(true);
180     RdbMultiProcessCreateDBTest::Callback helper;
181     for (uint32_t retry = 0; retry < RETRY_COUNT; ++retry) {
182         auto store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
183         EXPECT_TRUE(errCode == E_SQLITE_BUSY || errCode == E_OK);
184         if (errCode != E_SQLITE_BUSY) {
185             EXPECT_NE(store, nullptr);
186             break;
187         }
188         std::this_thread::sleep_for(std::chrono::milliseconds(SLEEP_TIME));
189     }
190     auto store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
191     EXPECT_TRUE(errCode == E_SQLITE_BUSY || errCode == E_OK);
192     ASSERT_NE(store, nullptr);
193 
194     int64_t id;
195     ValuesBucket values;
196     values.Put("name", "zhangsan");
197     // 18: age is 18
198     values.Put("age", 18);
199     // 100.5: salary is 100.5
200     values.Put("salary", 100.5);
201     values.Put("blobType", std::vector<uint8_t>{ 1, 2, 3 });
202     int ret = store->Insert(id, "test", values);
203     EXPECT_EQ(ret, E_OK);
204 
205     CheckResultSet(store);
206     // 2: await 2s
207     std::this_thread::sleep_for(std::chrono::seconds(2));
208     RdbHelper::DeleteRdbStore(RDB_TEST_PATH + RdbMultiProcessCreateDBTest::databaseName);
209 }
210 
211 /* *
212  * @tc.name: Rdb_ConcurrentCreate_001
213  * @tc.desc: tow processes create database at the same time
214  * @tc.type: FUNC
215  */
216 HWTEST_F(RdbMultiProcessCreateDBTest, Rdb_ConcurrentCreate_001, TestSize.Level1)
217 {
218     Create();
219 }
220 
main(int32_t argc,char * argv[])221 int32_t main(int32_t argc, char *argv[])
222 {
223     testing::GTEST_FLAG(output) = "xml:./";
224     testing::InitGoogleTest(&argc, argv);
225     pid_t pid = fork();
226     if (pid == 0) {
227         RdbMultiProcessCreateDBTest::Create();
228         exit(0);
229     } else if (pid < 0) {
230         return 1;
231     }
232     int res = RUN_ALL_TESTS();
233     if (pid > 0) {
234         int status;
235         waitpid(pid, &status, 0);
236     }
237     return res;
238 }