EXPORT_C void
exception_safety_tester::report_error()
{
    activity_guard ag( m_internal_activity );

    unit_test_log << unit_test::log::begin( m_execution_path.back().m_file_name,
                                            m_execution_path.back().m_line_num )
                  << log_all_errors;

    wrap_stringstream formatter;

    if( m_invairant_failed )
        formatter << "Failed invariant";

    if( m_memory_in_use.size() != 0 ) {
        if( m_invairant_failed )
            formatter << " and ";

        formatter << m_memory_in_use.size() << " memory leak";
        if( m_memory_in_use.size() > 1 )
            formatter << 's';
    }
    formatter << " detected in the execution path " << m_exec_path_counter << ":\n";

    format_execution_path( formatter, m_execution_path.begin(), m_execution_path.end() );

    unit_test_log << const_string( formatter.str() ) << unit_test::log::end();
}
Example #2
0
	u32 get_integer(const registry& psf, const std::string& key, u32 def)
	{
		const auto found = psf.find(key);

		if (found == psf.end() || found->second.type() != format::integer)
		{
			return def;
		}

		return found->second.as_integer();
	}
Example #3
0
	std::string get_string(const registry& psf, const std::string& key, const std::string& def)
	{
		const auto found = psf.find(key);

		if (found == psf.end() || (found->second.type() != format::string && found->second.type() != format::array))
		{
			return def;
		}

		return found->second.as_string();
	}
EXPORT_C void
exception_safety_tester::freed( void* p )
{
    if( m_internal_activity )
        return;

    activity_guard ag( m_internal_activity );

    registry::iterator it = m_memory_in_use.find( p );
    if( it != m_memory_in_use.end() ) {
        m_execution_path[it->second].m_alloc.ptr = 0;
        m_memory_in_use.erase( it );
    }
}
EXPORT_C bool
exception_safety_tester::next_execution_path()
{
    activity_guard ag( m_internal_activity );

    // check memory usage
    if( m_execution_path.size() > 0 ) {
        bool errors_detected = m_invairant_failed || (m_memory_in_use.size() != 0);
        framework::assertion_result( !errors_detected );

        if( errors_detected )
            report_error();

        m_memory_in_use.clear();
    }

    m_exec_path_point           = 0;
    m_exception_point_counter   = 0;
    m_invairant_failed          = false;
    ++m_exec_path_counter;

    while( m_execution_path.size() > 0 ) {
        switch( m_execution_path.back().m_type ) {
        case EPP_SCOPE:
        case EPP_ALLOC:
            m_execution_path.pop_back();
            break;

        case EPP_DECISION:
            if( !m_execution_path.back().m_decision.value ) {
                m_execution_path.pop_back();
                break;
            }

            m_execution_path.back().m_decision.value = false;
            m_forced_exception_point = m_execution_path.back().m_decision.forced_exception_point;
            return true;

        case EPP_EXCEPT:
            m_execution_path.pop_back();
            ++m_forced_exception_point;
            return true;
        }
    }

    BOOST_TEST_MESSAGE( "Total tested " << --m_exec_path_counter << " execution path" );

    return false;
}
EXPORT_C void
exception_safety_tester::allocated( const_string file, std::size_t line_num, void* p, std::size_t s )
{
    if( m_internal_activity )
        return;

    activity_guard ag( m_internal_activity );

    if( m_exec_path_point < m_execution_path.size() )
        BOOST_REQUIRE_MESSAGE( m_execution_path[m_exec_path_point].m_type == EPP_ALLOC,
                               "Function under test exibit non-deterministic behavior" );
    else
        m_execution_path.push_back(
            execution_path_point( EPP_ALLOC, file, line_num ) );

    m_execution_path[m_exec_path_point].m_alloc.ptr  = p;
    m_execution_path[m_exec_path_point].m_alloc.size = s;

    m_memory_in_use.insert( std::make_pair( p, m_exec_path_point++ ) );
}
Example #7
0
	std::vector<char> save_object(const registry& psf)
	{
		std::vector<def_table_t> indices; indices.reserve(psf.size());

		// Generate indices and calculate key table length
		std::size_t key_offset = 0, data_offset = 0;

		for (const auto& entry : psf)
		{
			def_table_t index;
			index.key_off = gsl::narrow<u32>(key_offset);
			index.param_fmt = entry.second.type();
			index.param_len = entry.second.size();
			index.param_max = entry.second.max();
			index.data_off = gsl::narrow<u32>(data_offset);

			// Update offsets:
			key_offset += gsl::narrow<u32>(entry.first.size() + 1); // key size
			data_offset += index.param_max;

			indices.push_back(index);
		}

		// Align next section (data) offset
		key_offset = ::align(key_offset, 4);

		// Generate header
		header_t header;
		header.magic = "\0PSF"_u32;
		header.version = 0x101;
		header.off_key_table = gsl::narrow<u32>(sizeof(header_t) + sizeof(def_table_t) * psf.size());
		header.off_data_table = gsl::narrow<u32>(header.off_key_table + key_offset);
		header.entries_num = gsl::narrow<u32>(psf.size());

		// Save header and indices
		std::vector<char> result; result.reserve(header.off_data_table + data_offset);

		result.insert(result.end(), (char*)&header, (char*)&header + sizeof(header_t));
		result.insert(result.end(), (char*)indices.data(), (char*)indices.data() + sizeof(def_table_t) * psf.size());

		// Save key table
		for (const auto& entry : psf)
		{
			result.insert(result.end(), entry.first.begin(), entry.first.end());
			result.push_back('\0');
		}

		// Insert zero padding
		result.insert(result.end(), header.off_data_table - result.size(), '\0');

		// Save data
		for (const auto& entry : psf)
		{
			const auto fmt = entry.second.type();
			const u32 max = entry.second.max();

			if (fmt == format::integer && max == sizeof(u32))
			{
				const le_t<u32> value = entry.second.as_integer();
				result.insert(result.end(), (char*)&value, (char*)&value + sizeof(u32));
			}
			else if (fmt == format::string || fmt == format::array)
			{
				const std::string& value = entry.second.as_string();
				const std::size_t size = std::min<std::size_t>(max, value.size());

				if (value.size() + (fmt == format::string) > max)
				{
					// TODO: check real limitations of PSF format
					log.error("Entry value shrinkage (key='%s', value='%s', size=0x%zx, max=0x%x)", entry.first, value, size, max);
				}

				result.insert(result.end(), value.begin(), value.begin() + size);
				result.insert(result.end(), max - size, '\0'); // Write zeros up to max_size
			}
			else
			{
				throw EXCEPTION("Invalid entry format (key='%s', fmt=0x%x)", entry.first, fmt);
			}
		}

		return result;
	}
Example #8
0
void
register_float_ops( registry &r )
{
	r.add( op( "d.castto", [](float v) -> double { return static_cast<double>( v ); }, op::simple ) );
	r.add( op( "d.castfrom", [](double v) -> float { return static_cast<float>( v ); }, op::simple ) );

	r.add( op( "f.negate", [](float v) -> float { return -v; }, op::simple ) );
	r.add( op( "d.negate", [](double v) -> double { return -v; }, op::simple ) );

	r.add( op( "f.add", [](float a, float b) -> float { return a + b; }, op::simple ) );
	r.add( op( "d.add", [](double a, double b) -> double { return a + b; }, op::simple ) );

	r.add( op( "f.sub", [](float a, float b) -> float { return a - b; }, op::simple ) );
	r.add( op( "d.sub", [](double a, double b) -> double { return a - b; }, op::simple ) );

	r.add( op( "f.mul", [](float a, float b) -> float { return a * b; }, op::simple ) );
	r.add( op( "d.mul", [](double a, double b) -> double { return a * b; }, op::simple ) );

	r.add( op( "f.div", [](float a, float b) -> float { return a / b; }, op::simple ) );
	r.add( op( "d.div", [](double a, double b) -> double { return a / b; }, op::simple ) );
}