PageRenderTime 266ms CodeModel.GetById 51ms RepoModel.GetById 5ms app.codeStats 3ms

/indra/newview/tests/llmediadataclient_test.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 969 lines | 655 code | 172 blank | 142 comment | 13 complexity | fc5583cbae6fde9be041afb7a14aeb85 MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file llmediadataclient_test.cpp
  3. * @brief LLMediaDatClient tests
  4. *
  5. * $LicenseInfo:firstyear=2001&license=viewerlgpl$
  6. * Second Life Viewer Source Code
  7. * Copyright (C) 2010, Linden Research, Inc.
  8. *
  9. * This library is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public
  11. * License as published by the Free Software Foundation;
  12. * version 2.1 of the License only.
  13. *
  14. * This library is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with this library; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22. *
  23. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  24. * $/LicenseInfo$
  25. */
  26. #include "linden_common.h"
  27. #include "../llviewerprecompiledheaders.h"
  28. #include <iostream>
  29. #include "../test/lltut.h"
  30. #include "llsdserialize.h"
  31. #include "llsdutil.h"
  32. #include "llerrorcontrol.h"
  33. #include "llhttpstatuscodes.h"
  34. #include "../llmediadataclient.h"
  35. #include "../llvovolume.h"
  36. #include "../../llprimitive/llmediaentry.cpp"
  37. #include "../../llprimitive/lltextureentry.cpp"
  38. #include "../../llmessage/tests/llcurl_stub.cpp"
  39. #if LL_WINDOWS
  40. #pragma warning (push)
  41. #pragma warning (disable : 4702) // boost::lexical_cast generates this warning
  42. #endif
  43. #include <boost/lexical_cast.hpp>
  44. #if LL_WINDOWS
  45. #pragma warning (pop)
  46. #endif
  47. #define VALID_OBJECT_ID "3607d5c4-644b-4a8a-871a-8b78471af2a2"
  48. #define VALID_OBJECT_ID_1 "11111111-1111-1111-1111-111111111111"
  49. #define VALID_OBJECT_ID_2 "22222222-2222-2222-2222-222222222222"
  50. #define VALID_OBJECT_ID_3 "33333333-3333-3333-3333-333333333333"
  51. #define VALID_OBJECT_ID_4 "44444444-4444-4444-4444-444444444444"
  52. #define FAKE_OBJECT_MEDIA_CAP_URL "foo_ObjectMedia"
  53. #define FAKE_OBJECT_MEDIA_NAVIGATE_CAP_URL "foo_ObjectMediaNavigate"
  54. #define FAKE_OBJECT_MEDIA_CAP_URL_503 "foo_ObjectMedia_503"
  55. #define FAKE_OBJECT_MEDIA_NAVIGATE_CAP_URL_ERROR "foo_ObjectMediaNavigate_ERROR"
  56. #define MEDIA_DATA "\
  57. <array> \
  58. <string>http://foo.example.com</string> \
  59. <string>http://bar.example.com</string> \
  60. <string>baz</string> \
  61. </array>"
  62. #define _DATA_URLS(ID,INTEREST,NEW,URL1,URL2) " \
  63. <llsd> \
  64. <map> \
  65. <key>uuid</key> \
  66. <string>" ID "</string> \
  67. <key>interest</key> \
  68. <real>" INTEREST "</real> \
  69. <key>cap_urls</key> \
  70. <map> \
  71. <key>ObjectMedia</key> \
  72. <string>" URL1 "</string> \
  73. <key>ObjectMediaNavigate</key> \
  74. <string>" URL2 "</string> \
  75. </map> \
  76. <key>media_data</key> \
  77. " MEDIA_DATA " \
  78. <key>is_dead</key> \
  79. <boolean>false</boolean> \
  80. <key>is_new</key> \
  81. <boolean>" NEW "</boolean> \
  82. </map> \
  83. </llsd>"
  84. #define _DATA(ID,INTEREST,NEW) _DATA_URLS(ID,INTEREST,NEW,FAKE_OBJECT_MEDIA_CAP_URL,FAKE_OBJECT_MEDIA_NAVIGATE_CAP_URL)
  85. const char *DATA = _DATA(VALID_OBJECT_ID,"1.0","true");
  86. #define STR(I) boost::lexical_cast<std::string>(I)
  87. #define LOG_TEST(N) LL_DEBUGS("LLMediaDataClient") << "\n" << \
  88. "================================================================================\n" << \
  89. "==================================== TEST " #N " ===================================\n" << \
  90. "================================================================================\n" << LL_ENDL;
  91. LLSD *gPostRecords = NULL;
  92. F64 gMinimumInterestLevel = (F64)0.0;
  93. // stubs:
  94. void LLHTTPClient::post(
  95. const std::string& url,
  96. const LLSD& body,
  97. LLHTTPClient::ResponderPtr responder,
  98. const LLSD& headers,
  99. const F32 timeout)
  100. {
  101. LLSD record;
  102. record["url"] = url;
  103. record["body"] = body;
  104. record["headers"] = headers;
  105. record["timeout"] = timeout;
  106. gPostRecords->append(record);
  107. // Magic URL that triggers a 503:
  108. LLSD result;
  109. result[LLTextureEntry::OBJECT_ID_KEY] = body[LLTextureEntry::OBJECT_ID_KEY];
  110. if ( url == FAKE_OBJECT_MEDIA_CAP_URL_503 )
  111. {
  112. responder->error(HTTP_SERVICE_UNAVAILABLE, "fake reason");
  113. return;
  114. }
  115. else if (url == FAKE_OBJECT_MEDIA_NAVIGATE_CAP_URL_ERROR)
  116. {
  117. LLSD error;
  118. error["code"] = LLObjectMediaNavigateClient::ERROR_PERMISSION_DENIED_CODE;
  119. result["error"] = error;
  120. }
  121. responder->result(result);
  122. }
  123. const F32 HTTP_REQUEST_EXPIRY_SECS = 60.0f;
  124. class LLMediaDataClientObjectTest : public LLMediaDataClientObject
  125. {
  126. public:
  127. LLMediaDataClientObjectTest(const char *data)
  128. {
  129. std::istringstream d(data);
  130. LLSDSerialize::fromXML(mRep, d);
  131. mNumBounceBacks = 0;
  132. // std::cout << ll_pretty_print_sd(mRep) << std::endl;
  133. // std::cout << "ID: " << getID() << std::endl;
  134. }
  135. LLMediaDataClientObjectTest(const LLSD &rep)
  136. : mRep(rep), mNumBounceBacks(0) {}
  137. ~LLMediaDataClientObjectTest()
  138. { LL_DEBUGS("LLMediaDataClient") << "~LLMediaDataClientObjectTest" << LL_ENDL; }
  139. virtual U8 getMediaDataCount() const
  140. { return mRep["media_data"].size(); }
  141. virtual LLSD getMediaDataLLSD(U8 index) const
  142. { return mRep["media_data"][(LLSD::Integer)index]; }
  143. virtual bool isCurrentMediaUrl(U8 index, const std::string &url) const
  144. { return (mRep["media_data"][(LLSD::Integer)index].asString() == url); }
  145. virtual LLUUID getID() const
  146. { return mRep["uuid"]; }
  147. virtual void mediaNavigateBounceBack(U8 index)
  148. { mNumBounceBacks++; }
  149. virtual bool hasMedia() const
  150. { return mRep.has("media_data"); }
  151. virtual void updateObjectMediaData(LLSD const &media_data_array, const std::string &media_version)
  152. { mRep["media_data"] = media_data_array; mRep["media_version"] = media_version; }
  153. virtual F64 getMediaInterest() const
  154. { return (LLSD::Real)mRep["interest"]; }
  155. virtual bool isInterestingEnough() const
  156. { return getMediaInterest() > gMinimumInterestLevel; }
  157. virtual std::string getCapabilityUrl(const std::string &name) const
  158. { return mRep["cap_urls"][name]; }
  159. virtual bool isDead() const
  160. { return mRep["is_dead"]; }
  161. virtual U32 getMediaVersion() const
  162. { return (LLSD::Integer)mRep["media_version"]; }
  163. virtual bool isNew() const
  164. { return mRep["is_new"]; }
  165. void setMediaInterest(F64 val)
  166. { mRep["interest"] = val; }
  167. int getNumBounceBacks() const
  168. { return mNumBounceBacks; }
  169. void markDead()
  170. { mRep["is_dead"] = true; }
  171. void markOld()
  172. { mRep["is_new"] = false; }
  173. private:
  174. LLSD mRep;
  175. int mNumBounceBacks;
  176. };
  177. // This special timer delay should ensure that the timer will fire on the very
  178. // next pump, no matter what (though this does make an assumption about the
  179. // implementation of LLEventTimer::updateClass()):
  180. const F32 NO_PERIOD = -1000.0f;
  181. static void pump_timers()
  182. {
  183. LLEventTimer::updateClass();
  184. }
  185. namespace tut
  186. {
  187. struct mediadataclient
  188. {
  189. mediadataclient() {
  190. gPostRecords = &mLLSD;
  191. gMinimumInterestLevel = (F64)0.0;
  192. // LLError::setDefaultLevel(LLError::LEVEL_DEBUG);
  193. // LLError::setClassLevel("LLMediaDataClient", LLError::LEVEL_DEBUG);
  194. // LLError::setTagLevel("MediaOnAPrim", LLError::LEVEL_DEBUG);
  195. }
  196. LLSD mLLSD;
  197. };
  198. typedef test_group<mediadataclient> mediadataclient_t;
  199. typedef mediadataclient_t::object mediadataclient_object_t;
  200. tut::mediadataclient_t tut_mediadataclient("LLMediaDataClient");
  201. void ensure(const std::string &msg, int value, int expected)
  202. {
  203. std::string m = msg;
  204. m += " value: " + STR(value);
  205. m += ", expected: " + STR(expected);
  206. ensure(m, value == expected);
  207. }
  208. void ensure(const std::string &msg, const std::string & value, const std::string & expected)
  209. {
  210. std::string m = msg;
  211. m += " value: " + value;
  212. m += ", expected: " + expected;
  213. ensure(m, value == expected);
  214. }
  215. void ensure(const std::string &msg, const LLUUID & value, const LLUUID & expected)
  216. {
  217. std::string m = msg;
  218. m += " value: " + value.asString();
  219. m += ", expected: " + expected.asString();
  220. ensure(m, value == expected);
  221. }
  222. void ensure_llsd(const std::string &msg, const LLSD & value, const char *expected)
  223. {
  224. LLSD expected_llsd;
  225. std::istringstream e(expected);
  226. LLSDSerialize::fromXML(expected_llsd, e);
  227. std::string value_str = ll_pretty_print_sd(value);
  228. std::string expected_str = ll_pretty_print_sd(expected_llsd);
  229. std::string m = msg;
  230. m += " value: " + value_str;
  231. m += ", expected: " + expected_str;
  232. ensure(m, value_str == expected_str);
  233. }
  234. //////////////////////////////////////////////////////////////////////////////////////////
  235. template<> template<>
  236. void mediadataclient_object_t::test<1>()
  237. {
  238. //
  239. // Test fetchMedia()
  240. //
  241. LOG_TEST(1);
  242. LLMediaDataClientObject::ptr_t o = new LLMediaDataClientObjectTest(DATA);
  243. int num_refs_start = o->getNumRefs();
  244. {
  245. LLPointer<LLObjectMediaDataClient> mdc = new LLObjectMediaDataClient(NO_PERIOD,NO_PERIOD);
  246. mdc->fetchMedia(o);
  247. // Make sure no posts happened yet...
  248. ensure("post records", gPostRecords->size(), 0);
  249. ::pump_timers();
  250. ensure("post records", gPostRecords->size(), 1);
  251. ensure("post url", (*gPostRecords)[0]["url"], FAKE_OBJECT_MEDIA_CAP_URL);
  252. ensure("post GET", (*gPostRecords)[0]["body"]["verb"], "GET");
  253. ensure("post object id", (*gPostRecords)[0]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID));
  254. ensure("queue empty", mdc->isEmpty());
  255. }
  256. // Make sure everyone's destroyed properly
  257. ensure("REF COUNT", o->getNumRefs(), num_refs_start);
  258. }
  259. //////////////////////////////////////////////////////////////////////////////////////////
  260. template<> template<>
  261. void mediadataclient_object_t::test<2>()
  262. {
  263. //
  264. // Test updateMedia()
  265. //
  266. LOG_TEST(2);
  267. LLMediaDataClientObject::ptr_t o = new LLMediaDataClientObjectTest(DATA);
  268. {
  269. // queue time w/ no delay ensures that ::pump_timers() will hit the tick()
  270. LLPointer<LLObjectMediaDataClient> mdc = new LLObjectMediaDataClient(NO_PERIOD,NO_PERIOD);
  271. mdc->updateMedia(o);
  272. ensure("post records", gPostRecords->size(), 0);
  273. ::pump_timers();
  274. ensure("post records", gPostRecords->size(), 1);
  275. ensure("post url", (*gPostRecords)[0]["url"], FAKE_OBJECT_MEDIA_CAP_URL);
  276. ensure("post UPDATE", (*gPostRecords)[0]["body"]["verb"], "UPDATE");
  277. ensure("post object id", (*gPostRecords)[0]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID));
  278. ensure_llsd("post data llsd", (*gPostRecords)[0]["body"][LLTextureEntry::OBJECT_MEDIA_DATA_KEY],
  279. "<llsd>" MEDIA_DATA "</llsd>");
  280. ensure("queue empty", mdc->isEmpty());
  281. }
  282. ensure("REF COUNT", o->getNumRefs(), 1);
  283. }
  284. //////////////////////////////////////////////////////////////////////////////////////////
  285. template<> template<>
  286. void mediadataclient_object_t::test<3>()
  287. {
  288. //
  289. // Test navigate()
  290. //
  291. LOG_TEST(3);
  292. LLMediaDataClientObject::ptr_t o = new LLMediaDataClientObjectTest(DATA);
  293. {
  294. LLPointer<LLObjectMediaNavigateClient> mdc = new LLObjectMediaNavigateClient(NO_PERIOD,NO_PERIOD);
  295. const char *TEST_URL = "http://example.com";
  296. mdc->navigate(o, 0, TEST_URL);
  297. ensure("post records", gPostRecords->size(), 0);
  298. ::pump_timers();
  299. // ensure no bounce back
  300. ensure("bounce back", dynamic_cast<LLMediaDataClientObjectTest*>(static_cast<LLMediaDataClientObject*>(o))->getNumBounceBacks(), 0);
  301. ensure("post records", gPostRecords->size(), 1);
  302. ensure("post url", (*gPostRecords)[0]["url"], FAKE_OBJECT_MEDIA_NAVIGATE_CAP_URL);
  303. ensure("post object id", (*gPostRecords)[0]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID));
  304. ensure("post data", (*gPostRecords)[0]["body"][LLTextureEntry::TEXTURE_INDEX_KEY], 0);
  305. ensure("post data", (*gPostRecords)[0]["body"][LLMediaEntry::CURRENT_URL_KEY], TEST_URL);
  306. ensure("queue empty", mdc->isEmpty());
  307. }
  308. ensure("REF COUNT", o->getNumRefs(), 1);
  309. }
  310. //////////////////////////////////////////////////////////////////////////////////////////
  311. template<> template<>
  312. void mediadataclient_object_t::test<4>()
  313. {
  314. //
  315. // Test queue ordering
  316. //
  317. LOG_TEST(4);
  318. LLMediaDataClientObject::ptr_t o1 = new LLMediaDataClientObjectTest(
  319. _DATA(VALID_OBJECT_ID_1,"1.0","true"));
  320. LLMediaDataClientObject::ptr_t o2 = new LLMediaDataClientObjectTest(
  321. _DATA(VALID_OBJECT_ID_2,"3.0","true"));
  322. LLMediaDataClientObject::ptr_t o3 = new LLMediaDataClientObjectTest(
  323. _DATA(VALID_OBJECT_ID_3,"2.0","true"));
  324. {
  325. LLPointer<LLObjectMediaDataClient> mdc = new LLObjectMediaDataClient(NO_PERIOD,NO_PERIOD);
  326. const char *ORDERED_OBJECT_IDS[] = { VALID_OBJECT_ID_2, VALID_OBJECT_ID_3, VALID_OBJECT_ID_1 };
  327. mdc->fetchMedia(o1);
  328. mdc->fetchMedia(o2);
  329. mdc->fetchMedia(o3);
  330. // Make sure no posts happened yet...
  331. ensure("post records", gPostRecords->size(), 0);
  332. // tick 3 times...
  333. ::pump_timers();
  334. ensure("post records", gPostRecords->size(), 1);
  335. ::pump_timers();
  336. ensure("post records", gPostRecords->size(), 2);
  337. ::pump_timers();
  338. ensure("post records", gPostRecords->size(), 3);
  339. for( int i=0; i < 3; i++ )
  340. {
  341. ensure("[" + STR(i) + "] post url", (*gPostRecords)[i]["url"], FAKE_OBJECT_MEDIA_CAP_URL);
  342. ensure("[" + STR(i) + "] post GET", (*gPostRecords)[i]["body"]["verb"], "GET");
  343. ensure("[" + STR(i) + "] post object id", (*gPostRecords)[i]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(),
  344. LLUUID(ORDERED_OBJECT_IDS[i]));
  345. }
  346. ensure("queue empty", mdc->isEmpty());
  347. }
  348. ensure("refcount of o1", o1->getNumRefs(), 1);
  349. ensure("refcount of o2", o2->getNumRefs(), 1);
  350. ensure("refcount of o3", o3->getNumRefs(), 1);
  351. }
  352. //////////////////////////////////////////////////////////////////////////////////////////
  353. template<> template<>
  354. void mediadataclient_object_t::test<5>()
  355. {
  356. //
  357. // Test fetchMedia() getting a 503 error
  358. //
  359. LOG_TEST(5);
  360. LLMediaDataClientObject::ptr_t o = new LLMediaDataClientObjectTest(
  361. _DATA_URLS(VALID_OBJECT_ID,
  362. "1.0","true",
  363. FAKE_OBJECT_MEDIA_CAP_URL_503,
  364. FAKE_OBJECT_MEDIA_NAVIGATE_CAP_URL));
  365. int num_refs_start = o->getNumRefs();
  366. {
  367. const int NUM_RETRIES = 5;
  368. LLPointer<LLObjectMediaDataClient> mdc = new LLObjectMediaDataClient(NO_PERIOD,NO_PERIOD,NUM_RETRIES);
  369. // This should generate a retry
  370. mdc->fetchMedia(o);
  371. // Make sure no posts happened yet...
  372. ensure("post records before", gPostRecords->size(), 0);
  373. // Once, causes retry
  374. // Second, fires retry timer
  375. // Third, fires queue timer again
  376. for (int i=0; i<NUM_RETRIES; ++i)
  377. {
  378. ::pump_timers(); // Should pump (fire) the queue timer, causing a retry timer to be scheduled
  379. // XXX This ensure is not guaranteed, because scheduling a timer might actually get it pumped in the same loop
  380. //ensure("post records " + STR(i), gPostRecords->size(), i+1);
  381. ::pump_timers(); // Should pump (fire) the retry timer, scheduling the queue timer
  382. }
  383. // Do some extra pumps to make sure no other timer work occurs.
  384. ::pump_timers();
  385. ::pump_timers();
  386. ::pump_timers();
  387. // Make sure there were 2 posts
  388. ensure("post records after", gPostRecords->size(), NUM_RETRIES);
  389. for (int i=0; i<NUM_RETRIES; ++i)
  390. {
  391. ensure("[" + STR(i) + "] post url", (*gPostRecords)[i]["url"], FAKE_OBJECT_MEDIA_CAP_URL_503);
  392. ensure("[" + STR(i) + "] post GET", (*gPostRecords)[i]["body"]["verb"], "GET");
  393. ensure("[" + STR(i) + "] post object id", (*gPostRecords)[i]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID));
  394. }
  395. ensure("queue empty", mdc->isEmpty());
  396. }
  397. // Make sure everyone's destroyed properly
  398. ensure("REF COUNT", o->getNumRefs(), num_refs_start);
  399. }
  400. template<> template<>
  401. void mediadataclient_object_t::test<6>()
  402. {
  403. //
  404. // Test navigate() with a bounce back
  405. //
  406. LOG_TEST(6);
  407. LLMediaDataClientObject::ptr_t o = new LLMediaDataClientObjectTest(
  408. _DATA_URLS(VALID_OBJECT_ID,
  409. "1.0","true",
  410. FAKE_OBJECT_MEDIA_CAP_URL,
  411. FAKE_OBJECT_MEDIA_NAVIGATE_CAP_URL_ERROR));
  412. {
  413. LLPointer<LLObjectMediaNavigateClient> mdc = new LLObjectMediaNavigateClient(NO_PERIOD,NO_PERIOD);
  414. const char *TEST_URL = "http://example.com";
  415. mdc->navigate(o, 0, TEST_URL);
  416. ensure("post records", gPostRecords->size(), 0);
  417. ::pump_timers();
  418. // ensure bounce back
  419. ensure("bounce back",
  420. dynamic_cast<LLMediaDataClientObjectTest*>(static_cast<LLMediaDataClientObject*>(o))->getNumBounceBacks(),
  421. 1);
  422. ensure("post records", gPostRecords->size(), 1);
  423. ensure("post url", (*gPostRecords)[0]["url"], FAKE_OBJECT_MEDIA_NAVIGATE_CAP_URL_ERROR);
  424. ensure("post object id", (*gPostRecords)[0]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID));
  425. ensure("post data", (*gPostRecords)[0]["body"][LLTextureEntry::TEXTURE_INDEX_KEY], 0);
  426. ensure("post data", (*gPostRecords)[0]["body"][LLMediaEntry::CURRENT_URL_KEY], TEST_URL);
  427. ensure("queue empty", mdc->isEmpty());
  428. }
  429. ensure("REF COUNT", o->getNumRefs(), 1);
  430. }
  431. template<> template<>
  432. void mediadataclient_object_t::test<7>()
  433. {
  434. // Test LLMediaDataClient::isInQueue()
  435. LOG_TEST(7);
  436. LLMediaDataClientObject::ptr_t o1 = new LLMediaDataClientObjectTest(
  437. _DATA(VALID_OBJECT_ID_1,"3.0","true"));
  438. LLMediaDataClientObject::ptr_t o2 = new LLMediaDataClientObjectTest(
  439. _DATA(VALID_OBJECT_ID_2,"1.0","true"));
  440. int num_refs_start = o1->getNumRefs();
  441. {
  442. LLPointer<LLObjectMediaDataClient> mdc = new LLObjectMediaDataClient(NO_PERIOD,NO_PERIOD);
  443. ensure("not in queue yet 1", ! mdc->isInQueue(o1));
  444. ensure("not in queue yet 2", ! mdc->isInQueue(o2));
  445. mdc->fetchMedia(o1);
  446. ensure("is in queue", mdc->isInQueue(o1));
  447. ensure("is not in queue", ! mdc->isInQueue(o2));
  448. ::pump_timers();
  449. ensure("not in queue anymore", ! mdc->isInQueue(o1));
  450. ensure("still is not in queue", ! mdc->isInQueue(o2));
  451. ensure("queue empty", mdc->isEmpty());
  452. }
  453. // Make sure everyone's destroyed properly
  454. ensure("REF COUNT", o1->getNumRefs(), num_refs_start);
  455. }
  456. template<> template<>
  457. void mediadataclient_object_t::test<8>()
  458. {
  459. // Test queue handling of objects that are marked dead.
  460. LOG_TEST(8);
  461. LLMediaDataClientObject::ptr_t o1 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_1,"4.0","true"));
  462. LLMediaDataClientObject::ptr_t o2 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_2,"3.0","true"));
  463. LLMediaDataClientObject::ptr_t o3 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_3,"2.0","true"));
  464. LLMediaDataClientObject::ptr_t o4 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_4,"1.0","true"));
  465. {
  466. LLPointer<LLObjectMediaDataClient> mdc = new LLObjectMediaDataClient(NO_PERIOD,NO_PERIOD);
  467. // queue up all 4 objects
  468. mdc->fetchMedia(o1);
  469. mdc->fetchMedia(o2);
  470. mdc->fetchMedia(o3);
  471. mdc->fetchMedia(o4);
  472. ensure("is in queue 1", mdc->isInQueue(o1));
  473. ensure("is in queue 2", mdc->isInQueue(o2));
  474. ensure("is in queue 3", mdc->isInQueue(o3));
  475. ensure("is in queue 4", mdc->isInQueue(o4));
  476. ensure("post records", gPostRecords->size(), 0);
  477. // and mark the second and fourth ones dead. Call removeFromQueue when marking dead, since this is what LLVOVolume will do.
  478. dynamic_cast<LLMediaDataClientObjectTest*>(static_cast<LLMediaDataClientObject*>(o2))->markDead();
  479. mdc->removeFromQueue(o2);
  480. dynamic_cast<LLMediaDataClientObjectTest*>(static_cast<LLMediaDataClientObject*>(o4))->markDead();
  481. mdc->removeFromQueue(o4);
  482. // The removeFromQueue calls should remove the second and fourth ones
  483. ensure("is in queue 1", mdc->isInQueue(o1));
  484. ensure("is not in queue 2", !mdc->isInQueue(o2));
  485. ensure("is in queue 3", mdc->isInQueue(o3));
  486. ensure("is not in queue 4", !mdc->isInQueue(o4));
  487. ensure("post records", gPostRecords->size(), 0);
  488. ::pump_timers();
  489. // The first tick should process the first item
  490. ensure("is not in queue 1", !mdc->isInQueue(o1));
  491. ensure("is not in queue 2", !mdc->isInQueue(o2));
  492. ensure("is in queue 3", mdc->isInQueue(o3));
  493. ensure("is not in queue 4", !mdc->isInQueue(o4));
  494. ensure("post records", gPostRecords->size(), 1);
  495. ::pump_timers();
  496. // The second tick should process the third, emptying the queue
  497. ensure("is not in queue 3", !mdc->isInQueue(o3));
  498. ensure("post records", gPostRecords->size(), 2);
  499. ensure("queue empty", mdc->isEmpty());
  500. }
  501. ensure("refcount of o1", o1->getNumRefs(), 1);
  502. ensure("refcount of o2", o2->getNumRefs(), 1);
  503. ensure("refcount of o3", o3->getNumRefs(), 1);
  504. ensure("refcount of o4", o4->getNumRefs(), 1);
  505. }
  506. //////////////////////////////////////////////////////////////////////////////////////////
  507. template<> template<>
  508. void mediadataclient_object_t::test<9>()
  509. {
  510. //
  511. // Test queue re-ordering
  512. //
  513. LOG_TEST(9);
  514. LLMediaDataClientObject::ptr_t o1 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_1,"40.0","true"));
  515. LLMediaDataClientObject::ptr_t o2 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_2,"30.0","true"));
  516. LLMediaDataClientObject::ptr_t o3 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_3,"20.0","true"));
  517. LLMediaDataClientObjectTest *object4 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_4,"10.0","true"));
  518. LLMediaDataClientObject::ptr_t o4 = object4;
  519. {
  520. LLPointer<LLObjectMediaDataClient> mdc = new LLObjectMediaDataClient(NO_PERIOD,NO_PERIOD);
  521. // queue up all 4 objects. They should now be in the queue in
  522. // order 1 through 4, with 4 being at the front of the queue
  523. mdc->fetchMedia(o1);
  524. mdc->fetchMedia(o2);
  525. mdc->fetchMedia(o3);
  526. mdc->fetchMedia(o4);
  527. int tick_num = 0;
  528. ensure(STR(tick_num) + ". is in queue 1", mdc->isInQueue(o1));
  529. ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2));
  530. ensure(STR(tick_num) + ". is in queue 3", mdc->isInQueue(o3));
  531. ensure(STR(tick_num) + ". is in queue 4", mdc->isInQueue(o4));
  532. ensure(STR(tick_num) + ". post records", gPostRecords->size(), 0);
  533. ::pump_timers();
  534. ++tick_num;
  535. // The first tick should remove the first one
  536. ensure(STR(tick_num) + ". is not in queue 1", !mdc->isInQueue(o1));
  537. ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2));
  538. ensure(STR(tick_num) + ". is in queue 3", mdc->isInQueue(o3));
  539. ensure(STR(tick_num) + ". is in queue 4", mdc->isInQueue(o4));
  540. ensure(STR(tick_num) + ". post records", gPostRecords->size(), 1);
  541. // Now, pretend that object 4 moved relative to the avatar such
  542. // that it is now closest
  543. object4->setMediaInterest(50.0);
  544. ::pump_timers();
  545. ++tick_num;
  546. // The second tick should still pick off item 2, but then re-sort
  547. // have picked off object 4
  548. ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2));
  549. ensure(STR(tick_num) + ". is in queue 3", mdc->isInQueue(o3));
  550. ensure(STR(tick_num) + ". is not in queue 4", !mdc->isInQueue(o4));
  551. ensure(STR(tick_num) + ". post records", gPostRecords->size(), 2);
  552. ::pump_timers();
  553. ++tick_num;
  554. // The third tick should pick off object 2
  555. ensure(STR(tick_num) + ". is not in queue 2", !mdc->isInQueue(o2));
  556. ensure(STR(tick_num) + ". is in queue 3", mdc->isInQueue(o3));
  557. ensure(STR(tick_num) + ". post records", gPostRecords->size(), 3);
  558. // The fourth tick should pick off object 3
  559. ::pump_timers();
  560. ++tick_num;
  561. ensure(STR(tick_num) + ". is not in queue 3", !mdc->isInQueue(o3));
  562. ensure(STR(tick_num) + ". post records", gPostRecords->size(), 4);
  563. ensure("queue empty", mdc->isEmpty());
  564. }
  565. ensure("refcount of o1", o1->getNumRefs(), 1);
  566. ensure("refcount of o2", o2->getNumRefs(), 1);
  567. ensure("refcount of o3", o3->getNumRefs(), 1);
  568. ensure("refcount of o4", o4->getNumRefs(), 1);
  569. }
  570. template<> template<>
  571. void mediadataclient_object_t::test<10>()
  572. {
  573. //
  574. // Test using the "round-robin" queue
  575. //
  576. LOG_TEST(10);
  577. LLMediaDataClientObject::ptr_t o1 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_1,"1.0","true"));
  578. LLMediaDataClientObject::ptr_t o2 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_2,"2.0","true"));
  579. LLMediaDataClientObject::ptr_t o3 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_3,"3.0","false"));
  580. LLMediaDataClientObject::ptr_t o4 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_4,"4.0","false"));
  581. {
  582. LLPointer<LLObjectMediaDataClient> mdc = new LLObjectMediaDataClient(NO_PERIOD,NO_PERIOD);
  583. // queue up all 4 objects. The first two should be in the sorted
  584. // queue [2 1], the second in the round-robin queue. The queues
  585. // are serviced interleaved, so we should expect:
  586. // 2, 3, 1, 4
  587. mdc->fetchMedia(o1);
  588. mdc->fetchMedia(o2);
  589. mdc->fetchMedia(o3);
  590. mdc->fetchMedia(o4);
  591. int tick_num = 0;
  592. // 0
  593. ensure(STR(tick_num) + ". is in queue 1", mdc->isInQueue(o1));
  594. ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2));
  595. ensure(STR(tick_num) + ". is in queue 3", mdc->isInQueue(o3));
  596. ensure(STR(tick_num) + ". is in queue 4", mdc->isInQueue(o4));
  597. ensure(STR(tick_num) + ". post records", gPostRecords->size(), 0);
  598. ::pump_timers();
  599. ++tick_num;
  600. // 1 The first tick should remove object 2
  601. ensure(STR(tick_num) + ". is in queue 1", mdc->isInQueue(o1));
  602. ensure(STR(tick_num) + ". is not in queue 2", !mdc->isInQueue(o2));
  603. ensure(STR(tick_num) + ". is in queue 3", mdc->isInQueue(o3));
  604. ensure(STR(tick_num) + ". is in queue 4", mdc->isInQueue(o4));
  605. ensure(STR(tick_num) + ". post records", gPostRecords->size(), 1);
  606. ensure(STR(tick_num) + ". post object id", (*gPostRecords)[0]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID_2));
  607. ::pump_timers();
  608. ++tick_num;
  609. // 2 The second tick should send object 3
  610. ensure(STR(tick_num) + ". is in queue 1", mdc->isInQueue(o1));
  611. ensure(STR(tick_num) + ". is not in queue 2", !mdc->isInQueue(o2));
  612. ensure(STR(tick_num) + ". is not in queue 3", !mdc->isInQueue(o3));
  613. ensure(STR(tick_num) + ". is in queue 4", mdc->isInQueue(o4));
  614. ensure(STR(tick_num) + ". post records", gPostRecords->size(), 2);
  615. ensure(STR(tick_num) + ". post object id", (*gPostRecords)[1]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID_3));
  616. ::pump_timers();
  617. ++tick_num;
  618. // 3 The third tick should remove object 1
  619. ensure(STR(tick_num) + ". is not in queue 1", !mdc->isInQueue(o1));
  620. ensure(STR(tick_num) + ". is not in queue 2", !mdc->isInQueue(o2));
  621. ensure(STR(tick_num) + ". is not in queue 3", !mdc->isInQueue(o3));
  622. ensure(STR(tick_num) + ". is in queue 4", mdc->isInQueue(o4));
  623. ensure(STR(tick_num) + ". post records", gPostRecords->size(), 3);
  624. ensure(STR(tick_num) + ". post object id", (*gPostRecords)[2]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID_1));
  625. ::pump_timers();
  626. ++tick_num;
  627. // 4 The fourth tick should send object 4
  628. ensure(STR(tick_num) + ". is not in queue 1", !mdc->isInQueue(o1));
  629. ensure(STR(tick_num) + ". is not in queue 2", !mdc->isInQueue(o2));
  630. ensure(STR(tick_num) + ". is not in queue 3", !mdc->isInQueue(o3));
  631. ensure(STR(tick_num) + ". is not in queue 4", !mdc->isInQueue(o4));
  632. ensure(STR(tick_num) + ". post records", gPostRecords->size(), 4);
  633. ensure(STR(tick_num) + ". post object id", (*gPostRecords)[3]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID_4));
  634. ::pump_timers();
  635. ++tick_num;
  636. // 5 The fifth tick should not change the state of anything.
  637. ensure(STR(tick_num) + ". is not in queue 1", !mdc->isInQueue(o1));
  638. ensure(STR(tick_num) + ". is not in queue 2", !mdc->isInQueue(o2));
  639. ensure(STR(tick_num) + ". is not in queue 3", !mdc->isInQueue(o3));
  640. ensure(STR(tick_num) + ". is not in queue 4", !mdc->isInQueue(o4));
  641. ensure(STR(tick_num) + ". post records", gPostRecords->size(), 4);
  642. ::pump_timers();
  643. // Whew....better be empty
  644. ensure("queue empty", mdc->isEmpty());
  645. }
  646. ensure("refcount of o1", o1->getNumRefs(), 1);
  647. ensure("refcount of o2", o2->getNumRefs(), 1);
  648. ensure("refcount of o3", o3->getNumRefs(), 1);
  649. ensure("refcount of o4", o4->getNumRefs(), 1);
  650. }
  651. template<> template<>
  652. void mediadataclient_object_t::test<11>()
  653. {
  654. //
  655. // Test LLMediaDataClient's destructor
  656. //
  657. LOG_TEST(11);
  658. LLMediaDataClientObject::ptr_t o = new LLMediaDataClientObjectTest(DATA);
  659. int num_refs_start = o->getNumRefs();
  660. {
  661. LLPointer<LLObjectMediaDataClient> mdc = new LLObjectMediaDataClient(NO_PERIOD,NO_PERIOD);
  662. mdc->fetchMedia(o);
  663. // must tick enough times to clear refcount of mdc
  664. ::pump_timers();
  665. }
  666. // Make sure everyone's destroyed properly
  667. ensure("REF COUNT", o->getNumRefs(), num_refs_start);
  668. }
  669. template<> template<>
  670. void mediadataclient_object_t::test<12>()
  671. {
  672. //
  673. // Test the "not interesting enough" call
  674. //
  675. LOG_TEST(12);
  676. LLMediaDataClientObjectTest *object1 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_1,"1.0","true"));
  677. LLMediaDataClientObject::ptr_t o1 = object1;
  678. LLMediaDataClientObject::ptr_t o2 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_2,"2.0","true"));
  679. LLMediaDataClientObject::ptr_t o3 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_3,"3.0","true"));
  680. LLMediaDataClientObject::ptr_t o4 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_4,"4.0","true"));
  681. {
  682. LLPointer<LLObjectMediaDataClient> mdc = new LLObjectMediaDataClient(NO_PERIOD,NO_PERIOD);
  683. // queue up all 4 objects. The first two are "interesting enough".
  684. // Firing the timer 4 times should therefore leave them.
  685. // Note that they should be sorted 4,3,2,1
  686. // Then, we'll make one "interesting enough", fire the timer a few
  687. // times, and make sure only it gets pulled off the queue
  688. gMinimumInterestLevel = 2.5;
  689. mdc->fetchMedia(o1);
  690. mdc->fetchMedia(o2);
  691. mdc->fetchMedia(o3);
  692. mdc->fetchMedia(o4);
  693. int tick_num = 0;
  694. // 0
  695. ensure(STR(tick_num) + ". is in queue 1", mdc->isInQueue(o1));
  696. ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2));
  697. ensure(STR(tick_num) + ". is in queue 3", mdc->isInQueue(o3));
  698. ensure(STR(tick_num) + ". is in queue 4", mdc->isInQueue(o4));
  699. ensure(STR(tick_num) + ". post records", gPostRecords->size(), 0);
  700. ::pump_timers();
  701. ++tick_num;
  702. // 1 The first tick should remove object 4
  703. ensure(STR(tick_num) + ". is in queue 1", mdc->isInQueue(o1));
  704. ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2));
  705. ensure(STR(tick_num) + ". is in queue 3", mdc->isInQueue(o3));
  706. ensure(STR(tick_num) + ". is not in queue 4", !mdc->isInQueue(o4));
  707. ensure(STR(tick_num) + ". post records", gPostRecords->size(), 1);
  708. ensure(STR(tick_num) + ". post object id", (*gPostRecords)[0]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID_4));
  709. ::pump_timers();
  710. ++tick_num;
  711. // 2 The second tick should send object 3
  712. ensure(STR(tick_num) + ". is in queue 1", mdc->isInQueue(o1));
  713. ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2));
  714. ensure(STR(tick_num) + ". is not in queue 3", !mdc->isInQueue(o3));
  715. ensure(STR(tick_num) + ". is not in queue 4", !mdc->isInQueue(o4));
  716. ensure(STR(tick_num) + ". post records", gPostRecords->size(), 2);
  717. ensure(STR(tick_num) + ". post object id", (*gPostRecords)[1]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID_3));
  718. ::pump_timers();
  719. ++tick_num;
  720. // 3 The third tick should not pull off anything
  721. ensure(STR(tick_num) + ". is in queue 1", mdc->isInQueue(o1));
  722. ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2));
  723. ensure(STR(tick_num) + ". is not in queue 3", !mdc->isInQueue(o3));
  724. ensure(STR(tick_num) + ". is not in queue 4", !mdc->isInQueue(o4));
  725. ensure(STR(tick_num) + ". post records", gPostRecords->size(), 2);
  726. ::pump_timers();
  727. ++tick_num;
  728. // 4 The fourth tick (for good measure) should not pull off anything
  729. ensure(STR(tick_num) + ". is in queue 1", mdc->isInQueue(o1));
  730. ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2));
  731. ensure(STR(tick_num) + ". is not in queue 3", !mdc->isInQueue(o3));
  732. ensure(STR(tick_num) + ". is not in queue 4", !mdc->isInQueue(o4));
  733. ensure(STR(tick_num) + ". post records", gPostRecords->size(), 2);
  734. // Okay, now futz with object 1's interest, such that it is now
  735. // "interesting enough"
  736. object1->setMediaInterest((F64)5.0);
  737. // This should sort so that the queue is now [1 2]
  738. ::pump_timers();
  739. ++tick_num;
  740. // 5 The fifth tick should now identify objects 3 and 4 as no longer
  741. // needing "updating", and remove them from the queue
  742. ensure(STR(tick_num) + ". is not in queue 1", !mdc->isInQueue(o1));
  743. ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2));
  744. ensure(STR(tick_num) + ". is not in queue 3", !mdc->isInQueue(o3));
  745. ensure(STR(tick_num) + ". is not in queue 4", !mdc->isInQueue(o4));
  746. ensure(STR(tick_num) + ". post records", gPostRecords->size(), 3);
  747. ensure(STR(tick_num) + ". post object id", (*gPostRecords)[2]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID_1));
  748. ::pump_timers();
  749. ++tick_num;
  750. // 6 The sixth tick should not pull off anything
  751. ensure(STR(tick_num) + ". is not in queue 1", !mdc->isInQueue(o1));
  752. ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2));
  753. ensure(STR(tick_num) + ". is not in queue 3", !mdc->isInQueue(o3));
  754. ensure(STR(tick_num) + ". is not in queue 4", !mdc->isInQueue(o4));
  755. ensure(STR(tick_num) + ". post records", gPostRecords->size(), 3);
  756. ::pump_timers();
  757. ++tick_num;
  758. // Whew....better NOT be empty ... o2 should still be there
  759. ensure("queue not empty", !mdc->isEmpty());
  760. // But, we need to clear the queue, or else we won't destroy MDC...
  761. // this is a strange interplay between the queue timer and the MDC
  762. mdc->removeFromQueue(o2);
  763. // tick
  764. ::pump_timers();
  765. }
  766. ensure("refcount of o1", o1->getNumRefs(), 1);
  767. ensure("refcount of o2", o2->getNumRefs(), 1);
  768. ensure("refcount of o3", o3->getNumRefs(), 1);
  769. ensure("refcount of o4", o4->getNumRefs(), 1);
  770. }
  771. template<> template<>
  772. void mediadataclient_object_t::test<13>()
  773. {
  774. //
  775. // Test supression of redundant navigates.
  776. //
  777. LOG_TEST(13);
  778. LLMediaDataClientObject::ptr_t o1 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_1,"1.0","true"));
  779. {
  780. LLPointer<LLObjectMediaNavigateClient> mdc = new LLObjectMediaNavigateClient(NO_PERIOD,NO_PERIOD);
  781. const char *TEST_URL = "http://foo.example.com";
  782. const char *TEST_URL_2 = "http://example.com";
  783. mdc->navigate(o1, 0, TEST_URL);
  784. mdc->navigate(o1, 1, TEST_URL);
  785. mdc->navigate(o1, 0, TEST_URL_2);
  786. mdc->navigate(o1, 1, TEST_URL_2);
  787. // This should add two requests to the queue, one for face 0 of the object and one for face 1.
  788. ensure("before pump: 1 is in queue", mdc->isInQueue(o1));
  789. ::pump_timers();
  790. ensure("after first pump: 1 is in queue", mdc->isInQueue(o1));
  791. ::pump_timers();
  792. ensure("after second pump: 1 is not in queue", !mdc->isInQueue(o1));
  793. ensure("first post has correct url", (*gPostRecords)[0]["body"][LLMediaEntry::CURRENT_URL_KEY].asString(), std::string(TEST_URL_2));
  794. ensure("second post has correct url", (*gPostRecords)[1]["body"][LLMediaEntry::CURRENT_URL_KEY].asString(), std::string(TEST_URL_2));
  795. }
  796. }
  797. }