• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #ifndef OMIT_JSON
17 #include <functional>
18 #include <gtest/gtest.h>
19 #include <string>
20 
21 #include "distributeddb_tools_unit_test.h"
22 #include "kv_store_delegate_manager.h"
23 #include "kv_store_nb_delegate.h"
24 #include "query.h"
25 
26 using namespace testing::ext;
27 using namespace DistributedDB;
28 using namespace DistributedDBUnitTest;
29 
30 namespace {
31     const std::string VALID_SCHEMA_STRICT_DEFINE = "{\"SCHEMA_VERSION\":\"1.0\","
32         "\"SCHEMA_MODE\":\"STRICT\","
33         "\"SCHEMA_DEFINE\":{"
34             "\"field_name1\":\"BOOL\","
35             "\"field_name2\":\"INTEGER, NOT NULL\""
36         "},"
37         "\"SCHEMA_INDEXES\":[\"$.field_name1\"]}";
38     const std::string VALID_SCHEMA_COMPA_DEFINE = "{\"SCHEMA_VERSION\":\"1.0\","
39         "\"SCHEMA_MODE\":\"COMPATIBLE\","
40         "\"SCHEMA_DEFINE\":{"
41             "\"field_name1\":\"BOOL\","
42             "\"field_name2\":\"INTEGER, NOT NULL\""
43         "},"
44         "\"SCHEMA_INDEXES\":[\"$.field_name1\"]}";
45     const std::string VALID_SCHEMA_COMPA_WITH_SQL_KEYWORD_DEFINE = "{\"SCHEMA_VERSION\":\"1.0\","
46         "\"SCHEMA_MODE\":\"COMPATIBLE\","
47         "\"SCHEMA_DEFINE\":{"
48             "\"create\":\"BOOL\","
49             "\"default\":\"INTEGER, NOT NULL\""
50         "},"
51         "\"SCHEMA_INDEXES\":[\"create\"]}";
52     // define some variables to init a KvStoreDelegateManager object.
53     KvStoreDelegateManager g_mgr("app0", "user0");
54     std::string g_testDir;
55     KvStoreConfig g_config;
56     std::string g_storeName = "schema_put_test";
57 
58     // define the g_kvNbDelegateCallback, used to get some information when open a kv store.
59     DBStatus g_kvDelegateStatus = INVALID_ARGS;
60     KvStoreNbDelegate *g_kvStore = nullptr;
61     CipherPassword g_passwd;
62     KvStoreNbDelegate::Option g_strictOpt = {true, false, false, CipherType::DEFAULT, g_passwd,
63         VALID_SCHEMA_STRICT_DEFINE};
64     KvStoreNbDelegate::Option g_compOpt = {true, false, false, CipherType::DEFAULT, g_passwd,
65         VALID_SCHEMA_COMPA_DEFINE};
66 
KvStoreNbDelegateCallback(DBStatus statusSrc,KvStoreNbDelegate * kvStoreSrc,DBStatus * statusDst,KvStoreNbDelegate ** kvStoreDst)67     void KvStoreNbDelegateCallback(
68         DBStatus statusSrc, KvStoreNbDelegate* kvStoreSrc, DBStatus* statusDst, KvStoreNbDelegate** kvStoreDst)
69     {
70         *statusDst = statusSrc;
71         *kvStoreDst = kvStoreSrc;
72     }
73 
74     // the type of g_kvNbDelegateCallback is function<void(DBStatus, KvStoreDelegate*)>
75     auto g_kvNbDelegateCallback = std::bind(&KvStoreNbDelegateCallback, std::placeholders::_1,
76         std::placeholders::_2, &g_kvDelegateStatus, &g_kvStore);
77 
CheckPutSchemaData(KvStoreNbDelegate * kvStore)78     void CheckPutSchemaData(KvStoreNbDelegate *kvStore)
79     {
80         ASSERT_NE(kvStore, nullptr);
81         Key key;
82         DistributedDBToolsUnitTest::GetRandomKeyValue(key);
83         /**
84          * @tc.steps:step1. Put one data whose value has less fields than the schema(less value is not null).
85          * @tc.expected: step1. return CONSTRAIN_VIOLATION.
86          */
87         std::string lessData = "{\"field_name1\":true}";
88         Value value(lessData.begin(), lessData.end());
89         EXPECT_EQ(g_kvStore->Put(key, value), CONSTRAIN_VIOLATION);
90 
91         /**
92          * @tc.steps:step2. Put one data whose value has different type with the schema.
93          * @tc.expected: step2. return INVALID_FIELD_TYPE.
94          */
95         std::string typeDiffData = "{\"field_name1\":30,\"field_name2\":10}";
96         value.assign(typeDiffData.begin(), typeDiffData.end());
97         EXPECT_EQ(kvStore->Put(key, value), INVALID_FIELD_TYPE);
98 
99         /**
100          * @tc.steps:step3. Put one data whose value has constrain violation with the schema.
101          * @tc.expected: step3. return CONSTRAIN_VIOLATION.
102          */
103         std::string constrainDiffData = "{\"field_name1\":false,\"field_name2\":null}";
104         value.assign(constrainDiffData.begin(), constrainDiffData.end());
105         EXPECT_EQ(kvStore->Put(key, value), CONSTRAIN_VIOLATION);
106 
107         /**
108          * @tc.steps:step4. Put one data whose value has invalid json.
109          * @tc.expected: step4. return INVALID_FORMAT.
110          */
111         std::string invalidJsonData = "{\"field_name1\":false,\"field_name2\":10";
112         value.assign(invalidJsonData.begin(), invalidJsonData.end());
113         EXPECT_EQ(kvStore->Put(key, value), INVALID_FORMAT);
114 
115         /**
116          * @tc.steps:step5. Put one data whose value is empty.
117          * @tc.expected: step5. return INVALID_FORMAT.
118          */
119         value.clear();
120         EXPECT_EQ(kvStore->Put(key, value), INVALID_FORMAT);
121 
122         /**
123          * @tc.steps:step6. Put one data whose value is match with the schema.
124          * @tc.expected: step6. return INVALID_FORMAT.
125          */
126         std::string validJsonData = "{\"field_name1\":false,\"field_name2\":10}";
127         value.assign(validJsonData.begin(), validJsonData.end());
128         EXPECT_EQ(kvStore->Put(key, value), OK);
129     }
130 
CheckPutBatchSchemaData(KvStoreNbDelegate * kvStore)131     void CheckPutBatchSchemaData(KvStoreNbDelegate *kvStore)
132     {
133         ASSERT_NE(kvStore, nullptr);
134         /**
135          * @tc.steps:step1. Put the batch data, one data is invalid.
136          * @tc.expected: step1. return INVALID_FORMAT.
137          */
138         Key key;
139         DistributedDBToolsUnitTest::GetRandomKeyValue(key);
140         std::string invalidData = "{\"field_name1\":true, \"field_name2\":null}";
141         Value value(invalidData.begin(), invalidData.end());
142         std::vector<Entry> entries;
143         entries.push_back({key, value});
144 
145         DistributedDBToolsUnitTest::GetRandomKeyValue(key);
146         std::string validData = "{\"field_name1\":true, \"field_name2\":0}";
147         value.assign(validData.begin(), validData.end());
148         entries.push_back({key, value});
149 
150         EXPECT_NE(kvStore->PutBatch(entries), INVALID_FORMAT);
151 
152         entries.clear();
153         entries.push_back({key, value});
154 
155         /**
156          * @tc.steps:step2. Put the batch data, both valid.
157          * @tc.expected: step2. return OK.
158          */
159         DistributedDBToolsUnitTest::GetRandomKeyValue(key);
160         validData = "{\"field_name1\":null, \"field_name2\":30}";
161         value.assign(validData.begin(), validData.end());
162         entries.push_back({key, value});
163 
164         EXPECT_EQ(kvStore->PutBatch(entries), OK);
165     }
166 }
167 class DistributedDBInterfacesNBDelegateSchemaPutTest : public testing::Test {
168 public:
169     static void SetUpTestCase(void);
170     static void TearDownTestCase(void);
171     void SetUp();
172     void TearDown();
173 };
174 
SetUpTestCase(void)175 void DistributedDBInterfacesNBDelegateSchemaPutTest::SetUpTestCase(void)
176 {
177     DistributedDBToolsUnitTest::TestDirInit(g_testDir);
178     g_config.dataDir = g_testDir;
179     g_mgr.SetKvStoreConfig(g_config);
180 }
181 
TearDownTestCase(void)182 void DistributedDBInterfacesNBDelegateSchemaPutTest::TearDownTestCase(void)
183 {
184     if (DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir) != 0) {
185         LOGE("rm test db files error!");
186     }
187 }
188 
SetUp(void)189 void DistributedDBInterfacesNBDelegateSchemaPutTest::SetUp(void)
190 {
191     DistributedDBToolsUnitTest::PrintTestCaseInfo();
192 }
193 
TearDown(void)194 void DistributedDBInterfacesNBDelegateSchemaPutTest::TearDown(void)
195 {
196     EXPECT_EQ(g_mgr.CloseKvStore(g_kvStore), OK);
197     EXPECT_EQ(g_mgr.DeleteKvStore(g_storeName), OK);
198     g_kvStore = nullptr;
199     g_kvDelegateStatus = INVALID_ARGS;
200 }
201 
202 /**
203   * @tc.name: PutValueStrictSchemaCheck001
204   * @tc.desc: Check the value in the strict schema mode.
205   * @tc.type: FUNC
206   * @tc.require:
207   * @tc.author: wangbingquan
208   */
209 HWTEST_F(DistributedDBInterfacesNBDelegateSchemaPutTest, PutValueStrictSchemaCheck001, TestSize.Level1)
210 {
211     g_mgr.GetKvStore(g_storeName, g_strictOpt, g_kvNbDelegateCallback);
212     ASSERT_TRUE(g_kvStore != nullptr);
213     EXPECT_TRUE(g_kvDelegateStatus == OK);
214 
215     /**
216      * @tc.steps:step1. Put one data whose value has more fields than the schema.
217      * @tc.expected: step1. return INVALID_VALUE_FIELDS.
218      */
219     Key key;
220     DistributedDBToolsUnitTest::GetRandomKeyValue(key);
221     std::string moreData = "{\"field_name1\":true,\"field_name2\":10,\"field_name3\":10}";
222     Value value(moreData.begin(), moreData.end());
223     EXPECT_EQ(g_kvStore->Put(key, value), INVALID_VALUE_FIELDS);
224 
225     /**
226      * @tc.steps:step2. Put one data whose value has diff fields than the schema.
227      * @tc.expected: step2. return INVALID_VALUE_FIELDS.
228      */
229     std::string diffData = "{\"field_name2\":10,\"field_name3\":10}";
230     Value value1(diffData.begin(), diffData.end());
231     EXPECT_EQ(g_kvStore->Put(key, value1), INVALID_VALUE_FIELDS);
232 
233     std::string filedDiffData = "{\"field_name1\":true,\"field_name3\":10}";
234     value.assign(filedDiffData.begin(), filedDiffData.end());
235     EXPECT_EQ(g_kvStore->Put(key, value), INVALID_VALUE_FIELDS);
236 
237     /**
238      * @tc.steps:step3. Put the data whose value is mismatch with the schema.
239      * @tc.expected: step3. return not OK.
240      */
241     CheckPutSchemaData(g_kvStore);
242     CheckPutBatchSchemaData(g_kvStore);
243 }
244 
245 /**
246   * @tc.name: PutValueReadOnlyCheck001
247   * @tc.desc: Test writing the data into the no-schema kvStore which has schema originally.
248   * @tc.type: FUNC
249   * @tc.require:
250   * @tc.author: wangbingquan
251   */
252 HWTEST_F(DistributedDBInterfacesNBDelegateSchemaPutTest, PutValueCompaSchemaCheck001, TestSize.Level1)
253 {
254     g_mgr.GetKvStore(g_storeName, g_compOpt, g_kvNbDelegateCallback);
255     ASSERT_TRUE(g_kvStore != nullptr);
256     EXPECT_TRUE(g_kvDelegateStatus == OK);
257     /**
258      * @tc.steps:step1. Put one data whose value has more fields than the schema.
259      * @tc.expected: step1. return OK.
260      */
261     Key key;
262     DistributedDBToolsUnitTest::GetRandomKeyValue(key);
263     std::string moreData = "{\"field_name1\":true,\"field_name2\":10,\"field_name3\":10}";
264     Value value(moreData.begin(), moreData.end());
265     EXPECT_EQ(g_kvStore->Put(key, value), OK);
266 
267 
268     /**
269      * @tc.steps:step2. Put one data whose value has different fields with the schema(less value is not null).
270      * @tc.expected: step2. return CONSTRAIN_VIOLATION.
271      */
272     std::string filedDiffData = "{\"field_name1\":true,\"field_name3\":10}";
273     value.assign(filedDiffData.begin(), filedDiffData.end());
274     EXPECT_EQ(g_kvStore->Put(key, value), CONSTRAIN_VIOLATION);
275 
276     /**
277      * @tc.steps:step2. Put the data whose value is mismatch with the schema.
278      * @tc.expected: step2. return not OK.
279      */
280     CheckPutSchemaData(g_kvStore);
281     CheckPutBatchSchemaData(g_kvStore);
282 }
283 
284 /**
285   * @tc.name: PutValueReadOnlyCheck001
286   * @tc.desc: Test writing the data into the no-schema kvStore which has schema originally.
287   * @tc.type: FUNC
288   * @tc.require:
289   * @tc.author: wangbingquan
290   */
291 HWTEST_F(DistributedDBInterfacesNBDelegateSchemaPutTest, PutValueReadOnlyCheck001, TestSize.Level1)
292 {
293     /**
294      * @tc.steps:step1. Open the kv store with valid schema, and close it.
295      */
296     g_mgr.GetKvStore(g_storeName, g_compOpt, g_kvNbDelegateCallback);
297     ASSERT_TRUE(g_kvStore != nullptr);
298     EXPECT_TRUE(g_kvDelegateStatus == OK);
299     EXPECT_EQ(g_mgr.CloseKvStore(g_kvStore), OK);
300     /**
301      * @tc.steps:step2. Open the kv store with no schema.
302      * @tc.expected: step2. return OK.
303      */
304     DistributedDB::KvStoreNbDelegate::Option option = g_compOpt;
305     option.schema.clear();
306     g_mgr.GetKvStore(g_storeName, option, g_kvNbDelegateCallback);
307     ASSERT_TRUE(g_kvStore != nullptr);
308     EXPECT_TRUE(g_kvDelegateStatus == OK);
309     /**
310      * @tc.steps:step3. Put the data.
311      * @tc.expected: step3. return READ_ONLY.
312      */
313     Key key;
314     DistributedDBToolsUnitTest::GetRandomKeyValue(key);
315     std::string valueData = "{\"field_name1\":true,\"field_name2\":20}";
316     Value value(valueData.begin(), valueData.end());
317     EXPECT_EQ(g_kvStore->Put(key, value), READ_ONLY);
318 }
319 
320 /**
321   * @tc.name: QueryDeleted001
322   * @tc.desc: Test the query in the deleted scene.
323   * @tc.type: FUNC
324   * @tc.require:
325   * @tc.author: wangbingquan
326   */
327 HWTEST_F(DistributedDBInterfacesNBDelegateSchemaPutTest, QueryDeleted001, TestSize.Level1)
328 {
329     g_mgr.GetKvStore(g_storeName, g_strictOpt, g_kvNbDelegateCallback);
330     ASSERT_TRUE(g_kvStore != nullptr);
331     EXPECT_TRUE(g_kvDelegateStatus == OK);
332 
333     /**
334      * @tc.steps:step1. Put 2 schema data.
335      * @tc.expected: step1. return OK.
336      */
337     Key key1;
338     std::string valueData = "{\"field_name1\":true,\"field_name2\":1}";
339     Value value(valueData.begin(), valueData.end());
340     DistributedDBToolsUnitTest::GetRandomKeyValue(key1);
341     EXPECT_EQ(g_kvStore->Put(key1, value), OK);
342 
343     Key key2;
344     valueData = "{\"field_name1\":true,\"field_name2\":2}";
345     value.assign(valueData.begin(), valueData.end());
346     DistributedDBToolsUnitTest::GetRandomKeyValue(key2);
347     EXPECT_EQ(g_kvStore->Put(key2, value), OK);
348 
349     /**
350      * @tc.steps:step2. Get the data through the query condition where the field value is 1.
351      * @tc.expected: step2. GetEntries return OK, and the data num is 1.
352      */
353     std::vector<Entry> entries;
354     KvStoreResultSet *resultSet = nullptr;
355     Query query = Query::Select().EqualTo("$.field_name2", 1);
356     EXPECT_EQ(g_kvStore->GetEntries(query, entries), OK);
357     EXPECT_EQ(g_kvStore->GetEntries(query, resultSet), OK);
358     ASSERT_NE(resultSet, nullptr);
359     EXPECT_EQ(resultSet->GetCount(), 1);
360     int count = 0;
361     EXPECT_EQ(g_kvStore->GetCount(query, count), OK);
362     EXPECT_EQ(count, 1);
363     EXPECT_EQ(g_kvStore->CloseResultSet(resultSet), OK);
364 
365     /**
366      * @tc.steps:step3. Delete the data whose field value is 1.
367      */
368     EXPECT_EQ(g_kvStore->Delete(key1), OK);
369 
370     /**
371      * @tc.steps:step4. Get the data whose field value is 1.
372      * @tc.expected: step4. GetEntries return NOT_FOUND, and the data num is 0.
373      */
374     EXPECT_EQ(g_kvStore->GetEntries(query, entries), NOT_FOUND);
375     EXPECT_EQ(g_kvStore->GetCount(query, count), NOT_FOUND);
376     EXPECT_EQ(g_kvStore->GetEntries(query, resultSet), OK);
377     ASSERT_NE(resultSet, nullptr);
378     EXPECT_EQ(resultSet->GetCount(), 0);
379     EXPECT_EQ(g_kvStore->CloseResultSet(resultSet), OK);
380 }
381 
382 /**
383   * @tc.name: SqliteKeyWord001
384   * @tc.desc: Test kv schema with sqlite key world.
385   * @tc.type: FUNC
386   * @tc.require:
387   * @tc.author: lianhuix
388   */
389 HWTEST_F(DistributedDBInterfacesNBDelegateSchemaPutTest, SqliteKeyWord001, TestSize.Level1)
390 {
391     KvStoreNbDelegate::Option option = {true, false, false};
392     option.schema = VALID_SCHEMA_COMPA_WITH_SQL_KEYWORD_DEFINE;
393     g_mgr.GetKvStore(g_storeName, option, g_kvNbDelegateCallback);
394     ASSERT_TRUE(g_kvStore != nullptr);
395     EXPECT_TRUE(g_kvDelegateStatus == OK);
396 
397     /**
398      * @tc.steps:step1. Put one data whose value has more fields than the schema.
399      * @tc.expected: step1. return INVALID_VALUE_FIELDS.
400      */
401     Key key;
402     DistributedDBToolsUnitTest::GetRandomKeyValue(key);
403     std::string moreData = "{\"create\":true,\"default\":10,\"field_name3\":10}";
404     Value value(moreData.begin(), moreData.end());
405     EXPECT_EQ(g_kvStore->Put(key, value), OK);
406 
407     std::vector<Entry> entries;
408     Query query = Query::Select().EqualTo("create", true);
409     EXPECT_EQ(g_kvStore->GetEntries(query, entries), OK);
410     EXPECT_EQ(entries.size(), 1U);
411 }
412 
413 /**
414   * @tc.name: ResultSetLimitTest001
415   * @tc.desc: Get result set over limit
416   * @tc.type: FUNC
417   * @tc.require:
418   * @tc.author: lianhuix
419   */
420 HWTEST_F(DistributedDBInterfacesNBDelegateSchemaPutTest, ResultSetLimitTest001, TestSize.Level0)
421 {
422     /**
423      * @tc.steps:step1. Create database.
424      * @tc.expected: step1. Returns a non-null kvstore.
425      */
426     g_mgr.GetKvStore(g_storeName, g_strictOpt, g_kvNbDelegateCallback);
427     ASSERT_TRUE(g_kvStore != nullptr);
428     EXPECT_TRUE(g_kvDelegateStatus == OK);
429 
430     /**
431      * @tc.steps:step2. Put the random entry into the database.
432      * @tc.expected: step2. Returns OK.
433      */
434     Key key1;
435     std::string valueData = "{\"field_name1\":true,\"field_name2\":1}";
436     Value value(valueData.begin(), valueData.end());
437     DistributedDBToolsUnitTest::GetRandomKeyValue(key1);
438     EXPECT_EQ(g_kvStore->Put(key1, value), OK);
439 
440     /**
441      * @tc.steps:step3. Get the resultset overlimit.
442      * @tc.expected: step3. In limit returns OK, else return OVER_MAX_LIMITS.
443      */
444     Query query = Query::Select().EqualTo("$.field_name2", 1);
445     std::vector<KvStoreResultSet *> dataResultSet;
446     for (int i = 0; i < 8; i++) { // 8: max result set count
447         KvStoreResultSet *resultSet = nullptr;
448         EXPECT_EQ(g_kvStore->GetEntries(query, resultSet), OK);
449         dataResultSet.push_back(resultSet);
450         EXPECT_NE(resultSet, nullptr);
451     }
452 
453     KvStoreResultSet *resultSet = nullptr;
454     EXPECT_EQ(g_kvStore->GetEntries(query, resultSet), OVER_MAX_LIMITS);
455     EXPECT_EQ(resultSet, nullptr);
456     if (resultSet != nullptr) {
457         EXPECT_EQ(g_kvStore->CloseResultSet(resultSet), OK);
458     }
459 
460     /**
461      * @tc.steps:step4. Close result set.
462      * @tc.expected: step4. Returns OK.
463      */
464     for (auto it : dataResultSet) {
465         EXPECT_EQ(g_kvStore->CloseResultSet(it), OK);
466     }
467 }
468 #endif // OMIT_JSON