shill: Fix cellular PIN unlock

There were three problems.  1) The properties of the modem were not
being parsed when the modem was first started, and so the lock status
of the modem was not known, which prevented the GUI from asking the
user to enter a PIN. 2) When the modem is locked, it cannot be
started successfully, but the software state of the modem was being
changed to "enabled", preventing it from being enabled when the PIN
was entered (you can't enable an already enabled modem).  3) When
enabling a modem failed, the asynchronous enable function still
thought the enable operation was in progress, preventing the
enabling of the modem once the PIN is entered.

BUG=chromium-os:29847
TEST=manual.  Try to enable a PIN-locked GSM modem.  Also added new
unittests.

Change-Id: I72258586c3ba59abbcc40e03b47d4b7b9e4b73da
Reviewed-on: https://gerrit.chromium.org/gerrit/21562
Reviewed-by: mukesh agrawal <quiche@chromium.org>
Reviewed-by: Jason Glasgow <jglasgow@chromium.org>
Commit-Ready: Gary Morain <gmorain@chromium.org>
Tested-by: Gary Morain <gmorain@chromium.org>
diff --git a/key_value_store_matcher.h b/key_value_store_matcher.h
new file mode 100644
index 0000000..10769de
--- /dev/null
+++ b/key_value_store_matcher.h
@@ -0,0 +1,133 @@
+// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SHILL_KEY_VALUE_STORE_MATCHER_
+#define SHILL_KEY_VALUE_STORE_MATCHER_
+
+#include <gmock/gmock.h>
+#include "shill/key_value_store.h"
+
+// A GMock matcher for a shill::KeyValueStore.  To be used in unittests.
+//
+// Usage:
+//   KeyValueStore expected;
+//   expected.SetBool(flimflam::kSIMLockEnabledProperty, false);
+//   EXPECT_CALL(*device_adaptor_, EmitKeyValueStoreChanged(
+//       flimflam::kSIMLockStatusProperty,
+//       KeyValueStoreEq(expected)));
+//
+// The EXPECT_CALL will match if |expected| has the same contents as the actual
+// parameter passed to EmitKeyValueStoreChanged().  If the match fails, a helped
+// message is emitted to show the mismatch between the actual and expected
+// parameters, like this:
+//
+//   Expected arg #1: KeyValueStore
+//      bools-map equals { ("LockEnabled", false) } and
+//      int-map equals {} and
+//      string-map equals {} and
+//      uint-map equals {}
+//            Actual: 96-byte object <C607 51F6 0000 0000 089C F0F8 089C F0F8
+//            089C F0F8 0100 0000 14A3 3FF7 0000 0000 0000 0000 585C E5FF 585C
+//            E5FF 0000 0000 0000 0000 0000 0000 489C F0F8 489C F0F8 489C F0F8
+//            0100 0000 AB5C E5FF 0000 0000 889C F0F8 889C F0F8 889C F0F8 0100
+//            0000> (
+//      Unmatched bools: Only in actual: ("LockEnabled", true); not in actual:
+//      ("LockEnabled", false)
+//      Unmatched ints:
+//      Unmatched strings: Only in actual: ("LockType", "")
+//      Unmatched uints: Only in actual: ("RetriesLeft", 0))
+//          Expected: to be called once
+//            Actual: never called - unsatisfied and active
+//
+// This shows you the expected value of the KeyValueStore, raw actual
+// KeyValueStore (which you can ignore), and, most importantly, the difference
+// between the actual and expected values.
+
+namespace shill {
+
+// This class is implemented instead of a simpler MATCHER_P so that the error
+// messages are clearer when a match fails.  A KeyValueStore is a aggregate of
+// maps.  This matcher uses ContainerEq to compare the maps of the expected
+// value to the actual one.  It also uses the the DescribeTo() and
+// ExplainMatchResultsTo() methods of ContainerEq to print a useful message when
+// the actual and expected values differ.  To do this, it needs a ContainerEq
+// object for each map contained by a KeyValueStore.
+class KeyValueStoreEqMatcher :
+      public testing::MatcherInterface<const KeyValueStore &> {
+ public:
+  explicit KeyValueStoreEqMatcher(const KeyValueStore &expected)
+      : expected_(expected),
+        bool_matcher_(testing::ContainerEq(expected_.bool_properties()).impl()),
+        int_matcher_(testing::ContainerEq(expected_.int_properties()).impl()),
+        string_matcher_(testing::ContainerEq(expected_.string_properties())
+                        .impl()),
+        uint_matcher_(testing::ContainerEq(expected_.uint_properties()).impl())
+  {}
+  // Returns true iff the matcher matches |actual|.  Each map of the actual
+  // KeyValueStore is compared to the maps contained with the |expected_|
+  // KeyValueStore.  The comparison is done by the ContainerEq objects creating
+  // in the constructor.
+  virtual bool Matches(const KeyValueStore &actual) const {
+    return bool_matcher_.impl().Matches(actual.bool_properties()) &&
+        int_matcher_.impl().Matches(actual.int_properties()) &&
+        string_matcher_.impl().Matches(actual.string_properties()) &&
+        uint_matcher_.impl().Matches(actual.uint_properties());
+  }
+  // Describes this matcher to an ostream.
+  virtual void DescribeTo(::std::ostream* os) const {
+    *os << "KeyValueStore" << std::endl << "\tbools-map ";
+    bool_matcher_.impl().DescribeTo(os);
+    *os << " and" << std::endl << "\tint-map ";
+    int_matcher_.impl().DescribeTo(os);
+    *os << " and" << std::endl << "\tstring-map ";
+    string_matcher_.impl().DescribeTo(os);
+    *os << " and" << std::endl << "\tuint-map ";
+    uint_matcher_.impl().DescribeTo(os);
+  }
+
+  // Explains why a match failed.
+  virtual void ExplainMatchResultTo(const KeyValueStore &actual,
+                                    ::std::ostream* os) const {
+    *os << std::endl << "\tUnmatched bools: ";
+    bool_matcher_.impl().ExplainMatchResultTo(actual.bool_properties(), os);
+    *os << std::endl << "\tUnmatched ints: ";
+    int_matcher_.impl().ExplainMatchResultTo(actual.int_properties(), os);
+    *os << std::endl << "\tUnmatched strings: ";
+    string_matcher_.impl().ExplainMatchResultTo(actual.string_properties(), os);
+    *os << std::endl << "\tUnmatched uints: ";
+    uint_matcher_.impl().ExplainMatchResultTo(actual.uint_properties(), os);
+  }
+
+ private:
+  // The expected value.  If |actual| passed to Matches does not equal this
+  // value, the match fails.
+  const KeyValueStore expected_;
+
+  // These are the ContainerEq objects used in the matching.  This signature is
+  // lifted from gmock/gmock-matchers.h.  One of these matchers is required for
+  // each map contained within a KeyValueStore.
+  testing::PolymorphicMatcher<
+    testing::internal::ContainerEqMatcher<std::map<std::string, bool> > >
+    bool_matcher_;
+
+  testing::PolymorphicMatcher<
+    testing::internal::ContainerEqMatcher<std::map<std::string, int> > >
+    int_matcher_;
+
+  testing::PolymorphicMatcher<
+    testing::internal::ContainerEqMatcher<std::map<std::string, std::string> > >
+    string_matcher_;
+
+  testing::PolymorphicMatcher<
+    testing::internal::ContainerEqMatcher<std::map<std::string, uint> > >
+    uint_matcher_;
+};
+
+inline testing::Matcher<const KeyValueStore&> KeyValueStoreEq(
+    const KeyValueStore &expected) {
+  return testing::MakeMatcher(new KeyValueStoreEqMatcher(expected));
+}
+
+}  // namespace shill
+#endif  // SHILL_KEY_VALUE_STORE_MATCHER_