1 // Copyright 2015 The Weave Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "src/states/state_change_queue.h"
6 
7 #include <gtest/gtest.h>
8 #include <weave/test/unittest_utils.h>
9 
10 #include "src/bind_lambda.h"
11 
12 namespace weave {
13 
14 using test::CreateDictionaryValue;
15 
16 class StateChangeQueueTest : public ::testing::Test {
17  public:
SetUp()18   void SetUp() override { queue_.reset(new StateChangeQueue(100)); }
19 
TearDown()20   void TearDown() override { queue_.reset(); }
21 
22   std::unique_ptr<StateChangeQueue> queue_;
23 };
24 
TEST_F(StateChangeQueueTest,Empty)25 TEST_F(StateChangeQueueTest, Empty) {
26   EXPECT_TRUE(queue_->GetAndClearRecordedStateChanges().empty());
27 }
28 
TEST_F(StateChangeQueueTest,UpdateOne)29 TEST_F(StateChangeQueueTest, UpdateOne) {
30   auto timestamp = base::Time::Now();
31   ASSERT_TRUE(queue_->NotifyPropertiesUpdated(
32       timestamp, *CreateDictionaryValue("{'prop': {'name': 23}}")));
33   auto changes = queue_->GetAndClearRecordedStateChanges();
34   ASSERT_EQ(1u, changes.size());
35   EXPECT_EQ(timestamp, changes.front().timestamp);
36   EXPECT_JSON_EQ("{'prop':{'name': 23}}", *changes.front().changed_properties);
37   EXPECT_TRUE(queue_->GetAndClearRecordedStateChanges().empty());
38 }
39 
TEST_F(StateChangeQueueTest,UpdateMany)40 TEST_F(StateChangeQueueTest, UpdateMany) {
41   auto timestamp1 = base::Time::Now();
42   const std::string state1 = "{'prop': {'name1': 23}}";
43   auto timestamp2 = timestamp1 + base::TimeDelta::FromSeconds(1);
44   const std::string state2 =
45       "{'prop': {'name1': 17, 'name2': 1.0, 'name3': false}}";
46   ASSERT_TRUE(queue_->NotifyPropertiesUpdated(timestamp1,
47                                               *CreateDictionaryValue(state1)));
48   ASSERT_TRUE(queue_->NotifyPropertiesUpdated(timestamp2,
49                                               *CreateDictionaryValue(state2)));
50 
51   auto changes = queue_->GetAndClearRecordedStateChanges();
52   ASSERT_EQ(2u, changes.size());
53   EXPECT_EQ(timestamp1, changes[0].timestamp);
54   EXPECT_JSON_EQ(state1, *changes[0].changed_properties);
55   EXPECT_EQ(timestamp2, changes[1].timestamp);
56   EXPECT_JSON_EQ(state2, *changes[1].changed_properties);
57   EXPECT_TRUE(queue_->GetAndClearRecordedStateChanges().empty());
58 }
59 
TEST_F(StateChangeQueueTest,GroupByTimestamp)60 TEST_F(StateChangeQueueTest, GroupByTimestamp) {
61   base::Time timestamp = base::Time::Now();
62   base::TimeDelta time_delta = base::TimeDelta::FromMinutes(1);
63 
64   ASSERT_TRUE(queue_->NotifyPropertiesUpdated(
65       timestamp, *CreateDictionaryValue("{'prop': {'name1': 1}}")));
66 
67   ASSERT_TRUE(queue_->NotifyPropertiesUpdated(
68       timestamp, *CreateDictionaryValue("{'prop': {'name2': 2}}")));
69 
70   ASSERT_TRUE(queue_->NotifyPropertiesUpdated(
71       timestamp, *CreateDictionaryValue("{'prop': {'name1': 3}}")));
72 
73   ASSERT_TRUE(queue_->NotifyPropertiesUpdated(
74       timestamp + time_delta,
75       *CreateDictionaryValue("{'prop': {'name1': 4}}")));
76 
77   auto changes = queue_->GetAndClearRecordedStateChanges();
78   ASSERT_EQ(2u, changes.size());
79 
80   const std::string expected1 = "{'prop': {'name1': 3, 'name2': 2}}";
81   const std::string expected2 = "{'prop': {'name1': 4}}";
82   EXPECT_EQ(timestamp, changes[0].timestamp);
83   EXPECT_JSON_EQ(expected1, *changes[0].changed_properties);
84   EXPECT_EQ(timestamp + time_delta, changes[1].timestamp);
85   EXPECT_JSON_EQ(expected2, *changes[1].changed_properties);
86 }
87 
TEST_F(StateChangeQueueTest,MaxQueueSize)88 TEST_F(StateChangeQueueTest, MaxQueueSize) {
89   queue_.reset(new StateChangeQueue(2));
90   base::Time start_time = base::Time::Now();
91   base::TimeDelta time_delta1 = base::TimeDelta::FromMinutes(1);
92   base::TimeDelta time_delta2 = base::TimeDelta::FromMinutes(3);
93 
94   ASSERT_TRUE(queue_->NotifyPropertiesUpdated(
95       start_time,
96       *CreateDictionaryValue("{'prop': {'name1': 1, 'name2': 2}}")));
97 
98   ASSERT_TRUE(queue_->NotifyPropertiesUpdated(
99       start_time + time_delta1,
100       *CreateDictionaryValue("{'prop': {'name1': 3, 'name3': 4}}")));
101 
102   ASSERT_TRUE(queue_->NotifyPropertiesUpdated(
103       start_time + time_delta2,
104       *CreateDictionaryValue("{'prop': {'name10': 10, 'name11': 11}}")));
105 
106   auto changes = queue_->GetAndClearRecordedStateChanges();
107   ASSERT_EQ(2u, changes.size());
108 
109   const std::string expected1 =
110       "{'prop': {'name1': 3, 'name2': 2, 'name3': 4}}";
111   EXPECT_EQ(start_time + time_delta1, changes[0].timestamp);
112   EXPECT_JSON_EQ(expected1, *changes[0].changed_properties);
113 
114   const std::string expected2 = "{'prop': {'name10': 10, 'name11': 11}}";
115   EXPECT_EQ(start_time + time_delta2, changes[1].timestamp);
116   EXPECT_JSON_EQ(expected2, *changes[1].changed_properties);
117 }
118 
119 }  // namespace weave
120