The source code and dockerfile for the GSW2024 AI Lab.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.

882 lines
26 KiB

4 weeks ago
  1. #include "cpptempl.h"
  2. #ifdef UNIT_TEST
  3. #include <boost/test/unit_test.hpp>
  4. #ifndef BOOST_TEST_MODULE
  5. #define BOOST_TEST_MODULE cpptemplTests
  6. #endif
  7. #pragma warning( disable : 4996 ) // doesn't like wcstombs
  8. #include "unit_testing.h"
  9. using namespace std ;
  10. BOOST_AUTO_TEST_SUITE( TestCppData )
  11. using namespace cpptempl ;
  12. // DataMap
  13. BOOST_AUTO_TEST_CASE(test_DataMap_getvalue)
  14. {
  15. data_map items ;
  16. data_ptr data(new DataMap(items)) ;
  17. BOOST_CHECK_THROW( data->getvalue(), TemplateException ) ;
  18. }
  19. BOOST_AUTO_TEST_CASE(test_DataMap_getlist_throws)
  20. {
  21. data_map items ;
  22. data_ptr data(new DataMap(items)) ;
  23. BOOST_CHECK_THROW( data->getlist(), TemplateException ) ;
  24. }
  25. BOOST_AUTO_TEST_CASE(test_DataMap_getitem_throws)
  26. {
  27. data_map items ;
  28. items[L"key"] = data_ptr(new DataValue(L"foo")) ;
  29. data_ptr data(new DataMap(items)) ;
  30. BOOST_CHECK_EQUAL( data->getmap()[L"key"]->getvalue(), L"foo" ) ;
  31. }
  32. // DataList
  33. BOOST_AUTO_TEST_CASE(test_DataList_getvalue)
  34. {
  35. data_list items ;
  36. data_ptr data(new DataList(items)) ;
  37. BOOST_CHECK_THROW( data->getvalue(), TemplateException ) ;
  38. }
  39. BOOST_AUTO_TEST_CASE(test_DataList_getlist_throws)
  40. {
  41. data_list items ;
  42. items.push_back(make_data(L"bar")) ;
  43. data_ptr data(new DataList(items)) ;
  44. BOOST_CHECK_EQUAL( data->getlist().size(), 1u ) ;
  45. }
  46. BOOST_AUTO_TEST_CASE(test_DataList_getitem_throws)
  47. {
  48. data_list items ;
  49. data_ptr data(new DataList(items)) ;
  50. BOOST_CHECK_THROW( data->getmap(), TemplateException ) ;
  51. }
  52. // DataValue
  53. BOOST_AUTO_TEST_CASE(test_DataValue_getvalue)
  54. {
  55. data_ptr data(new DataValue(L"foo")) ;
  56. BOOST_CHECK_EQUAL( data->getvalue(), L"foo" ) ;
  57. }
  58. BOOST_AUTO_TEST_CASE(test_DataValue_getlist_throws)
  59. {
  60. data_ptr data(new DataValue(L"foo")) ;
  61. BOOST_CHECK_THROW( data->getlist(), TemplateException ) ;
  62. }
  63. BOOST_AUTO_TEST_CASE(test_DataValue_getitem_throws)
  64. {
  65. data_ptr data(new DataValue(L"foo")) ;
  66. BOOST_CHECK_THROW( data->getmap(), TemplateException ) ;
  67. }
  68. BOOST_AUTO_TEST_SUITE_END()
  69. BOOST_AUTO_TEST_SUITE( TestCppParseVal )
  70. using namespace cpptempl ;
  71. BOOST_AUTO_TEST_CASE(test_quoted)
  72. {
  73. data_map data ;
  74. data[L"foo"] = make_data(L"bar") ;
  75. data_ptr value = parse_val(L"\"foo\"", data) ;
  76. BOOST_CHECK_EQUAL( value->getvalue(), L"foo" ) ;
  77. }
  78. BOOST_AUTO_TEST_CASE(test_value)
  79. {
  80. data_map data ;
  81. data[L"foo"] = make_data(L"bar") ;
  82. data_ptr value = parse_val(L"foo", data) ;
  83. BOOST_CHECK_EQUAL( value->getvalue(), L"bar" ) ;
  84. }
  85. BOOST_AUTO_TEST_CASE(test_not_found)
  86. {
  87. data_map data ;
  88. data[L"foo"] = make_data(L"bar") ;
  89. data_ptr value = parse_val(L"kettle", data) ;
  90. BOOST_CHECK_EQUAL( value->getvalue(), L"{$kettle}" ) ;
  91. }
  92. BOOST_AUTO_TEST_CASE(test_not_found_dotted)
  93. {
  94. data_map data ;
  95. data[L"foo"] = make_data(L"bar") ;
  96. data_ptr value = parse_val(L"kettle.black", data) ;
  97. BOOST_CHECK_EQUAL( value->getvalue(), L"{$kettle.black}" ) ;
  98. }
  99. BOOST_AUTO_TEST_CASE(test_my_ax)
  100. {
  101. data_map data ;
  102. data[L"item"] = make_data(L"my ax") ;
  103. BOOST_CHECK_EQUAL( parse_val(L"item", data)->getvalue(), L"my ax" ) ;
  104. }
  105. BOOST_AUTO_TEST_CASE(test_list)
  106. {
  107. data_map data ;
  108. data_list items ;
  109. items.push_back(make_data(L"bar")) ;
  110. data[L"foo"] = data_ptr(new DataList(items)) ;
  111. data_ptr value = parse_val(L"foo", data) ;
  112. BOOST_CHECK_EQUAL( value->getlist().size(), 1u ) ;
  113. }
  114. BOOST_AUTO_TEST_CASE(test_dotted)
  115. {
  116. data_map data ;
  117. data_map subdata ;
  118. subdata[L"b"] = data_ptr(new DataValue(L"c")) ;
  119. data[L"a"] = data_ptr(new DataMap(subdata)) ;
  120. data_ptr value = parse_val(L"a.b", data) ;
  121. BOOST_CHECK_EQUAL( value->getvalue(), L"c" ) ;
  122. }
  123. BOOST_AUTO_TEST_CASE(test_double_dotted)
  124. {
  125. data_map data ;
  126. data_map sub_data ;
  127. data_map sub_sub_data ;
  128. sub_sub_data[L"c"] = data_ptr(new DataValue(L"d")) ;
  129. sub_data[L"b"] = data_ptr(new DataMap(sub_sub_data)) ;
  130. data[L"a"] = data_ptr(new DataMap(sub_data)) ;
  131. data_ptr value = parse_val(L"a.b.c", data) ;
  132. BOOST_CHECK_EQUAL( value->getvalue(), L"d" ) ;
  133. }
  134. BOOST_AUTO_TEST_CASE(test_dotted_to_list)
  135. {
  136. data_list friends ;
  137. friends.push_back(make_data(L"Bob")) ;
  138. data_map person ;
  139. person[L"friends"] = make_data(friends) ;
  140. data_map data ;
  141. data[L"person"] = make_data(person) ;
  142. data_ptr value = parse_val(L"person.friends", data) ;
  143. BOOST_CHECK_EQUAL( value->getlist().size(), 1u ) ;
  144. }
  145. BOOST_AUTO_TEST_CASE(test_dotted_to_dict_list)
  146. {
  147. data_map bob ;
  148. bob[L"name"] = make_data(L"Bob") ;
  149. data_map betty ;
  150. betty[L"name"] = make_data(L"Betty") ;
  151. data_list friends ;
  152. friends.push_back(make_data(bob)) ;
  153. friends.push_back(make_data(betty)) ;
  154. data_map person ;
  155. person[L"friends"] = make_data(friends) ;
  156. data_map data ;
  157. data[L"person"] = make_data(person) ;
  158. data_ptr value = parse_val(L"person.friends", data) ;
  159. BOOST_CHECK_EQUAL( value->getlist()[0]->getmap()[L"name"]->getvalue(), L"Bob" ) ;
  160. }
  161. BOOST_AUTO_TEST_SUITE_END()
  162. BOOST_AUTO_TEST_SUITE( TestCppToken )
  163. using namespace cpptempl ;
  164. // TokenVar
  165. BOOST_AUTO_TEST_CASE(TestTokenVarType)
  166. {
  167. TokenVar token(L"foo") ;
  168. BOOST_CHECK_EQUAL( token.gettype(), TOKEN_TYPE_VAR ) ;
  169. }
  170. BOOST_AUTO_TEST_CASE(TestTokenVar)
  171. {
  172. token_ptr token(new TokenVar(L"foo")) ;
  173. data_map data ;
  174. data[L"foo"] = make_data(L"bar") ;
  175. BOOST_CHECK_EQUAL( gettext(token, data), L"bar" ) ;
  176. }
  177. BOOST_AUTO_TEST_CASE(TestTokenVarCantHaveChildren)
  178. {
  179. TokenVar token(L"foo") ;
  180. token_vector children ;
  181. BOOST_CHECK_THROW(token.set_children(children), TemplateException) ;
  182. }
  183. // TokenText
  184. BOOST_AUTO_TEST_CASE(TestTokenTextType)
  185. {
  186. TokenText token(L"foo") ;
  187. BOOST_CHECK_EQUAL( token.gettype(), TOKEN_TYPE_TEXT ) ;
  188. }
  189. BOOST_AUTO_TEST_CASE(TestTokenText)
  190. {
  191. token_ptr token(new TokenText(L"foo")) ;
  192. data_map data ;
  193. data[L"foo"] = make_data(L"bar") ;
  194. BOOST_CHECK_EQUAL( gettext(token, data), L"foo" ) ;
  195. }
  196. BOOST_AUTO_TEST_CASE(TestTokenTextCantHaveChildrenSet)
  197. {
  198. TokenText token(L"foo") ;
  199. token_vector children ;
  200. BOOST_CHECK_THROW(token.set_children(children), TemplateException) ;
  201. }
  202. BOOST_AUTO_TEST_CASE(TestTokenTextCantHaveChildrenGet)
  203. {
  204. TokenText token(L"foo") ;
  205. token_vector children ;
  206. BOOST_CHECK_THROW(token.get_children(), TemplateException) ;
  207. }
  208. // TokenFor
  209. BOOST_AUTO_TEST_CASE(TestTokenForBadSyntax)
  210. {
  211. BOOST_CHECK_THROW(TokenFor token(L"foo"), TemplateException ) ;
  212. }
  213. BOOST_AUTO_TEST_CASE(TestTokenForType)
  214. {
  215. TokenFor token(L"for item in items") ;
  216. BOOST_CHECK_EQUAL( token.gettype(), TOKEN_TYPE_FOR ) ;
  217. }
  218. BOOST_AUTO_TEST_CASE(TestTokenForTextEmpty)
  219. {
  220. token_ptr token(new TokenFor(L"for item in items")) ;
  221. data_map data ;
  222. data_list items ;
  223. items.push_back(make_data(L"first"));
  224. data[L"items"] = make_data(items) ;
  225. BOOST_CHECK_EQUAL( gettext(token, data), L"" ) ;
  226. }
  227. BOOST_AUTO_TEST_CASE(TestTokenForTextOneVar)
  228. {
  229. token_vector children ;
  230. children.push_back(token_ptr(new TokenVar(L"item"))) ;
  231. token_ptr token(new TokenFor(L"for item in items")) ;
  232. token->set_children(children) ;
  233. data_map data ;
  234. data_list items ;
  235. items.push_back(make_data(L"first "));
  236. items.push_back(make_data(L"second "));
  237. data[L"items"] = make_data(items) ;
  238. BOOST_CHECK_EQUAL( gettext(token, data), L"first second " ) ;
  239. }
  240. BOOST_AUTO_TEST_CASE(TestTokenForTextOneVarLoop)
  241. {
  242. token_vector children ;
  243. children.push_back(token_ptr(new TokenVar(L"loop.index"))) ;
  244. token_ptr token(new TokenFor(L"for item in items")) ;
  245. token->set_children(children) ;
  246. data_map data ;
  247. data_list items ;
  248. items.push_back(make_data(L"first "));
  249. items.push_back(make_data(L"second "));
  250. data[L"items"] = make_data(items) ;
  251. BOOST_CHECK_EQUAL( gettext(token, data), L"12" ) ;
  252. }
  253. BOOST_AUTO_TEST_CASE(TestTokenForLoopTextVar)
  254. {
  255. token_vector children ;
  256. children.push_back(token_ptr(new TokenVar(L"loop.index"))) ;
  257. children.push_back(token_ptr(new TokenText(L". "))) ;
  258. children.push_back(token_ptr(new TokenVar(L"item"))) ;
  259. children.push_back(token_ptr(new TokenText(L" "))) ;
  260. token_ptr token(new TokenFor(L"for item in items")) ;
  261. token->set_children(children) ;
  262. data_map data ;
  263. data_list items ;
  264. items.push_back(make_data(L"first"));
  265. items.push_back(make_data(L"second"));
  266. data[L"items"] = make_data(items) ;
  267. BOOST_CHECK_EQUAL( gettext(token, data), L"1. first 2. second " ) ;
  268. }
  269. BOOST_AUTO_TEST_CASE(TestTokenForLoopTextVarDottedKeyAndVal)
  270. {
  271. TokenFor token(L"for friend in person.friends") ;
  272. BOOST_CHECK_EQUAL( token.m_key, L"person.friends" ) ;
  273. BOOST_CHECK_EQUAL( token.m_val, L"friend" ) ;
  274. }
  275. BOOST_AUTO_TEST_CASE(TestTokenForLoopTextVarDotted)
  276. {
  277. token_vector children ;
  278. children.push_back(token_ptr(new TokenVar(L"loop.index"))) ;
  279. children.push_back(token_ptr(new TokenText(L". "))) ;
  280. children.push_back(token_ptr(new TokenVar(L"friend.name"))) ;
  281. children.push_back(token_ptr(new TokenText(L" "))) ;
  282. token_ptr token(new TokenFor(L"for friend in person.friends")) ;
  283. token->set_children(children) ;
  284. data_map bob ;
  285. bob[L"name"] = make_data(L"Bob") ;
  286. data_map betty ;
  287. betty[L"name"] = make_data(L"Betty") ;
  288. data_list friends ;
  289. friends.push_back(make_data(bob)) ;
  290. friends.push_back(make_data(betty)) ;
  291. data_map person ;
  292. person[L"friends"] = make_data(friends) ;
  293. data_map data ;
  294. data[L"person"] = make_data(person) ;
  295. BOOST_CHECK_EQUAL( gettext(token, data), L"1. Bob 2. Betty " ) ;
  296. }
  297. BOOST_AUTO_TEST_CASE(TestTokenForTextOneText)
  298. {
  299. token_vector children ;
  300. children.push_back(token_ptr(new TokenText(L"{--}"))) ;
  301. token_ptr token(new TokenFor(L"for item in items")) ;
  302. token->set_children(children) ;
  303. data_map data ;
  304. data_list items ;
  305. items.push_back(make_data(L"first "));
  306. items.push_back(make_data(L"second "));
  307. data[L"items"] = make_data(items) ;
  308. BOOST_CHECK_EQUAL( gettext(token, data), L"{--}{--}" ) ;
  309. }
  310. //////////////////////////////////////////////////////////////////////////
  311. // TokenIf
  312. //////////////////////////////////////////////////////////////////////////
  313. BOOST_AUTO_TEST_CASE(TestTokenIfType)
  314. {
  315. TokenIf token(L"if items") ;
  316. BOOST_CHECK_EQUAL( token.gettype(), TOKEN_TYPE_IF ) ;
  317. }
  318. // if not empty
  319. BOOST_AUTO_TEST_CASE(TestTokenIfTrueText)
  320. {
  321. token_vector children ;
  322. children.push_back(token_ptr(new TokenText(L"{--}"))) ;
  323. token_ptr token(new TokenIf(L"if item")) ;
  324. token->set_children(children) ;
  325. data_map data ;
  326. data[L"item"] = make_data(L"foo") ;
  327. BOOST_CHECK_EQUAL( gettext(token, data), L"{--}" ) ;
  328. }
  329. BOOST_AUTO_TEST_CASE(TestTokenIfTrueVar)
  330. {
  331. token_vector children ;
  332. children.push_back(token_ptr(new TokenVar(L"item"))) ;
  333. token_ptr token(new TokenIf(L"if item")) ;
  334. token->set_children(children) ;
  335. data_map data ;
  336. data[L"item"] = make_data(L"foo") ;
  337. BOOST_CHECK_EQUAL( gettext(token, data), L"foo" ) ;
  338. }
  339. BOOST_AUTO_TEST_CASE(TestTokenIfFalse)
  340. {
  341. token_vector children ;
  342. children.push_back(token_ptr(new TokenText(L"{--}"))) ;
  343. token_ptr token(new TokenIf(L"if item")) ;
  344. token->set_children(children) ;
  345. data_map data ;
  346. data[L"item"] = make_data(L"") ;
  347. BOOST_CHECK_EQUAL( gettext(token, data), L"") ;
  348. }
  349. // ==
  350. BOOST_AUTO_TEST_CASE(TestTokenIfEqualsTrue)
  351. {
  352. token_vector children ;
  353. children.push_back(token_ptr(new TokenVar(L"item"))) ;
  354. token_ptr token(new TokenIf(L"if item == \"foo\"")) ;
  355. token->set_children(children) ;
  356. data_map data ;
  357. data[L"item"] = make_data(L"foo") ;
  358. BOOST_CHECK_EQUAL( gettext(token, data), L"foo" ) ;
  359. }
  360. BOOST_AUTO_TEST_CASE(TestTokenIfEqualsFalse)
  361. {
  362. token_vector children ;
  363. children.push_back(token_ptr(new TokenVar(L"item"))) ;
  364. token_ptr token(new TokenIf(L"if item == \"bar\"")) ;
  365. token->set_children(children) ;
  366. data_map data ;
  367. data[L"item"] = make_data(L"foo") ;
  368. BOOST_CHECK_EQUAL( gettext(token, data), L"" ) ;
  369. }
  370. BOOST_AUTO_TEST_CASE(TestTokenIfEqualsTwoVarsTrue)
  371. {
  372. token_vector children ;
  373. children.push_back(token_ptr(new TokenVar(L"item"))) ;
  374. token_ptr token(new TokenIf(L"if item == foo")) ;
  375. token->set_children(children) ;
  376. data_map data ;
  377. data[L"item"] = make_data(L"x") ;
  378. data[L"foo"] = make_data(L"x") ;
  379. BOOST_CHECK_EQUAL( gettext(token, data), L"x" ) ;
  380. }
  381. // !=
  382. BOOST_AUTO_TEST_CASE(TestTokenIfNotEqualsTrue)
  383. {
  384. token_vector children ;
  385. children.push_back(token_ptr(new TokenVar(L"item"))) ;
  386. token_ptr token(new TokenIf(L"if item != \"foo\"")) ;
  387. token->set_children(children) ;
  388. data_map data ;
  389. data[L"item"] = make_data(L"foo") ;
  390. BOOST_CHECK_EQUAL( gettext(token, data), L"" ) ;
  391. }
  392. BOOST_AUTO_TEST_CASE(TestTokenIfNotEqualsFalse)
  393. {
  394. token_vector children ;
  395. children.push_back(token_ptr(new TokenVar(L"item"))) ;
  396. token_ptr token(new TokenIf(L"if item != \"bar\"")) ;
  397. token->set_children(children) ;
  398. data_map data ;
  399. data[L"item"] = make_data(L"foo") ;
  400. BOOST_CHECK_EQUAL( gettext(token, data), L"foo" ) ;
  401. }
  402. // not
  403. BOOST_AUTO_TEST_CASE(TestTokenIfNotTrueText)
  404. {
  405. token_vector children ;
  406. children.push_back(token_ptr(new TokenText(L"{--}"))) ;
  407. token_ptr token(new TokenIf(L"if not item")) ;
  408. token->set_children(children) ;
  409. data_map data ;
  410. data[L"item"] = make_data(L"foo") ;
  411. BOOST_CHECK_EQUAL( gettext(token, data), L"") ;
  412. }
  413. BOOST_AUTO_TEST_CASE(TestTokenIfNotFalseText)
  414. {
  415. token_vector children ;
  416. children.push_back(token_ptr(new TokenText(L"{--}"))) ;
  417. token_ptr token(new TokenIf(L"if not item")) ;
  418. token->set_children(children) ;
  419. data_map data ;
  420. data[L"item"] = make_data(L"") ;
  421. BOOST_CHECK_EQUAL( gettext(token, data), L"{--}") ;
  422. }
  423. // TokenEnd
  424. BOOST_AUTO_TEST_CASE(TestTokenEndFor)
  425. {
  426. TokenEnd token(L"endfor") ;
  427. BOOST_CHECK_EQUAL( token.gettype(), TOKEN_TYPE_ENDFOR ) ;
  428. }
  429. BOOST_AUTO_TEST_CASE(TestTokenEndIf)
  430. {
  431. TokenEnd token(L"endif") ;
  432. BOOST_CHECK_EQUAL( token.gettype(), TOKEN_TYPE_ENDIF ) ;
  433. }
  434. BOOST_AUTO_TEST_CASE(TestTokenEndIfCantHaveChildren)
  435. {
  436. TokenEnd token(L"endif") ;
  437. token_vector children ;
  438. BOOST_CHECK_THROW(token.set_children(children), TemplateException) ;
  439. }
  440. BOOST_AUTO_TEST_CASE(test_throws_on_gettext)
  441. {
  442. data_map data ;
  443. token_ptr token(new TokenEnd(L"endif")) ;
  444. BOOST_CHECK_THROW(gettext(token, data), TemplateException) ;
  445. }
  446. BOOST_AUTO_TEST_SUITE_END()
  447. BOOST_AUTO_TEST_SUITE( TestCppTokenize )
  448. using namespace cpptempl ;
  449. BOOST_AUTO_TEST_CASE(test_empty)
  450. {
  451. wstring text = L"" ;
  452. token_vector tokens ;
  453. tokenize(text, tokens) ;
  454. BOOST_CHECK_EQUAL( 0u, tokens.size() ) ;
  455. }
  456. BOOST_AUTO_TEST_CASE(test_text_only)
  457. {
  458. wstring text = L"blah blah blah" ;
  459. token_vector tokens ;
  460. tokenize(text, tokens) ;
  461. data_map data ;
  462. BOOST_CHECK_EQUAL( 1u, tokens.size() ) ;
  463. BOOST_CHECK_EQUAL( gettext(tokens[0], data), L"blah blah blah" ) ;
  464. }
  465. BOOST_AUTO_TEST_CASE(test_brackets_no_var)
  466. {
  467. wstring text = L"{foo}" ;
  468. token_vector tokens ;
  469. tokenize(text, tokens) ;
  470. data_map data ;
  471. BOOST_CHECK_EQUAL( 2u, tokens.size() ) ;
  472. BOOST_CHECK_EQUAL( gettext(tokens[0], data), L"{" ) ;
  473. BOOST_CHECK_EQUAL( gettext(tokens[1], data), L"foo}" ) ;
  474. }
  475. BOOST_AUTO_TEST_CASE(test_ends_with_bracket)
  476. {
  477. wstring text = L"blah blah blah{" ;
  478. token_vector tokens ;
  479. tokenize(text, tokens) ;
  480. data_map data ;
  481. BOOST_CHECK_EQUAL( 2u, tokens.size() ) ;
  482. BOOST_CHECK_EQUAL( gettext(tokens[0], data), L"blah blah blah" ) ;
  483. BOOST_CHECK_EQUAL( gettext(tokens[1], data), L"{" ) ;
  484. }
  485. // var
  486. BOOST_AUTO_TEST_CASE(test_var)
  487. {
  488. wstring text = L"{$foo}" ;
  489. token_vector tokens ;
  490. tokenize(text, tokens) ;
  491. data_map data ;
  492. data[L"foo"] = make_data(L"bar") ;
  493. BOOST_CHECK_EQUAL( 1u, tokens.size() ) ;
  494. BOOST_CHECK_EQUAL( gettext(tokens[0], data), L"bar" ) ;
  495. }
  496. // for
  497. BOOST_AUTO_TEST_CASE(test_for)
  498. {
  499. wstring text = L"{% for item in items %}" ;
  500. token_vector tokens ;
  501. tokenize(text, tokens) ;
  502. BOOST_CHECK_EQUAL( 1u, tokens.size() ) ;
  503. BOOST_CHECK_EQUAL( tokens[0]->gettype(), TOKEN_TYPE_FOR ) ;
  504. }
  505. BOOST_AUTO_TEST_CASE(test_for_full)
  506. {
  507. wstring text = L"{% for item in items %}{$item}{% endfor %}" ;
  508. token_vector tokens ;
  509. tokenize(text, tokens) ;
  510. BOOST_CHECK_EQUAL( 3u, tokens.size() ) ;
  511. BOOST_CHECK_EQUAL( tokens[0]->gettype(), TOKEN_TYPE_FOR ) ;
  512. BOOST_CHECK_EQUAL( tokens[1]->gettype(), TOKEN_TYPE_VAR ) ;
  513. BOOST_CHECK_EQUAL( tokens[2]->gettype(), TOKEN_TYPE_ENDFOR ) ;
  514. }
  515. BOOST_AUTO_TEST_CASE(test_for_full_with_text)
  516. {
  517. wstring text = L"{% for item in items %}*{$item}*{% endfor %}" ;
  518. token_vector tokens ;
  519. tokenize(text, tokens) ;
  520. data_map data ;
  521. data[L"item"] = make_data(L"my ax") ;
  522. BOOST_CHECK_EQUAL( 5u, tokens.size() ) ;
  523. BOOST_CHECK_EQUAL( tokens[0]->gettype(), TOKEN_TYPE_FOR ) ;
  524. BOOST_CHECK_EQUAL( gettext(tokens[1], data), L"*" ) ;
  525. BOOST_CHECK_EQUAL( tokens[2]->gettype(), TOKEN_TYPE_VAR ) ;
  526. BOOST_CHECK_EQUAL( gettext(tokens[2], data), L"my ax" ) ;
  527. BOOST_CHECK_EQUAL( gettext(tokens[3], data), L"*" ) ;
  528. BOOST_CHECK_EQUAL( tokens[4]->gettype(), TOKEN_TYPE_ENDFOR ) ;
  529. }
  530. // if
  531. BOOST_AUTO_TEST_CASE(test_if)
  532. {
  533. wstring text = L"{% if foo %}" ;
  534. token_vector tokens ;
  535. tokenize(text, tokens) ;
  536. BOOST_CHECK_EQUAL( 1u, tokens.size() ) ;
  537. BOOST_CHECK_EQUAL( tokens[0]->gettype(), TOKEN_TYPE_IF ) ;
  538. }
  539. BOOST_AUTO_TEST_CASE(test_if_full)
  540. {
  541. wstring text = L"{% if item %}{$item}{% endif %}" ;
  542. token_vector tokens ;
  543. tokenize(text, tokens) ;
  544. BOOST_CHECK_EQUAL( 3u, tokens.size() ) ;
  545. BOOST_CHECK_EQUAL( tokens[0]->gettype(), TOKEN_TYPE_IF ) ;
  546. BOOST_CHECK_EQUAL( tokens[1]->gettype(), TOKEN_TYPE_VAR ) ;
  547. BOOST_CHECK_EQUAL( tokens[2]->gettype(), TOKEN_TYPE_ENDIF ) ;
  548. }
  549. BOOST_AUTO_TEST_CASE(test_if_full_with_text)
  550. {
  551. wstring text = L"{% if item %}{{$item}}{% endif %}" ;
  552. token_vector tokens ;
  553. tokenize(text, tokens) ;
  554. data_map data ;
  555. data[L"item"] = make_data(L"my ax") ;
  556. BOOST_CHECK_EQUAL( 5u, tokens.size() ) ;
  557. BOOST_CHECK_EQUAL( tokens[0]->gettype(), TOKEN_TYPE_IF ) ;
  558. BOOST_CHECK_EQUAL( gettext(tokens[1], data), L"{" ) ;
  559. BOOST_CHECK_EQUAL( tokens[2]->gettype(), TOKEN_TYPE_VAR ) ;
  560. BOOST_CHECK_EQUAL( gettext(tokens[2], data), L"my ax" ) ;
  561. BOOST_CHECK_EQUAL( gettext(tokens[3], data), L"}" ) ;
  562. BOOST_CHECK_EQUAL( tokens[4]->gettype(), TOKEN_TYPE_ENDIF ) ;
  563. }
  564. BOOST_AUTO_TEST_SUITE_END()
  565. BOOST_AUTO_TEST_SUITE( test_parse_tree )
  566. using namespace cpptempl ;
  567. token_ptr make_tt(wstring text)
  568. {
  569. return token_ptr(new TokenText(text)) ;
  570. }
  571. token_ptr make_for(wstring text)
  572. {
  573. return token_ptr(new TokenFor(text)) ;
  574. }
  575. token_ptr make_if(wstring text)
  576. {
  577. return token_ptr(new TokenIf(text)) ;
  578. }
  579. token_ptr make_endfor()
  580. {
  581. return token_ptr(new TokenEnd(L"endfor")) ;
  582. }
  583. token_ptr make_endif()
  584. {
  585. return token_ptr(new TokenEnd(L"endif")) ;
  586. }
  587. BOOST_AUTO_TEST_CASE(test_empty)
  588. {
  589. token_vector tokens ;
  590. token_vector tree ;
  591. parse_tree(tokens, tree) ;
  592. BOOST_CHECK_EQUAL( 0u, tree.size() ) ;
  593. }
  594. BOOST_AUTO_TEST_CASE(test_one)
  595. {
  596. token_vector tokens ;
  597. tokens.push_back(make_tt(L"foo")) ;
  598. token_vector tree ;
  599. parse_tree(tokens, tree) ;
  600. BOOST_CHECK_EQUAL( 1u, tree.size() ) ;
  601. }
  602. BOOST_AUTO_TEST_CASE(test_for)
  603. {
  604. token_vector tokens ;
  605. tokens.push_back(make_for(L"for item in items")) ;
  606. tokens.push_back(make_tt(L"foo")) ;
  607. tokens.push_back(make_endfor()) ;
  608. token_vector tree ;
  609. parse_tree(tokens, tree) ;
  610. BOOST_CHECK_EQUAL( 1u, tree.size() ) ;
  611. BOOST_CHECK_EQUAL( 1u, tree[0]->get_children().size()) ;
  612. }
  613. BOOST_AUTO_TEST_CASE(test_if)
  614. {
  615. token_vector tokens ;
  616. tokens.push_back(make_if(L"if insane")) ;
  617. tokens.push_back(make_tt(L"foo")) ;
  618. tokens.push_back(make_endif()) ;
  619. token_vector tree ;
  620. parse_tree(tokens, tree) ;
  621. BOOST_CHECK_EQUAL( 1u, tree.size() ) ;
  622. BOOST_CHECK_EQUAL( 1u, tree[0]->get_children().size()) ;
  623. }
  624. BOOST_AUTO_TEST_SUITE_END()
  625. BOOST_AUTO_TEST_SUITE(TestCppParse)
  626. using namespace cpptempl ;
  627. BOOST_AUTO_TEST_CASE(test_empty)
  628. {
  629. wstring text = L"" ;
  630. data_map data ;
  631. wstring actual = parse(text, data) ;
  632. wstring expected = L"" ;
  633. BOOST_CHECK_EQUAL( expected, actual ) ;
  634. }
  635. BOOST_AUTO_TEST_CASE(test_no_vars)
  636. {
  637. wstring text = L"foo" ;
  638. data_map data ;
  639. wstring actual = parse(text, data) ;
  640. wstring expected = L"foo" ;
  641. BOOST_CHECK_EQUAL( expected, actual ) ;
  642. }
  643. BOOST_AUTO_TEST_CASE(test_var)
  644. {
  645. wstring text = L"{$foo}" ;
  646. data_map data ;
  647. data[L"foo"] = make_data(L"bar") ;
  648. wstring actual = parse(text, data) ;
  649. wstring expected = L"bar" ;
  650. BOOST_CHECK_EQUAL( expected, actual ) ;
  651. }
  652. BOOST_AUTO_TEST_CASE(test_var_surrounded)
  653. {
  654. wstring text = L"aaa{$foo}bbb" ;
  655. data_map data ;
  656. data[L"foo"] = make_data(L"---") ;
  657. wstring actual = parse(text, data) ;
  658. wstring expected = L"aaa---bbb" ;
  659. BOOST_CHECK_EQUAL( expected, actual ) ;
  660. }
  661. BOOST_AUTO_TEST_CASE(test_for)
  662. {
  663. wstring text = L"{% for item in items %}{$item}{% endfor %}" ;
  664. data_map data ;
  665. data_list items ;
  666. items.push_back(make_data(L"0")) ;
  667. items.push_back(make_data(L"1")) ;
  668. data[L"items"] = make_data(items) ;
  669. wstring actual = parse(text, data) ;
  670. wstring expected = L"01" ;
  671. BOOST_CHECK_EQUAL( expected, actual ) ;
  672. }
  673. BOOST_AUTO_TEST_CASE(test_if_false)
  674. {
  675. wstring text = L"{% if item %}{$item}{% endif %}" ;
  676. data_map data ;
  677. data[L"item"] = make_data(L"") ;
  678. wstring actual = parse(text, data) ;
  679. wstring expected = L"" ;
  680. BOOST_CHECK_EQUAL( expected, actual ) ;
  681. }
  682. BOOST_AUTO_TEST_CASE(test_if_true)
  683. {
  684. wstring text = L"{% if item %}{$item}{% endif %}" ;
  685. data_map data ;
  686. data[L"item"] = make_data(L"foo") ;
  687. wstring actual = parse(text, data) ;
  688. wstring expected = L"foo" ;
  689. BOOST_CHECK_EQUAL( expected, actual ) ;
  690. }
  691. BOOST_AUTO_TEST_CASE(test_nested_for)
  692. {
  693. wstring text = L"{% for item in items %}{% for thing in things %}{$item}{$thing}{% endfor %}{% endfor %}" ;
  694. data_map data ;
  695. data_list items ;
  696. items.push_back(make_data(L"0")) ;
  697. items.push_back(make_data(L"1")) ;
  698. data[L"items"] = make_data(items) ;
  699. data_list things ;
  700. things.push_back(make_data(L"a")) ;
  701. things.push_back(make_data(L"b")) ;
  702. data[L"things"] = make_data(things) ;
  703. wstring actual = parse(text, data) ;
  704. wstring expected = L"0a0b1a1b" ;
  705. BOOST_CHECK_EQUAL( expected, actual ) ;
  706. }
  707. BOOST_AUTO_TEST_CASE(test_nested_if_false)
  708. {
  709. wstring text = L"{% if item %}{% if thing %}{$item}{$thing}{% endif %}{% endif %}" ;
  710. data_map data ;
  711. data[L"item"] = make_data(L"aaa") ;
  712. data[L"thing"] = make_data(L"") ;
  713. wstring actual = parse(text, data) ;
  714. wstring expected = L"" ;
  715. BOOST_CHECK_EQUAL( expected, actual ) ;
  716. }
  717. BOOST_AUTO_TEST_CASE(test_nested_if_true)
  718. {
  719. wstring text = L"{% if item %}{% if thing %}{$item}{$thing}{% endif %}{% endif %}" ;
  720. data_map data ;
  721. data[L"item"] = make_data(L"aaa") ;
  722. data[L"thing"] = make_data(L"bbb") ;
  723. wstring actual = parse(text, data) ;
  724. wstring expected = L"aaabbb" ;
  725. BOOST_CHECK_EQUAL( expected, actual ) ;
  726. }
  727. BOOST_AUTO_TEST_CASE(test_usage_example)
  728. {
  729. wstring text = L"{% if item %}{$item}{% endif %}\n"
  730. L"{% if thing %}{$thing}{% endif %}" ;
  731. cpptempl::data_map data ;
  732. data[L"item"] = cpptempl::make_data(L"aaa") ;
  733. data[L"thing"] = cpptempl::make_data(L"bbb") ;
  734. wstring result = cpptempl::parse(text, data) ;
  735. wstring expected = L"aaa\nbbb" ;
  736. BOOST_CHECK_EQUAL( result, expected ) ;
  737. }
  738. BOOST_AUTO_TEST_CASE(test_syntax_if)
  739. {
  740. wstring text = L"{% if person.name == \"Bob\" %}Full name: Robert{% endif %}" ;
  741. data_map person ;
  742. person[L"name"] = make_data(L"Bob") ;
  743. person[L"occupation"] = make_data(L"Plumber") ;
  744. data_map data ;
  745. data[L"person"] = make_data(person) ;
  746. wstring result = cpptempl::parse(text, data) ;
  747. wstring expected = L"Full name: Robert" ;
  748. BOOST_CHECK_EQUAL( result, expected ) ;
  749. }
  750. BOOST_AUTO_TEST_CASE(test_syntax_dotted)
  751. {
  752. wstring text = L"{% for friend in person.friends %}"
  753. L"{$loop.index}. {$friend.name} "
  754. L"{% endfor %}" ;
  755. data_map bob ;
  756. bob[L"name"] = make_data(L"Bob") ;
  757. data_map betty ;
  758. betty[L"name"] = make_data(L"Betty") ;
  759. data_list friends ;
  760. friends.push_back(make_data(bob)) ;
  761. friends.push_back(make_data(betty)) ;
  762. data_map person ;
  763. person[L"friends"] = make_data(friends) ;
  764. data_map data ;
  765. data[L"person"] = make_data(person) ;
  766. wstring result = cpptempl::parse(text, data) ;
  767. wstring expected = L"1. Bob 2. Betty " ;
  768. BOOST_CHECK_EQUAL( result, expected ) ;
  769. }
  770. BOOST_AUTO_TEST_CASE(test_example_okinawa)
  771. {
  772. // The text template
  773. wstring text = L"I heart {$place}!" ;
  774. // Data to feed the template engine
  775. cpptempl::data_map data ;
  776. // {$place} => Okinawa
  777. data[L"place"] = cpptempl::make_data(L"Okinawa");
  778. // parse the template with the supplied data dictionary
  779. wstring result = cpptempl::parse(text, data) ;
  780. wstring expected = L"I heart Okinawa!" ;
  781. BOOST_CHECK_EQUAL( result, expected ) ;
  782. }
  783. BOOST_AUTO_TEST_CASE(test_example_ul)
  784. {
  785. wstring text = L"<h3>Locations</h3><ul>"
  786. L"{% for place in places %}"
  787. L"<li>{$place}</li>"
  788. L"{% endfor %}"
  789. L"</ul>" ;
  790. // Create the list of items
  791. cpptempl::data_list places;
  792. places.push_back(cpptempl::make_data(L"Okinawa"));
  793. places.push_back(cpptempl::make_data(L"San Francisco"));
  794. // Now set this in the data map
  795. cpptempl::data_map data ;
  796. data[L"places"] = cpptempl::make_data(places);
  797. // parse the template with the supplied data dictionary
  798. wstring result = cpptempl::parse(text, data) ;
  799. wstring expected = L"<h3>Locations</h3><ul>"
  800. L"<li>Okinawa</li>"
  801. L"<li>San Francisco</li>"
  802. L"</ul>" ;
  803. BOOST_CHECK_EQUAL(result, expected) ;
  804. }
  805. BOOST_AUTO_TEST_SUITE_END()
  806. #endif