<commit_before>// -----------------------------------------------------------------------
// pion-common: a collection of common libraries used by the Pion Platform
// -----------------------------------------------------------------------
// Copyright (C) 2007-2009 Atomic Labs, Inc.  (http://www.atomiclabs.com)
//
// Distributed under the Boost Software License, Version 1.0.
// See http://www.boost.org/LICENSE_1_0.txt
//

#ifndef __PION_PIONID_HEADER__
#define __PION_PIONID_HEADER__

#include <string>
#include <limits>
#include <ctime>
#include <cstring>
#include <cstdlib>
#include <boost/functional/hash.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/random/uniform_int.hpp>
#include <boost/random/variate_generator.hpp>
#include <boost/random/mersenne_twister.hpp>
#include <pion/PionConfig.hpp>

namespace pion {	// begin namespace pion

///
/// PionId: a random-number based universally unique identifier (UUID v4)
///
class PionId {
public:

	/// data type for iterating PionId byte values
	typedef unsigned char *			iterator;

	/// const data type for iterating PionId byte values
	typedef const unsigned char *	const_iterator;

	enum {
		PION_ID_DATA_BYTES = 16,			//< total number of data bytes
		PION_ID_HEX_BYTES = 16 * 2 + 4		//< number of bytes in hexadecimal representation
	};

	/// class may be extended (virtual destructor)
	virtual ~PionId() {}

	/// default constructor
	PionId(void) {
		typedef boost::mt19937 gen_type;
		typedef boost::uniform_int<unsigned long> dist_type;
		typedef boost::variate_generator<gen_type,dist_type> die_type;
		gen_type rng_gen(PionId::make_seed());
		dist_type rng_dist((std::numeric_limits<unsigned long>::min)(), (std::numeric_limits<unsigned long>::max)());
		die_type rng_die(rng_gen, rng_dist);
		generate(m_data, rng_die);
	}

	/// construction using a string representation (bb49b9ca-e733-47c0-9a26-0f8f53ea1660)
	explicit PionId(const std::string& str) {
		from_string(str.c_str());
	}

	/// construction using a null-terminated c-style string (bb49b9ca-e733-47c0-9a26-0f8f53ea1660)
	explicit PionId(const char *str) {
		from_string(str);
	}

	/// construction using an existing random number generator
	template<typename base_generator_type, typename distribution_type>
	explicit PionId(boost::variate_generator<base_generator_type, distribution_type>& rng) {
		generate(m_data, rng);
	}

	/// copy constructor
	PionId(const PionId& id) {
		memcpy(m_data, id.m_data, PION_ID_DATA_BYTES);
	}

	/// assignment operator
	PionId& operator=(const PionId& id) {
		memcpy(m_data, id.m_data, PION_ID_DATA_BYTES);
		return *this;
	}

	/// returns id value at byte offset
	inline unsigned char operator[](const std::size_t n) const {
		return m_data[n];
	}

	/// returns true if id equals this
	inline bool operator==(const PionId& id) const {
		return (memcmp(m_data, id.m_data, PION_ID_DATA_BYTES) == 0);
	}

	/// returns true if id does not equal this
	inline bool operator!=(const PionId& id) const {
		return (memcmp(m_data, id.m_data, PION_ID_DATA_BYTES) != 0);
	}

	/// returns true if id is less than this
	inline bool operator<(const PionId& id) const {
		return (memcmp(m_data, id.m_data, PION_ID_DATA_BYTES) < 0);
	}

	/// returns true if id is greater than this
	inline bool operator>(const PionId& id) const {
		return (memcmp(m_data, id.m_data, PION_ID_DATA_BYTES) > 0);
	}

	/// returns the beginning iterator
	inline iterator begin(void) { return m_data; }

	/// returns the ending iterator
	inline iterator end(void) { return m_data + PION_ID_DATA_BYTES; }

	/// returns the beginning iterator (const)
	inline const_iterator begin(void) const { return m_data; }

	/// returns the ending iterator (const)
	inline const_iterator end(void) const { return m_data + PION_ID_DATA_BYTES; }

	/// returns hexadecimal representation as a string (bb49b9ca-e733-47c0-9a26-0f8f53ea1660)
	inline std::string to_string(void) const {
		std::string hex_str;
		static const char hex[] = "0123456789abcdef";
		for (std::size_t i = 0; i < PION_ID_DATA_BYTES; i++) {
			hex_str += hex[m_data[i] >> 4];
			hex_str += hex[m_data[i] & 0x0f];
			if (i == 3 || i == 5 || i == 7 || i == 9)
				hex_str += '-';
		}
		return hex_str;
	}

	/// sets the data value based upon a null-terminated string representation (bb49b9ca-e733-47c0-9a26-0f8f53ea1660)
	void from_string(const char *str) {
		std::size_t data_pos = 0;
		char buf[3];
		buf[2] = '\0';
		while (*str != '\0' && data_pos < PION_ID_DATA_BYTES) {
			if (isxdigit(*str)) {
				buf[0] = *str;
				if (*(++str) == '\0' || !isxdigit(*str))	// sanity check
					break;
				buf[1] = *str;
				m_data[data_pos++] = strtoul(buf, NULL, 16);
			}
			++str;
		}
	}

	/// return a seed value for random number generators
	static inline boost::uint64_t make_seed(void) {
		// this could be much better...  and is probably far too trivial...
		boost::uint64_t seed = boost::posix_time::microsec_clock::local_time().time_of_day().total_microseconds();
		seed += (time(NULL) * 1000000);
		return seed;
	}

protected:

	/**
	 * generates a new data value using an existing random number generator
	 *
	 * @param data pointer to a data buffer that is PION_ID_DATA_BYTES in size
	 * @param rng initialized random number generator
	 */
	template<typename base_generator_type, typename distribution_type>
	static inline void generate(unsigned char *data, boost::variate_generator<base_generator_type, distribution_type>& rng) {
		// Note: this code is adapted from the Boost UUID library, (c) 2006 Andy Tompkins
		for (std::size_t i = 0; i < PION_ID_DATA_BYTES; i += sizeof(unsigned long)) {
            *reinterpret_cast<unsigned long*>(&data[i]) = rng();
		}

        // set variant
        // should be 0b10xxxxxx
        data[8] &= 0xBF;
        data[8] |= 0x80;

        // set version
        // should be 0b0100xxxx
        data[6] &= 0x4F; //0b01001111
        data[6] |= 0x40; //0b01000000
	}

	/// sequence of bytes representing the unique identifier
	unsigned char	m_data[PION_ID_DATA_BYTES];
};

/// returns hash value for a PionId object (used by boost::hash_map)
static inline std::size_t hash_value(const PionId& id) {
	std::size_t seed = 0;
	const unsigned char * data = id.begin();
	const unsigned char * const end = id.end();
	while (data < end) {
		boost::hash_combine(seed, *reinterpret_cast<const unsigned long*>(data));
		data += sizeof(unsigned long);
	}
	return seed;
}

///
/// PionIdGeneratorBase: class used to generated new PionId's
///
template <typename BaseGeneratorType>
class PionIdGeneratorBase {
public:

	/// make dynamic type for base generator available
	typedef BaseGeneratorType	base_generator_type;

	/// random number distribution type
	typedef boost::uniform_int<unsigned long>	distribution_type;

	/// random number generator type
	typedef boost::variate_generator<base_generator_type, distribution_type>	gen_type;

	/// class may be extended (virtual destructor)
	virtual ~PionIdGeneratorBase() {}

	/// default constructor
	PionIdGeneratorBase(void)
		: m_random_gen(PionId::make_seed()),
		m_random_dist((std::numeric_limits<unsigned long>::min)(), (std::numeric_limits<unsigned long>::max)()),
		m_random_die(m_random_gen, m_random_dist)
	{}

	/// returns a newly generated PionId object
	inline PionId operator()(void) { return PionId(m_random_die); }

	/// return random number generator
	inline gen_type& getRNG(void) { return m_random_die; }

	/// return random number generator
	inline unsigned long getNumber(void) { return m_random_die(); }

protected:

	/// random number generator
	base_generator_type				m_random_gen;

	/// random number distribution
	distribution_type				m_random_dist;

	/// random number die
	gen_type						m_random_die;
};

/// data type for the default PionId generator class
typedef PionIdGeneratorBase<boost::mt19937>	PionIdGenerator;

}	// end namespace pion

#endif
<commit_msg>http://trac.atomiclabs.com/ticket/515<commit_after>// -----------------------------------------------------------------------
// pion-common: a collection of common libraries used by the Pion Platform
// -----------------------------------------------------------------------
// Copyright (C) 2007-2009 Atomic Labs, Inc.  (http://www.atomiclabs.com)
//
// Distributed under the Boost Software License, Version 1.0.
// See http://www.boost.org/LICENSE_1_0.txt
//

#ifndef __PION_PIONID_HEADER__
#define __PION_PIONID_HEADER__

#include <string>
#include <limits>
#include <ctime>
#include <cstring>
#include <cstdlib>
#include <boost/functional/hash.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/random/uniform_int.hpp>
#include <boost/random/variate_generator.hpp>
#include <boost/random/mersenne_twister.hpp>
#include <pion/PionConfig.hpp>

namespace pion {	// begin namespace pion

///
/// PionId: a random-number based universally unique identifier (UUID v4)
///
class PionId {
public:

	/// data type for iterating PionId byte values
	typedef unsigned char *			iterator;

	/// const data type for iterating PionId byte values
	typedef const unsigned char *	const_iterator;

	enum {
		PION_ID_DATA_BYTES = 16,			//< total number of data bytes
		PION_ID_HEX_BYTES = 16 * 2 + 4		//< number of bytes in hexadecimal representation
	};

	/// class may be extended (virtual destructor)
	virtual ~PionId() {}

	/// default constructor
	PionId(void) {
		typedef boost::mt19937 gen_type;
		typedef boost::uniform_int<unsigned long> dist_type;
		typedef boost::variate_generator<gen_type,dist_type> die_type;
		gen_type rng_gen(PionId::make_seed());
		dist_type rng_dist((std::numeric_limits<unsigned long>::min)(), (std::numeric_limits<unsigned long>::max)());
		die_type rng_die(rng_gen, rng_dist);
		generate(m_data, rng_die);
	}

	/// construction using a string representation (bb49b9ca-e733-47c0-9a26-0f8f53ea1660)
	explicit PionId(const std::string& str) {
		from_string(str.c_str());
	}

	/// construction using a null-terminated c-style string (bb49b9ca-e733-47c0-9a26-0f8f53ea1660)
	explicit PionId(const char *str) {
		from_string(str);
	}

	/// construction using an existing random number generator
	template<typename base_generator_type, typename distribution_type>
	explicit PionId(boost::variate_generator<base_generator_type, distribution_type>& rng) {
		generate(m_data, rng);
	}

	/// copy constructor
	PionId(const PionId& id) {
		memcpy(m_data, id.m_data, PION_ID_DATA_BYTES);
	}

	/// assignment operator
	PionId& operator=(const PionId& id) {
		memcpy(m_data, id.m_data, PION_ID_DATA_BYTES);
		return *this;
	}

	/// returns id value at byte offset
	inline unsigned char operator[](const std::size_t n) const {
		return m_data[n];
	}

	/// returns true if id equals this
	inline bool operator==(const PionId& id) const {
		return (memcmp(m_data, id.m_data, PION_ID_DATA_BYTES) == 0);
	}

	/// returns true if id does not equal this
	inline bool operator!=(const PionId& id) const {
		return (memcmp(m_data, id.m_data, PION_ID_DATA_BYTES) != 0);
	}

	/// returns true if id is less than this
	inline bool operator<(const PionId& id) const {
		return (memcmp(m_data, id.m_data, PION_ID_DATA_BYTES) < 0);
	}

	/// returns true if id is greater than this
	inline bool operator>(const PionId& id) const {
		return (memcmp(m_data, id.m_data, PION_ID_DATA_BYTES) > 0);
	}

	/// returns the beginning iterator
	inline iterator begin(void) { return m_data; }

	/// returns the ending iterator
	inline iterator end(void) { return m_data + PION_ID_DATA_BYTES; }

	/// returns the beginning iterator (const)
	inline const_iterator begin(void) const { return m_data; }

	/// returns the ending iterator (const)
	inline const_iterator end(void) const { return m_data + PION_ID_DATA_BYTES; }

	/// returns hexadecimal representation as a string (bb49b9ca-e733-47c0-9a26-0f8f53ea1660)
	inline std::string to_string(void) const {
		std::string hex_str;
		static const char hex[] = "0123456789abcdef";
		for (std::size_t i = 0; i < PION_ID_DATA_BYTES; i++) {
			hex_str += hex[m_data[i] >> 4];
			hex_str += hex[m_data[i] & 0x0f];
			if (i == 3 || i == 5 || i == 7 || i == 9)
				hex_str += '-';
		}
		return hex_str;
	}

	/// sets the data value based upon a null-terminated string representation (bb49b9ca-e733-47c0-9a26-0f8f53ea1660)
	void from_string(const char *str) {
		std::size_t data_pos = 0;
		char buf[3];
		buf[2] = '\0';
		while (*str != '\0' && data_pos < PION_ID_DATA_BYTES) {
			if (isxdigit(*str)) {
				buf[0] = *str;
				if (*(++str) == '\0' || !isxdigit(*str))	// sanity check
					break;
				buf[1] = *str;
				m_data[data_pos++] = strtoul(buf, NULL, 16);
			}
			++str;
		}
	}

	/// return a seed value for random number generators
	static inline boost::uint32_t make_seed(void) {
		// this could probably be much better, but trying to KISS...
		typedef boost::mt19937 gen_type;
		typedef boost::uniform_int<unsigned long> dist_type;
		typedef boost::variate_generator<gen_type,dist_type> die_type;
		// initialize a static generator with seed based upon system time
		static gen_type rng_gen( (time(NULL) * 1000000) + boost::posix_time::microsec_clock::local_time().time_of_day().total_microseconds() );
		static dist_type rng_dist((std::numeric_limits<unsigned long>::min)(), (std::numeric_limits<unsigned long>::max)());
		static die_type rng_die(rng_gen, rng_dist);
		// use the static rng to produce seed values that initialize other generators
		return rng_die();
	}

protected:

	/**
	 * generates a new data value using an existing random number generator
	 *
	 * @param data pointer to a data buffer that is PION_ID_DATA_BYTES in size
	 * @param rng initialized random number generator
	 */
	template<typename base_generator_type, typename distribution_type>
	static inline void generate(unsigned char *data, boost::variate_generator<base_generator_type, distribution_type>& rng) {
		// Note: this code is adapted from the Boost UUID library, (c) 2006 Andy Tompkins
		for (std::size_t i = 0; i < PION_ID_DATA_BYTES; i += sizeof(unsigned long)) {
            *reinterpret_cast<unsigned long*>(&data[i]) = rng();
		}

        // set variant
        // should be 0b10xxxxxx
        data[8] &= 0xBF;
        data[8] |= 0x80;

        // set version
        // should be 0b0100xxxx
        data[6] &= 0x4F; //0b01001111
        data[6] |= 0x40; //0b01000000
	}

	/// sequence of bytes representing the unique identifier
	unsigned char	m_data[PION_ID_DATA_BYTES];
};

/// returns hash value for a PionId object (used by boost::hash_map)
static inline std::size_t hash_value(const PionId& id) {
	std::size_t seed = 0;
	const unsigned char * data = id.begin();
	const unsigned char * const end = id.end();
	while (data < end) {
		boost::hash_combine(seed, *reinterpret_cast<const unsigned long*>(data));
		data += sizeof(unsigned long);
	}
	return seed;
}

///
/// PionIdGeneratorBase: class used to generated new PionId's
///
template <typename BaseGeneratorType>
class PionIdGeneratorBase {
public:

	/// make dynamic type for base generator available
	typedef BaseGeneratorType	base_generator_type;

	/// random number distribution type
	typedef boost::uniform_int<unsigned long>	distribution_type;

	/// random number generator type
	typedef boost::variate_generator<base_generator_type, distribution_type>	gen_type;

	/// class may be extended (virtual destructor)
	virtual ~PionIdGeneratorBase() {}

	/// default constructor
	PionIdGeneratorBase(void)
		: m_random_gen(PionId::make_seed()),
		m_random_dist((std::numeric_limits<unsigned long>::min)(), (std::numeric_limits<unsigned long>::max)()),
		m_random_die(m_random_gen, m_random_dist)
	{}

	/// returns a newly generated PionId object
	inline PionId operator()(void) { return PionId(m_random_die); }

	/// return random number generator
	inline gen_type& getRNG(void) { return m_random_die; }

	/// return random number generator
	inline unsigned long getNumber(void) { return m_random_die(); }

protected:

	/// random number generator
	base_generator_type				m_random_gen;

	/// random number distribution
	distribution_type				m_random_dist;

	/// random number die
	gen_type						m_random_die;
};

/// data type for the default PionId generator class
typedef PionIdGeneratorBase<boost::mt19937>	PionIdGenerator;

}	// end namespace pion

#endif
<|endoftext|>


<commit_before>#include "seen_table.h"

#include <boost/assert.hpp>
#include <string.h>

void mue::Seen_table::add_meeting(Team_id id_1, Team_id id_2, Team_id id_3) noexcept
{
	_update_table(id_1, id_2, id_3);
	_update_table(id_2, id_3, id_1);
	_update_table(id_3, id_1, id_2);
}

mue::Seen_table::Seen_table(Seen_table const &old, int new_generation) noexcept
:
	_generation(new_generation),
	_max_teams(old._max_teams)
{
	memcpy(_table, old._table, sizeof(*_table) * MAX_TEAMS);
}

mue::Seen_table::Seen_table(Seen_table&& other) noexcept
:
	_generation(std::move(other._generation)),
	_max_teams(std::move(other._max_teams)),
	_table(std::move(other._table))
{ }

mue::Seen_table::Seen_table(int max_teams) noexcept
:
	_generation(0),
	_max_teams(max_teams)
{
	BOOST_ASSERT(max_teams <= MAX_TEAMS);

	for (int i = 0; i < max_teams; ++i) {
		_table[i].reset();
	}

	if (_id_bitsets.empty()) {
		for (int i = 0; i < MAX_TEAMS; ++i) {
			_id_bitsets.push_back(0x01LL << i);
		}
	}
}

std::vector<mue::Seen_table::Seen_bitset> mue::Seen_table::_id_bitsets;
<commit_msg>Remove mmecpy from seen_table<commit_after>#include "seen_table.h"

#include <boost/assert.hpp>
#include <string.h>

void mue::Seen_table::add_meeting(Team_id id_1, Team_id id_2, Team_id id_3) noexcept
{
	_update_table(id_1, id_2, id_3);
	_update_table(id_2, id_3, id_1);
	_update_table(id_3, id_1, id_2);
}

mue::Seen_table::Seen_table(Seen_table const &old, int new_generation) noexcept
:
	_generation(new_generation),
	_max_teams(old._max_teams),
	_table(old._table)
{ }

mue::Seen_table::Seen_table(Seen_table&& other) noexcept
:
	_generation(std::move(other._generation)),
	_max_teams(std::move(other._max_teams)),
	_table(std::move(other._table))
{ }

mue::Seen_table::Seen_table(int max_teams) noexcept
:
	_generation(0),
	_max_teams(max_teams)
{
	BOOST_ASSERT(max_teams <= MAX_TEAMS);

	for (int i = 0; i < max_teams; ++i) {
		_table[i].reset();
	}

	if (_id_bitsets.empty()) {
		for (int i = 0; i < MAX_TEAMS; ++i) {
			_id_bitsets.push_back(0x01LL << i);
		}
	}
}

std::vector<mue::Seen_table::Seen_bitset> mue::Seen_table::_id_bitsets;
<|endoftext|>


<commit_before>/**
 * Copyright 2008 Matthew Graham
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "testpp.h"
#include "shession_store.h"
#include <set>

/**
 * Test that the shession_constructor sets members to the proper default
 * values.
 */
TESTPP( test_shession_constructor )
{
	shession_c sh( "dog" );

	assertpp( sh.shession_id() ) == "dog";
	assertpp( sh.user_id() ) == "";
	assertpp( sh.expiration() ) == 0;
	assertpp( sh.expired( 5 ) ).t();
}

/**
 * Test that the constructor with the user ID works as expected.
 */
TESTPP( test_shession_user_id_constructor )
{
	shession_c sh( "dog", "cat" );

	assertpp( sh.shession_id() ) == "dog";
	assertpp( sh.user_id() ) == "cat";
	assertpp( sh.expiration() ) == 0;
	assertpp( sh.expired( 4 ) ).t();
}

/**
 * Test that the expiration functionality works.
 */
TESTPP( test_shession_expiration )
{
	shession_c sh( "dog" );

	sh.expire_at( 5 );
	assertpp( sh.expired( 4 ) ).f();
	assertpp( sh.expired( 5 ) ).t(); // should expire at the given time
	assertpp( sh.expired( 6 ) ).t();
}

/**
 * A mock timer class for injecting into the shession_store
 * for testing expiration.
 */
class mock_timer_c
: public shession_store_c::timer_c
{
public:
	/**
	 * Construct the timer, starting at 0
	 */
	mock_timer_c()
	: m_seconds( 0 )
	{}
	/**
	 * Return the constant number of seconds.
	 */
	virtual time_t now() const
	{
		return m_seconds;
	}
	/**
	 * Add time to this timer.
	 */
	virtual void operator += ( time_t seconds )
	{
		m_seconds += seconds;
	}

private:
	time_t m_seconds;
};

/**
 * Test 4 basic sessions to make sure they can be added and killed
 * and things work as expected.
 */
TESTPP( test_storing_4_sessions )
{
	shession_store_c store( 1 );

	const char *sid_1 = "dog";
	const char *sid_2 = "cat";
	const char *sid_3 = "mouse";
	const char *sid_4 = "flea";
	std::string empty;

	store.create( sid_1, empty );
	store.create( sid_2, empty );
	store.create( sid_3, empty );
	store.create( sid_4, empty );

	assertpp( store.renew( sid_1 ) ).t();
	assertpp( store.renew( sid_2 ) ).t();
	assertpp( store.renew( sid_3 ) ).t();
	assertpp( store.renew( sid_4 ) ).t();

	store.kill( sid_1 );
	store.kill( sid_2 );
	store.kill( sid_3 );
	store.kill( sid_4 );

	assertpp( store.renew( sid_1 ) ).f();
	assertpp( store.renew( sid_2 ) ).f();
	assertpp( store.renew( sid_3 ) ).f();
	assertpp( store.renew( sid_4 ) ).f();
}

/**
 * Test that expiration works as expected.
 */
TESTPP( test_expiration )
{
	shession_store_c store( 5 );
	mock_timer_c mock_timer;
	store.set_timer( mock_timer );

	const char *sid_1 = "dog";
	const char *sid_2 = "cat";
	const char *sid_3 = "mouse";
	const char *sid_4 = "flea";
	std::string user_id;

	store.create( sid_1, user_id );
	store.create( sid_2, user_id );
	store.create( sid_3, user_id );
	store.create( sid_4, user_id );

	mock_timer += 3;
	assertpp( store.renew( sid_4 ) ).t();

	mock_timer += 4;
	assertpp( store.renew( sid_4 ) ).t();
	assertpp( store.size() ) == 4;
	assertpp( store.renew( sid_1 ) ).f();
	assertpp( store.size() ) == 3;
	assertpp( store.kill_expired() ) == 2;
	assertpp( store.size() ) == 1;

	mock_timer += 4;
	assertpp( store.renew( sid_4 ) ).t();
}

/**
 * Test the live function on the shession_store class.
 */
TESTPP( test_shession_store_live )
{
	shession_store_c store( 5 );
	mock_timer_c mock_timer;
	store.set_timer( mock_timer );

	store.create( "dog", "cat" );
	mock_timer += 2;
	assertpp( store.live( "dog" ) ).t();

	mock_timer += 10;
	assertpp( store.live( "dog" ) ).f();
}

/**
 * Test that mirroring works correctly for creation.
 */
TESTPP( test_store_mirror_creation )
{
	shession_store_c store( 60 );

	store.mirror( "dog", "cat" );

	assertpp( store.live( "dog" ) ).t();
}

/**
 * Test that mirroring works correctly for renewal.
 */
TESTPP( test_store_mirror_renewal )
{
	shession_store_c store( 5 );
	mock_timer_c mock_timer;
	store.set_timer( mock_timer );

	store.mirror( "dog", "cat" );
	mock_timer += 3;
	store.mirror( "dog", "cat" );
	mock_timer += 4;

	assertpp( store.live( "dog" ) ).t();
}

/**
 * Test that const iteration works.
 */
TESTPP( test_const_iteration )
{
	shession_store_c store( 5 );
	store.create( "dog", "user1" );
	store.create( "cat", "user2" );
	store.create( "mouse", "user3" );
	std::set< std::string > found;

	const_shession_iterator_c it( store.begin() );
	for ( ; it!=store.end(); ++it ) {
		found.insert( it->shession_id() );
	}

	assertpp( found.find( "dog" ) != found.end() ).t();
	assertpp( found.find( "cat" ) != found.end() ).t();
	assertpp( found.find( "mouse" ) != found.end() ).t();
}

/**
 * Test that non-const iteration works.
 */
TESTPP( test_nonconst_iteration )
{
}

<commit_msg>added tests to verify the different permutations of constness between shession_store & iterator.<commit_after>/**
 * Copyright 2008 Matthew Graham
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "testpp.h"
#include "shession_store.h"
#include <set>

/**
 * Test that the shession_constructor sets members to the proper default
 * values.
 */
TESTPP( test_shession_constructor )
{
	shession_c sh( "dog" );

	assertpp( sh.shession_id() ) == "dog";
	assertpp( sh.user_id() ) == "";
	assertpp( sh.expiration() ) == 0;
	assertpp( sh.expired( 5 ) ).t();
}

/**
 * Test that the constructor with the user ID works as expected.
 */
TESTPP( test_shession_user_id_constructor )
{
	shession_c sh( "dog", "cat" );

	assertpp( sh.shession_id() ) == "dog";
	assertpp( sh.user_id() ) == "cat";
	assertpp( sh.expiration() ) == 0;
	assertpp( sh.expired( 4 ) ).t();
}

/**
 * Test that the expiration functionality works.
 */
TESTPP( test_shession_expiration )
{
	shession_c sh( "dog" );

	sh.expire_at( 5 );
	assertpp( sh.expired( 4 ) ).f();
	assertpp( sh.expired( 5 ) ).t(); // should expire at the given time
	assertpp( sh.expired( 6 ) ).t();
}

/**
 * A mock timer class for injecting into the shession_store
 * for testing expiration.
 */
class mock_timer_c
: public shession_store_c::timer_c
{
public:
	/**
	 * Construct the timer, starting at 0
	 */
	mock_timer_c()
	: m_seconds( 0 )
	{}
	/**
	 * Return the constant number of seconds.
	 */
	virtual time_t now() const
	{
		return m_seconds;
	}
	/**
	 * Add time to this timer.
	 */
	virtual void operator += ( time_t seconds )
	{
		m_seconds += seconds;
	}

private:
	time_t m_seconds;
};

/**
 * Test 4 basic sessions to make sure they can be added and killed
 * and things work as expected.
 */
TESTPP( test_storing_4_sessions )
{
	shession_store_c store( 1 );

	const char *sid_1 = "dog";
	const char *sid_2 = "cat";
	const char *sid_3 = "mouse";
	const char *sid_4 = "flea";
	std::string empty;

	store.create( sid_1, empty );
	store.create( sid_2, empty );
	store.create( sid_3, empty );
	store.create( sid_4, empty );

	assertpp( store.renew( sid_1 ) ).t();
	assertpp( store.renew( sid_2 ) ).t();
	assertpp( store.renew( sid_3 ) ).t();
	assertpp( store.renew( sid_4 ) ).t();

	store.kill( sid_1 );
	store.kill( sid_2 );
	store.kill( sid_3 );
	store.kill( sid_4 );

	assertpp( store.renew( sid_1 ) ).f();
	assertpp( store.renew( sid_2 ) ).f();
	assertpp( store.renew( sid_3 ) ).f();
	assertpp( store.renew( sid_4 ) ).f();
}

/**
 * Test that expiration works as expected.
 */
TESTPP( test_expiration )
{
	shession_store_c store( 5 );
	mock_timer_c mock_timer;
	store.set_timer( mock_timer );

	const char *sid_1 = "dog";
	const char *sid_2 = "cat";
	const char *sid_3 = "mouse";
	const char *sid_4 = "flea";
	std::string user_id;

	store.create( sid_1, user_id );
	store.create( sid_2, user_id );
	store.create( sid_3, user_id );
	store.create( sid_4, user_id );

	mock_timer += 3;
	assertpp( store.renew( sid_4 ) ).t();

	mock_timer += 4;
	assertpp( store.renew( sid_4 ) ).t();
	assertpp( store.size() ) == 4;
	assertpp( store.renew( sid_1 ) ).f();
	assertpp( store.size() ) == 3;
	assertpp( store.kill_expired() ) == 2;
	assertpp( store.size() ) == 1;

	mock_timer += 4;
	assertpp( store.renew( sid_4 ) ).t();
}

/**
 * Test the live function on the shession_store class.
 */
TESTPP( test_shession_store_live )
{
	shession_store_c store( 5 );
	mock_timer_c mock_timer;
	store.set_timer( mock_timer );

	store.create( "dog", "cat" );
	mock_timer += 2;
	assertpp( store.live( "dog" ) ).t();

	mock_timer += 10;
	assertpp( store.live( "dog" ) ).f();
}

/**
 * Test that mirroring works correctly for creation.
 */
TESTPP( test_store_mirror_creation )
{
	shession_store_c store( 60 );

	store.mirror( "dog", "cat" );

	assertpp( store.live( "dog" ) ).t();
}

/**
 * Test that mirroring works correctly for renewal.
 */
TESTPP( test_store_mirror_renewal )
{
	shession_store_c store( 5 );
	mock_timer_c mock_timer;
	store.set_timer( mock_timer );

	store.mirror( "dog", "cat" );
	mock_timer += 3;
	store.mirror( "dog", "cat" );
	mock_timer += 4;

	assertpp( store.live( "dog" ) ).t();
}

/**
 * Test that const iteration works when called on a const store.
 */
TESTPP( test_const_store_const_iteration )
{
	shession_store_c store( 5 );
	store.create( "dog", "user1" );
	store.create( "cat", "user2" );
	store.create( "mouse", "user3" );
	std::set< std::string > found;
	const shession_store_c &cstore( store );

	const_shession_iterator_c it( cstore.begin() );
	for ( ; it!=cstore.end(); ++it ) {
		found.insert( it->shession_id() );
	}

	assertpp( found.find( "dog" ) != found.end() ).t();
	assertpp( found.find( "cat" ) != found.end() ).t();
	assertpp( found.find( "mouse" ) != found.end() ).t();
}

/**
 * Test that const iteration works when called on a non-const store.
 */
TESTPP( test_store_const_iteration )
{
	shession_store_c store( 5 );
	store.create( "dog", "user1" );
	store.create( "cat", "user2" );
	store.create( "mouse", "user3" );
	std::set< std::string > found;

	const_shession_iterator_c it( store.begin() );
	for ( ; it!=store.end(); ++it ) {
		found.insert( it->shession_id() );
	}

	assertpp( found.find( "dog" ) != found.end() ).t();
	assertpp( found.find( "cat" ) != found.end() ).t();
	assertpp( found.find( "mouse" ) != found.end() ).t();
}

/**
 * Test that non-const iteration works.
 */
TESTPP( test_store_iteration )
{
	shession_store_c store( 5 );
	store.create( "dog", "user1" );
	store.create( "cat", "user2" );
	store.create( "mouse", "user3" );
	std::set< std::string > found;

	shession_iterator_c it( store.begin() );
	for ( ; it!=store.end(); ++it ) {
		found.insert( it->shession_id() );
	}

	assertpp( found.find( "dog" ) != found.end() ).t();
	assertpp( found.find( "cat" ) != found.end() ).t();
	assertpp( found.find( "mouse" ) != found.end() ).t();
}

<|endoftext|>


<commit_before>/*!
 * \page FQTTestSuite_cpp Command-Line Test to Demonstrate How To Test the SimFQT Project
 * \code
 */
// //////////////////////////////////////////////////////////////////////
// Import section
// //////////////////////////////////////////////////////////////////////
// STL
#include <sstream>
#include <fstream>
#include <string>
// Boost Unit Test Framework (UTF)
#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MAIN
#define BOOST_TEST_MODULE FQTTestSuite
#include <boost/test/unit_test.hpp>
// StdAir
#include <stdair/basic/BasLogParams.hpp>
#include <stdair/basic/BasDBParams.hpp>
#include <stdair/basic/BasFileMgr.hpp>
#include <stdair/service/Logger.hpp>
#include <stdair/bom/TravelSolutionStruct.hpp>
#include <stdair/bom/BookingRequestStruct.hpp>
// SimFQT
#include <simfqt/SIMFQT_Service.hpp>
#include <simfqt/config/simfqt-paths.hpp>

namespace boost_utf = boost::unit_test;

/**
 * Configuration for the Boost Unit Test Framework (UTF)
 */
struct UnitTestConfig {
  /** Constructor. */
  UnitTestConfig() {
    static std::ofstream _test_log ("FQTTestSuite_utfresults.xml");
    boost_utf::unit_test_log.set_stream (_test_log);
    boost_utf::unit_test_log.set_format (boost_utf::XML);
    boost_utf::unit_test_log.set_threshold_level (boost_utf::log_test_units);
    //boost_utf::unit_test_log.set_threshold_level (boost_utf::log_successful_tests);
  }

  /** Destructor. */
  ~UnitTestConfig() {
  }
};

// //////////////////////////////////////////////////////////////////////
/**
 * Build and fareQuote a default list of travel solutions
 */
void testFareQuoterHelper (const unsigned short iTestFlag,
                           const stdair::Filename_T iFareInputFilename,
                           const bool isBuiltin) {

  // Output log File
  std::ostringstream oStr;
  oStr << "FQTTestSuite_" << iTestFlag << ".log";
  const stdair::Filename_T lLogFilename (oStr.str());

  // Set the log parameters
  std::ofstream logOutputFile;
  // Open and clean the log outputfile
  logOutputFile.open (lLogFilename.c_str());
  logOutputFile.clear();

  // Initialise the SimFQT service object
  const stdair::BasLogParams lLogParams (stdair::LOG::DEBUG,
                                         logOutputFile);

  // Initialise the Simfqt service object
  SIMFQT::SIMFQT_Service simfqtService (lLogParams);

  // Check wether or not a (CSV) input file should be read
  if (isBuiltin == true) {

    // Build the default sample BOM tree (filled with fares) for Simfqt
    simfqtService.buildSampleBom();

  } else {

    // Build the BOM tree from parsing the fare input file
    SIMFQT::FareFilePath lFareFilePath (iFareInputFilename);
    simfqtService.parseAndLoad (lFareFilePath);
  }

  // Build a sample list of travel solutions and a booking request.
  stdair::TravelSolutionList_T lTravelSolutionList;
  simfqtService.buildSampleTravelSolutions (lTravelSolutionList);
  stdair::BookingRequestStruct lBookingRequest =
    simfqtService.buildBookingRequest();

  // Try to fareQuote the sample list of travel solutions
  simfqtService.quotePrices (lBookingRequest, lTravelSolutionList);

  // Close the log file
  logOutputFile.close();

}

// /////////////// Main: Unit Test Suite //////////////

// Set the UTF configuration (re-direct the output to a specific file)
BOOST_GLOBAL_FIXTURE (UnitTestConfig);

// Start the test suite
BOOST_AUTO_TEST_SUITE (master_test_suite)

/**
 * Test a simple price quotation
 */
BOOST_AUTO_TEST_CASE (simfqt_simple_pricing_test) {

  // Input file name
  const stdair::Filename_T lFareInputFilename (STDAIR_SAMPLE_DIR "/fare01.csv");

  // State whether the BOM tree should be built-in or parsed from an input file
  const bool isBuiltin = false;

  // Try to fareQuote the sample default list of travel solutions
  BOOST_CHECK_NO_THROW (testFareQuoterHelper (0, lFareInputFilename, isBuiltin));

}

/**
 * Test an error detection functionality
 * Expected to throw SIMFQT::AirportPairNotFoundException
 */
BOOST_AUTO_TEST_CASE (simfqt_error_pricing_test_01) {

  // Input file name
  const stdair::Filename_T lFareInputFilename (STDAIR_SAMPLE_DIR "/fareError01.csv");

  // State whether the BOM tree should be built-in or parsed from an input file
  const bool isBuiltin = false;

  // Try to fareQuote the sample default list of travel solutions
  BOOST_CHECK_THROW (testFareQuoterHelper (1, lFareInputFilename, isBuiltin),
                     SIMFQT::AirportPairNotFoundException);
}

/**
 * Test an error detection functionality
 * Expected to throw SIMFQT::PosOrChannelNotFoundException
 */
BOOST_AUTO_TEST_CASE (simfqt_error_pricing_test_02) {

  // Input file name
  const stdair::Filename_T lFareInputFilename (STDAIR_SAMPLE_DIR "/fareError02.csv");

  // State whether the BOM tree should be built-in or parsed from an input file
  const bool isBuiltin = false;

  // Try to fareQuote the sample default list of travel solutions
  BOOST_CHECK_THROW (testFareQuoterHelper (2, lFareInputFilename, isBuiltin),
                     SIMFQT::PosOrChannelNotFoundException);
}

/**
 * Test an error detection functionality
 * Expected to throw SIMFQT::FlightDateNotFoundException
 */
BOOST_AUTO_TEST_CASE (simfqt_error_pricing_test_03) {

  // Input file name
  const stdair::Filename_T lFareInputFilename (STDAIR_SAMPLE_DIR "/fareError03.csv");

  // State whether the BOM tree should be built-in or parsed from an input file
  const bool isBuiltin = false;

  // Try to fareQuote the sample default list of travel solutions
  BOOST_CHECK_THROW (testFareQuoterHelper (3, lFareInputFilename, isBuiltin),
                     SIMFQT::FlightDateNotFoundException);
}

/**
 * Test an error detection functionality
 * Expected to throw SIMFQT::FlightTimeNotFoundException
 */
BOOST_AUTO_TEST_CASE (simfqt_error_pricing_test_04) {

  // Input file name
  const stdair::Filename_T lFareInputFilename (STDAIR_SAMPLE_DIR "/fareError04.csv");

  // State whether the BOM tree should be built-in or parsed from an input file
  const bool isBuiltin = false;

  // Try to fareQuote the sample default list of travel solutions
  BOOST_CHECK_THROW (testFareQuoterHelper (4, lFareInputFilename, isBuiltin),
                     SIMFQT::FlightTimeNotFoundException);
}

/**
 * Test an error detection functionality
 * Expected to throw SIMFQT::FeaturesNotFoundException
 */
BOOST_AUTO_TEST_CASE (simfqt_error_pricing_test_05) {

  // Input file name
  const stdair::Filename_T lFareInputFilename (STDAIR_SAMPLE_DIR "/fareError05.csv");

  // State whether the BOM tree should be built-in or parsed from an input file
  const bool isBuiltin = false;

  // Try to fareQuote the sample default list of travel solutions
  BOOST_CHECK_THROW (testFareQuoterHelper (5, lFareInputFilename, isBuiltin),
                     SIMFQT::FeaturesNotFoundException);
}

/**
 * Test an error detection functionality
 * Expected to throw SIMFQT::AirlineNotFoundException
 */
BOOST_AUTO_TEST_CASE (simfqt_error_pricing_test_06) {

  // Input file name
  const stdair::Filename_T lFareInputFilename (STDAIR_SAMPLE_DIR "/fareError06.csv");

  // State whether the BOM tree should be built-in or parsed from an input file
  const bool isBuiltin = false;

  // Try to fareQuote the sample default list of travel solutions
  BOOST_CHECK_THROW (testFareQuoterHelper (6, lFareInputFilename, isBuiltin),
                     SIMFQT::AirlineNotFoundException);
}

/**
 * Test an error detection functionality
 * Expected to throw SIMFQT::FareFileParsingFailedException
 */
BOOST_AUTO_TEST_CASE (simfqt_error_pricing_test_07) {

  // Input file name
  const stdair::Filename_T lFareInputFilename (STDAIR_SAMPLE_DIR "/fareError07.csv");

  // State whether the BOM tree should be built-in or parsed from an input file
  const bool isBuiltin = false;

  // Try to fareQuote the sample default list of travel solutions
  BOOST_CHECK_THROW (testFareQuoterHelper (7, lFareInputFilename, isBuiltin),
                     SIMFQT::FareFileParsingFailedException);
}

/**
 * Test an error detection functionality
 * Expected to throw SIMFQT::FareInputFileNotFoundException
 */
BOOST_AUTO_TEST_CASE (simfqt_error_pricing_test_08) {

  // Input file name
  const stdair::Filename_T lFareInputFilename (STDAIR_SAMPLE_DIR "/missingFile.csv");

  // State whether the BOM tree should be built-in or parsed from an input file
  const bool isBuiltin = false;

  // Try to fareQuote the sample default list of travel solutions
  BOOST_CHECK_THROW (testFareQuoterHelper (8, lFareInputFilename, isBuiltin),
                     SIMFQT::FareInputFileNotFoundException);
}

/**
 * Test a simple price quotation using the default BOM tree
 * This test corresponds to the "-b" option of the batch.
 */
BOOST_AUTO_TEST_CASE (simfqt_error_pricing_test_09) {

  // Input file name
  const stdair::Filename_T lEmptyInputFilename (STDAIR_SAMPLE_DIR "/ ");

  // State whether the BOM tree should be built-in or parsed from an input file
  const bool isBuiltin = true;

  // Try to fareQuote the sample default list of travel solutions
  BOOST_CHECK_NO_THROW(testFareQuoterHelper (9, lEmptyInputFilename, isBuiltin));
}

// End the test suite
BOOST_AUTO_TEST_SUITE_END()

/*!
 * \endcode
 */
<commit_msg>[Test] Fixed a Boost UTF compatibility issue<commit_after>/*!
 * \page FQTTestSuite_cpp Command-Line Test to Demonstrate How To Test the SimFQT Project
 * \code
 */
// //////////////////////////////////////////////////////////////////////
// Import section
// //////////////////////////////////////////////////////////////////////
// STL
#include <sstream>
#include <fstream>
#include <string>
// Boost Unit Test Framework (UTF)
#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MAIN
#define BOOST_TEST_MODULE FQTTestSuite
#include <boost/test/unit_test.hpp>
// StdAir
#include <stdair/basic/BasLogParams.hpp>
#include <stdair/basic/BasDBParams.hpp>
#include <stdair/basic/BasFileMgr.hpp>
#include <stdair/service/Logger.hpp>
#include <stdair/bom/TravelSolutionStruct.hpp>
#include <stdair/bom/BookingRequestStruct.hpp>
// SimFQT
#include <simfqt/SIMFQT_Service.hpp>
#include <simfqt/config/simfqt-paths.hpp>

namespace boost_utf = boost::unit_test;

/**
 * Configuration for the Boost Unit Test Framework (UTF)
 */
struct UnitTestConfig {
  /** Constructor. */
  UnitTestConfig() {
    static std::ofstream _test_log ("FQTTestSuite_utfresults.xml");
    boost_utf::unit_test_log.set_stream (_test_log);
#if defined(BOOST_VERSION) && BOOST_VERSION >= 105900
    boost_utf::unit_test_log.set_format (boost_utf::OF_XML);
#else // BOOST_VERSION
    boost_utf::unit_test_log.set_format (boost_utf::XML);
#endif // BOOST_VERSION
    boost_utf::unit_test_log.set_threshold_level (boost_utf::log_test_units);
    //boost_utf::unit_test_log.set_threshold_level (boost_utf::log_successful_tests);
  }

  /** Destructor. */
  ~UnitTestConfig() {
  }
};

// //////////////////////////////////////////////////////////////////////
/**
 * Build and fareQuote a default list of travel solutions
 */
void testFareQuoterHelper (const unsigned short iTestFlag,
                           const stdair::Filename_T iFareInputFilename,
                           const bool isBuiltin) {

  // Output log File
  std::ostringstream oStr;
  oStr << "FQTTestSuite_" << iTestFlag << ".log";
  const stdair::Filename_T lLogFilename (oStr.str());

  // Set the log parameters
  std::ofstream logOutputFile;
  // Open and clean the log outputfile
  logOutputFile.open (lLogFilename.c_str());
  logOutputFile.clear();

  // Initialise the SimFQT service object
  const stdair::BasLogParams lLogParams (stdair::LOG::DEBUG,
                                         logOutputFile);

  // Initialise the Simfqt service object
  SIMFQT::SIMFQT_Service simfqtService (lLogParams);

  // Check wether or not a (CSV) input file should be read
  if (isBuiltin == true) {

    // Build the default sample BOM tree (filled with fares) for Simfqt
    simfqtService.buildSampleBom();

  } else {

    // Build the BOM tree from parsing the fare input file
    SIMFQT::FareFilePath lFareFilePath (iFareInputFilename);
    simfqtService.parseAndLoad (lFareFilePath);
  }

  // Build a sample list of travel solutions and a booking request.
  stdair::TravelSolutionList_T lTravelSolutionList;
  simfqtService.buildSampleTravelSolutions (lTravelSolutionList);
  stdair::BookingRequestStruct lBookingRequest =
    simfqtService.buildBookingRequest();

  // Try to fareQuote the sample list of travel solutions
  simfqtService.quotePrices (lBookingRequest, lTravelSolutionList);

  // Close the log file
  logOutputFile.close();

}

// /////////////// Main: Unit Test Suite //////////////

// Set the UTF configuration (re-direct the output to a specific file)
BOOST_GLOBAL_FIXTURE (UnitTestConfig);

// Start the test suite
BOOST_AUTO_TEST_SUITE (master_test_suite)

/**
 * Test a simple price quotation
 */
BOOST_AUTO_TEST_CASE (simfqt_simple_pricing_test) {

  // Input file name
  const stdair::Filename_T lFareInputFilename (STDAIR_SAMPLE_DIR "/fare01.csv");

  // State whether the BOM tree should be built-in or parsed from an input file
  const bool isBuiltin = false;

  // Try to fareQuote the sample default list of travel solutions
  BOOST_CHECK_NO_THROW (testFareQuoterHelper (0, lFareInputFilename, isBuiltin));

}

/**
 * Test an error detection functionality
 * Expected to throw SIMFQT::AirportPairNotFoundException
 */
BOOST_AUTO_TEST_CASE (simfqt_error_pricing_test_01) {

  // Input file name
  const stdair::Filename_T lFareInputFilename (STDAIR_SAMPLE_DIR "/fareError01.csv");

  // State whether the BOM tree should be built-in or parsed from an input file
  const bool isBuiltin = false;

  // Try to fareQuote the sample default list of travel solutions
  BOOST_CHECK_THROW (testFareQuoterHelper (1, lFareInputFilename, isBuiltin),
                     SIMFQT::AirportPairNotFoundException);
}

/**
 * Test an error detection functionality
 * Expected to throw SIMFQT::PosOrChannelNotFoundException
 */
BOOST_AUTO_TEST_CASE (simfqt_error_pricing_test_02) {

  // Input file name
  const stdair::Filename_T lFareInputFilename (STDAIR_SAMPLE_DIR "/fareError02.csv");

  // State whether the BOM tree should be built-in or parsed from an input file
  const bool isBuiltin = false;

  // Try to fareQuote the sample default list of travel solutions
  BOOST_CHECK_THROW (testFareQuoterHelper (2, lFareInputFilename, isBuiltin),
                     SIMFQT::PosOrChannelNotFoundException);
}

/**
 * Test an error detection functionality
 * Expected to throw SIMFQT::FlightDateNotFoundException
 */
BOOST_AUTO_TEST_CASE (simfqt_error_pricing_test_03) {

  // Input file name
  const stdair::Filename_T lFareInputFilename (STDAIR_SAMPLE_DIR "/fareError03.csv");

  // State whether the BOM tree should be built-in or parsed from an input file
  const bool isBuiltin = false;

  // Try to fareQuote the sample default list of travel solutions
  BOOST_CHECK_THROW (testFareQuoterHelper (3, lFareInputFilename, isBuiltin),
                     SIMFQT::FlightDateNotFoundException);
}

/**
 * Test an error detection functionality
 * Expected to throw SIMFQT::FlightTimeNotFoundException
 */
BOOST_AUTO_TEST_CASE (simfqt_error_pricing_test_04) {

  // Input file name
  const stdair::Filename_T lFareInputFilename (STDAIR_SAMPLE_DIR "/fareError04.csv");

  // State whether the BOM tree should be built-in or parsed from an input file
  const bool isBuiltin = false;

  // Try to fareQuote the sample default list of travel solutions
  BOOST_CHECK_THROW (testFareQuoterHelper (4, lFareInputFilename, isBuiltin),
                     SIMFQT::FlightTimeNotFoundException);
}

/**
 * Test an error detection functionality
 * Expected to throw SIMFQT::FeaturesNotFoundException
 */
BOOST_AUTO_TEST_CASE (simfqt_error_pricing_test_05) {

  // Input file name
  const stdair::Filename_T lFareInputFilename (STDAIR_SAMPLE_DIR "/fareError05.csv");

  // State whether the BOM tree should be built-in or parsed from an input file
  const bool isBuiltin = false;

  // Try to fareQuote the sample default list of travel solutions
  BOOST_CHECK_THROW (testFareQuoterHelper (5, lFareInputFilename, isBuiltin),
                     SIMFQT::FeaturesNotFoundException);
}

/**
 * Test an error detection functionality
 * Expected to throw SIMFQT::AirlineNotFoundException
 */
BOOST_AUTO_TEST_CASE (simfqt_error_pricing_test_06) {

  // Input file name
  const stdair::Filename_T lFareInputFilename (STDAIR_SAMPLE_DIR "/fareError06.csv");

  // State whether the BOM tree should be built-in or parsed from an input file
  const bool isBuiltin = false;

  // Try to fareQuote the sample default list of travel solutions
  BOOST_CHECK_THROW (testFareQuoterHelper (6, lFareInputFilename, isBuiltin),
                     SIMFQT::AirlineNotFoundException);
}

/**
 * Test an error detection functionality
 * Expected to throw SIMFQT::FareFileParsingFailedException
 */
BOOST_AUTO_TEST_CASE (simfqt_error_pricing_test_07) {

  // Input file name
  const stdair::Filename_T lFareInputFilename (STDAIR_SAMPLE_DIR "/fareError07.csv");

  // State whether the BOM tree should be built-in or parsed from an input file
  const bool isBuiltin = false;

  // Try to fareQuote the sample default list of travel solutions
  BOOST_CHECK_THROW (testFareQuoterHelper (7, lFareInputFilename, isBuiltin),
                     SIMFQT::FareFileParsingFailedException);
}

/**
 * Test an error detection functionality
 * Expected to throw SIMFQT::FareInputFileNotFoundException
 */
BOOST_AUTO_TEST_CASE (simfqt_error_pricing_test_08) {

  // Input file name
  const stdair::Filename_T lFareInputFilename (STDAIR_SAMPLE_DIR "/missingFile.csv");

  // State whether the BOM tree should be built-in or parsed from an input file
  const bool isBuiltin = false;

  // Try to fareQuote the sample default list of travel solutions
  BOOST_CHECK_THROW (testFareQuoterHelper (8, lFareInputFilename, isBuiltin),
                     SIMFQT::FareInputFileNotFoundException);
}

/**
 * Test a simple price quotation using the default BOM tree
 * This test corresponds to the "-b" option of the batch.
 */
BOOST_AUTO_TEST_CASE (simfqt_error_pricing_test_09) {

  // Input file name
  const stdair::Filename_T lEmptyInputFilename (STDAIR_SAMPLE_DIR "/ ");

  // State whether the BOM tree should be built-in or parsed from an input file
  const bool isBuiltin = true;

  // Try to fareQuote the sample default list of travel solutions
  BOOST_CHECK_NO_THROW(testFareQuoterHelper (9, lEmptyInputFilename, isBuiltin));
}

// End the test suite
BOOST_AUTO_TEST_SUITE_END()

/*!
 * \endcode
 */
<|endoftext|>


<commit_before><commit_msg>enum/namespace foo<commit_after><|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: XMLBitmapRepeatOffsetPropertyHandler.cxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-17 10:48:36 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    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
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_xmloff.hxx"

#ifndef _XMLOFF_XMLTOKEN_HXX
#include "xmltoken.hxx"
#endif

#ifndef _XMLOFF_XMLUCONV_HXX
#include "xmluconv.hxx"
#endif

#ifndef _RTL_USTRBUF_HXX_
#include <rtl/ustrbuf.hxx>
#endif

#ifndef _COM_SUN_STAR_UNO_ANY_HXX_
#include <com/sun/star/uno/Any.hxx>
#endif

#ifndef _XMLOFF_XMLBITMAPREPEATOFFSETPROPERTYHANDLER_HXX
#include "XMLBitmapRepeatOffsetPropertyHandler.hxx"
#endif

using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using namespace ::rtl;

using ::xmloff::token::GetXMLToken;
using ::xmloff::token::XML_VERTICAL;
using ::xmloff::token::XML_HORIZONTAL;

XMLBitmapRepeatOffsetPropertyHandler::XMLBitmapRepeatOffsetPropertyHandler( sal_Bool bX )
:   mbX( bX ),
    msVertical( GetXMLToken(XML_VERTICAL) ),
    msHorizontal( GetXMLToken(XML_HORIZONTAL) )
{
}

XMLBitmapRepeatOffsetPropertyHandler::~XMLBitmapRepeatOffsetPropertyHandler()
{
}

sal_Bool XMLBitmapRepeatOffsetPropertyHandler::importXML(
    const OUString& rStrImpValue,
    Any& rValue,
    const SvXMLUnitConverter& ) const
{
    SvXMLTokenEnumerator aTokenEnum( rStrImpValue );
    OUString aToken;
    if( aTokenEnum.getNextToken( aToken ) )
    {
        sal_Int32 nValue;
        if( SvXMLUnitConverter::convertPercent( nValue, aToken ) )
        {
            if( aTokenEnum.getNextToken( aToken ) )
            {
                if( ( mbX && ( aToken == msHorizontal ) ) || ( !mbX && ( aToken == msVertical ) ) )
                {
                    rValue <<= nValue;
                    return sal_True;
                }
            }
        }
    }

    return sal_False;

}

sal_Bool XMLBitmapRepeatOffsetPropertyHandler::exportXML(
    OUString& rStrExpValue,
    const Any& rValue,
    const SvXMLUnitConverter& ) const
{
    OUStringBuffer aOut;

    sal_Int32 nValue;
    if( rValue >>= nValue )
    {
        SvXMLUnitConverter::convertPercent( aOut, nValue );
        aOut.append( sal_Unicode( ' ' ) );
        aOut.append( mbX ? msHorizontal : msVertical );
        rStrExpValue = aOut.makeStringAndClear();

        return sal_True;
    }

    return sal_False;
}

<commit_msg>INTEGRATION: CWS pj65 (1.5.30); FILE MERGED 2006/10/31 14:03:59 pjanik 1.5.30.1: #i71027#: prevent warnings on Mac OS X with gcc 4.0.1.<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: XMLBitmapRepeatOffsetPropertyHandler.cxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: vg $ $Date: 2006-11-21 17:36:15 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    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
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_xmloff.hxx"

#ifndef _XMLOFF_XMLTOKEN_HXX
#include "xmltoken.hxx"
#endif

#ifndef _XMLOFF_XMLUCONV_HXX
#include "xmluconv.hxx"
#endif

#ifndef _RTL_USTRBUF_HXX_
#include <rtl/ustrbuf.hxx>
#endif

#ifndef _COM_SUN_STAR_UNO_ANY_HXX_
#include <com/sun/star/uno/Any.hxx>
#endif

#ifndef _XMLOFF_XMLBITMAPREPEATOFFSETPROPERTYHANDLER_HXX
#include "XMLBitmapRepeatOffsetPropertyHandler.hxx"
#endif

using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using namespace ::rtl;

using ::xmloff::token::GetXMLToken;
using ::xmloff::token::XML_VERTICAL;
using ::xmloff::token::XML_HORIZONTAL;

XMLBitmapRepeatOffsetPropertyHandler::XMLBitmapRepeatOffsetPropertyHandler( sal_Bool bX )
:   mbX( bX ),
    msVertical( GetXMLToken(XML_VERTICAL) ),
    msHorizontal( GetXMLToken(XML_HORIZONTAL) )
{
}

XMLBitmapRepeatOffsetPropertyHandler::~XMLBitmapRepeatOffsetPropertyHandler()
{
}

sal_Bool XMLBitmapRepeatOffsetPropertyHandler::importXML(
    const OUString& rStrImpValue,
    Any& rValue,
    const SvXMLUnitConverter& ) const
{
    SvXMLTokenEnumerator aTokenEnum( rStrImpValue );
    OUString aToken;
    if( aTokenEnum.getNextToken( aToken ) )
    {
        sal_Int32 nValue;
        if( SvXMLUnitConverter::convertPercent( nValue, aToken ) )
        {
            if( aTokenEnum.getNextToken( aToken ) )
            {
                if( ( mbX && ( aToken == msHorizontal ) ) || ( !mbX && ( aToken == msVertical ) ) )
                {
                    rValue <<= nValue;
                    return sal_True;
                }
            }
        }
    }

    return sal_False;

}

sal_Bool XMLBitmapRepeatOffsetPropertyHandler::exportXML(
    OUString& rStrExpValue,
    const Any& rValue,
    const SvXMLUnitConverter& ) const
{
    OUStringBuffer aOut;

    sal_Int32 nValue = 0;
    if( rValue >>= nValue )
    {
        SvXMLUnitConverter::convertPercent( aOut, nValue );
        aOut.append( sal_Unicode( ' ' ) );
        aOut.append( mbX ? msHorizontal : msVertical );
        rStrExpValue = aOut.makeStringAndClear();

        return sal_True;
    }

    return sal_False;
}

<|endoftext|>


<commit_before>// Copyright 2018 The gVisor Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <errno.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/un.h>
#include <unistd.h>

#include <vector>

#include "gtest/gtest.h"
#include "test/util/file_descriptor.h"
#include "test/util/temp_path.h"
#include "test/util/test_util.h"
#include "test/util/thread_util.h"

namespace gvisor {
namespace testing {

namespace {

TEST(MknodTest, RegularFile) {
  const std::string node0 = NewTempAbsPath();
  EXPECT_THAT(mknod(node0.c_str(), S_IFREG, 0), SyscallSucceeds());

  const std::string node1 = NewTempAbsPath();
  EXPECT_THAT(mknod(node1.c_str(), 0, 0), SyscallSucceeds());
}

TEST(MknodTest, RegularFilePermissions) {
  const std::string node = NewTempAbsPath();
  mode_t newUmask = 0077;
  umask(newUmask);

  // Attempt to open file with mode 0777. Not specifying file type should create
  // a regualar file.
  mode_t perms = S_IRWXU | S_IRWXG | S_IRWXO;
  EXPECT_THAT(mknod(node.c_str(), perms, 0), SyscallSucceeds());

  // In the absence of a default ACL, the permissions of the created node are
  // (mode & ~umask).  -- mknod(2)
  mode_t wantPerms = perms & ~newUmask;
  struct stat st;
  ASSERT_THAT(stat(node.c_str(), &st), SyscallSucceeds());
  ASSERT_EQ(st.st_mode & 0777, wantPerms);

  // "Zero file type is equivalent to type S_IFREG." - mknod(2)
  ASSERT_EQ(st.st_mode & S_IFMT, S_IFREG);
}

TEST(MknodTest, MknodAtFIFO) {
  const TempPath dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  const std::string fifo_relpath = NewTempRelPath();
  const std::string fifo = JoinPath(dir.path(), fifo_relpath);

  const FileDescriptor dirfd =
      ASSERT_NO_ERRNO_AND_VALUE(Open(dir.path().c_str(), O_RDONLY));
  ASSERT_THAT(mknodat(dirfd.get(), fifo_relpath.c_str(), S_IFIFO | S_IRUSR, 0),
              SyscallSucceeds());

  struct stat st;
  ASSERT_THAT(stat(fifo.c_str(), &st), SyscallSucceeds());
  EXPECT_TRUE(S_ISFIFO(st.st_mode));
}

TEST(MknodTest, MknodOnExistingPathFails) {
  const TempPath file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile());
  const TempPath slink = ASSERT_NO_ERRNO_AND_VALUE(
      TempPath::CreateSymlinkTo(GetAbsoluteTestTmpdir(), file.path()));

  EXPECT_THAT(mknod(file.path().c_str(), S_IFREG, 0),
              SyscallFailsWithErrno(EEXIST));
  EXPECT_THAT(mknod(file.path().c_str(), S_IFIFO, 0),
              SyscallFailsWithErrno(EEXIST));
  EXPECT_THAT(mknod(slink.path().c_str(), S_IFREG, 0),
              SyscallFailsWithErrno(EEXIST));
  EXPECT_THAT(mknod(slink.path().c_str(), S_IFIFO, 0),
              SyscallFailsWithErrno(EEXIST));
}

TEST(MknodTest, UnimplementedTypesReturnError) {
  const std::string path = NewTempAbsPath();

  if (IsRunningWithVFS1()) {
    ASSERT_THAT(mknod(path.c_str(), S_IFSOCK, 0),
                SyscallFailsWithErrno(EOPNOTSUPP));
  }
  // These will fail on linux as well since we don't have CAP_MKNOD.
  ASSERT_THAT(mknod(path.c_str(), S_IFCHR, 0), SyscallFailsWithErrno(EPERM));
  ASSERT_THAT(mknod(path.c_str(), S_IFBLK, 0), SyscallFailsWithErrno(EPERM));
}

TEST(MknodTest, Socket) {
  ASSERT_THAT(chdir(GetAbsoluteTestTmpdir().c_str()), SyscallSucceeds());

  SKIP_IF(IsRunningOnGvisor() && IsRunningWithVFS1());

  ASSERT_THAT(mknod("./file0", S_IFSOCK | S_IRUSR | S_IWUSR, 0),
              SyscallSucceeds());

  int sk;
  ASSERT_THAT(sk = socket(AF_UNIX, SOCK_SEQPACKET, 0), SyscallSucceeds());
  FileDescriptor fd(sk);

  struct sockaddr_un addr = {.sun_family = AF_UNIX};
  absl::SNPrintF(addr.sun_path, sizeof(addr.sun_path), "./file0");
  ASSERT_THAT(connect(sk, (struct sockaddr *)&addr, sizeof(addr)),
              SyscallFailsWithErrno(ECONNREFUSED));
}

TEST(MknodTest, Fifo) {
  const std::string fifo = NewTempAbsPath();
  ASSERT_THAT(mknod(fifo.c_str(), S_IFIFO | S_IRUSR | S_IWUSR, 0),
              SyscallSucceeds());

  struct stat st;
  ASSERT_THAT(stat(fifo.c_str(), &st), SyscallSucceeds());
  EXPECT_TRUE(S_ISFIFO(st.st_mode));

  std::string msg = "some std::string";
  std::vector<char> buf(512);

  // Read-end of the pipe.
  ScopedThread t([&fifo, &buf, &msg]() {
    FileDescriptor fd = ASSERT_NO_ERRNO_AND_VALUE(Open(fifo.c_str(), O_RDONLY));
    EXPECT_THAT(ReadFd(fd.get(), buf.data(), buf.size()),
                SyscallSucceedsWithValue(msg.length()));
    EXPECT_EQ(msg, std::string(buf.data()));
  });

  // Write-end of the pipe.
  FileDescriptor wfd = ASSERT_NO_ERRNO_AND_VALUE(Open(fifo.c_str(), O_WRONLY));
  EXPECT_THAT(WriteFd(wfd.get(), msg.c_str(), msg.length()),
              SyscallSucceedsWithValue(msg.length()));
}

TEST(MknodTest, FifoOtrunc) {
  const std::string fifo = NewTempAbsPath();
  ASSERT_THAT(mknod(fifo.c_str(), S_IFIFO | S_IRUSR | S_IWUSR, 0),
              SyscallSucceeds());

  struct stat st = {};
  ASSERT_THAT(stat(fifo.c_str(), &st), SyscallSucceeds());
  EXPECT_TRUE(S_ISFIFO(st.st_mode));

  std::string msg = "some std::string";
  std::vector<char> buf(512);
  // Read-end of the pipe.
  ScopedThread t([&fifo, &buf, &msg]() {
    FileDescriptor fd = ASSERT_NO_ERRNO_AND_VALUE(Open(fifo.c_str(), O_RDONLY));
    EXPECT_THAT(ReadFd(fd.get(), buf.data(), buf.size()),
                SyscallSucceedsWithValue(msg.length()));
    EXPECT_EQ(msg, std::string(buf.data()));
  });

  // Write-end of the pipe.
  FileDescriptor wfd =
      ASSERT_NO_ERRNO_AND_VALUE(Open(fifo.c_str(), O_WRONLY | O_TRUNC));
  EXPECT_THAT(WriteFd(wfd.get(), msg.c_str(), msg.length()),
              SyscallSucceedsWithValue(msg.length()));
}

TEST(MknodTest, FifoTruncNoOp) {
  const std::string fifo = NewTempAbsPath();
  ASSERT_THAT(mknod(fifo.c_str(), S_IFIFO | S_IRUSR | S_IWUSR, 0),
              SyscallSucceeds());

  EXPECT_THAT(truncate(fifo.c_str(), 0), SyscallFailsWithErrno(EINVAL));

  struct stat st = {};
  ASSERT_THAT(stat(fifo.c_str(), &st), SyscallSucceeds());
  EXPECT_TRUE(S_ISFIFO(st.st_mode));

  std::string msg = "some std::string";
  std::vector<char> buf(512);
  // Read-end of the pipe.
  ScopedThread t([&fifo, &buf, &msg]() {
    FileDescriptor fd = ASSERT_NO_ERRNO_AND_VALUE(Open(fifo.c_str(), O_RDONLY));
    EXPECT_THAT(ReadFd(fd.get(), buf.data(), buf.size()),
                SyscallSucceedsWithValue(msg.length()));
    EXPECT_EQ(msg, std::string(buf.data()));
  });

  FileDescriptor wfd =
      ASSERT_NO_ERRNO_AND_VALUE(Open(fifo.c_str(), O_WRONLY | O_TRUNC));
  EXPECT_THAT(ftruncate(wfd.get(), 0), SyscallFailsWithErrno(EINVAL));
  EXPECT_THAT(WriteFd(wfd.get(), msg.c_str(), msg.length()),
              SyscallSucceedsWithValue(msg.length()));
  EXPECT_THAT(ftruncate(wfd.get(), 0), SyscallFailsWithErrno(EINVAL));
}

TEST(MknodTest, MknodAtEmptyPath) {
  auto dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  auto fd =
      ASSERT_NO_ERRNO_AND_VALUE(Open(dir.path(), O_RDONLY | O_DIRECTORY, 0666));
  EXPECT_THAT(mknodat(fd.get(), "", S_IFREG | 0777, 0),
              SyscallFailsWithErrno(ENOENT));
}

}  // namespace

}  // namespace testing
}  // namespace gvisor
<commit_msg>test/syscall/mknod: Don't use a hard-coded file name<commit_after>// Copyright 2018 The gVisor Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <errno.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/un.h>
#include <unistd.h>

#include <vector>

#include "gtest/gtest.h"
#include "test/util/file_descriptor.h"
#include "test/util/temp_path.h"
#include "test/util/test_util.h"
#include "test/util/thread_util.h"

namespace gvisor {
namespace testing {

namespace {

TEST(MknodTest, RegularFile) {
  const std::string node0 = NewTempAbsPath();
  EXPECT_THAT(mknod(node0.c_str(), S_IFREG, 0), SyscallSucceeds());

  const std::string node1 = NewTempAbsPath();
  EXPECT_THAT(mknod(node1.c_str(), 0, 0), SyscallSucceeds());
}

TEST(MknodTest, RegularFilePermissions) {
  const std::string node = NewTempAbsPath();
  mode_t newUmask = 0077;
  umask(newUmask);

  // Attempt to open file with mode 0777. Not specifying file type should create
  // a regualar file.
  mode_t perms = S_IRWXU | S_IRWXG | S_IRWXO;
  EXPECT_THAT(mknod(node.c_str(), perms, 0), SyscallSucceeds());

  // In the absence of a default ACL, the permissions of the created node are
  // (mode & ~umask).  -- mknod(2)
  mode_t wantPerms = perms & ~newUmask;
  struct stat st;
  ASSERT_THAT(stat(node.c_str(), &st), SyscallSucceeds());
  ASSERT_EQ(st.st_mode & 0777, wantPerms);

  // "Zero file type is equivalent to type S_IFREG." - mknod(2)
  ASSERT_EQ(st.st_mode & S_IFMT, S_IFREG);
}

TEST(MknodTest, MknodAtFIFO) {
  const TempPath dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  const std::string fifo_relpath = NewTempRelPath();
  const std::string fifo = JoinPath(dir.path(), fifo_relpath);

  const FileDescriptor dirfd =
      ASSERT_NO_ERRNO_AND_VALUE(Open(dir.path().c_str(), O_RDONLY));
  ASSERT_THAT(mknodat(dirfd.get(), fifo_relpath.c_str(), S_IFIFO | S_IRUSR, 0),
              SyscallSucceeds());

  struct stat st;
  ASSERT_THAT(stat(fifo.c_str(), &st), SyscallSucceeds());
  EXPECT_TRUE(S_ISFIFO(st.st_mode));
}

TEST(MknodTest, MknodOnExistingPathFails) {
  const TempPath file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile());
  const TempPath slink = ASSERT_NO_ERRNO_AND_VALUE(
      TempPath::CreateSymlinkTo(GetAbsoluteTestTmpdir(), file.path()));

  EXPECT_THAT(mknod(file.path().c_str(), S_IFREG, 0),
              SyscallFailsWithErrno(EEXIST));
  EXPECT_THAT(mknod(file.path().c_str(), S_IFIFO, 0),
              SyscallFailsWithErrno(EEXIST));
  EXPECT_THAT(mknod(slink.path().c_str(), S_IFREG, 0),
              SyscallFailsWithErrno(EEXIST));
  EXPECT_THAT(mknod(slink.path().c_str(), S_IFIFO, 0),
              SyscallFailsWithErrno(EEXIST));
}

TEST(MknodTest, UnimplementedTypesReturnError) {
  const std::string path = NewTempAbsPath();

  if (IsRunningWithVFS1()) {
    ASSERT_THAT(mknod(path.c_str(), S_IFSOCK, 0),
                SyscallFailsWithErrno(EOPNOTSUPP));
  }
  // These will fail on linux as well since we don't have CAP_MKNOD.
  ASSERT_THAT(mknod(path.c_str(), S_IFCHR, 0), SyscallFailsWithErrno(EPERM));
  ASSERT_THAT(mknod(path.c_str(), S_IFBLK, 0), SyscallFailsWithErrno(EPERM));
}

TEST(MknodTest, Socket) {
  SKIP_IF(IsRunningOnGvisor() && IsRunningWithVFS1());

  ASSERT_THAT(chdir(GetAbsoluteTestTmpdir().c_str()), SyscallSucceeds());

  auto filename = NewTempRelPath();

  ASSERT_THAT(mknod(filename.c_str(), S_IFSOCK | S_IRUSR | S_IWUSR, 0),
              SyscallSucceeds());

  int sk;
  ASSERT_THAT(sk = socket(AF_UNIX, SOCK_SEQPACKET, 0), SyscallSucceeds());
  FileDescriptor fd(sk);

  struct sockaddr_un addr = {.sun_family = AF_UNIX};
  absl::SNPrintF(addr.sun_path, sizeof(addr.sun_path), "%s", filename.c_str());
  ASSERT_THAT(connect(sk, (struct sockaddr *)&addr, sizeof(addr)),
              SyscallFailsWithErrno(ECONNREFUSED));
  ASSERT_THAT(unlink(filename.c_str()), SyscallSucceeds());
}

TEST(MknodTest, Fifo) {
  const std::string fifo = NewTempAbsPath();
  ASSERT_THAT(mknod(fifo.c_str(), S_IFIFO | S_IRUSR | S_IWUSR, 0),
              SyscallSucceeds());

  struct stat st;
  ASSERT_THAT(stat(fifo.c_str(), &st), SyscallSucceeds());
  EXPECT_TRUE(S_ISFIFO(st.st_mode));

  std::string msg = "some std::string";
  std::vector<char> buf(512);

  // Read-end of the pipe.
  ScopedThread t([&fifo, &buf, &msg]() {
    FileDescriptor fd = ASSERT_NO_ERRNO_AND_VALUE(Open(fifo.c_str(), O_RDONLY));
    EXPECT_THAT(ReadFd(fd.get(), buf.data(), buf.size()),
                SyscallSucceedsWithValue(msg.length()));
    EXPECT_EQ(msg, std::string(buf.data()));
  });

  // Write-end of the pipe.
  FileDescriptor wfd = ASSERT_NO_ERRNO_AND_VALUE(Open(fifo.c_str(), O_WRONLY));
  EXPECT_THAT(WriteFd(wfd.get(), msg.c_str(), msg.length()),
              SyscallSucceedsWithValue(msg.length()));
}

TEST(MknodTest, FifoOtrunc) {
  const std::string fifo = NewTempAbsPath();
  ASSERT_THAT(mknod(fifo.c_str(), S_IFIFO | S_IRUSR | S_IWUSR, 0),
              SyscallSucceeds());

  struct stat st = {};
  ASSERT_THAT(stat(fifo.c_str(), &st), SyscallSucceeds());
  EXPECT_TRUE(S_ISFIFO(st.st_mode));

  std::string msg = "some std::string";
  std::vector<char> buf(512);
  // Read-end of the pipe.
  ScopedThread t([&fifo, &buf, &msg]() {
    FileDescriptor fd = ASSERT_NO_ERRNO_AND_VALUE(Open(fifo.c_str(), O_RDONLY));
    EXPECT_THAT(ReadFd(fd.get(), buf.data(), buf.size()),
                SyscallSucceedsWithValue(msg.length()));
    EXPECT_EQ(msg, std::string(buf.data()));
  });

  // Write-end of the pipe.
  FileDescriptor wfd =
      ASSERT_NO_ERRNO_AND_VALUE(Open(fifo.c_str(), O_WRONLY | O_TRUNC));
  EXPECT_THAT(WriteFd(wfd.get(), msg.c_str(), msg.length()),
              SyscallSucceedsWithValue(msg.length()));
}

TEST(MknodTest, FifoTruncNoOp) {
  const std::string fifo = NewTempAbsPath();
  ASSERT_THAT(mknod(fifo.c_str(), S_IFIFO | S_IRUSR | S_IWUSR, 0),
              SyscallSucceeds());

  EXPECT_THAT(truncate(fifo.c_str(), 0), SyscallFailsWithErrno(EINVAL));

  struct stat st = {};
  ASSERT_THAT(stat(fifo.c_str(), &st), SyscallSucceeds());
  EXPECT_TRUE(S_ISFIFO(st.st_mode));

  std::string msg = "some std::string";
  std::vector<char> buf(512);
  // Read-end of the pipe.
  ScopedThread t([&fifo, &buf, &msg]() {
    FileDescriptor fd = ASSERT_NO_ERRNO_AND_VALUE(Open(fifo.c_str(), O_RDONLY));
    EXPECT_THAT(ReadFd(fd.get(), buf.data(), buf.size()),
                SyscallSucceedsWithValue(msg.length()));
    EXPECT_EQ(msg, std::string(buf.data()));
  });

  FileDescriptor wfd =
      ASSERT_NO_ERRNO_AND_VALUE(Open(fifo.c_str(), O_WRONLY | O_TRUNC));
  EXPECT_THAT(ftruncate(wfd.get(), 0), SyscallFailsWithErrno(EINVAL));
  EXPECT_THAT(WriteFd(wfd.get(), msg.c_str(), msg.length()),
              SyscallSucceedsWithValue(msg.length()));
  EXPECT_THAT(ftruncate(wfd.get(), 0), SyscallFailsWithErrno(EINVAL));
}

TEST(MknodTest, MknodAtEmptyPath) {
  auto dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  auto fd =
      ASSERT_NO_ERRNO_AND_VALUE(Open(dir.path(), O_RDONLY | O_DIRECTORY, 0666));
  EXPECT_THAT(mknodat(fd.get(), "", S_IFREG | 0777, 0),
              SyscallFailsWithErrno(ENOENT));
}

}  // namespace

}  // namespace testing
}  // namespace gvisor
<|endoftext|>


<commit_before>//
// Kingsley Chen <kingsamchen at gmail dot com>
//

#include "lumper/commands.h"

#include <cstdint>

#include <sched.h>
#include <sys/mount.h>

#include "esl/scope_guard.h"
#include "fmt/ranges.h"
#include "spdlog/spdlog.h"

#include "base/exception.h"
#include "base/ignore.h"
#include "base/subprocess.h"
#include "lumper/cgroups/cgroup_manager.h"

namespace lumper {

struct mount_proc_before_exec : public base::subprocess::evil_pre_exec_callback {
    int run() noexcept override {
        std::uint64_t flags = MS_NOEXEC | MS_NOSUID | MS_NODEV;
        if (::mount("proc", "/proc", "proc", flags, "") == 0) {
            return 0;
        }
        return errno;
    }
};

void process(cli::cmd_run_t) {
    const auto& parser = cli::for_current_process().command_parser();

    base::subprocess::options opts;
    opts.clone_with_flags(CLONE_NEWUTS | CLONE_NEWPID | CLONE_NEWNS | CLONE_NEWNET | CLONE_NEWIPC);
    if (!parser.get<bool>("--it")) {
        opts.set_stdin(base::subprocess::use_null);
        opts.set_stdout(base::subprocess::use_null);
        opts.set_stderr(base::subprocess::use_null);
    }

    mount_proc_before_exec mount_proc;
    opts.set_evil_pre_exec_callback(&mount_proc);

    cgroups::resource_config res_cfg;

    auto mem_limit = parser.present<std::string>("--memory");
    if (mem_limit) {
        res_cfg.set_memory_limit(*mem_limit);
    }

    // TODO(KC): Explicitly throw if CMD is not provided.
    auto argv = parser.get<std::vector<std::string>>("CMD");
    SPDLOG_INFO("Prepare to run cmd: {}", argv);
    try {
        cgroups::cgroup_manager cgroup_mgr("lumper-cgroup", res_cfg);

        base::subprocess proc(argv, opts);
        ESL_ON_SCOPE_EXIT {
            base::ignore_unused(proc.wait());
        };
        cgroup_mgr.apply(proc.pid());
    } catch (const std::exception& ex) {
        base::rethrow_as<command_run_error>(
                std::current_exception(),
                fmt::format("Failed to run cmd in sub-process; cmd={}", argv));
    }
}

} // namespace lumper
<commit_msg>Lumper: fix leaked mount on kernel with newer systemd<commit_after>//
// Kingsley Chen <kingsamchen at gmail dot com>
//

#include "lumper/commands.h"

#include <cstdint>

#include <sched.h>
#include <sys/mount.h>

#include "esl/scope_guard.h"
#include "esl/strings.h"
#include "fmt/ranges.h"
#include "spdlog/spdlog.h"

#include "base/exception.h"
#include "base/ignore.h"
#include "base/subprocess.h"
#include "lumper/cgroups/cgroup_manager.h"

namespace lumper {

struct mount_proc_before_exec : public base::subprocess::evil_pre_exec_callback {
    int run() noexcept override {
        // See https://man7.org/linux/man-pages/man7/mount_namespaces.7.html#NOTES
        if (::mount("", "/", "", MS_PRIVATE | MS_REC, "") != 0) {
            return errno;
        }

        std::uint64_t flags = MS_NOEXEC | MS_NOSUID | MS_NODEV;
        if (::mount("proc", "/proc", "proc", flags, "") == 0) {
            return 0;
        }
        return errno;
    }
};

void process(cli::cmd_run_t) {
    const auto& parser = cli::for_current_process().command_parser();

    base::subprocess::options opts;
    opts.clone_with_flags(CLONE_NEWUTS | CLONE_NEWPID | CLONE_NEWNS | CLONE_NEWNET | CLONE_NEWIPC);
    if (!parser.get<bool>("--it")) {
        opts.set_stdin(base::subprocess::use_null);
        opts.set_stdout(base::subprocess::use_null);
        opts.set_stderr(base::subprocess::use_null);
    }

    mount_proc_before_exec mount_proc;
    opts.set_evil_pre_exec_callback(&mount_proc);

    cgroups::resource_config res_cfg;

    auto mem_limit = parser.present<std::string>("--memory");
    if (mem_limit) {
        res_cfg.set_memory_limit(*mem_limit);
    }

    // TODO(KC): Explicitly throw if CMD is not provided.
    auto argv = parser.get<std::vector<std::string>>("CMD");
    SPDLOG_INFO("Prepare to run cmd: {}", argv);
    try {
        cgroups::cgroup_manager cgroup_mgr("lumper-cgroup", res_cfg);

        base::subprocess proc(argv, opts);
        ESL_ON_SCOPE_EXIT {
            base::ignore_unused(proc.wait());
            // NOLINTNEXTLINE(bugprone-lambda-function-name)
            SPDLOG_INFO("Command {} completed", esl::strings::join(argv, " "));
        };

        cgroup_mgr.apply(proc.pid());
    } catch (const std::exception& ex) {
        base::rethrow_as<command_run_error>(
                std::current_exception(),
                fmt::format("Failed to run cmd in sub-process; cmd={}", argv));
    }
}

} // namespace lumper
<|endoftext|>


<commit_before>/*
 * Copyright 2010 MQWeb - Franky Braem
 *
 * Licensed under the EUPL, Version 1.1 or – as soon they
 * will be approved by the European Commission - subsequent
 * versions of the EUPL (the "Licence");
 * You may not use this work except in compliance with the
 * Licence.
 * You may obtain a copy of the Licence at:
 *
 * http://joinup.ec.europa.eu/software/page/eupl
 *
 * Unless required by applicable law or agreed to in
 * writing, software distributed under the Licence is
 * distributed on an "AS IS" basis,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
 * express or implied.
 * See the Licence for the specific language governing
 * permissions and limitations under the Licence.
 */
#include <Poco/DateTimeFormatter.h>
#include <Poco/URI.h>
#include <Poco/Net/HTMLForm.h>

#include <MQ/Web/QueueController.h>
#include <MQ/Web/QueueMapper.h>

namespace MQ
{
namespace Web
{

QueueController::QueueController() : MQController()
{
}

QueueController::~QueueController()
{
}

void QueueController::list()
{
	if ( !isPost() )
	{
		setResponseStatus(Poco::Net::HTTPResponse::HTTP_BAD_REQUEST);
		return;
	}

	Poco::JSON::Object::Ptr filter = new Poco::JSON::Object();

	std::string queueNameField = form().get("queueName", "*");
	if ( queueNameField.empty() )
	{
		queueNameField = "*";
	}
	filter->set("name", queueNameField);

	std::string queueDepthField = form().get("queueDepth", "");
	int queueDepth;
	if ( Poco::NumberParser::tryParse(queueDepthField, queueDepth) )
	{
		filter->set("qdepth", queueDepth);
	}

	filter->set("type", form().get("queueType", "All"));
	filter->set("excludeSystem", form().get("queueExcludeSystem", "0").compare("1") == 0);

	QueueMapper queueMapper(*commandServer());
	Poco::JSON::Array::Ptr jsonQueues = queueMapper.inquire(filter);

	for(int i = 0; i < jsonQueues->size(); ++i)
	{
		Poco::JSON::Object::Ptr jsonQueue = jsonQueues->getObject(i);
		if ( ! jsonQueue.isNull() )
		{
			Poco::JSON::Object::Ptr jsonType = jsonQueue->getObject("QType");
			if ( !jsonType.isNull() )
			{
				// Add a property with the type as propertyname and true as value
				// to help a view to check which type of queue we have. For example:
				// {
				//   "QType" : { "value" : 1, "display" : "Local", "Local" : true }
				// }
				std::string display = jsonType->optValue<std::string>("display", "");
				if ( ! display.empty() )
				{
					jsonType->set(display, true);
				}
			}
		}
	}

	set("queues", jsonQueues);
	render("queueList.tpl");
}

void QueueController::view()
{
	std::vector<std::string> parameters = getParameters();

	// First parameter is the queuemanager name
	// Second parameter is the queue name
	if ( parameters.size() < 2 )
	{
		setResponseStatus(Poco::Net::HTTPResponse::HTTP_BAD_REQUEST);
		return;
	}

	std::string queueName = parameters[1];

	Poco::JSON::Object::Ptr filter = new Poco::JSON::Object();
	filter->set("name", queueName);

	QueueMapper queueMapper(*commandServer());
	Poco::JSON::Array::Ptr jsonQueues = queueMapper.inquire(filter);

	if ( jsonQueues->size() > 0 )
	{
		Poco::JSON::Object::Ptr jsonQueue = jsonQueues->getObject(0);
		if ( ! jsonQueue.isNull() )
		{
			set("queue", jsonQueues->getObject(0));

			Poco::JSON::Object::Ptr jsonType = jsonQueue->getObject("QType");
			if ( !jsonType.isNull() )
			{
				// Add a property with the type as propertyname and true as value
				// to help a view to check which type of queue we have. For example:
				// {
				//   "QType" : { "value" : 1, "display" : "Local", "Local" : true }
				// }
				std::string display = jsonType->optValue<std::string>("display", "");
				if ( ! display.empty() )
				{
					jsonType->set(display, true);
				}
			}

			render("queue.tpl");

			return;
		}
	}

	setResponseStatus(Poco::Net::HTTPResponse::HTTP_NOT_FOUND);
}

} } // Namespace MQ::Web
<commit_msg>Allow get method and return json for list action<commit_after>/*
 * Copyright 2010 MQWeb - Franky Braem
 *
 * Licensed under the EUPL, Version 1.1 or – as soon they
 * will be approved by the European Commission - subsequent
 * versions of the EUPL (the "Licence");
 * You may not use this work except in compliance with the
 * Licence.
 * You may obtain a copy of the Licence at:
 *
 * http://joinup.ec.europa.eu/software/page/eupl
 *
 * Unless required by applicable law or agreed to in
 * writing, software distributed under the Licence is
 * distributed on an "AS IS" basis,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
 * express or implied.
 * See the Licence for the specific language governing
 * permissions and limitations under the Licence.
 */
#include <Poco/DateTimeFormatter.h>
#include <Poco/URI.h>
#include <Poco/Net/HTMLForm.h>

#include <MQ/Web/QueueController.h>
#include <MQ/Web/QueueMapper.h>

namespace MQ
{
namespace Web
{

QueueController::QueueController() : MQController()
{
}

QueueController::~QueueController()
{
}

void QueueController::list()
{
	Poco::JSON::Object::Ptr filter = new Poco::JSON::Object();

	std::string queueNameField = form().get("queueName", "*");
	if ( queueNameField.empty() )
	{
		queueNameField = "*";
	}
	filter->set("name", queueNameField);

	std::string queueDepthField = form().get("queueDepth", "");
	int queueDepth;
	if ( Poco::NumberParser::tryParse(queueDepthField, queueDepth) )
	{
		filter->set("qdepth", queueDepth);
	}

	filter->set("type", form().get("queueType", "All"));
	filter->set("excludeSystem", form().get("queueExcludeSystem", "0").compare("1") == 0);

	QueueMapper queueMapper(*commandServer());
	Poco::JSON::Array::Ptr jsonQueues = queueMapper.inquire(filter);

	for(int i = 0; i < jsonQueues->size(); ++i)
	{
		Poco::JSON::Object::Ptr jsonQueue = jsonQueues->getObject(i);
		if ( ! jsonQueue.isNull() )
		{
			Poco::JSON::Object::Ptr jsonType = jsonQueue->getObject("QType");
			if ( !jsonType.isNull() )
			{
				// Add a property with the type as propertyname and true as value
				// to help a view to check which type of queue we have. For example:
				// {
				//   "QType" : { "value" : 1, "display" : "Local", "Local" : true }
				// }
				std::string display = jsonType->optValue<std::string>("display", "");
				if ( ! display.empty() )
				{
					jsonType->set(display, true);
				}
			}
		}
	}

	set("queues", jsonQueues);

	if ( format().compare("html") == 0 )
	{
		render("queueList.tpl");
	}
	else if ( format().compare("json") == 0 )
	{
		data().stringify(response().send());
	}
}

void QueueController::view()
{
	std::vector<std::string> parameters = getParameters();

	// First parameter is the queuemanager name
	// Second parameter is the queue name
	if ( parameters.size() < 2 )
	{
		setResponseStatus(Poco::Net::HTTPResponse::HTTP_BAD_REQUEST);
		return;
	}

	std::string queueName = parameters[1];

	Poco::JSON::Object::Ptr filter = new Poco::JSON::Object();
	filter->set("name", queueName);

	QueueMapper queueMapper(*commandServer());
	Poco::JSON::Array::Ptr jsonQueues = queueMapper.inquire(filter);

	if ( jsonQueues->size() > 0 )
	{
		Poco::JSON::Object::Ptr jsonQueue = jsonQueues->getObject(0);
		if ( ! jsonQueue.isNull() )
		{
			set("queue", jsonQueues->getObject(0));

			Poco::JSON::Object::Ptr jsonType = jsonQueue->getObject("QType");
			if ( !jsonType.isNull() )
			{
				// Add a property with the type as propertyname and true as value
				// to help a view to check which type of queue we have. For example:
				// {
				//   "QType" : { "value" : 1, "display" : "Local", "Local" : true }
				// }
				std::string display = jsonType->optValue<std::string>("display", "");
				if ( ! display.empty() )
				{
					jsonType->set(display, true);
				}
			}

			render("queue.tpl");

			return;
		}
	}

	setResponseStatus(Poco::Net::HTTPResponse::HTTP_NOT_FOUND);
}

} } // Namespace MQ::Web
<|endoftext|>


<commit_before>#include <gtkmm.h>
#include <lilv/lilv.h>

class LV2PluginList : public Gtk::Window {

    class Columns : public Gtk::TreeModel::ColumnRecord {
    public:
        Columns() {
            add(col_id);
            add(col_name);
        }
        ~Columns() {}

        Gtk::TreeModelColumn<Glib::ustring> col_id;
        Gtk::TreeModelColumn<Glib::ustring> col_name;
    };
    Columns cols;

    Gtk::VBox topBox;
    Gtk::HBox buttonBox;
    Gtk::ComboBoxEntryText comboBox;
    Gtk::ScrolledWindow scrollWindow;
    Gtk::Button buttonQuit;
    Gtk::Button newList;
    Gtk::Entry textEntry;
    Gtk::TreeView treeView;
    Gtk::TreeModel::Row row ;

    Glib::RefPtr<Gtk::ListStore> listStore;
    Glib::RefPtr<Gtk::TreeView::Selection> selection;
    Glib::ustring interpret;
    Glib::ustring regex;
    bool new_world;

    LilvWorld* world;
    const LilvPlugins* lv2_plugins;

    void fill_list();
    void refill_list();
    void new_list();

    virtual void on_selection_changed();
    virtual void on_combo_changed();
    virtual void on_entry_changed();
    virtual void on_button_quit();

    public:
    LV2PluginList() :
        buttonQuit("Quit"),
        newList("New"),
        new_world(false) {
        set_title("LV2 plugs");
        set_default_size(350,200);
        comboBox.append_text("jalv.gtk ");
        comboBox.append_text("jalv.gtkmm ");
        comboBox.append_text("jalv.gtk3 ");
        comboBox.append_text("jalv.qt ");
        comboBox.append_text("jalv ");
        comboBox.set_active(0);
        interpret = "jalv.gtk ";

        treeView.set_model(listStore = Gtk::ListStore::create(cols));
        treeView.append_column("Name", cols.col_name);
        treeView.set_rules_hint(true);
        fill_list();

        scrollWindow.add(treeView);
        scrollWindow.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
        topBox.pack_start(scrollWindow);
        topBox.pack_end(buttonBox,Gtk::PACK_SHRINK);
        buttonBox.pack_start(comboBox,Gtk::PACK_SHRINK);
        buttonBox.pack_start(textEntry,Gtk::PACK_EXPAND_WIDGET);
        buttonBox.pack_start(newList,Gtk::PACK_SHRINK);
        buttonBox.pack_start(buttonQuit,Gtk::PACK_SHRINK);
        add(topBox);

        selection = treeView.get_selection();
        selection->signal_changed().connect( sigc::mem_fun(*this, &LV2PluginList::on_selection_changed) );
        buttonQuit.signal_clicked().connect( sigc::mem_fun(*this, &LV2PluginList::on_button_quit));
        newList.signal_clicked().connect( sigc::mem_fun(*this, &LV2PluginList::new_list));
        comboBox.signal_changed().connect( sigc::mem_fun(*this, &LV2PluginList::on_combo_changed));
        textEntry.signal_changed().connect( sigc::mem_fun(*this, &LV2PluginList::on_entry_changed));
        show_all_children();
    }
    ~LV2PluginList() {
        lilv_world_free(world);
    }
};

void LV2PluginList::fill_list() {
    world = lilv_world_new();
    lilv_world_load_all(world);
    lv2_plugins = lilv_world_get_all_plugins(world);
    LilvIter* it = lilv_plugins_begin(lv2_plugins);

    for (it; !lilv_plugins_is_end(lv2_plugins, it);
    it = lilv_plugins_next(lv2_plugins, it)) {
        row = *(listStore->append());
        const LilvPlugin* plug = lilv_plugins_get(lv2_plugins, it);
        row[cols.col_id] = lilv_node_as_string(lilv_plugin_get_uri(plug));
        row[cols.col_name] = lilv_node_as_string(lilv_plugin_get_name(plug));
    }
}

void LV2PluginList::refill_list() {
    Glib::ustring name;
    LilvIter* it = lilv_plugins_begin(lv2_plugins);
    for (it; !lilv_plugins_is_end(lv2_plugins, it);
    it = lilv_plugins_next(lv2_plugins, it)) {
        const LilvPlugin* plug = lilv_plugins_get(lv2_plugins, it);
        name = lilv_node_as_string(lilv_plugin_get_name(plug));
        Glib::ustring::size_type found = name.lowercase().find(regex.lowercase());
        if (found!=Glib::ustring::npos){
            row = *(listStore->append());
            row[cols.col_id] = lilv_node_as_string(lilv_plugin_get_uri(plug));
            row[cols.col_name] = name;
	    }
    }
}

void LV2PluginList::new_list() {
    new_world = true;
    listStore->clear();
    lilv_world_free(world);
    world = NULL;
    textEntry.set_text("");
    fill_list();
}

void LV2PluginList::on_entry_changed() {
    if(! new_world) {
        regex = textEntry.get_text();
        listStore->clear();
        refill_list();
    } else {
        new_world = false;
    }
}

void LV2PluginList::on_combo_changed() {
    interpret = comboBox.get_entry()->get_text();
}

void LV2PluginList::on_selection_changed() {
    Gtk::TreeModel::iterator iter = selection->get_selected();
    if(iter) {
        Gtk::TreeModel::Row row = *iter;
        Glib::ustring id = interpret + row[cols.col_id] + " & " ;
        if (system(NULL)) system( id.c_str());
        selection->unselect(*iter);
    }
}

void LV2PluginList::on_button_quit() {
    Gtk::Main::quit();
}

int main (int argc , char ** argv) {
    Gtk::Main kit (argc, argv);
    LV2PluginList lv2plugs;
    Gtk::Main::run (lv2plugs);
    return 0;
}
<commit_msg> * add tooltip area<commit_after>#include <gtkmm.h>
#include <lilv/lilv.h>

class LV2PluginList : public Gtk::Window {

    class Columns : public Gtk::TreeModel::ColumnRecord {
    public:
        Columns() {
            add(col_id);
            add(col_name);
            add(col_tip);
        }
        ~Columns() {}

        Gtk::TreeModelColumn<Glib::ustring> col_id;
        Gtk::TreeModelColumn<Glib::ustring> col_name;
        Gtk::TreeModelColumn<Glib::ustring> col_tip;
    };
    Columns cols;

    Gtk::VBox topBox;
    Gtk::HBox buttonBox;
    Gtk::ComboBoxEntryText comboBox;
    Gtk::ScrolledWindow scrollWindow;
    Gtk::Button buttonQuit;
    Gtk::Button newList;
    Gtk::Entry textEntry;
    Gtk::TreeView treeView;
    Gtk::TreeModel::Row row ;

    Glib::RefPtr<Gtk::ListStore> listStore;
    Glib::RefPtr<Gtk::TreeView::Selection> selection;
    Glib::ustring interpret;
    Glib::ustring regex;
    bool new_world;

    LilvWorld* world;
    const LilvPlugins* lv2_plugins;

    void fill_list();
    void refill_list();
    void new_list();

    virtual void on_selection_changed();
    virtual void on_combo_changed();
    virtual void on_entry_changed();
    virtual void on_button_quit();

    public:
    LV2PluginList() :
        buttonQuit("Quit"),
        newList("New"),
        new_world(false) {
        set_title("LV2 plugs");
        set_default_size(350,200);
        comboBox.append_text("jalv.gtk ");
        comboBox.append_text("jalv.gtkmm ");
        comboBox.append_text("jalv.gtk3 ");
        comboBox.append_text("jalv.qt ");
        comboBox.append_text("jalv ");
        comboBox.set_active(0);
        comboBox.set_size_request(120,-1);
        interpret = "jalv.gtk ";

        treeView.set_model(listStore = Gtk::ListStore::create(cols));
        treeView.append_column("Name", cols.col_name);
        treeView.set_tooltip_column(2);
        treeView.set_rules_hint(true);
        fill_list();

        scrollWindow.add(treeView);
        scrollWindow.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
        topBox.pack_start(scrollWindow);
        topBox.pack_end(buttonBox,Gtk::PACK_SHRINK);
        buttonBox.pack_start(comboBox,Gtk::PACK_SHRINK);
        buttonBox.pack_start(textEntry,Gtk::PACK_EXPAND_WIDGET);
        buttonBox.pack_start(newList,Gtk::PACK_SHRINK);
        buttonBox.pack_start(buttonQuit,Gtk::PACK_SHRINK);
        add(topBox);

        selection = treeView.get_selection();
        selection->signal_changed().connect( sigc::mem_fun(*this, &LV2PluginList::on_selection_changed) );
        buttonQuit.signal_clicked().connect( sigc::mem_fun(*this, &LV2PluginList::on_button_quit));
        newList.signal_clicked().connect( sigc::mem_fun(*this, &LV2PluginList::new_list));
        comboBox.signal_changed().connect( sigc::mem_fun(*this, &LV2PluginList::on_combo_changed));
        textEntry.signal_changed().connect( sigc::mem_fun(*this, &LV2PluginList::on_entry_changed));
        show_all_children();
    }
    ~LV2PluginList() {
        lilv_world_free(world);
    }
};

void LV2PluginList::fill_list() {
    Glib::ustring tip;
    Glib::ustring tipby = " \nby ";
    world = lilv_world_new();
    lilv_world_load_all(world);
    lv2_plugins = lilv_world_get_all_plugins(world);
    LilvIter* it = lilv_plugins_begin(lv2_plugins);

    for (it; !lilv_plugins_is_end(lv2_plugins, it);
    it = lilv_plugins_next(lv2_plugins, it)) {
        row = *(listStore->append());
        const LilvPlugin* plug = lilv_plugins_get(lv2_plugins, it);
        row[cols.col_id] = lilv_node_as_string(lilv_plugin_get_uri(plug));
        row[cols.col_name] = lilv_node_as_string(lilv_plugin_get_name(plug));
        const LilvPluginClass* cls = lilv_plugin_get_class(plug);
        tip = lilv_node_as_string(lilv_plugin_class_get_label(cls));

        LilvNode* nd = lilv_plugin_get_author_name(plug);
        if (!nd) {
            nd = lilv_plugin_get_project(plug);
        }
        if (nd) {
             tip += tipby + lilv_node_as_string(nd);
        }
        lilv_node_free(nd);
        row[cols.col_tip] = tip;
    }
}

void LV2PluginList::refill_list() {
    Glib::ustring name;
    Glib::ustring tip;
    Glib::ustring tipby = " \nby ";
    LilvIter* it = lilv_plugins_begin(lv2_plugins);
    for (it; !lilv_plugins_is_end(lv2_plugins, it);
    it = lilv_plugins_next(lv2_plugins, it)) {
        const LilvPlugin* plug = lilv_plugins_get(lv2_plugins, it);
        name = lilv_node_as_string(lilv_plugin_get_name(plug));
        Glib::ustring::size_type found = name.lowercase().find(regex.lowercase());
        if (found!=Glib::ustring::npos){
            row = *(listStore->append());
            row[cols.col_id] = lilv_node_as_string(lilv_plugin_get_uri(plug));
            row[cols.col_name] = name;
            const LilvPluginClass* cls = lilv_plugin_get_class(plug);
            tip = lilv_node_as_string(lilv_plugin_class_get_label(cls));

            LilvNode* nd = lilv_plugin_get_author_name(plug);
            if (!nd) {
                nd = lilv_plugin_get_project(plug);
            }
            if (nd) {
                tip += tipby + lilv_node_as_string(nd);
            }
            lilv_node_free(nd);
            row[cols.col_tip] = tip;
        }
    }
}

void LV2PluginList::new_list() {
    new_world = true;
    listStore->clear();
    lilv_world_free(world);
    world = NULL;
    textEntry.set_text("");
    fill_list();
}

void LV2PluginList::on_entry_changed() {
    if(! new_world) {
        regex = textEntry.get_text();
        listStore->clear();
        refill_list();
    } else {
        new_world = false;
    }
}

void LV2PluginList::on_combo_changed() {
    interpret = comboBox.get_entry()->get_text();
}

void LV2PluginList::on_selection_changed() {
    Gtk::TreeModel::iterator iter = selection->get_selected();
    if(iter) {
        Gtk::TreeModel::Row row = *iter;
        Glib::ustring id = interpret + " " + row[cols.col_id] + " & " ;
        if (system(NULL)) system( id.c_str());
        selection->unselect(*iter);
    }
}

void LV2PluginList::on_button_quit() {
    Gtk::Main::quit();
}

int main (int argc , char ** argv) {
    Gtk::Main kit (argc, argv);
    LV2PluginList lv2plugs;
    Gtk::Main::run (lv2plugs);
    return 0;
}
<|endoftext|>