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