//
// Copyright (C) 2014 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

#include "update_engine/update_manager/variable.h"

#include <vector>

#include <brillo/message_loops/fake_message_loop.h>
#include <brillo/message_loops/message_loop.h>
#include <brillo/message_loops/message_loop_utils.h>
#include <gtest/gtest.h>

using base::TimeDelta;
using brillo::MessageLoop;
using brillo::MessageLoopRunMaxIterations;
using std::string;
using std::vector;

namespace chromeos_update_manager {

// Variable class that returns a value constructed with the default value.
template <typename T>
class DefaultVariable : public Variable<T> {
 public:
  DefaultVariable(const string& name, VariableMode mode)
      : Variable<T>(name, mode) {}
  DefaultVariable(const string& name, const TimeDelta& poll_interval)
      : Variable<T>(name, poll_interval) {}
  ~DefaultVariable() override {}

 protected:
  const T* GetValue(TimeDelta /* timeout */,
                    string* /* errmsg */) override {
    return new T();
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(DefaultVariable);
};

class UmBaseVariableTest : public ::testing::Test {
 protected:
  void SetUp() override {
    loop_.SetAsCurrent();
  }

  brillo::FakeMessageLoop loop_{nullptr};
};

TEST_F(UmBaseVariableTest, GetNameTest) {
  DefaultVariable<int> var("var", kVariableModeConst);
  EXPECT_EQ(var.GetName(), string("var"));
}

TEST_F(UmBaseVariableTest, GetModeTest) {
  DefaultVariable<int> var("var", kVariableModeConst);
  EXPECT_EQ(var.GetMode(), kVariableModeConst);
  DefaultVariable<int> other_var("other_var", kVariableModePoll);
  EXPECT_EQ(other_var.GetMode(), kVariableModePoll);
}

TEST_F(UmBaseVariableTest, DefaultPollIntervalTest) {
  DefaultVariable<int> const_var("const_var", kVariableModeConst);
  EXPECT_EQ(const_var.GetPollInterval(), TimeDelta());
  DefaultVariable<int> poll_var("poll_var", kVariableModePoll);
  EXPECT_EQ(poll_var.GetPollInterval(), TimeDelta::FromMinutes(5));
}

TEST_F(UmBaseVariableTest, GetPollIntervalTest) {
  DefaultVariable<int> var("var", TimeDelta::FromMinutes(3));
  EXPECT_EQ(var.GetMode(), kVariableModePoll);
  EXPECT_EQ(var.GetPollInterval(), TimeDelta::FromMinutes(3));
}

class BaseVariableObserver : public BaseVariable::ObserverInterface {
 public:
  void ValueChanged(BaseVariable* variable) {
    calls_.push_back(variable);
  }

  // List of called functions.
  vector<BaseVariable*> calls_;
};

TEST_F(UmBaseVariableTest, RepeatedObserverTest) {
  DefaultVariable<int> var("var", kVariableModeAsync);
  BaseVariableObserver observer;
  var.AddObserver(&observer);
  EXPECT_EQ(var.observer_list_.size(), 1);
  var.AddObserver(&observer);
  EXPECT_EQ(var.observer_list_.size(), 1);
  var.RemoveObserver(&observer);
  EXPECT_EQ(var.observer_list_.size(), 0);
  var.RemoveObserver(&observer);
  EXPECT_EQ(var.observer_list_.size(), 0);
}

TEST_F(UmBaseVariableTest, NotifyValueChangedTest) {
  DefaultVariable<int> var("var", kVariableModeAsync);
  BaseVariableObserver observer1;
  var.AddObserver(&observer1);
  // Simulate a value change on the variable's implementation.
  var.NotifyValueChanged();
  ASSERT_EQ(0, observer1.calls_.size());
  MessageLoopRunMaxIterations(MessageLoop::current(), 100);

  ASSERT_EQ(1, observer1.calls_.size());
  // Check that the observer is called with the right argument.
  EXPECT_EQ(&var, observer1.calls_[0]);

  BaseVariableObserver observer2;
  var.AddObserver(&observer2);
  var.NotifyValueChanged();
  MessageLoopRunMaxIterations(MessageLoop::current(), 100);

  // Check that all the observers are called.
  EXPECT_EQ(2, observer1.calls_.size());
  EXPECT_EQ(1, observer2.calls_.size());

  var.RemoveObserver(&observer1);
  var.RemoveObserver(&observer2);
}

class BaseVariableObserverRemover : public BaseVariable::ObserverInterface {
 public:
  BaseVariableObserverRemover() : calls_(0) {}

  void ValueChanged(BaseVariable* variable) override {
    for (auto& observer : remove_observers_) {
      variable->RemoveObserver(observer);
    }
    calls_++;
  }

  void OnCallRemoveObserver(BaseVariable::ObserverInterface* observer) {
    remove_observers_.push_back(observer);
  }

  int get_calls() { return calls_; }

 private:
  vector<BaseVariable::ObserverInterface*> remove_observers_;
  int calls_;
};

// Tests that we can remove an observer from a Variable on the ValueChanged()
// call to that observer.
TEST_F(UmBaseVariableTest, NotifyValueRemovesObserversTest) {
  DefaultVariable<int> var("var", kVariableModeAsync);
  BaseVariableObserverRemover observer1;
  BaseVariableObserverRemover observer2;

  var.AddObserver(&observer1);
  var.AddObserver(&observer2);

  // Make each observer remove both observers on ValueChanged.
  observer1.OnCallRemoveObserver(&observer1);
  observer1.OnCallRemoveObserver(&observer2);
  observer2.OnCallRemoveObserver(&observer1);
  observer2.OnCallRemoveObserver(&observer2);

  var.NotifyValueChanged();
  MessageLoopRunMaxIterations(MessageLoop::current(), 100);

  EXPECT_EQ(1, observer1.get_calls() + observer2.get_calls());
}

}  // namespace chromeos_update_manager
