#include #include "StringProcessing.h" namespace { typedef StringProcessing::VariableValues VariableValues; typedef StringProcessing::VariableNameList VariableNameList; typedef std::tuple TokenizeTestSpec; class TokenizeTestSpecBuilder { public: TokenizeTestSpecBuilder& str(tstring::const_pointer v) { theStr = v; return *this; } TokenizeTestSpecBuilder& expectStr(tstring::const_pointer v) { theExpectedStr = std::make_unique(v); return *this; } TokenizeTestSpecBuilder& expectVar(tstring::const_pointer v) { theExpectedVarNames.push_back(v); return *this; } TokenizeTestSpec create() const { return std::make_tuple(theStr, expectedStr(), theExpectedVarNames); } private: tstring expectedStr() const { if (theExpectedStr) { return *theExpectedStr; } else { return theStr; } } private: tstring theStr; std::unique_ptr theExpectedStr; VariableNameList theExpectedVarNames; }; class TokenizeTest :public ::testing::TestWithParam {}; } // namespace TEST_P(TokenizeTest, Test) { const auto params = GetParam(); const auto str = std::get<0>(params); const auto expectedStr = std::get<1>(params); auto expectedVarNames = std::get<2>(params); std::sort(expectedVarNames.begin(), expectedVarNames.end()); const auto tokens = StringProcessing::tokenize(str); auto actualVarNames = StringProcessing::extractVariableNames(tokens); std::sort(actualVarNames.begin(), actualVarNames.end()); EXPECT_EQ(expectedVarNames, actualVarNames); const auto actualStr = StringProcessing::stringify(tokens); EXPECT_EQ(expectedStr, actualStr); } INSTANTIATE_TEST_CASE_P(StringProcessingTests, TokenizeTest, ::testing::Values( TokenizeTestSpecBuilder().create(), TokenizeTestSpecBuilder().str(_T("foo")).create(), TokenizeTestSpecBuilder().str(_T("\\")).create(), TokenizeTestSpecBuilder().str(_T("$")).create(), TokenizeTestSpecBuilder().str(_T("$\\\\")).expectStr(_T("$\\")).create(), TokenizeTestSpecBuilder().str(_T("${")).create(), TokenizeTestSpecBuilder().str(_T("${}")).expectVar(_T("")).create(), TokenizeTestSpecBuilder().str(_T("$98")).create(), TokenizeTestSpecBuilder().str(_T("foo$_b$a|r")).expectVar(_T("_b")).expectVar(_T("a")).create(), TokenizeTestSpecBuilder().str(_T("$9{8}")).create(), TokenizeTestSpecBuilder().str(_T("$a")).expectVar(_T("a")).create(), TokenizeTestSpecBuilder().str(_T("${a}")).expectVar(_T("a")).create(), TokenizeTestSpecBuilder().str(_T("${a$\\$b}")).expectStr(_T("${a$\\$b}")).expectVar(_T("a$\\$b")).create(), TokenizeTestSpecBuilder().str(_T("b $a ${a} $a")).expectVar(_T("a")).create(), TokenizeTestSpecBuilder().str(_T("foo $a $bar%")).expectVar(_T("a")).expectVar(_T("bar")).create(), TokenizeTestSpecBuilder().str(_T("foo $a $bar")).expectVar(_T("a")).expectVar(_T("bar")).create(), TokenizeTestSpecBuilder().str(_T("foo $a ${bar")).expectVar(_T("a")).create(), TokenizeTestSpecBuilder().str(_T("foo ${a} ${bar}%")).expectVar(_T("a")).expectVar(_T("bar")).create(), TokenizeTestSpecBuilder().str(_T("The ${lazy} \\$dog ${has had} enough")).expectStr(_T("The ${lazy} $dog ${has had} enough")).expectVar(_T("lazy")).expectVar(_T("has had")).create(), TokenizeTestSpecBuilder().str(_T(" \\$${foo} ")).expectStr(_T(" $${foo} ")).expectVar(_T("foo")).create(), TokenizeTestSpecBuilder().str(_T(" \\$${fo$o} ")).expectStr(_T(" $${fo$o} ")).expectVar(_T("fo$o")).create(), TokenizeTestSpecBuilder().str(_T("\\$foo")).expectStr(_T("$foo")).create(), TokenizeTestSpecBuilder().str(_T("\\\\$foo")).expectStr(_T("\\$foo")).expectVar(_T("foo")).create() )); namespace { typedef std::tuple ExpandVariablesTestSpec; class ExpandVariablesTestSpecBuilder { public: ExpandVariablesTestSpecBuilder& str(tstring::const_pointer v) { theStr = v; return *this; } ExpandVariablesTestSpecBuilder& expectStr(tstring::const_pointer v) { theExpectedStr = std::make_unique(v); return *this; } ExpandVariablesTestSpecBuilder& var(tstring::const_pointer name, tstring::const_pointer value) { theVariableValues.insert(std::make_pair(name, value)); return *this; } ExpandVariablesTestSpec create() const { return std::make_tuple(theStr, expectedStr(), theVariableValues); } private: tstring expectedStr() const { if (theExpectedStr) { return *theExpectedStr; } else { return theStr; } } private: tstring theStr; std::unique_ptr theExpectedStr; VariableValues theVariableValues; }; class ExpandVariablesTest :public ::testing::TestWithParam {}; tstring expandVariables(const tstring& str, const VariableValues& variableValues) { auto tokens = StringProcessing::tokenize(str); StringProcessing::expandVariables(tokens, variableValues); return StringProcessing::stringify(tokens); } } // namespace TEST_P(ExpandVariablesTest, Test) { const auto params = GetParam(); const auto str = std::get<0>(params); const auto expectedStr = std::get<1>(params); const auto varValues = std::get<2>(params); const auto actualStr = expandVariables(str, varValues); EXPECT_EQ(expectedStr, actualStr); } INSTANTIATE_TEST_CASE_P(StringProcessingTests, ExpandVariablesTest, ::testing::Values( ExpandVariablesTestSpecBuilder() .str(_T("foo$_b$a|r")) .expectStr(_T("fooBBB|r")) .var(_T("_b"), _T("BBB")).var(_T("a"), _T("")).create(), ExpandVariablesTestSpecBuilder() .str(_T("$one ${two} ${one} $two one two")) .expectStr(_T("ONE TWO ONE TWO one two")) .var(_T("one"), _T("ONE")).var(_T("two"), _T("TWO")).create(), ExpandVariablesTestSpecBuilder() .str(_T("$one ${two} \\${one} \\$two one two")) .expectStr(_T("ONE TWO ${one} $two one two")) .var(_T("one"), _T("ONE")).var(_T("two"), _T("TWO")).create(), ExpandVariablesTestSpecBuilder() .str(_T("\\$FOO\\\\$FOO\\${FOO}\\\\${FOO}")) .expectStr(_T("$FOO\\BAR${FOO}\\BAR")) .var(_T("FOO"), _T("BAR")).create() ));