1 /*
2 * Copyright (c) 2022 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 #ifndef OMIT_JSON
17 #include <gtest/gtest.h>
18 #include <cmath>
19
20 #include "db_errno.h"
21 #include "distributeddb_tools_unit_test.h"
22 #include "log_print.h"
23 #include "relational_schema_object.h"
24 #include "schema_utils.h"
25 #include "schema_constant.h"
26 #include "schema_negotiate.h"
27
28 using namespace std;
29 using namespace testing::ext;
30 using namespace DistributedDB;
31 using namespace DistributedDBUnitTest;
32
33 namespace {
34 constexpr const char* DB_SUFFIX = ".db";
35 constexpr const char* STORE_ID = "Relational_Store_ID";
36 string g_testDir;
37 string g_dbDir;
38
39 const std::string NORMAL_SCHEMA = R""({
40 "SCHEMA_VERSION": "2.0",
41 "SCHEMA_TYPE": "RELATIVE",
42 "TABLES": [{
43 "NAME": "FIRST",
44 "DEFINE": {
45 "field_name1": {
46 "COLUMN_ID":1,
47 "TYPE": "STRING",
48 "NOT_NULL": true,
49 "DEFAULT": "abcd"
50 },
51 "field_name2": {
52 "COLUMN_ID":2,
53 "TYPE": "MYINT(21)",
54 "NOT_NULL": false,
55 "DEFAULT": "222"
56 },
57 "field_name3": {
58 "COLUMN_ID":3,
59 "TYPE": "INTGER",
60 "NOT_NULL": false,
61 "DEFAULT": "1"
62 }
63 },
64 "AUTOINCREMENT": true,
65 "UNIQUE": [["field_name1"], ["field_name2", "field_name3"]],
66 "PRIMARY_KEY": "field_name1",
67 "INDEX": {
68 "index_name1": ["field_name1", "field_name2"],
69 "index_name2": ["field_name3"]
70 }
71 }, {
72 "NAME": "SECOND",
73 "DEFINE": {
74 "key": {
75 "COLUMN_ID":1,
76 "TYPE": "BLOB",
77 "NOT_NULL": true
78 },
79 "value": {
80 "COLUMN_ID":2,
81 "TYPE": "BLOB",
82 "NOT_NULL": false
83 }
84 },
85 "PRIMARY_KEY": "field_name1"
86 }]
87 })"";
88
89 const std::string NORMAL_SCHEMA_V2_1 = R""({
90 "SCHEMA_VERSION": "2.1",
91 "SCHEMA_TYPE": "RELATIVE",
92 "TABLE_MODE": "SPLIT_BY_DEVICE",
93 "TABLES": [{
94 "NAME": "FIRST",
95 "DEFINE": {
96 "field_name1": {
97 "COLUMN_ID":1,
98 "TYPE": "STRING",
99 "NOT_NULL": true,
100 "DEFAULT": "abcd"
101 },
102 "field_name2": {
103 "COLUMN_ID":2,
104 "TYPE": "MYINT(21)",
105 "NOT_NULL": false,
106 "DEFAULT": "222"
107 },
108 "field_name3": {
109 "COLUMN_ID":3,
110 "TYPE": "INTGER",
111 "NOT_NULL": false,
112 "DEFAULT": "1"
113 }
114 },
115 "AUTOINCREMENT": true,
116 "UNIQUE": [["field_name1"], ["field_name2", "field_name3"]],
117 "PRIMARY_KEY": ["field_name1", "field_name3"],
118 "INDEX": {
119 "index_name1": ["field_name1", "field_name2"],
120 "index_name2": ["field_name3"]
121 }
122 }, {
123 "NAME": "SECOND",
124 "DEFINE": {
125 "key": {
126 "COLUMN_ID":1,
127 "TYPE": "BLOB",
128 "NOT_NULL": true
129 },
130 "value": {
131 "COLUMN_ID":2,
132 "TYPE": "BLOB",
133 "NOT_NULL": false
134 }
135 },
136 "PRIMARY_KEY": ["field_name1"]
137 }]
138 })"";
139
140 const std::string INVALID_SCHEMA = R""({
141 "SCHEMA_VERSION": "2.0",
142 "SCHEMA_TYPE": "RELATIVE",
143 "TABLES": [{
144 "NAME": "FIRST",
145 "DEFINE": {
146 "field_name1": {
147 "COLUMN_ID":1,
148 "TYPE": "STRING",
149 "NOT_NULL": true,
150 "DEFAULT": "abcd"
151 },"field_name2": {
152 "COLUMN_ID":2,
153 "TYPE": "MYINT(21)",
154 "NOT_NULL": false,
155 "DEFAULT": "222"
156 }
157 },
158 "PRIMARY_KEY": "field_name1"
159 }]
160 })"";
161
162 const std::string INVALID_JSON_STRING = R""({
163 "SCHEMA_VERSION": "2.0",
164 "SCHEMA_TYPE": "RELATIVE",
165 "TABLES": [{
166 "NAME": "FIRST",
167 "DEFINE": {
168 "field_name1": {)"";
169
170 const std::string SCHEMA_VERSION_STR_1 = R"("SCHEMA_VERSION": "1.0",)";
171 const std::string SCHEMA_VERSION_STR_2 = R"("SCHEMA_VERSION": "2.0",)";
172 const std::string SCHEMA_VERSION_STR_2_1 = R"("SCHEMA_VERSION": "2.1",)";
173 const std::string SCHEMA_VERSION_STR_INVALID = R"("SCHEMA_VERSION": "awd3",)";
174 const std::string SCHEMA_TYPE_STR_NONE = R"("SCHEMA_TYPE": "NONE",)";
175 const std::string SCHEMA_TYPE_STR_JSON = R"("SCHEMA_TYPE": "JSON",)";
176 const std::string SCHEMA_TYPE_STR_FLATBUFFER = R"("SCHEMA_TYPE": "FLATBUFFER",)";
177 const std::string SCHEMA_TYPE_STR_RELATIVE = R"("SCHEMA_TYPE": "RELATIVE",)";
178 const std::string SCHEMA_TYPE_STR_INVALID = R"("SCHEMA_TYPE": "adewaaSAD",)";
179 const std::string SCHEMA_TABLE_MODE_COLLABORATION = R"("TABLE_MODE": "COLLABORATION",)";
180 const std::string SCHEMA_TABLE_MODE_SPLIT_BY_DEVICE = R"("TABLE_MODE": "SPLIT_BY_DEVICE",)";
181 const std::string SCHEMA_TABLE_MODE_INVALID = R"("TABLE_MODE": "SPLIT_BY_USER",)";
182
183 const std::string SCHEMA_TABLE_STR = R""("TABLES": [{
184 "NAME": "FIRST",
185 "DEFINE": {
186 "field_name1": {
187 "COLUMN_ID":1,
188 "TYPE": "STRING",
189 "NOT_NULL": true,
190 "DEFAULT": "abcd"
191 },"field_name2": {
192 "COLUMN_ID":2,
193 "TYPE": "MYINT(21)",
194 "NOT_NULL": false,
195 "DEFAULT": "222"
196 }
197 },
198 "PRIMARY_KEY": "field_name1"
199 }])"";
200
201 const std::string TABLE_DEFINE_STR = R""({
202 "NAME": "FIRST",
203 "DEFINE": {
204 "field_name1": {
205 "COLUMN_ID":1,
206 "TYPE": "STRING",
207 "NOT_NULL": true,
208 "DEFAULT": "abcd"
209 },"field_name2": {
210 "COLUMN_ID":2,
211 "TYPE": "MYINT(21)",
212 "NOT_NULL": false,
213 "DEFAULT": "222"
214 }
215 },
216 "PRIMARY_KEY": "field_name1"
217 })"";
218
219 const std::string TABLE_DEFINE_STR_NAME = R""("NAME": "FIRST",)"";
220 const std::string TABLE_DEFINE_STR_NAME_INVALID = R"("NAME": 123,)";
221 const std::string TABLE_DEFINE_STR_NAME_INVALID_CHARACTER = R"("NAME": "t1; --",)";
222 const std::string TABLE_DEFINE_STR_FIELDS = R""("DEFINE": {
223 "field_name1": {
224 "COLUMN_ID":1,
225 "TYPE": "STRING",
226 "NOT_NULL": true,
227 "DEFAULT": "abcd"
228 },"field_name2": {
229 "COLUMN_ID":2,
230 "TYPE": "MYINT(21)",
231 "NOT_NULL": false,
232 "DEFAULT": "222"
233 }
234 },)"";
235 const std::string TABLE_DEFINE_STR_FIELDS_EMPTY = R""("DEFINE": {},)"";
236 const std::string TABLE_DEFINE_STR_FIELDS_NOTYPE = R""("DEFINE": {
237 "field_name1": {
238 "COLUMN_ID":1,
239 "NOT_NULL": true,
240 "DEFAULT": "abcd"
241 }},)"";
242 const std::string TABLE_DEFINE_STR_FIELDS_INVALID_CHARACTER = R""("DEFINE": {
243 "1 = 1; --": {
244 "COLUMN_ID":1,
245 "NOT_NULL": true,
246 "DEFAULT": "abcd"
247 }},)"";
248 const std::string TABLE_DEFINE_STR_KEY = R""("PRIMARY_KEY": "field_name1")"";
249 const std::string TABLE_DEFINE_BOOL_KEY_INVALID = R""("PRIMARY_KEY": false)"";
250 const std::string TABLE_DEFINE_BOOL_ARRAY_KEY_INVALID = R""("PRIMARY_KEY": [false, true, true])"";
251 }
252
253 class DistributedDBRelationalSchemaObjectTest : public testing::Test {
254 public:
255 static void SetUpTestCase(void);
256 static void TearDownTestCase(void);
257 void SetUp() override;
258 void TearDown() override;
259 };
260
SetUpTestCase(void)261 void DistributedDBRelationalSchemaObjectTest::SetUpTestCase(void)
262 {
263 DistributedDBToolsUnitTest::TestDirInit(g_testDir);
264 DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir);
265 LOGI("The test db is:%s", g_testDir.c_str());
266 g_dbDir = g_testDir + "/";
267 }
268
TearDownTestCase(void)269 void DistributedDBRelationalSchemaObjectTest::TearDownTestCase(void)
270 {
271 }
272
SetUp()273 void DistributedDBRelationalSchemaObjectTest::SetUp()
274 {
275 DistributedDBToolsUnitTest::PrintTestCaseInfo();
276 }
277
TearDown()278 void DistributedDBRelationalSchemaObjectTest::TearDown()
279 {
280 if (DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir) != 0) {
281 LOGE("rm test db files error.");
282 }
283 return;
284 }
285
286 /**
287 * @tc.name: RelationalSchemaParseTest001
288 * @tc.desc: Test relational schema parse from json string
289 * @tc.type: FUNC
290 * @tc.require: AR000GK58I
291 * @tc.author: lianhuix
292 */
293 HWTEST_F(DistributedDBRelationalSchemaObjectTest, RelationalSchemaParseTest001, TestSize.Level1)
294 {
295 const std::string schemaStr = NORMAL_SCHEMA;
296 RelationalSchemaObject schemaObj;
297 int errCode = schemaObj.ParseFromSchemaString(schemaStr);
298 EXPECT_EQ(errCode, E_OK);
299 EXPECT_EQ(schemaObj.GetTable("FIRST").GetUniqueDefine().size(), 2u);
300
301 RelationalSchemaObject schemaObj2;
302 schemaObj2.ParseFromSchemaString(schemaObj.ToSchemaString());
303 EXPECT_EQ(errCode, E_OK);
304 EXPECT_EQ(schemaObj2.GetTable("FIRST").GetUniqueDefine().size(), 2u);
305
306 RelationalSyncOpinion op = SchemaNegotiate::MakeLocalSyncOpinion(schemaObj, schemaObj2.ToSchemaString(),
307 static_cast<uint8_t>(SchemaType::RELATIVE));
308
309 EXPECT_EQ(op.size(), 2u);
310 EXPECT_EQ(op.at("FIRST").permitSync, true);
311 EXPECT_EQ(op.at("SECOND").permitSync, true);
312 }
313
314 /**
315 * @tc.name: RelationalSchemaParseTest002
316 * @tc.desc: Test relational schema parse from invalid json string
317 * @tc.type: FUNC
318 * @tc.require: AR000GK58I
319 * @tc.author: lianhuix
320 */
321 HWTEST_F(DistributedDBRelationalSchemaObjectTest, RelationalSchemaParseTest002, TestSize.Level1)
322 {
323 RelationalSchemaObject schemaObj;
324
325 std::string schemaStr01(SchemaConstant::SCHEMA_STRING_SIZE_LIMIT + 1, 's');
326 int errCode = schemaObj.ParseFromSchemaString(schemaStr01);
327 EXPECT_EQ(errCode, -E_INVALID_ARGS);
328
329 errCode = schemaObj.ParseFromSchemaString(INVALID_JSON_STRING);
330 EXPECT_EQ(errCode, -E_JSON_PARSE_FAIL);
331
332 std::string noVersion = "{" + SCHEMA_TYPE_STR_RELATIVE + SCHEMA_TABLE_STR + "}";
333 errCode = schemaObj.ParseFromSchemaString(noVersion);
334 EXPECT_EQ(errCode, -E_SCHEMA_PARSE_FAIL);
335
336 std::string invalidVersion1 = "{" + SCHEMA_VERSION_STR_1 + SCHEMA_TYPE_STR_RELATIVE + SCHEMA_TABLE_STR + "}";
337 errCode = schemaObj.ParseFromSchemaString(invalidVersion1);
338 EXPECT_EQ(errCode, -E_SCHEMA_PARSE_FAIL);
339
340 std::string invalidVersion2 = "{" + SCHEMA_VERSION_STR_INVALID + SCHEMA_TYPE_STR_RELATIVE + SCHEMA_TABLE_STR + "}";
341 errCode = schemaObj.ParseFromSchemaString(invalidVersion2);
342 EXPECT_EQ(errCode, -E_SCHEMA_PARSE_FAIL);
343
344 std::string noType = "{" + SCHEMA_VERSION_STR_2 + SCHEMA_TABLE_STR + "}";
345 errCode = schemaObj.ParseFromSchemaString(noType);
346 EXPECT_EQ(errCode, -E_SCHEMA_PARSE_FAIL);
347
348 std::string invalidType1 = "{" + SCHEMA_VERSION_STR_2 + SCHEMA_TYPE_STR_NONE + SCHEMA_TABLE_STR + "}";
349 errCode = schemaObj.ParseFromSchemaString(invalidType1);
350 EXPECT_EQ(errCode, -E_SCHEMA_PARSE_FAIL);
351
352 std::string invalidType2 = "{" + SCHEMA_VERSION_STR_2 + SCHEMA_TYPE_STR_JSON + SCHEMA_TABLE_STR + "}";
353 errCode = schemaObj.ParseFromSchemaString(invalidType2);
354 EXPECT_EQ(errCode, -E_SCHEMA_PARSE_FAIL);
355
356 std::string invalidType3 = "{" + SCHEMA_VERSION_STR_2 + SCHEMA_TYPE_STR_FLATBUFFER + SCHEMA_TABLE_STR + "}";
357 errCode = schemaObj.ParseFromSchemaString(invalidType3);
358 EXPECT_EQ(errCode, -E_SCHEMA_PARSE_FAIL);
359
360 std::string invalidType4 = "{" + SCHEMA_VERSION_STR_2 + SCHEMA_TYPE_STR_INVALID + SCHEMA_TABLE_STR + "}";
361 errCode = schemaObj.ParseFromSchemaString(invalidType4);
362 EXPECT_EQ(errCode, -E_SCHEMA_PARSE_FAIL);
363
364 std::string noTable = "{" + SCHEMA_VERSION_STR_2 +
365 SCHEMA_TYPE_STR_RELATIVE.substr(0, SCHEMA_TYPE_STR_RELATIVE.length() - 1) + "}";
366 errCode = schemaObj.ParseFromSchemaString(noTable);
367 EXPECT_EQ(errCode, -E_SCHEMA_PARSE_FAIL);
368 }
369
370 namespace {
GenerateFromTableStr(const std::string & tableStr)371 std::string GenerateFromTableStr(const std::string &tableStr)
372 {
373 return R""({
374 "SCHEMA_VERSION": "2.0",
375 "SCHEMA_TYPE": "RELATIVE",
376 "TABLES": )"" + tableStr + "}";
377 }
378 }
379
380 /**
381 * @tc.name: RelationalSchemaParseTest003
382 * @tc.desc: Test relational schema parse from invalid json string
383 * @tc.type: FUNC
384 * @tc.require: AR000GK58I
385 * @tc.author: lianhuix
386 */
387 HWTEST_F(DistributedDBRelationalSchemaObjectTest, RelationalSchemaParseTest003, TestSize.Level1)
388 {
389 RelationalSchemaObject schemaObj;
390 int errCode = E_OK;
391
392 errCode = schemaObj.ParseFromSchemaString(GenerateFromTableStr(TABLE_DEFINE_STR));
393 EXPECT_EQ(errCode, -E_SCHEMA_PARSE_FAIL);
394
395 std::string invalidTableStr01 = "{" + TABLE_DEFINE_STR_FIELDS + TABLE_DEFINE_STR_KEY + "}";
396 errCode = schemaObj.ParseFromSchemaString(GenerateFromTableStr("[" + invalidTableStr01 + "]"));
397 EXPECT_EQ(errCode, -E_SCHEMA_PARSE_FAIL);
398
399 std::string invalidTableStr02 = "{" + TABLE_DEFINE_STR_NAME_INVALID + TABLE_DEFINE_STR_FIELDS +
400 TABLE_DEFINE_STR_KEY + "}";
401 errCode = schemaObj.ParseFromSchemaString(GenerateFromTableStr("[" + invalidTableStr02 + "]"));
402 EXPECT_EQ(errCode, -E_SCHEMA_PARSE_FAIL);
403
404 std::string invalidTableStr04 = "{" + TABLE_DEFINE_STR_NAME + TABLE_DEFINE_STR_FIELDS_NOTYPE +
405 TABLE_DEFINE_STR_KEY + "}";
406 errCode = schemaObj.ParseFromSchemaString(GenerateFromTableStr("[" + invalidTableStr04 + "]"));
407 EXPECT_EQ(errCode, -E_SCHEMA_PARSE_FAIL);
408
409 std::string invalidTableStr05 = "{" + TABLE_DEFINE_STR_NAME + TABLE_DEFINE_STR_FIELDS +
410 TABLE_DEFINE_BOOL_KEY_INVALID + "}";
411 errCode = schemaObj.ParseFromSchemaString(GenerateFromTableStr("[" + invalidTableStr05 + "]"));
412 EXPECT_EQ(errCode, -E_SCHEMA_PARSE_FAIL);
413
414 std::string invalidTableStr06 = "{" + TABLE_DEFINE_STR_NAME + TABLE_DEFINE_STR_FIELDS +
415 TABLE_DEFINE_BOOL_ARRAY_KEY_INVALID + "}";
416 errCode = schemaObj.ParseFromSchemaString(GenerateFromTableStr("[" + invalidTableStr06 + "]"));
417 EXPECT_EQ(errCode, -E_SCHEMA_PARSE_FAIL);
418
419 std::string invalidTableStr07 = "{" + TABLE_DEFINE_STR_NAME_INVALID_CHARACTER + TABLE_DEFINE_STR_FIELDS +
420 TABLE_DEFINE_STR_KEY + "}";
421 errCode = schemaObj.ParseFromSchemaString(GenerateFromTableStr("[" + invalidTableStr07 + "]"));
422 EXPECT_EQ(errCode, -E_SCHEMA_PARSE_FAIL);
423
424 std::string invalidTableStr08 = "{" + TABLE_DEFINE_STR_NAME + TABLE_DEFINE_STR_FIELDS_INVALID_CHARACTER +
425 TABLE_DEFINE_STR_KEY + "}";
426 errCode = schemaObj.ParseFromSchemaString(GenerateFromTableStr("[" + invalidTableStr08 + "]"));
427 EXPECT_EQ(errCode, -E_SCHEMA_PARSE_FAIL);
428
429 errCode = schemaObj.ParseFromSchemaString("");
430 EXPECT_EQ(errCode, -E_INVALID_ARGS);
431 }
432
433 /**
434 * @tc.name: RelationalSchemaParseTest004
435 * @tc.desc:
436 * @tc.type: FUNC
437 * @tc.require:
438 * @tc.author: lianhuix
439 */
440 HWTEST_F(DistributedDBRelationalSchemaObjectTest, RelationalSchemaParseTest004, TestSize.Level1)
441 {
442 RelationalSchemaObject schemaObj;
443 int errCode = E_OK;
444
445 std::string schema = "{" + SCHEMA_VERSION_STR_2_1 + SCHEMA_TABLE_MODE_COLLABORATION + SCHEMA_TYPE_STR_RELATIVE +
446 SCHEMA_TABLE_STR + "}";
447 errCode = schemaObj.ParseFromSchemaString(schema);
448 EXPECT_EQ(errCode, E_OK);
449 }
450
451 /**
452 * @tc.name: RelationalSchemaParseTest005
453 * @tc.desc:
454 * @tc.type: FUNC
455 * @tc.require:
456 * @tc.author: lianhuix
457 */
458 HWTEST_F(DistributedDBRelationalSchemaObjectTest, RelationalSchemaParseTest005, TestSize.Level1)
459 {
460 RelationalSchemaObject schemaObj;
461 int errCode = E_OK;
462
463 std::string schema = "{" + SCHEMA_VERSION_STR_2_1 + SCHEMA_TABLE_MODE_SPLIT_BY_DEVICE + SCHEMA_TYPE_STR_RELATIVE +
464 SCHEMA_TABLE_STR + "}";
465 errCode = schemaObj.ParseFromSchemaString(schema);
466 EXPECT_EQ(errCode, E_OK);
467 }
468
469 /**
470 * @tc.name: RelationalSchemaParseTest006
471 * @tc.desc:
472 * @tc.type: FUNC
473 * @tc.require:
474 * @tc.author: lianhuix
475 */
476 HWTEST_F(DistributedDBRelationalSchemaObjectTest, RelationalSchemaParseTest006, TestSize.Level1)
477 {
478 RelationalSchemaObject schemaObj;
479 int errCode = E_OK;
480
481 std::string schema = "{" + SCHEMA_VERSION_STR_2_1 + SCHEMA_TABLE_MODE_INVALID + SCHEMA_TYPE_STR_RELATIVE +
482 SCHEMA_TABLE_STR + "}";
483 errCode = schemaObj.ParseFromSchemaString(schema);
484 EXPECT_EQ(errCode, -E_SCHEMA_PARSE_FAIL);
485 }
486
487
488 /**
489 * @tc.name: RelationalSchemaCompareTest001
490 * @tc.desc: Test relational schema negotiate with same schema string
491 * @tc.type: FUNC
492 * @tc.require: AR000GK58I
493 * @tc.author: lianhuix
494 */
495 HWTEST_F(DistributedDBRelationalSchemaObjectTest, RelationalSchemaCompareTest001, TestSize.Level1)
496 {
497 RelationalSchemaObject schemaObj;
498 int errCode = schemaObj.ParseFromSchemaString(NORMAL_SCHEMA);
499 EXPECT_EQ(errCode, E_OK);
500
501 RelationalSyncOpinion opinion = SchemaNegotiate::MakeLocalSyncOpinion(schemaObj, NORMAL_SCHEMA,
502 static_cast<uint8_t>(SchemaType::RELATIVE));
503 EXPECT_EQ(opinion.at("FIRST").permitSync, true);
504 EXPECT_EQ(opinion.at("FIRST").checkOnReceive, false);
505 EXPECT_EQ(opinion.at("FIRST").requirePeerConvert, false);
506 }
507
508 /**
509 * @tc.name: RelationalSchemaCompareTest002
510 * @tc.desc: Test relational schema v2.1 negotiate with same schema string
511 * @tc.type: FUNC
512 * @tc.require: AR000H2PKN
513 * @tc.author: lianhuix
514 */
515 HWTEST_F(DistributedDBRelationalSchemaObjectTest, RelationalSchemaCompareTest002, TestSize.Level1)
516 {
517 RelationalSchemaObject schemaObj;
518 int errCode = schemaObj.ParseFromSchemaString(NORMAL_SCHEMA_V2_1);
519 EXPECT_EQ(errCode, E_OK);
520
521 RelationalSyncOpinion opinion = SchemaNegotiate::MakeLocalSyncOpinion(schemaObj, NORMAL_SCHEMA_V2_1,
522 static_cast<uint8_t>(SchemaType::RELATIVE));
523 EXPECT_EQ(opinion.at("FIRST").permitSync, true);
524 EXPECT_EQ(opinion.at("FIRST").checkOnReceive, false);
525 EXPECT_EQ(opinion.at("FIRST").requirePeerConvert, false);
526 }
527
528 /**
529 * @tc.name: RelationalSchemaCompareTest003
530 * @tc.desc: Test relational schema v2.1 negotiate with schema v2.0
531 * @tc.type: FUNC
532 * @tc.require: AR000H2PKN
533 * @tc.author: lianhuix
534 */
535 HWTEST_F(DistributedDBRelationalSchemaObjectTest, RelationalSchemaCompareTest003, TestSize.Level1)
536 {
537 RelationalSchemaObject schemaObj;
538 int errCode = schemaObj.ParseFromSchemaString(NORMAL_SCHEMA_V2_1);
539 EXPECT_EQ(errCode, E_OK);
540
541 RelationalSyncOpinion opinion = SchemaNegotiate::MakeLocalSyncOpinion(schemaObj, NORMAL_SCHEMA,
542 static_cast<uint8_t>(SchemaType::RELATIVE));
543 EXPECT_TRUE(opinion.empty());
544 }
545
546 /**
547 * @tc.name: RelationalSchemaCompareTest004
548 * @tc.desc: Test relational schema v2.0 negotiate with schema v2.1
549 * @tc.type: FUNC
550 * @tc.require: AR000H2PKN
551 * @tc.author: lianhuix
552 */
553 HWTEST_F(DistributedDBRelationalSchemaObjectTest, RelationalSchemaCompareTest004, TestSize.Level1)
554 {
555 RelationalSchemaObject schemaObj;
556 int errCode = schemaObj.ParseFromSchemaString(NORMAL_SCHEMA);
557 EXPECT_EQ(errCode, E_OK);
558
559 RelationalSyncOpinion opinion = SchemaNegotiate::MakeLocalSyncOpinion(schemaObj, NORMAL_SCHEMA_V2_1,
560 static_cast<uint8_t>(SchemaType::RELATIVE));
561 EXPECT_TRUE(opinion.empty());
562 }
563
564 /**
565 * @tc.name: RelationalSchemaCompareTest005
566 * @tc.desc: Test collaboration relational schema negotiate with other table mode
567 * @tc.type: FUNC
568 * @tc.require: AR000H2PKN
569 * @tc.author: lianhuix
570 */
571 HWTEST_F(DistributedDBRelationalSchemaObjectTest, RelationalSchemaCompareTest005, TestSize.Level1)
572 {
573 RelationalSchemaObject schemaObj;
574 int errCode = schemaObj.ParseFromSchemaString(NORMAL_SCHEMA_V2_1);
575 EXPECT_EQ(errCode, E_OK);
576 schemaObj.SetTableMode(DistributedTableMode::COLLABORATION);
577
578 RelationalSyncOpinion opinion = SchemaNegotiate::MakeLocalSyncOpinion(schemaObj, NORMAL_SCHEMA_V2_1,
579 static_cast<uint8_t>(SchemaType::RELATIVE));
580 EXPECT_TRUE(opinion.empty());
581 }
582
583 /**
584 * @tc.name: RelationalTableCompareTest001
585 * @tc.desc: Test relational schema negotiate with same schema string
586 * @tc.type: FUNC
587 * @tc.require: AR000GK58I
588 * @tc.author: lianhuix
589 */
590 HWTEST_F(DistributedDBRelationalSchemaObjectTest, RelationalTableCompareTest001, TestSize.Level1)
591 {
592 RelationalSchemaObject schemaObj;
593 int errCode = schemaObj.ParseFromSchemaString(NORMAL_SCHEMA);
594 EXPECT_EQ(errCode, E_OK);
595 TableInfo table1 = schemaObj.GetTable("FIRST");
596 TableInfo table2 = schemaObj.GetTable("FIRST");
597 EXPECT_EQ(table1.CompareWithTable(table2), -E_RELATIONAL_TABLE_EQUAL);
598
599 table2.AddIndexDefine("indexname", {"field_name2", "field_name1"});
600 EXPECT_EQ(table1.CompareWithTable(table2), -E_RELATIONAL_TABLE_COMPATIBLE);
601
602 TableInfo table3 = schemaObj.GetTable("SECOND");
603 EXPECT_EQ(table1.CompareWithTable(table3), -E_RELATIONAL_TABLE_INCOMPATIBLE);
604
605 TableInfo table4 = schemaObj.GetTable("FIRST");
606 table4.AddField(table3.GetFields().at("value"));
607 EXPECT_EQ(table1.CompareWithTable(table4), -E_RELATIONAL_TABLE_COMPATIBLE_UPGRADE);
608
609 TableInfo table5 = schemaObj.GetTable("FIRST");
610 table5.AddField(table3.GetFields().at("key"));
611 EXPECT_EQ(table1.CompareWithTable(table5), -E_RELATIONAL_TABLE_INCOMPATIBLE);
612
613 TableInfo table6 = schemaObj.GetTable("FIRST");
614 table6.SetUniqueDefine({{"field_name1", "field_name1"}});
615 EXPECT_EQ(table1.CompareWithTable(table6, SchemaConstant::SCHEMA_SUPPORT_VERSION_V2_1),
616 -E_RELATIONAL_TABLE_INCOMPATIBLE);
617
618 TableInfo table7 = schemaObj.GetTable("FIRST");
619 table7.SetAutoIncrement(false);
620 EXPECT_EQ(table1.CompareWithTable(table7, SchemaConstant::SCHEMA_SUPPORT_VERSION_V2_1),
621 -E_RELATIONAL_TABLE_INCOMPATIBLE);
622 }
623
624 /**
625 * @tc.name: RelationalSchemaOpinionTest001
626 * @tc.desc: Test relational schema sync opinion
627 * @tc.type: FUNC
628 * @tc.require: AR000GK58I
629 * @tc.author: lianhuix
630 */
631 HWTEST_F(DistributedDBRelationalSchemaObjectTest, RelationalSchemaOpinionTest001, TestSize.Level1)
632 {
633 RelationalSyncOpinion opinion;
634 opinion["table_1"] = SyncOpinion {true, false, false};
635 opinion["table_2"] = SyncOpinion {false, true, false};
636 opinion["table_3"] = SyncOpinion {false, false, true};
637
638 uint32_t len = SchemaNegotiate::CalculateParcelLen(opinion);
639 std::vector<uint8_t> buff(len, 0);
640 Parcel writeParcel(buff.data(), len);
641 int errCode = SchemaNegotiate::SerializeData(opinion, writeParcel);
642 EXPECT_EQ(errCode, E_OK);
643
644 Parcel readParcel(buff.data(), len);
645 RelationalSyncOpinion opinionRecv;
646 errCode = SchemaNegotiate::DeserializeData(readParcel, opinionRecv);
647 EXPECT_EQ(errCode, E_OK);
648
649 EXPECT_EQ(opinion.size(), opinionRecv.size());
650 for (const auto &it : opinion) {
651 SyncOpinion tableOpinionRecv = opinionRecv.at(it.first);
652 EXPECT_EQ(it.second.permitSync, tableOpinionRecv.permitSync);
653 EXPECT_EQ(it.second.requirePeerConvert, tableOpinionRecv.requirePeerConvert);
654 }
655 }
656
657 /**
658 * @tc.name: RelationalSchemaNegotiateTest001
659 * @tc.desc: Test relational schema negotiate
660 * @tc.type: FUNC
661 * @tc.require: AR000GK58I
662 * @tc.author: lianhuix
663 */
664 HWTEST_F(DistributedDBRelationalSchemaObjectTest, RelationalSchemaNegotiateTest001, TestSize.Level1)
665 {
666 RelationalSyncOpinion localOpinion;
667 localOpinion["table_1"] = SyncOpinion {true, false, false};
668 localOpinion["table_2"] = SyncOpinion {false, true, false};
669 localOpinion["table_3"] = SyncOpinion {false, false, true};
670
671 RelationalSyncOpinion remoteOpinion;
672 remoteOpinion["table_2"] = SyncOpinion {true, false, false};
673 remoteOpinion["table_3"] = SyncOpinion {false, true, false};
674 remoteOpinion["table_4"] = SyncOpinion {false, false, true};
675 RelationalSyncStrategy strategy = SchemaNegotiate::ConcludeSyncStrategy(localOpinion, remoteOpinion);
676
677 EXPECT_EQ(strategy.size(), 2u);
678 EXPECT_EQ(strategy.at("table_2").permitSync, true);
679 EXPECT_EQ(strategy.at("table_3").permitSync, false);
680 }
681
682 /**
683 * @tc.name: TableCompareTest001
684 * @tc.desc: Test table compare
685 * @tc.type: FUNC
686 * @tc.require: AR000GK58I
687 * @tc.author: lianhuix
688 */
689 HWTEST_F(DistributedDBRelationalSchemaObjectTest, TableCompareTest001, TestSize.Level1)
690 {
691 FieldInfo field1;
692 field1.SetFieldName("a");
693 FieldInfo field2;
694 field2.SetFieldName("b");
695 FieldInfo field3;
696 field3.SetFieldName("c");
697 FieldInfo field4;
698 field4.SetFieldName("d");
699
700 TableInfo table;
701 table.AddField(field2);
702 table.AddField(field3);
703
704 TableInfo inTable1;
705 inTable1.AddField(field1);
706 inTable1.AddField(field2);
707 inTable1.AddField(field3);
708 EXPECT_EQ(table.CompareWithTable(inTable1), -E_RELATIONAL_TABLE_COMPATIBLE_UPGRADE);
709
710 TableInfo inTable2;
711 inTable2.AddField(field1);
712 inTable2.AddField(field2);
713 inTable2.AddField(field4);
714 EXPECT_EQ(table.CompareWithTable(inTable2), -E_RELATIONAL_TABLE_INCOMPATIBLE);
715
716 TableInfo inTable3;
717 inTable3.AddField(field3);
718 inTable3.AddField(field2);
719 EXPECT_EQ(table.CompareWithTable(inTable3), -E_RELATIONAL_TABLE_EQUAL);
720 }
721
722 HWTEST_F(DistributedDBRelationalSchemaObjectTest, TableCaseInsensitiveCompareTest001, TestSize.Level1)
723 {
724 sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX);
725 EXPECT_NE(db, nullptr);
726 EXPECT_EQ(RelationalTestUtils::ExecSql(db, "PRAGMA journal_mode=WAL;"), SQLITE_OK);
727 std::string createStudentSql = "CREATE TABLE student(id INTEGER PRIMARY KEY, name TEXT, score INT, level INT)";
728 EXPECT_EQ(RelationalTestUtils::ExecSql(db, createStudentSql), SQLITE_OK);
729
730 TableInfo tableStudent;
731 EXPECT_EQ(SQLiteUtils::AnalysisSchema(db, "STUDENT", tableStudent), E_OK);
732
733 RelationalSchemaObject schema;
734 schema.AddRelationalTable(tableStudent);
735
736 EXPECT_FALSE(schema.GetTable("STUDENT").Empty());
737 EXPECT_FALSE(schema.GetTable("StudENT").Empty());
738 EXPECT_EQ(schema.GetTable("StudENT").CompareWithTable(schema.GetTable("STUDENT")), -E_RELATIONAL_TABLE_EQUAL);
739
740 EXPECT_EQ(sqlite3_close_v2(db), E_OK);
741 }
742
743 namespace {
GetTableInfo(sqlite3 * db,const std::string & tableName,const std::string & sql)744 TableInfo GetTableInfo(sqlite3 *db, const std::string &tableName, const std::string &sql)
745 {
746 EXPECT_NE(db, nullptr);
747 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), SQLITE_OK);
748 TableInfo tableInfo;
749 EXPECT_EQ(SQLiteUtils::AnalysisSchema(db, tableName, tableInfo), E_OK);
750 EXPECT_EQ(RelationalTestUtils::ExecSql(db, "DROP TABLE IF EXISTS " + tableName), SQLITE_OK);
751 return tableInfo;
752 }
753 }
754
755 HWTEST_F(DistributedDBRelationalSchemaObjectTest, TableCaseInsensitiveCompareTest002, TestSize.Level1)
756 {
757 sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX);
758 EXPECT_NE(db, nullptr);
759 EXPECT_EQ(RelationalTestUtils::ExecSql(db, "PRAGMA journal_mode=WAL;"), SQLITE_OK);
760
761 std::string createTableSql1 = "CREATE TABLE student(id INTEGER PRIMARY KEY, name TEXT, score INT, level INT); " \
762 "create index index_name on student (name);";
763 TableInfo table1 = GetTableInfo(db, "student", createTableSql1);
764 std::string createTableSql2 = "CREATE TABLE Student(ID INTEGER PRIMARY KEY, Name TEXT, Score INT, Level INT); " \
765 "create index index_NAME on student (Name);";
766 TableInfo table2 = GetTableInfo(db, "Student", createTableSql2);
767
768 EXPECT_EQ(table1.CompareWithTable(table2), -E_RELATIONAL_TABLE_EQUAL);
769
770 EXPECT_EQ(sqlite3_close_v2(db), E_OK);
771 db = nullptr;
772 }
773
774 namespace {
TableCompareTest(sqlite3 * db,const std::string & sql1,const std::string & sql2)775 int TableCompareTest(sqlite3 *db, const std::string &sql1, const std::string &sql2)
776 {
777 RelationalTestUtils::ExecSql(db, sql1);
778 TableInfo table1;
779 SQLiteUtils::AnalysisSchema(db, "student", table1);
780 RelationalTestUtils::ExecSql(db, "DROP TABLE IF EXISTS student");
781 RelationalTestUtils::ExecSql(db, sql2);
782 TableInfo table2;
783 SQLiteUtils::AnalysisSchema(db, "student", table2);
784 RelationalTestUtils::ExecSql(db, "DROP TABLE IF EXISTS student");
785 return table1.CompareWithTable(table2);
786 }
787
788 /**
789 * @tc.name: TableCompareTest001
790 * @tc.desc: Test table compare with default value
791 * @tc.type: FUNC
792 * @tc.require: AR000GK58I
793 * @tc.author: lianhuix
794 */
795 HWTEST_F(DistributedDBRelationalSchemaObjectTest, TableCompareTest002, TestSize.Level1)
796 {
797 sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX);
798 EXPECT_EQ(TableCompareTest(db, "CREATE TABLE student(id INTEGER PRIMARY KEY, name TEXT)",
799 "CREATE TABLE student(id INTEGER PRIMARY KEY, name TEXT)"),
800 -E_RELATIONAL_TABLE_EQUAL);
801 EXPECT_EQ(TableCompareTest(db, "CREATE TABLE student(id INTEGER PRIMARY KEY, name TEXT)",
802 "CREATE TABLE student(id INTEGER PRIMARY KEY, name TEXT DEFAULT 'xue')"),
803 -E_RELATIONAL_TABLE_INCOMPATIBLE);
804 EXPECT_EQ(TableCompareTest(db, "CREATE TABLE student(id INTEGER PRIMARY KEY, name TEXT)",
805 "CREATE TABLE student(id INTEGER PRIMARY KEY, name TEXT DEFAULT '')"),
806 -E_RELATIONAL_TABLE_INCOMPATIBLE);
807 EXPECT_EQ(TableCompareTest(db, "CREATE TABLE student(id INTEGER PRIMARY KEY, name TEXT)",
808 "CREATE TABLE student(id INTEGER PRIMARY KEY, name TEXT DEFAULT 'NULL')"),
809 -E_RELATIONAL_TABLE_INCOMPATIBLE);
810 EXPECT_EQ(TableCompareTest(db, "CREATE TABLE student(id INTEGER PRIMARY KEY, name TEXT)",
811 "CREATE TABLE student(id INTEGER PRIMARY KEY, name TEXT DEFAULT 'null')"),
812 -E_RELATIONAL_TABLE_INCOMPATIBLE);
813 EXPECT_EQ(TableCompareTest(db, "CREATE TABLE student(id INTEGER PRIMARY KEY, name TEXT)",
814 "CREATE TABLE student(id INTEGER PRIMARY KEY, name TEXT DEFAULT NULL)"),
815 -E_RELATIONAL_TABLE_INCOMPATIBLE);
816 EXPECT_EQ(TableCompareTest(db, "CREATE TABLE student(id INTEGER PRIMARY KEY, name TEXT)",
817 "CREATE TABLE student(id INTEGER PRIMARY KEY, name TEXT DEFAULT null)"),
818 -E_RELATIONAL_TABLE_INCOMPATIBLE);
819 EXPECT_EQ(TableCompareTest(db, "CREATE TABLE student(id INTEGER PRIMARY KEY, name TEXT DEFAULT 'XUE')",
820 "CREATE TABLE student(id INTEGER PRIMARY KEY, name TEXT DEFAULT 'xue')"),
821 -E_RELATIONAL_TABLE_INCOMPATIBLE);
822 EXPECT_EQ(TableCompareTest(db, "CREATE TABLE student(id INTEGER PRIMARY KEY, name TEXT DEFAULT NULL)",
823 "CREATE TABLE student(id INTEGER PRIMARY KEY, name TEXT DEFAULT null)"),
824 -E_RELATIONAL_TABLE_EQUAL);
825 EXPECT_EQ(TableCompareTest(db, "CREATE TABLE student(id INTEGER PRIMARY KEY, name TEXT DEFAULT 'NULL')",
826 "CREATE TABLE student(id INTEGER PRIMARY KEY, name TEXT DEFAULT 'null')"),
827 -E_RELATIONAL_TABLE_INCOMPATIBLE);
828 EXPECT_EQ(TableCompareTest(db, "CREATE TABLE student(id INTEGER PRIMARY KEY, name TEXT DEFAULT '')",
829 "CREATE TABLE student(id INTEGER PRIMARY KEY, name TEXT DEFAULT NULL)"),
830 -E_RELATIONAL_TABLE_INCOMPATIBLE);
831 EXPECT_EQ(TableCompareTest(db, "CREATE TABLE student(id INTEGER PRIMARY KEY, name TEXT DEFAULT '')",
832 "CREATE TABLE student(id INTEGER PRIMARY KEY, name TEXT DEFAULT null)"),
833 -E_RELATIONAL_TABLE_INCOMPATIBLE);
834 EXPECT_EQ(TableCompareTest(db, "CREATE TABLE student(id INTEGER PRIMARY KEY, name TEXT DEFAULT '')",
835 "CREATE TABLE student(id INTEGER PRIMARY KEY, name TEXT DEFAULT '')"),
836 -E_RELATIONAL_TABLE_EQUAL);
837 EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK);
838 db = nullptr;
839 }
840 } // namespace
841
842 /**
843 * @tc.name: FieldInfoCompareTest
844 * @tc.desc: Test field info compare
845 * @tc.type: FUNC
846 * @tc.require: DTS2024073106613
847 * @tc.author: suyue
848 */
849 HWTEST_F(DistributedDBRelationalSchemaObjectTest, FieldInfoCompareTest, TestSize.Level1)
850 {
851 /**
852 * @tc.steps: step1. call CompareWithField when storageType is different
853 * @tc.expected: step1. return false.
854 */
855 FieldInfo field1;
856 field1.SetStorageType(StorageType::STORAGE_TYPE_INTEGER);
857 FieldInfo field2;
858 EXPECT_EQ(field2.CompareWithField(field1, true), false);
859
860 /**
861 * @tc.steps: step2. call CompareWithField when fieldName is different
862 * @tc.expected: step2. return false.
863 */
864 field1.SetFieldName("test1");
865 field1.SetFieldName("test2");
866 EXPECT_EQ(field2.CompareWithField(field1, true), false);
867 }
868
869 /**
870 * @tc.name: TableInfoInterfacesTest
871 * @tc.desc: Test TableInfo interfaces
872 * @tc.type: FUNC
873 * @tc.require: DTS2024073106613
874 * @tc.author: suyue
875 */
876 HWTEST_F(DistributedDBRelationalSchemaObjectTest, TableInfoInterfacesTest, TestSize.Level1)
877 {
878 /**
879 * @tc.steps: step1. GetFieldName with empty TableInfo class
880 * @tc.expected: step1. return empty string.
881 */
882 TableInfo table1;
883 std::string str1 = table1.GetFieldName(0);
884 const std::string expectStr1 = "";
885 EXPECT_TRUE(str1.compare(0, expectStr1.length(), expectStr1) == 0);
886 table1.ToTableInfoString("");
887
888 /**
889 * @tc.steps: step2. Set and get tableId.
890 * @tc.expected: step2. success.
891 */
892 int inputId = 1;
893 table1.SetTableId(inputId);
894 int outputId = table1.GetTableId();
895 EXPECT_EQ(outputId, inputId);
896 }
897
898 /**
899 * @tc.name: SchemaTableCompareTest
900 * @tc.desc: Test LiteSchemaTable Compare
901 * @tc.type: FUNC
902 * @tc.require: DTS2024073106613
903 * @tc.author: suyue
904 */
905 HWTEST_F(DistributedDBRelationalSchemaObjectTest, SchemaTableCompareTest, TestSize.Level1)
906 {
907 /**
908 * @tc.steps: step1. Set key index of SetPrimaryKey to an invalid value
909 * @tc.expected: step1. fieldName vector is null.
910 */
911 TableInfo table1;
912 int keyIndex = -1;
913 table1.SetPrimaryKey("test", keyIndex);
914 CompositeFields vec = table1.GetIdentifyKey();
915 uint32_t expectedVal = 0;
916 EXPECT_EQ(vec.size(), expectedVal);
917
918 /**
919 * @tc.steps: step2. Compare table when fieldName of SetPrimaryKey is set to'rowid'
920 * @tc.expected: step2. compare return -E_RELATIONAL_TABLE_INCOMPATIBLE.
921 */
922 const std::vector<CompositeFields> uniqueDefine = {{"test0", "test1"}};
923 table1.SetUniqueDefine(uniqueDefine);
924 const std::map<int, FieldName> keyName1 = {{0, "rowid"}};
925 table1.SetPrimaryKey(keyName1);
926
927 vec = table1.GetIdentifyKey();
928 EXPECT_EQ(vec.size(), uniqueDefine[0].size());
929 int ret = table1.CompareWithLiteSchemaTable(table1);
930 EXPECT_EQ(ret, -E_RELATIONAL_TABLE_INCOMPATIBLE);
931
932 /**
933 * @tc.steps: step3. Compare table when fieldName of SetPrimaryKey is not set to "rowid".
934 * @tc.expected: step3. compare return E_OK.
935 */
936 FieldInfo field1;
937 table1.AddField(field1);
938 const std::map<int, FieldName> keyName2 = {{0, "test0"}, {1, "test1"}};
939 table1.SetPrimaryKey(keyName2);
940
941 vec = table1.GetIdentifyKey();
942 EXPECT_EQ(vec.size(), keyName2.size());
943 field1.SetFieldName("test1");
944 ret = table1.CompareWithLiteSchemaTable(table1);
945 EXPECT_EQ(ret, E_OK);
946 }
947 #endif