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
12namespace weave {
13
14using test::CreateDictionaryValue;
15
16class StateChangeQueueTest : public ::testing::Test {
17 public:
18  void SetUp() override { queue_.reset(new StateChangeQueue(100)); }
19
20  void TearDown() override { queue_.reset(); }
21
22  std::unique_ptr<StateChangeQueue> queue_;
23};
24
25TEST_F(StateChangeQueueTest, Empty) {
26  EXPECT_TRUE(queue_->GetAndClearRecordedStateChanges().empty());
27}
28
29TEST_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
40TEST_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
60TEST_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
88TEST_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