// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "shill/external_task.h"

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

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

#include "shill/event_dispatcher.h"
#include "shill/nice_mock_control.h"
#include "shill/mock_adaptors.h"
#include "shill/mock_glib.h"
#include "shill/mock_process_killer.h"

using std::map;
using std::set;
using std::string;
using std::vector;
using testing::_;
using testing::Matcher;
using testing::MatchesRegex;
using testing::NiceMock;
using testing::Return;
using testing::SetArgumentPointee;
using testing::StrEq;

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_, &glib_, weak_ptr_factory_.GetWeakPtr(),
                             death_callback_)),
        test_rpc_task_destroyed_(false) {
    external_task_->process_killer_ = &process_killer_;
  }

  virtual ~ExternalTaskTest() {}

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

    if (external_task_->child_watch_tag_) {
      EXPECT_CALL(glib_, SourceRemove(external_task_->child_watch_tag_));
    }

    if (external_task_->pid_) {
      EXPECT_CALL(process_killer_, Kill(external_task_->pid_, _));
    }
  }

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

 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 dead_process, int exit_status));

  NiceMockControl control_;
  EventDispatcher dispatcher_;
  MockGLib glib_;
  MockProcessKiller process_killer_;
  base::WeakPtrFactory<ExternalTaskTest> weak_ptr_factory_;
  base::Callback<void(pid_t, int)> death_callback_;
  scoped_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_ = NULL;
}

}  // namespace

TEST_F(ExternalTaskTest, Destructor) {
  const unsigned int kTag = 123;
  external_task_->child_watch_tag_ = kTag;
  EXPECT_CALL(glib_, SourceRemove(kTag));
  const int kPID = 123456;
  external_task_->pid_ = kPID;
  EXPECT_CALL(process_killer_, Kill(kPID, _));
  external_task_->rpc_task_.reset(new TestRPCTask(&control_, this));
  external_task_.reset();
  EXPECT_TRUE(test_rpc_task_destroyed_);
}

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 == NULL) {
      *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"}};
  const vector<string> kExpectedEnv{"SHILL_TASK_SERVICE=.+",
                                    "SHILL_TASK_PATH=.+", "env1=val1",
                                    "env2=val2"};
  const int kPID = 234678;
  EXPECT_CALL(glib_, SpawnAsync(_,
                                HasElementsMatching(kCommandOptions),
                                HasElementsMatching(kExpectedEnv),
                                _, _, _, _, _))
      .WillOnce(Return(false))
      .WillOnce(DoAll(SetArgumentPointee<6>(kPID), Return(true)));
  const int kTag = 6;
  Error error;
  EXPECT_CALL(glib_,
              ChildWatchAdd(
                  kPID, &external_task_->OnTaskDied, external_task_.get()))
      .WillOnce(Return(kTag));
  EXPECT_FALSE(
      external_task_->Start(
          base::FilePath(kCommand), kCommandOptions, kCommandEnv, &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, &error));
  EXPECT_TRUE(error.IsSuccess());
  EXPECT_EQ(kPID, external_task_->pid_);
  EXPECT_EQ(kTag, external_task_->child_watch_tag_);
  EXPECT_TRUE(external_task_->rpc_task_);
}

TEST_F(ExternalTaskTest, Stop) {
  const unsigned int kTag = 123;
  external_task_->child_watch_tag_ = kTag;
  EXPECT_CALL(glib_, SourceRemove(kTag));
  const int kPID = 123456;
  external_task_->pid_ = kPID;
  EXPECT_CALL(process_killer_, Kill(kPID, _));
  external_task_->rpc_task_.reset(new TestRPCTask(&control_, this));
  external_task_->Stop();

  EXPECT_EQ(0, external_task_->child_watch_tag_);
  EXPECT_EQ(0, external_task_->pid_);
  EXPECT_FALSE(external_task_->rpc_task_);
  EXPECT_TRUE(test_rpc_task_destroyed_);
}

TEST_F(ExternalTaskTest, StopNotStarted) {
  EXPECT_CALL(glib_, SourceRemove(_)).Times(0);
  EXPECT_CALL(process_killer_, Kill(_, _)).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_->child_watch_tag_ = 333;
  external_task_->pid_ = kPID;
  EXPECT_CALL(process_killer_, Kill(_, _)).Times(0);
  EXPECT_CALL(*this, TaskDiedCallback(kPID, kExitStatus));
  ExternalTask::OnTaskDied(kPID, kExitStatus, external_task_.get());
  EXPECT_EQ(0, external_task_->child_watch_tag_);
  EXPECT_EQ(0, external_task_->pid_);
}

}  // namespace shill
