20#include <boost/test/unit_test.hpp>
24#include <wx/wfstream.h>
28#include <magic_enum.hpp>
29#include <magic_enum_iostream.hpp>
35using magic_enum::iostream_operators::operator<<;
42 file.
name =
"test_file";
43 std::string data =
"Hello, World!";
48 file.
data_hash = hash.digest().ToString();
57 file.
name =
"test_file";
58 std::string data =
"Hello, World!";
73 data.reserve( 13 * 100000 + 1 );
75 for(
int i = 0; i < 100000; ++i )
76 data +=
"Hello, World!";
92 data.reserve( 100000 );
94 for(
int i = 0; i < 100000; ++i )
95 data +=
static_cast<char>( i % 256 );
110 data.reserve( 100000 );
115 for(
int i = 0; i < 100000; ++i )
116 data +=
static_cast<char>(
rng() % 256 );
134 file.
name =
"test_file";
135 std::string data =
"Hello, World!";
154 std::string data =
"Test file content for hash computation";
157 wxFFileOutputStream out( tempFile.GetFullPath() );
159 out.Write( data.data(), data.size() );
163 std::string computedHash;
166 BOOST_CHECK( !computedHash.empty() );
184 std::string data1 =
"Content version 1";
185 std::string data2 =
"Content version 2";
188 wxFFileOutputStream out1( tempFile1.GetFullPath() );
190 out1.Write( data1.data(), data1.size() );
194 wxFFileOutputStream out2( tempFile2.GetFullPath() );
196 out2.Write( data2.data(), data2.size() );
200 std::string hash1, hash2;
207 BOOST_CHECK_NE( hash1, hash2 );
213 wxFileName nonExistent( wxS(
"/nonexistent/path/file.txt" ) );
218 BOOST_CHECK( hash.empty() );
227 auto testV1Fallback = [](
const std::string& aData )
230 file.
name =
"v1_hash_test";
235 v1hash.
addDataV1(
reinterpret_cast<const uint8_t*
>( aData.data() ), aData.size() );
243 if( aData.size() % 16 != 0 )
244 BOOST_CHECK_NE( file.
data_hash, currentHash );
258 testV1Fallback(
"Hello, World!" );
261 testV1Fallback(
"12345678901234567" );
264 testV1Fallback(
"1234567890123456789012345678901" );
267 std::string aligned( 100000UL * 16,
'x' );
269 alignedFile.
name =
"aligned_test";
273 v1h.
addDataV1(
reinterpret_cast<const uint8_t*
>( aligned.data() ), aligned.size() );
293 file->name = wxS(
"shared_model.step" );
296 std::string payload( 1024 * 1024,
'x' );
297 file->decompressedData.assign( payload.begin(), payload.end() );
300 hash.
add( file->decompressedData );
324 BOOST_CHECK_NE( copy2File, originalFile );
331 BOOST_CHECK( !transient.
HasFile( wxS(
"shared_model.step" ) ) );
334 BOOST_CHECK( original.
HasFile( wxS(
"shared_model.step" ) ) );
335 BOOST_CHECK( copy1.
HasFile( wxS(
"shared_model.step" ) ) );
336 BOOST_CHECK( copy2.
HasFile( wxS(
"shared_model.step" ) ) );
353 file->name = wxS(
"deep_copy.bin" );
354 file->decompressedData.assign( {
'1',
'2',
'3' } );
357 hash.
add( file->decompressedData );
369 BOOST_CHECK_NE( deepFile, file );
382 file->name = wxS(
"ARTIDIS-KiCAD_HEADER.kicad_wks" );
384 file->decompressedData.assign( {
'1',
'2',
'3' } );
387 hash.
add( file->decompressedData );
401 BOOST_CHECK( !target.
IsEmpty() );
402 BOOST_CHECK( target.
HasFile( wxS(
"ARTIDIS-KiCAD_HEADER.kicad_wks" ) ) );
403 BOOST_CHECK( working.
HasFile( wxS(
"ARTIDIS-KiCAD_HEADER.kicad_wks" ) ) );
407 BOOST_CHECK( working.
HasFile( wxS(
"ARTIDIS-KiCAD_HEADER.kicad_wks" ) ) );
409 std::set<wxString> exclude{ wxS(
"ARTIDIS-KiCAD_HEADER.kicad_wks" ) };
411 BOOST_CHECK( !working.
HasFile( wxS(
"ARTIDIS-KiCAD_HEADER.kicad_wks" ) ) );
422 first->name = wxS(
"duplicate.step" );
423 first->decompressedData.assign( {
'k',
'e',
'p',
't' } );
425 BOOST_REQUIRE_EQUAL( files.
AddFile( first ), first );
428 duplicate->name = wxS(
"duplicate.step" );
429 duplicate->decompressedData.assign( {
'd',
'r',
'o',
'p',
'p',
'e',
'd' } );
433 BOOST_REQUIRE_EQUAL( stored, first );
442 std::string(
"kept" ) );
static RETURN_CODE DecompressAndDecode(EMBEDDED_FILE &aFile, bool aAllowEmptyHash=false)
Takes data from the #compressedEncodedData buffer and Base64 decodes it.
@ FILE_NOT_FOUND
File not found on disk.
@ CHECKSUM_ERROR
Checksum in file does not match data.
EMBEDDED_FILE * GetEmbeddedFile(const wxString &aName) const
Returns the embedded file with the given name or nullptr if it does not exist.
static RETURN_CODE ComputeFileHash(const wxFileName &aFileName, std::string &aHash)
Compute the hash of a file on disk without fully embedding it.
bool HasFile(const wxString &name) const
void ClearEmbeddedFiles(bool aDeleteFiles=true)
EMBEDDED_FILE * AddFile(const wxFileName &aName, bool aOverwrite)
Load a file from disk and adds it to the collection.
const std::map< wxString, std::shared_ptr< EMBEDDED_FILE > > & EmbeddedFileMap() const
Provide an iterable view of the file collection.
static RETURN_CODE CompressAndEncode(EMBEDDED_FILE &aFile)
Take data from the #decompressedData buffer and compresses it using ZSTD into the #compressedEncodedD...
void AssignSharedFrom(const EMBEDDED_FILES &aSource, const std::set< wxString > &aExcludedNames={})
Replace this collection's files with references to aSource's files, skipping any whose name appears i...
wxString CreateChildFileStr(const wxString &aName) const
Create and return the path to a direct child file as a wxString.
A streaming C++ equivalent for MurmurHash3_x64_128.
FORCE_INLINE void addDataV1(const uint8_t *data, size_t length)
FORCE_INLINE void add(const std::string &input)
FORCE_INLINE HASH_128 digest()
FORCE_INLINE void reset(uint32_t aSeed=0)
static thread_local boost::mt19937 rng
std::vector< char > decompressedData
std::string ToString() const
BOOST_AUTO_TEST_CASE(HorizontalAlignment)
BOOST_AUTO_TEST_SUITE(CadstarPartParser)
BOOST_AUTO_TEST_CASE(CompressAndEncode_OK)
BOOST_REQUIRE(intersection.has_value()==c.ExpectedIntersection.has_value())
BOOST_AUTO_TEST_SUITE_END()
wxString result
Test unit parsing edge cases and error handling.
BOOST_CHECK_EQUAL(result, "25.4")