• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 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 "cloud/schema_mgr.h"
16 
17 #include <gtest/gtest.h>
18 
19 #include "db_errno.h"
20 #include "distributeddb_tools_unit_test.h"
21 #include "relational_store_manager.h"
22 #include "relational_schema_object.h"
23 #include "distributeddb_data_generate_unit_test.h"
24 #include "relational_sync_able_storage.h"
25 #include "relational_store_instance.h"
26 #include "sqlite_relational_store.h"
27 #include "log_table_manager_factory.h"
28 
29 using namespace testing::ext;
30 using namespace DistributedDB;
31 using namespace DistributedDBUnitTest;
32 using namespace std;
33 
34 namespace {
35     constexpr auto TABLE_NAME_1 = "tableName1";
36     constexpr auto TABLE_NAME_2 = "tableName2";
37     constexpr auto TABLE_NAME_3 = "tableName3";
38     constexpr auto TABLE_NAME_4 = "tableName4";
39 
40     constexpr auto FIELD_NAME_1 = "field_name_1";
41     constexpr auto FIELD_NAME_2 = "field_name_2";
42     constexpr auto FIELD_NAME_3 = "field_name_3";
43 
44 std::unique_ptr<SchemaMgr> g_schemaMgr = nullptr;
45 
46 class DistributedDBCloudSchemaMgrTest : public testing::Test {
47 public:
48     static void SetUpTestCase(void);
49     static void TearDownTestCase(void);
50     void SetUp();
51     void TearDown();
52 };
53 
SetUpTestCase(void)54 void DistributedDBCloudSchemaMgrTest::SetUpTestCase(void)
55 {
56 }
57 
TearDownTestCase(void)58 void DistributedDBCloudSchemaMgrTest::TearDownTestCase(void)
59 {
60 }
61 
SetUp(void)62 void DistributedDBCloudSchemaMgrTest::SetUp(void)
63 {
64     g_schemaMgr = std::make_unique<SchemaMgr>();
65 }
66 
TearDown(void)67 void DistributedDBCloudSchemaMgrTest::TearDown(void)
68 {
69     g_schemaMgr = nullptr;
70 }
71 
72 DataBaseSchema g_schema = {
73     .tables = {
74         {
75             .name = TABLE_NAME_1,
76             .fields = {
77                 {
78                     .colName = FIELD_NAME_1,
79                     .type = TYPE_INDEX<int64_t>,
80                     .primary = true,
81                     .nullable = true,
82                 },
83                 {
84                     .colName = FIELD_NAME_2,
85                     .type = TYPE_INDEX<int64_t>,
86                     .primary = false,
87                     .nullable = true,
88                 }
89             }
90         },
91         {
92             .name = TABLE_NAME_2,
93             .fields = {
94                 {
95                     .colName = FIELD_NAME_1,
96                     .type = TYPE_INDEX<int64_t>,
97                     .primary = true,
98                     .nullable = true,
99                 },
100                 {
101                     .colName = FIELD_NAME_2,
102                     .type = TYPE_INDEX<int64_t>,
103                     .primary = false,
104                     .nullable = true,
105                 }
106             }
107         },
108         {
109             .name = TABLE_NAME_3,
110             .fields = {
111                 {
112                     .colName = FIELD_NAME_1,
113                     .type = TYPE_INDEX<Asset>,
114                     .primary = true,
115                     .nullable = true,
116                 },
117                 {
118                     .colName = FIELD_NAME_2,
119                     .type = TYPE_INDEX<std::string>,
120                     .primary = false,
121                     .nullable = true,
122                 },
123                 {
124                     .colName = FIELD_NAME_3,
125                     .type = TYPE_INDEX<int64_t>,
126                     .primary = false,
127                     .nullable = true,
128                 }
129             }
130         },
131         {
132             .name = TABLE_NAME_4,
133             .fields = {
134                 {
135                     .colName = FIELD_NAME_1,
136                     .type = TYPE_INDEX<Assets>,
137                     .primary = false,
138                     .nullable = true,
139                 },
140                 {
141                     .colName = FIELD_NAME_2,
142                     .type = TYPE_INDEX<std::string>,
143                     .primary = false,
144                     .nullable = true,
145                 },
146                 {
147                     .colName = FIELD_NAME_3,
148                     .type = TYPE_INDEX<int64_t>,
149                     .primary = false,
150                     .nullable = true,
151                 }
152             }
153         }
154     }
155 };
156 
157 DataBaseSchema g_schema2 = {
158     .tables = {
159         {
160             .name = TABLE_NAME_2,
161             .fields = {
162                 {
163                     .colName = FIELD_NAME_1,
164                     .type = TYPE_INDEX<int64_t>,
165                     .primary = true,
166                     .nullable = true,
167                 },
168                 {
169                     .colName = FIELD_NAME_2,
170                     .type = TYPE_INDEX<int64_t>,
171                     .primary = false,
172                     .nullable = true,
173                 }
174             }
175         },
176         {
177             .name = TABLE_NAME_3,
178             .fields = {
179                 {
180                     .colName = FIELD_NAME_1,
181                     .type = TYPE_INDEX<int64_t>,
182                     .primary = true,
183                     .nullable = true,
184                 },
185                 {
186                     .colName = FIELD_NAME_2,
187                     .type = TYPE_INDEX<int64_t>,
188                     .primary = false,
189                     .nullable = true,
190                 }
191             }
192         },
193         {
194             .name = TABLE_NAME_4,
195             .fields = {
196                 {
197                     .colName = FIELD_NAME_1,
198                     .type = TYPE_INDEX<int64_t>,
199                     .primary = true,
200                     .nullable = true,
201                 },
202                 {
203                     .colName = FIELD_NAME_2,
204                     .type = TYPE_INDEX<int64_t>,
205                     .primary = false,
206                     .nullable = true,
207                 }
208             }
209         }
210     }
211 };
212 
213 
SetField(std::string fieldName,std::string dataType,bool nullable)214 FieldInfo SetField(std::string fieldName, std::string dataType, bool nullable)
215 {
216     FieldInfo field;
217     field.SetFieldName(fieldName);
218     field.SetDataType(dataType);
219     field.SetNotNull(!nullable);
220     return field;
221 }
222 
223 /**
224   * @tc.name: SchemaMgrTest001
225   * @tc.desc: Cloud schema and local schema are not been set
226   * test situation: TABLE_NAME exist and not exist(TABLE_NAME_3)
227   * @tc.type: FUNC
228   * @tc.require:
229   * @tc.author: wanyi
230   */
231 HWTEST_F(DistributedDBCloudSchemaMgrTest, SchemaMgrTest001, TestSize.Level0)
232 {
233     FieldInfo field1 = SetField(FIELD_NAME_1, "int", true);
234     FieldInfo field2 = SetField(FIELD_NAME_2, "int", true);
235     TableInfo table;
236     table.SetTableName(TABLE_NAME_2);
237     table.AddField(field1);
238     table.AddField(field2);
239     table.SetPrimaryKey(FIELD_NAME_1, 1);
240     table.SetTableSyncType(TableSyncType::CLOUD_COOPERATION);
241     RelationalSchemaObject localSchema;
242     localSchema.AddRelationalTable(table);
243 
244     EXPECT_EQ(g_schemaMgr->ChkSchema(TABLE_NAME_1, localSchema), -E_SCHEMA_MISMATCH);
245     EXPECT_EQ(g_schemaMgr->ChkSchema(TABLE_NAME_2, localSchema), -E_SCHEMA_MISMATCH);
246     EXPECT_EQ(g_schemaMgr->ChkSchema(TABLE_NAME_3, localSchema), -E_SCHEMA_MISMATCH);
247 }
248 
249 /**
250   * @tc.name: SchemaMgrTest002
251   * @tc.desc: Cloud schema and local schema are the same
252   * @tc.type: FUNC
253   * @tc.require:
254   * @tc.author: wanyi
255   */
256 HWTEST_F(DistributedDBCloudSchemaMgrTest, SchemaMgrTest002, TestSize.Level0)
257 {
258     FieldInfo field1 = SetField(FIELD_NAME_1, "int", true);
259     FieldInfo field2 = SetField(FIELD_NAME_2, "int", true);
260     TableInfo table;
261     table.SetTableName(TABLE_NAME_2);
262     table.AddField(field1);
263     table.AddField(field2);
264     table.SetPrimaryKey(FIELD_NAME_1, 1);
265     table.SetTableSyncType(TableSyncType::CLOUD_COOPERATION);
266     RelationalSchemaObject localSchema;
267     localSchema.AddRelationalTable(table);
268 
269     g_schemaMgr->SetCloudDbSchema(g_schema);
270     EXPECT_EQ(g_schemaMgr->ChkSchema(TABLE_NAME_2, localSchema), E_OK);
271     EXPECT_EQ(g_schemaMgr->ChkSchema(TABLE_NAME_2, localSchema), E_OK);
272     EXPECT_EQ(g_schemaMgr->ChkSchema(TABLE_NAME_2, localSchema), E_OK);
273 }
274 
275 /**
276   * @tc.name: SchemaMgrTest003
277   * @tc.desc: Local schema contain extra primary key
278   * @tc.type: FUNC
279   * @tc.require:
280   * @tc.author: wanyi
281   */
282 HWTEST_F(DistributedDBCloudSchemaMgrTest, SchemaMgrTest003, TestSize.Level0)
283 {
284     FieldInfo field1 = SetField(FIELD_NAME_1, "int", true);
285     FieldInfo field2 = SetField(FIELD_NAME_2, "int", true);
286     FieldInfo field3 = SetField(FIELD_NAME_3, "int", true);
287 
288     TableInfo table;
289     table.SetTableName(TABLE_NAME_2);
290     table.AddField(field1);
291     table.AddField(field2);
292     table.AddField(field3);
293     table.SetPrimaryKey(FIELD_NAME_1, 1);
294     table.SetPrimaryKey(FIELD_NAME_3, 2);
295     table.SetTableSyncType(TableSyncType::CLOUD_COOPERATION);
296     RelationalSchemaObject localSchema;
297     localSchema.AddRelationalTable(table);
298 
299     g_schemaMgr->SetCloudDbSchema(g_schema);
300     EXPECT_EQ(g_schemaMgr->ChkSchema(TABLE_NAME_2, localSchema), -E_SCHEMA_MISMATCH);
301 }
302 
303 /**
304   * @tc.name: SchemaMgrTest003
305   * @tc.desc: Column from local schema is not within cloud schema but is not nullable
306   * @tc.type: FUNC
307   * @tc.require:
308   * @tc.author: wanyi
309   */
310 HWTEST_F(DistributedDBCloudSchemaMgrTest, SchemaMgrTest004, TestSize.Level0)
311 {
312     FieldInfo field1 = SetField(FIELD_NAME_1, "int", true);
313     FieldInfo field2 = SetField(FIELD_NAME_2, "int", true);
314     FieldInfo field3 = SetField(FIELD_NAME_2, "int", false);
315 
316     TableInfo table;
317     table.SetTableName(TABLE_NAME_2);
318     table.AddField(field1);
319     table.AddField(field2);
320     table.AddField(field3);
321     table.SetPrimaryKey(FIELD_NAME_1, 1);
322     table.SetTableSyncType(TableSyncType::CLOUD_COOPERATION);
323     RelationalSchemaObject localSchema;
324     localSchema.AddRelationalTable(table);
325 
326     g_schemaMgr->SetCloudDbSchema(g_schema);
327     EXPECT_EQ(g_schemaMgr->ChkSchema(TABLE_NAME_2, localSchema), -E_SCHEMA_MISMATCH);
328 }
329 
330 /**
331   * @tc.name: SchemaMgrTest003
332   * @tc.desc: Local schema contain extra noraml key with default value but cannot be null
333   * @tc.type: FUNC
334   * @tc.require:
335   * @tc.author: wanyi
336   */
337 HWTEST_F(DistributedDBCloudSchemaMgrTest, SchemaMgrTest005, TestSize.Level0)
338 {
339     FieldInfo field1 = SetField(FIELD_NAME_1, "int", true);
340     FieldInfo field2 = SetField(FIELD_NAME_2, "int", true);
341     FieldInfo field3 = SetField(FIELD_NAME_3, "int", false);
342     field3.SetDefaultValue("0");
343 
344     TableInfo table;
345     table.SetTableName(TABLE_NAME_2);
346     table.AddField(field1);
347     table.AddField(field2);
348     table.AddField(field3);
349     table.SetPrimaryKey(FIELD_NAME_1, 1);
350     table.SetTableSyncType(TableSyncType::CLOUD_COOPERATION);
351     RelationalSchemaObject localSchema;
352     localSchema.AddRelationalTable(table);
353 
354     g_schemaMgr->SetCloudDbSchema(g_schema);
355     EXPECT_EQ(g_schemaMgr->ChkSchema(TABLE_NAME_2, localSchema), E_OK);
356 }
357 
358 /**
359   * @tc.name: SchemaMgrTest003
360   * @tc.desc: Local schema contain extra noraml key with default value but cannot be null
361   * @tc.type: FUNC
362   * @tc.require:
363   * @tc.author: wanyi
364   */
365 HWTEST_F(DistributedDBCloudSchemaMgrTest, SchemaMgrTest006, TestSize.Level0)
366 {
367     FieldInfo field1 = SetField(FIELD_NAME_1, "int", true);
368     FieldInfo field2 = SetField(FIELD_NAME_2, "int", true);
369     FieldInfo field3 = SetField(FIELD_NAME_3, "int", true);
370     field3.SetDefaultValue("0");
371 
372     TableInfo table;
373     table.SetTableName(TABLE_NAME_2);
374     table.AddField(field1);
375     table.AddField(field2);
376     table.AddField(field3);
377     table.SetPrimaryKey(FIELD_NAME_1, 1);
378     table.SetTableSyncType(TableSyncType::CLOUD_COOPERATION);
379     RelationalSchemaObject localSchema;
380     localSchema.AddRelationalTable(table);
381 
382     g_schemaMgr->SetCloudDbSchema(g_schema);
383     EXPECT_EQ(g_schemaMgr->ChkSchema(TABLE_NAME_2, localSchema), E_OK);
384 }
385 
386 /**
387   * @tc.name: SchemaMgrTest003
388   * @tc.desc: Local schema contain extra noraml key with default value but cannot be null
389   * @tc.type: FUNC
390   * @tc.require:
391   * @tc.author: wanyi
392   */
393 HWTEST_F(DistributedDBCloudSchemaMgrTest, SchemaMgrTest007, TestSize.Level0)
394 {
395     FieldInfo field1 = SetField(FIELD_NAME_1, "int", true);
396     FieldInfo field2 = SetField(FIELD_NAME_2, "int", true);
397     FieldInfo field3 = SetField(FIELD_NAME_3, "int", true);
398 
399     TableInfo table;
400     table.SetTableName(TABLE_NAME_2);
401     table.AddField(field1);
402     table.AddField(field2);
403     table.AddField(field3);
404     table.SetPrimaryKey(FIELD_NAME_1, 1);
405     table.SetTableSyncType(TableSyncType::CLOUD_COOPERATION);
406     RelationalSchemaObject localSchema;
407     localSchema.AddRelationalTable(table);
408 
409     g_schemaMgr->SetCloudDbSchema(g_schema);
410     EXPECT_EQ(g_schemaMgr->ChkSchema(TABLE_NAME_2, localSchema), E_OK);
411 }
412 
413 /**
414   * @tc.name: SchemaMgrTest008
415   * @tc.desc: Cloud schema or local schema are not exist
416   * @tc.type: FUNC
417   * @tc.require:
418   * @tc.author: wanyi
419   */
420 HWTEST_F(DistributedDBCloudSchemaMgrTest, SchemaMgrTest008, TestSize.Level0)
421 {
422     FieldInfo field1 = SetField(FIELD_NAME_1, "int", true);
423     FieldInfo field2 = SetField(FIELD_NAME_2, "int", true);
424     TableInfo table;
425     table.SetTableName(TABLE_NAME_3);
426     table.AddField(field1);
427     table.AddField(field2);
428     table.SetPrimaryKey(FIELD_NAME_1, 1);
429     table.SetTableSyncType(TableSyncType::CLOUD_COOPERATION);
430 
431     TableInfo table2;
432     table2.SetTableName(TABLE_NAME_1);
433     table2.AddField(field1);
434     table2.AddField(field2);
435     table2.SetPrimaryKey(FIELD_NAME_1, 1);
436     table2.SetTableSyncType(TableSyncType::CLOUD_COOPERATION);
437 
438     RelationalSchemaObject localSchema;
439     localSchema.AddRelationalTable(table);
440     localSchema.AddRelationalTable(table2);
441 
442     g_schemaMgr->SetCloudDbSchema(g_schema);
443     // local schema exist but cloud schema not exist
444     EXPECT_EQ(g_schemaMgr->ChkSchema(TABLE_NAME_3, localSchema), -E_SCHEMA_MISMATCH);
445     // cloud schema exist but local schema not exist
446     EXPECT_EQ(g_schemaMgr->ChkSchema(TABLE_NAME_2, localSchema), -E_SCHEMA_MISMATCH);
447     // Both cloud schema and local schema does not exist
448     EXPECT_EQ(g_schemaMgr->ChkSchema(TABLE_NAME_4, localSchema), -E_SCHEMA_MISMATCH);
449     // Both cloud schema and local schema exist
450     EXPECT_EQ(g_schemaMgr->ChkSchema(TABLE_NAME_1, localSchema), E_OK);
451 
452     g_schemaMgr->SetCloudDbSchema(g_schema2);
453     EXPECT_EQ(g_schemaMgr->ChkSchema(TABLE_NAME_3, localSchema), E_OK);
454     EXPECT_EQ(g_schemaMgr->ChkSchema(TABLE_NAME_1, localSchema), -E_SCHEMA_MISMATCH);
455 }
456 
457 /**
458   * @tc.name: SchemaMgrTest008
459   * @tc.desc: Test schema mgr with empty local schema
460   * @tc.type: FUNC
461   * @tc.require:
462   * @tc.author: wanyi
463   */
464 HWTEST_F(DistributedDBCloudSchemaMgrTest, SchemaMgrTest009, TestSize.Level0)
465 {
466     RelationalSchemaObject localSchema;
467     g_schemaMgr->SetCloudDbSchema(g_schema);
468     EXPECT_EQ(g_schemaMgr->ChkSchema(TABLE_NAME_1, localSchema), -E_SCHEMA_MISMATCH);
469 }
470 
471 /**
472   * @tc.name: SchemaMgrTest010
473   * @tc.desc: Test local schema with un-expected sync type
474   * @tc.type: FUNC
475   * @tc.require:
476   * @tc.author: wanyi
477   */
478 HWTEST_F(DistributedDBCloudSchemaMgrTest, SchemaMgrTest010, TestSize.Level0)
479 {
480     FieldInfo field1 = SetField(FIELD_NAME_1, "int", true);
481     FieldInfo field2 = SetField(FIELD_NAME_2, "int", true);
482     FieldInfo field3 = SetField(FIELD_NAME_3, "int", true);
483 
484     TableInfo table;
485     table.SetTableName(TABLE_NAME_2);
486     table.AddField(field1);
487     table.AddField(field2);
488     table.AddField(field3);
489     table.SetPrimaryKey(FIELD_NAME_1, 1);
490     table.SetTableSyncType(TableSyncType::DEVICE_COOPERATION);
491     RelationalSchemaObject localSchema;
492     localSchema.AddRelationalTable(table);
493 
494     g_schemaMgr->SetCloudDbSchema(g_schema);
495     EXPECT_EQ(g_schemaMgr->ChkSchema(TABLE_NAME_2, localSchema), -E_NOT_SUPPORT);
496 }
497 
498 /**
499   * @tc.name: SchemaMgrTest011
500   * @tc.desc: Test local schema with un-expected data type
501   * @tc.type: FUNC
502   * @tc.require:
503   * @tc.author: wanyi
504   */
505 HWTEST_F(DistributedDBCloudSchemaMgrTest, SchemaMgrTest011, TestSize.Level0)
506 {
507     FieldInfo field1 = SetField(FIELD_NAME_1, "int", true);
508     FieldInfo field2 = SetField(FIELD_NAME_2, "text", true);
509     FieldInfo field3 = SetField(FIELD_NAME_3, "int", true);
510 
511     TableInfo table;
512     table.SetTableName(TABLE_NAME_2);
513     table.AddField(field1);
514     table.AddField(field2);
515     table.AddField(field3);
516     table.SetPrimaryKey(FIELD_NAME_1, 1);
517     table.SetTableSyncType(TableSyncType::CLOUD_COOPERATION);
518     RelationalSchemaObject localSchema;
519     localSchema.AddRelationalTable(table);
520 
521     g_schemaMgr->SetCloudDbSchema(g_schema);
522     EXPECT_EQ(g_schemaMgr->ChkSchema(TABLE_NAME_2, localSchema), -E_SCHEMA_MISMATCH);
523 }
524 
525 /**
526   * @tc.name: SchemaMgrTest012
527   * @tc.desc: table 3 contain primary asset field
528   * @tc.type: FUNC
529   * @tc.require:
530   * @tc.author: wanyi
531   */
532 HWTEST_F(DistributedDBCloudSchemaMgrTest, SchemaMgrTest012, TestSize.Level0)
533 {
534     FieldInfo field1 = SetField(FIELD_NAME_1, "blob", true);
535     FieldInfo field2 = SetField(FIELD_NAME_2, "text", true);
536     FieldInfo field3 = SetField(FIELD_NAME_3, "int", true);
537 
538     TableInfo table;
539     table.SetTableName(TABLE_NAME_3);
540     table.AddField(field1);
541     table.AddField(field2);
542     table.AddField(field3);
543     table.SetPrimaryKey(FIELD_NAME_1, 1);
544     table.SetTableSyncType(TableSyncType::CLOUD_COOPERATION);
545     RelationalSchemaObject localSchema;
546     localSchema.AddRelationalTable(table);
547 
548     g_schemaMgr->SetCloudDbSchema(g_schema);
549     EXPECT_EQ(g_schemaMgr->ChkSchema(TABLE_NAME_3, localSchema), -E_SCHEMA_MISMATCH);
550 }
551 
552 /**
553   * @tc.name: SchemaMgrTest013
554   * @tc.desc: table 4 do not contain primary assets field
555   * @tc.type: FUNC
556   * @tc.require:
557   * @tc.author: wanyi
558   */
559 HWTEST_F(DistributedDBCloudSchemaMgrTest, SchemaMgrTest013, TestSize.Level0)
560 {
561     /**
562      * @tc.steps:step1. local schema's asset field is not primary
563      * @tc.expected: step1. return ok.
564      */
565     FieldInfo field1 = SetField(FIELD_NAME_1, "blob", true);
566     FieldInfo field2 = SetField(FIELD_NAME_2, "text", true);
567     FieldInfo field3 = SetField(FIELD_NAME_3, "int", true);
568 
569     TableInfo table;
570     table.SetTableName(TABLE_NAME_4);
571     table.AddField(field1);
572     table.AddField(field2);
573     table.AddField(field3);
574     table.SetTableSyncType(TableSyncType::CLOUD_COOPERATION);
575     RelationalSchemaObject localSchema;
576     localSchema.AddRelationalTable(table);
577 
578     g_schemaMgr->SetCloudDbSchema(g_schema);
579     EXPECT_EQ(g_schemaMgr->ChkSchema(TABLE_NAME_4, localSchema), E_OK);
580     /**
581      * @tc.steps:step2. local schema's asset field is primary
582      * @tc.expected: step2. return E_SCHEMA_MISMATCH.
583      */
584     table.SetPrimaryKey(FIELD_NAME_1, 1);
585     RelationalSchemaObject localSchemaWithAssetPrimary;
586     localSchemaWithAssetPrimary.AddRelationalTable(table);
587     EXPECT_EQ(g_schemaMgr->ChkSchema(TABLE_NAME_4, localSchemaWithAssetPrimary), -E_SCHEMA_MISMATCH);
588 }
589 }