| /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying |
| file LICENSE.rst or https://cmake.org/licensing for details. */ |
| #include <iostream> |
| #include <string> |
| |
| #include <cm/memory> |
| |
| #include "cmGeneratorExpression.h" |
| #include "cmGlobalGenerator.h" |
| #include "cmLocalGenerator.h" |
| #include "cmMakefile.h" |
| #include "cmState.h" |
| #include "cmStateDirectory.h" |
| #include "cmStateSnapshot.h" |
| #include "cmake.h" |
| |
| namespace { |
| struct GenExFixture |
| { |
| cmake CMake{ cmState::Role::Project }; |
| std::unique_ptr<cmGlobalGenerator> GG; |
| std::unique_ptr<cmMakefile> MF; |
| std::unique_ptr<cmLocalGenerator> LG; |
| |
| GenExFixture() |
| { |
| this->GG = cm::make_unique<cmGlobalGenerator>(&this->CMake); |
| cmStateSnapshot snapshot = this->CMake.GetCurrentSnapshot(); |
| snapshot.GetDirectory().SetCurrentBinary("."); |
| snapshot.GetDirectory().SetCurrentSource("."); |
| this->MF = cm::make_unique<cmMakefile>(this->GG.get(), snapshot); |
| this->LG = this->GG->CreateLocalGenerator(this->MF.get()); |
| } |
| |
| std::string Eval(std::string const& expr) |
| { |
| return cmGeneratorExpression::Evaluate(expr, this->LG.get(), "Debug"); |
| } |
| }; |
| |
| bool expectEq(char const* name, std::string const& got, |
| std::string const& want) |
| { |
| if (got != want) { |
| std::cerr << name << ": expected '" << want << "', got '" << got << "'\n"; |
| return false; |
| } |
| return true; |
| } |
| } |
| |
| static bool testFilterPredicateInclude() |
| { |
| GenExFixture fx; |
| // Keep only elements equal to "a". |
| return expectEq( |
| "testFilterPredicateInclude", |
| fx.Eval("$<LIST:FILTER,a;b;a;c,INCLUDE,PREDICATE,$<STREQUAL:$<_0>,a>>"), |
| "a;a"); |
| } |
| |
| static bool testFilterPredicateExclude() |
| { |
| GenExFixture fx; |
| // Drop elements equal to "a". |
| return expectEq( |
| "testFilterPredicateExclude", |
| fx.Eval("$<LIST:FILTER,a;b;a;c,EXCLUDE,PREDICATE,$<STREQUAL:$<_0>,a>>"), |
| "b;c"); |
| } |
| |
| static bool testFilterRegexKeyword() |
| { |
| GenExFixture fx; |
| // Explicit REGEX keyword behaves like the bare form. |
| return expectEq("testFilterRegexKeyword", |
| fx.Eval("$<LIST:FILTER,foo;bar;baz,INCLUDE,REGEX,^ba>"), |
| "bar;baz"); |
| } |
| |
| static bool testFilterBareRegexUnchanged() |
| { |
| GenExFixture fx; |
| // The legacy bare form still works. |
| return expectEq("testFilterBareRegexUnchanged", |
| fx.Eval("$<LIST:FILTER,foo;bar;baz,EXCLUDE,^ba>"), "foo"); |
| } |
| |
| static bool testCannedTransformStillWorks() |
| { |
| GenExFixture fx; |
| // Existing canned action + REGEX selector must be unaffected by the |
| // refactor. |
| return expectEq("testCannedTransformStillWorks", |
| fx.Eval("$<LIST:TRANSFORM,foo;bar;baz,TOUPPER,REGEX,^ba>"), |
| "foo;BAR;BAZ"); |
| } |
| |
| static bool testTransformPredicateCanned() |
| { |
| GenExFixture fx; |
| // PREPEND "X-" only to elements equal to "a"; others pass through. |
| return expectEq( |
| "testTransformPredicateCanned", |
| fx.Eval( |
| "$<LIST:TRANSFORM,a;b;a,PREPEND,X-,PREDICATE,$<STREQUAL:$<_0>,a>>"), |
| "X-a;b;X-a"); |
| } |
| |
| static bool testTransformPredicateNoneSelected() |
| { |
| GenExFixture fx; |
| // No element matches: the list is returned unchanged. |
| return expectEq("testTransformPredicateNoneSelected", |
| fx.Eval("$<LIST:TRANSFORM,a;b;c,TOUPPER,PREDICATE,0>"), |
| "a;b;c"); |
| } |
| |
| static bool testTransformPredicateApply() |
| { |
| GenExFixture fx; |
| // Upper-case only elements equal to "a"; "b" passes through unchanged. |
| return expectEq("testTransformPredicateApply", |
| fx.Eval("$<LIST:TRANSFORM,a;b;a,APPLY,$<UPPER_CASE:$<_0>>," |
| "PREDICATE,$<STREQUAL:$<_0>,a>>"), |
| "A;b;A"); |
| } |
| |
| static bool testTransformPredicateApplyShadowing() |
| { |
| GenExFixture fx; |
| // The apply body and predicate body each independently bind $<_0>. |
| return expectEq("testTransformPredicateApplyShadowing", |
| fx.Eval("$<LIST:TRANSFORM,a;bb,APPLY,$<_0>$<_0>,PREDICATE," |
| "$<STREQUAL:$<_0>,a>>"), |
| "aa;bb"); |
| } |
| |
| static bool testFilterPredicateEmptyList() |
| { |
| GenExFixture fx; |
| return expectEq("testFilterPredicateEmptyList", |
| fx.Eval("$<LIST:FILTER,,INCLUDE,PREDICATE,1>"), ""); |
| } |
| |
| static bool testTransformPredicateEmptyList() |
| { |
| GenExFixture fx; |
| return expectEq("testTransformPredicateEmptyList", |
| fx.Eval("$<LIST:TRANSFORM,,TOUPPER,PREDICATE,1>"), ""); |
| } |
| |
| int testGenExListPredicate(int /*argc*/, char* /*argv*/[]) |
| { |
| if (!testFilterPredicateInclude()) { |
| return 1; |
| } |
| if (!testFilterPredicateExclude()) { |
| return 1; |
| } |
| if (!testFilterRegexKeyword()) { |
| return 1; |
| } |
| if (!testFilterBareRegexUnchanged()) { |
| return 1; |
| } |
| if (!testCannedTransformStillWorks()) { |
| return 1; |
| } |
| if (!testTransformPredicateCanned()) { |
| return 1; |
| } |
| if (!testTransformPredicateNoneSelected()) { |
| return 1; |
| } |
| if (!testTransformPredicateApply()) { |
| return 1; |
| } |
| if (!testTransformPredicateApplyShadowing()) { |
| return 1; |
| } |
| if (!testFilterPredicateEmptyList()) { |
| return 1; |
| } |
| if (!testTransformPredicateEmptyList()) { |
| return 1; |
| } |
| return 0; |
| } |