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 <gtest/gtest.h>
16
17 #include <functional>
18 #include <string>
19
20 #include "common.h"
21 #include "rdb_errno.h"
22 #include "rdb_helper.h"
23 #include "rdb_open_callback.h"
24 #include "rdb_sql_statistic.h"
25 #include "rdb_store_manager.h"
26 #include "rdb_types.h"
27
28 using namespace testing::ext;
29 using namespace OHOS::NativeRdb;
30 using namespace OHOS::DistributedRdb;
31 using CheckOnChangeFunc = std::function<void(RdbStoreObserver::ChangeInfo &changeInfo)>;
32 using SqlStatisticsFunc = std::function<void(SqlObserver::SqlExecutionInfo &info)>;
33 class SubObserver : public RdbStoreObserver {
34 public:
~SubObserver()35 virtual ~SubObserver()
36 {
37 }
38 void OnChange(const std::vector<std::string> &devices) override;
39 void OnChange(
40 const Origin &origin, const PrimaryFields &fields, RdbStoreObserver::ChangeInfo &&changeInfo) override;
41 void OnChange() override;
42 void RegisterCallback(const CheckOnChangeFunc &callback);
43 uint32_t count = 0;
44
45 private:
46 CheckOnChangeFunc checkOnChangeFunc_;
47 };
48
49 class StatisticsObserver : public SqlObserver {
50 public:
~StatisticsObserver()51 virtual ~StatisticsObserver()
52 {
53 }
54 void OnStatistic(const SqlExecutionInfo &info);
55 void Callback(const SqlStatisticsFunc &callback);
56
57 private:
58 SqlStatisticsFunc sqlStatisticsFunc_;
59 };
60
61 class RdbStoreSubTest : public testing::Test {
62 public:
63 static void SetUpTestCase(void);
64 static void TearDownTestCase(void);
65 void SetUp();
66 void TearDown();
67
68 static const std::string MAIN_DATABASE_NAME;
69 static std::shared_ptr<RdbStore> CreateRDB(int version);
70 static void RegisterCheckInsertCallback(const std::vector<std::shared_ptr<SubObserver>> &SubObservers);
71 static void RegisterCheckUpdateCallback(const std::vector<std::shared_ptr<SubObserver>> &SubObservers);
72 static std::shared_ptr<RdbStore> store;
73 static std::shared_ptr<SubObserver> observer_;
74 static std::shared_ptr<StatisticsObserver> sqlObserver_;
75 };
76
77 class TestDetailProgressObserver : public DetailProgressObserver {
78 public:
~TestDetailProgressObserver()79 virtual ~TestDetailProgressObserver()
80 {
81 }
ProgressNotification(const Details & details)82 void ProgressNotification(const Details &details) override {};
83 };
84
85 const std::string RdbStoreSubTest::MAIN_DATABASE_NAME = RDB_TEST_PATH + "subscribe.db";
86 std::shared_ptr<RdbStore> RdbStoreSubTest::store = nullptr;
87 std::shared_ptr<SubObserver> RdbStoreSubTest::observer_ = nullptr;
88 std::shared_ptr<StatisticsObserver> RdbStoreSubTest::sqlObserver_ = nullptr;
89
SetUpTestCase(void)90 void RdbStoreSubTest::SetUpTestCase(void)
91 {
92 RdbHelper::DeleteRdbStore(MAIN_DATABASE_NAME);
93 store = CreateRDB(1);
94 if (observer_ == nullptr) {
95 observer_ = std::make_shared<SubObserver>();
96 }
97 if (sqlObserver_ == nullptr) {
98 sqlObserver_ = std::make_shared<StatisticsObserver>();
99 }
100 }
101
TearDownTestCase(void)102 void RdbStoreSubTest::TearDownTestCase(void)
103 {
104 store = nullptr;
105 RdbHelper::DeleteRdbStore(MAIN_DATABASE_NAME);
106 }
107
SetUp()108 void RdbStoreSubTest::SetUp()
109 {
110 }
111
TearDown()112 void RdbStoreSubTest::TearDown()
113 {
114 }
115
116 class Callback : public RdbOpenCallback {
117 public:
118 int OnCreate(RdbStore &store) override;
119 int OnUpgrade(RdbStore &store, int oldVersion, int newVersion) override;
120 };
121
OnCreate(RdbStore & store)122 int Callback::OnCreate(RdbStore &store)
123 {
124 return E_OK;
125 }
126
OnUpgrade(RdbStore & store,int oldVersion,int newVersion)127 int Callback::OnUpgrade(RdbStore &store, int oldVersion, int newVersion)
128 {
129 return E_OK;
130 }
131
OnChange(const std::vector<std::string> & devices)132 void SubObserver::OnChange(const std::vector<std::string> &devices)
133 {
134 }
135
OnChange(const Origin & origin,const PrimaryFields & fields,RdbStoreObserver::ChangeInfo && changeInfo)136 void SubObserver::OnChange(const Origin &origin, const PrimaryFields &fields, RdbStoreObserver::ChangeInfo &&changeInfo)
137 {
138 count++;
139 if (checkOnChangeFunc_) {
140 checkOnChangeFunc_(changeInfo);
141 }
142 }
143
OnChange()144 void SubObserver::OnChange()
145 {
146 count++;
147 const std::string CREATE_TABLE_TEST = "CREATE TABLE IF NOT EXISTS test "
148 "(id INTEGER PRIMARY KEY AUTOINCREMENT, "
149 "name TEXT NOT NULL, age INTEGER, salary "
150 "REAL, blobType BLOB)";
151 RdbStoreSubTest::store->ExecuteSql(CREATE_TABLE_TEST);
152 ValuesBucket values;
153 int64_t id;
154 values.PutInt("id", count);
155 values.PutString("name", std::string("zhangsan"));
156 values.PutInt("age", 18);
157 values.PutDouble("salary", 100.5);
158 values.PutBlob("blobType", std::vector<uint8_t>{ 1, 2, 3 });
159 int ret = RdbStoreSubTest::store->Insert(id, "test", values);
160 EXPECT_EQ(ret, E_OK);
161 EXPECT_EQ(count, id);
162 }
163
RegisterCallback(const CheckOnChangeFunc & callback)164 void SubObserver::RegisterCallback(const CheckOnChangeFunc &callback)
165 {
166 checkOnChangeFunc_ = callback;
167 }
168
OnStatistic(const StatisticsObserver::SqlExecutionInfo & info)169 void StatisticsObserver::OnStatistic(const StatisticsObserver::SqlExecutionInfo &info)
170 {
171 }
172
Callback(const SqlStatisticsFunc & callback)173 void StatisticsObserver::Callback(const SqlStatisticsFunc &callback)
174 {
175 sqlStatisticsFunc_ = callback;
176 }
177
CreateRDB(int version)178 std::shared_ptr<RdbStore> RdbStoreSubTest::CreateRDB(int version)
179 {
180 RdbStoreConfig config(RdbStoreSubTest::MAIN_DATABASE_NAME);
181 config.SetBundleName("subscribe_test");
182 config.SetArea(0);
183 config.SetCreateNecessary(true);
184 config.SetDistributedType(RDB_DEVICE_COLLABORATION);
185 config.SetSecurityLevel(OHOS::NativeRdb::SecurityLevel::S1);
186 Callback helper;
187 int errCode = E_OK;
188 std::shared_ptr<RdbStore> store = RdbHelper::GetRdbStore(config, version, helper, errCode);
189 EXPECT_NE(store, nullptr);
190 return store;
191 }
192
RegisterCheckInsertCallback(const std::vector<std::shared_ptr<SubObserver>> & SubObservers)193 void RdbStoreSubTest::RegisterCheckInsertCallback(const std::vector<std::shared_ptr<SubObserver>> &SubObservers)
194 {
195 for (const auto &observer : SubObservers) {
196 observer->RegisterCallback([](RdbStoreObserver::ChangeInfo &changeInfo) {
197 ASSERT_EQ(changeInfo.size(), 1u);
198 EXPECT_TRUE(changeInfo["local_test"][1].empty());
199 EXPECT_TRUE(changeInfo["local_test"][2].empty()); // 2 is delete subscript
200 EXPECT_EQ(std::get<int64_t>(changeInfo["local_test"][0][0]), 1);
201 });
202 }
203 }
204
RegisterCheckUpdateCallback(const std::vector<std::shared_ptr<SubObserver>> & SubObservers)205 void RdbStoreSubTest::RegisterCheckUpdateCallback(const std::vector<std::shared_ptr<SubObserver>> &SubObservers)
206 {
207 for (const auto &observer : SubObservers) {
208 observer->RegisterCallback([](RdbStoreObserver::ChangeInfo &changeInfo) {
209 ASSERT_EQ(changeInfo.size(), 1u);
210 EXPECT_TRUE(changeInfo["local_test"][0].empty());
211 EXPECT_TRUE(changeInfo["local_test"][2].empty()); // 2 is delete subscript
212 EXPECT_EQ(std::get<int64_t>(changeInfo["local_test"][1][0]), 1);
213 });
214 }
215 }
216
217 /**
218 * @tc.name: RdbStoreSubscribeRemote
219 * @tc.desc: RdbStoreSubscribe
220 * @tc.type: FUNC
221 * @tc.require:
222 * @tc.author:
223 */
224 HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeRemote, TestSize.Level1)
225 {
226 EXPECT_NE(store, nullptr) << "store is null";
227 EXPECT_NE(observer_, nullptr) << "observer is null";
228 auto status = store->Subscribe({ SubscribeMode::REMOTE, "observer" }, observer_.get());
229 EXPECT_EQ(status, E_OK);
230 status = store->UnSubscribe({ SubscribeMode::REMOTE, "observer" }, observer_.get());
231 EXPECT_EQ(status, E_OK);
232 }
233
234 /**
235 * @tc.name: RdbStoreSubscribeCloud
236 * @tc.desc: RdbStoreSubscribe
237 * @tc.type: FUNC
238 * @tc.require:
239 * @tc.author:
240 */
241 HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeCloud, TestSize.Level1)
242 {
243 EXPECT_NE(store, nullptr) << "store is null";
244 EXPECT_NE(observer_, nullptr) << "observer is null";
245 auto status = store->Subscribe({ SubscribeMode::CLOUD, "observer" }, observer_.get());
246 EXPECT_EQ(status, E_OK);
247 status = store->UnSubscribe({ SubscribeMode::CLOUD, "observer" }, observer_.get());
248 EXPECT_EQ(status, E_OK);
249 }
250
251 /**
252 * @tc.name: RdbStoreSubscribeCloudDetail
253 * @tc.desc: RdbStoreSubscribe
254 * @tc.type: FUNC
255 * @tc.require:
256 * @tc.author:
257 */
258 HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeCloudDetail, TestSize.Level1)
259 {
260 EXPECT_NE(store, nullptr) << "store is null";
261 EXPECT_NE(observer_, nullptr) << "observer is null";
262 auto status = store->Subscribe({ SubscribeMode::CLOUD_DETAIL, "observer" }, observer_.get());
263 EXPECT_EQ(status, E_OK);
264 status = store->UnSubscribe({ SubscribeMode::CLOUD_DETAIL, "observer" }, observer_.get());
265 EXPECT_EQ(status, E_OK);
266 }
267
268 /**
269 * @tc.name: RdbStoreSubscribeLocal
270 * @tc.desc: RdbStoreSubscribe
271 * @tc.type: FUNC
272 * @tc.require:
273 * @tc.author:
274 */
275 HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeLocal, TestSize.Level1)
276 {
277 EXPECT_NE(store, nullptr) << "store is null";
278 EXPECT_NE(observer_, nullptr) << "observer is null";
279 auto status = store->Subscribe({ SubscribeMode::LOCAL, "observer1" }, observer_.get());
280 store->Subscribe({ SubscribeMode::LOCAL, "observer1" }, observer_.get());
281 EXPECT_EQ(status, E_OK);
282 store->Subscribe({ SubscribeMode::LOCAL, "observer2" }, observer_.get());
283 EXPECT_EQ(status, E_OK);
284
285 status = store->Notify("observer1");
286 EXPECT_EQ(status, E_OK);
287 status = store->Notify("observer2");
288 EXPECT_EQ(status, E_OK);
289 EXPECT_EQ(observer_->count, 2);
290
291 std::shared_ptr<ResultSet> resultSet = store->QuerySql("SELECT * FROM test");
292 int count;
293 resultSet->GetRowCount(count);
294 EXPECT_EQ(observer_->count, count);
295 status = store->UnSubscribe({ SubscribeMode::LOCAL, "nonexistent" }, observer_.get());
296 EXPECT_EQ(status, E_OK);
297 status = store->UnSubscribe({ SubscribeMode::LOCAL, "observer1" }, observer_.get());
298 EXPECT_EQ(status, E_OK);
299 status = store->UnSubscribe({ SubscribeMode::LOCAL, "nonexistent" }, nullptr);
300 EXPECT_EQ(status, E_OK);
301 status = store->UnSubscribe({ SubscribeMode::LOCAL, "observer2" }, nullptr);
302 EXPECT_EQ(status, E_OK);
303 status = store->Notify("observer1");
304 EXPECT_EQ(status, E_OK);
305 }
306
307 /**
308 * @tc.name: RdbStoreSubscribeLocalShared
309 * @tc.desc: RdbStoreSubscribe
310 * @tc.type: FUNC
311 * @tc.require:
312 * @tc.author:
313 */
314 HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeLocalShared, TestSize.Level1)
315 {
316 EXPECT_NE(store, nullptr) << "store is null";
317 EXPECT_NE(observer_, nullptr) << "observer is null";
318 auto status = store->Subscribe({ SubscribeMode::LOCAL_SHARED, "observer1" }, observer_.get());
319 store->Subscribe({ SubscribeMode::LOCAL_SHARED, "observer1" }, observer_.get());
320 EXPECT_EQ(status, E_OK);
321 store->Subscribe({ SubscribeMode::LOCAL_SHARED, "observer2" }, observer_.get());
322 EXPECT_EQ(status, E_OK);
323
324 status = store->UnSubscribe({ SubscribeMode::LOCAL_SHARED, "nonexistent" }, observer_.get());
325 EXPECT_EQ(status, E_OK);
326 status = store->UnSubscribe({ SubscribeMode::LOCAL_SHARED, "observer1" }, observer_.get());
327 EXPECT_EQ(status, E_OK);
328 status = store->UnSubscribe({ SubscribeMode::LOCAL_SHARED, "nonexistent" }, nullptr);
329 EXPECT_EQ(status, E_OK);
330 status = store->UnSubscribe({ SubscribeMode::LOCAL_SHARED, "observer2" }, nullptr);
331 EXPECT_EQ(status, E_OK);
332 }
333
334 /**
335 * @tc.name: RdbStoreSubscribeLocalDetail001
336 * @tc.desc: test local observer onchange when insert data
337 * @tc.type: FUNC
338 * @tc.require:
339 * @tc.author:
340 */
341 HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeLocalDetail001, TestSize.Level1)
342 {
343 EXPECT_NE(store, nullptr) << "store is null";
344 EXPECT_NE(observer_, nullptr) << "observer is null";
345 constexpr const char *createTableTest = "CREATE TABLE IF NOT EXISTS local_test "
346 "(id INTEGER PRIMARY KEY AUTOINCREMENT, "
347 "name TEXT NOT NULL, age INTEGER)";
348 store->ExecuteSql(createTableTest);
349 auto status = store->SubscribeObserver({ SubscribeMode::LOCAL_DETAIL, "dataChange" }, observer_);
350 EXPECT_EQ(status, E_OK);
351 EXPECT_EQ(status, E_OK);
352 auto observer2 = std::make_shared<SubObserver>();
353 status = store->SubscribeObserver({ SubscribeMode::LOCAL_DETAIL, "dataChange" }, observer2);
354
355 RegisterCheckInsertCallback({ observer_, observer2 });
356
357 ValuesBucket values;
358 int64_t id;
359 values.PutInt("id", 1);
360 values.PutString("name", std::string("zhangsan"));
361 values.PutInt("age", 18); // 18 is random age
362 status = store->Insert(id, "local_test", values);
363 EXPECT_EQ(status, E_OK);
364 EXPECT_EQ(id, 1);
365
__anon49a42f570302(RdbStoreObserver::ChangeInfo &) 366 observer_->RegisterCallback([](RdbStoreObserver::ChangeInfo &) { ASSERT_TRUE(false); });
__anon49a42f570402(RdbStoreObserver::ChangeInfo &) 367 observer2->RegisterCallback([](RdbStoreObserver::ChangeInfo &) { ASSERT_TRUE(false); });
368 status = store->UnsubscribeObserver({ SubscribeMode::LOCAL_DETAIL, "dataChange" }, observer_);
369 EXPECT_EQ(status, E_OK);
370 status = store->UnsubscribeObserver({ SubscribeMode::LOCAL_DETAIL, "dataChange" }, observer2);
371 EXPECT_EQ(status, E_OK);
372
373 ValuesBucket values2;
374 int id2;
375 values2.PutString("name", std::string("zhangsan_update1"));
376 values2.PutInt("age", 19); // 19 is random age
377 AbsRdbPredicates predicates("local_test");
378 predicates.EqualTo("id", 1);
379 status = store->Update(id2, values2, predicates);
380 EXPECT_EQ(status, E_OK);
381 EXPECT_EQ(id2, 1);
382 observer_->RegisterCallback(nullptr);
383 observer2->RegisterCallback(nullptr);
384 }
385
386 /**
387 * @tc.name: RdbStoreSubscribeLocalDetail002
388 * @tc.desc: test local observer onchange when update data
389 * @tc.type: FUNC
390 * @tc.require:
391 * @tc.author:
392 */
393 HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeLocalDetail002, TestSize.Level1)
394 {
395 EXPECT_NE(store, nullptr) << "store is null";
396 EXPECT_NE(observer_, nullptr) << "observer is null";
397 auto status = store->SubscribeObserver({ SubscribeMode::LOCAL_DETAIL, "dataChange" }, observer_);
398 EXPECT_EQ(status, E_OK);
399 EXPECT_EQ(status, E_OK);
400 auto observer2 = std::make_shared<SubObserver>();
401 status = store->SubscribeObserver({ SubscribeMode::LOCAL_DETAIL, "dataChange" }, observer2);
402
403 RegisterCheckUpdateCallback({ observer_, observer2 });
404
405 int id;
406 ValuesBucket values;
407 values.PutString("name", std::string("zhangsan_update2"));
408 values.PutInt("age", 20); // 20 is random age
409 AbsRdbPredicates predicates("local_test");
410 predicates.EqualTo("id", 1);
411 status = store->Update(id, values, predicates);
412 EXPECT_EQ(status, E_OK);
413 EXPECT_EQ(id, 1);
414
__anon49a42f570502(RdbStoreObserver::ChangeInfo &) 415 observer_->RegisterCallback([](RdbStoreObserver::ChangeInfo &) { ASSERT_TRUE(false); });
416 status = store->UnsubscribeObserver({ SubscribeMode::LOCAL_DETAIL, "dataChange" }, observer_);
417 EXPECT_EQ(status, E_OK);
418
419 ValuesBucket values2;
420 int id2;
421 values2.PutString("name", std::string("zhangsan_update1"));
422 values2.PutInt("age", 19); // 19 is random age
423 AbsRdbPredicates predicates2("local_test");
424 predicates2.EqualTo("id", 1);
425 status = store->Update(id2, values2, predicates2);
426 EXPECT_EQ(status, E_OK);
427 EXPECT_EQ(id2, 1);
428 observer_->RegisterCallback(nullptr);
429 observer2->RegisterCallback(nullptr);
430 status = store->UnsubscribeObserver({ SubscribeMode::LOCAL_DETAIL, "dataChange" }, observer2);
431 EXPECT_EQ(status, E_OK);
432 }
433
434 /**
435 * @tc.name: RdbStoreSubscribeLocalDetail003
436 * @tc.desc: test local observer onchange when delete data
437 * @tc.type: FUNC
438 * @tc.require:
439 * @tc.author:
440 */
441 HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeLocalDetail003, TestSize.Level1)
442 {
443 EXPECT_NE(store, nullptr) << "store is null";
444 EXPECT_NE(observer_, nullptr) << "observer is null";
445 auto status = store->SubscribeObserver({ SubscribeMode::LOCAL_DETAIL, "dataChange" }, observer_);
446 EXPECT_EQ(status, E_OK);
447
__anon49a42f570602(RdbStoreObserver::ChangeInfo &changeInfo) 448 observer_->RegisterCallback([](RdbStoreObserver::ChangeInfo &changeInfo) {
449 ASSERT_EQ(changeInfo.size(), 1u);
450 EXPECT_TRUE(changeInfo["local_test"][0].empty());
451 EXPECT_TRUE(changeInfo["local_test"][1].empty());
452 EXPECT_EQ(std::get<int64_t>(changeInfo["local_test"][2][0]), 1);
453 });
454
455 observer_->count = 0;
456 int id;
457 status = store->Delete(id, "local_test", "id = ?", std::vector<std::string>{ "1" });
458 EXPECT_EQ(status, E_OK);
459 EXPECT_EQ(id, 1);
460 EXPECT_EQ(observer_->count, 1);
461
462 status = store->UnsubscribeObserver({ SubscribeMode::LOCAL_DETAIL, "dataChange" }, observer_);
463 EXPECT_EQ(status, E_OK);
464 observer_->RegisterCallback(nullptr);
465 }
466
467 /**
468 * @tc.name: RdbStoreSubscribeLocalDetail004
469 * @tc.desc: test local observer onchange when batchinsert data
470 * @tc.type: FUNC
471 * @tc.require:
472 * @tc.author:
473 */
474 HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeLocalDetail004, TestSize.Level1)
475 {
476 int num = 10;
477 EXPECT_NE(store, nullptr) << "store is null";
478 EXPECT_NE(observer_, nullptr) << "observer is null";
479 auto status = store->SubscribeObserver({ SubscribeMode::LOCAL_DETAIL, "dataChange" }, observer_);
480 EXPECT_EQ(status, E_OK);
481
__anon49a42f570702(RdbStoreObserver::ChangeInfo &changeInfo) 482 observer_->RegisterCallback([num](RdbStoreObserver::ChangeInfo &changeInfo) {
483 ASSERT_EQ(changeInfo.size(), 1u);
484 EXPECT_TRUE(changeInfo["local_test"][1].empty());
485 EXPECT_TRUE(changeInfo["local_test"][2].empty()); // 2 is delete subscript
486 for (int i = 0; i < num; i++) {
487 EXPECT_EQ(std::get<int64_t>(changeInfo["local_test"][0][i]), i);
488 }
489 });
490
491 observer_->count = 0;
492 int64_t id;
493 std::vector<ValuesBucket> values;
494 for (int i = 0; i < num; i++) {
495 ValuesBucket value;
496 value.PutInt("id", i);
497 value.PutString("name", std::string("zhangsan"));
498 value.PutInt("age", 18); // 18 is random age
499 values.push_back(value);
500 }
501 status = store->BatchInsert(id, "local_test", values);
502 EXPECT_EQ(status, E_OK);
503 EXPECT_EQ(id, num);
504 EXPECT_EQ(observer_->count, 1);
505 status = store->UnsubscribeObserver({ SubscribeMode::LOCAL_DETAIL, "dataChange" }, observer_);
506 EXPECT_EQ(status, E_OK);
507 observer_->RegisterCallback(nullptr);
508 }
509
510 /**
511 * @tc.name: RdbStoreSubscribeLocalDetail005
512 * @tc.desc: test local observer onchange when create table after register observer
513 * @tc.type: FUNC
514 * @tc.require:
515 * @tc.author:
516 */
517 HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeLocalDetail005, TestSize.Level1)
518 {
519 int num = 1;
520 EXPECT_NE(store, nullptr) << "store is null";
521 EXPECT_NE(observer_, nullptr) << "observer is null";
522 auto status = store->SubscribeObserver({ SubscribeMode::LOCAL_DETAIL, "dataChange" }, observer_);
523 EXPECT_EQ(status, E_OK);
524 constexpr const char *createTableTest = "CREATE TABLE IF NOT EXISTS local_test1 "
525 "(id INTEGER PRIMARY KEY AUTOINCREMENT, "
526 "name TEXT NOT NULL, age INTEGER)";
527 store->ExecuteSql(createTableTest);
528
__anon49a42f570802(RdbStoreObserver::ChangeInfo &changeInfo) 529 observer_->RegisterCallback([num](RdbStoreObserver::ChangeInfo &changeInfo) {
530 ASSERT_EQ(changeInfo.size(), 1u);
531 EXPECT_TRUE(changeInfo["local_test1"][1].empty());
532 EXPECT_TRUE(changeInfo["local_test1"][2].empty()); // 2 is delete subscript
533 for (int i = 0; i < num; i++) {
534 EXPECT_EQ(std::get<int64_t>(changeInfo["local_test1"][0][i]), i);
535 }
536 });
537 observer_->count = 0;
538
539 int64_t id;
540 std::vector<ValuesBucket> values;
541 for (int i = 0; i < num; i++) {
542 ValuesBucket value;
543 value.PutInt("id", i);
544 value.PutString("name", std::string("zhangsan"));
545 value.PutInt("age", 18); // 18 is random age
546 values.push_back(value);
547 }
548 status = store->BatchInsert(id, "local_test1", values);
549 EXPECT_EQ(status, E_OK);
550 EXPECT_EQ(id, num);
551 EXPECT_EQ(observer_->count, 1);
552 status = store->UnsubscribeObserver({ SubscribeMode::LOCAL_DETAIL, "dataChange" }, observer_);
553 EXPECT_EQ(status, E_OK);
554 status = store->SubscribeObserver({ SubscribeMode::LOCAL_DETAIL, "dataChange" }, observer_);
555 EXPECT_EQ(status, E_OK);
556 status = store->UnsubscribeObserver({ SubscribeMode::LOCAL_DETAIL, "dataChange" }, nullptr);
557 EXPECT_EQ(status, E_OK);
558 observer_->RegisterCallback(nullptr);
559 }
560
561 /**
562 * @tc.name: RdbStoreSubscribeLocalDetail006
563 * @tc.desc: test abnormal parametar subscribe
564 * @tc.type: FUNC
565 * @tc.require:
566 * @tc.author:
567 */
568 HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeLocalDetail006, TestSize.Level1)
569 {
570 int num = 20;
571 EXPECT_NE(store, nullptr) << "store is null";
572 EXPECT_NE(observer_, nullptr) << "observer is null";
573 constexpr const char *createTableTest = "CREATE TABLE IF NOT EXISTS local_test2"
574 "(id INTEGER PRIMARY KEY AUTOINCREMENT, "
575 "name TEXT NOT NULL, age INTEGER)";
576 store->ExecuteSql(createTableTest);
577 auto status = store->SubscribeObserver({ SubscribeMode::LOCAL_DETAIL, "dataChange" }, observer_);
578 EXPECT_EQ(status, E_OK);
579
__anon49a42f570902(RdbStoreObserver::ChangeInfo &changeInfo) 580 observer_->RegisterCallback([num](RdbStoreObserver::ChangeInfo &changeInfo) {
581 ASSERT_EQ(changeInfo.size(), 1u);
582 EXPECT_TRUE(changeInfo["local_test2"][1].empty());
583 EXPECT_TRUE(changeInfo["local_test2"][2].empty()); // 2 is delete subscript
584 for (int i = 0; i < num; i++) {
585 EXPECT_EQ(std::get<int64_t>(changeInfo["local_test2"][0][i]), i);
586 }
587 });
588
589 observer_->count = 0;
590 std::vector<ValuesBucket> values;
591 for (int i = 0; i < num; i++) {
592 ValuesBucket value;
593 value.PutInt("id", i);
594 value.PutString("name", std::string("lisi"));
595 value.PutInt("age", 16);
596 values.push_back(value);
597 }
598 std::shared_ptr<Transaction> trans = nullptr;
599 std::tie(status, trans) = store->CreateTransaction(Transaction::DEFERRED);
600 EXPECT_EQ(status, E_OK);
601 int64_t insertRows = 0;
602 std::tie(status, insertRows) = trans->BatchInsert("local_test2", values);
603 EXPECT_EQ(status, E_OK);
604 EXPECT_EQ(insertRows, num);
605 EXPECT_EQ(observer_->count, 0);
606 trans->Commit();
607 trans = nullptr;
608 EXPECT_EQ(observer_->count, 1);
609 status = store->UnsubscribeObserver({ SubscribeMode::LOCAL_DETAIL, "dataChange" }, observer_);
610 EXPECT_EQ(status, E_OK);
611 observer_->RegisterCallback(nullptr);
612 }
613
614 /**
615 * @tc.name: RdbStoreSubscribeLocalDetail007
616 * @tc.desc: test abnormal parametar subscribe
617 * @tc.type: FUNC
618 * @tc.require:
619 * @tc.author:
620 */
621 HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeLocalDetail007, TestSize.Level1)
622 {
623 int num = 20;
624 EXPECT_NE(store, nullptr) << "store is null";
625 EXPECT_NE(observer_, nullptr) << "observer is null";
626 constexpr const char *createTableTest = "CREATE TABLE IF NOT EXISTS local_test3"
627 "(id INTEGER PRIMARY KEY AUTOINCREMENT, "
628 "name TEXT NOT NULL, age INTEGER)";
629 store->ExecuteSql(createTableTest);
630 std::shared_ptr<Transaction> trans1 = nullptr;
631 int status = 0;
632 std::tie(status, trans1) = store->CreateTransaction(Transaction::DEFERRED);
633 EXPECT_EQ(status, E_OK);
634 status = store->SubscribeObserver({ SubscribeMode::LOCAL_DETAIL, "dataChange" }, observer_);
635 EXPECT_EQ(status, E_OK);
636 trans1 = nullptr;
__anon49a42f570a02(RdbStoreObserver::ChangeInfo &changeInfo) 637 observer_->RegisterCallback([num](RdbStoreObserver::ChangeInfo &changeInfo) {
638 ASSERT_EQ(changeInfo.size(), 1u);
639 EXPECT_TRUE(changeInfo["local_test3"][1].empty());
640 EXPECT_TRUE(changeInfo["local_test3"][2].empty()); // 2 is delete subscript
641 for (int i = 0; i < num; i++) {
642 EXPECT_EQ(std::get<int64_t>(changeInfo["local_test3"][0][i]), i);
643 }
644 });
645
646 observer_->count = 0;
647 std::vector<ValuesBucket> values;
648 for (int i = 0; i < num; i++) {
649 ValuesBucket value;
650 value.PutInt("id", i);
651 value.PutString("name", std::string("lisi"));
652 value.PutInt("age", 16);
653 values.push_back(value);
654 }
655 std::shared_ptr<Transaction> trans2 = nullptr;
656 std::tie(status, trans2) = store->CreateTransaction(Transaction::DEFERRED);
657 EXPECT_EQ(status, E_OK);
658 int64_t insertRows = 0;
659 std::tie(status, insertRows) = trans2->BatchInsert("local_test3", values);
660 EXPECT_EQ(status, E_OK);
661 EXPECT_EQ(insertRows, num);
662 EXPECT_EQ(observer_->count, 0);
663 trans2->Commit();
664 trans2 = nullptr;
665 EXPECT_EQ(observer_->count, 1);
666 status = store->UnsubscribeObserver({ SubscribeMode::LOCAL_DETAIL, "dataChange" }, observer_);
667 EXPECT_EQ(status, E_OK);
668 observer_->RegisterCallback(nullptr);
669 }
670
671 /**
672 * @tc.name: RdbStoreSubscribeLocalDetail008
673 * @tc.desc: test abnormal parametar subscribe
674 * @tc.type: FUNC
675 * @tc.require:
676 * @tc.author:
677 */
678 HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeLocalDetail008, TestSize.Level1)
679 {
680 int num = 20;
681 EXPECT_NE(store, nullptr) << "store is null";
682 EXPECT_NE(observer_, nullptr) << "observer is null";
683 constexpr const char *createTableTest = "CREATE TABLE IF NOT EXISTS local_test4"
684 "(id INTEGER PRIMARY KEY AUTOINCREMENT, "
685 "name TEXT NOT NULL, age INTEGER)";
686 store->ExecuteSql(createTableTest);
687 auto status = store->SubscribeObserver({ SubscribeMode::LOCAL_DETAIL, "dataChange" }, observer_);
688 EXPECT_EQ(status, E_OK);
689
__anon49a42f570b02(RdbStoreObserver::ChangeInfo &) 690 observer_->RegisterCallback([](RdbStoreObserver::ChangeInfo &) { ASSERT_TRUE(false); });
691
692 observer_->count = 0;
693 std::vector<ValuesBucket> values;
694 for (int i = 0; i < num; i++) {
695 ValuesBucket value;
696 value.PutInt("id", i);
697 value.PutString("name", std::string("lisi"));
698 value.PutInt("age", 16);
699 values.push_back(value);
700 }
701 std::shared_ptr<Transaction> trans = nullptr;
702 std::tie(status, trans) = store->CreateTransaction(Transaction::DEFERRED);
703 EXPECT_EQ(status, E_OK);
704 int64_t insertRows = 0;
705 std::tie(status, insertRows) = trans->BatchInsert("local_test4", values);
706 EXPECT_EQ(status, E_OK);
707 EXPECT_EQ(insertRows, num);
708 EXPECT_EQ(observer_->count, 0);
709 status = store->UnsubscribeObserver({ SubscribeMode::LOCAL_DETAIL, "dataChange" }, observer_);
710 EXPECT_EQ(status, E_OK);
711 trans->Commit();
712 trans = nullptr;
713 EXPECT_EQ(observer_->count, 0);
714 observer_->RegisterCallback(nullptr);
715 }
716
717 /**
718 * @tc.name: RdbStoreSubscribeLocalDetail009
719 * @tc.desc: test abnormal parametar subscribe
720 * @tc.type: FUNC
721 * @tc.require:
722 * @tc.author:
723 */
724 HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeLocalDetail009, TestSize.Level1)
725 {
726 EXPECT_NE(store, nullptr) << "store is null";
727 EXPECT_NE(observer_, nullptr) << "observer is null";
728 auto status = store->SubscribeObserver({ SubscribeMode::LOCAL_DETAIL, "dataChange" }, nullptr);
729 EXPECT_EQ(status, E_OK);
__anon49a42f570c02(RdbStoreObserver::ChangeInfo &) 730 observer_->RegisterCallback([](RdbStoreObserver::ChangeInfo &) { ASSERT_TRUE(false); });
731 ValuesBucket values;
732 int id;
733 values.PutString("name", std::string("zhangsan_update1"));
734 values.PutInt("age", 19); // 19 is random age
735 AbsRdbPredicates predicates("local_test");
736 predicates.EqualTo("id", 1);
737 status = store->Update(id, values, predicates);
738 EXPECT_EQ(status, E_OK);
739 EXPECT_EQ(id, 1); // 2 is random id
740 observer_->RegisterCallback(nullptr);
741 }
742
743 /**
744 * @tc.name: RdbStoreSubscribeStatistics001
745 * @tc.desc: test statistics observer when insert data
746 * @tc.type: FUNC
747 * @tc.require:
748 * @tc.author:
749 */
750 HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeStatistics001, TestSize.Level1)
751 {
752 EXPECT_NE(store, nullptr) << "store is null";
753 EXPECT_NE(sqlObserver_, nullptr) << "observer is null";
754 constexpr const char *createTableTest = "CREATE TABLE IF NOT EXISTS statistics_test "
755 "(id INTEGER PRIMARY KEY AUTOINCREMENT, "
756 "name TEXT NOT NULL, age INTEGER)";
757 store->ExecuteSql(createTableTest);
758 auto status = SqlStatistic::Subscribe(sqlObserver_);
759 EXPECT_EQ(status, E_OK);
760 auto observer2 = std::make_shared<StatisticsObserver>();
761 status = SqlStatistic::Subscribe(sqlObserver_);
762 ValuesBucket values;
763 int64_t id;
764 values.PutInt("id", 1);
765 values.PutString("name", std::string("zhangsan"));
766 values.PutInt("age", 18); // 18 is random age
767 status = store->Insert(id, "statistics_test", values);
768 EXPECT_EQ(status, E_OK);
769 EXPECT_EQ(id, 1);
__anon49a42f570d02(SqlObserver::SqlExecutionInfo &info) 770 sqlObserver_->Callback([](SqlObserver::SqlExecutionInfo &info) { ASSERT_EQ(info.sql_.size(), 1); });
__anon49a42f570e02(SqlObserver::SqlExecutionInfo &info) 771 observer2->Callback([](SqlObserver::SqlExecutionInfo &info) { ASSERT_EQ(info.sql_.size(), 1); });
772 status = SqlStatistic::Unsubscribe(sqlObserver_);
773 EXPECT_EQ(status, E_OK);
774 status = SqlStatistic::Unsubscribe(observer2);
775 EXPECT_EQ(status, E_OK);
776 }
777
778 /**
779 * @tc.name: RdbStoreSubscribeStatistics002
780 * @tc.desc: test statistics observer when update data
781 * @tc.type: FUNC
782 * @tc.require:
783 * @tc.author:
784 */
785 HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeStatistics002, TestSize.Level1)
786 {
787 EXPECT_NE(store, nullptr) << "store is null";
788 EXPECT_NE(sqlObserver_, nullptr) << "observer is null";
789 auto status = SqlStatistic::Subscribe(sqlObserver_);
790 EXPECT_EQ(status, E_OK);
791 int id;
792 ValuesBucket values;
793 values.PutString("name", std::string("zhangsan_update2"));
794 values.PutInt("age", 20); // 20 is random age
795 AbsRdbPredicates predicates("statistics_test");
796 predicates.EqualTo("id", 1);
797 status = store->Update(id, values, predicates);
798 EXPECT_EQ(status, E_OK);
799 EXPECT_EQ(id, 1);
__anon49a42f570f02(SqlObserver::SqlExecutionInfo &info) 800 sqlObserver_->Callback([](SqlObserver::SqlExecutionInfo &info) { ASSERT_EQ(info.sql_.size(), 1); });
801 status = SqlStatistic::Unsubscribe(sqlObserver_);
802 EXPECT_EQ(status, E_OK);
803 }
804
805 /**
806 * @tc.name: RdbStoreSubscribeStatistics003
807 * @tc.desc: test statistics observer when delete data
808 * @tc.type: FUNC
809 * @tc.require:
810 * @tc.author:
811 */
812 HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeStatistics003, TestSize.Level1)
813 {
814 EXPECT_NE(store, nullptr) << "store is null";
815 EXPECT_NE(sqlObserver_, nullptr) << "observer is null";
816 auto status = SqlStatistic::Subscribe(sqlObserver_);
817 EXPECT_EQ(status, E_OK);
__anon49a42f571002(SqlObserver::SqlExecutionInfo &info) 818 sqlObserver_->Callback([](SqlObserver::SqlExecutionInfo &info) { ASSERT_EQ(info.sql_.size(), 1); });
819 int id;
820 status = store->Delete(id, "statistics_test", "id = ?", std::vector<std::string>{ "1" });
821 EXPECT_EQ(status, E_OK);
822 EXPECT_EQ(id, 1);
823
824 status = SqlStatistic::Unsubscribe(sqlObserver_);
825 EXPECT_EQ(status, E_OK);
826 sqlObserver_->Callback(nullptr);
827 }
828
829 /**
830 * @tc.name: RdbStoreSubscribeStatistics001
831 * @tc.desc: test statistics observer when batchinsert data
832 * @tc.type: FUNC
833 * @tc.require:
834 * @tc.author:
835 */
836 HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeStatistics004, TestSize.Level1)
837 {
838 int num = 10;
839 EXPECT_NE(store, nullptr) << "store is null";
840 EXPECT_NE(sqlObserver_, nullptr) << "observer is null";
841 auto status = SqlStatistic::Subscribe(sqlObserver_);
842 EXPECT_EQ(status, E_OK);
__anon49a42f571102(SqlObserver::SqlExecutionInfo &info) 843 sqlObserver_->Callback([](SqlObserver::SqlExecutionInfo &info) { ASSERT_EQ(info.sql_.size(), 1); });
844 int64_t id;
845 std::vector<ValuesBucket> values;
846 for (int i = 0; i < num; i++) {
847 ValuesBucket value;
848 value.PutInt("id", i);
849 value.PutString("name", std::string("zhangsan"));
850 value.PutInt("age", 18); // 18 is random age
851 values.push_back(value);
852 }
853 status = store->BatchInsert(id, "statistics_test", values);
854 EXPECT_EQ(status, E_OK);
855 EXPECT_EQ(id, num);
856 status = SqlStatistic::Unsubscribe(sqlObserver_);
857 EXPECT_EQ(status, E_OK);
858 }
859
860 /**
861 * @tc.name: RdbStoreSubscribeStatistics001
862 * @tc.desc: test statistics observer when create table after register observer
863 * @tc.type: FUNC
864 * @tc.require:
865 * @tc.author:
866 */
867 HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeStatistics005, TestSize.Level1)
868 {
869 EXPECT_NE(store, nullptr) << "store is null";
870 EXPECT_NE(sqlObserver_, nullptr) << "observer is null";
871 auto status = SqlStatistic::Subscribe(sqlObserver_);
872 EXPECT_EQ(status, E_OK);
873 constexpr const char *createTableTest = "CREATE TABLE IF NOT EXISTS statistics_test1 "
874 "(id INTEGER PRIMARY KEY AUTOINCREMENT, "
875 "name TEXT NOT NULL, age INTEGER)";
876 store->ExecuteSql(createTableTest);
877
__anon49a42f571202(SqlObserver::SqlExecutionInfo &info) 878 sqlObserver_->Callback([](SqlObserver::SqlExecutionInfo &info) { ASSERT_EQ(info.sql_.size(), 3); });
879 ValuesBucket values;
880 int64_t id;
881 values.PutInt("id", 1);
882 values.PutString("name", std::string("zhangsan"));
883 values.PutInt("age", 18); // 18 is random age
884 status = store->Insert(id, "statistics_test1", values);
885 EXPECT_EQ(status, E_OK);
886 EXPECT_EQ(id, 1);
887 status = SqlStatistic::Unsubscribe(sqlObserver_);
888 EXPECT_EQ(status, E_OK);
889 }
890
891 /**
892 * @tc.name: RdbStoreSubscribeStatistics006
893 * @tc.desc: test statistics observer when query data
894 * @tc.type: FUNC
895 * @tc.require:
896 * @tc.author:
897 */
898 HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeStatistics006, TestSize.Level1)
899 {
900 EXPECT_NE(store, nullptr) << "store is null";
901 EXPECT_NE(sqlObserver_, nullptr) << "observer is null";
902 auto status = SqlStatistic::Subscribe(sqlObserver_);
903 EXPECT_EQ(status, E_OK);
__anon49a42f571302(SqlObserver::SqlExecutionInfo &info) 904 sqlObserver_->Callback([](SqlObserver::SqlExecutionInfo &info) { ASSERT_EQ(info.sql_.size(), 2); });
905 std::shared_ptr<ResultSet> resultSet = store->QueryByStep("SELECT * FROM statistics_test");
906 EXPECT_NE(resultSet, nullptr);
907 status = SqlStatistic::Unsubscribe(sqlObserver_);
908 EXPECT_EQ(status, E_OK);
909 }
910
911 /**
912 * @tc.name: RdbStoreSubscribeStatistics007
913 * @tc.desc: test statistics observer when query data
914 * @tc.type: FUNC
915 * @tc.require:
916 * @tc.author:
917 */
918 HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeStatistics007, TestSize.Level1)
919 {
920 EXPECT_NE(store, nullptr) << "store is null";
921 EXPECT_NE(sqlObserver_, nullptr) << "observer is null";
922 auto status = SqlStatistic::Subscribe(sqlObserver_);
923 EXPECT_EQ(status, E_OK);
__anon49a42f571402(SqlObserver::SqlExecutionInfo &info) 924 sqlObserver_->Callback([](SqlObserver::SqlExecutionInfo &info) { ASSERT_EQ(info.sql_.size(), 2); });
925 std::shared_ptr<ResultSet> resultSet = store->QuerySql("SELECT * FROM statistics_test");
926 EXPECT_NE(resultSet, nullptr);
927 status = SqlStatistic::Unsubscribe(sqlObserver_);
928 EXPECT_EQ(status, E_OK);
929 }
930
931 /**
932 * @tc.name: RdbStoreSubscribeStatistics008
933 * @tc.desc: test statistics observer when Execute pragma
934 * @tc.type: FUNC
935 * @tc.require:
936 * @tc.author:
937 */
938 HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeStatistics008, TestSize.Level1)
939 {
940 EXPECT_NE(store, nullptr) << "store is null";
941 EXPECT_NE(sqlObserver_, nullptr) << "observer is null";
942 auto status = SqlStatistic::Subscribe(sqlObserver_);
943 EXPECT_EQ(status, E_OK);
__anon49a42f571502(SqlObserver::SqlExecutionInfo &info) 944 sqlObserver_->Callback([](SqlObserver::SqlExecutionInfo &info) { ASSERT_EQ(info.sql_[0], "PRAGMA quick_check"); });
945 auto [ret, object] = store->Execute("PRAGMA quick_check");
946 status = SqlStatistic::Unsubscribe(sqlObserver_);
947 EXPECT_EQ(status, E_OK);
948 }
949
950 /**
951 * @tc.name: RdbStoreSubscribeStatistics009
952 * @tc.desc: test statistics observer when ExecuteSql
953 * @tc.type: FUNC
954 * @tc.require:
955 * @tc.author:
956 */
957 HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeStatistics009, TestSize.Level1)
958 {
959 EXPECT_NE(store, nullptr) << "store is null";
960 EXPECT_NE(sqlObserver_, nullptr) << "observer is null";
961 std::string value = "with test as (select * from statistics_test) select * from test1";
962 auto status = SqlStatistic::Subscribe(sqlObserver_);
963 EXPECT_EQ(status, E_OK);
__anon49a42f571602(SqlObserver::SqlExecutionInfo &info) 964 sqlObserver_->Callback([value](SqlObserver::SqlExecutionInfo &info) { ASSERT_EQ(info.sql_[0], value); });
965 store->ExecuteSql(value);
966 status = SqlStatistic::Unsubscribe(sqlObserver_);
967 EXPECT_EQ(status, E_OK);
968 }
969
970 /**
971 * @tc.name: RdbStoreSubscribeStatistics010
972 * @tc.desc: test abnormal parametar subscribe
973 * @tc.type: FUNC
974 * @tc.require:
975 * @tc.author:
976 */
977 HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeStatistics010, TestSize.Level1)
978 {
979 EXPECT_NE(store, nullptr) << "store is null";
980 EXPECT_NE(sqlObserver_, nullptr) << "observer is null";
981 auto status = SqlStatistic::Subscribe(nullptr);
982 EXPECT_EQ(status, E_OK);
983 }
984
985 /**
986 * @tc.name: RdbStore_RegisterAutoSyncCallbackAndRdbStore_UnregisterAutoSyncCallback_001
987 * @tc.desc: Test RegisterAutoSyncCallback and UnregisterAutoSyncCallback
988 * @tc.type: FUNC
989 */
990 HWTEST_F(RdbStoreSubTest, RdbStore_RegisterAutoSyncCallbackAndRdbStore_UnregisterAutoSyncCallback_001, TestSize.Level1)
991 {
992 EXPECT_NE(store, nullptr) << "store is null";
993 auto obs = std::make_shared<TestDetailProgressObserver>();
994 auto status = store->RegisterAutoSyncCallback(obs);
995 EXPECT_EQ(status, E_OK);
996
997 status = store->UnregisterAutoSyncCallback(obs);
998 EXPECT_EQ(status, E_OK);
999 }
1000