OLD | NEW |
| (Empty) |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "sync/internal_api/public/model_type_store_backend.h" | |
6 | |
7 #include "testing/gtest/include/gtest/gtest.h" | |
8 #include "third_party/leveldatabase/src/include/leveldb/env.h" | |
9 #include "third_party/leveldatabase/src/include/leveldb/write_batch.h" | |
10 | |
11 namespace syncer_v2 { | |
12 | |
13 class ModelTypeStoreBackendTest : public testing::Test { | |
14 public: | |
15 scoped_refptr<ModelTypeStoreBackend> GetOrCreateBackend() { | |
16 std::string path = "/test_db"; | |
17 return GetOrCreateBackendWithPath(path); | |
18 } | |
19 | |
20 scoped_refptr<ModelTypeStoreBackend> GetOrCreateBackendWithPath( | |
21 std::string custom_path) { | |
22 std::unique_ptr<leveldb::Env> in_memory_env = | |
23 ModelTypeStoreBackend::CreateInMemoryEnv(); | |
24 std::string path; | |
25 in_memory_env->GetTestDirectory(&path); | |
26 path += custom_path; | |
27 | |
28 ModelTypeStore::Result result; | |
29 // In-memory store backend works on the same thread as test. | |
30 scoped_refptr<ModelTypeStoreBackend> backend = | |
31 ModelTypeStoreBackend::GetOrCreateBackend( | |
32 path, std::move(in_memory_env), &result); | |
33 EXPECT_TRUE(backend.get()); | |
34 EXPECT_EQ(result, ModelTypeStore::Result::SUCCESS); | |
35 return backend; | |
36 } | |
37 | |
38 bool BackendExistsForPath(std::string path) { | |
39 if (ModelTypeStoreBackend::backend_map_.Get().end() == | |
40 ModelTypeStoreBackend::backend_map_.Get().find(path)) { | |
41 return false; | |
42 } | |
43 return true; | |
44 } | |
45 | |
46 std::string GetBackendPath(scoped_refptr<ModelTypeStoreBackend> backend) { | |
47 return backend->path_; | |
48 } | |
49 }; | |
50 | |
51 // Test that after record is written to backend it can be read back even after | |
52 // backend is destroyed and recreated in the same environment. | |
53 TEST_F(ModelTypeStoreBackendTest, WriteThenRead) { | |
54 scoped_refptr<ModelTypeStoreBackend> backend = GetOrCreateBackend(); | |
55 | |
56 // Write record. | |
57 std::unique_ptr<leveldb::WriteBatch> write_batch(new leveldb::WriteBatch()); | |
58 write_batch->Put("prefix:id1", "data1"); | |
59 ModelTypeStore::Result result = | |
60 backend->WriteModifications(std::move(write_batch)); | |
61 ASSERT_EQ(ModelTypeStore::Result::SUCCESS, result); | |
62 | |
63 // Read all records with prefix. | |
64 ModelTypeStore::RecordList record_list; | |
65 result = backend->ReadAllRecordsWithPrefix("prefix:", &record_list); | |
66 ASSERT_EQ(ModelTypeStore::Result::SUCCESS, result); | |
67 ASSERT_EQ(1ul, record_list.size()); | |
68 ASSERT_EQ("id1", record_list[0].id); | |
69 ASSERT_EQ("data1", record_list[0].value); | |
70 record_list.clear(); | |
71 | |
72 // Recreate backend and read all records with prefix. | |
73 backend = GetOrCreateBackend(); | |
74 result = backend->ReadAllRecordsWithPrefix("prefix:", &record_list); | |
75 ASSERT_EQ(ModelTypeStore::Result::SUCCESS, result); | |
76 ASSERT_EQ(1ul, record_list.size()); | |
77 ASSERT_EQ("id1", record_list[0].id); | |
78 ASSERT_EQ("data1", record_list[0].value); | |
79 } | |
80 | |
81 // Test that ReadAllRecordsWithPrefix correclty filters records by prefix. | |
82 TEST_F(ModelTypeStoreBackendTest, ReadAllRecordsWithPrefix) { | |
83 scoped_refptr<ModelTypeStoreBackend> backend = GetOrCreateBackend(); | |
84 | |
85 std::unique_ptr<leveldb::WriteBatch> write_batch(new leveldb::WriteBatch()); | |
86 write_batch->Put("prefix1:id1", "data1"); | |
87 write_batch->Put("prefix2:id2", "data2"); | |
88 ModelTypeStore::Result result = | |
89 backend->WriteModifications(std::move(write_batch)); | |
90 ASSERT_EQ(ModelTypeStore::Result::SUCCESS, result); | |
91 | |
92 ModelTypeStore::RecordList record_list; | |
93 result = backend->ReadAllRecordsWithPrefix("prefix1:", &record_list); | |
94 ASSERT_EQ(ModelTypeStore::Result::SUCCESS, result); | |
95 ASSERT_EQ(1UL, record_list.size()); | |
96 ASSERT_EQ("id1", record_list[0].id); | |
97 ASSERT_EQ("data1", record_list[0].value); | |
98 } | |
99 | |
100 // Test that deleted records are correctly marked as milling in results of | |
101 // ReadRecordsWithPrefix. | |
102 TEST_F(ModelTypeStoreBackendTest, ReadDeletedRecord) { | |
103 scoped_refptr<ModelTypeStoreBackend> backend = GetOrCreateBackend(); | |
104 | |
105 // Create records, ensure they are returned by ReadRecordsWithPrefix. | |
106 std::unique_ptr<leveldb::WriteBatch> write_batch(new leveldb::WriteBatch()); | |
107 write_batch->Put("prefix:id1", "data1"); | |
108 write_batch->Put("prefix:id2", "data2"); | |
109 ModelTypeStore::Result result = | |
110 backend->WriteModifications(std::move(write_batch)); | |
111 ASSERT_EQ(ModelTypeStore::Result::SUCCESS, result); | |
112 | |
113 ModelTypeStore::IdList id_list; | |
114 ModelTypeStore::IdList missing_id_list; | |
115 ModelTypeStore::RecordList record_list; | |
116 id_list.push_back("id1"); | |
117 id_list.push_back("id2"); | |
118 result = backend->ReadRecordsWithPrefix("prefix:", id_list, &record_list, | |
119 &missing_id_list); | |
120 ASSERT_EQ(ModelTypeStore::Result::SUCCESS, result); | |
121 ASSERT_EQ(2UL, record_list.size()); | |
122 ASSERT_TRUE(missing_id_list.empty()); | |
123 | |
124 // Delete one record. | |
125 write_batch.reset(new leveldb::WriteBatch()); | |
126 write_batch->Delete("prefix:id2"); | |
127 result = backend->WriteModifications(std::move(write_batch)); | |
128 ASSERT_EQ(ModelTypeStore::Result::SUCCESS, result); | |
129 | |
130 // Ensure deleted record id is returned in missing_id_list. | |
131 record_list.clear(); | |
132 missing_id_list.clear(); | |
133 result = backend->ReadRecordsWithPrefix("prefix:", id_list, &record_list, | |
134 &missing_id_list); | |
135 ASSERT_EQ(ModelTypeStore::Result::SUCCESS, result); | |
136 ASSERT_EQ(1UL, record_list.size()); | |
137 ASSERT_EQ("id1", record_list[0].id); | |
138 ASSERT_EQ(1UL, missing_id_list.size()); | |
139 ASSERT_EQ("id2", missing_id_list[0]); | |
140 } | |
141 | |
142 // Test that only one backend got create when we ask two backend with same path, | |
143 // and after de-reference the backend, the backend will be deleted. | |
144 TEST_F(ModelTypeStoreBackendTest, TwoSameBackendTest) { | |
145 // Create two backend with same path, check if they are reference to same | |
146 // address. | |
147 scoped_refptr<ModelTypeStoreBackend> backend = GetOrCreateBackend(); | |
148 scoped_refptr<ModelTypeStoreBackend> backend_second = GetOrCreateBackend(); | |
149 std::string path = GetBackendPath(backend); | |
150 ASSERT_EQ(backend.get(), backend_second.get()); | |
151 | |
152 // Delete one reference, check the real backend still here. | |
153 backend = nullptr; | |
154 ASSERT_FALSE(backend.get()); | |
155 ASSERT_TRUE(backend_second.get()); | |
156 ASSERT_TRUE(backend_second->HasOneRef()); | |
157 | |
158 // Delete another reference, check the real backend is deleted. | |
159 backend_second = nullptr; | |
160 ASSERT_FALSE(backend_second.get()); | |
161 ASSERT_FALSE(BackendExistsForPath(path)); | |
162 } | |
163 | |
164 // Test that two backend got create when we ask two backend with different path, | |
165 // and after de-reference two backend, the both backend will be deleted. | |
166 TEST_F(ModelTypeStoreBackendTest, TwoDifferentBackendTest) { | |
167 // Create two backend with different path, check if they are reference to | |
168 // different address. | |
169 scoped_refptr<ModelTypeStoreBackend> backend = GetOrCreateBackend(); | |
170 scoped_refptr<ModelTypeStoreBackend> backend_second = | |
171 GetOrCreateBackendWithPath("/test_db2"); | |
172 std::string path = GetBackendPath(backend); | |
173 ASSERT_NE(backend.get(), backend_second.get()); | |
174 ASSERT_TRUE(backend->HasOneRef()); | |
175 ASSERT_TRUE(backend_second->HasOneRef()); | |
176 | |
177 // delete one backend, check only one got deleted. | |
178 backend = nullptr; | |
179 ASSERT_FALSE(backend.get()); | |
180 ASSERT_TRUE(backend_second.get()); | |
181 ASSERT_TRUE(backend_second->HasOneRef()); | |
182 ASSERT_FALSE(BackendExistsForPath(path)); | |
183 | |
184 // delete another backend. | |
185 backend_second = nullptr; | |
186 ASSERT_FALSE(backend_second.get()); | |
187 ASSERT_FALSE(BackendExistsForPath("/test_db2")); | |
188 } | |
189 | |
190 } // namespace syncer_v2 | |
OLD | NEW |