1 // Copyright 2014 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 "extensions/browser/value_store/value_store_unittest.h"
6
7 #include <utility>
8
9 #include "base/json/json_writer.h"
10 #include "base/values.h"
11
12 namespace {
13
14 // To save typing ValueStore::DEFAULTS everywhere.
15 const ValueStore::WriteOptions DEFAULTS = ValueStore::DEFAULTS;
16
17 // Gets the pretty-printed JSON for a value.
GetJSON(const base::Value & value)18 std::string GetJSON(const base::Value& value) {
19 std::string json;
20 base::JSONWriter::WriteWithOptions(
21 value, base::JSONWriter::OPTIONS_PRETTY_PRINT, &json);
22 return json;
23 }
24
25 } // namespace
26
27 // Compares two possibly NULL values for equality, filling |error| with an
28 // appropriate error message if they're different.
ValuesEqual(const base::Value * expected,const base::Value * actual,std::string * error)29 bool ValuesEqual(const base::Value* expected,
30 const base::Value* actual,
31 std::string* error) {
32 if (expected == actual) {
33 return true;
34 }
35 if (expected && !actual) {
36 *error = "Expected: " + GetJSON(*expected) + ", actual: NULL";
37 return false;
38 }
39 if (actual && !expected) {
40 *error = "Expected: NULL, actual: " + GetJSON(*actual);
41 return false;
42 }
43 if (!expected->Equals(actual)) {
44 *error =
45 "Expected: " + GetJSON(*expected) + ", actual: " + GetJSON(*actual);
46 return false;
47 }
48 return true;
49 }
50
51 // Returns whether the read result of a storage operation has the expected
52 // settings.
SettingsEq(const char * _1,const char * _2,const base::DictionaryValue & expected,ValueStore::ReadResult actual_result)53 testing::AssertionResult SettingsEq(
54 const char* _1, const char* _2,
55 const base::DictionaryValue& expected,
56 ValueStore::ReadResult actual_result) {
57 if (!actual_result.status().ok()) {
58 return testing::AssertionFailure()
59 << "Result has error: " << actual_result.status().message;
60 }
61
62 std::string error;
63 if (!ValuesEqual(&expected, &actual_result.settings(), &error)) {
64 return testing::AssertionFailure() << error;
65 }
66
67 return testing::AssertionSuccess();
68 }
69
70 // Returns whether the write result of a storage operation has the expected
71 // changes.
ChangesEq(const char * _1,const char * _2,const ValueStoreChangeList & expected,ValueStore::WriteResult actual_result)72 testing::AssertionResult ChangesEq(
73 const char* _1, const char* _2,
74 const ValueStoreChangeList& expected,
75 ValueStore::WriteResult actual_result) {
76 if (!actual_result.status().ok()) {
77 return testing::AssertionFailure()
78 << "Result has error: " << actual_result.status().message;
79 }
80
81 const ValueStoreChangeList& actual = actual_result.changes();
82 if (expected.size() != actual.size()) {
83 return testing::AssertionFailure() <<
84 "Actual has wrong size, expecting " << expected.size() <<
85 " but was " << actual.size();
86 }
87
88 std::map<std::string, std::unique_ptr<ValueStoreChange>> expected_as_map;
89 for (const ValueStoreChange& change : expected)
90 expected_as_map[change.key()] = std::make_unique<ValueStoreChange>(change);
91
92 std::set<std::string> keys_seen;
93
94 for (auto it = actual.cbegin(); it != actual.cend(); ++it) {
95 if (keys_seen.count(it->key())) {
96 return testing::AssertionFailure() <<
97 "Multiple changes seen for key: " << it->key();
98 }
99 keys_seen.insert(it->key());
100
101 if (!expected_as_map.count(it->key())) {
102 return testing::AssertionFailure() <<
103 "Actual has unexpected change for key: " << it->key();
104 }
105
106 ValueStoreChange expected_change = *expected_as_map[it->key()];
107 std::string error;
108 if (!ValuesEqual(expected_change.new_value(), it->new_value(), &error)) {
109 return testing::AssertionFailure() <<
110 "New value for " << it->key() << " was unexpected: " << error;
111 }
112 if (!ValuesEqual(expected_change.old_value(), it->old_value(), &error)) {
113 return testing::AssertionFailure() <<
114 "Old value for " << it->key() << " was unexpected: " << error;
115 }
116 }
117
118 return testing::AssertionSuccess();
119 }
120
ValueStoreTest()121 ValueStoreTest::ValueStoreTest()
122 : key1_("foo"),
123 key2_("bar"),
124 key3_("baz"),
125 empty_dict_(new base::DictionaryValue()),
126 dict1_(new base::DictionaryValue()),
127 dict3_(new base::DictionaryValue()),
128 dict12_(new base::DictionaryValue()),
129 dict123_(new base::DictionaryValue()) {
130 val1_.reset(new base::Value(key1_ + "Value"));
131 val2_.reset(new base::Value(key2_ + "Value"));
132 val3_.reset(new base::Value(key3_ + "Value"));
133
134 list1_.push_back(key1_);
135 list2_.push_back(key2_);
136 list3_.push_back(key3_);
137 list12_.push_back(key1_);
138 list12_.push_back(key2_);
139 list13_.push_back(key1_);
140 list13_.push_back(key3_);
141 list123_.push_back(key1_);
142 list123_.push_back(key2_);
143 list123_.push_back(key3_);
144
145 set1_.insert(list1_.begin(), list1_.end());
146 set2_.insert(list2_.begin(), list2_.end());
147 set3_.insert(list3_.begin(), list3_.end());
148 set12_.insert(list12_.begin(), list12_.end());
149 set13_.insert(list13_.begin(), list13_.end());
150 set123_.insert(list123_.begin(), list123_.end());
151
152 dict1_->Set(key1_, val1_->CreateDeepCopy());
153 dict3_->Set(key3_, val3_->CreateDeepCopy());
154 dict12_->Set(key1_, val1_->CreateDeepCopy());
155 dict12_->Set(key2_, val2_->CreateDeepCopy());
156 dict123_->Set(key1_, val1_->CreateDeepCopy());
157 dict123_->Set(key2_, val2_->CreateDeepCopy());
158 dict123_->Set(key3_, val3_->CreateDeepCopy());
159 }
160
~ValueStoreTest()161 ValueStoreTest::~ValueStoreTest() {}
162
SetUp()163 void ValueStoreTest::SetUp() {
164 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
165 storage_.reset((GetParam())(temp_dir_.GetPath().AppendASCII("dbName")));
166 ASSERT_TRUE(storage_.get());
167 }
168
TearDown()169 void ValueStoreTest::TearDown() {
170 storage_.reset();
171 }
172
TEST_P(ValueStoreTest,GetWhenEmpty)173 TEST_P(ValueStoreTest, GetWhenEmpty) {
174 EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(key1_));
175 EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(empty_list_));
176 EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(list123_));
177 EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get());
178 }
179
TEST_P(ValueStoreTest,GetWithSingleValue)180 TEST_P(ValueStoreTest, GetWithSingleValue) {
181 {
182 ValueStoreChangeList changes;
183 changes.push_back(ValueStoreChange(key1_, base::nullopt, val1_->Clone()));
184 EXPECT_PRED_FORMAT2(ChangesEq,
185 changes, storage_->Set(DEFAULTS, key1_, *val1_));
186 }
187
188 EXPECT_PRED_FORMAT2(SettingsEq, *dict1_, storage_->Get(key1_));
189 EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(key2_));
190 EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(key3_));
191 EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(empty_list_));
192 EXPECT_PRED_FORMAT2(SettingsEq, *dict1_, storage_->Get(list123_));
193 EXPECT_PRED_FORMAT2(SettingsEq, *dict1_, storage_->Get());
194 }
195
TEST_P(ValueStoreTest,GetWithMultipleValues)196 TEST_P(ValueStoreTest, GetWithMultipleValues) {
197 {
198 ValueStoreChangeList changes;
199 changes.push_back(ValueStoreChange(key1_, base::nullopt, val1_->Clone()));
200 changes.push_back(ValueStoreChange(key2_, base::nullopt, val2_->Clone()));
201 EXPECT_PRED_FORMAT2(ChangesEq, changes, storage_->Set(DEFAULTS, *dict12_));
202 }
203
204 EXPECT_PRED_FORMAT2(SettingsEq, *dict1_, storage_->Get(key1_));
205 EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(key3_));
206 EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(empty_list_));
207 EXPECT_PRED_FORMAT2(SettingsEq, *dict12_, storage_->Get(list123_));
208 EXPECT_PRED_FORMAT2(SettingsEq, *dict12_, storage_->Get());
209 }
210
TEST_P(ValueStoreTest,RemoveWhenEmpty)211 TEST_P(ValueStoreTest, RemoveWhenEmpty) {
212 EXPECT_PRED_FORMAT2(ChangesEq, ValueStoreChangeList(),
213 storage_->Remove(key1_));
214
215 EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(key1_));
216 EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(list1_));
217 EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get());
218 }
219
TEST_P(ValueStoreTest,RemoveWithSingleValue)220 TEST_P(ValueStoreTest, RemoveWithSingleValue) {
221 storage_->Set(DEFAULTS, *dict1_);
222 {
223 ValueStoreChangeList changes;
224 changes.push_back(ValueStoreChange(key1_, val1_->Clone(), base::nullopt));
225 EXPECT_PRED_FORMAT2(ChangesEq, changes, storage_->Remove(key1_));
226 }
227
228 EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(key1_));
229 EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(key2_));
230 EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(list1_));
231 EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(list12_));
232 EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get());
233 }
234
TEST_P(ValueStoreTest,RemoveWithMultipleValues)235 TEST_P(ValueStoreTest, RemoveWithMultipleValues) {
236 storage_->Set(DEFAULTS, *dict123_);
237 {
238 ValueStoreChangeList changes;
239 changes.push_back(ValueStoreChange(key3_, val3_->Clone(), base::nullopt));
240 EXPECT_PRED_FORMAT2(ChangesEq, changes, storage_->Remove(key3_));
241 }
242
243 EXPECT_PRED_FORMAT2(SettingsEq, *dict1_, storage_->Get(key1_));
244 EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(key3_));
245 EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(empty_list_));
246 EXPECT_PRED_FORMAT2(SettingsEq, *dict1_, storage_->Get(list1_));
247 EXPECT_PRED_FORMAT2(SettingsEq, *dict12_, storage_->Get(list12_));
248 EXPECT_PRED_FORMAT2(SettingsEq, *dict1_, storage_->Get(list13_));
249 EXPECT_PRED_FORMAT2(SettingsEq, *dict12_, storage_->Get(list123_));
250 EXPECT_PRED_FORMAT2(SettingsEq, *dict12_, storage_->Get());
251
252 {
253 ValueStoreChangeList changes;
254 changes.push_back(ValueStoreChange(key1_, val1_->Clone(), base::nullopt));
255 changes.push_back(ValueStoreChange(key2_, val2_->Clone(), base::nullopt));
256 EXPECT_PRED_FORMAT2(ChangesEq, changes, storage_->Remove(list12_));
257 }
258
259 EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(key1_));
260 EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(key3_));
261 EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(empty_list_));
262 EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(list1_));
263 EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(list12_));
264 EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(list13_));
265 EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(list123_));
266 EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get());
267 }
268
TEST_P(ValueStoreTest,SetWhenOverwriting)269 TEST_P(ValueStoreTest, SetWhenOverwriting) {
270 storage_->Set(DEFAULTS, key1_, *val2_);
271 {
272 ValueStoreChangeList changes;
273 changes.push_back(ValueStoreChange(key1_, val2_->Clone(), val1_->Clone()));
274 changes.push_back(ValueStoreChange(key2_, base::nullopt, val2_->Clone()));
275 EXPECT_PRED_FORMAT2(ChangesEq, changes, storage_->Set(DEFAULTS, *dict12_));
276 }
277
278 EXPECT_PRED_FORMAT2(SettingsEq, *dict1_, storage_->Get(key1_));
279 EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(key3_));
280 EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(empty_list_));
281 EXPECT_PRED_FORMAT2(SettingsEq, *dict1_, storage_->Get(list1_));
282 EXPECT_PRED_FORMAT2(SettingsEq, *dict12_, storage_->Get(list12_));
283 EXPECT_PRED_FORMAT2(SettingsEq, *dict1_, storage_->Get(list13_));
284 EXPECT_PRED_FORMAT2(SettingsEq, *dict12_, storage_->Get(list123_));
285 EXPECT_PRED_FORMAT2(SettingsEq, *dict12_, storage_->Get());
286 }
287
TEST_P(ValueStoreTest,ClearWhenEmpty)288 TEST_P(ValueStoreTest, ClearWhenEmpty) {
289 EXPECT_PRED_FORMAT2(ChangesEq, ValueStoreChangeList(), storage_->Clear());
290
291 EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(key1_));
292 EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(empty_list_));
293 EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(list123_));
294 EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get());
295 }
296
TEST_P(ValueStoreTest,ClearWhenNotEmpty)297 TEST_P(ValueStoreTest, ClearWhenNotEmpty) {
298 storage_->Set(DEFAULTS, *dict12_);
299 {
300 ValueStoreChangeList changes;
301 changes.push_back(ValueStoreChange(key1_, val1_->Clone(), base::nullopt));
302 changes.push_back(ValueStoreChange(key2_, val2_->Clone(), base::nullopt));
303 EXPECT_PRED_FORMAT2(ChangesEq, changes, storage_->Clear());
304 }
305
306 EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(key1_));
307 EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(empty_list_));
308 EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(list123_));
309 EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get());
310 }
311
312 // Dots should be allowed in key names; they shouldn't be interpreted as
313 // indexing into a dictionary.
TEST_P(ValueStoreTest,DotsInKeyNames)314 TEST_P(ValueStoreTest, DotsInKeyNames) {
315 std::string dot_key("foo.bar");
316 base::Value dot_value("baz.qux");
317 std::vector<std::string> dot_list;
318 dot_list.push_back(dot_key);
319 base::DictionaryValue dot_dict;
320 dot_dict.SetWithoutPathExpansion(dot_key, dot_value.CreateDeepCopy());
321
322 EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(dot_key));
323
324 {
325 ValueStoreChangeList changes;
326 changes.push_back(
327 ValueStoreChange(dot_key, base::nullopt, dot_value.Clone()));
328 EXPECT_PRED_FORMAT2(ChangesEq,
329 changes, storage_->Set(DEFAULTS, dot_key, dot_value));
330 }
331 EXPECT_PRED_FORMAT2(ChangesEq,
332 ValueStoreChangeList(), storage_->Set(DEFAULTS, dot_key, dot_value));
333
334 EXPECT_PRED_FORMAT2(SettingsEq, dot_dict, storage_->Get(dot_key));
335
336 {
337 ValueStoreChangeList changes;
338 changes.push_back(
339 ValueStoreChange(dot_key, dot_value.Clone(), base::nullopt));
340 EXPECT_PRED_FORMAT2(ChangesEq, changes, storage_->Remove(dot_key));
341 }
342 EXPECT_PRED_FORMAT2(ChangesEq,
343 ValueStoreChangeList(), storage_->Remove(dot_key));
344 {
345 ValueStoreChangeList changes;
346 changes.push_back(
347 ValueStoreChange(dot_key, base::nullopt, dot_value.Clone()));
348 EXPECT_PRED_FORMAT2(ChangesEq, changes, storage_->Set(DEFAULTS, dot_dict));
349 }
350
351 EXPECT_PRED_FORMAT2(SettingsEq, dot_dict, storage_->Get(dot_list));
352 EXPECT_PRED_FORMAT2(SettingsEq, dot_dict, storage_->Get());
353
354 {
355 ValueStoreChangeList changes;
356 changes.push_back(
357 ValueStoreChange(dot_key, dot_value.Clone(), base::nullopt));
358 EXPECT_PRED_FORMAT2(ChangesEq, changes, storage_->Remove(dot_list));
359 }
360
361 EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(dot_key));
362 EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get());
363 }
364
TEST_P(ValueStoreTest,DotsInKeyNamesWithDicts)365 TEST_P(ValueStoreTest, DotsInKeyNamesWithDicts) {
366 base::DictionaryValue outer_dict;
367 base::DictionaryValue inner_dict;
368 inner_dict.SetString("bar", "baz");
369 outer_dict.Set("foo", inner_dict.CreateDeepCopy());
370
371 {
372 ValueStoreChangeList changes;
373 changes.push_back(
374 ValueStoreChange("foo", base::nullopt, inner_dict.Clone()));
375 EXPECT_PRED_FORMAT2(ChangesEq, changes,
376 storage_->Set(DEFAULTS, outer_dict));
377 }
378
379 EXPECT_PRED_FORMAT2(SettingsEq, outer_dict, storage_->Get("foo"));
380 EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get("foo.bar"));
381 }
382
TEST_P(ValueStoreTest,ComplexChangedKeysScenarios)383 TEST_P(ValueStoreTest, ComplexChangedKeysScenarios) {
384 // Test:
385 // - Setting over missing/changed/same keys, combinations.
386 // - Removing over missing and present keys, combinations.
387 // - Clearing.
388 std::vector<std::string> complex_list;
389 base::DictionaryValue complex_changed_dict;
390
391 storage_->Set(DEFAULTS, key1_, *val1_);
392 EXPECT_PRED_FORMAT2(ChangesEq,
393 ValueStoreChangeList(), storage_->Set(DEFAULTS, key1_, *val1_));
394 {
395 ValueStoreChangeList changes;
396 changes.push_back(ValueStoreChange(key1_, val1_->Clone(), val2_->Clone()));
397 EXPECT_PRED_FORMAT2(ChangesEq,
398 changes, storage_->Set(DEFAULTS, key1_, *val2_));
399 }
400 {
401 ValueStoreChangeList changes;
402 changes.push_back(ValueStoreChange(key1_, val2_->Clone(), base::nullopt));
403 EXPECT_PRED_FORMAT2(ChangesEq, changes, storage_->Remove(key1_));
404 EXPECT_PRED_FORMAT2(ChangesEq,
405 ValueStoreChangeList(), storage_->Remove(key1_));
406 }
407 {
408 ValueStoreChangeList changes;
409 changes.push_back(ValueStoreChange(key1_, base::nullopt, val1_->Clone()));
410 EXPECT_PRED_FORMAT2(ChangesEq,
411 changes, storage_->Set(DEFAULTS, key1_, *val1_));
412 }
413 {
414 ValueStoreChangeList changes;
415 changes.push_back(ValueStoreChange(key1_, val1_->Clone(), base::nullopt));
416 EXPECT_PRED_FORMAT2(ChangesEq, changes, storage_->Clear());
417 EXPECT_PRED_FORMAT2(ChangesEq, ValueStoreChangeList(), storage_->Clear());
418 }
419
420 {
421 ValueStoreChangeList changes;
422 changes.push_back(ValueStoreChange(key1_, base::nullopt, val1_->Clone()));
423 changes.push_back(ValueStoreChange(key2_, base::nullopt, val2_->Clone()));
424 EXPECT_PRED_FORMAT2(ChangesEq, changes, storage_->Set(DEFAULTS, *dict12_));
425 EXPECT_PRED_FORMAT2(ChangesEq,
426 ValueStoreChangeList(), storage_->Set(DEFAULTS, *dict12_));
427 }
428 {
429 ValueStoreChangeList changes;
430 changes.push_back(ValueStoreChange(key3_, base::nullopt, val3_->Clone()));
431 EXPECT_PRED_FORMAT2(ChangesEq, changes, storage_->Set(DEFAULTS, *dict123_));
432 }
433 {
434 base::DictionaryValue to_set;
435 to_set.Set(key1_, val2_->CreateDeepCopy());
436 to_set.Set(key2_, val2_->CreateDeepCopy());
437 to_set.Set("asdf", val1_->CreateDeepCopy());
438 to_set.Set("qwerty", val3_->CreateDeepCopy());
439
440 ValueStoreChangeList changes;
441 changes.push_back(ValueStoreChange(key1_, val1_->Clone(), val2_->Clone()));
442 changes.push_back(ValueStoreChange("asdf", base::nullopt, val1_->Clone()));
443 changes.push_back(
444 ValueStoreChange("qwerty", base::nullopt, val3_->Clone()));
445 EXPECT_PRED_FORMAT2(ChangesEq, changes, storage_->Set(DEFAULTS, to_set));
446 }
447 {
448 ValueStoreChangeList changes;
449 changes.push_back(ValueStoreChange(key1_, val2_->Clone(), base::nullopt));
450 changes.push_back(ValueStoreChange(key2_, val2_->Clone(), base::nullopt));
451 EXPECT_PRED_FORMAT2(ChangesEq, changes, storage_->Remove(list12_));
452 }
453 {
454 std::vector<std::string> to_remove;
455 to_remove.push_back(key1_);
456 to_remove.push_back("asdf");
457
458 ValueStoreChangeList changes;
459 changes.push_back(ValueStoreChange("asdf", val1_->Clone(), base::nullopt));
460 EXPECT_PRED_FORMAT2(ChangesEq, changes, storage_->Remove(to_remove));
461 }
462 {
463 ValueStoreChangeList changes;
464 changes.push_back(ValueStoreChange(key3_, val3_->Clone(), base::nullopt));
465 changes.push_back(
466 ValueStoreChange("qwerty", val3_->Clone(), base::nullopt));
467 EXPECT_PRED_FORMAT2(ChangesEq, changes, storage_->Clear());
468 EXPECT_PRED_FORMAT2(ChangesEq, ValueStoreChangeList(), storage_->Clear());
469 }
470 }
471