PageRenderTime 37ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/indra/test/llsdutil_tut.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 389 lines | 289 code | 39 blank | 61 comment | 20 complexity | 78398669443f6f025b9dc48c34adfac6 MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file llsdutil_tut.cpp
  3. * @author Adroit
  4. * @date 2007-02
  5. * @brief LLSD conversion routines test cases.
  6. *
  7. * $LicenseInfo:firstyear=2007&license=viewerlgpl$
  8. * Second Life Viewer Source Code
  9. * Copyright (C) 2010, Linden Research, Inc.
  10. *
  11. * This library is free software; you can redistribute it and/or
  12. * modify it under the terms of the GNU Lesser General Public
  13. * License as published by the Free Software Foundation;
  14. * version 2.1 of the License only.
  15. *
  16. * This library is distributed in the hope that it will be useful,
  17. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  19. * Lesser General Public License for more details.
  20. *
  21. * You should have received a copy of the GNU Lesser General Public
  22. * License along with this library; if not, write to the Free Software
  23. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  24. *
  25. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  26. * $/LicenseInfo$
  27. */
  28. #include "linden_common.h"
  29. #include "lltut.h"
  30. #include "m4math.h"
  31. #include "v2math.h"
  32. #include "v2math.h"
  33. #include "v3color.h"
  34. #include "v3math.h"
  35. #include "v3dmath.h"
  36. #include "v4coloru.h"
  37. #include "v4math.h"
  38. #include "llquaternion.h"
  39. #include "llsdutil.h"
  40. #include "llsdutil_math.h"
  41. #include "stringize.h"
  42. #include <set>
  43. #include <boost/range.hpp>
  44. namespace tut
  45. {
  46. struct llsdutil_data
  47. {
  48. void test_matches(const std::string& proto_key, const LLSD& possibles,
  49. const char** begin, const char** end)
  50. {
  51. std::set<std::string> succeed(begin, end);
  52. LLSD prototype(possibles[proto_key]);
  53. for (LLSD::map_const_iterator pi(possibles.beginMap()), pend(possibles.endMap());
  54. pi != pend; ++pi)
  55. {
  56. std::string match(llsd_matches(prototype, pi->second));
  57. std::set<std::string>::const_iterator found = succeed.find(pi->first);
  58. if (found != succeed.end())
  59. {
  60. // This test is supposed to succeed. Comparing to the
  61. // empty string ensures that if the test fails, it will
  62. // display the string received so we can tell what failed.
  63. ensure_equals("match", match, "");
  64. }
  65. else
  66. {
  67. // This test is supposed to fail. If we get a false match,
  68. // the string 'match' will be empty, which doesn't tell us
  69. // much about which case went awry. So construct a more
  70. // detailed description string.
  71. ensure(proto_key + " shouldn't match " + pi->first, ! match.empty());
  72. }
  73. }
  74. }
  75. };
  76. typedef test_group<llsdutil_data> llsdutil_test;;
  77. typedef llsdutil_test::object llsdutil_object;
  78. tut::llsdutil_test tutil("llsdutil");
  79. template<> template<>
  80. void llsdutil_object::test<1>()
  81. {
  82. LLSD sd;
  83. U64 valueIn , valueOut;
  84. valueIn = U64L(0xFEDCBA9876543210);
  85. sd = ll_sd_from_U64(valueIn);
  86. valueOut = ll_U64_from_sd(sd);
  87. ensure_equals("U64 valueIn->sd->valueOut", valueIn, valueOut);
  88. }
  89. template<> template<>
  90. void llsdutil_object::test<2>()
  91. {
  92. LLSD sd;
  93. U32 valueIn, valueOut;
  94. valueIn = 0x87654321;
  95. sd = ll_sd_from_U32(valueIn);
  96. valueOut = ll_U32_from_sd(sd);
  97. ensure_equals("U32 valueIn->sd->valueOut", valueIn, valueOut);
  98. }
  99. template<> template<>
  100. void llsdutil_object::test<3>()
  101. {
  102. U32 valueIn, valueOut;
  103. valueIn = 0x87654321;
  104. LLSD sd;
  105. sd = ll_sd_from_ipaddr(valueIn);
  106. valueOut = ll_ipaddr_from_sd(sd);
  107. ensure_equals("valueIn->sd->valueOut", valueIn, valueOut);
  108. }
  109. template<> template<>
  110. void llsdutil_object::test<4>()
  111. {
  112. LLSD sd;
  113. LLVector3 vec1(-1.0, 2.0, -3.0);
  114. sd = ll_sd_from_vector3(vec1);
  115. LLVector3 vec2 = ll_vector3_from_sd(sd);
  116. ensure_equals("vector3 -> sd -> vector3: 1", vec1, vec2);
  117. LLVector3 vec3(sd);
  118. ensure_equals("vector3 -> sd -> vector3: 2", vec1, vec3);
  119. sd.clear();
  120. vec1.setVec(0., 0., 0.);
  121. sd = ll_sd_from_vector3(vec1);
  122. vec2 = ll_vector3_from_sd(sd);
  123. ensure_equals("vector3 -> sd -> vector3: 3", vec1, vec2);
  124. sd.clear();
  125. }
  126. template<> template<>
  127. void llsdutil_object::test<5>()
  128. {
  129. LLSD sd;
  130. LLVector3d vec1((F64)(U64L(0xFEDCBA9876543210) << 2), -1., 0);
  131. sd = ll_sd_from_vector3d(vec1);
  132. LLVector3d vec2 = ll_vector3d_from_sd(sd);
  133. ensure_equals("vector3d -> sd -> vector3d: 1", vec1, vec2);
  134. LLVector3d vec3(sd);
  135. ensure_equals("vector3d -> sd -> vector3d : 2", vec1, vec3);
  136. }
  137. template<> template<>
  138. void llsdutil_object::test<6>()
  139. {
  140. LLSD sd;
  141. LLVector2 vec((F32) -3., (F32) 4.2);
  142. sd = ll_sd_from_vector2(vec);
  143. LLVector2 vec1 = ll_vector2_from_sd(sd);
  144. ensure_equals("vector2 -> sd -> vector2", vec, vec1);
  145. LLSD sd2 = ll_sd_from_vector2(vec1);
  146. ensure_equals("sd -> vector2 -> sd: 2", sd, sd2);
  147. }
  148. template<> template<>
  149. void llsdutil_object::test<7>()
  150. {
  151. LLSD sd;
  152. LLQuaternion quat((F32) 1., (F32) -0.98, (F32) 2.3, (F32) 0xffff);
  153. sd = ll_sd_from_quaternion(quat);
  154. LLQuaternion quat1 = ll_quaternion_from_sd(sd);
  155. ensure_equals("LLQuaternion -> sd -> LLQuaternion", quat, quat1);
  156. LLSD sd2 = ll_sd_from_quaternion(quat1);
  157. ensure_equals("sd -> LLQuaternion -> sd ", sd, sd2);
  158. }
  159. template<> template<>
  160. void llsdutil_object::test<8>()
  161. {
  162. LLSD sd;
  163. LLColor4 c(1.0f, 2.2f, 4.0f, 7.f);
  164. sd = ll_sd_from_color4(c);
  165. LLColor4 c1 =ll_color4_from_sd(sd);
  166. ensure_equals("LLColor4 -> sd -> LLColor4", c, c1);
  167. LLSD sd1 = ll_sd_from_color4(c1);
  168. ensure_equals("sd -> LLColor4 -> sd", sd, sd1);
  169. }
  170. template<> template<>
  171. void llsdutil_object::test<9>()
  172. {
  173. set_test_name("llsd_matches");
  174. // for this test, construct a map of all possible LLSD types
  175. LLSD map;
  176. map.insert("empty", LLSD());
  177. map.insert("Boolean", LLSD::Boolean());
  178. map.insert("Integer", LLSD::Integer(0));
  179. map.insert("Real", LLSD::Real(0.0));
  180. map.insert("String", LLSD::String("bah"));
  181. map.insert("NumString", LLSD::String("1"));
  182. map.insert("UUID", LLSD::UUID());
  183. map.insert("Date", LLSD::Date());
  184. map.insert("URI", LLSD::URI());
  185. map.insert("Binary", LLSD::Binary());
  186. map.insert("Map", LLSD().with("foo", LLSD()));
  187. // Only an empty array can be constructed on the fly
  188. LLSD array;
  189. array.append(LLSD());
  190. map.insert("Array", array);
  191. // These iterators are declared outside our various for loops to avoid
  192. // fatal MSVC warning: "I used to be broken, but I'm all better now!"
  193. LLSD::map_const_iterator mi, mend(map.endMap());
  194. /*-------------------------- llsd_matches --------------------------*/
  195. // empty prototype matches anything
  196. for (mi = map.beginMap(); mi != mend; ++mi)
  197. {
  198. ensure_equals(std::string("empty matches ") + mi->first, llsd_matches(LLSD(), mi->second), "");
  199. }
  200. LLSD proto_array, data_array;
  201. for (int i = 0; i < 3; ++i)
  202. {
  203. proto_array.append(LLSD());
  204. data_array.append(LLSD());
  205. }
  206. // prototype array matches only array
  207. for (mi = map.beginMap(); mi != mend; ++mi)
  208. {
  209. ensure(std::string("array doesn't match ") + mi->first,
  210. ! llsd_matches(proto_array, mi->second).empty());
  211. }
  212. // data array must be at least as long as prototype array
  213. proto_array.append(LLSD());
  214. ensure_equals("data array too short", llsd_matches(proto_array, data_array),
  215. "Array size 4 required instead of Array size 3");
  216. data_array.append(LLSD());
  217. ensure_equals("data array just right", llsd_matches(proto_array, data_array), "");
  218. data_array.append(LLSD());
  219. ensure_equals("data array longer", llsd_matches(proto_array, data_array), "");
  220. // array element matching
  221. data_array[0] = LLSD::String();
  222. ensure_equals("undefined prototype array entry", llsd_matches(proto_array, data_array), "");
  223. proto_array[0] = LLSD::Binary();
  224. ensure_equals("scalar prototype array entry", llsd_matches(proto_array, data_array),
  225. "[0]: Binary required instead of String");
  226. data_array[0] = LLSD::Binary();
  227. ensure_equals("matching prototype array entry", llsd_matches(proto_array, data_array), "");
  228. // build a coupla maps
  229. LLSD proto_map, data_map;
  230. data_map["got"] = LLSD();
  231. data_map["found"] = LLSD();
  232. for (LLSD::map_const_iterator dmi(data_map.beginMap()), dmend(data_map.endMap());
  233. dmi != dmend; ++dmi)
  234. {
  235. proto_map[dmi->first] = dmi->second;
  236. }
  237. proto_map["foo"] = LLSD();
  238. proto_map["bar"] = LLSD();
  239. // prototype map matches only map
  240. for (mi = map.beginMap(); mi != mend; ++mi)
  241. {
  242. ensure(std::string("map doesn't match ") + mi->first,
  243. ! llsd_matches(proto_map, mi->second).empty());
  244. }
  245. // data map must contain all keys in prototype map
  246. std::string error(llsd_matches(proto_map, data_map));
  247. ensure_contains("missing keys", error, "missing keys");
  248. ensure_contains("missing foo", error, "foo");
  249. ensure_contains("missing bar", error, "bar");
  250. ensure_does_not_contain("found found", error, "found");
  251. ensure_does_not_contain("got got", error, "got");
  252. data_map["bar"] = LLSD();
  253. error = llsd_matches(proto_map, data_map);
  254. ensure_contains("missing foo", error, "foo");
  255. ensure_does_not_contain("got bar", error, "bar");
  256. data_map["foo"] = LLSD();
  257. ensure_equals("data map just right", llsd_matches(proto_map, data_map), "");
  258. data_map["extra"] = LLSD();
  259. ensure_equals("data map with extra", llsd_matches(proto_map, data_map), "");
  260. // map element matching
  261. data_map["foo"] = LLSD::String();
  262. ensure_equals("undefined prototype map entry", llsd_matches(proto_map, data_map), "");
  263. proto_map["foo"] = LLSD::Binary();
  264. ensure_equals("scalar prototype map entry", llsd_matches(proto_map, data_map),
  265. "['foo']: Binary required instead of String");
  266. data_map["foo"] = LLSD::Binary();
  267. ensure_equals("matching prototype map entry", llsd_matches(proto_map, data_map), "");
  268. // String
  269. {
  270. static const char* matches[] = { "String", "NumString", "Boolean", "Integer",
  271. "Real", "UUID", "Date", "URI" };
  272. test_matches("String", map, boost::begin(matches), boost::end(matches));
  273. }
  274. // Boolean, Integer, Real
  275. static const char* numerics[] = { "Boolean", "Integer", "Real" };
  276. for (const char **ni = boost::begin(numerics), **nend = boost::end(numerics);
  277. ni != nend; ++ni)
  278. {
  279. static const char* matches[] = { "Boolean", "Integer", "Real", "String", "NumString" };
  280. test_matches(*ni, map, boost::begin(matches), boost::end(matches));
  281. }
  282. // UUID
  283. {
  284. static const char* matches[] = { "UUID", "String", "NumString" };
  285. test_matches("UUID", map, boost::begin(matches), boost::end(matches));
  286. }
  287. // Date
  288. {
  289. static const char* matches[] = { "Date", "String", "NumString" };
  290. test_matches("Date", map, boost::begin(matches), boost::end(matches));
  291. }
  292. // URI
  293. {
  294. static const char* matches[] = { "URI", "String", "NumString" };
  295. test_matches("URI", map, boost::begin(matches), boost::end(matches));
  296. }
  297. // Binary
  298. {
  299. static const char* matches[] = { "Binary" };
  300. test_matches("Binary", map, boost::begin(matches), boost::end(matches));
  301. }
  302. /*-------------------------- llsd_equals ---------------------------*/
  303. // Cross-product of each LLSD type with every other
  304. for (LLSD::map_const_iterator lmi(map.beginMap()), lmend(map.endMap());
  305. lmi != lmend; ++lmi)
  306. {
  307. for (LLSD::map_const_iterator rmi(map.beginMap()), rmend(map.endMap());
  308. rmi != rmend; ++rmi)
  309. {
  310. // Name this test based on the map keys naming the types of
  311. // interest, e.g "String::Integer".
  312. // We expect the values (xmi->second) to be equal if and only
  313. // if the type names (xmi->first) are equal.
  314. ensure(STRINGIZE(lmi->first << "::" << rmi->first),
  315. bool(lmi->first == rmi->first) ==
  316. bool(llsd_equals(lmi->second, rmi->second)));
  317. }
  318. }
  319. // Array cases
  320. LLSD rarray;
  321. rarray.append(1.0);
  322. rarray.append(2);
  323. rarray.append("3");
  324. LLSD larray(rarray);
  325. ensure("llsd_equals(equal arrays)", llsd_equals(larray, rarray));
  326. rarray[2] = "4";
  327. ensure("llsd_equals(different [2])", ! llsd_equals(larray, rarray));
  328. rarray = larray;
  329. rarray.append(LLSD::Date());
  330. ensure("llsd_equals(longer right array)", ! llsd_equals(larray, rarray));
  331. rarray = larray;
  332. rarray.erase(2);
  333. ensure("llsd_equals(shorter right array)", ! llsd_equals(larray, rarray));
  334. // Map cases
  335. LLSD rmap;
  336. rmap["San Francisco"] = 65;
  337. rmap["Phoenix"] = 92;
  338. rmap["Boston"] = 77;
  339. LLSD lmap(rmap);
  340. ensure("llsd_equals(equal maps)", llsd_equals(lmap, rmap));
  341. rmap["Boston"] = 80;
  342. ensure("llsd_equals(different [\"Boston\"])", ! llsd_equals(lmap, rmap));
  343. rmap = lmap;
  344. rmap["Atlanta"] = 95;
  345. ensure("llsd_equals(superset right map)", ! llsd_equals(lmap, rmap));
  346. rmap = lmap;
  347. lmap["Seattle"] = 72;
  348. ensure("llsd_equals(superset left map)", ! llsd_equals(lmap, rmap));
  349. }
  350. }