• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
30 using std::map;
31 using std::string;
32 using std::vector;
33 using ::testing::Return;
34 using ::testing::Test;
35 
36 namespace shill {
37 
TEST(PropertyAccessorTest,SignedIntCorrectness)38 TEST(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 
TEST(PropertyAccessorTest,UnsignedIntCorrectness)119 TEST(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 
TEST(PropertyAccessorTest,StringCorrectness)201 TEST(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 
TEST(PropertyAccessorTest,ByteArrayCorrectness)281 TEST(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 
366 class StringWrapper {
367  public:
Get(Error *)368   string Get(Error* /*error*/) {
369     return value_;
370   }
ConstGet(Error *) const371   string ConstGet(Error* /*error*/) const {
372     return value_;
373   }
Set(const string & value,Error *)374   bool Set(const string& value, Error* /*error*/) {
375     if (value_ == value) {
376       return false;
377     }
378     value_ = value;
379     return true;
380   }
Clear(Error *)381   void Clear(Error* /*error*/) {
382     value_.clear();
383   }
384 
385   string value_;
386 };
387 
TEST(PropertyAccessorTest,CustomAccessorCorrectness)388 TEST(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 
TEST(PropertyAccessorTest,CustomWriteOnlyAccessorWithDefault)457 TEST(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 
TEST(PropertyAccessorTest,CustomWriteOnlyAccessorWithClear)500 TEST(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 
TEST(PropertyAccessorTest,CustomReadOnlyAccessor)540 TEST(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 
574 class StringMapWrapper {
575  public:
Clear(const string & key,Error *)576   void Clear(const string& key, Error* /*error*/) {
577     value_.erase(key);
578   }
Get(const string & key,Error *)579   string Get(const string& key, Error* /*error*/) {
580     EXPECT_TRUE(ContainsKey(value_, key));
581     return value_[key];
582   }
Set(const string & key,const string & value,Error *)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 
TEST(PropertyAccessorTest,CustomMappedAccessor)594 TEST(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