42#include <wx/filename.h>
65 m_tempDir = wxFileName::GetTempDir() + wxFileName::GetPathSeparator()
66 + wxString::Format(
"kicad_vcs_test_%ld", wxGetProcessId() );
68 wxFileName::Mkdir(
m_tempDir, wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL );
81 wxFileName::Rmdir(
m_tempDir, wxPATH_RMDIR_RECURSIVE );
95 git_repository* repo =
nullptr;
97 if( git_repository_init( &repo,
m_tempDir.ToUTF8().data(), 0 ) != 0 )
101 git_config*
config =
nullptr;
103 if( git_repository_config( &
config, repo ) == 0 )
107 git_config_free(
config );
111 wxString filePath =
m_tempDir + wxFileName::GetPathSeparator() + wxT(
"test.txt" );
114 std::ofstream f( filePath.ToStdString() );
115 f <<
"test content\n";
119 git_index*
index =
nullptr;
121 if( git_repository_index( &
index, repo ) != 0 )
123 git_repository_free( repo );
127 git_index_add_bypath(
index,
"test.txt" );
128 git_index_write(
index );
133 if( git_index_write_tree( &treeOid,
index ) != 0 )
135 git_index_free(
index );
136 git_repository_free( repo );
140 git_index_free(
index );
142 git_tree* tree =
nullptr;
144 if( git_tree_lookup( &tree, repo, &treeOid ) != 0 )
146 git_repository_free( repo );
151 git_signature* sig =
nullptr;
155 git_tree_free( tree );
156 git_repository_free( repo );
161 int err = git_commit_create_v( &commitOid, repo,
"HEAD", sig, sig,
nullptr,
164 git_signature_free( sig );
165 git_tree_free( tree );
166 git_repository_free( repo );
186 BOOST_TEST_REQUIRE( repoReady() );
192 std::string expression;
196 const std::vector<TestCase> cases = {
197 {
"@{vcsidentifier()}", 40 },
198 {
"@{vcsidentifier(40)}", 40 },
199 {
"@{vcsidentifier(7)}", 7 },
200 {
"@{vcsidentifier(8)}", 8 },
201 {
"@{vcsidentifier(12)}", 12 },
202 {
"@{vcsidentifier(4)}", 4 },
204 {
"@{vcsfileidentifier(\".\")}", 40 },
205 {
"@{vcsfileidentifier(\".\", 8)}", 8 },
208 std::regex hexPattern(
"^[0-9a-f]+$" );
210 for(
const auto& testCase : cases )
212 auto result = evaluator.
Evaluate( wxString::FromUTF8( testCase.expression ) );
214 BOOST_CHECK_MESSAGE( !evaluator.
HasErrors(),
215 "Error in expression: " + testCase.expression +
" Errors: "
219 BOOST_CHECK( std::regex_match(
result.ToStdString(), hexPattern ) );
228 BOOST_TEST_REQUIRE( repoReady() );
232 auto branch = evaluator.
Evaluate(
"@{vcsbranch()}" );
234 BOOST_CHECK( !branch.IsEmpty() );
236 auto authorEmail = evaluator.
Evaluate(
"@{vcsauthoremail()}" );
240 auto committerEmail = evaluator.
Evaluate(
"@{vcscommitteremail()}" );
244 auto author = evaluator.
Evaluate(
"@{vcsauthor()}" );
248 auto committer = evaluator.
Evaluate(
"@{vcscommitter()}" );
253 auto fileAuthorEmail = evaluator.
Evaluate(
"@{vcsfileauthoremail(\".\")}" );
257 auto fileCommitterEmail = evaluator.
Evaluate(
"@{vcsfilecommitteremail(\".\")}" );
267 BOOST_TEST_REQUIRE( repoReady() );
273 std::string expression;
276 const std::vector<TestCase> cases = {
278 {
"@{vcsdirty(0)}" },
279 {
"@{vcsdirty(1)}" },
282 for(
const auto& testCase : cases )
284 auto result = evaluator.
Evaluate( wxString::FromUTF8( testCase.expression ) );
296 BOOST_TEST_REQUIRE( repoReady() );
300 const std::vector<std::string> cases = {
301 "@{vcsdirtysuffix()}",
302 "@{vcsdirtysuffix(\"-modified\")}",
303 "@{vcsdirtysuffix(\"+\", 1)}",
306 for(
const auto& expr : cases )
308 evaluator.
Evaluate( wxString::FromUTF8( expr ) );
318 BOOST_TEST_REQUIRE( repoReady() );
322 const std::vector<std::string> cases = {
323 "@{vcsnearestlabel()}",
324 "@{vcsnearestlabel(\"\")}",
325 "@{vcsnearestlabel(\"v*\")}",
326 "@{vcsnearestlabel(\"\", 0)}",
327 "@{vcsnearestlabel(\"\", 1)}",
329 "@{vcslabeldistance()}",
330 "@{vcslabeldistance(\"v*\")}",
331 "@{vcslabeldistance(\"\", 1)}",
334 std::regex numberPattern(
"^[0-9]+$" );
336 for(
const auto& expr : cases )
341 if( !
result.IsEmpty() && expr.find(
"distance" ) != std::string::npos )
343 BOOST_CHECK( std::regex_match(
result.ToStdString(), numberPattern ) );
353 BOOST_TEST_REQUIRE( repoReady() );
359 std::string expression;
363 const std::vector<TestCase> cases = {
364 {
"@{vcscommitdate()}", std::regex(
"^[0-9]{4}-[0-9]{2}-[0-9]{2}$" ) },
365 {
"@{vcscommitdate(\"ISO\")}", std::regex(
"^[0-9]{4}-[0-9]{2}-[0-9]{2}$" ) },
366 {
"@{vcscommitdate(\"US\")}", std::regex(
"^[0-9]{2}/[0-9]{2}/[0-9]{4}$" ) },
367 {
"@{vcscommitdate(\"EU\")}", std::regex(
"^[0-9]{2}/[0-9]{2}/[0-9]{4}$" ) },
369 {
"@{vcsfilecommitdate(\".\")}", std::regex(
"^[0-9]{4}-[0-9]{2}-[0-9]{2}$" ) },
372 for(
const auto& testCase : cases )
374 auto result = evaluator.
Evaluate( wxString::FromUTF8( testCase.expression ) );
376 BOOST_CHECK_MESSAGE( !evaluator.
HasErrors(),
377 "Error in expression: " + testCase.expression +
" Errors: "
380 BOOST_CHECK_MESSAGE( std::regex_match(
result.ToStdString(), testCase.pattern ),
381 "Bad date format for " + testCase.expression +
": "
391 BOOST_TEST_REQUIRE( repoReady() );
395 auto start = std::chrono::high_resolution_clock::now();
397 for(
int i = 0; i < 100; ++i )
403 auto end = std::chrono::high_resolution_clock::now();
404 auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(
end - start );
407#if defined( KICAD_SANITIZE_THREADS ) || defined( KICAD_SANITIZE_ADDRESS )
410 BOOST_CHECK_LT( duration.count(), 2000 );
419 BOOST_TEST_REQUIRE( repoReady() );
422 evaluator.
SetVariable( wxString(
"PROJECT" ), wxString(
"MyProject" ) );
424 const std::vector<std::string> cases = {
425 "Version: @{vcsbranch()}",
426 "Commit: @{vcsidentifier(7)}",
427 "Author: @{vcsauthor()} <@{vcsauthoremail()}>",
429 "${PROJECT} @{vcsbranch()}",
430 "Built from @{vcsnearestlabel()}@{vcsdirtysuffix()}",
432 "Distance: @{vcslabeldistance() + 0}",
435 for(
const auto& expr : cases )
440 BOOST_CHECK( !
result.IsEmpty() );
453 BOOST_TEST_REQUIRE( repoReady() );
457 wxString scratchDir = wxFileName::GetTempDir() + wxFileName::GetPathSeparator()
458 + wxString::Format(
"kicad_vcs_cli_%ld", wxGetProcessId() );
460 wxFileName::Mkdir( scratchDir, wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL );
461 wxSetWorkingDirectory( scratchDir );
463 auto cleanupCwd = [&]()
465 wxSetWorkingDirectory( tempDir() );
467 if( wxFileName::DirExists( scratchDir ) )
468 wxFileName::Rmdir( scratchDir, wxPATH_RMDIR_RECURSIVE );
476 auto noContext = evaluator.
Evaluate(
"@{vcsidentifier(7)}" );
484 auto hash = evaluator.
Evaluate(
"@{vcsidentifier(7)}" );
488 std::regex hexPattern(
"^[0-9a-f]+$" );
489 BOOST_CHECK( std::regex_match( hash.ToStdString(), hexPattern ) );
491 auto branch = evaluator.
Evaluate(
"@{vcsbranch()}" );
493 BOOST_CHECK( !branch.IsEmpty() );
494 BOOST_CHECK( branch != wxS(
"<unknown>" ) );
496 auto author = evaluator.
Evaluate(
"@{vcsauthor()}" );
502 auto afterScope = evaluator.
Evaluate(
"@{vcsidentifier(7)}" );
522 BOOST_TEST_REQUIRE( repoReady() );
524 wxString scratchDir = wxFileName::GetTempDir() + wxFileName::GetPathSeparator()
525 + wxString::Format(
"kicad_vcs_loadproject_%ld", wxGetProcessId() );
527 wxFileName::Mkdir( scratchDir, wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL );
528 wxSetWorkingDirectory( scratchDir );
532 wxString projectFile = tempDir() + wxFileName::GetPathSeparator()
533 + wxT(
"issue23959.kicad_pro" );
536 std::ofstream f( projectFile.ToStdString() );
537 f <<
"{ \"meta\": { \"filename\": \"issue23959.kicad_pro\", \"version\": 3 } }";
542 wxRemoveFile( projectFile );
543 wxSetWorkingDirectory( tempDir() );
545 if( wxFileName::DirExists( scratchDir ) )
546 wxFileName::Rmdir( scratchDir, wxPATH_RMDIR_RECURSIVE );
553 auto baseline = evaluator.
Evaluate(
"@{vcsidentifier(7)}" );
556 BOOST_REQUIRE(
Pgm().GetSettingsManager().LoadProject( projectFile,
true ) );
559 auto loaded = evaluator.
Evaluate(
"@{vcsidentifier(7)}" );
563 std::regex hexPattern(
"^[0-9a-f]+$" );
564 BOOST_CHECK( std::regex_match( loaded.ToStdString(), hexPattern ) );
570 auto afterUnload = evaluator.
Evaluate(
"@{vcsidentifier(7)}" );
High-level wrapper for evaluating mathematical and string expressions in wxString format.
wxString Evaluate(const wxString &aInput)
Main evaluation function - processes input string and evaluates all} expressions.
bool HasErrors() const
Check if the last evaluation had errors.
wxString GetErrorSummary() const
Get detailed error information from the last evaluation.
void SetVariable(const wxString &aName, double aValue)
Set a numeric variable for use in expressions.
virtual SETTINGS_MANAGER & GetSettingsManager() const
bool UnloadProject(PROJECT *aProject, bool aSave=true)
Save, unload and unregister the given PROJECT.
RAII helper that sets the VCS context path on construction and restores the previous value on destruc...
void SetGitBackend(GIT_BACKEND *aBackend)
PGM_BASE & Pgm()
The global program "get" accessor.
Fixture that creates a temporary git repo with one committed file.
LIBGIT_BACKEND * m_backend
TEXT_EVAL_VCS::CONTEXT_PATH_SCOPE m_context
const wxString & tempDir() const
const wxString & originalDir() const
BOOST_AUTO_TEST_CASE(HorizontalAlignment)
static const char * TEST_AUTHOR_NAME
static const char * TEST_AUTHOR_EMAIL
BOOST_REQUIRE(intersection.has_value()==c.ExpectedIntersection.has_value())
BOOST_AUTO_TEST_SUITE_END()
BOOST_TEST_MESSAGE("Polyline has "<< chain.PointCount()<< " points")
wxString result
Test unit parsing edge cases and error handling.
BOOST_CHECK_EQUAL(result, "25.4")
static const char * TEST_AUTHOR_NAME
static const char * TEST_AUTHOR_EMAIL
BOOST_AUTO_TEST_CASE(VcsIdentifierFormatting)
Test VCS identifier functions with various lengths.
static const char * TEST_COMMIT_MSG