1aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//
2aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// Copyright (C) 2014 The Android Open Source Project
3aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//
4aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// Licensed under the Apache License, Version 2.0 (the "License");
5aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// you may not use this file except in compliance with the License.
6aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// You may obtain a copy of the License at
7aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//
8aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//      http://www.apache.org/licenses/LICENSE-2.0
9aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//
10aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// Unless required by applicable law or agreed to in writing, software
11aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// distributed under the License is distributed on an "AS IS" BASIS,
12aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// See the License for the specific language governing permissions and
14aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// limitations under the License.
15aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//
16391ad9f1b6ac96dc80d4c1b740245444fdae5765Alex Deymo
1763784a578dd26880454d70797519358a2326291bAlex Deymo#include "update_engine/update_manager/variable.h"
1853556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo
19a07a1234e8ca7654af91048fccff152ab3db8420Alex Deymo#include <vector>
20a07a1234e8ca7654af91048fccff152ab3db8420Alex Deymo
213f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenko#include <brillo/message_loops/fake_message_loop.h>
223f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenko#include <brillo/message_loops/message_loop.h>
233f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenko#include <brillo/message_loops/message_loop_utils.h>
24391ad9f1b6ac96dc80d4c1b740245444fdae5765Alex Deymo#include <gtest/gtest.h>
25391ad9f1b6ac96dc80d4c1b740245444fdae5765Alex Deymo
26a80339362c7a5175c2b7019095c0f04b388380cbAlex Deymousing base::TimeDelta;
273f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenkousing brillo::MessageLoop;
283f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenkousing brillo::MessageLoopRunMaxIterations;
29391ad9f1b6ac96dc80d4c1b740245444fdae5765Alex Deymousing std::string;
30a07a1234e8ca7654af91048fccff152ab3db8420Alex Deymousing std::vector;
31391ad9f1b6ac96dc80d4c1b740245444fdae5765Alex Deymo
3263784a578dd26880454d70797519358a2326291bAlex Deymonamespace chromeos_update_manager {
33391ad9f1b6ac96dc80d4c1b740245444fdae5765Alex Deymo
34391ad9f1b6ac96dc80d4c1b740245444fdae5765Alex Deymo// Variable class that returns a value constructed with the default value.
35391ad9f1b6ac96dc80d4c1b740245444fdae5765Alex Deymotemplate <typename T>
36391ad9f1b6ac96dc80d4c1b740245444fdae5765Alex Deymoclass DefaultVariable : public Variable<T> {
37391ad9f1b6ac96dc80d4c1b740245444fdae5765Alex Deymo public:
380e433699df9ac4462c9587ce398c8a2561adb929Alex Deymo  DefaultVariable(const string& name, VariableMode mode)
390e433699df9ac4462c9587ce398c8a2561adb929Alex Deymo      : Variable<T>(name, mode) {}
40a80339362c7a5175c2b7019095c0f04b388380cbAlex Deymo  DefaultVariable(const string& name, const TimeDelta& poll_interval)
41a80339362c7a5175c2b7019095c0f04b388380cbAlex Deymo      : Variable<T>(name, poll_interval) {}
42610277efc6f7e5239158dfa4bb3b1021804326e0Alex Deymo  ~DefaultVariable() override {}
43391ad9f1b6ac96dc80d4c1b740245444fdae5765Alex Deymo
44391ad9f1b6ac96dc80d4c1b740245444fdae5765Alex Deymo protected:
4535866ed08bcefa9d8bffab9ca64cf994ad0f4290Yunlian Jiang  const T* GetValue(TimeDelta /* timeout */,
4635866ed08bcefa9d8bffab9ca64cf994ad0f4290Yunlian Jiang                    string* /* errmsg */) override {
47391ad9f1b6ac96dc80d4c1b740245444fdae5765Alex Deymo    return new T();
48391ad9f1b6ac96dc80d4c1b740245444fdae5765Alex Deymo  }
49391ad9f1b6ac96dc80d4c1b740245444fdae5765Alex Deymo
50391ad9f1b6ac96dc80d4c1b740245444fdae5765Alex Deymo private:
51391ad9f1b6ac96dc80d4c1b740245444fdae5765Alex Deymo  DISALLOW_COPY_AND_ASSIGN(DefaultVariable);
52391ad9f1b6ac96dc80d4c1b740245444fdae5765Alex Deymo};
53391ad9f1b6ac96dc80d4c1b740245444fdae5765Alex Deymo
54509dd5376f47e38d18fe7d29da776e3dc9a9786dAlex Deymoclass UmBaseVariableTest : public ::testing::Test {
55509dd5376f47e38d18fe7d29da776e3dc9a9786dAlex Deymo protected:
56509dd5376f47e38d18fe7d29da776e3dc9a9786dAlex Deymo  void SetUp() override {
57509dd5376f47e38d18fe7d29da776e3dc9a9786dAlex Deymo    loop_.SetAsCurrent();
58509dd5376f47e38d18fe7d29da776e3dc9a9786dAlex Deymo  }
59509dd5376f47e38d18fe7d29da776e3dc9a9786dAlex Deymo
603f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenko  brillo::FakeMessageLoop loop_{nullptr};
61509dd5376f47e38d18fe7d29da776e3dc9a9786dAlex Deymo};
62509dd5376f47e38d18fe7d29da776e3dc9a9786dAlex Deymo
63509dd5376f47e38d18fe7d29da776e3dc9a9786dAlex DeymoTEST_F(UmBaseVariableTest, GetNameTest) {
640e433699df9ac4462c9587ce398c8a2561adb929Alex Deymo  DefaultVariable<int> var("var", kVariableModeConst);
65391ad9f1b6ac96dc80d4c1b740245444fdae5765Alex Deymo  EXPECT_EQ(var.GetName(), string("var"));
66391ad9f1b6ac96dc80d4c1b740245444fdae5765Alex Deymo}
67391ad9f1b6ac96dc80d4c1b740245444fdae5765Alex Deymo
68509dd5376f47e38d18fe7d29da776e3dc9a9786dAlex DeymoTEST_F(UmBaseVariableTest, GetModeTest) {
690e433699df9ac4462c9587ce398c8a2561adb929Alex Deymo  DefaultVariable<int> var("var", kVariableModeConst);
700e433699df9ac4462c9587ce398c8a2561adb929Alex Deymo  EXPECT_EQ(var.GetMode(), kVariableModeConst);
710e433699df9ac4462c9587ce398c8a2561adb929Alex Deymo  DefaultVariable<int> other_var("other_var", kVariableModePoll);
720e433699df9ac4462c9587ce398c8a2561adb929Alex Deymo  EXPECT_EQ(other_var.GetMode(), kVariableModePoll);
730e433699df9ac4462c9587ce398c8a2561adb929Alex Deymo}
740e433699df9ac4462c9587ce398c8a2561adb929Alex Deymo
75509dd5376f47e38d18fe7d29da776e3dc9a9786dAlex DeymoTEST_F(UmBaseVariableTest, DefaultPollIntervalTest) {
76a80339362c7a5175c2b7019095c0f04b388380cbAlex Deymo  DefaultVariable<int> const_var("const_var", kVariableModeConst);
77a80339362c7a5175c2b7019095c0f04b388380cbAlex Deymo  EXPECT_EQ(const_var.GetPollInterval(), TimeDelta());
78a80339362c7a5175c2b7019095c0f04b388380cbAlex Deymo  DefaultVariable<int> poll_var("poll_var", kVariableModePoll);
79a80339362c7a5175c2b7019095c0f04b388380cbAlex Deymo  EXPECT_EQ(poll_var.GetPollInterval(), TimeDelta::FromMinutes(5));
80a80339362c7a5175c2b7019095c0f04b388380cbAlex Deymo}
81a80339362c7a5175c2b7019095c0f04b388380cbAlex Deymo
82509dd5376f47e38d18fe7d29da776e3dc9a9786dAlex DeymoTEST_F(UmBaseVariableTest, GetPollIntervalTest) {
83a80339362c7a5175c2b7019095c0f04b388380cbAlex Deymo  DefaultVariable<int> var("var", TimeDelta::FromMinutes(3));
84a80339362c7a5175c2b7019095c0f04b388380cbAlex Deymo  EXPECT_EQ(var.GetMode(), kVariableModePoll);
85a80339362c7a5175c2b7019095c0f04b388380cbAlex Deymo  EXPECT_EQ(var.GetPollInterval(), TimeDelta::FromMinutes(3));
86a80339362c7a5175c2b7019095c0f04b388380cbAlex Deymo}
87a80339362c7a5175c2b7019095c0f04b388380cbAlex Deymo
8853556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymoclass BaseVariableObserver : public BaseVariable::ObserverInterface {
89a07a1234e8ca7654af91048fccff152ab3db8420Alex Deymo public:
90a07a1234e8ca7654af91048fccff152ab3db8420Alex Deymo  void ValueChanged(BaseVariable* variable) {
91a07a1234e8ca7654af91048fccff152ab3db8420Alex Deymo    calls_.push_back(variable);
92a07a1234e8ca7654af91048fccff152ab3db8420Alex Deymo  }
93a07a1234e8ca7654af91048fccff152ab3db8420Alex Deymo
94a07a1234e8ca7654af91048fccff152ab3db8420Alex Deymo  // List of called functions.
95a07a1234e8ca7654af91048fccff152ab3db8420Alex Deymo  vector<BaseVariable*> calls_;
96a07a1234e8ca7654af91048fccff152ab3db8420Alex Deymo};
97a07a1234e8ca7654af91048fccff152ab3db8420Alex Deymo
98509dd5376f47e38d18fe7d29da776e3dc9a9786dAlex DeymoTEST_F(UmBaseVariableTest, RepeatedObserverTest) {
99a07a1234e8ca7654af91048fccff152ab3db8420Alex Deymo  DefaultVariable<int> var("var", kVariableModeAsync);
100a07a1234e8ca7654af91048fccff152ab3db8420Alex Deymo  BaseVariableObserver observer;
101a07a1234e8ca7654af91048fccff152ab3db8420Alex Deymo  var.AddObserver(&observer);
10280f70ff45f8ea9a679c0c3ed0dc143dd2fe2b63eAlex Deymo  EXPECT_EQ(1U, var.observer_list_.size());
103a07a1234e8ca7654af91048fccff152ab3db8420Alex Deymo  var.AddObserver(&observer);
10480f70ff45f8ea9a679c0c3ed0dc143dd2fe2b63eAlex Deymo  EXPECT_EQ(1U, var.observer_list_.size());
105a07a1234e8ca7654af91048fccff152ab3db8420Alex Deymo  var.RemoveObserver(&observer);
10680f70ff45f8ea9a679c0c3ed0dc143dd2fe2b63eAlex Deymo  EXPECT_EQ(0U, var.observer_list_.size());
107a07a1234e8ca7654af91048fccff152ab3db8420Alex Deymo  var.RemoveObserver(&observer);
10880f70ff45f8ea9a679c0c3ed0dc143dd2fe2b63eAlex Deymo  EXPECT_EQ(0U, var.observer_list_.size());
109a07a1234e8ca7654af91048fccff152ab3db8420Alex Deymo}
110a07a1234e8ca7654af91048fccff152ab3db8420Alex Deymo
111509dd5376f47e38d18fe7d29da776e3dc9a9786dAlex DeymoTEST_F(UmBaseVariableTest, NotifyValueChangedTest) {
112a07a1234e8ca7654af91048fccff152ab3db8420Alex Deymo  DefaultVariable<int> var("var", kVariableModeAsync);
113a07a1234e8ca7654af91048fccff152ab3db8420Alex Deymo  BaseVariableObserver observer1;
114a07a1234e8ca7654af91048fccff152ab3db8420Alex Deymo  var.AddObserver(&observer1);
115a07a1234e8ca7654af91048fccff152ab3db8420Alex Deymo  // Simulate a value change on the variable's implementation.
116a07a1234e8ca7654af91048fccff152ab3db8420Alex Deymo  var.NotifyValueChanged();
11780f70ff45f8ea9a679c0c3ed0dc143dd2fe2b63eAlex Deymo  ASSERT_EQ(0U, observer1.calls_.size());
118509dd5376f47e38d18fe7d29da776e3dc9a9786dAlex Deymo  MessageLoopRunMaxIterations(MessageLoop::current(), 100);
119a07a1234e8ca7654af91048fccff152ab3db8420Alex Deymo
12080f70ff45f8ea9a679c0c3ed0dc143dd2fe2b63eAlex Deymo  ASSERT_EQ(1U, observer1.calls_.size());
121a07a1234e8ca7654af91048fccff152ab3db8420Alex Deymo  // Check that the observer is called with the right argument.
12253556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo  EXPECT_EQ(&var, observer1.calls_[0]);
123a07a1234e8ca7654af91048fccff152ab3db8420Alex Deymo
124a07a1234e8ca7654af91048fccff152ab3db8420Alex Deymo  BaseVariableObserver observer2;
125a07a1234e8ca7654af91048fccff152ab3db8420Alex Deymo  var.AddObserver(&observer2);
126a07a1234e8ca7654af91048fccff152ab3db8420Alex Deymo  var.NotifyValueChanged();
127509dd5376f47e38d18fe7d29da776e3dc9a9786dAlex Deymo  MessageLoopRunMaxIterations(MessageLoop::current(), 100);
128a07a1234e8ca7654af91048fccff152ab3db8420Alex Deymo
129a07a1234e8ca7654af91048fccff152ab3db8420Alex Deymo  // Check that all the observers are called.
13080f70ff45f8ea9a679c0c3ed0dc143dd2fe2b63eAlex Deymo  EXPECT_EQ(2U, observer1.calls_.size());
13180f70ff45f8ea9a679c0c3ed0dc143dd2fe2b63eAlex Deymo  EXPECT_EQ(1U, observer2.calls_.size());
132a5856e431d7be09dbbde0ab274fdddca868bb269Alex Deymo
133a5856e431d7be09dbbde0ab274fdddca868bb269Alex Deymo  var.RemoveObserver(&observer1);
134a5856e431d7be09dbbde0ab274fdddca868bb269Alex Deymo  var.RemoveObserver(&observer2);
135a5856e431d7be09dbbde0ab274fdddca868bb269Alex Deymo}
136a5856e431d7be09dbbde0ab274fdddca868bb269Alex Deymo
137a5856e431d7be09dbbde0ab274fdddca868bb269Alex Deymoclass BaseVariableObserverRemover : public BaseVariable::ObserverInterface {
138a5856e431d7be09dbbde0ab274fdddca868bb269Alex Deymo public:
139a5856e431d7be09dbbde0ab274fdddca868bb269Alex Deymo  BaseVariableObserverRemover() : calls_(0) {}
140a5856e431d7be09dbbde0ab274fdddca868bb269Alex Deymo
141a5856e431d7be09dbbde0ab274fdddca868bb269Alex Deymo  void ValueChanged(BaseVariable* variable) override {
142a5856e431d7be09dbbde0ab274fdddca868bb269Alex Deymo    for (auto& observer : remove_observers_) {
143a5856e431d7be09dbbde0ab274fdddca868bb269Alex Deymo      variable->RemoveObserver(observer);
144a5856e431d7be09dbbde0ab274fdddca868bb269Alex Deymo    }
145a5856e431d7be09dbbde0ab274fdddca868bb269Alex Deymo    calls_++;
146a5856e431d7be09dbbde0ab274fdddca868bb269Alex Deymo  }
147a5856e431d7be09dbbde0ab274fdddca868bb269Alex Deymo
148a5856e431d7be09dbbde0ab274fdddca868bb269Alex Deymo  void OnCallRemoveObserver(BaseVariable::ObserverInterface* observer) {
149a5856e431d7be09dbbde0ab274fdddca868bb269Alex Deymo    remove_observers_.push_back(observer);
150a5856e431d7be09dbbde0ab274fdddca868bb269Alex Deymo  }
151a5856e431d7be09dbbde0ab274fdddca868bb269Alex Deymo
152a5856e431d7be09dbbde0ab274fdddca868bb269Alex Deymo  int get_calls() { return calls_; }
153a5856e431d7be09dbbde0ab274fdddca868bb269Alex Deymo
154a5856e431d7be09dbbde0ab274fdddca868bb269Alex Deymo private:
155a5856e431d7be09dbbde0ab274fdddca868bb269Alex Deymo  vector<BaseVariable::ObserverInterface*> remove_observers_;
156a5856e431d7be09dbbde0ab274fdddca868bb269Alex Deymo  int calls_;
157a5856e431d7be09dbbde0ab274fdddca868bb269Alex Deymo};
158a5856e431d7be09dbbde0ab274fdddca868bb269Alex Deymo
159a5856e431d7be09dbbde0ab274fdddca868bb269Alex Deymo// Tests that we can remove an observer from a Variable on the ValueChanged()
160a5856e431d7be09dbbde0ab274fdddca868bb269Alex Deymo// call to that observer.
161509dd5376f47e38d18fe7d29da776e3dc9a9786dAlex DeymoTEST_F(UmBaseVariableTest, NotifyValueRemovesObserversTest) {
162a5856e431d7be09dbbde0ab274fdddca868bb269Alex Deymo  DefaultVariable<int> var("var", kVariableModeAsync);
163a5856e431d7be09dbbde0ab274fdddca868bb269Alex Deymo  BaseVariableObserverRemover observer1;
164a5856e431d7be09dbbde0ab274fdddca868bb269Alex Deymo  BaseVariableObserverRemover observer2;
165a5856e431d7be09dbbde0ab274fdddca868bb269Alex Deymo
166a5856e431d7be09dbbde0ab274fdddca868bb269Alex Deymo  var.AddObserver(&observer1);
167a5856e431d7be09dbbde0ab274fdddca868bb269Alex Deymo  var.AddObserver(&observer2);
168a5856e431d7be09dbbde0ab274fdddca868bb269Alex Deymo
169a5856e431d7be09dbbde0ab274fdddca868bb269Alex Deymo  // Make each observer remove both observers on ValueChanged.
170a5856e431d7be09dbbde0ab274fdddca868bb269Alex Deymo  observer1.OnCallRemoveObserver(&observer1);
171a5856e431d7be09dbbde0ab274fdddca868bb269Alex Deymo  observer1.OnCallRemoveObserver(&observer2);
172a5856e431d7be09dbbde0ab274fdddca868bb269Alex Deymo  observer2.OnCallRemoveObserver(&observer1);
173a5856e431d7be09dbbde0ab274fdddca868bb269Alex Deymo  observer2.OnCallRemoveObserver(&observer2);
174a5856e431d7be09dbbde0ab274fdddca868bb269Alex Deymo
175a5856e431d7be09dbbde0ab274fdddca868bb269Alex Deymo  var.NotifyValueChanged();
176509dd5376f47e38d18fe7d29da776e3dc9a9786dAlex Deymo  MessageLoopRunMaxIterations(MessageLoop::current(), 100);
177a5856e431d7be09dbbde0ab274fdddca868bb269Alex Deymo
178a5856e431d7be09dbbde0ab274fdddca868bb269Alex Deymo  EXPECT_EQ(1, observer1.get_calls() + observer2.get_calls());
179a07a1234e8ca7654af91048fccff152ab3db8420Alex Deymo}
180a07a1234e8ca7654af91048fccff152ab3db8420Alex Deymo
18163784a578dd26880454d70797519358a2326291bAlex Deymo}  // namespace chromeos_update_manager
182