parse_enum_ut.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  1. #include <library/cpp/resource/resource.h>
  2. #include <library/cpp/testing/unittest/registar.h>
  3. #include <tools/enum_parser/parse_enum/parse_enum.h>
  4. typedef TEnumParser::TEnum TEnum;
  5. typedef TEnumParser::TEnums TEnums;
  6. typedef TEnumParser::TItems TItems;
  7. Y_UNIT_TEST_SUITE(TEnumParserTest) {
  8. Y_UNIT_TEST(MainTest) {
  9. TString text = NResource::Find("/enums");
  10. TMemoryInput input(text.data(), text.size());
  11. TEnumParser parser(input);
  12. const TEnums& enums = parser.Enums;
  13. UNIT_ASSERT_VALUES_EQUAL(enums.size(), 16u);
  14. // check ESimple
  15. {
  16. const TEnum& e = enums[0];
  17. UNIT_ASSERT_VALUES_EQUAL(e.Scope.size(), 0u);
  18. UNIT_ASSERT_VALUES_EQUAL(e.CppName, "ESimple");
  19. const TItems& it = e.Items;
  20. UNIT_ASSERT_VALUES_EQUAL(it.size(), 3u);
  21. UNIT_ASSERT_VALUES_EQUAL(it[0].CppName, "Http");
  22. UNIT_ASSERT_VALUES_EQUAL(it[0].Aliases.size(), 0u);
  23. UNIT_ASSERT(!it[0].Value.Defined());
  24. UNIT_ASSERT_VALUES_EQUAL(it[1].CppName, "Https");
  25. UNIT_ASSERT_VALUES_EQUAL(it[1].Aliases.size(), 0u);
  26. UNIT_ASSERT(!it[1].Value.Defined());
  27. UNIT_ASSERT_VALUES_EQUAL(it[2].CppName, "ItemCount");
  28. UNIT_ASSERT_VALUES_EQUAL(it[2].Aliases.size(), 0u);
  29. UNIT_ASSERT(!it[2].Value.Defined());
  30. }
  31. // ESimpleWithComma
  32. {
  33. const TEnum& e = enums[1];
  34. UNIT_ASSERT_VALUES_EQUAL(e.Scope.size(), 0u);
  35. UNIT_ASSERT_VALUES_EQUAL(e.CppName, "ESimpleWithComma");
  36. const TItems& it = e.Items;
  37. UNIT_ASSERT_VALUES_EQUAL(it.size(), 4u);
  38. UNIT_ASSERT_VALUES_EQUAL(it[0].CppName, "Http");
  39. UNIT_ASSERT(it[0].Value.Defined());
  40. UNIT_ASSERT_VALUES_EQUAL(*it[0].Value, "3");
  41. UNIT_ASSERT_VALUES_EQUAL(it[0].Aliases.size(), 0u);
  42. UNIT_ASSERT_VALUES_EQUAL(it[1].CppName, "Http2");
  43. UNIT_ASSERT(it[1].Value.Defined());
  44. UNIT_ASSERT_VALUES_EQUAL(it[1].Aliases.size(), 0u);
  45. UNIT_ASSERT_VALUES_EQUAL(*it[1].Value, "Http");
  46. UNIT_ASSERT_VALUES_EQUAL(it[2].CppName, "Https");
  47. UNIT_ASSERT_VALUES_EQUAL(it[2].Aliases.size(), 0u);
  48. UNIT_ASSERT(!it[2].Value.Defined());
  49. UNIT_ASSERT_VALUES_EQUAL(it[3].CppName, "ItemCount");
  50. UNIT_ASSERT_VALUES_EQUAL(it[3].Aliases.size(), 0u);
  51. UNIT_ASSERT(!it[3].Value.Defined());
  52. }
  53. // check ECustomAliases
  54. {
  55. const TEnum& e = enums[2];
  56. UNIT_ASSERT_VALUES_EQUAL(e.Scope.size(), 0u);
  57. UNIT_ASSERT_VALUES_EQUAL(e.CppName, "ECustomAliases");
  58. const TItems& it = e.Items;
  59. UNIT_ASSERT_VALUES_EQUAL(it.size(), 3u);
  60. UNIT_ASSERT_VALUES_EQUAL(it[0].CppName, "CAHttp");
  61. UNIT_ASSERT(it[0].Value.Defined());
  62. UNIT_ASSERT_VALUES_EQUAL(*it[0].Value, "3");
  63. UNIT_ASSERT_VALUES_EQUAL(it[0].Aliases.size(), 1u);
  64. UNIT_ASSERT_VALUES_EQUAL(it[0].Aliases[0], "http");
  65. UNIT_ASSERT(!it[1].Value.Defined());
  66. UNIT_ASSERT_VALUES_EQUAL(it[1].CppName, "CAHttps");
  67. UNIT_ASSERT_VALUES_EQUAL(it[1].Aliases.size(), 1u);
  68. UNIT_ASSERT_VALUES_EQUAL(it[1].Aliases[0], "https");
  69. UNIT_ASSERT_VALUES_EQUAL(it[2].CppName, "CAItemCount");
  70. UNIT_ASSERT_VALUES_EQUAL(it[2].Aliases.size(), 0u);
  71. }
  72. // check EMultipleAliases
  73. {
  74. const TEnum& e = enums[3];
  75. UNIT_ASSERT_VALUES_EQUAL(e.Scope.size(), 0u);
  76. UNIT_ASSERT_VALUES_EQUAL(e.CppName, "EMultipleAliases");
  77. const TItems& it = e.Items;
  78. UNIT_ASSERT_VALUES_EQUAL(it.size(), 3u);
  79. UNIT_ASSERT_VALUES_EQUAL(it[0].CppName, "MAHttp");
  80. UNIT_ASSERT(it[0].Value.Defined());
  81. UNIT_ASSERT_VALUES_EQUAL(*it[0].Value, "9");
  82. UNIT_ASSERT_VALUES_EQUAL(it[0].Aliases.size(), 3u);
  83. UNIT_ASSERT_VALUES_EQUAL(it[0].Aliases[0], "http://");
  84. UNIT_ASSERT_VALUES_EQUAL(it[0].Aliases[1], "secondary");
  85. // yes, quoted values are NOT decoded, it is a known (minor) bug
  86. UNIT_ASSERT_VALUES_EQUAL(it[0].Aliases[2], "old\\nvalue");
  87. UNIT_ASSERT_VALUES_EQUAL(it[1].CppName, "MAHttps");
  88. UNIT_ASSERT(it[1].Value.Defined());
  89. UNIT_ASSERT_VALUES_EQUAL(*it[1].Value, "1");
  90. UNIT_ASSERT_VALUES_EQUAL(it[1].Aliases.size(), 1u);
  91. UNIT_ASSERT_VALUES_EQUAL(it[1].Aliases[0], "https://");
  92. UNIT_ASSERT_VALUES_EQUAL(it[2].CppName, "MAItemCount");
  93. UNIT_ASSERT(!it[2].Value.Defined());
  94. UNIT_ASSERT_VALUES_EQUAL(it[2].Aliases.size(), 0u);
  95. }
  96. // check NEnumNamespace::EInNamespace
  97. {
  98. const TEnum& e = enums[4];
  99. UNIT_ASSERT_VALUES_EQUAL(e.Scope.size(), 1u);
  100. UNIT_ASSERT_VALUES_EQUAL(e.Scope[0], "NEnumNamespace");
  101. UNIT_ASSERT_VALUES_EQUAL(e.CppName, "EInNamespace");
  102. const TItems& it = e.Items;
  103. UNIT_ASSERT_VALUES_EQUAL(it.size(), 3u);
  104. UNIT_ASSERT_VALUES_EQUAL(it[0].CppName, "Http");
  105. UNIT_ASSERT(it[0].Value.Defined());
  106. }
  107. // check NEnumNamespace::TEnumClass::EInClass
  108. {
  109. const TEnum& e = enums[5];
  110. UNIT_ASSERT_VALUES_EQUAL(e.Scope.size(), 2u);
  111. UNIT_ASSERT_VALUES_EQUAL(e.Scope[0], "NEnumNamespace");
  112. UNIT_ASSERT_VALUES_EQUAL(e.Scope[1], "TEnumClass");
  113. UNIT_ASSERT_VALUES_EQUAL(e.CppName, "EInClass");
  114. const TItems& it = e.Items;
  115. UNIT_ASSERT_VALUES_EQUAL(it.size(), 3u);
  116. UNIT_ASSERT_VALUES_EQUAL(it[0].CppName, "Http");
  117. UNIT_ASSERT(it[0].Value.Defined());
  118. UNIT_ASSERT_VALUES_EQUAL(*it[0].Value, "9");
  119. UNIT_ASSERT(it[1].Value.Defined());
  120. UNIT_ASSERT_VALUES_EQUAL(*it[1].Value, "NEnumNamespace::Https");
  121. UNIT_ASSERT_VALUES_EQUAL(it[2].CppName, "Https3");
  122. UNIT_ASSERT(it[2].Value.Defined());
  123. UNIT_ASSERT_VALUES_EQUAL(*it[2].Value, "1 + 2");
  124. }
  125. // check unnamed enum (no code should be generated for it)
  126. {
  127. const TEnum& e = enums[6];
  128. UNIT_ASSERT_VALUES_EQUAL(e.Scope.size(), 0u);
  129. UNIT_ASSERT_VALUES_EQUAL(e.CppName, "");
  130. const TItems& it = e.Items;
  131. UNIT_ASSERT_VALUES_EQUAL(it.size(), 3u);
  132. }
  133. // TEXT_WEIGHT
  134. {
  135. const TEnum& e = enums[7];
  136. UNIT_ASSERT_VALUES_EQUAL(e.Scope.size(), 0u);
  137. UNIT_ASSERT_VALUES_EQUAL(e.CppName, "TEXT_WEIGHT");
  138. const TItems& it = e.Items;
  139. UNIT_ASSERT_VALUES_EQUAL(it.size(), 5u);
  140. UNIT_ASSERT_VALUES_EQUAL(it[0].CppName, "WEIGHT_ZERO");
  141. UNIT_ASSERT(it[0].Value.Defined());
  142. UNIT_ASSERT_VALUES_EQUAL(*it[0].Value, "-1");
  143. UNIT_ASSERT_VALUES_EQUAL(it[0].Aliases.size(), 0u);
  144. UNIT_ASSERT_VALUES_EQUAL(it[1].CppName, "WEIGHT_LOW");
  145. UNIT_ASSERT_VALUES_EQUAL(it[1].Aliases.size(), 0u);
  146. UNIT_ASSERT(!it[1].Value.Defined());
  147. UNIT_ASSERT_VALUES_EQUAL(it[2].CppName, "WEIGHT_NORMAL");
  148. UNIT_ASSERT_VALUES_EQUAL(it[2].Aliases.size(), 0u);
  149. UNIT_ASSERT(!it[2].Value.Defined());
  150. }
  151. // EDuplicateKeys
  152. {
  153. const TEnum& e = enums[8];
  154. UNIT_ASSERT_VALUES_EQUAL(e.Scope.size(), 0u);
  155. UNIT_ASSERT_VALUES_EQUAL(e.CppName, "EDuplicateKeys");
  156. const TItems& it = e.Items;
  157. UNIT_ASSERT_VALUES_EQUAL(it.size(), 5u);
  158. UNIT_ASSERT_VALUES_EQUAL(it[0].CppName, "Key0");
  159. UNIT_ASSERT(it[0].Value.Defined());
  160. UNIT_ASSERT_VALUES_EQUAL(*it[0].Value, "0");
  161. UNIT_ASSERT_VALUES_EQUAL(it[0].Aliases.size(), 0u);
  162. UNIT_ASSERT_VALUES_EQUAL(it[1].CppName, "Key0Second");
  163. UNIT_ASSERT(it[1].Value.Defined());
  164. UNIT_ASSERT_VALUES_EQUAL(*it[1].Value, "Key0");
  165. UNIT_ASSERT_VALUES_EQUAL(it[1].Aliases.size(), 0u);
  166. }
  167. // EEmpty
  168. {
  169. const TEnum& e = enums[10];
  170. const TItems& it = e.Items;
  171. UNIT_ASSERT_VALUES_EQUAL(it.size(), 0u);
  172. }
  173. // NComposite::NInner::EInCompositeNamespaceSimple
  174. {
  175. const TEnum& e = enums[11];
  176. UNIT_ASSERT_VALUES_EQUAL(e.Scope.size(), 1u);
  177. UNIT_ASSERT_VALUES_EQUAL(e.Scope[0], "NComposite::NInner");
  178. UNIT_ASSERT_VALUES_EQUAL(e.CppName, "EInCompositeNamespaceSimple");
  179. const TItems& it = e.Items;
  180. UNIT_ASSERT_VALUES_EQUAL(it.size(), 3u);
  181. UNIT_ASSERT_VALUES_EQUAL(it[0].CppName, "one");
  182. UNIT_ASSERT_VALUES_EQUAL(*it[1].Value, "2") ;
  183. }
  184. // NOuterSimple::NComposite::NMiddle::NInner::NInnerSimple::TEnumClass::EVeryDeep
  185. {
  186. const TEnum& e = enums[12];
  187. UNIT_ASSERT_VALUES_EQUAL(e.Scope.size(), 4u);
  188. UNIT_ASSERT_VALUES_EQUAL(e.Scope[0], "NOuterSimple");
  189. UNIT_ASSERT_VALUES_EQUAL(e.Scope[1], "NComposite::NMiddle::NInner");
  190. UNIT_ASSERT_VALUES_EQUAL(e.Scope[2], "NInnerSimple");
  191. UNIT_ASSERT_VALUES_EQUAL(e.Scope[3], "TEnumClass");
  192. UNIT_ASSERT_VALUES_EQUAL(e.CppName, "EVeryDeep");
  193. const TItems& it = e.Items;
  194. UNIT_ASSERT_VALUES_EQUAL(it.size(), 2u);
  195. UNIT_ASSERT_VALUES_EQUAL(it[0].CppName, "Key0");
  196. UNIT_ASSERT_VALUES_EQUAL(it[1].CppName, "Key1");
  197. UNIT_ASSERT_VALUES_EQUAL(*it[1].Value, "1");
  198. }
  199. // ENonLiteralValues
  200. {
  201. const TEnum& e = enums[13];
  202. UNIT_ASSERT_VALUES_EQUAL(e.Scope.size(), 0u);
  203. UNIT_ASSERT_VALUES_EQUAL(e.CppName, "ENonLiteralValues");
  204. const TItems& it = e.Items;
  205. UNIT_ASSERT_VALUES_EQUAL(it.size(), 5u);
  206. UNIT_ASSERT_VALUES_EQUAL(it[0].CppName, "one");
  207. UNIT_ASSERT_VALUES_EQUAL(*it[0].Value, "MACRO(1, 2)");
  208. UNIT_ASSERT_VALUES_EQUAL(it[1].CppName, "two");
  209. UNIT_ASSERT_VALUES_EQUAL(*it[1].Value, "2");
  210. UNIT_ASSERT_VALUES_EQUAL(it[2].CppName, "three");
  211. UNIT_ASSERT_VALUES_EQUAL(*it[2].Value, "func(3)");
  212. UNIT_ASSERT_VALUES_EQUAL(it[3].CppName, "four");
  213. UNIT_ASSERT_VALUES_EQUAL(it[3].Value.Defined(), false);
  214. UNIT_ASSERT_VALUES_EQUAL(it[4].CppName, "five");
  215. UNIT_ASSERT_VALUES_EQUAL(it[4].Value, "MACRO(MACRO(1, 2), 2)");
  216. }
  217. // NotifyingStatus
  218. {
  219. const TEnum& e = enums[15];
  220. UNIT_ASSERT_VALUES_EQUAL(e.Scope.size(), 0u);
  221. UNIT_ASSERT_VALUES_EQUAL(e.CppName, "NotifyingStatus");
  222. const TItems& it = e.Items;
  223. UNIT_ASSERT_VALUES_EQUAL(it.size(), 4u);
  224. UNIT_ASSERT_VALUES_EQUAL(it[0].CppName, "NEW");
  225. UNIT_ASSERT_VALUES_EQUAL(*it[0].Value, "0");
  226. UNIT_ASSERT_VALUES_EQUAL(it[1].CppName, "FAILED_WILL_RETRY");
  227. UNIT_ASSERT_VALUES_EQUAL(*it[1].Value, "1");
  228. UNIT_ASSERT_VALUES_EQUAL(it[2].CppName, "FAILED_NO_MORE_TRIALS");
  229. UNIT_ASSERT_VALUES_EQUAL(*it[2].Value, "2");
  230. UNIT_ASSERT_VALUES_EQUAL(it[3].CppName, "SENT");
  231. UNIT_ASSERT_VALUES_EQUAL(*it[3].Value, "3");
  232. }
  233. }
  234. Y_UNIT_TEST(BadCodeParseTest) {
  235. TString text = NResource::Find("/badcode");
  236. TMemoryInput input(text.data(), text.size());
  237. TEnumParser parser(input);
  238. const TEnums& enums = parser.Enums;
  239. UNIT_ASSERT_VALUES_EQUAL(enums.size(), 1u);
  240. // check <anonymous namespace>::ETest correct parsing
  241. {
  242. const TEnum& e = enums[0];
  243. UNIT_ASSERT_VALUES_EQUAL(e.Scope.size(), 1u);
  244. UNIT_ASSERT_VALUES_EQUAL(e.CppName, "ETest");
  245. const TItems& it = e.Items;
  246. UNIT_ASSERT_VALUES_EQUAL(it.size(), 3u);
  247. UNIT_ASSERT_VALUES_EQUAL(it[0].CppName, "Http");
  248. UNIT_ASSERT(it[0].Value.Defined());
  249. }
  250. }
  251. Y_UNIT_TEST(UnbalancedCodeParseTest) {
  252. // Thanks gotmanov@ for providing this example
  253. TString text = NResource::Find("/unbalanced");
  254. TMemoryInput input(text.data(), text.size());
  255. try {
  256. TEnumParser parser(input);
  257. UNIT_ASSERT(false);
  258. } catch(...) {
  259. UNIT_ASSERT(CurrentExceptionMessage().Contains("unbalanced scope. Did you miss a closing"));
  260. }
  261. }
  262. Y_UNIT_TEST(AliasBeforeNameTest) {
  263. TString text = NResource::Find("/alias_before_name");
  264. TMemoryInput input(text.data(), text.size());
  265. try {
  266. TEnumParser parser(input);
  267. UNIT_ASSERT(false);
  268. } catch(...) {
  269. UNIT_ASSERT(CurrentExceptionMessage().Contains("https://clubs.at.yandex-team.ru/stackoverflow/2603"));
  270. }
  271. }
  272. }