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: 38 DefaultVariable(const string& name, VariableMode mode) 39 : Variable<T>(name, mode) {} 40 DefaultVariable(const string& name, const TimeDelta& poll_interval) 41 : Variable<T>(name, poll_interval) {} 42 ~DefaultVariable() override {} 43 44 protected: 45 const T* GetValue(TimeDelta /* timeout */, 46 string* /* errmsg */) override { 47 return new T(); 48 } 49 50 private: 51 DISALLOW_COPY_AND_ASSIGN(DefaultVariable); 52 }; 53 54 class UmBaseVariableTest : public ::testing::Test { 55 protected: 56 void SetUp() override { 57 loop_.SetAsCurrent(); 58 } 59 60 brillo::FakeMessageLoop loop_{nullptr}; 61 }; 62 63 TEST_F(UmBaseVariableTest, GetNameTest) { 64 DefaultVariable<int> var("var", kVariableModeConst); 65 EXPECT_EQ(var.GetName(), string("var")); 66 } 67 68 TEST_F(UmBaseVariableTest, GetModeTest) { 69 DefaultVariable<int> var("var", kVariableModeConst); 70 EXPECT_EQ(var.GetMode(), kVariableModeConst); 71 DefaultVariable<int> other_var("other_var", kVariableModePoll); 72 EXPECT_EQ(other_var.GetMode(), kVariableModePoll); 73 } 74 75 TEST_F(UmBaseVariableTest, DefaultPollIntervalTest) { 76 DefaultVariable<int> const_var("const_var", kVariableModeConst); 77 EXPECT_EQ(const_var.GetPollInterval(), TimeDelta()); 78 DefaultVariable<int> poll_var("poll_var", kVariableModePoll); 79 EXPECT_EQ(poll_var.GetPollInterval(), TimeDelta::FromMinutes(5)); 80 } 81 82 TEST_F(UmBaseVariableTest, GetPollIntervalTest) { 83 DefaultVariable<int> var("var", TimeDelta::FromMinutes(3)); 84 EXPECT_EQ(var.GetMode(), kVariableModePoll); 85 EXPECT_EQ(var.GetPollInterval(), TimeDelta::FromMinutes(3)); 86 } 87 88 class BaseVariableObserver : public BaseVariable::ObserverInterface { 89 public: 90 void ValueChanged(BaseVariable* variable) { 91 calls_.push_back(variable); 92 } 93 94 // List of called functions. 95 vector<BaseVariable*> calls_; 96 }; 97 98 TEST_F(UmBaseVariableTest, RepeatedObserverTest) { 99 DefaultVariable<int> var("var", kVariableModeAsync); 100 BaseVariableObserver observer; 101 var.AddObserver(&observer); 102 EXPECT_EQ(1U, var.observer_list_.size()); 103 var.AddObserver(&observer); 104 EXPECT_EQ(1U, var.observer_list_.size()); 105 var.RemoveObserver(&observer); 106 EXPECT_EQ(0U, var.observer_list_.size()); 107 var.RemoveObserver(&observer); 108 EXPECT_EQ(0U, var.observer_list_.size()); 109 } 110 111 TEST_F(UmBaseVariableTest, NotifyValueChangedTest) { 112 DefaultVariable<int> var("var", kVariableModeAsync); 113 BaseVariableObserver observer1; 114 var.AddObserver(&observer1); 115 // Simulate a value change on the variable's implementation. 116 var.NotifyValueChanged(); 117 ASSERT_EQ(0U, observer1.calls_.size()); 118 MessageLoopRunMaxIterations(MessageLoop::current(), 100); 119 120 ASSERT_EQ(1U, observer1.calls_.size()); 121 // Check that the observer is called with the right argument. 122 EXPECT_EQ(&var, observer1.calls_[0]); 123 124 BaseVariableObserver observer2; 125 var.AddObserver(&observer2); 126 var.NotifyValueChanged(); 127 MessageLoopRunMaxIterations(MessageLoop::current(), 100); 128 129 // Check that all the observers are called. 130 EXPECT_EQ(2U, observer1.calls_.size()); 131 EXPECT_EQ(1U, observer2.calls_.size()); 132 133 var.RemoveObserver(&observer1); 134 var.RemoveObserver(&observer2); 135 } 136 137 class BaseVariableObserverRemover : public BaseVariable::ObserverInterface { 138 public: 139 BaseVariableObserverRemover() : calls_(0) {} 140 141 void ValueChanged(BaseVariable* variable) override { 142 for (auto& observer : remove_observers_) { 143 variable->RemoveObserver(observer); 144 } 145 calls_++; 146 } 147 148 void OnCallRemoveObserver(BaseVariable::ObserverInterface* observer) { 149 remove_observers_.push_back(observer); 150 } 151 152 int get_calls() { return calls_; } 153 154 private: 155 vector<BaseVariable::ObserverInterface*> remove_observers_; 156 int calls_; 157 }; 158 159 // Tests that we can remove an observer from a Variable on the ValueChanged() 160 // call to that observer. 161 TEST_F(UmBaseVariableTest, NotifyValueRemovesObserversTest) { 162 DefaultVariable<int> var("var", kVariableModeAsync); 163 BaseVariableObserverRemover observer1; 164 BaseVariableObserverRemover observer2; 165 166 var.AddObserver(&observer1); 167 var.AddObserver(&observer2); 168 169 // Make each observer remove both observers on ValueChanged. 170 observer1.OnCallRemoveObserver(&observer1); 171 observer1.OnCallRemoveObserver(&observer2); 172 observer2.OnCallRemoveObserver(&observer1); 173 observer2.OnCallRemoveObserver(&observer2); 174 175 var.NotifyValueChanged(); 176 MessageLoopRunMaxIterations(MessageLoop::current(), 100); 177 178 EXPECT_EQ(1, observer1.get_calls() + observer2.get_calls()); 179 } 180 181 } // namespace chromeos_update_manager 182