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 #ifdef RELATIONAL_STORE
16 #include <gtest/gtest.h>
17
18 #include "data_transformer.h"
19 #include "data_value.h"
20 #include "db_errno.h"
21 #include "distributeddb/result_set.h"
22 #include "distributeddb_tools_unit_test.h"
23 #include "log_print.h"
24 #include "relational_result_set_impl.h"
25 #include "relational_row_data.h"
26 #include "relational_row_data_impl.h"
27 #include "relational_row_data_set.h"
28 #include "relational_store_sqlite_ext.h"
29 #include "types_export.h"
30
31 using namespace testing::ext;
32 using namespace DistributedDB;
33 using namespace DistributedDBUnitTest;
34 using namespace std;
35
36 namespace {
37 string g_testDir;
38 string g_storePath;
39 string g_tableName { "data" };
40
41 const vector<uint8_t> BLOB_VALUE { 'a', 'b', 'l', 'o', 'b', '\0', 'e', 'n', 'd' };
42 const double DOUBLE_VALUE = 1.123456; // 1.123456 for test
43 const int64_t INT64_VALUE = 123456; // 123456 for test
44 const std::string STR_VALUE = "I'm a string.";
45
46 DataValue g_blobValue;
47 DataValue g_doubleValue;
48 DataValue g_int64Value;
49 DataValue g_nullValue;
50 DataValue g_strValue;
51
InitGlobalValue()52 void InitGlobalValue()
53 {
54 Blob *blob = new (std::nothrow) Blob();
55 blob->WriteBlob(BLOB_VALUE.data(), BLOB_VALUE.size());
56 g_blobValue.Set(blob);
57
58 g_doubleValue = DOUBLE_VALUE;
59 g_int64Value = INT64_VALUE;
60 g_strValue = STR_VALUE;
61 }
62
CreateDBAndTable()63 void CreateDBAndTable()
64 {
65 sqlite3 *db = nullptr;
66 int errCode = sqlite3_open(g_storePath.c_str(), &db);
67 if (errCode != SQLITE_OK) {
68 LOGE("open db failed:%d", errCode);
69 sqlite3_close(db);
70 return;
71 }
72
73 const string sql =
74 "PRAGMA journal_mode=WAL;"
75 "CREATE TABLE " + g_tableName + "(key INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, value INTEGER);";
76 char *zErrMsg = nullptr;
77 errCode = sqlite3_exec(db, sql.c_str(), nullptr, nullptr, &zErrMsg);
78 if (errCode != SQLITE_OK) {
79 LOGE("sql error:%s", zErrMsg);
80 sqlite3_free(zErrMsg);
81 }
82 sqlite3_close(db);
83 }
84 }
85
86 class DistributedDBRelationalResultSetTest : public testing::Test {
87 public:
88 static void SetUpTestCase();
89 static void TearDownTestCase();
90 void SetUp();
91 void TearDown();
92 };
93
SetUpTestCase(void)94 void DistributedDBRelationalResultSetTest::SetUpTestCase(void)
95 {
96 DistributedDBToolsUnitTest::TestDirInit(g_testDir);
97 InitGlobalValue();
98 g_storePath = g_testDir + "/relationalResultSetTest.db";
99 LOGI("The test db is:%s", g_testDir.c_str());
100 }
101
TearDownTestCase(void)102 void DistributedDBRelationalResultSetTest::TearDownTestCase(void) {}
103
SetUp(void)104 void DistributedDBRelationalResultSetTest::SetUp(void)
105 {
106 DistributedDBToolsUnitTest::PrintTestCaseInfo();
107 CreateDBAndTable();
108 }
109
TearDown(void)110 void DistributedDBRelationalResultSetTest::TearDown(void)
111 {
112 if (DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir) != 0) {
113 LOGE("rm test db files error.");
114 }
115 }
116
117 /**
118 * @tc.name: SerializeAndDeserialize
119 * @tc.desc: Serialize and deserialize.
120 * @tc.type: FUNC
121 * @tc.require:
122 * @tc.author: lidongwei
123 */
124 HWTEST_F(DistributedDBRelationalResultSetTest, SerializeAndDeserialize, TestSize.Level1)
125 {
126 RowData data1 {g_strValue, g_int64Value, g_doubleValue, g_blobValue, g_nullValue};
127 RowData data2 {g_nullValue, g_blobValue, g_doubleValue, g_int64Value, g_strValue}; // data1.reverse()
128
129 auto rowDataImpl1 = new (std::nothrow) RelationalRowDataImpl(std::move(data1));
130 auto rowDataImpl2 = new (std::nothrow) RelationalRowDataImpl(std::move(data2));
131
132 /**
133 * @tc.steps: step1. Create a row data set which contains two row data;
134 * @tc.expected: OK.
135 */
136 RelationalRowDataSet rowDataSet1;
137 rowDataSet1.SetColNames({"column 1", "column 2", "column 3", "column 4", "column 5"});
138 rowDataSet1.Insert(rowDataImpl1);
139 rowDataSet1.Insert(rowDataImpl2);
140
141 /**
142 * @tc.steps: step2. Serialize the row data set;
143 * @tc.expected: Serialize OK.
144 */
145 auto bufferLength = rowDataSet1.CalcLength();
146 vector<uint8_t> buffer1(bufferLength);
147 Parcel parcel1(buffer1.data(), buffer1.size());
148 ASSERT_EQ(rowDataSet1.Serialize(parcel1), E_OK);
149 ASSERT_FALSE(parcel1.IsError());
150
151 /**
152 * @tc.steps: step3. Deserialize the row data set;
153 * @tc.expected: Deserialize OK.
154 */
155 vector<uint8_t> buffer2 = buffer1;
156 Parcel parcel2(buffer2.data(), buffer2.size());
157 RelationalRowDataSet rowDataSet2;
158 ASSERT_EQ(rowDataSet2.DeSerialize(parcel2), E_OK);
159 ASSERT_FALSE(parcel2.IsError());
160
161 /**
162 * @tc.steps: step4. Compare the deserialized row data set with the original;
163 * @tc.expected: Compare OK. They are the same.
164 */
165 std::vector<std::string> colNames {"column 1", "column 2", "column 3", "column 4", "column 5"};
166 EXPECT_EQ(rowDataSet2.GetColNames(), colNames);
167
168 // test the second row. if the second row ok, the first row is likely ok
169 StorageType type = StorageType::STORAGE_TYPE_NONE;
170 EXPECT_EQ(rowDataSet2.Get(1)->GetType(0, type), E_OK);
171 EXPECT_EQ(type, StorageType::STORAGE_TYPE_NULL);
172
173 vector<uint8_t> desBlob;
174 EXPECT_EQ(rowDataSet2.Get(1)->Get(1, desBlob), E_OK);
175 EXPECT_EQ(desBlob, BLOB_VALUE);
176
177 double desDoub;
178 EXPECT_EQ(rowDataSet2.Get(1)->Get(2, desDoub), E_OK);
179 EXPECT_EQ(desDoub, DOUBLE_VALUE);
180
181 int64_t desInt64;
182 EXPECT_EQ(rowDataSet2.Get(1)->Get(3, desInt64), E_OK);
183 EXPECT_EQ(desInt64, INT64_VALUE);
184
185 std::string desStr;
186 EXPECT_EQ(rowDataSet2.Get(1)->Get(4, desStr), E_OK);
187 EXPECT_EQ(desStr, STR_VALUE);
188 }
189
190 /**
191 * @tc.name: Put
192 * @tc.desc: Test put into result set
193 * @tc.type: FUNC
194 * @tc.require:
195 * @tc.author: lidongwei
196 */
197 HWTEST_F(DistributedDBRelationalResultSetTest, Put, TestSize.Level1)
198 {
199 RowData data1 {g_strValue, g_int64Value, g_doubleValue, g_blobValue, g_nullValue};
200 RowData data2 {g_nullValue, g_blobValue, g_doubleValue, g_int64Value, g_strValue}; // data1.reverse()
201 RowData data3 {g_strValue, g_int64Value, g_doubleValue, g_blobValue, g_nullValue};
202
203 auto rowDataImpl1 = new (std::nothrow) RelationalRowDataImpl(std::move(data1));
204 auto rowDataImpl2 = new (std::nothrow) RelationalRowDataImpl(std::move(data2));
205 auto rowDataImpl3 = new (std::nothrow) RelationalRowDataImpl(std::move(data3));
206 /**
207 * @tc.steps: step1. Create 2 row data set which contains 3 row data totally;
208 * @tc.expected: OK.
209 */
210 RelationalRowDataSet rowDataSet1;
211 rowDataSet1.Insert(rowDataImpl1);
212
213 RelationalRowDataSet rowDataSet2;
214 rowDataSet2.SetRowData({ rowDataImpl2, rowDataImpl3 });
215
216 /**
217 * @tc.steps: step2. Put row data set;
218 * @tc.expected: The count is in expect.
219 */
220 RelationalResultSetImpl resultSet;
221 resultSet.Put("", 1, std::move(rowDataSet2));
222 resultSet.Put("", 2, std::move(rowDataSet1));
223 EXPECT_EQ(resultSet.GetCount(), 3);
224 }
225
226 /**
227 * @tc.name: EmptyResultSet
228 * @tc.desc: Empty result set.
229 * @tc.type: FUNC
230 * @tc.require:
231 * @tc.author: lidongwei
232 */
233 HWTEST_F(DistributedDBRelationalResultSetTest, EmptyResultSet, TestSize.Level1)
234 {
235 ResultSet *resultSet = new (std::nothrow) RelationalResultSetImpl;
236 ASSERT_NE(resultSet, nullptr);
237
238 EXPECT_EQ(resultSet->GetCount(), 0); // 0 row data
239 EXPECT_EQ(resultSet->GetPosition(), -1); // the init position=-1
240 EXPECT_FALSE(resultSet->MoveToFirst()); // move fail. position=-1
241 EXPECT_FALSE(resultSet->MoveToLast()); // move fail. position=-1
242 EXPECT_FALSE(resultSet->MoveToNext()); // move fail. position=-1
243 EXPECT_FALSE(resultSet->MoveToPrevious()); // move fail. position=-1
244 EXPECT_FALSE(resultSet->Move(1)); // move fail. position=-1
245 EXPECT_FALSE(resultSet->MoveToPosition(0)); // move fail. position=1
246 EXPECT_FALSE(resultSet->IsFirst()); // position=1, not the first one
247 EXPECT_FALSE(resultSet->IsLast()); // position=1, not the last one
248 EXPECT_TRUE(resultSet->IsBeforeFirst()); // empty result set, always true
249 EXPECT_TRUE(resultSet->IsAfterLast()); // empty result set, always true
250 EXPECT_FALSE(resultSet->IsClosed()); // not closed
251 Entry entry;
252 EXPECT_EQ(resultSet->GetEntry(entry), DBStatus::NOT_SUPPORT); // for relational result set, not support get entry.
253 ResultSet::ColumnType columnType;
254 EXPECT_EQ(resultSet->GetColumnType(0, columnType), DBStatus::NOT_FOUND); // the invalid position
255 int columnIndex = -1;
256 EXPECT_EQ(resultSet->GetColumnIndex("", columnIndex), DBStatus::NOT_FOUND); // empty result set
257 int64_t value = 0;
258 EXPECT_EQ(resultSet->Get(0, value), DBStatus::NOT_FOUND); // the invalid position
259 std::map<std::string, VariantData> data;
260 EXPECT_EQ(resultSet->GetRow(data), DBStatus::NOT_FOUND); // the invalid position
261 delete resultSet;
262 }
263
264 /**
265 * @tc.name: NormalResultSet
266 * @tc.desc: Normal result set.
267 * @tc.type: FUNC
268 * @tc.require:
269 * @tc.author: lidongwei
270 */
271 HWTEST_F(DistributedDBRelationalResultSetTest, NormalResultSet, TestSize.Level1)
272 {
273 auto *resultSet = new (std::nothrow) RelationalResultSetImpl;
274 ASSERT_NE(resultSet, nullptr);
275
276 /**
277 * @tc.steps: step1. Create a result set which contains two row data;
278 * @tc.expected: OK.
279 */
280 RelationalRowDataSet rowDataSet1;
281 EXPECT_EQ(rowDataSet1.Insert(new (std::nothrow) RelationalRowDataImpl({g_strValue, g_int64Value})), E_OK);
282 RelationalRowDataSet rowDataSet2;
283 rowDataSet2.SetColNames({"column 1", "column 2"});
284 EXPECT_EQ(rowDataSet2.Insert(new (std::nothrow) RelationalRowDataImpl({g_nullValue, g_blobValue})), E_OK);
285
286 EXPECT_EQ(resultSet->Put("", 2, std::move(rowDataSet2)), E_OK); // the second one
287 EXPECT_EQ(resultSet->Put("", 1, std::move(rowDataSet1)), E_OK); // the first one
288
289 /**
290 * @tc.steps: step2. Check the result set;
291 * @tc.expected: All the interface is running in expect.
292 */
293 EXPECT_EQ(resultSet->GetCount(), 2); // two row data
294 EXPECT_EQ(resultSet->GetPosition(), -1); // the init position=-1
295 EXPECT_TRUE(resultSet->MoveToFirst()); // move ok. position=0
296 EXPECT_TRUE(resultSet->MoveToLast()); // move ok. position=1
297 EXPECT_FALSE(resultSet->MoveToNext()); // move fail. position=2
298 EXPECT_TRUE(resultSet->MoveToPrevious()); // move ok. position=1
299 EXPECT_FALSE(resultSet->Move(1)); // move fail. position=2
300 EXPECT_TRUE(resultSet->MoveToPosition(0)); // move ok. position=0
301 EXPECT_TRUE(resultSet->IsFirst()); // position=0, the first one
302 EXPECT_FALSE(resultSet->IsLast()); // position=0, not the last one
303 EXPECT_FALSE(resultSet->IsBeforeFirst()); // position=0, not before the first
304 EXPECT_FALSE(resultSet->IsAfterLast()); // position=0, not after the last
305 EXPECT_FALSE(resultSet->IsClosed()); // not closed
306
307 Entry entry;
308 EXPECT_EQ(resultSet->GetEntry(entry), DBStatus::NOT_SUPPORT); // for relational result set, not support get entry.
309
310 ResultSet::ColumnType columnType;
311 EXPECT_EQ(resultSet->GetColumnType(0, columnType), DBStatus::OK);
312 EXPECT_EQ(columnType, ResultSet::ColumnType::STRING);
313
314 std::vector<std::string> expectCols { "column 1", "column 2" };
315 std::vector<std::string> colNames;
316 resultSet->GetColumnNames(colNames);
317 EXPECT_EQ(colNames, expectCols);
318
319 int columnIndex = -1;
320 EXPECT_EQ(resultSet->GetColumnIndex("", columnIndex), DBStatus::NONEXISTENT); // the invalid column name
321 EXPECT_EQ(resultSet->GetColumnIndex("column 1", columnIndex), DBStatus::OK);
322 EXPECT_EQ(columnIndex, 0);
323
324 int64_t value = 0;
325 EXPECT_EQ(resultSet->Get(1, value), DBStatus::OK);
326 EXPECT_EQ(value, INT64_VALUE);
327
328 std::map<std::string, VariantData> data;
329 EXPECT_EQ(resultSet->GetRow(data), DBStatus::OK);
330 EXPECT_EQ(std::get<std::string>(data["column 1"]), STR_VALUE);
331 EXPECT_EQ(std::get<int64_t>(data["column 2"]), INT64_VALUE);
332 delete resultSet;
333 }
334
335
336 HWTEST_F(DistributedDBRelationalResultSetTest, Test001, TestSize.Level1)
337 {
338 auto *resultSet = new (std::nothrow) RelationalResultSetImpl;
339 ASSERT_NE(resultSet, nullptr);
340
341 /**
342 * @tc.steps: step1. Create a result set which contains two row data;
343 * @tc.expected: OK.
344 */
345 RelationalRowDataSet rowDataSet1;
346 RowData rowData = {g_blobValue, g_doubleValue, g_int64Value, g_nullValue, g_strValue};
347 EXPECT_EQ(rowDataSet1.Insert(new (std::nothrow) RelationalRowDataImpl(std::move(rowData))), E_OK);
348 EXPECT_EQ(resultSet->Put("", 1, std::move(rowDataSet1)), E_OK); // the first one
349
350 EXPECT_EQ(resultSet->MoveToFirst(), true);
351 ResultSet::ColumnType columnType;
352 EXPECT_EQ(resultSet->GetColumnType(0, columnType), DBStatus::OK);
353 EXPECT_EQ(columnType, ResultSet::ColumnType::BLOB);
354 EXPECT_EQ(resultSet->GetColumnType(1, columnType), DBStatus::OK);
355 EXPECT_EQ(columnType, ResultSet::ColumnType::DOUBLE);
356 EXPECT_EQ(resultSet->GetColumnType(2, columnType), DBStatus::OK);
357 EXPECT_EQ(columnType, ResultSet::ColumnType::INT64);
358 EXPECT_EQ(resultSet->GetColumnType(3, columnType), DBStatus::OK);
359 EXPECT_EQ(columnType, ResultSet::ColumnType::NULL_VALUE);
360 EXPECT_EQ(resultSet->GetColumnType(4, columnType), DBStatus::OK);
361 EXPECT_EQ(columnType, ResultSet::ColumnType::STRING);
362
363 delete resultSet;
364 }
365
366 /**
367 * @tc.name: ResultSetTest001
368 * @tc.desc: Test get rowData and close
369 * @tc.type: FUNC
370 * @tc.require:
371 * @tc.author: chenchaohao
372 */
373 HWTEST_F(DistributedDBRelationalResultSetTest, ResultSetTest001, TestSize.Level0)
374 {
375 auto *resultSet = new (std::nothrow) RelationalResultSetImpl;
376 ASSERT_NE(resultSet, nullptr);
377
378 /**
379 * @tc.steps: step1. Create a result set which contains five row data;
380 * @tc.expected: OK.
381 */
382 RelationalRowDataSet rowDataSet1;
383 RowData rowData = {g_blobValue, g_doubleValue, g_int64Value, g_nullValue, g_strValue};
384 rowDataSet1.SetColNames({"column 1", "column 2", "column 3", "column 4", "column 5"});
385 EXPECT_EQ(rowDataSet1.Insert(new (std::nothrow) RelationalRowDataImpl(std::move(rowData))), E_OK);
386 EXPECT_EQ(resultSet->Put("", 1, std::move(rowDataSet1)), E_OK); // the first one
387 EXPECT_EQ(resultSet->MoveToFirst(), true);
388
389 /**
390 * @tc.steps: step2. Check data
391 * @tc.expected: OK.
392 */
393 std::map<std::string, VariantData> data;
394 EXPECT_EQ(resultSet->GetRow(data), DBStatus::OK);
395 EXPECT_EQ(std::get<std::vector<uint8_t>>(data["column 1"]), BLOB_VALUE);
396 EXPECT_EQ(std::get<double>(data["column 2"]), DOUBLE_VALUE);
397 EXPECT_EQ(std::get<int64_t>(data["column 3"]), INT64_VALUE);
398 EXPECT_EQ(std::get<std::string>(data["column 5"]), STR_VALUE);
399
400 /**
401 * @tc.steps: step3. Check close twice
402 * @tc.expected: OK.
403 */
404 resultSet->Close();
405 EXPECT_EQ(resultSet->GetCount(), 0);
406 resultSet->Close();
407 EXPECT_EQ(resultSet->GetCount(), 0);
408
409 delete resultSet;
410 }
411
412 /**
413 * @tc.name: ResultSetTest002
414 * @tc.desc: Test get data in null resultSet
415 * @tc.type: FUNC
416 * @tc.require:
417 * @tc.author: chenchaohao
418 */
419 HWTEST_F(DistributedDBRelationalResultSetTest, ResultSetTest002, TestSize.Level0)
420 {
421 auto *resultSet = new (std::nothrow) RelationalResultSetImpl;
422 ASSERT_NE(resultSet, nullptr);
423
424 /**
425 * @tc.steps: step1. check whether status is not found when get null resultSet
426 * @tc.expected: OK.
427 */
428 std::vector<uint8_t> blob;
429 EXPECT_EQ(resultSet->Get(0, blob), DBStatus::NOT_FOUND);
430 std::string strValue = "";
431 EXPECT_EQ(resultSet->Get(0, strValue), DBStatus::NOT_FOUND);
432 int64_t intValue = 0;
433 EXPECT_EQ(resultSet->Get(0, intValue), DBStatus::NOT_FOUND);
434 double doubleValue = 0.0;
435 EXPECT_EQ(resultSet->Get(0, doubleValue), DBStatus::NOT_FOUND);
436 bool isNull = true;
437 EXPECT_EQ(resultSet->IsColumnNull(0, isNull), DBStatus::NOT_FOUND);
438
439 delete resultSet;
440 }
441
442 /**
443 * @tc.name: SerializeTest001
444 * @tc.desc: Test Serialize func
445 * @tc.type: FUNC
446 * @tc.require:
447 * @tc.author: tiansimiao
448 */
449 HWTEST_F(DistributedDBRelationalResultSetTest, SerializeTest001, TestSize.Level0)
450 {
451 DataValue dataValue;
452 dataValue.ResetValue();
453 RowData rowData;
454 rowData.push_back(dataValue);
455 RelationalRowDataImpl row(std::move(rowData));
456 Parcel parcel(nullptr, 0);
457 EXPECT_EQ(row.Serialize(parcel), -E_PARSE_FAIL);
458 }
459
460 /**
461 * @tc.name: SerializeTest002
462 * @tc.desc: Test Serialize func
463 * @tc.type: FUNC
464 * @tc.require:
465 * @tc.author: tiansimiao
466 */
467 HWTEST_F(DistributedDBRelationalResultSetTest, SerializeTest002, TestSize.Level0)
468 {
469 std::string largeString(DBConstant::MAX_SET_VALUE_SIZE + 1, 'a');
470 DataValue dataValue;
471 dataValue.SetText(largeString);
472 RowData rowData;
473 rowData.push_back(dataValue);
474 RelationalRowDataImpl row(std::move(rowData));
475 uint32_t parcelSize = DBConstant::MAX_SET_VALUE_SIZE;
476 uint8_t* buffer = new(std::nothrow) uint8_t[parcelSize];
477 ASSERT_NE(buffer, nullptr);
478 Parcel parcel(buffer, parcelSize);
479 EXPECT_EQ(row.Serialize(parcel), -E_PARSE_FAIL);
480 delete[] buffer;
481 }
482
483 /**
484 * @tc.name: DeSerializeTest001
485 * @tc.desc: Test DeSerialize func
486 * @tc.type: FUNC
487 * @tc.require:
488 * @tc.author: tiansimiao
489 */
490 HWTEST_F(DistributedDBRelationalResultSetTest, DeSerializeTest001, TestSize.Level0)
491 {
492 uint8_t buffer[100] = {0};
493 Parcel parcelA(buffer, 100);
494 EXPECT_FALSE(parcelA.IsError());
495 uint32_t size = 1;
496 (void)parcelA.WriteUInt32(size);
497 EXPECT_FALSE(parcelA.IsError());
498 uint32_t type = static_cast<uint32_t>(StorageType::STORAGE_TYPE_NONE);
499 (void)parcelA.WriteUInt32(type);
500 EXPECT_FALSE(parcelA.IsError());
501 RelationalRowDataImpl row;
502 Parcel parcelB(buffer, 100);
503 EXPECT_EQ(row.DeSerialize(parcelB), -E_PARSE_FAIL);
504 }
505
506 /**
507 * @tc.name: DeSerializeTest002
508 * @tc.desc: Test DeSerialize func
509 * @tc.type: FUNC
510 * @tc.require:
511 * @tc.author: tiansimiao
512 */
513 HWTEST_F(DistributedDBRelationalResultSetTest, DeSerializeTest002, TestSize.Level0)
514 {
515 /**
516 * @tc.steps: step1. Set totalLen as the critical condition.
517 * satisfies the write condition (parcelLen is less than totalLen), but does not meet the byte alignment condition
518 * parcelLen is 12 after writing, after byte alignment it becomes 16, which is greater than totalLen.
519 */
520 uint8_t buffer[12] = {0}; // Set totalLen as 12
521 Parcel parcelA(buffer, 12);
522 uint32_t size = 1;
523 (void)parcelA.WriteUInt32(size);
524 EXPECT_FALSE(parcelA.IsError());
525 uint32_t type = static_cast<uint32_t>(StorageType::STORAGE_TYPE_NULL);
526 (void)parcelA.WriteUInt32(type);
527 EXPECT_FALSE(parcelA.IsError());
528 RelationalRowDataImpl row;
529 Parcel parcelB(buffer, 12);
530 EXPECT_EQ(row.DeSerialize(parcelB), -E_PARSE_FAIL);
531 }
532
533 /**
534 * @tc.name: GetTypeTest001
535 * @tc.desc: Test GetType func
536 * @tc.type: FUNC
537 * @tc.require:
538 * @tc.author: tiansimiao
539 */
540 HWTEST_F(DistributedDBRelationalResultSetTest, GetTypeTest001, TestSize.Level0)
541 {
542 DistributedDB::RowData data;
543 DistributedDB::DataValue value;
544 value.SetText("test");
545 data.emplace_back(std::move(value));
546 DistributedDB::RelationalRowDataImpl row(std::move(data));
547 DistributedDB::StorageType type;
548 EXPECT_EQ(row.GetType(-1, type), -E_NONEXISTENT);
549 EXPECT_EQ(row.GetType(3, type), -E_NONEXISTENT);
550 }
551
552 /**
553 * @tc.name: GetTest001
554 * @tc.desc: Test Get func
555 * @tc.type: FUNC
556 * @tc.require:
557 * @tc.author: tiansimiao
558 */
559 HWTEST_F(DistributedDBRelationalResultSetTest, GetTest001, TestSize.Level0)
560 {
561 DistributedDB::RowData data;
562 DistributedDB::DataValue value;
563 value.SetText("test");
564 data.emplace_back(std::move(value));
565 DistributedDB::RelationalRowDataImpl row(std::move(data));
566 int64_t intValue;
567 double doubleValue;
568 std::string stringValueResult;
569 std::vector<uint8_t> blobValueResult;
570 EXPECT_EQ(row.Get(-1, intValue), -E_NONEXISTENT);
571 EXPECT_EQ(row.Get(1, intValue), -E_NONEXISTENT);
572 EXPECT_EQ(row.Get(-1, doubleValue), -E_NONEXISTENT);
573 EXPECT_EQ(row.Get(1, doubleValue), -E_NONEXISTENT);
574 EXPECT_EQ(row.Get(-1, stringValueResult), -E_NONEXISTENT);
575 EXPECT_EQ(row.Get(1, stringValueResult), -E_NONEXISTENT);
576 EXPECT_EQ(row.Get(-1, blobValueResult), -E_NONEXISTENT);
577 EXPECT_EQ(row.Get(1, blobValueResult), -E_NONEXISTENT);
578 }
579
580 /**
581 * @tc.name: GetTest002
582 * @tc.desc: Test Get func
583 * @tc.type: FUNC
584 * @tc.require:
585 * @tc.author: tiansimiao
586 */
587 HWTEST_F(DistributedDBRelationalResultSetTest, GetTest002, TestSize.Level0)
588 {
589 DistributedDB::RowData data;
590 DistributedDB::DataValue value;
591 value.SetText("test");
592 data.emplace_back(std::move(value));
593 DistributedDB::RelationalRowDataImpl row(std::move(data));
594 int64_t intValue;
595 EXPECT_EQ(row.Get(0, intValue), -E_TYPE_MISMATCH);
596 double doubleValue;
597 EXPECT_EQ(row.Get(0, doubleValue), -E_TYPE_MISMATCH);
598 }
599
600 /**
601 * @tc.name: GetTest003
602 * @tc.desc: Test Get func
603 * @tc.type: FUNC
604 * @tc.require:
605 * @tc.author: tiansimiao
606 */
607 HWTEST_F(DistributedDBRelationalResultSetTest, GetTest003, TestSize.Level0)
608 {
609 DistributedDB::RowData data;
610 DistributedDB::DataValue value;
611 int64_t intValue = 10;
612 value.GetInt64(intValue);
613 data.emplace_back(std::move(value));
614 DistributedDB::RelationalRowDataImpl row(std::move(data));
615 std::string stringValueResult;
616 EXPECT_EQ(row.Get(0, stringValueResult), -E_TYPE_MISMATCH);
617 std::vector<uint8_t> blobValueResult;
618 EXPECT_EQ(row.Get(0, blobValueResult), -E_TYPE_MISMATCH);
619 }
620
621 /**
622 * @tc.name: BinlogSupportTest001
623 * @tc.desc: Test binlog support API return values as expected
624 * @tc.type: FUNC
625 * @tc.require:
626 * @tc.author: hongyangliu
627 */
628 HWTEST_F(DistributedDBRelationalResultSetTest, BinlogSupportTest001, TestSize.Level0)
629 {
630 EXPECT_EQ(sqlite3_is_support_binlog(nullptr), SQLITE_ERROR);
631 EXPECT_EQ(sqlite3_is_support_binlog(""), sqlite3_is_support_binlog(" "));
632 }
633
634 /**
635 * @tc.name: CompressSupportTest001
636 * @tc.desc: Test sqlite open with different vfs option return values as expected
637 * @tc.type: FUNC
638 * @tc.require:
639 * @tc.author: hongyangliu
640 */
641 HWTEST_F(DistributedDBRelationalResultSetTest, CompressSupportTest001, TestSize.Level0)
642 {
643 sqlite3 *db = nullptr;
644 uint32_t openOption = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_FULLMUTEX;
645 /**
646 * @tc.steps: step1. sqlite open with both filepath and vfs as null
647 * @tc.expected: no crash
648 */
649 ASSERT_NO_FATAL_FAILURE(sqlite3_open_v2(nullptr, &db, openOption, nullptr));
650 sqlite3_close_v2(db);
651 db = nullptr;
652 /**
653 * @tc.steps: step2. sqlite open with null filepath and random vfs
654 * @tc.expected: no crash
655 */
656 ASSERT_NO_FATAL_FAILURE(sqlite3_open_v2(nullptr, &db, openOption, "non-exist"));
657 sqlite3_close_v2(db);
658 db = nullptr;
659 /**
660 * @tc.steps: step3. sqlite open with null filepath and compress vfs
661 * @tc.expected: no crash
662 */
663 ASSERT_NO_FATAL_FAILURE(sqlite3_open_v2(nullptr, &db, openOption, "compressvfs"));
664 sqlite3_close_v2(db);
665 db = nullptr;
666 /**
667 * @tc.steps: step4. sqlite open with a regular file with no vfs
668 * @tc.expected: open ok
669 */
670 EXPECT_EQ(sqlite3_open_v2(g_storePath.c_str(), &db, openOption, nullptr), SQLITE_OK);
671 sqlite3_close_v2(db);
672 db = nullptr;
673 /**
674 * @tc.steps: step5. sqlite open with a non-whitelist file using compress vfs
675 * @tc.expected: open ok
676 */
677 std::string nonWhiteDb = g_testDir + "/nonWhiteList.db";
678 EXPECT_EQ(sqlite3_open_v2(nonWhiteDb.c_str(), &db, openOption, "compressvfs"), SQLITE_OK);
679 sqlite3_close_v2(db);
680 db = nullptr;
681 /**
682 * @tc.steps: step6. sqlite open with a whitelist file using compress vfs
683 * @tc.expected: no crash
684 */
685 std::string whitelistDb = g_testDir + "/test.db";
686 ASSERT_NO_FATAL_FAILURE(sqlite3_open_v2(whitelistDb.c_str(), &db, openOption, "compressvfs"));
687 sqlite3_close_v2(db);
688 db = nullptr;
689 }
690 #endif
691