wxregextest.cpp 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // Name: tests/regex/wxregex.cpp
  3. // Purpose: Test wxRegEx
  4. // Author: Vadim Zeitlin, Mike Wetherell
  5. // Copyright: Vadim Zeitlin, Mike Wetherell
  6. // Licence: wxWindows licence
  7. ///////////////////////////////////////////////////////////////////////////////
  8. #include "testprec.h"
  9. #ifdef __BORLANDC__
  10. # pragma hdrstop
  11. #endif
  12. #ifndef WX_PRECOMP
  13. # include "wx/wx.h"
  14. #endif
  15. #if wxUSE_REGEX
  16. #include "wx/regex.h"
  17. #include "wx/tokenzr.h"
  18. #include <string>
  19. using CppUnit::Test;
  20. using CppUnit::TestCase;
  21. using CppUnit::TestSuite;
  22. using std::string;
  23. ///////////////////////////////////////////////////////////////////////////////
  24. // Compile Test
  25. class RegExCompileTestCase : public TestCase
  26. {
  27. public:
  28. RegExCompileTestCase(const char *name, const wxString& pattern,
  29. bool correct, int flags)
  30. : TestCase(name),
  31. m_pattern(pattern),
  32. m_correct(correct),
  33. m_flags(flags)
  34. { }
  35. protected:
  36. void runTest();
  37. private:
  38. wxString m_pattern;
  39. bool m_correct;
  40. int m_flags;
  41. };
  42. void RegExCompileTestCase::runTest()
  43. {
  44. wxRegEx re;
  45. bool ok = re.Compile(m_pattern, m_flags);
  46. if (m_correct)
  47. CPPUNIT_ASSERT_MESSAGE("compile failed", ok);
  48. else
  49. CPPUNIT_ASSERT_MESSAGE("compile succeeded (should fail)", !ok);
  50. }
  51. ///////////////////////////////////////////////////////////////////////////////
  52. // Match Test
  53. class RegExMatchTestCase : public TestCase
  54. {
  55. public:
  56. RegExMatchTestCase(const char *name, const wxString& pattern,
  57. const wxString& text, const char *expected,
  58. int flags)
  59. : TestCase(name),
  60. m_pattern(pattern),
  61. m_text(text),
  62. m_expected(expected),
  63. m_flags(flags)
  64. { }
  65. protected:
  66. void runTest();
  67. private:
  68. wxString m_pattern;
  69. wxString m_text;
  70. const char *m_expected;
  71. int m_flags;
  72. };
  73. void RegExMatchTestCase::runTest()
  74. {
  75. int compileFlags = m_flags & ~(wxRE_NOTBOL | wxRE_NOTEOL);
  76. int matchFlags = m_flags & (wxRE_NOTBOL | wxRE_NOTEOL);
  77. wxRegEx re(m_pattern, compileFlags);
  78. CPPUNIT_ASSERT_MESSAGE("compile failed", re.IsValid());
  79. bool ok = re.Matches(m_text, matchFlags);
  80. if (m_expected) {
  81. CPPUNIT_ASSERT_MESSAGE("match failed", ok);
  82. wxStringTokenizer tkz(wxString(m_expected, *wxConvCurrent),
  83. wxT("\t"), wxTOKEN_RET_EMPTY);
  84. size_t i;
  85. for (i = 0; i < re.GetMatchCount() && tkz.HasMoreTokens(); i++) {
  86. wxString expected = tkz.GetNextToken();
  87. wxString result = re.GetMatch(m_text, i);
  88. wxString msgstr;
  89. msgstr.Printf(wxT("\\%d == '%s' (expected '%s')"),
  90. (int)i, result.c_str(), expected.c_str());
  91. CPPUNIT_ASSERT_MESSAGE((const char*)msgstr.mb_str(),
  92. result == expected);
  93. }
  94. if ((m_flags & wxRE_NOSUB) == 0)
  95. CPPUNIT_ASSERT(re.GetMatchCount() == i);
  96. }
  97. else {
  98. CPPUNIT_ASSERT_MESSAGE("match succeeded (should fail)", !ok);
  99. }
  100. }
  101. ///////////////////////////////////////////////////////////////////////////////
  102. // Replacement Test
  103. class RegExReplaceTestCase : public TestCase
  104. {
  105. public:
  106. RegExReplaceTestCase(const char *name, const wxString& pattern,
  107. const wxString& text, const wxString& repl,
  108. const wxString& expected, size_t count, int flags)
  109. : TestCase(name),
  110. m_pattern(pattern),
  111. m_text(text),
  112. m_repl(repl),
  113. m_expected(expected),
  114. m_count(count),
  115. m_flags(flags)
  116. { }
  117. protected:
  118. void runTest();
  119. private:
  120. wxString m_pattern;
  121. wxString m_text;
  122. wxString m_repl;
  123. wxString m_expected;
  124. size_t m_count;
  125. int m_flags;
  126. };
  127. void RegExReplaceTestCase::runTest()
  128. {
  129. wxRegEx re(m_pattern, m_flags);
  130. wxString text(m_text);
  131. size_t nRepl = re.Replace(&text, m_repl);
  132. wxString msgstr;
  133. msgstr.Printf(wxT("returns '%s' (expected '%s')"), text.c_str(), m_expected.c_str());
  134. CPPUNIT_ASSERT_MESSAGE((const char*)msgstr.mb_str(), text == m_expected);
  135. msgstr.Printf(wxT("matches %d times (expected %d)"), (int)nRepl, (int)m_count);
  136. CPPUNIT_ASSERT_MESSAGE((const char*)msgstr.mb_str(), nRepl == m_count);
  137. }
  138. ///////////////////////////////////////////////////////////////////////////////
  139. // The suite
  140. class wxRegExTestSuite : public TestSuite
  141. {
  142. public:
  143. wxRegExTestSuite() : TestSuite("wxRegExTestSuite") { }
  144. static Test *suite();
  145. private:
  146. void add(const char *pattern, bool correct, int flags = wxRE_DEFAULT);
  147. void add(const char *pattern, const char *text,
  148. const char *expected = NULL, int flags = wxRE_DEFAULT);
  149. void add(const char *pattern, const char *text, const char *replacement,
  150. const char *expected, size_t count, int flags = wxRE_DEFAULT);
  151. static wxString FlagStr(int flags);
  152. static wxString Conv(const char *str) { return wxString(str, *wxConvCurrent); }
  153. };
  154. // Build the suite (static)
  155. //
  156. Test *wxRegExTestSuite::suite()
  157. {
  158. wxRegExTestSuite *suite = new wxRegExTestSuite;
  159. // Compile tests
  160. // pattern, expected result
  161. suite->add("foo", true);
  162. suite->add("foo(", false);
  163. suite->add("foo(bar", false);
  164. suite->add("foo(bar)", true);
  165. suite->add("foo[", false);
  166. suite->add("foo[bar", false);
  167. suite->add("foo[bar]", true);
  168. suite->add("foo{1", false);
  169. suite->add("foo{1}", true);
  170. suite->add("foo{1,2}", true);
  171. suite->add("foo*", true);
  172. suite->add("foo+", true);
  173. suite->add("foo?", true);
  174. // Match tests
  175. // pattern, text, expected results (match, followed by submatches
  176. // tab separated, or NULL for no match expected)
  177. suite->add("foo", "bar");
  178. suite->add("foo", "foobar", "foo");
  179. suite->add("^foo", "foobar", "foo");
  180. suite->add("^foo", "barfoo");
  181. suite->add("bar$", "barbar", "bar");
  182. suite->add("bar$", "barbar ");
  183. suite->add("OoBa", "FoObAr", "oObA", wxRE_ICASE);
  184. suite->add("^[A-Z].*$", "AA\nbb\nCC", "AA\nbb\nCC");
  185. suite->add("^[A-Z].*$", "AA\nbb\nCC", "AA", wxRE_NEWLINE);
  186. suite->add("^[a-z].*$", "AA\nbb\nCC", "bb", wxRE_NEWLINE);
  187. suite->add("^[A-Z].*$", "AA\nbb\nCC", "CC", wxRE_NEWLINE | wxRE_NOTBOL);
  188. suite->add("^[A-Z].*$", "AA\nbb\nCC", NULL, wxRE_NEWLINE | wxRE_NOTBOL | wxRE_NOTEOL);
  189. suite->add("([[:alpha:]]+) ([[:alpha:]]+) ([[:digit:]]+).* ([[:digit:]]+)$",
  190. "Fri Jul 13 18:37:52 CEST 2001",
  191. "Fri Jul 13 18:37:52 CEST 2001\tFri\tJul\t13\t2001");
  192. // Replace tests
  193. // pattern, text, replacement, expected result and number of matches
  194. const char *patn = "([a-z]+)[^0-9]*([0-9]+)";
  195. suite->add(patn, "foo123", "bar", "bar", 1);
  196. suite->add(patn, "foo123", "\\2\\1", "123foo", 1);
  197. suite->add(patn, "foo_123", "\\2\\1", "123foo", 1);
  198. suite->add(patn, "123foo", "bar", "123foo", 0);
  199. suite->add(patn, "123foo456foo", "&&", "123foo456foo456foo", 1);
  200. suite->add(patn, "123foo456foo", "\\0\\0", "123foo456foo456foo", 1);
  201. suite->add(patn, "foo123foo123", "bar", "barbar", 2);
  202. suite->add(patn, "foo123_foo456_foo789", "bar", "bar_bar_bar", 3);
  203. return suite;
  204. }
  205. // Add a compile test
  206. //
  207. void wxRegExTestSuite::add(
  208. const char *pattern,
  209. bool correct,
  210. int flags /*=wxRE_DEFAULT*/)
  211. {
  212. addTest(new RegExCompileTestCase(
  213. (wxT("/") + Conv(pattern) + wxT("/") + FlagStr(flags)).mb_str(),
  214. Conv(pattern), correct, flags));
  215. }
  216. // Add a match test
  217. //
  218. void wxRegExTestSuite::add(
  219. const char *pattern,
  220. const char *text,
  221. const char *expected /*=NULL*/,
  222. int flags /*=wxRE_DEFAULT*/)
  223. {
  224. wxString name;
  225. name << wxT("'") << Conv(text) << wxT("' =~ /") << Conv(pattern) << wxT("/")
  226. << FlagStr(flags);
  227. name.Replace(wxT("\n"), wxT("\\n"));
  228. addTest(new RegExMatchTestCase(name.mb_str(), Conv(pattern),
  229. Conv(text), expected, flags));
  230. }
  231. // Add a replace test
  232. //
  233. void wxRegExTestSuite::add(
  234. const char *pattern,
  235. const char *text,
  236. const char *replacement,
  237. const char *expected,
  238. size_t count,
  239. int flags /*=wxRE_DEFAULT*/)
  240. {
  241. wxString name;
  242. name << wxT("'") << Conv(text) << wxT("' =~ s/") << Conv(pattern) << wxT("/")
  243. << Conv(replacement) << wxT("/g") << FlagStr(flags);
  244. name.Replace(wxT("\n"), wxT("\\n"));
  245. addTest(new RegExReplaceTestCase(
  246. name.mb_str(), Conv(pattern), Conv(text),
  247. Conv(replacement), Conv(expected), count, flags));
  248. }
  249. // Display string for the flags
  250. //
  251. wxString wxRegExTestSuite::FlagStr(int flags)
  252. {
  253. wxString str;
  254. if (!flags)
  255. return str;
  256. for (int i = 0; (unsigned)flags >> i; i++) {
  257. switch (flags & (1 << i)) {
  258. case 0: break;
  259. #ifdef wxHAS_REGEX_ADVANCED
  260. case wxRE_ADVANCED: str += wxT(" | wxRE_ADVANCED"); break;
  261. #endif
  262. case wxRE_BASIC: str += wxT(" | wxRE_BASIC"); break;
  263. case wxRE_ICASE: str += wxT(" | wxRE_ICASE"); break;
  264. case wxRE_NOSUB: str += wxT(" | wxRE_NOSUB"); break;
  265. case wxRE_NEWLINE: str += wxT(" | wxRE_NEWLINE"); break;
  266. case wxRE_NOTBOL: str += wxT(" | wxRE_NOTBOL"); break;
  267. case wxRE_NOTEOL: str += wxT(" | wxRE_NOTEOL"); break;
  268. default: wxFAIL; break;
  269. }
  270. }
  271. return wxT(" (") + str.Mid(3) + wxT(")");
  272. }
  273. // register in the unnamed registry so that these tests are run by default
  274. CPPUNIT_TEST_SUITE_REGISTRATION(wxRegExTestSuite);
  275. // also include in its own registry so that these tests can be run alone
  276. CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(wxRegExTestSuite, "wxRegExTestSuite");
  277. #endif // wxUSE_REGEX