/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
 * Copyright (C) 2019, Google Inc.
 *
 * log_process.cpp - Logging in isolated child process test
 */

#include <fcntl.h>
#include <iostream>
#include <random>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <vector>

#include <libcamera/logging.h>

#include <libcamera/base/event_dispatcher.h>
#include <libcamera/base/log.h>
#include <libcamera/base/thread.h>
#include <libcamera/base/timer.h>
#include <libcamera/base/utils.h>

#include "libcamera/internal/process.h"

#include "test.h"

using namespace libcamera;
using namespace std;
using namespace std::chrono_literals;

static const string message("hello from the child");

LOG_DEFINE_CATEGORY(LogProcessTest)

class LogProcessTestChild
{
public:
	int run(int status, int num)
	{
		usleep(50000);

		string logPath = "/tmp/libcamera.worker.test." +
				 to_string(num) + ".log";
		if (logSetFile(logPath.c_str()) < 0)
			return TestSkip;

		LOG(LogProcessTest, Warning) << message;

		return status;
	}
};

class LogProcessTest : public Test
{
protected:
	int init()
	{
		random_device random;
		num_ = random();
		logPath_ = "/tmp/libcamera.worker.test." +
			   to_string(num_) + ".log";

		proc_.finished.connect(this, &LogProcessTest::procFinished);
		return 0;
	}

	int run()
	{
		EventDispatcher *dispatcher = Thread::current()->eventDispatcher();
		Timer timeout;

		int exitCode = 42;
		vector<std::string> args;
		args.push_back(to_string(exitCode));
		args.push_back(to_string(num_));
		int ret = proc_.start(self(), args);
		if (ret) {
			cerr << "failed to start process" << endl;
			return TestFail;
		}

		timeout.start(200ms);
		while (timeout.isRunning())
			dispatcher->processEvents();

		if (exitStatus_ != Process::NormalExit) {
			cerr << "process did not exit normally" << endl;
			return TestFail;
		}

		if (exitCode_ == TestSkip)
			return TestSkip;

		if (exitCode_ != exitCode) {
			cerr << "exit code should be " << exitCode
			     << ", actual is " << exitCode_ << endl;
			return TestFail;
		}

		int fd = open(logPath_.c_str(), O_RDONLY, S_IRUSR);
		if (fd < 0) {
			cerr << "failed to open tmp log file" << endl;
			return TestFail;
		}

		char buf[200];
		memset(buf, 0, sizeof(buf));
		if (read(fd, buf, sizeof(buf)) < 0) {
			cerr << "Failed to read tmp log file" << endl;
			close(fd);
			return TestFail;
		}
		close(fd);

		string str(buf);
		if (str.find(message) == string::npos)
			return TestFail;

		return TestPass;
	}

	void cleanup()
	{
		unlink(logPath_.c_str());
	}

private:
	void procFinished(enum Process::ExitStatus exitStatus, int exitCode)
	{
		exitStatus_ = exitStatus;
		exitCode_ = exitCode;
	}

	ProcessManager processManager_;

	Process proc_;
	Process::ExitStatus exitStatus_;
	string logPath_;
	int exitCode_;
	int num_;
};

/*
 * Can't use TEST_REGISTER() as single binary needs to act as both
 * parent and child processes.
 */
int main(int argc, char **argv)
{
	if (argc == 3) {
		int status = std::stoi(argv[1]);
		int num = std::stoi(argv[2]);
		LogProcessTestChild child;
		return child.run(status, num);
	}

	LogProcessTest test;
	test.setArgs(argc, argv);
	return test.execute();
}
