1 //
2 // Copyright (C) 2014 The Android Open Source Project
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16
17 #include "update_engine/update_manager/variable.h"
18
19 #include <vector>
20
21 #include <brillo/message_loops/fake_message_loop.h>
22 #include <brillo/message_loops/message_loop.h>
23 #include <brillo/message_loops/message_loop_utils.h>
24 #include <gtest/gtest.h>
25
26 using base::TimeDelta;
27 using brillo::MessageLoop;
28 using brillo::MessageLoopRunMaxIterations;
29 using std::string;
30 using std::vector;
31
32 namespace chromeos_update_manager {
33
34 // Variable class that returns a value constructed with the default value.
35 template <typename T>
36 class DefaultVariable : public Variable<T> {
37 public:
DefaultVariable(const string & name,VariableMode mode)38 DefaultVariable(const string& name, VariableMode mode)
39 : Variable<T>(name, mode) {}
DefaultVariable(const string & name,const TimeDelta & poll_interval)40 DefaultVariable(const string& name, const TimeDelta& poll_interval)
41 : Variable<T>(name, poll_interval) {}
~DefaultVariable()42 ~DefaultVariable() override {}
43
44 protected:
GetValue(TimeDelta,string *)45 const T* GetValue(TimeDelta /* timeout */, string* /* errmsg */) override {
46 return new T();
47 }
48
49 private:
50 DISALLOW_COPY_AND_ASSIGN(DefaultVariable);
51 };
52
53 class UmBaseVariableTest : public ::testing::Test {
54 protected:
SetUp()55 void SetUp() override { loop_.SetAsCurrent(); }
56
57 brillo::FakeMessageLoop loop_{nullptr};
58 };
59
TEST_F(UmBaseVariableTest,GetNameTest)60 TEST_F(UmBaseVariableTest, GetNameTest) {
61 DefaultVariable<int> var("var", kVariableModeConst);
62 EXPECT_EQ(var.GetName(), string("var"));
63 }
64
TEST_F(UmBaseVariableTest,GetModeTest)65 TEST_F(UmBaseVariableTest, GetModeTest) {
66 DefaultVariable<int> var("var", kVariableModeConst);
67 EXPECT_EQ(var.GetMode(), kVariableModeConst);
68 DefaultVariable<int> other_var("other_var", kVariableModePoll);
69 EXPECT_EQ(other_var.GetMode(), kVariableModePoll);
70 }
71
TEST_F(UmBaseVariableTest,DefaultPollIntervalTest)72 TEST_F(UmBaseVariableTest, DefaultPollIntervalTest) {
73 DefaultVariable<int> const_var("const_var", kVariableModeConst);
74 EXPECT_EQ(const_var.GetPollInterval(), TimeDelta());
75 DefaultVariable<int> poll_var("poll_var", kVariableModePoll);
76 EXPECT_EQ(poll_var.GetPollInterval(), TimeDelta::FromMinutes(5));
77 }
78
TEST_F(UmBaseVariableTest,GetPollIntervalTest)79 TEST_F(UmBaseVariableTest, GetPollIntervalTest) {
80 DefaultVariable<int> var("var", TimeDelta::FromMinutes(3));
81 EXPECT_EQ(var.GetMode(), kVariableModePoll);
82 EXPECT_EQ(var.GetPollInterval(), TimeDelta::FromMinutes(3));
83 }
84
85 class BaseVariableObserver : public BaseVariable::ObserverInterface {
86 public:
ValueChanged(BaseVariable * variable)87 void ValueChanged(BaseVariable* variable) { calls_.push_back(variable); }
88
89 // List of called functions.
90 vector<BaseVariable*> calls_;
91 };
92
TEST_F(UmBaseVariableTest,RepeatedObserverTest)93 TEST_F(UmBaseVariableTest, RepeatedObserverTest) {
94 DefaultVariable<int> var("var", kVariableModeAsync);
95 BaseVariableObserver observer;
96 var.AddObserver(&observer);
97 EXPECT_EQ(1U, var.observer_list_.size());
98 var.AddObserver(&observer);
99 EXPECT_EQ(1U, var.observer_list_.size());
100 var.RemoveObserver(&observer);
101 EXPECT_EQ(0U, var.observer_list_.size());
102 var.RemoveObserver(&observer);
103 EXPECT_EQ(0U, var.observer_list_.size());
104 }
105
TEST_F(UmBaseVariableTest,NotifyValueChangedTest)106 TEST_F(UmBaseVariableTest, NotifyValueChangedTest) {
107 DefaultVariable<int> var("var", kVariableModeAsync);
108 BaseVariableObserver observer1;
109 var.AddObserver(&observer1);
110 // Simulate a value change on the variable's implementation.
111 var.NotifyValueChanged();
112 ASSERT_EQ(0U, observer1.calls_.size());
113 MessageLoopRunMaxIterations(MessageLoop::current(), 100);
114
115 ASSERT_EQ(1U, observer1.calls_.size());
116 // Check that the observer is called with the right argument.
117 EXPECT_EQ(&var, observer1.calls_[0]);
118
119 BaseVariableObserver observer2;
120 var.AddObserver(&observer2);
121 var.NotifyValueChanged();
122 MessageLoopRunMaxIterations(MessageLoop::current(), 100);
123
124 // Check that all the observers are called.
125 EXPECT_EQ(2U, observer1.calls_.size());
126 EXPECT_EQ(1U, observer2.calls_.size());
127
128 var.RemoveObserver(&observer1);
129 var.RemoveObserver(&observer2);
130 }
131
132 class BaseVariableObserverRemover : public BaseVariable::ObserverInterface {
133 public:
BaseVariableObserverRemover()134 BaseVariableObserverRemover() : calls_(0) {}
135
ValueChanged(BaseVariable * variable)136 void ValueChanged(BaseVariable* variable) override {
137 for (auto& observer : remove_observers_) {
138 variable->RemoveObserver(observer);
139 }
140 calls_++;
141 }
142
OnCallRemoveObserver(BaseVariable::ObserverInterface * observer)143 void OnCallRemoveObserver(BaseVariable::ObserverInterface* observer) {
144 remove_observers_.push_back(observer);
145 }
146
get_calls()147 int get_calls() { return calls_; }
148
149 private:
150 vector<BaseVariable::ObserverInterface*> remove_observers_;
151 int calls_;
152 };
153
154 // Tests that we can remove an observer from a Variable on the ValueChanged()
155 // call to that observer.
TEST_F(UmBaseVariableTest,NotifyValueRemovesObserversTest)156 TEST_F(UmBaseVariableTest, NotifyValueRemovesObserversTest) {
157 DefaultVariable<int> var("var", kVariableModeAsync);
158 BaseVariableObserverRemover observer1;
159 BaseVariableObserverRemover observer2;
160
161 var.AddObserver(&observer1);
162 var.AddObserver(&observer2);
163
164 // Make each observer remove both observers on ValueChanged.
165 observer1.OnCallRemoveObserver(&observer1);
166 observer1.OnCallRemoveObserver(&observer2);
167 observer2.OnCallRemoveObserver(&observer1);
168 observer2.OnCallRemoveObserver(&observer2);
169
170 var.NotifyValueChanged();
171 MessageLoopRunMaxIterations(MessageLoop::current(), 100);
172
173 EXPECT_EQ(1, observer1.get_calls() + observer2.get_calls());
174 }
175
176 } // namespace chromeos_update_manager
177