|  | // Copyright 2015 The Weave Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #include "src/states/state_change_queue.h" | 
|  |  | 
|  | #include <gtest/gtest.h> | 
|  | #include <weave/test/unittest_utils.h> | 
|  |  | 
|  | #include "src/bind_lambda.h" | 
|  |  | 
|  | namespace weave { | 
|  |  | 
|  | using test::CreateDictionaryValue; | 
|  |  | 
|  | class StateChangeQueueTest : public ::testing::Test { | 
|  | public: | 
|  | void SetUp() override { queue_.reset(new StateChangeQueue(100)); } | 
|  |  | 
|  | void TearDown() override { queue_.reset(); } | 
|  |  | 
|  | std::unique_ptr<StateChangeQueue> queue_; | 
|  | }; | 
|  |  | 
|  | TEST_F(StateChangeQueueTest, Empty) { | 
|  | EXPECT_TRUE(queue_->GetAndClearRecordedStateChanges().empty()); | 
|  | } | 
|  |  | 
|  | TEST_F(StateChangeQueueTest, UpdateOne) { | 
|  | auto timestamp = base::Time::Now(); | 
|  | ASSERT_TRUE(queue_->NotifyPropertiesUpdated( | 
|  | timestamp, *CreateDictionaryValue("{'prop': {'name': 23}}"))); | 
|  | auto changes = queue_->GetAndClearRecordedStateChanges(); | 
|  | ASSERT_EQ(1u, changes.size()); | 
|  | EXPECT_EQ(timestamp, changes.front().timestamp); | 
|  | EXPECT_JSON_EQ("{'prop':{'name': 23}}", *changes.front().changed_properties); | 
|  | EXPECT_TRUE(queue_->GetAndClearRecordedStateChanges().empty()); | 
|  | } | 
|  |  | 
|  | TEST_F(StateChangeQueueTest, UpdateMany) { | 
|  | auto timestamp1 = base::Time::Now(); | 
|  | const std::string state1 = "{'prop': {'name1': 23}}"; | 
|  | auto timestamp2 = timestamp1 + base::TimeDelta::FromSeconds(1); | 
|  | const std::string state2 = | 
|  | "{'prop': {'name1': 17, 'name2': 1.0, 'name3': false}}"; | 
|  | ASSERT_TRUE(queue_->NotifyPropertiesUpdated(timestamp1, | 
|  | *CreateDictionaryValue(state1))); | 
|  | ASSERT_TRUE(queue_->NotifyPropertiesUpdated(timestamp2, | 
|  | *CreateDictionaryValue(state2))); | 
|  |  | 
|  | auto changes = queue_->GetAndClearRecordedStateChanges(); | 
|  | ASSERT_EQ(2u, changes.size()); | 
|  | EXPECT_EQ(timestamp1, changes[0].timestamp); | 
|  | EXPECT_JSON_EQ(state1, *changes[0].changed_properties); | 
|  | EXPECT_EQ(timestamp2, changes[1].timestamp); | 
|  | EXPECT_JSON_EQ(state2, *changes[1].changed_properties); | 
|  | EXPECT_TRUE(queue_->GetAndClearRecordedStateChanges().empty()); | 
|  | } | 
|  |  | 
|  | TEST_F(StateChangeQueueTest, GroupByTimestamp) { | 
|  | base::Time timestamp = base::Time::Now(); | 
|  | base::TimeDelta time_delta = base::TimeDelta::FromMinutes(1); | 
|  |  | 
|  | ASSERT_TRUE(queue_->NotifyPropertiesUpdated( | 
|  | timestamp, *CreateDictionaryValue("{'prop': {'name1': 1}}"))); | 
|  |  | 
|  | ASSERT_TRUE(queue_->NotifyPropertiesUpdated( | 
|  | timestamp, *CreateDictionaryValue("{'prop': {'name2': 2}}"))); | 
|  |  | 
|  | ASSERT_TRUE(queue_->NotifyPropertiesUpdated( | 
|  | timestamp, *CreateDictionaryValue("{'prop': {'name1': 3}}"))); | 
|  |  | 
|  | ASSERT_TRUE(queue_->NotifyPropertiesUpdated( | 
|  | timestamp + time_delta, | 
|  | *CreateDictionaryValue("{'prop': {'name1': 4}}"))); | 
|  |  | 
|  | auto changes = queue_->GetAndClearRecordedStateChanges(); | 
|  | ASSERT_EQ(2u, changes.size()); | 
|  |  | 
|  | const std::string expected1 = "{'prop': {'name1': 3, 'name2': 2}}"; | 
|  | const std::string expected2 = "{'prop': {'name1': 4}}"; | 
|  | EXPECT_EQ(timestamp, changes[0].timestamp); | 
|  | EXPECT_JSON_EQ(expected1, *changes[0].changed_properties); | 
|  | EXPECT_EQ(timestamp + time_delta, changes[1].timestamp); | 
|  | EXPECT_JSON_EQ(expected2, *changes[1].changed_properties); | 
|  | } | 
|  |  | 
|  | TEST_F(StateChangeQueueTest, MaxQueueSize) { | 
|  | queue_.reset(new StateChangeQueue(2)); | 
|  | base::Time start_time = base::Time::Now(); | 
|  | base::TimeDelta time_delta1 = base::TimeDelta::FromMinutes(1); | 
|  | base::TimeDelta time_delta2 = base::TimeDelta::FromMinutes(3); | 
|  |  | 
|  | ASSERT_TRUE(queue_->NotifyPropertiesUpdated( | 
|  | start_time, | 
|  | *CreateDictionaryValue("{'prop': {'name1': 1, 'name2': 2}}"))); | 
|  |  | 
|  | ASSERT_TRUE(queue_->NotifyPropertiesUpdated( | 
|  | start_time + time_delta1, | 
|  | *CreateDictionaryValue("{'prop': {'name1': 3, 'name3': 4}}"))); | 
|  |  | 
|  | ASSERT_TRUE(queue_->NotifyPropertiesUpdated( | 
|  | start_time + time_delta2, | 
|  | *CreateDictionaryValue("{'prop': {'name10': 10, 'name11': 11}}"))); | 
|  |  | 
|  | auto changes = queue_->GetAndClearRecordedStateChanges(); | 
|  | ASSERT_EQ(2u, changes.size()); | 
|  |  | 
|  | const std::string expected1 = | 
|  | "{'prop': {'name1': 3, 'name2': 2, 'name3': 4}}"; | 
|  | EXPECT_EQ(start_time + time_delta1, changes[0].timestamp); | 
|  | EXPECT_JSON_EQ(expected1, *changes[0].changed_properties); | 
|  |  | 
|  | const std::string expected2 = "{'prop': {'name10': 10, 'name11': 11}}"; | 
|  | EXPECT_EQ(start_time + time_delta2, changes[1].timestamp); | 
|  | EXPECT_JSON_EQ(expected2, *changes[1].changed_properties); | 
|  | } | 
|  |  | 
|  | }  // namespace weave |