40#include <wx/filename.h>
87 std::string expression;
91 const std::vector<TestCase> cases = {
92 {
"@{vcsidentifier()}", 40 },
93 {
"@{vcsidentifier(40)}", 40 },
94 {
"@{vcsidentifier(7)}", 7 },
95 {
"@{vcsidentifier(8)}", 8 },
96 {
"@{vcsidentifier(12)}", 12 },
97 {
"@{vcsidentifier(4)}", 4 },
99 {
"@{vcsfileidentifier(\".\")}", 40 },
100 {
"@{vcsfileidentifier(\".\", 8)}", 8 },
103 std::regex hexPattern(
"^[0-9a-f]+$" );
105 for(
const auto& testCase : cases )
107 auto result = evaluator.
Evaluate( wxString::FromUTF8( testCase.expression ) );
109 BOOST_CHECK_MESSAGE( !evaluator.
HasErrors(),
110 "Error in expression: " + testCase.expression +
" Errors: "
114 BOOST_CHECK( std::regex_match(
result.ToStdString(), hexPattern ) );
125 auto branch = evaluator.
Evaluate(
"@{vcsbranch()}" );
127 BOOST_CHECK( !branch.IsEmpty() );
129 auto authorEmail = evaluator.
Evaluate(
"@{vcsauthoremail()}" );
133 auto committerEmail = evaluator.
Evaluate(
"@{vcscommitteremail()}" );
137 auto author = evaluator.
Evaluate(
"@{vcsauthor()}" );
141 auto committer = evaluator.
Evaluate(
"@{vcscommitter()}" );
146 auto fileAuthorEmail = evaluator.
Evaluate(
"@{vcsfileauthoremail(\".\")}" );
150 auto fileCommitterEmail = evaluator.
Evaluate(
"@{vcsfilecommitteremail(\".\")}" );
164 std::string expression;
167 const std::vector<TestCase> cases = {
169 {
"@{vcsdirty(0)}" },
170 {
"@{vcsdirty(1)}" },
173 for(
const auto& testCase : cases )
175 auto result = evaluator.
Evaluate( wxString::FromUTF8( testCase.expression ) );
189 const std::vector<std::string> cases = {
190 "@{vcsdirtysuffix()}",
191 "@{vcsdirtysuffix(\"-modified\")}",
192 "@{vcsdirtysuffix(\"+\", 1)}",
195 for(
const auto& expr : cases )
197 evaluator.
Evaluate( wxString::FromUTF8( expr ) );
209 const std::vector<std::string> cases = {
210 "@{vcsnearestlabel()}",
211 "@{vcsnearestlabel(\"\")}",
212 "@{vcsnearestlabel(\"v*\")}",
213 "@{vcsnearestlabel(\"\", 0)}",
214 "@{vcsnearestlabel(\"\", 1)}",
216 "@{vcslabeldistance()}",
217 "@{vcslabeldistance(\"v*\")}",
218 "@{vcslabeldistance(\"\", 1)}",
221 std::regex numberPattern(
"^[0-9]+$" );
223 for(
const auto& expr : cases )
228 if( !
result.IsEmpty() && expr.find(
"distance" ) != std::string::npos )
230 BOOST_CHECK( std::regex_match(
result.ToStdString(), numberPattern ) );
244 std::string expression;
248 const std::vector<TestCase> cases = {
249 {
"@{vcscommitdate()}", std::regex(
"^[0-9]{4}-[0-9]{2}-[0-9]{2}$" ) },
250 {
"@{vcscommitdate(\"ISO\")}", std::regex(
"^[0-9]{4}-[0-9]{2}-[0-9]{2}$" ) },
251 {
"@{vcscommitdate(\"US\")}", std::regex(
"^[0-9]{2}/[0-9]{2}/[0-9]{4}$" ) },
252 {
"@{vcscommitdate(\"EU\")}", std::regex(
"^[0-9]{2}/[0-9]{2}/[0-9]{4}$" ) },
254 {
"@{vcsfilecommitdate(\".\")}", std::regex(
"^[0-9]{4}-[0-9]{2}-[0-9]{2}$" ) },
257 for(
const auto& testCase : cases )
259 auto result = evaluator.
Evaluate( wxString::FromUTF8( testCase.expression ) );
261 BOOST_CHECK_MESSAGE( !evaluator.
HasErrors(),
262 "Error in expression: " + testCase.expression +
" Errors: "
265 BOOST_CHECK_MESSAGE( std::regex_match(
result.ToStdString(), testCase.pattern ),
266 "Bad date format for " + testCase.expression +
": "
278 auto start = std::chrono::high_resolution_clock::now();
280 for(
int i = 0; i < 100; ++i )
286 auto end = std::chrono::high_resolution_clock::now();
287 auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(
end - start );
290#if defined( KICAD_SANITIZE_THREADS ) || defined( KICAD_SANITIZE_ADDRESS )
293 BOOST_CHECK_LT( duration.count(), 2000 );
303 evaluator.
SetVariable( wxString(
"PROJECT" ), wxString(
"MyProject" ) );
305 const std::vector<std::string> cases = {
306 "Version: @{vcsbranch()}",
307 "Commit: @{vcsidentifier(7)}",
308 "Author: @{vcsauthor()} <@{vcsauthoremail()}>",
310 "${PROJECT} @{vcsbranch()}",
311 "Built from @{vcsnearestlabel()}@{vcsdirtysuffix()}",
313 "Distance: @{vcslabeldistance() + 0}",
316 for(
const auto& expr : cases )
321 BOOST_CHECK( !
result.IsEmpty() );
336 wxString scratchDir = wxFileName::GetTempDir() + wxFileName::GetPathSeparator()
337 + wxString::Format(
"kicad_vcs_cli_%ld", wxGetProcessId() );
339 wxFileName::Mkdir( scratchDir, wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL );
340 wxSetWorkingDirectory( scratchDir );
342 auto cleanupCwd = [&]()
344 wxSetWorkingDirectory( tempDir() );
346 if( wxFileName::DirExists( scratchDir ) )
347 wxFileName::Rmdir( scratchDir, wxPATH_RMDIR_RECURSIVE );
355 auto noContext = evaluator.
Evaluate(
"@{vcsidentifier(7)}" );
363 auto hash = evaluator.
Evaluate(
"@{vcsidentifier(7)}" );
367 std::regex hexPattern(
"^[0-9a-f]+$" );
368 BOOST_CHECK( std::regex_match( hash.ToStdString(), hexPattern ) );
370 auto branch = evaluator.
Evaluate(
"@{vcsbranch()}" );
372 BOOST_CHECK( !branch.IsEmpty() );
373 BOOST_CHECK( branch != wxS(
"<unknown>" ) );
375 auto author = evaluator.
Evaluate(
"@{vcsauthor()}" );
381 auto afterScope = evaluator.
Evaluate(
"@{vcsidentifier(7)}" );
401 wxString scratchDir = wxFileName::GetTempDir() + wxFileName::GetPathSeparator()
402 + wxString::Format(
"kicad_vcs_loadproject_%ld", wxGetProcessId() );
404 wxFileName::Mkdir( scratchDir, wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL );
405 wxSetWorkingDirectory( scratchDir );
409 wxString projectFile = tempDir() + wxFileName::GetPathSeparator()
410 + wxT(
"issue23959.kicad_pro" );
413 std::ofstream f( projectFile.ToStdString() );
414 f <<
"{ \"meta\": { \"filename\": \"issue23959.kicad_pro\", \"version\": 3 } }";
419 wxRemoveFile( projectFile );
420 wxSetWorkingDirectory( tempDir() );
422 if( wxFileName::DirExists( scratchDir ) )
423 wxFileName::Rmdir( scratchDir, wxPATH_RMDIR_RECURSIVE );
430 auto baseline = evaluator.
Evaluate(
"@{vcsidentifier(7)}" );
433 BOOST_REQUIRE(
Pgm().GetSettingsManager().LoadProject( projectFile,
true ) );
436 auto loaded = evaluator.
Evaluate(
"@{vcsidentifier(7)}" );
440 std::regex hexPattern(
"^[0-9a-f]+$" );
441 BOOST_CHECK( std::regex_match( loaded.ToStdString(), hexPattern ) );
448 auto afterUnload = evaluator.
Evaluate(
"@{vcsidentifier(7)}" );
464 wxString projectPath = tempDir() + wxFileName::GetPathSeparator() + wxT(
"ctx.kicad_pro" );
467 std::ofstream f( projectPath.ToStdString() );
468 f <<
"{\"meta\": {\"filename\": \"ctx.kicad_pro\", \"version\": 3}}";
473 BOOST_TEST_REQUIRE( mgr.
LoadProject( projectPath ) );
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.
Give each test a backend and a temporary directory.
const wxString & TempPath() const
virtual SETTINGS_MANAGER & GetSettingsManager() const
bool LoadProject(const wxString &aFullPath, bool aSetActive=true)
Load a project or sets up a new project with a specified path.
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...
static std::string ToStdString(const wxString &aStr)
std::unique_ptr< git_repository, decltype([](git_repository *aRepo) { git_repository_free(aRepo); })> GitRepositoryPtr
A unique pointer for git_repository objects with automatic cleanup.
KIGIT::GitRepositoryPtr InitGitRepository(const wxString &aPath, const char *aBranch="main", const char *aAuthorName="QA Test", const char *aAuthorEmail="
[email protected]")
Pin the branch and author so repository setup does not depend on the user's Git config.
void WriteGitFile(const wxString &aRepoPath, const wxString &aRelativePath, const std::string &aContents)
Write test data without staging it. Create parent directories when needed.
git_oid CommitGitFile(git_repository *aRepo, const wxString &aPath, const wxString &aMessage)
Stage one file and commit the index. Other staged changes are kept.
wxString GetContextPath()
Return the current context path for repo-scoped VCS queries.
PGM_BASE & Pgm()
The global program "get" accessor.
Fixture that creates a temporary git repo with one committed file.
TEXT_EVAL_VCS::CONTEXT_PATH_SCOPE m_context
const wxString & tempDir() 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