46#include <wx/filename.h>
69 m_tempDir = wxFileName::GetTempDir() + wxFileName::GetPathSeparator()
70 + wxString::Format(
"kicad_vcs_test_%ld", wxGetProcessId() );
72 wxFileName::Mkdir(
m_tempDir, wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL );
85 wxFileName::Rmdir(
m_tempDir, wxPATH_RMDIR_RECURSIVE );
99 git_repository* repo =
nullptr;
101 if( git_repository_init( &repo,
m_tempDir.ToUTF8().data(), 0 ) != 0 )
105 git_config*
config =
nullptr;
107 if( git_repository_config( &
config, repo ) == 0 )
111 git_config_free(
config );
115 wxString filePath =
m_tempDir + wxFileName::GetPathSeparator() + wxT(
"test.txt" );
118 std::ofstream f( filePath.ToStdString() );
119 f <<
"test content\n";
123 git_index*
index =
nullptr;
125 if( git_repository_index( &
index, repo ) != 0 )
127 git_repository_free( repo );
131 git_index_add_bypath(
index,
"test.txt" );
132 git_index_write(
index );
137 if( git_index_write_tree( &treeOid,
index ) != 0 )
139 git_index_free(
index );
140 git_repository_free( repo );
144 git_index_free(
index );
146 git_tree* tree =
nullptr;
148 if( git_tree_lookup( &tree, repo, &treeOid ) != 0 )
150 git_repository_free( repo );
155 git_signature* sig =
nullptr;
159 git_tree_free( tree );
160 git_repository_free( repo );
165 int err = git_commit_create_v( &commitOid, repo,
"HEAD", sig, sig,
nullptr,
168 git_signature_free( sig );
169 git_tree_free( tree );
170 git_repository_free( repo );
188 BOOST_TEST_REQUIRE( repoReady() );
194 std::string expression;
198 const std::vector<TestCase> cases = {
199 {
"@{vcsidentifier()}", 40 },
200 {
"@{vcsidentifier(40)}", 40 },
201 {
"@{vcsidentifier(7)}", 7 },
202 {
"@{vcsidentifier(8)}", 8 },
203 {
"@{vcsidentifier(12)}", 12 },
204 {
"@{vcsidentifier(4)}", 4 },
206 {
"@{vcsfileidentifier(\".\")}", 40 },
207 {
"@{vcsfileidentifier(\".\", 8)}", 8 },
210 std::regex hexPattern(
"^[0-9a-f]+$" );
212 for(
const auto& testCase : cases )
214 auto result = evaluator.
Evaluate( wxString::FromUTF8( testCase.expression ) );
217 "Error in expression: " + testCase.expression +
" Errors: "
221 BOOST_CHECK( std::regex_match(
result.ToStdString(), hexPattern ) );
230 BOOST_TEST_REQUIRE( repoReady() );
234 auto branch = evaluator.
Evaluate(
"@{vcsbranch()}" );
236 BOOST_CHECK( !branch.IsEmpty() );
238 auto authorEmail = evaluator.
Evaluate(
"@{vcsauthoremail()}" );
242 auto committerEmail = evaluator.
Evaluate(
"@{vcscommitteremail()}" );
246 auto author = evaluator.
Evaluate(
"@{vcsauthor()}" );
250 auto committer = evaluator.
Evaluate(
"@{vcscommitter()}" );
255 auto fileAuthorEmail = evaluator.
Evaluate(
"@{vcsfileauthoremail(\".\")}" );
259 auto fileCommitterEmail = evaluator.
Evaluate(
"@{vcsfilecommitteremail(\".\")}" );
269 BOOST_TEST_REQUIRE( repoReady() );
275 std::string expression;
278 const std::vector<TestCase> cases = {
280 {
"@{vcsdirty(0)}" },
281 {
"@{vcsdirty(1)}" },
284 for(
const auto& testCase : cases )
286 auto result = evaluator.
Evaluate( wxString::FromUTF8( testCase.expression ) );
298 BOOST_TEST_REQUIRE( repoReady() );
302 const std::vector<std::string> cases = {
303 "@{vcsdirtysuffix()}",
304 "@{vcsdirtysuffix(\"-modified\")}",
305 "@{vcsdirtysuffix(\"+\", 1)}",
308 for(
const auto& expr : cases )
310 evaluator.
Evaluate( wxString::FromUTF8( expr ) );
320 BOOST_TEST_REQUIRE( repoReady() );
324 const std::vector<std::string> cases = {
325 "@{vcsnearestlabel()}",
326 "@{vcsnearestlabel(\"\")}",
327 "@{vcsnearestlabel(\"v*\")}",
328 "@{vcsnearestlabel(\"\", 0)}",
329 "@{vcsnearestlabel(\"\", 1)}",
331 "@{vcslabeldistance()}",
332 "@{vcslabeldistance(\"v*\")}",
333 "@{vcslabeldistance(\"\", 1)}",
336 std::regex numberPattern(
"^[0-9]+$" );
338 for(
const auto& expr : cases )
343 if( !
result.IsEmpty() && expr.find(
"distance" ) != std::string::npos )
345 BOOST_CHECK( std::regex_match(
result.ToStdString(), numberPattern ) );
355 BOOST_TEST_REQUIRE( repoReady() );
361 std::string expression;
365 const std::vector<TestCase> cases = {
366 {
"@{vcscommitdate()}", std::regex(
"^[0-9]{4}-[0-9]{2}-[0-9]{2}$" ) },
367 {
"@{vcscommitdate(\"ISO\")}", std::regex(
"^[0-9]{4}-[0-9]{2}-[0-9]{2}$" ) },
368 {
"@{vcscommitdate(\"US\")}", std::regex(
"^[0-9]{2}/[0-9]{2}/[0-9]{4}$" ) },
369 {
"@{vcscommitdate(\"EU\")}", std::regex(
"^[0-9]{2}/[0-9]{2}/[0-9]{4}$" ) },
371 {
"@{vcsfilecommitdate(\".\")}", std::regex(
"^[0-9]{4}-[0-9]{2}-[0-9]{2}$" ) },
374 for(
const auto& testCase : cases )
376 auto result = evaluator.
Evaluate( wxString::FromUTF8( testCase.expression ) );
379 "Error in expression: " + testCase.expression +
" Errors: "
383 "Bad date format for " + testCase.expression +
": "
393 BOOST_TEST_REQUIRE( repoReady() );
397 auto start = std::chrono::high_resolution_clock::now();
399 for(
int i = 0; i < 100; ++i )
405 auto end = std::chrono::high_resolution_clock::now();
406 auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(
end - start );
408 BOOST_CHECK_LT( duration.count(), 2000 );
416 BOOST_TEST_REQUIRE( repoReady() );
419 evaluator.
SetVariable( wxString(
"PROJECT" ), wxString(
"MyProject" ) );
421 const std::vector<std::string> cases = {
422 "Version: @{vcsbranch()}",
423 "Commit: @{vcsidentifier(7)}",
424 "Author: @{vcsauthor()} <@{vcsauthoremail()}>",
426 "${PROJECT} @{vcsbranch()}",
427 "Built from @{vcsnearestlabel()}@{vcsdirtysuffix()}",
429 "Distance: @{vcslabeldistance() + 0}",
432 for(
const auto& expr : cases )
437 BOOST_CHECK( !
result.IsEmpty() );
450 BOOST_TEST_REQUIRE( repoReady() );
454 wxString scratchDir = wxFileName::GetTempDir() + wxFileName::GetPathSeparator()
455 + wxString::Format(
"kicad_vcs_cli_%ld", wxGetProcessId() );
457 wxFileName::Mkdir( scratchDir, wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL );
458 wxSetWorkingDirectory( scratchDir );
460 auto cleanupCwd = [&]()
462 wxSetWorkingDirectory( tempDir() );
464 if( wxFileName::DirExists( scratchDir ) )
465 wxFileName::Rmdir( scratchDir, wxPATH_RMDIR_RECURSIVE );
473 auto noContext = evaluator.
Evaluate(
"@{vcsidentifier(7)}" );
481 auto hash = evaluator.
Evaluate(
"@{vcsidentifier(7)}" );
485 std::regex hexPattern(
"^[0-9a-f]+$" );
486 BOOST_CHECK( std::regex_match( hash.ToStdString(), hexPattern ) );
488 auto branch = evaluator.
Evaluate(
"@{vcsbranch()}" );
490 BOOST_CHECK( !branch.IsEmpty() );
491 BOOST_CHECK( branch != wxS(
"<unknown>" ) );
493 auto author = evaluator.
Evaluate(
"@{vcsauthor()}" );
499 auto afterScope = evaluator.
Evaluate(
"@{vcsidentifier(7)}" );
519 BOOST_TEST_REQUIRE( repoReady() );
521 wxString scratchDir = wxFileName::GetTempDir() + wxFileName::GetPathSeparator()
522 + wxString::Format(
"kicad_vcs_loadproject_%ld", wxGetProcessId() );
524 wxFileName::Mkdir( scratchDir, wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL );
525 wxSetWorkingDirectory( scratchDir );
529 wxString projectFile = tempDir() + wxFileName::GetPathSeparator()
530 + wxT(
"issue23959.kicad_pro" );
533 std::ofstream f( projectFile.ToStdString() );
534 f <<
"{ \"meta\": { \"filename\": \"issue23959.kicad_pro\", \"version\": 3 } }";
539 wxRemoveFile( projectFile );
540 wxSetWorkingDirectory( tempDir() );
542 if( wxFileName::DirExists( scratchDir ) )
543 wxFileName::Rmdir( scratchDir, wxPATH_RMDIR_RECURSIVE );
550 auto baseline = evaluator.
Evaluate(
"@{vcsidentifier(7)}" );
553 BOOST_REQUIRE(
Pgm().GetSettingsManager().LoadProject( projectFile,
true ) );
556 auto loaded = evaluator.
Evaluate(
"@{vcsidentifier(7)}" );
560 std::regex hexPattern(
"^[0-9a-f]+$" );
561 BOOST_CHECK( std::regex_match( loaded.ToStdString(), hexPattern ) );
567 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)
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