#include "piprocess.h"
#include "pitime.h"

#include "gtest/gtest.h"


class ProcessTest: public ::testing::Test {
protected:
	PIProcess launcher;
	const PIString command =
#ifdef _WIN32
		"C:/Windows/System32/cmd.exe";
#else
		"/bin/sh";
#endif

	void SetUp() override {
		launcher.enableWriteStdIn(false);
		launcher.enableReadStdOut();
		launcher.enableReadStdErr();
	}

	void TearDown() override {
		if (launcher.isRunning()) {
			launcher.waitForFinish();
		}
	}
};


TEST_F(ProcessTest, Output) {
#ifdef _WIN32
	const PIStringList args = {"/c", "echo Hello from stdout && echo Hello from stderr 1>&2"};
#else
	const PIStringList args = {"-c", "echo Hello from stdout; echo Hello from stderr 1>&2"};
#endif

	launcher.exec(command, args);
	ASSERT_TRUE(launcher.isRunning());

	ASSERT_TRUE(launcher.waitForFinish());
	ASSERT_TRUE(launcher.isExecFinished());

	const auto out = PIString::fromAscii(launcher.readOutput());
	const auto err = PIString::fromAscii(launcher.readError());

	EXPECT_TRUE(out.contains("Hello from stdout"));
	EXPECT_TRUE(err.contains("Hello from stderr"));

	const int exit_code = launcher.exitCode();
	EXPECT_FALSE(launcher.isRunning());

#ifdef _WIN32
	EXPECT_EQ(exit_code, 0);
#else
	EXPECT_TRUE(WIFEXITED(exit_code));
	EXPECT_EQ(WEXITSTATUS(exit_code), 0);
#endif
}


TEST_F(ProcessTest, Input) {
#ifdef _WIN32
	const PIStringList args = {"/c", "more"};
#else
	const PIStringList args = {"-c", "read input; echo $input"};
#endif

	launcher.enableWriteStdIn();
	launcher.exec(command, args);
	ASSERT_TRUE(launcher.isRunning());
	piMSleep(100);
	EXPECT_TRUE(launcher.isExecStarted());
	EXPECT_TRUE(!launcher.isExecFinished());

	PIString test_input = "Test input string\n";
	EXPECT_TRUE(launcher.writeInput(test_input.toAscii()));
	launcher.closeInput();

	ASSERT_TRUE(launcher.waitForFinish());
	EXPECT_TRUE(launcher.isExecFinished());

	const auto out = PIString::fromAscii(launcher.readOutput());
	EXPECT_TRUE(out.contains("Test input string"));
}


TEST_F(ProcessTest, NonexistentCommand) {
	const PIString command = {"nonexistent_command_12345"};

	launcher.enableWriteStdIn(false);
	launcher.enableReadStdOut(false);
	launcher.enableReadStdErr(false);
	launcher.exec(command);
	ASSERT_TRUE(launcher.isRunning());
	ASSERT_TRUE(launcher.waitForFinish());
	EXPECT_FALSE(launcher.isExecFinished());
}
