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 26using base::TimeDelta; 27using brillo::MessageLoop; 28using brillo::MessageLoopRunMaxIterations; 29using std::string; 30using std::vector; 31 32namespace chromeos_update_manager { 33 34// Variable class that returns a value constructed with the default value. 35template <typename T> 36class 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 54class UmBaseVariableTest : public ::testing::Test { 55 protected: 56 void SetUp() override { 57 loop_.SetAsCurrent(); 58 } 59 60 brillo::FakeMessageLoop loop_{nullptr}; 61}; 62 63TEST_F(UmBaseVariableTest, GetNameTest) { 64 DefaultVariable<int> var("var", kVariableModeConst); 65 EXPECT_EQ(var.GetName(), string("var")); 66} 67 68TEST_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 75TEST_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 82TEST_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 88class 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 98TEST_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 111TEST_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 137class 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. 161TEST_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