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
20 #include "common.h"
21 #include "rdb_errno.h"
22 #include "rdb_helper.h"
23 #include "rdb_open_callback.h"
24
25 using namespace testing::ext;
26 using namespace OHOS::NativeRdb;
27
28 class RdbAttachTest : public testing::Test {
29 public:
30 static void SetUpTestCase(void);
31 static void TearDownTestCase(void);
32 void SetUp();
33 void TearDown();
34 void QueryCheck1(std::shared_ptr<RdbStore> &store) const;
35 void QueryCheck2(std::shared_ptr<RdbStore> &store) const;
36
37 static const std::string MAIN_DATABASE_NAME;
38 static const std::string ATTACHED_DATABASE_NAME;
39 };
40
41 const std::string RdbAttachTest::MAIN_DATABASE_NAME = RDB_TEST_PATH + "main.db";
42
43 class MainOpenCallback : public RdbOpenCallback {
44 public:
45 int OnCreate(RdbStore &store) override;
46 int OnUpgrade(RdbStore &store, int oldVersion, int newVersion) override;
47 static const std::string CREATE_TABLE_TEST;
48 };
49
50 std::string const MainOpenCallback::CREATE_TABLE_TEST = "CREATE TABLE IF NOT EXISTS test1(id INTEGER PRIMARY KEY "
51 "AUTOINCREMENT, name TEXT NOT NULL)";
52
OnCreate(RdbStore & store)53 int MainOpenCallback::OnCreate(RdbStore &store)
54 {
55 return store.ExecuteSql(CREATE_TABLE_TEST);
56 }
57
OnUpgrade(RdbStore & store,int oldVersion,int newVersion)58 int MainOpenCallback::OnUpgrade(RdbStore &store, int oldVersion, int newVersion)
59 {
60 return E_OK;
61 }
62
63 const std::string RdbAttachTest::ATTACHED_DATABASE_NAME = RDB_TEST_PATH + "attached.db";
64
65 class AttachedOpenCallback : public RdbOpenCallback {
66 public:
67 int OnCreate(RdbStore &store) override;
68 int OnUpgrade(RdbStore &store, int oldVersion, int newVersion) override;
69 static const std::string CREATE_TABLE_TEST;
70 };
71
72 std::string const AttachedOpenCallback::CREATE_TABLE_TEST = "CREATE TABLE IF NOT EXISTS test2(id INTEGER PRIMARY KEY "
73 "AUTOINCREMENT, name TEXT NOT NULL)";
74
OnCreate(RdbStore & store)75 int AttachedOpenCallback::OnCreate(RdbStore &store)
76 {
77 return store.ExecuteSql(CREATE_TABLE_TEST);
78 }
79
OnUpgrade(RdbStore & store,int oldVersion,int newVersion)80 int AttachedOpenCallback::OnUpgrade(RdbStore &store, int oldVersion, int newVersion)
81 {
82 return E_OK;
83 }
84
SetUpTestCase(void)85 void RdbAttachTest::SetUpTestCase(void)
86 {
87 RdbStoreConfig attachedConfig(RdbAttachTest::ATTACHED_DATABASE_NAME);
88 AttachedOpenCallback attachedHelper;
89 int errCode = E_OK;
90 std::shared_ptr<RdbStore> attachedStore = RdbHelper::GetRdbStore(attachedConfig, 1, attachedHelper, errCode);
91 EXPECT_NE(attachedStore, nullptr);
92 }
93
TearDownTestCase(void)94 void RdbAttachTest::TearDownTestCase(void)
95 {
96 RdbHelper::DeleteRdbStore(MAIN_DATABASE_NAME);
97 RdbHelper::DeleteRdbStore(ATTACHED_DATABASE_NAME);
98 }
99
SetUp(void)100 void RdbAttachTest::SetUp(void)
101 {
102 }
103
TearDown(void)104 void RdbAttachTest::TearDown(void)
105 {
106 RdbHelper::ClearCache();
107 }
108
109 /**
110 * @tc.name: RdbStore_Attach_001
111 * @tc.desc: test attach, attach is not supported in wal mode
112 * @tc.type: FUNC
113 */
114 HWTEST_F(RdbAttachTest, RdbStore_Attach_001, TestSize.Level1)
115 {
116 RdbStoreConfig config(RdbAttachTest::MAIN_DATABASE_NAME);
117 MainOpenCallback helper;
118 int errCode = E_OK;
119 std::shared_ptr<RdbStore> store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
120 EXPECT_NE(store, nullptr);
121
122 int ret = store->ExecuteSql("ATTACH '" + ATTACHED_DATABASE_NAME + "' as attached");
123 EXPECT_EQ(ret, E_NOT_SUPPORTED_ATTACH_IN_WAL_MODE);
124 }
125
126 /**
127 * @tc.name: RdbStore_Attach_002
128 * @tc.desc: test RdbStore attach
129 * @tc.type: FUNC
130 */
131 HWTEST_F(RdbAttachTest, RdbStore_Attach_002, TestSize.Level1)
132 {
133 RdbStoreConfig config(RdbAttachTest::MAIN_DATABASE_NAME);
134 config.SetJournalMode(JournalMode::MODE_TRUNCATE);
135 MainOpenCallback helper;
136 int errCode = E_OK;
137 std::shared_ptr<RdbStore> store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
138 EXPECT_NE(store, nullptr);
139
140 int ret = store->ExecuteSql("ATTACH DATABASE '" + ATTACHED_DATABASE_NAME + "' as 'attached'");
141 EXPECT_EQ(ret, E_OK);
142
143 int64_t id;
144 ValuesBucket values;
145 values.PutInt("id", 1);
146 values.PutString("name", std::string("zhangsan"));
147 ret = store->Insert(id, "test1", values);
148 EXPECT_EQ(ret, E_OK);
149 EXPECT_EQ(id, 1);
150
151 values.Clear();
152 values.PutInt("id", 1);
153 values.PutString("name", std::string("lisi"));
154 ret = store->Insert(id, "test2", values);
155 EXPECT_EQ(ret, E_OK);
156 EXPECT_EQ(id, 1);
157
158 QueryCheck1(store);
159
160 ret = store->ExecuteSql("DETACH DATABASE 'attached'");
161 EXPECT_EQ(ret, E_OK);
162
163 QueryCheck2(store);
164
165 ret = store->ExecuteSql("attach database '" + ATTACHED_DATABASE_NAME + "' as 'attached'");
166 EXPECT_EQ(ret, E_OK);
167
168 ret = store->ExecuteSql("detach database 'attached'");
169 EXPECT_EQ(ret, E_OK);
170 }
171
172
173 /* *
174 * @tc.name: RdbStore_Attach_003
175 * @tc.desc: Abnormal testCase for Attach
176 * @tc.type: FUNC
177 */
178 HWTEST_F(RdbAttachTest, RdbStore_Attach_003, TestSize.Level2)
179 {
180 const std::string alias = "attached";
181 std::vector<uint8_t> destEncryptKey;
182 RdbStoreConfig config(RdbAttachTest::MAIN_DATABASE_NAME);
183 MainOpenCallback helper;
184 int errCode = E_OK;
185
186 // journal mode is wal
187 std::shared_ptr<RdbStore> store1 = RdbHelper::GetRdbStore(config, 1, helper, errCode);
188 EXPECT_NE(nullptr, store1);
189 EXPECT_EQ(E_OK, errCode);
190
191 int ret = store1->Attach(alias, RdbAttachTest::ATTACHED_DATABASE_NAME, destEncryptKey);
192 EXPECT_EQ(E_NOT_SUPPORTED_ATTACH_IN_WAL_MODE, ret);
193 RdbHelper::DeleteRdbStore(RdbAttachTest::MAIN_DATABASE_NAME);
194
195 // journal mode is TRUNCATE
196 // destEncryptKey is empty and isEncrypt_ is false
197 config.SetJournalMode(JournalMode::MODE_TRUNCATE);
198 std::shared_ptr<RdbStore> store2 = RdbHelper::GetRdbStore(config, 1, helper, errCode);
199 EXPECT_NE(nullptr, store2);
200 EXPECT_EQ(E_OK, errCode);
201 ret = store2->Attach(alias, RdbAttachTest::ATTACHED_DATABASE_NAME, destEncryptKey);
202 EXPECT_EQ(E_OK, ret);
203
204 // destEncryptKey is not empty and isEncrypt_ is false
205 destEncryptKey = {1};
206 ret = store2->Attach(alias, RdbAttachTest::ATTACHED_DATABASE_NAME, destEncryptKey);
207 EXPECT_NE(E_OK, ret);
208 RdbHelper::DeleteRdbStore(RdbAttachTest::MAIN_DATABASE_NAME);
209
210 // destEncryptKey is not empty and isEncrypt_ is true
211 config.SetEncryptStatus(true);
212 std::shared_ptr<RdbStore> store3 = RdbHelper::GetRdbStore(config, 1, helper, errCode);
213 EXPECT_NE(nullptr, store3);
214 EXPECT_EQ(E_OK, errCode);
215 ret = store3->Attach(alias, RdbAttachTest::ATTACHED_DATABASE_NAME, destEncryptKey);
216 EXPECT_NE(E_OK, ret);
217 }
218
QueryCheck1(std::shared_ptr<RdbStore> & store) const219 void RdbAttachTest::QueryCheck1(std::shared_ptr<RdbStore> &store) const
220 {
221 std::shared_ptr<ResultSet> resultSet = store->QuerySql("SELECT * FROM test1");
222 EXPECT_NE(resultSet, nullptr);
223 int ret = resultSet->GoToNextRow();
224 EXPECT_EQ(ret, E_OK);
225 int columnIndex;
226 int intVal;
227 ret = resultSet->GetColumnIndex("id", columnIndex);
228 EXPECT_EQ(ret, E_OK);
229 ret = resultSet->GetInt(columnIndex, intVal);
230 EXPECT_EQ(ret, E_OK);
231 EXPECT_EQ(intVal, 1);
232 std::string strVal;
233 ret = resultSet->GetColumnIndex("name", columnIndex);
234 EXPECT_EQ(ret, E_OK);
235 ret = resultSet->GetString(columnIndex, strVal);
236 EXPECT_EQ(ret, E_OK);
237 EXPECT_EQ(strVal, "zhangsan");
238
239 resultSet = store->QuerySql("SELECT * FROM test2");
240 EXPECT_NE(resultSet, nullptr);
241 ret = resultSet->GoToNextRow();
242 EXPECT_EQ(ret, E_OK);
243 ret = resultSet->GetColumnIndex("id", columnIndex);
244 EXPECT_EQ(ret, E_OK);
245 ret = resultSet->GetInt(columnIndex, intVal);
246 EXPECT_EQ(ret, E_OK);
247 EXPECT_EQ(intVal, 1);
248 ret = resultSet->GetColumnIndex("name", columnIndex);
249 EXPECT_EQ(ret, E_OK);
250 ret = resultSet->GetString(columnIndex, strVal);
251 EXPECT_EQ(ret, E_OK);
252 EXPECT_EQ(strVal, "lisi");
253 }
254
QueryCheck2(std::shared_ptr<RdbStore> & store) const255 void RdbAttachTest::QueryCheck2(std::shared_ptr<RdbStore> &store) const
256 {
257 std::shared_ptr<ResultSet> resultSet = store->QuerySql("SELECT * FROM test1");
258 EXPECT_NE(resultSet, nullptr);
259 int ret = resultSet->GoToNextRow();
260 EXPECT_EQ(ret, E_OK);
261 int columnIndex;
262 int intVal;
263 ret = resultSet->GetColumnIndex("id", columnIndex);
264 EXPECT_EQ(ret, E_OK);
265 ret = resultSet->GetInt(columnIndex, intVal);
266 EXPECT_EQ(ret, E_OK);
267 EXPECT_EQ(intVal, 1);
268 std::string strVal;
269 ret = resultSet->GetColumnIndex("name", columnIndex);
270 EXPECT_EQ(ret, E_OK);
271 ret = resultSet->GetString(columnIndex, strVal);
272 EXPECT_EQ(ret, E_OK);
273 EXPECT_EQ(strVal, "zhangsan");
274
275 // detached, no table test2
276 resultSet = store->QuerySql("SELECT * FROM test2");
277 EXPECT_NE(resultSet, nullptr);
278 }