diff --git a/src/pvxs/unittest.h b/src/pvxs/unittest.h index c6d9097..d34b370 100644 --- a/src/pvxs/unittest.h +++ b/src/pvxs/unittest.h @@ -89,6 +89,13 @@ public: msg<"); - std::string rhs(rrhs ? rrhs : ""); - - size_t posL=0u, posR=0u; - - while(posL(const std::string& s) { return ret; } +static +std::vector +splitLines(const char *inp) +{ + std::vector ret; + while(*inp) { + auto start = inp; + // find next EoL or nil + for(char c=*inp; c!='\0' && c!='\n' && c!='\r'; c=*++inp) {} + // inp points to EoL or nil + ret.emplace_back(start, inp); // copy line w/o EoL + // skip past one EoL ("\n", "\r\n", or "\n\r") + if(inp[0]=='\n' && inp[1]=='\r') inp+=2u; + else if(inp[0]=='\r' && inp[1]=='\n') inp+=2u; + else if(inp[0]=='\n') inp+=1u; + } + return ret; +} + +void strDiff(std::ostream& out, + const char *lhs, + const char *rhs) +{ + if(!lhs) + lhs = ""; + if(!rhs) + rhs = ""; + auto l_lines(splitLines(lhs)); + auto r_lines(splitLines(rhs)); + size_t L, R; + + for(L=0u, R=0u; L=l_lines.size() && testR>=r_lines.size()) { + goto done; + } + + if(testL>=l_lines.size() || testR>=r_lines.size()) { + continue; + } + + if(l_lines[testL]==r_lines[testR]) { + // found matching line + + for(; L < testL; L++) { + out<<"- \""< #include +#include #include #include @@ -204,11 +205,73 @@ void testTestEq() testStrMatch("[Hh]ello [Ww]orld", "hello world"); } +void testStrDiff() +{ + testShow()<<__func__; + + const auto testD = [](const char *lhs, const char *rhs, const char *expect) -> bool { + std::ostringstream strm; + strDiff(strm, lhs, rhs); + auto actual(strm.str()); + return testEq(expect, actual).operator bool(); + }; + + testD("", "", ""); + testD("one", "one", " \"one\"\n"); + testD("one\n", + "one\n", + " \"one\"\n"); + testD("one\n", + "two\n", + "- \"one\"\n" + "+ \"two\"\n"); + testD("one\n" + " aaa\n" + "two\n", + "one\n" + " bbb\n" + "two\n", + " \"one\"\n" + "- \" aaa\"\n" + "+ \" bbb\"\n" + " \"two\"\n"); + testD("one\n" + " aaa\n" + "two\n", + "one\n" + "two\n", + " \"one\"\n" + "- \" aaa\"\n" + " \"two\"\n"); + testD("one\n" + "two\n", + "one\n" + " bbb\n" + "two\n", + " \"one\"\n" + "+ \" bbb\"\n" + " \"two\"\n"); + testD("one\n" + " aaa\n" + "two\n" + " xxx\n", + "one\n" + " bbb\n" + "two\n" + " yyy\n", + " \"one\"\n" + "- \" aaa\"\n" + "+ \" bbb\"\n" + " \"two\"\n" + "- \" xxx\"\n" + "+ \" yyy\"\n"); +} + } // namespace MAIN(testutil) { - testPlan(25); + testPlan(33); testTrue(version_abi_check())<<" 0x"<