/*
 * Copyright (C) 2007  Enrico Zini <enrico@enricozini.org>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
 */

#include "tests/test-utils.h"
#include "processrunner.h"
#include <util/output.h>

#include <wibble/sys/mutex.h>
#include <sys/wait.h>
#include <unistd.h>
#include <sstream>
#include <iostream>

namespace tut {
using namespace std;
using namespace util;

struct util_processrunner_shar {
	util_processrunner_shar()
	{
		//util::Output::get().debug(true);
		Starter::get().reset();
		ProcessRunner::reset();
	}
};
TESTGRP(util_processrunner);

struct TestListener : public ProcessListener
{
protected:
	wibble::sys::Mutex mutex;
	
	string m_tag;
	int m_status;
	bool m_fired;

public:
	TestListener() : m_status(-1), m_fired(false) {};

	void handleTermination(const std::string& tag, int status)
	{
		wibble::sys::MutexLock lock(mutex);
		m_tag = tag;
		m_status = status;
		m_fired = true;
	}

	string tag()
	{
		wibble::sys::MutexLock lock(mutex);
		return m_tag;
	}
	int status()
	{
		wibble::sys::MutexLock lock(mutex);
		return m_status;
	}
	bool fired()
	{
		wibble::sys::MutexLock lock(mutex);
		return m_fired;
	}
};

// Check that simple key = val items are parsed correctly
template<> template<>
void to::test<1>()
{
	TestListener ltrue, lfalse;
	vector<string> env;

	Starter& s = Starter::get();

	// Start everything
	s.start();

	// We can add after starting, it will work nicely
	ProcessRunner::get().addProcess("true", "/bin/true", env, &ltrue);
	ProcessRunner::get().addProcess("false", "/bin/false", env, &lfalse);

	// Wait at most 3 seconds until all processes terminate
	unsigned maxwait;
	for (maxwait = 30; !ltrue.fired() && !lfalse.fired() && maxwait > 0; --maxwait)
		usleep(100000);

	// Check that we didn't time out
	ensure(maxwait > 0);

	// Check that we got the right information to the listeners
	ensure_equals(ltrue.tag(), "true");
	ensure_equals(ltrue.status(), 0);

	ensure_equals(lfalse.tag(), "false");
	int status = lfalse.status();
	ensure(WIFEXITED(status));
	ensure(WEXITSTATUS(status) != 0);

	s.stop();
}

}

// vim:set ts=4 sw=4:
