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 );
184 BOOST_TEST_REQUIRE( repoReady() );
190 std::string expression;
194 const std::vector<TestCase> cases = {
195 {
"@{vcsidentifier()}", 40 },
196 {
"@{vcsidentifier(40)}", 40 },
197 {
"@{vcsidentifier(7)}", 7 },
198 {
"@{vcsidentifier(8)}", 8 },
199 {
"@{vcsidentifier(12)}", 12 },
200 {
"@{vcsidentifier(4)}", 4 },
202 {
"@{vcsfileidentifier(\".\")}", 40 },
203 {
"@{vcsfileidentifier(\".\", 8)}", 8 },
206 std::regex hexPattern(
"^[0-9a-f]+$" );
208 for(
const auto& testCase : cases )
210 auto result = evaluator.
Evaluate( wxString::FromUTF8( testCase.expression ) );
213 "Error in expression: " + testCase.expression +
" Errors: "
217 BOOST_CHECK( std::regex_match(
result.ToStdString(), hexPattern ) );
226 BOOST_TEST_REQUIRE( repoReady() );
230 auto branch = evaluator.
Evaluate(
"@{vcsbranch()}" );
232 BOOST_CHECK( !branch.IsEmpty() );
234 auto authorEmail = evaluator.
Evaluate(
"@{vcsauthoremail()}" );
238 auto committerEmail = evaluator.
Evaluate(
"@{vcscommitteremail()}" );
242 auto author = evaluator.
Evaluate(
"@{vcsauthor()}" );
246 auto committer = evaluator.
Evaluate(
"@{vcscommitter()}" );
251 auto fileAuthorEmail = evaluator.
Evaluate(
"@{vcsfileauthoremail(\".\")}" );
255 auto fileCommitterEmail = evaluator.
Evaluate(
"@{vcsfilecommitteremail(\".\")}" );
265 BOOST_TEST_REQUIRE( repoReady() );
271 std::string expression;
274 const std::vector<TestCase> cases = {
276 {
"@{vcsdirty(0)}" },
277 {
"@{vcsdirty(1)}" },
280 for(
const auto& testCase : cases )
282 auto result = evaluator.
Evaluate( wxString::FromUTF8( testCase.expression ) );
294 BOOST_TEST_REQUIRE( repoReady() );
298 const std::vector<std::string> cases = {
299 "@{vcsdirtysuffix()}",
300 "@{vcsdirtysuffix(\"-modified\")}",
301 "@{vcsdirtysuffix(\"+\", 1)}",
304 for(
const auto& expr : cases )
306 evaluator.
Evaluate( wxString::FromUTF8( expr ) );
316 BOOST_TEST_REQUIRE( repoReady() );
320 const std::vector<std::string> cases = {
321 "@{vcsnearestlabel()}",
322 "@{vcsnearestlabel(\"\")}",
323 "@{vcsnearestlabel(\"v*\")}",
324 "@{vcsnearestlabel(\"\", 0)}",
325 "@{vcsnearestlabel(\"\", 1)}",
327 "@{vcslabeldistance()}",
328 "@{vcslabeldistance(\"v*\")}",
329 "@{vcslabeldistance(\"\", 1)}",
332 std::regex numberPattern(
"^[0-9]+$" );
334 for(
const auto& expr : cases )
339 if( !
result.IsEmpty() && expr.find(
"distance" ) != std::string::npos )
341 BOOST_CHECK( std::regex_match(
result.ToStdString(), numberPattern ) );
351 BOOST_TEST_REQUIRE( repoReady() );
357 std::string expression;
361 const std::vector<TestCase> cases = {
362 {
"@{vcscommitdate()}", std::regex(
"^[0-9]{4}-[0-9]{2}-[0-9]{2}$" ) },
363 {
"@{vcscommitdate(\"ISO\")}", std::regex(
"^[0-9]{4}-[0-9]{2}-[0-9]{2}$" ) },
364 {
"@{vcscommitdate(\"US\")}", std::regex(
"^[0-9]{2}/[0-9]{2}/[0-9]{4}$" ) },
365 {
"@{vcscommitdate(\"EU\")}", std::regex(
"^[0-9]{2}/[0-9]{2}/[0-9]{4}$" ) },
367 {
"@{vcsfilecommitdate(\".\")}", std::regex(
"^[0-9]{4}-[0-9]{2}-[0-9]{2}$" ) },
370 for(
const auto& testCase : cases )
372 auto result = evaluator.
Evaluate( wxString::FromUTF8( testCase.expression ) );
375 "Error in expression: " + testCase.expression +
" Errors: "
379 "Bad date format for " + testCase.expression +
": "
389 BOOST_TEST_REQUIRE( repoReady() );
393 auto start = std::chrono::high_resolution_clock::now();
395 for(
int i = 0; i < 100; ++i )
401 auto end = std::chrono::high_resolution_clock::now();
402 auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(
end - start );
404 BOOST_CHECK_LT( duration.count(), 2000 );
412 BOOST_TEST_REQUIRE( repoReady() );
415 evaluator.
SetVariable( wxString(
"PROJECT" ), wxString(
"MyProject" ) );
417 const std::vector<std::string> cases = {
418 "Version: @{vcsbranch()}",
419 "Commit: @{vcsidentifier(7)}",
420 "Author: @{vcsauthor()} <@{vcsauthoremail()}>",
422 "${PROJECT} @{vcsbranch()}",
423 "Built from @{vcsnearestlabel()}@{vcsdirtysuffix()}",
425 "Distance: @{vcslabeldistance() + 0}",
428 for(
const auto& expr : cases )
433 BOOST_CHECK( !
result.IsEmpty() );
446 BOOST_TEST_REQUIRE( repoReady() );
450 wxString scratchDir = wxFileName::GetTempDir() + wxFileName::GetPathSeparator()
451 + wxString::Format(
"kicad_vcs_cli_%ld", wxGetProcessId() );
453 wxFileName::Mkdir( scratchDir, wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL );
454 wxSetWorkingDirectory( scratchDir );
456 auto cleanupCwd = [&]()
458 wxSetWorkingDirectory( tempDir() );
460 if( wxFileName::DirExists( scratchDir ) )
461 wxFileName::Rmdir( scratchDir, wxPATH_RMDIR_RECURSIVE );
469 auto noContext = evaluator.
Evaluate(
"@{vcsidentifier(7)}" );
477 auto hash = evaluator.
Evaluate(
"@{vcsidentifier(7)}" );
481 std::regex hexPattern(
"^[0-9a-f]+$" );
482 BOOST_CHECK( std::regex_match( hash.ToStdString(), hexPattern ) );
484 auto branch = evaluator.
Evaluate(
"@{vcsbranch()}" );
486 BOOST_CHECK( !branch.IsEmpty() );
487 BOOST_CHECK( branch != wxS(
"<unknown>" ) );
489 auto author = evaluator.
Evaluate(
"@{vcsauthor()}" );
495 auto afterScope = evaluator.
Evaluate(
"@{vcsidentifier(7)}" );
515 BOOST_TEST_REQUIRE( repoReady() );
517 wxString scratchDir = wxFileName::GetTempDir() + wxFileName::GetPathSeparator()
518 + wxString::Format(
"kicad_vcs_loadproject_%ld", wxGetProcessId() );
520 wxFileName::Mkdir( scratchDir, wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL );
521 wxSetWorkingDirectory( scratchDir );
525 wxString projectFile = tempDir() + wxFileName::GetPathSeparator()
526 + wxT(
"issue23959.kicad_pro" );
529 std::ofstream f( projectFile.ToStdString() );
530 f <<
"{ \"meta\": { \"filename\": \"issue23959.kicad_pro\", \"version\": 3 } }";
535 wxRemoveFile( projectFile );
536 wxSetWorkingDirectory( tempDir() );
538 if( wxFileName::DirExists( scratchDir ) )
539 wxFileName::Rmdir( scratchDir, wxPATH_RMDIR_RECURSIVE );
546 auto baseline = evaluator.
Evaluate(
"@{vcsidentifier(7)}" );
549 BOOST_REQUIRE(
Pgm().GetSettingsManager().LoadProject( projectFile,
true ) );
552 auto loaded = evaluator.
Evaluate(
"@{vcsidentifier(7)}" );
556 std::regex hexPattern(
"^[0-9a-f]+$" );
557 BOOST_CHECK( std::regex_match( loaded.ToStdString(), hexPattern ) );
563 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
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_CHECK_MESSAGE(totalMismatches==0, std::to_string(totalMismatches)+" board(s) with strategy disagreements")
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