/indra/newview/tests/llviewerassetstats_test.cpp

https://bitbucket.org/lindenlab/viewer-beta/ · C++ · 984 lines · 717 code · 195 blank · 72 comment · 69 complexity · 1492ce71f40e5d6fe50b38e4776f3cdd MD5 · raw file

  1. /**
  2. * @file llviewerassetstats_tut.cpp
  3. * @date 2010-10-28
  4. * @brief Test cases for some of newview/llviewerassetstats.cpp
  5. *
  6. * $LicenseInfo:firstyear=2010&license=viewerlgpl$
  7. * Second Life Viewer Source Code
  8. * Copyright (C) 2010, Linden Research, Inc.
  9. *
  10. * This library is free software; you can redistribute it and/or
  11. * modify it under the terms of the GNU Lesser General Public
  12. * License as published by the Free Software Foundation;
  13. * version 2.1 of the License only.
  14. *
  15. * This library is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  18. * Lesser General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU Lesser General Public
  21. * License along with this library; if not, write to the Free Software
  22. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  23. *
  24. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  25. * $/LicenseInfo$
  26. */
  27. #include "linden_common.h"
  28. #include <tut/tut.hpp>
  29. #include <iostream>
  30. #include "lltut.h"
  31. #include "../llviewerassetstats.h"
  32. #include "lluuid.h"
  33. #include "llsdutil.h"
  34. #include "llregionhandle.h"
  35. static const char * all_keys[] =
  36. {
  37. "duration",
  38. "fps",
  39. "get_other",
  40. "get_texture_temp_http",
  41. "get_texture_temp_udp",
  42. "get_texture_non_temp_http",
  43. "get_texture_non_temp_udp",
  44. "get_wearable_udp",
  45. "get_sound_udp",
  46. "get_gesture_udp"
  47. };
  48. static const char * resp_keys[] =
  49. {
  50. "get_other",
  51. "get_texture_temp_http",
  52. "get_texture_temp_udp",
  53. "get_texture_non_temp_http",
  54. "get_texture_non_temp_udp",
  55. "get_wearable_udp",
  56. "get_sound_udp",
  57. "get_gesture_udp"
  58. };
  59. static const char * sub_keys[] =
  60. {
  61. "dequeued",
  62. "enqueued",
  63. "resp_count",
  64. "resp_max",
  65. "resp_min",
  66. "resp_mean"
  67. };
  68. static const char * mmm_resp_keys[] =
  69. {
  70. "fps"
  71. };
  72. static const char * mmm_sub_keys[] =
  73. {
  74. "count",
  75. "max",
  76. "min",
  77. "mean"
  78. };
  79. static const LLUUID region1("4e2d81a3-6263-6ffe-ad5c-8ce04bee07e8");
  80. static const LLUUID region2("68762cc8-b68b-4e45-854b-e830734f2d4a");
  81. static const U64 region1_handle(0x0000040000003f00ULL);
  82. static const U64 region2_handle(0x0000030000004200ULL);
  83. static const std::string region1_handle_str("0000040000003f00");
  84. static const std::string region2_handle_str("0000030000004200");
  85. #if 0
  86. static bool
  87. is_empty_map(const LLSD & sd)
  88. {
  89. return sd.isMap() && 0 == sd.size();
  90. }
  91. static bool
  92. is_single_key_map(const LLSD & sd, const std::string & key)
  93. {
  94. return sd.isMap() && 1 == sd.size() && sd.has(key);
  95. }
  96. #endif
  97. static bool
  98. is_double_key_map(const LLSD & sd, const std::string & key1, const std::string & key2)
  99. {
  100. return sd.isMap() && 2 == sd.size() && sd.has(key1) && sd.has(key2);
  101. }
  102. static bool
  103. is_no_stats_map(const LLSD & sd)
  104. {
  105. return is_double_key_map(sd, "duration", "regions");
  106. }
  107. static bool
  108. is_single_slot_array(const LLSD & sd, U64 region_handle)
  109. {
  110. U32 grid_x(0), grid_y(0);
  111. grid_from_region_handle(region_handle, &grid_x, &grid_y);
  112. return (sd.isArray() &&
  113. 1 == sd.size() &&
  114. sd[0].has("grid_x") &&
  115. sd[0].has("grid_y") &&
  116. sd[0]["grid_x"].isInteger() &&
  117. sd[0]["grid_y"].isInteger() &&
  118. grid_x == sd[0]["grid_x"].asInteger() &&
  119. grid_y == sd[0]["grid_y"].asInteger());
  120. }
  121. static bool
  122. is_double_slot_array(const LLSD & sd, U64 region_handle1, U64 region_handle2)
  123. {
  124. U32 grid_x1(0), grid_y1(0);
  125. U32 grid_x2(0), grid_y2(0);
  126. grid_from_region_handle(region_handle1, &grid_x1, &grid_y1);
  127. grid_from_region_handle(region_handle2, &grid_x2, &grid_y2);
  128. return (sd.isArray() &&
  129. 2 == sd.size() &&
  130. sd[0].has("grid_x") &&
  131. sd[0].has("grid_y") &&
  132. sd[0]["grid_x"].isInteger() &&
  133. sd[0]["grid_y"].isInteger() &&
  134. sd[1].has("grid_x") &&
  135. sd[1].has("grid_y") &&
  136. sd[1]["grid_x"].isInteger() &&
  137. sd[1]["grid_y"].isInteger() &&
  138. ((grid_x1 == sd[0]["grid_x"].asInteger() &&
  139. grid_y1 == sd[0]["grid_y"].asInteger() &&
  140. grid_x2 == sd[1]["grid_x"].asInteger() &&
  141. grid_y2 == sd[1]["grid_y"].asInteger()) ||
  142. (grid_x1 == sd[1]["grid_x"].asInteger() &&
  143. grid_y1 == sd[1]["grid_y"].asInteger() &&
  144. grid_x2 == sd[0]["grid_x"].asInteger() &&
  145. grid_y2 == sd[0]["grid_y"].asInteger())));
  146. }
  147. static LLSD
  148. get_region(const LLSD & sd, U64 region_handle1)
  149. {
  150. U32 grid_x(0), grid_y(0);
  151. grid_from_region_handle(region_handle1, &grid_x, &grid_y);
  152. for (LLSD::array_const_iterator it(sd["regions"].beginArray());
  153. sd["regions"].endArray() != it;
  154. ++it)
  155. {
  156. if ((*it).has("grid_x") &&
  157. (*it).has("grid_y") &&
  158. (*it)["grid_x"].isInteger() &&
  159. (*it)["grid_y"].isInteger() &&
  160. (*it)["grid_x"].asInteger() == grid_x &&
  161. (*it)["grid_y"].asInteger() == grid_y)
  162. {
  163. return *it;
  164. }
  165. }
  166. return LLSD();
  167. }
  168. namespace tut
  169. {
  170. struct tst_viewerassetstats_index
  171. {};
  172. typedef test_group<tst_viewerassetstats_index> tst_viewerassetstats_index_t;
  173. typedef tst_viewerassetstats_index_t::object tst_viewerassetstats_index_object_t;
  174. tut::tst_viewerassetstats_index_t tut_tst_viewerassetstats_index("tst_viewerassetstats_test");
  175. // Testing free functions without global stats allocated
  176. template<> template<>
  177. void tst_viewerassetstats_index_object_t::test<1>()
  178. {
  179. // Check that helpers aren't bothered by missing global stats
  180. ensure("Global gViewerAssetStatsMain should be NULL", (NULL == gViewerAssetStatsMain));
  181. LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_TEXTURE, false, false);
  182. LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_TEXTURE, false, false);
  183. LLViewerAssetStatsFF::record_response_main(LLViewerAssetType::AT_GESTURE, false, false, 12300000ULL);
  184. }
  185. // Create a non-global instance and check the structure
  186. template<> template<>
  187. void tst_viewerassetstats_index_object_t::test<2>()
  188. {
  189. ensure("Global gViewerAssetStatsMain should be NULL", (NULL == gViewerAssetStatsMain));
  190. LLViewerAssetStats * it = new LLViewerAssetStats();
  191. ensure("Global gViewerAssetStatsMain should still be NULL", (NULL == gViewerAssetStatsMain));
  192. LLSD sd_full = it->asLLSD(false);
  193. // Default (NULL) region ID doesn't produce LLSD results so should
  194. // get an empty map back from output
  195. ensure("Stat-less LLSD initially", is_no_stats_map(sd_full));
  196. // Once the region is set, we will get a response even with no data collection
  197. it->setRegion(region1_handle);
  198. sd_full = it->asLLSD(false);
  199. ensure("Correct single-key LLSD map root", is_double_key_map(sd_full, "duration", "regions"));
  200. ensure("Correct single-slot LLSD array regions", is_single_slot_array(sd_full["regions"], region1_handle));
  201. LLSD sd = sd_full["regions"][0];
  202. delete it;
  203. // Check the structure of the LLSD
  204. for (int i = 0; i < LL_ARRAY_SIZE(all_keys); ++i)
  205. {
  206. std::string line = llformat("Has '%s' key", all_keys[i]);
  207. ensure(line, sd.has(all_keys[i]));
  208. }
  209. for (int i = 0; i < LL_ARRAY_SIZE(resp_keys); ++i)
  210. {
  211. for (int j = 0; j < LL_ARRAY_SIZE(sub_keys); ++j)
  212. {
  213. std::string line = llformat("Key '%s' has '%s' key", resp_keys[i], sub_keys[j]);
  214. ensure(line, sd[resp_keys[i]].has(sub_keys[j]));
  215. }
  216. }
  217. for (int i = 0; i < LL_ARRAY_SIZE(mmm_resp_keys); ++i)
  218. {
  219. for (int j = 0; j < LL_ARRAY_SIZE(mmm_sub_keys); ++j)
  220. {
  221. std::string line = llformat("Key '%s' has '%s' key", mmm_resp_keys[i], mmm_sub_keys[j]);
  222. ensure(line, sd[mmm_resp_keys[i]].has(mmm_sub_keys[j]));
  223. }
  224. }
  225. }
  226. // Create a non-global instance and check some content
  227. template<> template<>
  228. void tst_viewerassetstats_index_object_t::test<3>()
  229. {
  230. LLViewerAssetStats * it = new LLViewerAssetStats();
  231. it->setRegion(region1_handle);
  232. LLSD sd = it->asLLSD(false);
  233. ensure("Correct single-key LLSD map root", is_double_key_map(sd, "regions", "duration"));
  234. ensure("Correct single-slot LLSD array regions", is_single_slot_array(sd["regions"], region1_handle));
  235. sd = sd[0];
  236. delete it;
  237. // Check a few points on the tree for content
  238. ensure("sd[get_texture_temp_http][dequeued] is 0", (0 == sd["get_texture_temp_http"]["dequeued"].asInteger()));
  239. ensure("sd[get_sound_udp][resp_min] is 0", (0.0 == sd["get_sound_udp"]["resp_min"].asReal()));
  240. }
  241. // Create a global instance and verify free functions do something useful
  242. template<> template<>
  243. void tst_viewerassetstats_index_object_t::test<4>()
  244. {
  245. gViewerAssetStatsMain = new LLViewerAssetStats();
  246. LLViewerAssetStatsFF::set_region_main(region1_handle);
  247. LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_TEXTURE, false, false);
  248. LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_TEXTURE, false, false);
  249. LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_BODYPART, false, false);
  250. LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_BODYPART, false, false);
  251. LLSD sd = gViewerAssetStatsMain->asLLSD(false);
  252. ensure("Correct single-key LLSD map root", is_double_key_map(sd, "regions", "duration"));
  253. ensure("Correct single-slot LLSD array regions", is_single_slot_array(sd["regions"], region1_handle));
  254. sd = sd["regions"][0];
  255. // Check a few points on the tree for content
  256. ensure("sd[get_texture_non_temp_udp][enqueued] is 1", (1 == sd["get_texture_non_temp_udp"]["enqueued"].asInteger()));
  257. ensure("sd[get_texture_temp_udp][enqueued] is 0", (0 == sd["get_texture_temp_udp"]["enqueued"].asInteger()));
  258. ensure("sd[get_texture_non_temp_http][enqueued] is 0", (0 == sd["get_texture_non_temp_http"]["enqueued"].asInteger()));
  259. ensure("sd[get_texture_temp_http][enqueued] is 0", (0 == sd["get_texture_temp_http"]["enqueued"].asInteger()));
  260. ensure("sd[get_gesture_udp][dequeued] is 0", (0 == sd["get_gesture_udp"]["dequeued"].asInteger()));
  261. // Reset and check zeros...
  262. // Reset leaves current region in place
  263. gViewerAssetStatsMain->reset();
  264. sd = gViewerAssetStatsMain->asLLSD(false)["regions"][region1_handle_str];
  265. delete gViewerAssetStatsMain;
  266. gViewerAssetStatsMain = NULL;
  267. ensure("sd[get_texture_non_temp_udp][enqueued] is reset", (0 == sd["get_texture_non_temp_udp"]["enqueued"].asInteger()));
  268. ensure("sd[get_gesture_udp][dequeued] is reset", (0 == sd["get_gesture_udp"]["dequeued"].asInteger()));
  269. }
  270. // Create two global instances and verify no interactions
  271. template<> template<>
  272. void tst_viewerassetstats_index_object_t::test<5>()
  273. {
  274. gViewerAssetStatsThread1 = new LLViewerAssetStats();
  275. gViewerAssetStatsMain = new LLViewerAssetStats();
  276. LLViewerAssetStatsFF::set_region_main(region1_handle);
  277. LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_TEXTURE, false, false);
  278. LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_TEXTURE, false, false);
  279. LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_BODYPART, false, false);
  280. LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_BODYPART, false, false);
  281. LLSD sd = gViewerAssetStatsThread1->asLLSD(false);
  282. ensure("Other collector is empty", is_no_stats_map(sd));
  283. sd = gViewerAssetStatsMain->asLLSD(false);
  284. ensure("Correct single-key LLSD map root", is_double_key_map(sd, "regions", "duration"));
  285. ensure("Correct single-slot LLSD array regions", is_single_slot_array(sd["regions"], region1_handle));
  286. sd = sd["regions"][0];
  287. // Check a few points on the tree for content
  288. ensure("sd[get_texture_non_temp_udp][enqueued] is 1", (1 == sd["get_texture_non_temp_udp"]["enqueued"].asInteger()));
  289. ensure("sd[get_texture_temp_udp][enqueued] is 0", (0 == sd["get_texture_temp_udp"]["enqueued"].asInteger()));
  290. ensure("sd[get_texture_non_temp_http][enqueued] is 0", (0 == sd["get_texture_non_temp_http"]["enqueued"].asInteger()));
  291. ensure("sd[get_texture_temp_http][enqueued] is 0", (0 == sd["get_texture_temp_http"]["enqueued"].asInteger()));
  292. ensure("sd[get_gesture_udp][dequeued] is 0", (0 == sd["get_gesture_udp"]["dequeued"].asInteger()));
  293. // Reset and check zeros...
  294. // Reset leaves current region in place
  295. gViewerAssetStatsMain->reset();
  296. sd = gViewerAssetStatsMain->asLLSD(false)["regions"][0];
  297. delete gViewerAssetStatsMain;
  298. gViewerAssetStatsMain = NULL;
  299. delete gViewerAssetStatsThread1;
  300. gViewerAssetStatsThread1 = NULL;
  301. ensure("sd[get_texture_non_temp_udp][enqueued] is reset", (0 == sd["get_texture_non_temp_udp"]["enqueued"].asInteger()));
  302. ensure("sd[get_gesture_udp][dequeued] is reset", (0 == sd["get_gesture_udp"]["dequeued"].asInteger()));
  303. }
  304. // Check multiple region collection
  305. template<> template<>
  306. void tst_viewerassetstats_index_object_t::test<6>()
  307. {
  308. gViewerAssetStatsMain = new LLViewerAssetStats();
  309. LLViewerAssetStatsFF::set_region_main(region1_handle);
  310. LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_TEXTURE, false, false);
  311. LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_TEXTURE, false, false);
  312. LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_BODYPART, false, false);
  313. LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_BODYPART, false, false);
  314. LLViewerAssetStatsFF::set_region_main(region2_handle);
  315. LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_GESTURE, false, false);
  316. LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_GESTURE, false, false);
  317. LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_GESTURE, false, false);
  318. LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_GESTURE, false, false);
  319. LLSD sd = gViewerAssetStatsMain->asLLSD(false);
  320. // std::cout << sd << std::endl;
  321. ensure("Correct double-key LLSD map root", is_double_key_map(sd, "duration", "regions"));
  322. ensure("Correct double-slot LLSD array regions", is_double_slot_array(sd["regions"], region1_handle, region2_handle));
  323. LLSD sd1 = get_region(sd, region1_handle);
  324. LLSD sd2 = get_region(sd, region2_handle);
  325. ensure("Region1 is present in results", sd1.isMap());
  326. ensure("Region2 is present in results", sd2.isMap());
  327. // Check a few points on the tree for content
  328. ensure_equals("sd1[get_texture_non_temp_udp][enqueued] is 1", sd1["get_texture_non_temp_udp"]["enqueued"].asInteger(), 1);
  329. ensure_equals("sd1[get_texture_temp_udp][enqueued] is 0", sd1["get_texture_temp_udp"]["enqueued"].asInteger(), 0);
  330. ensure_equals("sd1[get_texture_non_temp_http][enqueued] is 0", sd1["get_texture_non_temp_http"]["enqueued"].asInteger(), 0);
  331. ensure_equals("sd1[get_texture_temp_http][enqueued] is 0", sd1["get_texture_temp_http"]["enqueued"].asInteger(), 0);
  332. ensure_equals("sd1[get_gesture_udp][dequeued] is 0", sd1["get_gesture_udp"]["dequeued"].asInteger(), 0);
  333. // Check a few points on the tree for content
  334. ensure("sd2[get_gesture_udp][enqueued] is 4", (4 == sd2["get_gesture_udp"]["enqueued"].asInteger()));
  335. ensure("sd2[get_gesture_udp][dequeued] is 0", (0 == sd2["get_gesture_udp"]["dequeued"].asInteger()));
  336. ensure("sd2[get_texture_non_temp_udp][enqueued] is 0", (0 == sd2["get_texture_non_temp_udp"]["enqueued"].asInteger()));
  337. // Reset and check zeros...
  338. // Reset leaves current region in place
  339. gViewerAssetStatsMain->reset();
  340. sd = gViewerAssetStatsMain->asLLSD(false);
  341. ensure("Correct single-key LLSD map root", is_double_key_map(sd, "regions", "duration"));
  342. ensure("Correct single-slot LLSD array regions (p2)", is_single_slot_array(sd["regions"], region2_handle));
  343. sd2 = sd["regions"][0];
  344. delete gViewerAssetStatsMain;
  345. gViewerAssetStatsMain = NULL;
  346. ensure("sd2[get_texture_non_temp_udp][enqueued] is reset", (0 == sd2["get_texture_non_temp_udp"]["enqueued"].asInteger()));
  347. ensure("sd2[get_gesture_udp][enqueued] is reset", (0 == sd2["get_gesture_udp"]["enqueued"].asInteger()));
  348. }
  349. // Check multiple region collection jumping back-and-forth between regions
  350. template<> template<>
  351. void tst_viewerassetstats_index_object_t::test<7>()
  352. {
  353. gViewerAssetStatsMain = new LLViewerAssetStats();
  354. LLViewerAssetStatsFF::set_region_main(region1_handle);
  355. LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_TEXTURE, false, false);
  356. LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_TEXTURE, false, false);
  357. LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_BODYPART, false, false);
  358. LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_BODYPART, false, false);
  359. LLViewerAssetStatsFF::set_region_main(region2_handle);
  360. LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_GESTURE, false, false);
  361. LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_GESTURE, false, false);
  362. LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_GESTURE, false, false);
  363. LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_GESTURE, false, false);
  364. LLViewerAssetStatsFF::set_region_main(region1_handle);
  365. LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_TEXTURE, true, true);
  366. LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_TEXTURE, true, true);
  367. LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_BODYPART, false, false);
  368. LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_BODYPART, false, false);
  369. LLViewerAssetStatsFF::set_region_main(region2_handle);
  370. LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_GESTURE, false, false);
  371. LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_GESTURE, false, false);
  372. LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_GESTURE, false, false);
  373. LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_GESTURE, false, false);
  374. LLSD sd = gViewerAssetStatsMain->asLLSD(false);
  375. ensure("Correct double-key LLSD map root", is_double_key_map(sd, "duration", "regions"));
  376. ensure("Correct double-slot LLSD array regions", is_double_slot_array(sd["regions"], region1_handle, region2_handle));
  377. LLSD sd1 = get_region(sd, region1_handle);
  378. LLSD sd2 = get_region(sd, region2_handle);
  379. ensure("Region1 is present in results", sd1.isMap());
  380. ensure("Region2 is present in results", sd2.isMap());
  381. // Check a few points on the tree for content
  382. ensure("sd1[get_texture_non_temp_udp][enqueued] is 1", (1 == sd1["get_texture_non_temp_udp"]["enqueued"].asInteger()));
  383. ensure("sd1[get_texture_temp_udp][enqueued] is 0", (0 == sd1["get_texture_temp_udp"]["enqueued"].asInteger()));
  384. ensure("sd1[get_texture_non_temp_http][enqueued] is 0", (0 == sd1["get_texture_non_temp_http"]["enqueued"].asInteger()));
  385. ensure("sd1[get_texture_temp_http][enqueued] is 1", (1 == sd1["get_texture_temp_http"]["enqueued"].asInteger()));
  386. ensure("sd1[get_gesture_udp][dequeued] is 0", (0 == sd1["get_gesture_udp"]["dequeued"].asInteger()));
  387. // Check a few points on the tree for content
  388. ensure("sd2[get_gesture_udp][enqueued] is 8", (8 == sd2["get_gesture_udp"]["enqueued"].asInteger()));
  389. ensure("sd2[get_gesture_udp][dequeued] is 0", (0 == sd2["get_gesture_udp"]["dequeued"].asInteger()));
  390. ensure("sd2[get_texture_non_temp_udp][enqueued] is 0", (0 == sd2["get_texture_non_temp_udp"]["enqueued"].asInteger()));
  391. // Reset and check zeros...
  392. // Reset leaves current region in place
  393. gViewerAssetStatsMain->reset();
  394. sd = gViewerAssetStatsMain->asLLSD(false);
  395. ensure("Correct single-key LLSD map root", is_double_key_map(sd, "duration", "regions"));
  396. ensure("Correct single-slot LLSD array regions (p2)", is_single_slot_array(sd["regions"], region2_handle));
  397. sd2 = get_region(sd, region2_handle);
  398. ensure("Region2 is present in results", sd2.isMap());
  399. delete gViewerAssetStatsMain;
  400. gViewerAssetStatsMain = NULL;
  401. ensure_equals("sd2[get_texture_non_temp_udp][enqueued] is reset", sd2["get_texture_non_temp_udp"]["enqueued"].asInteger(), 0);
  402. ensure_equals("sd2[get_gesture_udp][enqueued] is reset", sd2["get_gesture_udp"]["enqueued"].asInteger(), 0);
  403. }
  404. // Non-texture assets ignore transport and persistence flags
  405. template<> template<>
  406. void tst_viewerassetstats_index_object_t::test<8>()
  407. {
  408. gViewerAssetStatsThread1 = new LLViewerAssetStats();
  409. gViewerAssetStatsMain = new LLViewerAssetStats();
  410. LLViewerAssetStatsFF::set_region_main(region1_handle);
  411. LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_TEXTURE, false, false);
  412. LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_TEXTURE, false, false);
  413. LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_BODYPART, false, false);
  414. LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_BODYPART, false, false);
  415. LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_BODYPART, false, true);
  416. LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_BODYPART, false, true);
  417. LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_BODYPART, true, false);
  418. LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_BODYPART, true, false);
  419. LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_BODYPART, true, true);
  420. LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_BODYPART, true, true);
  421. LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_LSL_BYTECODE, false, false);
  422. LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_LSL_BYTECODE, false, true);
  423. LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_LSL_BYTECODE, true, false);
  424. LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  425. LLSD sd = gViewerAssetStatsThread1->asLLSD(false);
  426. ensure("Other collector is empty", is_no_stats_map(sd));
  427. sd = gViewerAssetStatsMain->asLLSD(false);
  428. ensure("Correct single-key LLSD map root", is_double_key_map(sd, "regions", "duration"));
  429. ensure("Correct single-slot LLSD array regions", is_single_slot_array(sd["regions"], region1_handle));
  430. sd = get_region(sd, region1_handle);
  431. ensure("Region1 is present in results", sd.isMap());
  432. // Check a few points on the tree for content
  433. ensure("sd[get_gesture_udp][enqueued] is 0", (0 == sd["get_gesture_udp"]["enqueued"].asInteger()));
  434. ensure("sd[get_gesture_udp][dequeued] is 0", (0 == sd["get_gesture_udp"]["dequeued"].asInteger()));
  435. ensure("sd[get_wearable_udp][enqueued] is 4", (4 == sd["get_wearable_udp"]["enqueued"].asInteger()));
  436. ensure("sd[get_wearable_udp][dequeued] is 4", (4 == sd["get_wearable_udp"]["dequeued"].asInteger()));
  437. ensure("sd[get_other][enqueued] is 4", (4 == sd["get_other"]["enqueued"].asInteger()));
  438. ensure("sd[get_other][dequeued] is 0", (0 == sd["get_other"]["dequeued"].asInteger()));
  439. // Reset and check zeros...
  440. // Reset leaves current region in place
  441. gViewerAssetStatsMain->reset();
  442. sd = get_region(gViewerAssetStatsMain->asLLSD(false), region1_handle);
  443. ensure("Region1 is present in results", sd.isMap());
  444. delete gViewerAssetStatsMain;
  445. gViewerAssetStatsMain = NULL;
  446. delete gViewerAssetStatsThread1;
  447. gViewerAssetStatsThread1 = NULL;
  448. ensure_equals("sd[get_texture_non_temp_udp][enqueued] is reset", sd["get_texture_non_temp_udp"]["enqueued"].asInteger(), 0);
  449. ensure_equals("sd[get_gesture_udp][dequeued] is reset", sd["get_gesture_udp"]["dequeued"].asInteger(), 0);
  450. }
  451. // LLViewerAssetStats::merge() basic functions work
  452. template<> template<>
  453. void tst_viewerassetstats_index_object_t::test<9>()
  454. {
  455. LLViewerAssetStats s1;
  456. LLViewerAssetStats s2;
  457. s1.setRegion(region1_handle);
  458. s2.setRegion(region1_handle);
  459. s1.recordGetServiced(LLViewerAssetType::AT_TEXTURE, true, true, 5000000);
  460. s1.recordGetServiced(LLViewerAssetType::AT_TEXTURE, true, true, 6000000);
  461. s1.recordGetServiced(LLViewerAssetType::AT_TEXTURE, true, true, 8000000);
  462. s1.recordGetServiced(LLViewerAssetType::AT_TEXTURE, true, true, 7000000);
  463. s1.recordGetServiced(LLViewerAssetType::AT_TEXTURE, true, true, 9000000);
  464. s2.recordGetServiced(LLViewerAssetType::AT_TEXTURE, true, true, 2000000);
  465. s2.recordGetServiced(LLViewerAssetType::AT_TEXTURE, true, true, 3000000);
  466. s2.recordGetServiced(LLViewerAssetType::AT_TEXTURE, true, true, 4000000);
  467. s2.merge(s1);
  468. LLSD s2_llsd = get_region(s2.asLLSD(false), region1_handle);
  469. ensure("Region1 is present in results", s2_llsd.isMap());
  470. ensure_equals("count after merge", s2_llsd["get_texture_temp_http"]["resp_count"].asInteger(), 8);
  471. ensure_approximately_equals("min after merge", s2_llsd["get_texture_temp_http"]["resp_min"].asReal(), 2.0, 22);
  472. ensure_approximately_equals("max after merge", s2_llsd["get_texture_temp_http"]["resp_max"].asReal(), 9.0, 22);
  473. ensure_approximately_equals("max after merge", s2_llsd["get_texture_temp_http"]["resp_mean"].asReal(), 5.5, 22);
  474. }
  475. // LLViewerAssetStats::merge() basic functions work without corrupting source data
  476. template<> template<>
  477. void tst_viewerassetstats_index_object_t::test<10>()
  478. {
  479. LLViewerAssetStats s1;
  480. LLViewerAssetStats s2;
  481. s1.setRegion(region1_handle);
  482. s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  483. s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  484. s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  485. s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  486. s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  487. s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  488. s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  489. s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  490. s1.recordGetServiced(LLViewerAssetType::AT_LSL_BYTECODE, true, true, 23289200);
  491. s1.recordGetServiced(LLViewerAssetType::AT_LSL_BYTECODE, true, true, 282900);
  492. s2.setRegion(region2_handle);
  493. s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  494. s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  495. s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  496. s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  497. s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  498. s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  499. s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  500. s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  501. s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  502. s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  503. s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  504. s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  505. s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  506. s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  507. s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  508. s2.recordGetServiced(LLViewerAssetType::AT_LSL_BYTECODE, true, true, 6500000);
  509. s2.recordGetServiced(LLViewerAssetType::AT_LSL_BYTECODE, true, true, 10000);
  510. {
  511. s2.merge(s1);
  512. LLSD src = s1.asLLSD(false);
  513. LLSD dst = s2.asLLSD(false);
  514. ensure_equals("merge src has single region", src["regions"].size(), 1);
  515. ensure_equals("merge dst has dual regions", dst["regions"].size(), 2);
  516. // Remove time stamps, they're a problem
  517. src.erase("duration");
  518. src["regions"][0].erase("duration");
  519. dst.erase("duration");
  520. dst["regions"][0].erase("duration");
  521. dst["regions"][1].erase("duration");
  522. LLSD s1_llsd = get_region(src, region1_handle);
  523. ensure("Region1 is present in src", s1_llsd.isMap());
  524. LLSD s2_llsd = get_region(dst, region1_handle);
  525. ensure("Region1 is present in dst", s2_llsd.isMap());
  526. ensure("result from src is in dst", llsd_equals(s1_llsd, s2_llsd));
  527. }
  528. s1.setRegion(region1_handle);
  529. s2.setRegion(region1_handle);
  530. s1.reset();
  531. s2.reset();
  532. s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  533. s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  534. s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  535. s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  536. s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  537. s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  538. s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  539. s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  540. s1.recordGetServiced(LLViewerAssetType::AT_LSL_BYTECODE, true, true, 23289200);
  541. s1.recordGetServiced(LLViewerAssetType::AT_LSL_BYTECODE, true, true, 282900);
  542. s2.setRegion(region1_handle);
  543. s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  544. s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  545. s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  546. s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  547. s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  548. s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  549. s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  550. s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  551. s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  552. s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  553. s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  554. s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  555. s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  556. s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  557. s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  558. s2.recordGetServiced(LLViewerAssetType::AT_LSL_BYTECODE, true, true, 6500000);
  559. s2.recordGetServiced(LLViewerAssetType::AT_LSL_BYTECODE, true, true, 10000);
  560. {
  561. s2.merge(s1);
  562. LLSD src = s1.asLLSD(false);
  563. LLSD dst = s2.asLLSD(false);
  564. ensure_equals("merge src has single region (p2)", src["regions"].size(), 1);
  565. ensure_equals("merge dst has single region (p2)", dst["regions"].size(), 1);
  566. // Remove time stamps, they're a problem
  567. src.erase("duration");
  568. src["regions"][0].erase("duration");
  569. dst.erase("duration");
  570. dst["regions"][0].erase("duration");
  571. LLSD s1_llsd = get_region(src, region1_handle);
  572. ensure("Region1 is present in src", s1_llsd.isMap());
  573. LLSD s2_llsd = get_region(dst, region1_handle);
  574. ensure("Region1 is present in dst", s2_llsd.isMap());
  575. ensure_equals("src counts okay (enq)", s1_llsd["get_other"]["enqueued"].asInteger(), 4);
  576. ensure_equals("src counts okay (deq)", s1_llsd["get_other"]["dequeued"].asInteger(), 4);
  577. ensure_equals("src resp counts okay", s1_llsd["get_other"]["resp_count"].asInteger(), 2);
  578. ensure_approximately_equals("src respmin okay", s1_llsd["get_other"]["resp_min"].asReal(), 0.2829, 20);
  579. ensure_approximately_equals("src respmax okay", s1_llsd["get_other"]["resp_max"].asReal(), 23.2892, 20);
  580. ensure_equals("dst counts okay (enq)", s2_llsd["get_other"]["enqueued"].asInteger(), 12);
  581. ensure_equals("src counts okay (deq)", s2_llsd["get_other"]["dequeued"].asInteger(), 11);
  582. ensure_equals("dst resp counts okay", s2_llsd["get_other"]["resp_count"].asInteger(), 4);
  583. ensure_approximately_equals("dst respmin okay", s2_llsd["get_other"]["resp_min"].asReal(), 0.010, 20);
  584. ensure_approximately_equals("dst respmax okay", s2_llsd["get_other"]["resp_max"].asReal(), 23.2892, 20);
  585. }
  586. }
  587. // Maximum merges are interesting when one side contributes nothing
  588. template<> template<>
  589. void tst_viewerassetstats_index_object_t::test<11>()
  590. {
  591. LLViewerAssetStats s1;
  592. LLViewerAssetStats s2;
  593. s1.setRegion(region1_handle);
  594. s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  595. s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  596. s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  597. s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  598. s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  599. s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  600. s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  601. s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  602. // Want to test negative numbers here but have to work in U64
  603. s1.recordGetServiced(LLViewerAssetType::AT_LSL_BYTECODE, true, true, 0);
  604. s1.recordGetServiced(LLViewerAssetType::AT_LSL_BYTECODE, true, true, 0);
  605. s1.recordGetServiced(LLViewerAssetType::AT_LSL_BYTECODE, true, true, 0);
  606. s2.setRegion(region1_handle);
  607. s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  608. s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  609. s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  610. s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  611. s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  612. s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  613. s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  614. s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  615. s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  616. s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  617. s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  618. s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  619. s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  620. s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  621. s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  622. {
  623. s2.merge(s1);
  624. LLSD src = s1.asLLSD(false);
  625. LLSD dst = s2.asLLSD(false);
  626. ensure_equals("merge src has single region", src["regions"].size(), 1);
  627. ensure_equals("merge dst has single region", dst["regions"].size(), 1);
  628. // Remove time stamps, they're a problem
  629. src.erase("duration");
  630. src["regions"][0].erase("duration");
  631. dst.erase("duration");
  632. dst["regions"][0].erase("duration");
  633. LLSD s2_llsd = get_region(dst, region1_handle);
  634. ensure("Region1 is present in dst", s2_llsd.isMap());
  635. ensure_equals("dst counts come from src only", s2_llsd["get_other"]["resp_count"].asInteger(), 3);
  636. ensure_approximately_equals("dst maximum with count 0 does not contribute to merged maximum",
  637. s2_llsd["get_other"]["resp_max"].asReal(), F64(0.0), 20);
  638. }
  639. // Other way around
  640. s1.setRegion(region1_handle);
  641. s2.setRegion(region1_handle);
  642. s1.reset();
  643. s2.reset();
  644. s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  645. s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  646. s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  647. s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  648. s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  649. s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  650. s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  651. s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  652. // Want to test negative numbers here but have to work in U64
  653. s1.recordGetServiced(LLViewerAssetType::AT_LSL_BYTECODE, true, true, 0);
  654. s1.recordGetServiced(LLViewerAssetType::AT_LSL_BYTECODE, true, true, 0);
  655. s1.recordGetServiced(LLViewerAssetType::AT_LSL_BYTECODE, true, true, 0);
  656. s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  657. s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  658. s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  659. s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  660. s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  661. s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  662. s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  663. s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  664. s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  665. s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  666. s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  667. s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  668. s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  669. s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  670. s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  671. {
  672. s1.merge(s2);
  673. LLSD src = s2.asLLSD(false);
  674. LLSD dst = s1.asLLSD(false);
  675. ensure_equals("merge src has single region", src["regions"].size(), 1);
  676. ensure_equals("merge dst has single region", dst["regions"].size(), 1);
  677. // Remove time stamps, they're a problem
  678. src.erase("duration");
  679. src["regions"][0].erase("duration");
  680. dst.erase("duration");
  681. dst["regions"][0].erase("duration");
  682. LLSD s2_llsd = get_region(dst, region1_handle);
  683. ensure("Region1 is present in dst", s2_llsd.isMap());
  684. ensure_equals("dst counts come from src only (flipped)", s2_llsd["get_other"]["resp_count"].asInteger(), 3);
  685. ensure_approximately_equals("dst maximum with count 0 does not contribute to merged maximum (flipped)",
  686. s2_llsd["get_other"]["resp_max"].asReal(), F64(0.0), 20);
  687. }
  688. }
  689. // Minimum merges are interesting when one side contributes nothing
  690. template<> template<>
  691. void tst_viewerassetstats_index_object_t::test<12>()
  692. {
  693. LLViewerAssetStats s1;
  694. LLViewerAssetStats s2;
  695. s1.setRegion(region1_handle);
  696. s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  697. s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  698. s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  699. s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  700. s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  701. s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  702. s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  703. s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  704. s1.recordGetServiced(LLViewerAssetType::AT_LSL_BYTECODE, true, true, 3800000);
  705. s1.recordGetServiced(LLViewerAssetType::AT_LSL_BYTECODE, true, true, 2700000);
  706. s1.recordGetServiced(LLViewerAssetType::AT_LSL_BYTECODE, true, true, 2900000);
  707. s2.setRegion(region1_handle);
  708. s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  709. s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  710. s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  711. s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  712. s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  713. s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  714. s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  715. s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  716. s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  717. s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  718. s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  719. s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  720. s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  721. s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  722. s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  723. {
  724. s2.merge(s1);
  725. LLSD src = s1.asLLSD(false);
  726. LLSD dst = s2.asLLSD(false);
  727. ensure_equals("merge src has single region", src["regions"].size(), 1);
  728. ensure_equals("merge dst has single region", dst["regions"].size(), 1);
  729. // Remove time stamps, they're a problem
  730. src.erase("duration");
  731. src["regions"][0].erase("duration");
  732. dst.erase("duration");
  733. dst["regions"][0].erase("duration");
  734. LLSD s2_llsd = get_region(dst, region1_handle);
  735. ensure("Region1 is present in dst", s2_llsd.isMap());
  736. ensure_equals("dst counts come from src only", s2_llsd["get_other"]["resp_count"].asInteger(), 3);
  737. ensure_approximately_equals("dst minimum with count 0 does not contribute to merged minimum",
  738. s2_llsd["get_other"]["resp_min"].asReal(), F64(2.7), 20);
  739. }
  740. // Other way around
  741. s1.setRegion(region1_handle);
  742. s2.setRegion(region1_handle);
  743. s1.reset();
  744. s2.reset();
  745. s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  746. s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  747. s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  748. s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  749. s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  750. s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  751. s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  752. s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  753. s1.recordGetServiced(LLViewerAssetType::AT_LSL_BYTECODE, true, true, 3800000);
  754. s1.recordGetServiced(LLViewerAssetType::AT_LSL_BYTECODE, true, true, 2700000);
  755. s1.recordGetServiced(LLViewerAssetType::AT_LSL_BYTECODE, true, true, 2900000);
  756. s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  757. s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  758. s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  759. s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  760. s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  761. s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  762. s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  763. s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  764. s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  765. s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  766. s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  767. s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  768. s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  769. s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  770. s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
  771. {
  772. s1.merge(s2);
  773. LLSD src = s2.asLLSD(false);
  774. LLSD dst = s1.asLLSD(false);
  775. ensure_equals("merge src has single region", src["regions"].size(), 1);
  776. ensure_equals("merge dst has single region", dst["regions"].size(), 1);
  777. // Remove time stamps, they're a problem
  778. src.erase("duration");
  779. src["regions"][0].erase("duration");
  780. dst.erase("duration");
  781. dst["regions"][0].erase("duration");
  782. LLSD s2_llsd = get_region(dst, region1_handle);
  783. ensure("Region1 is present in dst", s2_llsd.isMap());
  784. ensure_equals("dst counts come from src only (flipped)", s2_llsd["get_other"]["resp_count"].asInteger(), 3);
  785. ensure_approximately_equals("dst minimum with count 0 does not contribute to merged minimum (flipped)",
  786. s2_llsd["get_other"]["resp_min"].asReal(), F64(2.7), 20);
  787. }
  788. }
  789. }