//
// Copyright (C) 2012 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 "shill/external_task.h"

#include <map>
#include <memory>
#include <set>
#include <string>
#include <vector>

#include <base/bind.h>
#include <base/files/file_path.h>
#include <base/memory/weak_ptr.h>
#include <base/strings/string_util.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>

#include "shill/mock_adaptors.h"
#include "shill/mock_process_manager.h"
#include "shill/nice_mock_control.h"
#include "shill/test_event_dispatcher.h"

using std::map;
using std::string;
using std::vector;
using testing::_;
using testing::MatchesRegex;
using testing::Mock;
using testing::NiceMock;
using testing::Return;

namespace shill {

class ExternalTaskTest : public testing::Test,
                         public RPCTaskDelegate {
 public:
  ExternalTaskTest()
      : weak_ptr_factory_(this),
        death_callback_(
          base::Bind(&ExternalTaskTest::TaskDiedCallback,
                     weak_ptr_factory_.GetWeakPtr())),
        external_task_(
            new ExternalTask(&control_, &process_manager_,
                             weak_ptr_factory_.GetWeakPtr(),
                             death_callback_)),
        test_rpc_task_destroyed_(false) {}

  virtual ~ExternalTaskTest() {}

  virtual void TearDown() {
    if (!external_task_) {
      return;
    }

    if (external_task_->pid_) {
      EXPECT_CALL(process_manager_, StopProcess(external_task_->pid_));
    }
  }

  void set_test_rpc_task_destroyed(bool destroyed) {
    test_rpc_task_destroyed_ = destroyed;
  }

  // Defined out-of-line, due to dependency on TestRPCTask.
  void FakeUpRunningProcess(unsigned int tag, int pid);

  void ExpectStop(unsigned int tag, int pid) {
    EXPECT_CALL(process_manager_, StopProcess(pid));
  }

  void VerifyStop() {
    if (external_task_) {
      EXPECT_EQ(0, external_task_->pid_);
      EXPECT_FALSE(external_task_->rpc_task_);
    }
    EXPECT_TRUE(test_rpc_task_destroyed_);
    // Make sure EXPECTations were met before the fixture's dtor.
    Mock::VerifyAndClearExpectations(&process_manager_);
  }

 protected:
  // Implements RPCTaskDelegate interface.
  MOCK_METHOD2(GetLogin, void(string* user, string* password));
  MOCK_METHOD2(Notify, void(const string& reason,
                            const map<string, string>& dict));

  MOCK_METHOD2(TaskDiedCallback, void(pid_t pid, int exit_status));

  NiceMockControl control_;
  EventDispatcherForTest dispatcher_;
  MockProcessManager process_manager_;
  base::WeakPtrFactory<ExternalTaskTest> weak_ptr_factory_;
  base::Callback<void(pid_t, int)> death_callback_;
  std::unique_ptr<ExternalTask> external_task_;
  bool test_rpc_task_destroyed_;
};

namespace {

class TestRPCTask : public RPCTask {
 public:
  TestRPCTask(ControlInterface* control, ExternalTaskTest* test);
  virtual ~TestRPCTask();

 private:
  ExternalTaskTest* test_;
};

TestRPCTask::TestRPCTask(ControlInterface* control, ExternalTaskTest* test)
    : RPCTask(control, test),
      test_(test) {
  test_->set_test_rpc_task_destroyed(false);
}

TestRPCTask::~TestRPCTask() {
  test_->set_test_rpc_task_destroyed(true);
  test_ = nullptr;
}

}  // namespace

void ExternalTaskTest::FakeUpRunningProcess(unsigned int tag, int pid) {
  external_task_->pid_ = pid;
  external_task_->rpc_task_.reset(new TestRPCTask(&control_, this));
}

TEST_F(ExternalTaskTest, Destructor) {
  const unsigned int kTag = 123;
  const int kPID = 123456;
  FakeUpRunningProcess(kTag, kPID);
  ExpectStop(kTag, kPID);
  external_task_.reset();
  VerifyStop();
}

TEST_F(ExternalTaskTest, DestroyLater) {
  const unsigned int kTag = 123;
  const int kPID = 123456;
  FakeUpRunningProcess(kTag, kPID);
  ExpectStop(kTag, kPID);
  external_task_.release()->DestroyLater(&dispatcher_);
  dispatcher_.DispatchPendingEvents();
  VerifyStop();
}

namespace {

// Returns true iff. there is at least one anchored match in |arg|,
// for each item in |expected_values|. Order of items does not matter.
//
// |arg| is a NULL-terminated array of C-strings.
// |expected_values| is a container of regular expressions (as strings).
MATCHER_P(HasElementsMatching, expected_values, "") {
  for (const auto& expected_value : expected_values) {
    auto regex_matcher(MatchesRegex(expected_value).impl());
    char** arg_local = arg;
    while (*arg_local) {
      if (regex_matcher.MatchAndExplain(*arg_local, result_listener)) {
        break;
      }
      ++arg_local;
    }
    if (*arg_local == nullptr) {
      *result_listener << "missing value " << expected_value << "\n";
      arg_local = arg;
      while (*arg_local) {
        *result_listener << "received: " << *arg_local << "\n";
        ++arg_local;
      }
      return false;
    }
  }
  return true;
}

}  // namespace

TEST_F(ExternalTaskTest, Start) {
  const string kCommand = "/run/me";
  const vector<string> kCommandOptions{"arg1", "arg2"};
  const map<string, string> kCommandEnv{{"env1", "val1"}, {"env2", "val2"}};
  map<string, string> expected_env;
  expected_env.emplace(kRPCTaskServiceVariable, RPCTaskMockAdaptor::kRpcConnId);
  expected_env.emplace(kRPCTaskPathVariable, RPCTaskMockAdaptor::kRpcId);
  expected_env.insert(kCommandEnv.begin(), kCommandEnv.end());
  const int kPID = 234678;
  EXPECT_CALL(process_manager_,
              StartProcess(_, base::FilePath(kCommand), kCommandOptions,
                           expected_env, false, _))
      .WillOnce(Return(-1))
      .WillOnce(Return(kPID));
  Error error;
  EXPECT_FALSE(external_task_->Start(
      base::FilePath(kCommand), kCommandOptions, kCommandEnv, false, &error));
  EXPECT_EQ(Error::kInternalError, error.type());
  EXPECT_FALSE(external_task_->rpc_task_);

  error.Reset();
  EXPECT_TRUE(external_task_->Start(
      base::FilePath(kCommand), kCommandOptions, kCommandEnv, false, &error));
  EXPECT_TRUE(error.IsSuccess());
  EXPECT_EQ(kPID, external_task_->pid_);
  EXPECT_NE(nullptr, external_task_->rpc_task_);
}

TEST_F(ExternalTaskTest, Stop) {
  const unsigned int kTag = 123;
  const int kPID = 123456;
  FakeUpRunningProcess(kTag, kPID);
  ExpectStop(kTag, kPID);
  external_task_->Stop();
  ASSERT_NE(nullptr, external_task_);
  VerifyStop();
}

TEST_F(ExternalTaskTest, StopNotStarted) {
  EXPECT_CALL(process_manager_, StopProcess(_)).Times(0);
  external_task_->Stop();
  EXPECT_FALSE(test_rpc_task_destroyed_);
}

TEST_F(ExternalTaskTest, GetLogin) {
  string username;
  string password;
  EXPECT_CALL(*this, GetLogin(&username, &password));
  EXPECT_CALL(*this, Notify(_, _)).Times(0);
  external_task_->GetLogin(&username, &password);
}

TEST_F(ExternalTaskTest, Notify) {
  const string kReason("you may already have won!");
  const map<string, string>& kArgs{
    {"arg1", "val1"},
    {"arg2", "val2"}};
  EXPECT_CALL(*this, GetLogin(_, _)).Times(0);
  EXPECT_CALL(*this, Notify(kReason, kArgs));
  external_task_->Notify(kReason, kArgs);
}

TEST_F(ExternalTaskTest, OnTaskDied) {
  const int kPID = 99999;
  const int kExitStatus = 1;
  external_task_->pid_ = kPID;
  EXPECT_CALL(process_manager_, StopProcess(_)).Times(0);
  EXPECT_CALL(*this, TaskDiedCallback(kPID, kExitStatus));
  external_task_->OnTaskDied(kExitStatus);
  EXPECT_EQ(0, external_task_->pid_);
}

}  // namespace shill
