1//
2// Copyright (C) 2012 The Android Open Source Project
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8//      http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15//
16
17#include "shill/property_accessor.h"
18
19#include <limits>
20#include <map>
21#include <string>
22#include <vector>
23
24#include <base/stl_util.h>
25#include <gtest/gtest.h>
26#include <gmock/gmock.h>
27
28#include "shill/error.h"
29
30using std::map;
31using std::string;
32using std::vector;
33using ::testing::Return;
34using ::testing::Test;
35
36namespace shill {
37
38TEST(PropertyAccessorTest, SignedIntCorrectness) {
39  int32_t int_store = 0;
40  {
41    Error error;
42    int32_t orig_value = int_store;
43    Int32Accessor accessor(new PropertyAccessor<int32_t>(&int_store));
44    EXPECT_EQ(int_store, accessor->Get(&error));
45
46    int32_t expected_int32 = 127;
47    EXPECT_TRUE(accessor->Set(expected_int32, &error));
48    EXPECT_TRUE(error.IsSuccess());
49    EXPECT_EQ(expected_int32, accessor->Get(&error));
50    // Resetting to the same value should return false, but without
51    // an error.
52    EXPECT_FALSE(accessor->Set(expected_int32, &error));
53    EXPECT_TRUE(error.IsSuccess());
54
55    accessor->Clear(&error);
56    EXPECT_TRUE(error.IsSuccess());
57    EXPECT_EQ(orig_value, accessor->Get(&error));
58
59    int_store = std::numeric_limits<int32_t>::max();
60    EXPECT_EQ(std::numeric_limits<int32_t>::max(), accessor->Get(&error));
61  }
62  {
63    Error error;
64    Int32Accessor accessor(new ConstPropertyAccessor<int32_t>(&int_store));
65    EXPECT_EQ(int_store, accessor->Get(&error));
66
67    int32_t expected_int32 = 127;
68    accessor->Set(expected_int32, &error);
69    ASSERT_FALSE(error.IsSuccess());
70    EXPECT_EQ(Error::kInvalidArguments, error.type());
71    EXPECT_EQ(int_store, accessor->Get(&error));
72
73    int_store = std::numeric_limits<int32_t>::max();
74    EXPECT_EQ(std::numeric_limits<int32_t>::max(), accessor->Get(&error));
75  }
76  {
77    Error error;
78    Int32Accessor accessor(new ConstPropertyAccessor<int32_t>(&int_store));
79    accessor->Clear(&error);
80    ASSERT_FALSE(error.IsSuccess());
81  }
82  {
83    Error error;
84    Int32Accessor accessor(new WriteOnlyPropertyAccessor<int32_t>(&int_store));
85    accessor->Get(&error);
86    EXPECT_TRUE(error.IsFailure());
87    EXPECT_EQ(Error::kPermissionDenied, error.type());
88  }
89  {
90    Error error;
91    int32_t expected_int32 = 127;
92    WriteOnlyPropertyAccessor<int32_t> accessor(&int_store);
93    EXPECT_TRUE(accessor.Set(expected_int32, &error));
94    EXPECT_TRUE(error.IsSuccess());
95    EXPECT_EQ(expected_int32, *accessor.property_);
96    // Resetting to the same value should return false, but without
97    // an error.
98    EXPECT_FALSE(accessor.Set(expected_int32, &error));
99    EXPECT_TRUE(error.IsSuccess());
100    // As a write-only, the value can't be read.
101    EXPECT_EQ(int32_t(), accessor.Get(&error));
102    ASSERT_FALSE(error.IsSuccess());
103
104    int_store = std::numeric_limits<int32_t>::max();
105    EXPECT_EQ(std::numeric_limits<int32_t>::max(), *accessor.property_);
106  }
107  {
108    Error error;
109    int32_t orig_value = int_store = 0;
110    WriteOnlyPropertyAccessor<int32_t> accessor(&int_store);
111
112    EXPECT_TRUE(accessor.Set(127, &error));
113    accessor.Clear(&error);
114    EXPECT_TRUE(error.IsSuccess());
115    EXPECT_EQ(orig_value, *accessor.property_);
116  }
117}
118
119TEST(PropertyAccessorTest, UnsignedIntCorrectness) {
120  uint32_t int_store = 0;
121  {
122    Error error;
123    uint32_t orig_value = int_store;
124    Uint32Accessor accessor(new PropertyAccessor<uint32_t>(&int_store));
125    EXPECT_EQ(int_store, accessor->Get(&error));
126
127    uint32_t expected_uint32 = 127;
128    EXPECT_TRUE(accessor->Set(expected_uint32, &error));
129    EXPECT_TRUE(error.IsSuccess());
130    EXPECT_EQ(expected_uint32, accessor->Get(&error));
131    // Resetting to the same value should return false, but without
132    // an error.
133    EXPECT_FALSE(accessor->Set(expected_uint32, &error));
134    EXPECT_TRUE(error.IsSuccess());
135
136    accessor->Clear(&error);
137    EXPECT_TRUE(error.IsSuccess());
138    EXPECT_EQ(orig_value, accessor->Get(&error));
139
140    int_store = std::numeric_limits<uint32_t>::max();
141    EXPECT_EQ(std::numeric_limits<uint32_t>::max(), accessor->Get(&error));
142  }
143  {
144    Error error;
145    Uint32Accessor accessor(new ConstPropertyAccessor<uint32_t>(&int_store));
146    EXPECT_EQ(int_store, accessor->Get(&error));
147
148    uint32_t expected_uint32 = 127;
149    EXPECT_FALSE(accessor->Set(expected_uint32, &error));
150    ASSERT_FALSE(error.IsSuccess());
151    EXPECT_EQ(Error::kInvalidArguments, error.type());
152    EXPECT_EQ(int_store, accessor->Get(&error));
153
154    int_store = std::numeric_limits<uint32_t>::max();
155    EXPECT_EQ(std::numeric_limits<uint32_t>::max(), accessor->Get(&error));
156  }
157  {
158    Error error;
159    Uint32Accessor accessor(new ConstPropertyAccessor<uint32_t>(&int_store));
160    accessor->Clear(&error);
161    ASSERT_FALSE(error.IsSuccess());
162  }
163  {
164    Error error;
165    Uint32Accessor accessor(
166        new WriteOnlyPropertyAccessor<uint32_t>(&int_store));
167    accessor->Get(&error);
168    EXPECT_TRUE(error.IsFailure());
169    EXPECT_EQ(Error::kPermissionDenied, error.type());
170  }
171  {
172    Error error;
173    uint32_t expected_uint32 = 127;
174    WriteOnlyPropertyAccessor<uint32_t> accessor(&int_store);
175    EXPECT_TRUE(accessor.Set(expected_uint32, &error));
176    EXPECT_TRUE(error.IsSuccess());
177    EXPECT_EQ(expected_uint32, *accessor.property_);
178    // Resetting to the same value should return false, but without
179    // an error.
180    EXPECT_FALSE(accessor.Set(expected_uint32, &error));
181    EXPECT_TRUE(error.IsSuccess());
182    // As a write-only, the value can't be read.
183    EXPECT_EQ(uint32_t(), accessor.Get(&error));
184    ASSERT_FALSE(error.IsSuccess());
185
186    int_store = std::numeric_limits<uint32_t>::max();
187    EXPECT_EQ(std::numeric_limits<uint32_t>::max(), *accessor.property_);
188  }
189  {
190    Error error;
191    uint32_t orig_value = int_store = 0;
192    WriteOnlyPropertyAccessor<uint32_t> accessor(&int_store);
193
194    EXPECT_TRUE(accessor.Set(127, &error));
195    accessor.Clear(&error);
196    EXPECT_TRUE(error.IsSuccess());
197    EXPECT_EQ(orig_value, *accessor.property_);
198  }
199}
200
201TEST(PropertyAccessorTest, StringCorrectness) {
202  string storage;
203  {
204    Error error;
205    string orig_value = storage;
206    StringAccessor accessor(new PropertyAccessor<string>(&storage));
207    EXPECT_EQ(storage, accessor->Get(&error));
208
209    string expected_string("what");
210    EXPECT_TRUE(accessor->Set(expected_string, &error));
211    EXPECT_TRUE(error.IsSuccess());
212    EXPECT_EQ(expected_string, accessor->Get(&error));
213    // Resetting to the same value should return false, but without
214    // an error.
215    EXPECT_FALSE(accessor->Set(expected_string, &error));
216    EXPECT_TRUE(error.IsSuccess());
217
218    accessor->Clear(&error);
219    EXPECT_TRUE(error.IsSuccess());
220    EXPECT_EQ(orig_value, accessor->Get(&error));
221
222    storage = "nooooo";
223    EXPECT_EQ(storage, accessor->Get(&error));
224  }
225  {
226    Error error;
227    StringAccessor accessor(new ConstPropertyAccessor<string>(&storage));
228    EXPECT_EQ(storage, accessor->Get(&error));
229
230    string expected_string("what");
231    EXPECT_FALSE(accessor->Set(expected_string, &error));
232    ASSERT_FALSE(error.IsSuccess());
233    EXPECT_EQ(Error::kInvalidArguments, error.type());
234    EXPECT_EQ(storage, accessor->Get(&error));
235
236    storage = "nooooo";
237    EXPECT_EQ(storage, accessor->Get(&error));
238  }
239  {
240    Error error;
241    StringAccessor accessor(new ConstPropertyAccessor<string>(&storage));
242    accessor->Clear(&error);
243    ASSERT_FALSE(error.IsSuccess());
244  }
245  {
246    Error error;
247    StringAccessor accessor(new WriteOnlyPropertyAccessor<string>(&storage));
248    accessor->Get(&error);
249    EXPECT_TRUE(error.IsFailure());
250    EXPECT_EQ(Error::kPermissionDenied, error.type());
251  }
252  {
253    Error error;
254    string expected_string = "what";
255    WriteOnlyPropertyAccessor<string> accessor(&storage);
256    EXPECT_TRUE(accessor.Set(expected_string, &error));
257    EXPECT_TRUE(error.IsSuccess());
258    EXPECT_EQ(expected_string, *accessor.property_);
259    // Resetting to the same value should return false, but without
260    // an error.
261    EXPECT_FALSE(accessor.Set(expected_string, &error));
262    EXPECT_TRUE(error.IsSuccess());
263    // As a write-only, the value can't be read.
264    EXPECT_EQ(string(), accessor.Get(&error));
265    ASSERT_FALSE(error.IsSuccess());
266
267    storage = "nooooo";
268    EXPECT_EQ("nooooo", *accessor.property_);
269  }
270  {
271    Error error;
272    string orig_value = storage = "original value";
273    WriteOnlyPropertyAccessor<string> accessor(&storage);
274    EXPECT_TRUE(accessor.Set("new value", &error));
275    accessor.Clear(&error);
276    EXPECT_TRUE(error.IsSuccess());
277    EXPECT_EQ(orig_value, *accessor.property_);
278  }
279}
280
281TEST(PropertyAccessorTest, ByteArrayCorrectness) {
282  ByteArray byteArray;
283  {
284    Error error;
285    ByteArray orig_byteArray = byteArray;
286    ByteArrayAccessor accessor(new PropertyAccessor<ByteArray>(&byteArray));
287    EXPECT_EQ(byteArray, accessor->Get(&error));
288
289    ByteArray expected_byteArray({ 0x01, 0x7F, 0x80, 0xFF });
290    EXPECT_TRUE(accessor->Set(expected_byteArray, &error));
291    EXPECT_TRUE(error.IsSuccess());
292    EXPECT_EQ(expected_byteArray, accessor->Get(&error));
293
294    // Resetting to the same value should return false, but without
295    // an error.
296    EXPECT_FALSE(accessor->Set(expected_byteArray, &error));
297    EXPECT_TRUE(error.IsSuccess());
298
299    accessor->Clear(&error);
300    EXPECT_TRUE(error.IsSuccess());
301    EXPECT_EQ(orig_byteArray, accessor->Get(&error));
302
303    byteArray = ByteArray({ 0xFF, 0x7F, 0x80, 0x00 });
304    EXPECT_EQ(byteArray, accessor->Get(&error));
305  }
306  {
307    Error error;
308    ByteArrayAccessor accessor(new ConstPropertyAccessor<ByteArray>(&byteArray));
309    EXPECT_EQ(byteArray, accessor->Get(&error));
310
311    ByteArray expected_byteArray({ 0x01, 0x7F, 0x80, 0xFF });
312    EXPECT_FALSE(accessor->Set(expected_byteArray, &error));
313    ASSERT_FALSE(error.IsSuccess());
314    EXPECT_EQ(Error::kInvalidArguments, error.type());
315    EXPECT_EQ(byteArray, accessor->Get(&error));
316
317    byteArray = ByteArray({ 0xFF, 0x7F, 0x80, 0x00 });
318    EXPECT_EQ(byteArray, accessor->Get(&error));
319  }
320  {
321    Error error;
322    ByteArrayAccessor accessor(new ConstPropertyAccessor<ByteArray>(&byteArray));
323    accessor->Clear(&error);
324    ASSERT_FALSE(error.IsSuccess());
325  }
326  {
327    Error error;
328    ByteArrayAccessor accessor(new WriteOnlyPropertyAccessor<ByteArray>(&byteArray));
329    accessor->Get(&error);
330    EXPECT_TRUE(error.IsFailure());
331    EXPECT_EQ(Error::kPermissionDenied, error.type());
332  }
333  {
334    Error error;
335    ByteArray expected_byteArray({ 0x01, 0x7F, 0x80, 0xFF });
336    WriteOnlyPropertyAccessor<ByteArray> accessor(&byteArray);
337
338    EXPECT_TRUE(accessor.Set(expected_byteArray, &error));
339    EXPECT_TRUE(error.IsSuccess());
340    EXPECT_EQ(expected_byteArray, *accessor.property_);
341
342    // Resetting to the same value should return false, but without
343    // an error.
344    EXPECT_FALSE(accessor.Set(expected_byteArray, &error));
345    EXPECT_TRUE(error.IsSuccess());
346
347    // As a write-only, the value can't be read.
348    EXPECT_EQ(ByteArray(), accessor.Get(&error));
349    EXPECT_FALSE(error.IsSuccess());
350
351    byteArray = ByteArray({ 0xFF, 0x7F, 0x80, 0x00 });
352    EXPECT_EQ(ByteArray({ 0xFF, 0x7F, 0x80, 0x00 }), *accessor.property_);
353  }
354  {
355    Error error;
356    ByteArray orig_byteArray = byteArray = ByteArray({ 0x00, 0x7F, 0x80, 0xFF });
357    WriteOnlyPropertyAccessor<ByteArray> accessor(&byteArray);
358
359    EXPECT_TRUE(accessor.Set(ByteArray({ 0xFF, 0x7F, 0x80, 0x00 }), &error));
360    accessor.Clear(&error);
361    EXPECT_TRUE(error.IsSuccess());
362    EXPECT_EQ(orig_byteArray, *accessor.property_);
363  }
364}
365
366class StringWrapper {
367 public:
368  string Get(Error* /*error*/) {
369    return value_;
370  }
371  string ConstGet(Error* /*error*/) const {
372    return value_;
373  }
374  bool Set(const string& value, Error* /*error*/) {
375    if (value_ == value) {
376      return false;
377    }
378    value_ = value;
379    return true;
380  }
381  void Clear(Error* /*error*/) {
382    value_.clear();
383  }
384
385  string value_;
386};
387
388TEST(PropertyAccessorTest, CustomAccessorCorrectness) {
389  StringWrapper wrapper;
390  {
391    // Custom accessor: read, write, write-same, clear, read-updated.
392    // Together, write and write-same verify that the CustomAccessor
393    // template passes through the value from the called function.
394    Error error;
395    const string orig_value = wrapper.value_ = "original value";
396    CustomAccessor<StringWrapper, string> accessor(&wrapper,
397                                                   &StringWrapper::Get,
398                                                   &StringWrapper::Set);
399    EXPECT_EQ(orig_value, accessor.Get(&error));
400    EXPECT_TRUE(error.IsSuccess());
401
402    const string expected_string = "new value";
403    EXPECT_TRUE(accessor.Set(expected_string, &error));
404    EXPECT_TRUE(error.IsSuccess());
405    EXPECT_EQ(expected_string, accessor.Get(&error));
406    // Set to same value.
407    EXPECT_FALSE(accessor.Set(expected_string, &error));
408    EXPECT_TRUE(error.IsSuccess());
409
410    accessor.Clear(&error);
411    EXPECT_TRUE(error.IsSuccess());
412    EXPECT_EQ(orig_value, accessor.Get(&error));
413
414    wrapper.value_ = "nooooo";
415    EXPECT_EQ(wrapper.value_, accessor.Get(&error));
416  }
417  {
418    // Custom read-only accessor: read, write, read-updated.
419    Error error;
420    CustomAccessor<StringWrapper, string> accessor(&wrapper,
421                                                   &StringWrapper::Get,
422                                                   nullptr);
423    EXPECT_EQ(wrapper.value_, accessor.Get(&error));
424
425    const string expected_string = "what";
426    EXPECT_FALSE(accessor.Set(expected_string, &error));
427    ASSERT_FALSE(error.IsSuccess());
428    EXPECT_EQ(Error::kInvalidArguments, error.type());
429    EXPECT_EQ(wrapper.value_, accessor.Get(&error));
430
431    wrapper.value_ = "nooooo";
432    EXPECT_EQ(wrapper.value_, accessor.Get(&error));
433  }
434  {
435    // Custom read-only accessor: clear.
436    Error error;
437    CustomAccessor<StringWrapper, string> accessor(&wrapper,
438                                                   &StringWrapper::Get,
439                                                   nullptr);
440    accessor.Clear(&error);
441    ASSERT_FALSE(error.IsSuccess());
442  }
443  {
444    // Custom read-only accessor with custom clear method.
445    Error error;
446    CustomAccessor<StringWrapper, string> accessor(&wrapper,
447                                                   &StringWrapper::Get,
448                                                   nullptr,
449                                                   &StringWrapper::Clear);
450    wrapper.value_ = "empty this";
451    accessor.Clear(&error);
452    ASSERT_TRUE(error.IsSuccess());
453    EXPECT_TRUE(wrapper.value_.empty());
454  }
455}
456
457TEST(PropertyAccessorTest, CustomWriteOnlyAccessorWithDefault) {
458  StringWrapper wrapper;
459  {
460    // Test reading.
461    Error error;
462    const string default_value = "default value";
463    CustomWriteOnlyAccessor<StringWrapper, string> accessor(
464        &wrapper, &StringWrapper::Set, nullptr, &default_value);
465    wrapper.value_ = "can't read this";
466    EXPECT_EQ(string(), accessor.Get(&error));
467    EXPECT_TRUE(error.IsFailure());
468    EXPECT_EQ(Error::kPermissionDenied, error.type());
469  }
470  {
471    // Test writing.
472    Error error;
473    const string default_value = "default value";
474    const string expected_string = "what";
475    CustomWriteOnlyAccessor<StringWrapper, string> accessor(
476        &wrapper, &StringWrapper::Set, nullptr, &default_value);
477    EXPECT_TRUE(accessor.Set(expected_string, &error));
478    EXPECT_TRUE(error.IsSuccess());
479    EXPECT_EQ(expected_string, wrapper.value_);
480    // Set to same value. With the above, this verifies that the
481    // CustomWriteOnlyAccessor template passes through the return
482    // value.
483    EXPECT_FALSE(accessor.Set(expected_string, &error));
484    EXPECT_TRUE(error.IsSuccess());
485  }
486  {
487    // Test clearing.
488    Error error;
489    const string default_value = "default value";
490    CustomWriteOnlyAccessor<StringWrapper, string> accessor(
491        &wrapper, &StringWrapper::Set, nullptr, &default_value);
492    accessor.Set("new value", &error);
493    EXPECT_EQ("new value", wrapper.value_);
494    accessor.Clear(&error);
495    EXPECT_TRUE(error.IsSuccess());
496    EXPECT_EQ(default_value, wrapper.value_);
497  }
498}
499
500TEST(PropertyAccessorTest, CustomWriteOnlyAccessorWithClear) {
501  StringWrapper wrapper;
502  {
503    // Test reading.
504    Error error;
505    CustomWriteOnlyAccessor<StringWrapper, string> accessor(
506        &wrapper, &StringWrapper::Set, &StringWrapper::Clear, nullptr);
507    wrapper.value_ = "can't read this";
508    EXPECT_EQ(string(), accessor.Get(&error));
509    EXPECT_TRUE(error.IsFailure());
510    EXPECT_EQ(Error::kPermissionDenied, error.type());
511  }
512  {
513    // Test writing.
514    Error error;
515    const string expected_string = "what";
516    CustomWriteOnlyAccessor<StringWrapper, string> accessor(
517        &wrapper, &StringWrapper::Set, &StringWrapper::Clear, nullptr);
518    EXPECT_TRUE(accessor.Set(expected_string, &error));
519    EXPECT_TRUE(error.IsSuccess());
520    EXPECT_EQ(expected_string, wrapper.value_);
521    // Set to same value. With the above, this verifies that the
522    // CustomWriteOnlyAccessor template passes through the return
523    // value.
524    EXPECT_FALSE(accessor.Set(expected_string, &error));
525    EXPECT_TRUE(error.IsSuccess());
526  }
527  {
528    // Test clearing.
529    Error error;
530    CustomWriteOnlyAccessor<StringWrapper, string> accessor(
531        &wrapper, &StringWrapper::Set, &StringWrapper::Clear, nullptr);
532    EXPECT_TRUE(accessor.Set("new value", &error));
533    EXPECT_EQ("new value", wrapper.value_);
534    accessor.Clear(&error);
535    EXPECT_TRUE(error.IsSuccess());
536    EXPECT_EQ("", wrapper.value_);
537  }
538}
539
540TEST(PropertyAccessorTest, CustomReadOnlyAccessor) {
541  StringWrapper wrapper;
542  CustomReadOnlyAccessor<StringWrapper, string> accessor(
543      &wrapper, &StringWrapper::ConstGet);
544  const string orig_value = wrapper.value_ = "original value";
545  {
546    // Test reading.
547    Error error;
548    EXPECT_EQ(orig_value, accessor.Get(&error));
549    EXPECT_TRUE(error.IsSuccess());
550  }
551  {
552    // Test writing.
553    Error error;
554    EXPECT_FALSE(accessor.Set("new value", &error));
555    EXPECT_EQ(Error::kInvalidArguments, error.type());
556    EXPECT_EQ(orig_value, accessor.Get(&error));
557  }
558  {
559    // Test writing original value -- this also fails.
560    Error error;
561    EXPECT_FALSE(accessor.Set(orig_value, &error));
562    EXPECT_EQ(Error::kInvalidArguments, error.type());
563    EXPECT_EQ(orig_value, accessor.Get(&error));
564  }
565  {
566    // Test clearing.
567    Error error;
568    accessor.Clear(&error);
569    EXPECT_EQ(Error::kInvalidArguments, error.type());
570    EXPECT_EQ(orig_value, accessor.Get(&error));
571  }
572}
573
574class StringMapWrapper {
575 public:
576  void Clear(const string& key, Error* /*error*/) {
577    value_.erase(key);
578  }
579  string Get(const string& key, Error* /*error*/) {
580    EXPECT_TRUE(ContainsKey(value_, key));
581    return value_[key];
582  }
583  bool Set(const string& key, const string& value, Error* /*error*/) {
584    if (value_[key] == value) {
585      return false;
586    }
587    value_[key] = value;
588    return true;
589  }
590
591  map<string, string> value_;
592};
593
594TEST(PropertyAccessorTest, CustomMappedAccessor) {
595  const string kKey = "entry_key";
596  const string kValue = "entry_value";
597  {
598    // Test reading.
599    StringMapWrapper wrapper;
600    CustomMappedAccessor<StringMapWrapper, string, string> accessor(
601        &wrapper, &StringMapWrapper::Clear, &StringMapWrapper::Get,
602        &StringMapWrapper::Set, kKey);
603    wrapper.value_[kKey] = kValue;
604    Error error;
605    EXPECT_EQ(kValue, accessor.Get(&error));
606    EXPECT_TRUE(error.IsSuccess());
607  }
608  {
609    // Test writing.
610    StringMapWrapper wrapper;
611    CustomMappedAccessor<StringMapWrapper, string, string> accessor(
612        &wrapper, &StringMapWrapper::Clear, &StringMapWrapper::Get,
613        &StringMapWrapper::Set, kKey);
614    Error error;
615    EXPECT_TRUE(accessor.Set(kValue, &error));
616    EXPECT_TRUE(error.IsSuccess());
617    EXPECT_EQ(kValue, wrapper.value_[kKey]);
618    // Set to same value. With the above, this verifies that the
619    // CustomMappedAccessor template passes through the return
620    // value.
621    EXPECT_FALSE(accessor.Set(kValue, &error));
622    EXPECT_TRUE(error.IsSuccess());
623  }
624  {
625    // Test clearing.
626    StringMapWrapper wrapper;
627    CustomMappedAccessor<StringMapWrapper, string, string> accessor(
628        &wrapper, &StringMapWrapper::Clear, &StringMapWrapper::Get,
629        &StringMapWrapper::Set, kKey);
630    wrapper.value_[kKey] = kValue;
631    Error error;
632    accessor.Clear(&error);
633    EXPECT_TRUE(error.IsSuccess());
634    EXPECT_FALSE(ContainsKey(wrapper.value_, kKey));
635  }
636}
637
638}  // namespace shill
639