buffet: Fix issues in StateChangeQueue

Addressed additional code review issues brought after the original
code has been published.

- NotifyPropertiesUpdated() now takes timestamp and property set
  as separate parameters to simplify implementation of StateManager.
- StateChangeQueue::max_queue_size_ is made 'const'
- StateChangeQueue now maintains a time-to-event map instead of
  a vector of StateChange. This allows to keep the events sorted
  by time stamp. Also adding discrete events with the same time stamp
  coalesces the property changes.
- added a unit test for coalescing property set changes based on
  the timestamp.

BUG=None
TEST=FEATURES=test emerge-link buffet

Change-Id: I309816d1f040558620fa68a844b05251d0e4319b
Reviewed-on: https://chromium-review.googlesource.com/226300
Reviewed-by: Christopher Wiley <wiley@chromium.org>
Reviewed-by: Anton Muhin <antonm@chromium.org>
Commit-Queue: Alex Vakulenko <avakulenko@chromium.org>
Tested-by: Alex Vakulenko <avakulenko@chromium.org>
diff --git a/buffet/states/state_manager.cc b/buffet/states/state_manager.cc
index f31801f..7511928 100644
--- a/buffet/states/state_manager.cc
+++ b/buffet/states/state_manager.cc
@@ -79,9 +79,10 @@
   return dict;
 }
 
-bool StateManager::UpdatePropertyValue(const std::string& full_property_name,
-                                       const chromeos::Any& value,
-                                       chromeos::ErrorPtr* error) {
+bool StateManager::SetPropertyValue(const std::string& full_property_name,
+                                    const chromeos::Any& value,
+                                    const base::Time& timestamp,
+                                    chromeos::ErrorPtr* error) {
   std::string package_name;
   std::string property_name;
   bool split = chromeos::string_utils::SplitAtFirst(
@@ -106,34 +107,11 @@
                             package_name.c_str());
     return false;
   }
-  return package->SetPropertyValue(property_name, value, error);
-}
-
-bool StateManager::SetPropertyValue(const std::string& full_property_name,
-                                    const chromeos::Any& value,
-                                    chromeos::ErrorPtr* error) {
-  if (!UpdatePropertyValue(full_property_name, value, error))
+  if (!package->SetPropertyValue(property_name, value, error))
     return false;
 
-  StateChange change;
-  change.timestamp = base::Time::Now();
-  change.property_set.emplace(full_property_name, value);
-  state_change_queue_->NotifyPropertiesUpdated(change);
-  return true;
-}
-
-bool StateManager::UpdateProperties(
-    const chromeos::VariantDictionary& property_set,
-    chromeos::ErrorPtr* error) {
-  for (const auto& pair : property_set) {
-    if (!UpdatePropertyValue(pair.first, pair.second, error))
-      return false;
-  }
-
-  StateChange change;
-  change.timestamp = base::Time::Now();
-  change.property_set = property_set;
-  state_change_queue_->NotifyPropertiesUpdated(change);
+  chromeos::VariantDictionary prop_set{{full_property_name, value}};
+  state_change_queue_->NotifyPropertiesUpdated(timestamp, prop_set);
   return true;
 }