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(); }
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; }
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; }