scheme_ut.cpp 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966
  1. #include <library/cpp/scheme/scimpl_private.h>
  2. #include <library/cpp/scheme/ut_utils/scheme_ut_utils.h>
  3. #include <library/cpp/testing/unittest/registar.h>
  4. #include <util/stream/null.h>
  5. #include <library/cpp/string_utils/quote/quote.h>
  6. #include <util/string/subst.h>
  7. #include <util/string/util.h>
  8. #include <type_traits>
  9. Y_UNIT_TEST_SUITE(TSchemeTest) {
  10. Y_UNIT_TEST(TestNaN) {
  11. UNIT_ASSERT_VALUES_EQUAL("null", NSc::TValue(std::numeric_limits<double>::quiet_NaN()).ToJson());
  12. UNIT_ASSERT_VALUES_EQUAL("null", NSc::TValue(-std::numeric_limits<double>::infinity()).ToJson());
  13. UNIT_ASSERT_VALUES_EQUAL("null", NSc::TValue(std::numeric_limits<double>::infinity()).ToJson());
  14. UNIT_ASSERT_VALUES_EQUAL("1", NSc::TValue(1.0).ToJson());
  15. }
  16. Y_UNIT_TEST(TestNumbers) {
  17. {
  18. NSc::TValue vd;
  19. UNIT_ASSERT_VALUES_EQUAL(2.5, vd.GetNumberMutable(2.5));
  20. UNIT_ASSERT_VALUES_EQUAL(2, vd.GetIntNumberMutable(-1));
  21. }
  22. {
  23. NSc::TValue vi;
  24. UNIT_ASSERT_VALUES_EQUAL(2, vi.GetIntNumberMutable(2));
  25. UNIT_ASSERT_VALUES_EQUAL(2., vi.GetNumberMutable(-1));
  26. }
  27. {
  28. NSc::TValue vb = NSc::TValue::FromJson("true");
  29. UNIT_ASSERT_VALUES_EQUAL("true", vb.ToJson());
  30. UNIT_ASSERT(vb.IsBool());
  31. UNIT_ASSERT(vb.IsIntNumber());
  32. UNIT_ASSERT(vb.IsNumber());
  33. UNIT_ASSERT_VALUES_EQUAL(true, vb.GetBool());
  34. UNIT_ASSERT_VALUES_EQUAL(1, vb.GetIntNumber());
  35. UNIT_ASSERT_VALUES_EQUAL(1.0, vb.GetNumber());
  36. NSc::TValue vb1 = vb.Clone();
  37. UNIT_ASSERT(NSc::TValue::Equal(vb, vb1));
  38. UNIT_ASSERT_VALUES_EQUAL(true, vb.GetBool());
  39. UNIT_ASSERT_VALUES_EQUAL(1, vb.GetIntNumber());
  40. UNIT_ASSERT_VALUES_EQUAL(1.0, vb.GetNumber());
  41. UNIT_ASSERT(vb.IsBool());
  42. UNIT_ASSERT_VALUES_EQUAL(1, vb.GetIntNumberMutable());
  43. UNIT_ASSERT(!vb.IsBool());
  44. UNIT_ASSERT(NSc::TValue::Equal(vb, vb1));
  45. UNIT_ASSERT(vb1.IsBool());
  46. UNIT_ASSERT_VALUES_EQUAL(1.0, vb1.GetNumberMutable());
  47. UNIT_ASSERT(!vb1.IsBool());
  48. vb.SetBool(true);
  49. UNIT_ASSERT(vb.IsBool());
  50. UNIT_ASSERT(NSc::TValue::Equal(vb, vb1));
  51. vb = NSc::TValue::FromJson("false");
  52. UNIT_ASSERT_VALUES_EQUAL("false", vb.ToJson());
  53. UNIT_ASSERT(!NSc::TValue::Equal(vb, vb1));
  54. UNIT_ASSERT(vb.IsBool());
  55. UNIT_ASSERT(vb.IsIntNumber());
  56. UNIT_ASSERT(vb.IsNumber());
  57. UNIT_ASSERT_VALUES_EQUAL(false, vb.GetBool());
  58. UNIT_ASSERT_VALUES_EQUAL(0.0, vb.GetNumber());
  59. UNIT_ASSERT_VALUES_EQUAL(0, vb.GetIntNumber());
  60. NSc::TValue vd = NSc::TValue::FromJson("1.0");
  61. UNIT_ASSERT(vd.IsNumber());
  62. UNIT_ASSERT(!vd.IsIntNumber());
  63. UNIT_ASSERT_VALUES_EQUAL(1.0, vd.GetNumber());
  64. UNIT_ASSERT_VALUES_EQUAL(1, vd.GetIntNumber());
  65. UNIT_ASSERT_VALUES_EQUAL(1.0, vd.GetNumberMutable());
  66. NSc::TValue vi = NSc::TValue::FromJson("1");
  67. UNIT_ASSERT(vi.IsNumber());
  68. UNIT_ASSERT(vi.IsIntNumber());
  69. UNIT_ASSERT_VALUES_EQUAL(1.0, vi.GetNumber());
  70. UNIT_ASSERT_VALUES_EQUAL(1, vi.GetIntNumber());
  71. UNIT_ASSERT_VALUES_EQUAL(1, vi.GetIntNumberMutable());
  72. UNIT_ASSERT(NSc::TValue::Equal(vd, vi));
  73. vd.SetNumber(1.5);
  74. UNIT_ASSERT(vd.IsNumber());
  75. UNIT_ASSERT(!vd.IsIntNumber());
  76. UNIT_ASSERT_VALUES_EQUAL(1.5, vd.GetNumber());
  77. UNIT_ASSERT_VALUES_EQUAL(1, vd.GetIntNumber());
  78. UNIT_ASSERT_VALUES_EQUAL(1.5, vd.GetNumberMutable());
  79. UNIT_ASSERT(!NSc::TValue::Equal(vd, vi));
  80. UNIT_ASSERT_VALUES_EQUAL("1", vi.ToJson());
  81. UNIT_ASSERT_VALUES_EQUAL("1.5", vd.ToJson());
  82. UNIT_ASSERT_VALUES_EQUAL(1, vd.GetIntNumberMutable());
  83. UNIT_ASSERT(NSc::TValue::Equal(vd, vi));
  84. vd.SetIntNumber(2);
  85. UNIT_ASSERT(!NSc::TValue::Equal(vd, vi));
  86. vi.SetNumber(2.);
  87. UNIT_ASSERT(NSc::TValue::Equal(vd, vi));
  88. vd.SetNumber(2.);
  89. UNIT_ASSERT(NSc::TValue::Equal(vd, vi));
  90. vi.SetIntNumber(5);
  91. vd.MergeUpdate(vi);
  92. UNIT_ASSERT(vd.IsNumber());
  93. UNIT_ASSERT(vd.IsIntNumber());
  94. UNIT_ASSERT_VALUES_EQUAL(5, vd.GetIntNumber());
  95. vd.SetNumber(3.3);
  96. vi.MergeUpdate(vd);
  97. UNIT_ASSERT(vi.IsNumber());
  98. UNIT_ASSERT(!vi.IsIntNumber());
  99. UNIT_ASSERT_VALUES_EQUAL(3.3, vi.GetNumber());
  100. vi.SetIntNumber(Max<i64>());
  101. UNIT_ASSERT_VALUES_EQUAL("9223372036854775807", vi.ToJson());
  102. }
  103. }
  104. template <typename T>
  105. void DoTestForce(T t) {
  106. UNIT_ASSERT_VALUES_EQUAL_C(i64(t), NSc::TValue(i64(t)).ForceIntNumber(), ToString(t));
  107. UNIT_ASSERT_VALUES_EQUAL_C(double(t), NSc::TValue(double(t)).ForceNumber(), ToString(t));
  108. UNIT_ASSERT_VALUES_EQUAL_C(i64(t), NSc::TValue(TStringBuf(ToString(i64(t)))).ForceIntNumber(), ToString(t));
  109. UNIT_ASSERT_VALUES_EQUAL_C(ToString(double(t)), ToString(NSc::TValue(TStringBuf(ToString(double(t)))).ForceNumber()), ToString(t));
  110. UNIT_ASSERT_VALUES_EQUAL_C(ToString(i64(t)), NSc::TValue(TStringBuf(ToString(i64(t)))).ForceString(), ToString(t));
  111. UNIT_ASSERT_VALUES_EQUAL_C(ToString(double(t)), NSc::TValue(TStringBuf(ToString(double(t)))).ForceString(), ToString(t));
  112. }
  113. Y_UNIT_TEST(TestForce) {
  114. DoTestForce(Max<i64>());
  115. DoTestForce(Min<i64>());
  116. DoTestForce(1.5);
  117. DoTestForce(-1.5);
  118. UNIT_ASSERT_VALUES_EQUAL(1, NSc::TValue("32a").ForceIntNumber(1));
  119. UNIT_ASSERT_VALUES_EQUAL(1.5, NSc::TValue("32a").ForceNumber(1.5));
  120. }
  121. template <typename T>
  122. void DoCheckRelations(T t, T tless, T tmore, const NSc::TValue& v, TStringBuf ss) {
  123. UNIT_ASSERT_C((t == v), ss);
  124. UNIT_ASSERT_C(!(t != v), ss);
  125. UNIT_ASSERT_C((t <= v), ss);
  126. UNIT_ASSERT_C((t >= v), ss);
  127. UNIT_ASSERT_C(!(t < v), ss);
  128. UNIT_ASSERT_C(!(t > v), ss);
  129. UNIT_ASSERT_C(!(tless == v), ss);
  130. UNIT_ASSERT_C((tless != v), ss);
  131. UNIT_ASSERT_C((tless <= v), ss);
  132. UNIT_ASSERT_C(!(tless >= v), ss);
  133. UNIT_ASSERT_C((tless < v), ss);
  134. UNIT_ASSERT_C(!(tless > v), ss);
  135. UNIT_ASSERT_C(!(tmore == v), ss);
  136. UNIT_ASSERT_C((tmore != v), ss);
  137. UNIT_ASSERT_C(!(tmore <= v), ss);
  138. UNIT_ASSERT_C((tmore >= v), ss);
  139. UNIT_ASSERT_C(!(tmore < v), ss);
  140. UNIT_ASSERT_C((tmore > v), ss);
  141. }
  142. void DoCheckRelations(const NSc::TValue& t, const NSc::TValue&, const NSc::TValue&, const NSc::TValue& v, TStringBuf ss) {
  143. UNIT_ASSERT_C((t == v), ss);
  144. UNIT_ASSERT_C(!(t != v), ss);
  145. }
  146. // void DoCheckRelations(bool t, bool, bool, const NSc::TValue& v, TStringBuf ss) {
  147. // UNIT_ASSERT_C((t == v), ss);
  148. // UNIT_ASSERT_C(!(t != v), ss);
  149. // }
  150. template <typename T>
  151. void DoCheckAssignment(T t, T tless, T tmore, TStringBuf s, TStringBuf ss) {
  152. bool expectint = std::is_integral<T>::value;
  153. bool expectnum = std::is_arithmetic<T>::value;
  154. bool expectbool = std::is_same<bool, T>::value;
  155. {
  156. NSc::TValue v(t);
  157. UNIT_ASSERT_VALUES_EQUAL_C(expectnum, v.IsNumber(), ss);
  158. UNIT_ASSERT_VALUES_EQUAL_C(expectint, v.IsIntNumber(), ss);
  159. UNIT_ASSERT_VALUES_EQUAL_C(expectbool, v.IsBool(), ss);
  160. UNIT_ASSERT_VALUES_EQUAL_C(s, v.ToJson(), ss);
  161. DoCheckRelations(t, tless, tmore, v, ss);
  162. }
  163. {
  164. NSc::TValue v;
  165. UNIT_ASSERT(v.IsNull());
  166. v = t;
  167. UNIT_ASSERT(!v.IsNull());
  168. UNIT_ASSERT_VALUES_EQUAL_C(expectnum, v.IsNumber(), ss);
  169. UNIT_ASSERT_VALUES_EQUAL_C(expectint, v.IsIntNumber(), ss);
  170. UNIT_ASSERT_VALUES_EQUAL_C(expectbool, v.IsBool(), ss);
  171. UNIT_ASSERT_VALUES_EQUAL_C(s, v.ToJson(), ss);
  172. DoCheckRelations(t, tless, tmore, v, ss);
  173. }
  174. }
  175. template <size_t N>
  176. void DoCheckAssignmentArr(const char (&t)[N], const char (&tless)[N], const char (&tmore)[N], TStringBuf s, TStringBuf ss) {
  177. {
  178. NSc::TValue v(t);
  179. UNIT_ASSERT_C(v.IsString(), ss);
  180. UNIT_ASSERT_VALUES_EQUAL_C(s, v.ToJson(), ss);
  181. DoCheckRelations(t, tless, tmore, v, ss);
  182. }
  183. {
  184. NSc::TValue v;
  185. v = t;
  186. UNIT_ASSERT_C(v.IsString(), ss);
  187. UNIT_ASSERT_VALUES_EQUAL_C(s, v.ToJson(), ss);
  188. DoCheckRelations(t, tless, tmore, v, ss);
  189. }
  190. }
  191. template <typename T>
  192. void DoCheckAssignmentNum(T t, T tless, T tmore, TStringBuf s, TStringBuf ss) {
  193. DoCheckAssignment(t, tless, tmore, s, ss);
  194. {
  195. NSc::TValue v;
  196. T tt = (v = t);
  197. UNIT_ASSERT_VALUES_EQUAL_C(t, tt, ss);
  198. }
  199. }
  200. Y_UNIT_TEST(TestAssignments) {
  201. for (int i = -2; i < 3; ++i) {
  202. TString ii = ToString(i);
  203. int iless = i - 1;
  204. int imore = i + 1;
  205. DoCheckAssignmentNum<signed char>(i, iless, imore, ii, "schar");
  206. DoCheckAssignmentNum<short>(i, iless, imore, ii, "short");
  207. DoCheckAssignmentNum<int>(i, iless, imore, ii, "int");
  208. DoCheckAssignmentNum<long>(i, iless, imore, ii, "long");
  209. DoCheckAssignmentNum<long long>(i, iless, imore, ii, "longlong");
  210. DoCheckAssignmentNum<i8>(i, iless, imore, ii, "i8");
  211. DoCheckAssignmentNum<i16>(i, iless, imore, ii, "i16");
  212. DoCheckAssignmentNum<i32>(i, iless, imore, ii, "i32");
  213. DoCheckAssignmentNum<i64>(i, iless, imore, ii, "i64");
  214. DoCheckAssignmentNum<float>(i, iless, imore, ii, "float");
  215. DoCheckAssignmentNum<double>(i, iless, imore, ii, "double");
  216. }
  217. // DoCheckAssignment<bool>(true, true, true, "true", "bool");
  218. // DoCheckAssignment<bool>(false, false, false, "false", "bool");
  219. for (int i = 1; i < 3; ++i) {
  220. TString ii = ToString(i);
  221. int iless = i - 1;
  222. int imore = i + 1;
  223. DoCheckAssignmentNum<char>(i, iless, imore, ii, "char");
  224. DoCheckAssignmentNum<signed char>(i, iless, imore, ii, "schar");
  225. DoCheckAssignmentNum<short>(i, iless, imore, ii, "short");
  226. DoCheckAssignmentNum<int>(i, iless, imore, ii, "int");
  227. DoCheckAssignmentNum<long>(i, iless, imore, ii, "long");
  228. DoCheckAssignmentNum<long long>(i, iless, imore, ii, "longlong");
  229. DoCheckAssignmentNum<i8>(i, iless, imore, ii, "i8");
  230. DoCheckAssignmentNum<i16>(i, iless, imore, ii, "i16");
  231. DoCheckAssignmentNum<i32>(i, iless, imore, ii, "i32");
  232. DoCheckAssignmentNum<i64>(i, iless, imore, ii, "i64");
  233. DoCheckAssignmentNum<unsigned char>(i, iless, imore, ii, "uchar");
  234. DoCheckAssignmentNum<unsigned short>(i, iless, imore, ii, "ushort");
  235. DoCheckAssignmentNum<unsigned int>(i, iless, imore, ii, "uint");
  236. DoCheckAssignmentNum<unsigned long>(i, iless, imore, ii, "ulong");
  237. DoCheckAssignmentNum<unsigned long long>(i, iless, imore, ii, "ulonglong");
  238. DoCheckAssignmentNum<ui8>(i, iless, imore, ii, "ui8");
  239. DoCheckAssignmentNum<ui16>(i, iless, imore, ii, "ui16");
  240. DoCheckAssignmentNum<ui32>(i, iless, imore, ii, "ui32");
  241. DoCheckAssignmentNum<ui64>(i, iless, imore, ii, "ui64");
  242. DoCheckAssignmentNum<float>(i, iless, imore, ii, "float");
  243. DoCheckAssignmentNum<double>(i, iless, imore, ii, "double");
  244. }
  245. TString uuu = "uuu";
  246. TString uua = "uua";
  247. TString uuz = "uuz";
  248. DoCheckAssignment<char*>(uuu.begin(), uua.begin(), uuz.begin(), "\"uuu\"", "char*");
  249. DoCheckAssignment<const char*>("www", "wwa", "wwz", "\"www\"", "const char*");
  250. DoCheckAssignmentArr("xxx", "xxa", "xxz", "\"xxx\"", "const char[]");
  251. DoCheckAssignment<TStringBuf>("yyy", "yya", "yyz", "\"yyy\"", "TStringBuf");
  252. #if defined(_MSC_VER)
  253. //TODO
  254. #else
  255. DoCheckAssignment<TString>("ttt", "tta", "ttz", "\"ttt\"", "TString");
  256. #endif
  257. NSc::TValue v;
  258. v.SetDict();
  259. DoCheckAssignment<NSc::TValue>(v, v, v, "{}", "TValue");
  260. DoCheckAssignment<NSc::TValue&>(v, v, v, "{}", "TValue&");
  261. DoCheckAssignment<const NSc::TValue&>(v, v, v, "{}", "const TValue&");
  262. NSc::TValue v1{1};
  263. UNIT_ASSERT_VALUES_EQUAL(v1.ToJson(), "1");
  264. }
  265. Y_UNIT_TEST(TestAssignmentDictChild) {
  266. {
  267. NSc::TValue v;
  268. {
  269. NSc::TValue b;
  270. v["a"] = b;
  271. }
  272. v = v["a"];
  273. }
  274. {
  275. NSc::TValue v;
  276. {
  277. NSc::TValue b;
  278. v["a"] = b;
  279. }
  280. v = v.Get("a");
  281. }
  282. {
  283. NSc::TValue v;
  284. {
  285. NSc::TValue b;
  286. v["a"] = b;
  287. }
  288. v = std::move(v["a"]);
  289. }
  290. }
  291. Y_UNIT_TEST(TestInsert) {
  292. NSc::TValue v;
  293. v.Insert(0, "b");
  294. v.Insert(0, "a");
  295. v.Insert(2, "d");
  296. v.Insert(2, "c");
  297. UNIT_ASSERT_VALUES_EQUAL(v.ToJson(), R"(["a","b","c","d"])");
  298. v.AppendAll({1, 2, 3});
  299. UNIT_ASSERT_VALUES_EQUAL(v.ToJson(), R"(["a","b","c","d",1,2,3])");
  300. TVector<int> d{4, 5, 6};
  301. v.AppendAll(d);
  302. UNIT_ASSERT_VALUES_EQUAL(v.ToJson(), R"(["a","b","c","d",1,2,3,4,5,6])");
  303. UNIT_ASSERT_VALUES_EQUAL(d.size(), 3u);
  304. TVector<TStringBuf> s{"x", "y", "z"};
  305. v.AppendAll(s.begin(), s.end());
  306. UNIT_ASSERT_VALUES_EQUAL(v.ToJson(), R"(["a","b","c","d",1,2,3,4,5,6,"x","y","z"])");
  307. UNIT_ASSERT_VALUES_EQUAL(v.Clone().Clear().AppendAll(s).ToJson(), R"(["x","y","z"])");
  308. UNIT_ASSERT_VALUES_EQUAL(v.Clone().Clear().AppendAll(TVector<TStringBuf>()).ToJson(), R"([])");
  309. v.AddAll({{"a", "b"}, {"c", "d"}});
  310. UNIT_ASSERT_VALUES_EQUAL(v.ToJson(), R"({"a":"b","c":"d"})");
  311. }
  312. Y_UNIT_TEST(TestFrontBack) {
  313. NSc::TValue v;
  314. const NSc::TValue& vv = v;
  315. UNIT_ASSERT(NSc::TValue::Same(vv.Front(), NSc::Null()));
  316. UNIT_ASSERT(NSc::TValue::Same(vv.Back(), NSc::Null()));
  317. UNIT_ASSERT(!vv.IsArray());
  318. v.Back() = "a";
  319. UNIT_ASSERT_VALUES_EQUAL("a", vv.Front().GetString());
  320. UNIT_ASSERT_VALUES_EQUAL("a", vv.Back().GetString());
  321. UNIT_ASSERT(vv.IsArray());
  322. v.Push("b");
  323. UNIT_ASSERT_VALUES_EQUAL("a", vv.Front().GetString());
  324. UNIT_ASSERT_VALUES_EQUAL("b", vv.Back().GetString());
  325. UNIT_ASSERT_VALUES_EQUAL("b", v.Pop().GetString());
  326. UNIT_ASSERT_VALUES_EQUAL("a", vv.Front().GetString());
  327. UNIT_ASSERT_VALUES_EQUAL("a", vv.Back().GetString());
  328. UNIT_ASSERT_VALUES_EQUAL("a", v.Pop().GetString());
  329. UNIT_ASSERT(NSc::TValue::Same(vv.Front(), NSc::Null()));
  330. UNIT_ASSERT(NSc::TValue::Same(vv.Back(), NSc::Null()));
  331. v.Front() = "a";
  332. UNIT_ASSERT_VALUES_EQUAL("a", vv.Front().GetString());
  333. UNIT_ASSERT_VALUES_EQUAL("a", vv.Back().GetString());
  334. }
  335. Y_UNIT_TEST(TestAssign) {
  336. NSc::TValue v;
  337. v.SetArray();
  338. v.Push() = "test";
  339. UNIT_ASSERT_VALUES_EQUAL(v.ToJson(), "[\"test\"]");
  340. UNIT_ASSERT(NSc::TValue::SamePool(v[0], v));
  341. }
  342. NSc::TValue MutableRef(const NSc::TValue& v) {
  343. return v;
  344. }
  345. NSc::TValue Clone(const NSc::TValue& v) {
  346. NSc::TValue v1 = v.Clone();
  347. UNIT_ASSERT_VALUES_EQUAL(v1.ToJson(true), v.ToJson(true));
  348. return v1;
  349. }
  350. Y_UNIT_TEST(TestCOW) {
  351. NSc::TValue vd = NSc::TValue::FromJson("{ a : 1, b : c}");
  352. NSc::TValue va = NSc::TValue::FromJson("[ x, y]");
  353. NSc::TValue vs = NSc::TValue::FromJson("foo");
  354. NSc::TValue vn = NSc::TValue::FromJson("1");
  355. TString sd = "{\"a\":1,\"b\":\"c\"}";
  356. TString sa = "[\"x\",\"y\"]";
  357. TString ss = "\"foo\"";
  358. TString sn = "1";
  359. UNIT_ASSERT_VALUES_EQUAL(sd, vd.ToJson(true));
  360. UNIT_ASSERT_VALUES_EQUAL(sa, va.ToJson(true));
  361. UNIT_ASSERT_VALUES_EQUAL(ss, vs.ToJson(true));
  362. UNIT_ASSERT_VALUES_EQUAL(sn, vn.ToJson(true));
  363. {
  364. NSc::TValue v2 = MutableRef(vn);
  365. v2 = -1;
  366. UNIT_ASSERT_VALUES_EQUAL(sn, vn.ToJson(true));
  367. NSc::TValue v3 = Clone(vn);
  368. v3 = -1;
  369. UNIT_ASSERT_VALUES_EQUAL(v3.ToJson(true), v2.ToJson(true));
  370. }
  371. {
  372. NSc::TValue v2 = MutableRef(vs);
  373. v2 = "xxx";
  374. UNIT_ASSERT_VALUES_EQUAL(ss, vs.ToJson(true));
  375. NSc::TValue v3 = Clone(vs);
  376. v3 = "xxx";
  377. UNIT_ASSERT_VALUES_EQUAL(v3.ToJson(true), v2.ToJson(true));
  378. }
  379. {
  380. NSc::TValue v2 = MutableRef(vd);
  381. v2["a"] = "zzz";
  382. UNIT_ASSERT_VALUES_EQUAL(sd, vd.ToJson(true));
  383. NSc::TValue v3 = Clone(vd);
  384. v3["a"] = "zzz";
  385. UNIT_ASSERT_VALUES_EQUAL(v3.ToJson(true), v2.ToJson(true));
  386. }
  387. {
  388. NSc::TValue v2 = MutableRef(va);
  389. v2[0] = "zzz";
  390. UNIT_ASSERT_VALUES_EQUAL(sa, va.ToJson(true));
  391. NSc::TValue v3 = Clone(va);
  392. v3[0] = "zzz";
  393. UNIT_ASSERT_VALUES_EQUAL(v3.ToJson(true), v2.ToJson(true));
  394. }
  395. {
  396. NSc::TValue v2 = MutableRef(va);
  397. UNIT_ASSERT_VALUES_EQUAL(sa, va.ToJson(true));
  398. NSc::TValue v3 = Clone(va);
  399. UNIT_ASSERT_VALUES_EQUAL(v3.ToJson(true), v2.ToJson(true));
  400. }
  401. {
  402. NSc::TValue v2 = MutableRef(va);
  403. v2.ClearArray();
  404. UNIT_ASSERT_VALUES_EQUAL(sa, va.ToJson(true));
  405. NSc::TValue v3 = Clone(va);
  406. v3.ClearArray();
  407. UNIT_ASSERT_VALUES_EQUAL(v3.ToJson(true), v2.ToJson(true));
  408. }
  409. }
  410. Y_UNIT_TEST(TestOperators) {
  411. UNIT_ASSERT("test" == NSc::TValue("test"));
  412. UNIT_ASSERT(NSc::TValue("test") == "test");
  413. UNIT_ASSERT("test1" != NSc::TValue("test"));
  414. UNIT_ASSERT(NSc::TValue("test") != "test1");
  415. UNIT_ASSERT("test1" > NSc::TValue("test"));
  416. UNIT_ASSERT(NSc::TValue("test") < "test1");
  417. UNIT_ASSERT("test" < NSc::TValue("test1"));
  418. UNIT_ASSERT(NSc::TValue("test1") > "test");
  419. UNIT_ASSERT(1 == NSc::TValue(1));
  420. UNIT_ASSERT(NSc::TValue(1) == 1);
  421. UNIT_ASSERT(2 != NSc::TValue(1));
  422. UNIT_ASSERT(NSc::TValue(1) != 2);
  423. UNIT_ASSERT(1 < NSc::TValue(2));
  424. UNIT_ASSERT(NSc::TValue(2) > 1);
  425. UNIT_ASSERT(2 > NSc::TValue(1));
  426. UNIT_ASSERT(NSc::TValue(1) < 2);
  427. UNIT_ASSERT(TString("test") == NSc::TValue("test"));
  428. }
  429. Y_UNIT_TEST(TestDestructor) {
  430. NSc::TValue v;
  431. const NSc::TValue& v1 = v;
  432. v1.GetString();
  433. v1.GetArray();
  434. v1.GetNumber();
  435. v1.GetDict();
  436. v.GetString();
  437. v.GetArray();
  438. v.GetNumber();
  439. v.GetDict();
  440. }
  441. void DoTestSamePool(TStringBuf json, TStringBuf jpath) {
  442. NSc::TValue v = NSc::TValue::FromJson(json);
  443. UNIT_ASSERT_C(NSc::TValue::SamePool(v, v.TrySelect(jpath)), json);
  444. }
  445. Y_UNIT_TEST(TestSamePool) {
  446. DoTestSamePool("", "");
  447. DoTestSamePool("a", "");
  448. DoTestSamePool("[a]", "0");
  449. DoTestSamePool("{a:b}", "a");
  450. DoTestSamePool("{a:{b:c}}", "a/b");
  451. DoTestSamePool("{a:{b:[c, {}]}}", "a/b/1");
  452. DoTestSamePool("{a:{b:[c, {d:{e:[]}}]}}", "a/b/1/d/e");
  453. UNIT_ASSERT(!NSc::TValue::SamePool(NSc::TValue(), NSc::TValue()));
  454. UNIT_ASSERT(!NSc::TValue::SamePool(NSc::Null().Clone(), NSc::Null()));
  455. UNIT_ASSERT(!NSc::TValue::SamePool(NSc::TValue() = 0, NSc::TValue()));
  456. UNIT_ASSERT(!NSc::TValue::SamePool(NSc::TValue::FromJson("a"), NSc::TValue::FromJson("a")));
  457. NSc::TValue v, vv;
  458. v["x"] = vv;
  459. UNIT_ASSERT(!NSc::TValue::SamePool(v, vv));
  460. UNIT_ASSERT(!NSc::TValue::SamePool(v, v["x"]));
  461. v = vv;
  462. UNIT_ASSERT(NSc::TValue::SamePool(v, vv));
  463. }
  464. Y_UNIT_TEST(TestLoopDetection) {
  465. NSc::NImpl::GetTlsInstance<NSc::NImpl::TSelfLoopContext>().ReportingMode
  466. = NSc::NImpl::TSelfLoopContext::EMode::Stderr;
  467. NSc::TValue x;
  468. x["a"]["x"] = x;
  469. x["b"][0] = x;
  470. UNIT_ASSERT(x.IsSameOrAncestorOf(x));
  471. UNIT_ASSERT(x.IsSameOrAncestorOf(x.Get("a")));
  472. UNIT_ASSERT(x.Get("a").IsSameOrAncestorOf(x));
  473. UNIT_ASSERT_VALUES_EQUAL(x.ToJson(), "{\"a\":{\"x\":null},\"b\":[null]}");
  474. NSc::TValue y = x.Clone();
  475. UNIT_ASSERT(y.Has("a"));
  476. UNIT_ASSERT(y.Get("a").Has("x"));
  477. UNIT_ASSERT(y.Get("a").Get("x").IsNull());
  478. UNIT_ASSERT(y.Get("a").Get("x").IsNull());
  479. UNIT_ASSERT(y.Has("b"));
  480. UNIT_ASSERT(y.Get("b").Has(0));
  481. UNIT_ASSERT(y.Get("b").Get(0).IsNull());
  482. UNIT_ASSERT_VALUES_EQUAL(y.ToJson(), "{\"a\":{\"x\":null},\"b\":[null]}");
  483. NSc::TValue z;
  484. z.MergeUpdate(x);
  485. UNIT_ASSERT(z.Has("a"));
  486. UNIT_ASSERT(z.Get("a").Has("x"));
  487. UNIT_ASSERT(z.Get("a").Get("x").IsNull());
  488. UNIT_ASSERT(z.Has("b"));
  489. UNIT_ASSERT(z.Get("b").Has(0));
  490. UNIT_ASSERT(z.Get("b").Get(0).IsNull());
  491. UNIT_ASSERT_VALUES_EQUAL(z.ToJson(), "{\"a\":{\"x\":null},\"b\":[null]}");
  492. x["a"].Delete("x");
  493. x["b"].Delete(0);
  494. UNIT_ASSERT(x.IsSameOrAncestorOf(x));
  495. UNIT_ASSERT(x.IsSameOrAncestorOf(x.Get("a")));
  496. UNIT_ASSERT(!x.Get("a").IsSameOrAncestorOf(x));
  497. }
  498. Y_UNIT_TEST(TestLoopDetectionThrow) {
  499. NSc::NImpl::GetTlsInstance<NSc::NImpl::TSelfLoopContext>().ReportingMode
  500. = NSc::NImpl::TSelfLoopContext::EMode::Throw;
  501. {
  502. NSc::TValue x;
  503. x["a"]["x"] = x;
  504. UNIT_ASSERT(x.IsSameOrAncestorOf(x));
  505. UNIT_ASSERT(x.IsSameOrAncestorOf(x.Get("a")));
  506. UNIT_ASSERT(x.Get("a").IsSameOrAncestorOf(x));
  507. UNIT_ASSERT_EXCEPTION(x.ToJson(), NSc::TSchemeException);
  508. UNIT_ASSERT_EXCEPTION(x.Clone(), NSc::TSchemeException);
  509. NSc::TValue z;
  510. UNIT_ASSERT_EXCEPTION(z.MergeUpdate(x), NSc::TSchemeException);
  511. UNIT_ASSERT_VALUES_EQUAL(z.ToJson(), "{\"a\":{\"x\":null}}");
  512. x["a"].Delete("x");
  513. UNIT_ASSERT(x.IsSameOrAncestorOf(x));
  514. UNIT_ASSERT(x.IsSameOrAncestorOf(x.Get("a")));
  515. UNIT_ASSERT(!x.Get("a").IsSameOrAncestorOf(x));
  516. UNIT_ASSERT_VALUES_EQUAL(x.ToJson(), "{\"a\":{}}");
  517. }
  518. {
  519. NSc::TValue x;
  520. x["a"][0] = x;
  521. UNIT_ASSERT(x.IsSameOrAncestorOf(x));
  522. UNIT_ASSERT(x.IsSameOrAncestorOf(x.Get("a")));
  523. UNIT_ASSERT(x.Get("a").IsSameOrAncestorOf(x));
  524. UNIT_ASSERT_EXCEPTION(x.ToJson(), NSc::TSchemeException);
  525. UNIT_ASSERT_EXCEPTION(x.Clone(), NSc::TSchemeException);
  526. NSc::TValue z;
  527. UNIT_ASSERT_EXCEPTION(z.MergeUpdate(x), NSc::TSchemeException);
  528. UNIT_ASSERT_VALUES_EQUAL(z.ToJson(), "{\"a\":[null]}");
  529. x["a"].Delete(0);
  530. UNIT_ASSERT(x.IsSameOrAncestorOf(x));
  531. UNIT_ASSERT(x.IsSameOrAncestorOf(x.Get("a")));
  532. UNIT_ASSERT(!x.Get("a").IsSameOrAncestorOf(x));
  533. UNIT_ASSERT_VALUES_EQUAL(x.ToJson(), "{\"a\":[]}");
  534. }
  535. }
  536. Y_UNIT_TEST(TestIsSameOrAncestorOf) {
  537. NSc::TValue x;
  538. UNIT_ASSERT(x.IsSameOrAncestorOf(x));
  539. x["a"] = NSc::Null();
  540. UNIT_ASSERT(x.IsSameOrAncestorOf(x.Get("a")));
  541. NSc::TValue a = 1;
  542. NSc::TValue b = 2;
  543. NSc::TValue c = 3;
  544. NSc::TValue d = 4;
  545. x["a"] = a;
  546. x["b"] = b;
  547. x["c"] = a;
  548. UNIT_ASSERT(x.IsSameOrAncestorOf(a));
  549. UNIT_ASSERT(x.IsSameOrAncestorOf(b));
  550. UNIT_ASSERT(x.Get("a").IsSameOrAncestorOf(a));
  551. UNIT_ASSERT(x.Get("b").IsSameOrAncestorOf(b));
  552. UNIT_ASSERT(x.Get("c").IsSameOrAncestorOf(a));
  553. UNIT_ASSERT(!x.Get("a").IsSameOrAncestorOf(b));
  554. UNIT_ASSERT(!x.Get("b").IsSameOrAncestorOf(a));
  555. UNIT_ASSERT(!x.Get("a").Get(0).IsSameOrAncestorOf(a));
  556. b.Push() = c;
  557. b.Push() = d;
  558. b.Push() = c;
  559. UNIT_ASSERT(x.Get("b").IsSameOrAncestorOf(b));
  560. UNIT_ASSERT(x.IsSameOrAncestorOf(c));
  561. UNIT_ASSERT(x.IsSameOrAncestorOf(d));
  562. UNIT_ASSERT(x.Get("b").Get(0).IsSameOrAncestorOf(c));
  563. UNIT_ASSERT(x.Get("b").Get(1).IsSameOrAncestorOf(d));
  564. UNIT_ASSERT(x.Get("b").Get(2).IsSameOrAncestorOf(c));
  565. UNIT_ASSERT(b.Get(0).IsSameOrAncestorOf(b.Get(2)));
  566. UNIT_ASSERT(b.Get(2).IsSameOrAncestorOf(b.Get(0)));
  567. UNIT_ASSERT(b.Get(0).IsSameOrAncestorOf(c));
  568. UNIT_ASSERT(b.Get(1).IsSameOrAncestorOf(d));
  569. UNIT_ASSERT(!b.Get(0).IsSameOrAncestorOf(d));
  570. UNIT_ASSERT(!b.Get(1).IsSameOrAncestorOf(c));
  571. }
  572. static void ByVal(NSc::TValue v) {
  573. v["VAL"] = 1;
  574. }
  575. static void ByRef(NSc::TValue& v) {
  576. ByVal(v);
  577. }
  578. static void ByRefAndModify(NSc::TValue& v) {
  579. v["REF"] = 1;
  580. ByVal(v);
  581. }
  582. Y_UNIT_TEST(TestMove) {
  583. using namespace NSc;
  584. {
  585. TValue v = TValue::FromJson("{}");
  586. ByRef(v);
  587. UNIT_ASSERT_VALUES_EQUAL(v.ToJson(), "{\"VAL\":1}");
  588. }
  589. {
  590. TValue v = TValue::FromJson("{}");
  591. ByVal(v);
  592. UNIT_ASSERT_VALUES_EQUAL(v.ToJson(), "{\"VAL\":1}");
  593. }
  594. {
  595. TValue v;
  596. ByVal(v);
  597. UNIT_ASSERT_VALUES_EQUAL(v.ToJson(), "{\"VAL\":1}");
  598. }
  599. {
  600. TValue v = TValue::FromJson("{}");
  601. ByRefAndModify(v);
  602. UNIT_ASSERT_VALUES_EQUAL(v.ToJson(), "{\"REF\":1,\"VAL\":1}");
  603. }
  604. {
  605. TValue v = TValue::FromJson("{foo:bar}");
  606. TValue w(std::move(v));
  607. UNIT_ASSERT(v.IsNull());
  608. v = static_cast<TValue&>(v);
  609. UNIT_ASSERT(v.IsNull());
  610. UNIT_ASSERT_VALUES_EQUAL(w.Get("foo").GetString(), "bar");
  611. v = std::move(w);
  612. UNIT_ASSERT_VALUES_EQUAL(v.Get("foo").GetString(), "bar");
  613. UNIT_ASSERT(w.IsNull());
  614. UNIT_ASSERT(w.Get("foo").IsNull()); // no crash here
  615. w["foo"] = "baz"; // no crash here
  616. UNIT_ASSERT(w.IsDict());
  617. UNIT_ASSERT_VALUES_EQUAL(w.Get("foo").GetString(), "baz");
  618. }
  619. UNIT_ASSERT(NSc::TValue::DefaultValue().IsNull());
  620. }
  621. //SPI-25156
  622. Y_UNIT_TEST(TestMoveNotCorruptingDefault) {
  623. using namespace NSc;
  624. TValue w = TValue::FromJson("{foo:bar}");
  625. TValue v = std::move(w);
  626. w["foo"] = "baz"; // no crash here
  627. UNIT_ASSERT(NSc::TValue::DefaultValue().IsNull());
  628. }
  629. Y_UNIT_TEST(TestCopyFrom) {
  630. {
  631. TString sa = "[1,2]";
  632. const NSc::TValue& va = NSc::TValue::FromJson(sa);
  633. NSc::TValue vb = va;
  634. vb.CopyFrom(va);
  635. UNIT_ASSERT_VALUES_EQUAL(va.ToJson(), sa);
  636. UNIT_ASSERT_VALUES_EQUAL(vb.ToJson(), sa);
  637. }
  638. {
  639. TString sa = "[1,2]";
  640. NSc::TValue va = NSc::TValue::FromJson(sa);
  641. NSc::TValue vb = va;
  642. vb.CopyFrom(va);
  643. UNIT_ASSERT_VALUES_EQUAL(va.ToJson(), sa);
  644. UNIT_ASSERT_VALUES_EQUAL(vb.ToJson(), sa);
  645. }
  646. {
  647. TString sa = "[1,2]";
  648. NSc::TValue va = NSc::TValue::FromJson(sa);
  649. const NSc::TValue& vb = va;
  650. va.CopyFrom(vb);
  651. UNIT_ASSERT_VALUES_EQUAL(va.ToJson(), sa);
  652. UNIT_ASSERT_VALUES_EQUAL(vb.ToJson(), sa);
  653. }
  654. {
  655. TString sa = "[1,2]";
  656. NSc::TValue va = NSc::TValue::FromJson(sa);
  657. NSc::TValue vb = va;
  658. va.CopyFrom(vb);
  659. UNIT_ASSERT_VALUES_EQUAL(va.ToJson(), sa);
  660. UNIT_ASSERT_VALUES_EQUAL(vb.ToJson(), sa);
  661. }
  662. {
  663. NSc::TValue va = NSc::TValue::FromJson("{\"x\":\"ab\",\"y\":{\"p\":\"cd\",\"q\":\"ef\"}}");
  664. NSc::TValue vb = va.Get("y");
  665. va.CopyFrom(vb);
  666. TString sa = "{\"p\":\"cd\",\"q\":\"ef\"}";
  667. UNIT_ASSERT_VALUES_EQUAL(va.ToJson(), sa);
  668. UNIT_ASSERT_VALUES_EQUAL(vb.ToJson(), sa);
  669. }
  670. {
  671. NSc::TValue va = NSc::TValue::FromJson("{\"x\":\"ab\",\"y\":{\"p\":\"cd\",\"q\":\"ef\"}}");
  672. const NSc::TValue& vb = va.Get("y");
  673. va.CopyFrom(vb);
  674. TString sa = "{\"p\":\"cd\",\"q\":\"ef\"}";
  675. UNIT_ASSERT_VALUES_EQUAL(va.ToJson(), sa);
  676. }
  677. {
  678. NSc::TValue va = NSc::TValue::FromJson("{\"x\":\"ab\",\"y\":{\"p\":\"cd\",\"q\":\"ef\"}}");
  679. NSc::TValue vb = va.Get("y");
  680. va = vb;
  681. TString sa = "{\"p\":\"cd\",\"q\":\"ef\"}";
  682. UNIT_ASSERT_VALUES_EQUAL(va.ToJson(), sa);
  683. UNIT_ASSERT_VALUES_EQUAL(vb.ToJson(), sa);
  684. }
  685. {
  686. NSc::TValue va = NSc::TValue::FromJson("{\"x\":\"ab\",\"y\":{\"p\":\"cd\",\"q\":\"ef\"}}");
  687. const NSc::TValue& vb = va.Get("y");
  688. va = vb;
  689. TString sa = "{\"p\":\"cd\",\"q\":\"ef\"}";
  690. UNIT_ASSERT_VALUES_EQUAL(va.ToJson(), sa);
  691. UNIT_ASSERT_VALUES_EQUAL(vb.ToJson(), sa);
  692. }
  693. }
  694. Y_UNIT_TEST(TestCopyingDictIntoSelf) { //Found by fuzzing
  695. NSc::TValue a;
  696. NSc::TValue b = a.GetOrAdd("aa");
  697. b.CopyFrom(a);
  698. NSc::TValue target = NSc::TValue::FromJsonThrow("{\"aa\":null}");
  699. UNIT_ASSERT_VALUES_EQUAL(b, target);
  700. UNIT_ASSERT_VALUES_EQUAL(a, target);
  701. }
  702. Y_UNIT_TEST(TestCopyingDictIntoSelfByRef) { //Found by fuzzing
  703. NSc::TValue a;
  704. NSc::TValue& b = a.GetOrAdd("aa");
  705. b.CopyFrom(a);
  706. UNIT_ASSERT_VALUES_EQUAL(b, NSc::TValue::FromJsonThrow("{\"aa\":null}"));
  707. UNIT_ASSERT_VALUES_EQUAL(a, NSc::TValue::FromJsonThrow("{\"aa\": {\"aa\": null}}"));
  708. }
  709. Y_UNIT_TEST(TestGetNoAdd) {
  710. NSc::TValue v = NSc::NUt::AssertFromJson("{a:[null,-1,2,3.4],b:3,c:{d:5}}");
  711. UNIT_ASSERT(v.GetNoAdd("a") != nullptr);
  712. UNIT_ASSERT(v.GetNoAdd("b") != nullptr);
  713. UNIT_ASSERT(v.GetNoAdd("c") != nullptr);
  714. UNIT_ASSERT(v.GetNoAdd("d") == nullptr);
  715. UNIT_ASSERT(v.GetNoAdd("value") == nullptr);
  716. NSc::TValue* child = v.GetNoAdd("c");
  717. UNIT_ASSERT(child != nullptr);
  718. (*child)["e"]["f"] = 42;
  719. const NSc::TValue expectedResult = NSc::NUt::AssertFromJson("{a:[null,-1,2,3.4],b:3,c:{d:5,e:{f:42}}}");
  720. UNIT_ASSERT_VALUES_EQUAL(v, expectedResult);
  721. }
  722. Y_UNIT_TEST(TestNewNodeOnCurrentPool) {
  723. NSc::TValue parent;
  724. parent["foo"] = "bar";
  725. // standalone
  726. NSc::TValue firstChild(10);
  727. UNIT_ASSERT(!NSc::TValue::SamePool(parent, firstChild));
  728. // shares a memory pool
  729. NSc::TValue secondChild = parent.CreateNew();
  730. UNIT_ASSERT(secondChild.IsNull());
  731. UNIT_ASSERT(NSc::TValue::SamePool(parent, secondChild));
  732. secondChild = 20;
  733. UNIT_ASSERT(secondChild.IsIntNumber());
  734. UNIT_ASSERT(NSc::TValue::SamePool(parent, secondChild));
  735. // attach children to parent
  736. parent["first"] = std::move(firstChild);
  737. parent["second"] = std::move(secondChild);
  738. UNIT_ASSERT_VALUES_EQUAL(parent["first"].GetIntNumber(), 10);
  739. UNIT_ASSERT_VALUES_EQUAL(parent["second"].GetIntNumber(), 20);
  740. UNIT_ASSERT(!NSc::TValue::SamePool(parent, parent["first"]));
  741. UNIT_ASSERT(NSc::TValue::SamePool(parent, parent["second"]));
  742. }
  743. Y_UNIT_TEST(TestNewNodeAfterMove) {
  744. NSc::TValue a;
  745. NSc::TValue b = std::move(a); // after this, `a` has no memory pool
  746. NSc::TValue a2 = a.CreateNew(); // no crash here
  747. NSc::TValue b2 = b.CreateNew();
  748. UNIT_ASSERT(!NSc::TValue::SamePool(a, b));
  749. UNIT_ASSERT(NSc::TValue::SamePool(b, b2));
  750. UNIT_ASSERT(!NSc::TValue::SamePool(a2, b2));
  751. }
  752. namespace {
  753. bool FillChild(int x, NSc::TValue& result) {
  754. if (x % 2 == 0) {
  755. result["value"] = x;
  756. return true;
  757. }
  758. return false;
  759. }
  760. }
  761. Y_UNIT_TEST(TestHierarchyCreationPatterns) {
  762. const int n = 1000;
  763. // Good: the code looks so clear and intuitive.
  764. // Bad: it creates one thousand of independent memory pools, half of them remain alive at the end.
  765. NSc::TValue list1;
  766. for (int i = 0; i < n; ++i) {
  767. NSc::TValue child;
  768. if (FillChild(i, child)) {
  769. list1.Push(std::move(child));
  770. }
  771. }
  772. // Good: a single memory pool is reused.
  773. // Bad: we have to add and remove a child manually.
  774. // Bad: some memory on pool remains unused (gaps are left after removing nodes).
  775. NSc::TValue list2;
  776. for (int i = 0; i < n; ++i) {
  777. auto& child = list2.Push();
  778. if (!FillChild(i, child)) {
  779. list2.Pop();
  780. }
  781. }
  782. // Good: a single memory pool is reused.
  783. // Good: the code looks quite intuitive.
  784. // Good: there could be multiple parents on the same pool.
  785. // Bad: some memory on pool remains unused.
  786. // Bad: you have to know about the special method `CreateNew()`.
  787. NSc::TValue list3;
  788. for (int i = 0; i < n; ++i) {
  789. auto child = list3.CreateNew();
  790. if (FillChild(i, child)) {
  791. list3.Push(std::move(child));
  792. }
  793. }
  794. // Results are the same
  795. UNIT_ASSERT_VALUES_EQUAL(list1.ToJson(), list2.ToJson());
  796. UNIT_ASSERT_VALUES_EQUAL(list2.ToJson(), list3.ToJson());
  797. }
  798. }