// Copyright (c) 2012 The Chromium 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 <windows.h>

#include <string>

#include "base/command_line.h"
#include "base/process/kill.h"
#include "base/test/multiprocess_test.h"
#include "base/win/scoped_process_information.h"
#include "testing/multiprocess_func_list.h"

namespace {

const DWORD kProcessId = 4321;
const DWORD kThreadId = 1234;
const HANDLE kProcessHandle = reinterpret_cast<HANDLE>(7651);
const HANDLE kThreadHandle = reinterpret_cast<HANDLE>(1567);

void MockCreateProcess(base::win::ScopedProcessInformation* process_info) {
  PROCESS_INFORMATION process_information = {};
  process_information.dwProcessId = kProcessId;
  process_information.dwThreadId = kThreadId;
  process_information.hProcess = kProcessHandle;
  process_information.hThread = kThreadHandle;
  process_info->Set(process_information);
}

}  // namespace

class ScopedProcessInformationTest : public base::MultiProcessTest {
 protected:
  void DoCreateProcess(const std::string& main_id,
                       PROCESS_INFORMATION* process_handle);
};

MULTIPROCESS_TEST_MAIN(ReturnSeven) {
  return 7;
}

MULTIPROCESS_TEST_MAIN(ReturnNine) {
  return 9;
}

void ScopedProcessInformationTest::DoCreateProcess(
    const std::string& main_id, PROCESS_INFORMATION* process_handle) {
  std::wstring cmd_line = MakeCmdLine(main_id).GetCommandLineString();
  STARTUPINFO startup_info = {};
  startup_info.cb = sizeof(startup_info);

  EXPECT_TRUE(::CreateProcess(NULL, &cmd_line[0],
                              NULL, NULL, false, 0, NULL, NULL,
                              &startup_info, process_handle));
}

TEST_F(ScopedProcessInformationTest, InitiallyInvalid) {
  base::win::ScopedProcessInformation process_info;
  ASSERT_FALSE(process_info.IsValid());
}

TEST_F(ScopedProcessInformationTest, Receive) {
  base::win::ScopedProcessInformation process_info;
  MockCreateProcess(&process_info);

  EXPECT_TRUE(process_info.IsValid());
  EXPECT_EQ(kProcessId, process_info.process_id());
  EXPECT_EQ(kThreadId, process_info.thread_id());
  EXPECT_EQ(kProcessHandle, process_info.process_handle());
  EXPECT_EQ(kThreadHandle, process_info.thread_handle());
  process_info.Take();
}

TEST_F(ScopedProcessInformationTest, TakeProcess) {
  base::win::ScopedProcessInformation process_info;
  MockCreateProcess(&process_info);

  HANDLE process = process_info.TakeProcessHandle();
  EXPECT_EQ(kProcessHandle, process);
  EXPECT_EQ(NULL, process_info.process_handle());
  EXPECT_EQ(0, process_info.process_id());
  EXPECT_TRUE(process_info.IsValid());
  process_info.Take();
}

TEST_F(ScopedProcessInformationTest, TakeThread) {
  base::win::ScopedProcessInformation process_info;
  MockCreateProcess(&process_info);

  HANDLE thread = process_info.TakeThreadHandle();
  EXPECT_EQ(kThreadHandle, thread);
  EXPECT_EQ(NULL, process_info.thread_handle());
  EXPECT_EQ(0, process_info.thread_id());
  EXPECT_TRUE(process_info.IsValid());
  process_info.Take();
}

TEST_F(ScopedProcessInformationTest, TakeBoth) {
  base::win::ScopedProcessInformation process_info;
  MockCreateProcess(&process_info);

  process_info.TakeProcessHandle();
  process_info.TakeThreadHandle();
  EXPECT_FALSE(process_info.IsValid());
  process_info.Take();
}

TEST_F(ScopedProcessInformationTest, TakeWholeStruct) {
  base::win::ScopedProcessInformation process_info;
  MockCreateProcess(&process_info);

  PROCESS_INFORMATION to_discard = process_info.Take();
  EXPECT_EQ(kProcessId, to_discard.dwProcessId);
  EXPECT_EQ(kThreadId, to_discard.dwThreadId);
  EXPECT_EQ(kProcessHandle, to_discard.hProcess);
  EXPECT_EQ(kThreadHandle, to_discard.hThread);
  EXPECT_FALSE(process_info.IsValid());
}

TEST_F(ScopedProcessInformationTest, Duplicate) {
  PROCESS_INFORMATION temp_process_information;
  DoCreateProcess("ReturnSeven", &temp_process_information);
  base::win::ScopedProcessInformation process_info;
  process_info.Set(temp_process_information);

  base::win::ScopedProcessInformation duplicate;
  duplicate.DuplicateFrom(process_info);

  ASSERT_TRUE(process_info.IsValid());
  ASSERT_NE(0u, process_info.process_id());
  ASSERT_EQ(duplicate.process_id(), process_info.process_id());
  ASSERT_NE(0u, process_info.thread_id());
  ASSERT_EQ(duplicate.thread_id(), process_info.thread_id());

  // Validate that we have separate handles that are good.
  int exit_code = 0;
  ASSERT_TRUE(base::WaitForExitCode(process_info.TakeProcessHandle(),
                                    &exit_code));
  ASSERT_EQ(7, exit_code);

  exit_code = 0;
  ASSERT_TRUE(base::WaitForExitCode(duplicate.TakeProcessHandle(),
                                    &exit_code));
  ASSERT_EQ(7, exit_code);

  ASSERT_TRUE(::CloseHandle(process_info.TakeThreadHandle()));
  ASSERT_TRUE(::CloseHandle(duplicate.TakeThreadHandle()));
}

TEST_F(ScopedProcessInformationTest, Set) {
  base::win::ScopedProcessInformation base_process_info;
  MockCreateProcess(&base_process_info);

  PROCESS_INFORMATION base_struct = base_process_info.Take();

  base::win::ScopedProcessInformation process_info;
  process_info.Set(base_struct);

  EXPECT_EQ(kProcessId, process_info.process_id());
  EXPECT_EQ(kThreadId, process_info.thread_id());
  EXPECT_EQ(kProcessHandle, process_info.process_handle());
  EXPECT_EQ(kThreadHandle, process_info.thread_handle());
  base_struct = process_info.Take();
}
