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 */, 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: 55 void SetUp() override { loop_.SetAsCurrent(); } 56 57 brillo::FakeMessageLoop loop_{nullptr}; 58 }; 59 60 TEST_F(UmBaseVariableTest, GetNameTest) { 61 DefaultVariable<int> var("var", kVariableModeConst); 62 EXPECT_EQ(var.GetName(), string("var")); 63 } 64 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 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 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: 87 void ValueChanged(BaseVariable* variable) { calls_.push_back(variable); } 88 89 // List of called functions. 90 vector<BaseVariable*> calls_; 91 }; 92 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 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: 134 BaseVariableObserverRemover() : calls_(0) {} 135 136 void ValueChanged(BaseVariable* variable) override { 137 for (auto& observer : remove_observers_) { 138 variable->RemoveObserver(observer); 139 } 140 calls_++; 141 } 142 143 void OnCallRemoveObserver(BaseVariable::ObserverInterface* observer) { 144 remove_observers_.push_back(observer); 145 } 146 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. 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