PageRenderTime 57ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/indra/test/io.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 1597 lines | 1285 code | 118 blank | 194 comment | 18 complexity | 9f244e082b7266502a853b67c4f227e5 MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file io.cpp
  3. * @author Phoenix
  4. * @date 2005-10-02
  5. * @brief Tests for io classes and helpers
  6. *
  7. * $LicenseInfo:firstyear=2005&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 <iterator>
  31. #include "apr_pools.h"
  32. #include "llbuffer.h"
  33. #include "llbufferstream.h"
  34. #include "lliosocket.h"
  35. #include "llioutil.h"
  36. #include "llmemorystream.h"
  37. #include "llpipeutil.h"
  38. #include "llpumpio.h"
  39. #include "llsd.h"
  40. #include "llsdrpcclient.h"
  41. #include "llsdrpcserver.h"
  42. #include "llsdserialize.h"
  43. #include "lluuid.h"
  44. #include "llinstantmessage.h"
  45. namespace tut
  46. {
  47. struct heap_buffer_data
  48. {
  49. heap_buffer_data() : mBuffer(NULL) {}
  50. ~heap_buffer_data() { if(mBuffer) delete mBuffer; }
  51. LLHeapBuffer* mBuffer;
  52. };
  53. typedef test_group<heap_buffer_data> heap_buffer_test;
  54. typedef heap_buffer_test::object heap_buffer_object;
  55. tut::heap_buffer_test thb("heap_buffer");
  56. template<> template<>
  57. void heap_buffer_object::test<1>()
  58. {
  59. const S32 BUF_SIZE = 100;
  60. mBuffer = new LLHeapBuffer(BUF_SIZE);
  61. ensure_equals("empty buffer capacity", mBuffer->capacity(), BUF_SIZE);
  62. const S32 SEGMENT_SIZE = 50;
  63. LLSegment segment;
  64. mBuffer->createSegment(0, SEGMENT_SIZE, segment);
  65. ensure_equals("used buffer capacity", mBuffer->capacity(), BUF_SIZE);
  66. }
  67. template<> template<>
  68. void heap_buffer_object::test<2>()
  69. {
  70. const S32 BUF_SIZE = 10;
  71. mBuffer = new LLHeapBuffer(BUF_SIZE);
  72. LLSegment segment;
  73. mBuffer->createSegment(0, BUF_SIZE, segment);
  74. ensure("segment is in buffer", mBuffer->containsSegment(segment));
  75. ensure_equals("buffer consumed", mBuffer->bytesLeft(), 0);
  76. bool created;
  77. created = mBuffer->createSegment(0, 0, segment);
  78. ensure("Create zero size segment fails", !created);
  79. created = mBuffer->createSegment(0, BUF_SIZE, segment);
  80. ensure("Create segment fails", !created);
  81. }
  82. template<> template<>
  83. void heap_buffer_object::test<3>()
  84. {
  85. const S32 BUF_SIZE = 10;
  86. mBuffer = new LLHeapBuffer(BUF_SIZE);
  87. LLSegment segment;
  88. mBuffer->createSegment(0, BUF_SIZE, segment);
  89. ensure("segment is in buffer", mBuffer->containsSegment(segment));
  90. ensure_equals("buffer consumed", mBuffer->bytesLeft(), 0);
  91. bool reclaimed = mBuffer->reclaimSegment(segment);
  92. ensure("buffer reclaimed.", reclaimed);
  93. ensure_equals("buffer available", mBuffer->bytesLeft(), BUF_SIZE);
  94. bool created;
  95. created = mBuffer->createSegment(0, 0, segment);
  96. ensure("Create zero size segment fails", !created);
  97. created = mBuffer->createSegment(0, BUF_SIZE, segment);
  98. ensure("Create another segment succeeds", created);
  99. }
  100. template<> template<>
  101. void heap_buffer_object::test<4>()
  102. {
  103. const S32 BUF_SIZE = 10;
  104. const S32 SEGMENT_SIZE = 4;
  105. mBuffer = new LLHeapBuffer(BUF_SIZE);
  106. LLSegment seg1;
  107. mBuffer->createSegment(0, SEGMENT_SIZE, seg1);
  108. ensure("segment is in buffer", mBuffer->containsSegment(seg1));
  109. LLSegment seg2;
  110. mBuffer->createSegment(0, SEGMENT_SIZE, seg2);
  111. ensure("segment is in buffer", mBuffer->containsSegment(seg2));
  112. LLSegment seg3;
  113. mBuffer->createSegment(0, SEGMENT_SIZE, seg3);
  114. ensure("segment is in buffer", mBuffer->containsSegment(seg3));
  115. ensure_equals("segment is truncated", seg3.size(), 2);
  116. LLSegment seg4;
  117. bool created;
  118. created = mBuffer->createSegment(0, SEGMENT_SIZE, seg4);
  119. ensure("Create segment fails", !created);
  120. bool reclaimed;
  121. reclaimed = mBuffer->reclaimSegment(seg1);
  122. ensure("buffer reclaim succeed.", reclaimed);
  123. ensure_equals("no buffer available", mBuffer->bytesLeft(), 0);
  124. reclaimed = mBuffer->reclaimSegment(seg2);
  125. ensure("buffer reclaim succeed.", reclaimed);
  126. ensure_equals("buffer reclaimed", mBuffer->bytesLeft(), 0);
  127. reclaimed = mBuffer->reclaimSegment(seg3);
  128. ensure("buffer reclaim succeed.", reclaimed);
  129. ensure_equals("buffer reclaimed", mBuffer->bytesLeft(), BUF_SIZE);
  130. created = mBuffer->createSegment(0, SEGMENT_SIZE, seg1);
  131. ensure("segment is in buffer", mBuffer->containsSegment(seg1));
  132. ensure("Create segment succeds", created);
  133. }
  134. }
  135. namespace tut
  136. {
  137. struct buffer_data
  138. {
  139. LLBufferArray mBuffer;
  140. };
  141. typedef test_group<buffer_data> buffer_test;
  142. typedef buffer_test::object buffer_object;
  143. tut::buffer_test tba("buffer_array");
  144. template<> template<>
  145. void buffer_object::test<1>()
  146. {
  147. const char HELLO_WORLD[] = "hello world";
  148. const S32 str_len = strlen(HELLO_WORLD);
  149. LLChannelDescriptors ch = mBuffer.nextChannel();
  150. mBuffer.append(ch.in(), (U8*)HELLO_WORLD, str_len);
  151. S32 count = mBuffer.countAfter(ch.in(), NULL);
  152. ensure_equals("total append size", count, str_len);
  153. LLBufferArray::segment_iterator_t it = mBuffer.beginSegment();
  154. U8* first = (*it).data();
  155. count = mBuffer.countAfter(ch.in(), first);
  156. ensure_equals("offset append size", count, str_len - 1);
  157. }
  158. template<> template<>
  159. void buffer_object::test<2>()
  160. {
  161. const char HELLO_WORLD[] = "hello world";
  162. const S32 str_len = strlen(HELLO_WORLD); /* Flawfinder: ignore */
  163. LLChannelDescriptors ch = mBuffer.nextChannel();
  164. mBuffer.append(ch.in(), (U8*)HELLO_WORLD, str_len);
  165. mBuffer.append(ch.in(), (U8*)HELLO_WORLD, str_len);
  166. S32 count = mBuffer.countAfter(ch.in(), NULL);
  167. ensure_equals("total append size", count, 2 * str_len);
  168. LLBufferArray::segment_iterator_t it = mBuffer.beginSegment();
  169. U8* first = (*it).data();
  170. count = mBuffer.countAfter(ch.in(), first);
  171. ensure_equals("offset append size", count, (2 * str_len) - 1);
  172. }
  173. template<> template<>
  174. void buffer_object::test<3>()
  175. {
  176. const char ONE[] = "one";
  177. const char TWO[] = "two";
  178. std::string expected(ONE);
  179. expected.append(TWO);
  180. LLChannelDescriptors ch = mBuffer.nextChannel();
  181. mBuffer.append(ch.in(), (U8*)ONE, 3);
  182. mBuffer.append(ch.in(), (U8*)TWO, 3);
  183. char buffer[255]; /* Flawfinder: ignore */
  184. S32 len = 6;
  185. mBuffer.readAfter(ch.in(), NULL, (U8*)buffer, len);
  186. ensure_equals(len, 6);
  187. buffer[len] = '\0';
  188. std::string actual(buffer);
  189. ensure_equals("read", actual, expected);
  190. }
  191. template<> template<>
  192. void buffer_object::test<4>()
  193. {
  194. const char ONE[] = "one";
  195. const char TWO[] = "two";
  196. std::string expected(ONE);
  197. expected.append(TWO);
  198. LLChannelDescriptors ch = mBuffer.nextChannel();
  199. mBuffer.append(ch.in(), (U8*)TWO, 3);
  200. mBuffer.prepend(ch.in(), (U8*)ONE, 3);
  201. char buffer[255]; /* Flawfinder: ignore */
  202. S32 len = 6;
  203. mBuffer.readAfter(ch.in(), NULL, (U8*)buffer, len);
  204. ensure_equals(len, 6);
  205. buffer[len] = '\0';
  206. std::string actual(buffer);
  207. ensure_equals("read", actual, expected);
  208. }
  209. template<> template<>
  210. void buffer_object::test<5>()
  211. {
  212. const char ONE[] = "one";
  213. const char TWO[] = "two";
  214. std::string expected("netwo");
  215. LLChannelDescriptors ch = mBuffer.nextChannel();
  216. mBuffer.append(ch.in(), (U8*)TWO, 3);
  217. mBuffer.prepend(ch.in(), (U8*)ONE, 3);
  218. char buffer[255]; /* Flawfinder: ignore */
  219. S32 len = 5;
  220. LLBufferArray::segment_iterator_t it = mBuffer.beginSegment();
  221. U8* addr = (*it).data();
  222. mBuffer.readAfter(ch.in(), addr, (U8*)buffer, len);
  223. ensure_equals(len, 5);
  224. buffer[len] = '\0';
  225. std::string actual(buffer);
  226. ensure_equals("read", actual, expected);
  227. }
  228. template<> template<>
  229. void buffer_object::test<6>()
  230. {
  231. std::string request("The early bird catches the worm.");
  232. std::string response("If you're a worm, sleep late.");
  233. std::ostringstream expected;
  234. expected << "ContentLength: " << response.length() << "\r\n\r\n"
  235. << response;
  236. LLChannelDescriptors ch = mBuffer.nextChannel();
  237. mBuffer.append(ch.in(), (U8*)request.c_str(), request.length());
  238. mBuffer.append(ch.out(), (U8*)response.c_str(), response.length());
  239. S32 count = mBuffer.countAfter(ch.out(), NULL);
  240. std::ostringstream header;
  241. header << "ContentLength: " << count << "\r\n\r\n";
  242. std::string head(header.str());
  243. mBuffer.prepend(ch.out(), (U8*)head.c_str(), head.length());
  244. char buffer[1024]; /* Flawfinder: ignore */
  245. S32 len = response.size() + head.length();
  246. ensure_equals("same length", len, (S32)expected.str().length());
  247. mBuffer.readAfter(ch.out(), NULL, (U8*)buffer, len);
  248. buffer[len] = '\0';
  249. std::string actual(buffer);
  250. ensure_equals("threaded writes", actual, expected.str());
  251. }
  252. template<> template<>
  253. void buffer_object::test<7>()
  254. {
  255. const S32 LINE_COUNT = 3;
  256. std::string lines[LINE_COUNT] =
  257. {
  258. std::string("GET /index.htm HTTP/1.0\r\n"),
  259. std::string("User-Agent: Wget/1.9.1\r\n"),
  260. std::string("Host: localhost:8008\r\n")
  261. };
  262. std::string text;
  263. S32 i;
  264. for(i = 0; i < LINE_COUNT; ++i)
  265. {
  266. text.append(lines[i]);
  267. }
  268. LLChannelDescriptors ch = mBuffer.nextChannel();
  269. mBuffer.append(ch.in(), (U8*)text.c_str(), text.length());
  270. const S32 BUFFER_LEN = 1024;
  271. char buf[BUFFER_LEN];
  272. S32 len;
  273. U8* last = NULL;
  274. std::string last_line;
  275. for(i = 0; i < LINE_COUNT; ++i)
  276. {
  277. len = BUFFER_LEN;
  278. last = mBuffer.readAfter(ch.in(), last, (U8*)buf, len);
  279. char* newline = strchr((char*)buf, '\n');
  280. S32 offset = -((len - 1) - (newline - buf));
  281. ++newline;
  282. *newline = '\0';
  283. last_line.assign(buf);
  284. std::ostringstream message;
  285. message << "line reads in line[" << i << "]";
  286. ensure_equals(message.str().c_str(), last_line, lines[i]);
  287. last = mBuffer.seek(ch.in(), last, offset);
  288. }
  289. }
  290. template<> template<>
  291. void buffer_object::test<8>()
  292. {
  293. LLChannelDescriptors ch = mBuffer.nextChannel();
  294. mBuffer.append(ch.in(), (U8*)"1", 1);
  295. LLBufferArray buffer;
  296. buffer.append(ch.in(), (U8*)"2", 1);
  297. mBuffer.takeContents(buffer);
  298. mBuffer.append(ch.in(), (U8*)"3", 1);
  299. S32 count = mBuffer.countAfter(ch.in(), NULL);
  300. ensure_equals("buffer size", count, 3);
  301. U8* temp = new U8[count];
  302. mBuffer.readAfter(ch.in(), NULL, temp, count);
  303. ensure("buffer content", (0 == memcmp(temp, (void*)"123", 3)));
  304. delete[] temp;
  305. }
  306. template<> template<>
  307. void buffer_object::test<9>()
  308. {
  309. LLChannelDescriptors ch = mBuffer.nextChannel();
  310. mBuffer.append(ch.in(), (U8*)"1", 1);
  311. S32 capacity = mBuffer.capacity();
  312. ensure("has capacity", capacity > 0);
  313. U8* temp = new U8[capacity - 1];
  314. mBuffer.append(ch.in(), temp, capacity - 1);
  315. capacity = mBuffer.capacity();
  316. ensure("has capacity when full", capacity > 0);
  317. S32 used = mBuffer.countAfter(ch.in(), NULL);
  318. ensure_equals("used equals capacity", used, capacity);
  319. LLBufferArray::segment_iterator_t iter = mBuffer.beginSegment();
  320. while(iter != mBuffer.endSegment())
  321. {
  322. mBuffer.eraseSegment(iter++);
  323. }
  324. used = mBuffer.countAfter(ch.in(), NULL);
  325. ensure_equals("used is zero", used, 0);
  326. S32 capacity2 = mBuffer.capacity();
  327. ensure_equals("capacity the same after erase", capacity2, capacity);
  328. mBuffer.append(ch.in(), temp, capacity - 1);
  329. capacity2 = mBuffer.capacity();
  330. ensure_equals("capacity the same after append", capacity2, capacity);
  331. delete[] temp;
  332. }
  333. #if 0
  334. template<> template<>
  335. void buffer_object::test<9>()
  336. {
  337. char buffer[1024]; /* Flawfinder: ignore */
  338. S32 size = sprintf(buffer,
  339. "%d|%d|%s|%s|%s|%s|%s|%x|%x|%x|%x|%x|%s|%s|%d|%d|%x",
  340. 7,
  341. 7,
  342. "Hang Glider INFO",
  343. "18e84d1e-04a4-4c0d-8cb6-6c73477f0a9a",
  344. "0e346d8b-4433-4d66-a6b0-fd37083abc4c",
  345. "0e346d8b-4433-4d66-a6b0-fd37083abc4c",
  346. "00000000-0000-0000-0000-000000000000",
  347. 0x7fffffff,
  348. 0x7fffffff,
  349. 0,
  350. 0,
  351. 0x7fffffff,
  352. "69e0d357-2e7c-8990-a2bc-7f61c868e5a3",
  353. "2004-06-04 16:09:17 note card",
  354. 0,
  355. 10,
  356. 0) + 1;
  357. //const char* expected = "7|7|Hang Glider INFO|18e84d1e-04a4-4c0d-8cb6-6c73477f0a9a|0e346d8b-4433-4d66-a6b0-fd37083abc4c|0e346d8b-4433-4d66-a6b0-fd37083abc4c|00000000-0000-0000-0000-000000000000|7fffffff|7fffffff|0|0|7fffffff|69e0d357-2e7c-8990-a2bc-7f61c868e5a3|2004-06-04 16:09:17 note card|0|10|0\0";
  358. LLSD* bin_bucket = LLIMInfo::buildSDfrombuffer((U8*)buffer,size);
  359. char post_buffer[1024];
  360. U32 post_size;
  361. LLIMInfo::getBinaryBucket(bin_bucket,(U8*)post_buffer,post_size);
  362. ensure_equals("Buffer sizes",size,(S32)post_size);
  363. ensure("Buffer content",!strcmp(buffer,post_buffer));
  364. }
  365. #endif
  366. /*
  367. template<> template<>
  368. void buffer_object::test<>()
  369. {
  370. }
  371. */
  372. }
  373. namespace tut
  374. {
  375. struct buffer_and_stream_data
  376. {
  377. LLBufferArray mBuffer;
  378. };
  379. typedef test_group<buffer_and_stream_data> bas_test;
  380. typedef bas_test::object bas_object;
  381. tut::bas_test tbs("buffer_stream");
  382. template<> template<>
  383. void bas_object::test<1>()
  384. {
  385. const char HELLO_WORLD[] = "hello world";
  386. const S32 str_len = strlen(HELLO_WORLD); /* Flawfinder: ignore */
  387. LLChannelDescriptors ch = mBuffer.nextChannel();
  388. LLBufferStream str(ch, &mBuffer);
  389. mBuffer.append(ch.in(), (U8*)HELLO_WORLD, str_len);
  390. std::string hello;
  391. std::string world;
  392. str >> hello >> world;
  393. ensure_equals("first word", hello, std::string("hello"));
  394. ensure_equals("second word", world, std::string("world"));
  395. }
  396. template<> template<>
  397. void bas_object::test<2>()
  398. {
  399. std::string part1("Eat my shor");
  400. std::string part2("ts ho");
  401. std::string part3("mer");
  402. std::string ignore("ignore me");
  403. LLChannelDescriptors ch = mBuffer.nextChannel();
  404. LLBufferStream str(ch, &mBuffer);
  405. mBuffer.append(ch.in(), (U8*)part1.c_str(), part1.length());
  406. mBuffer.append(ch.in(), (U8*)part2.c_str(), part2.length());
  407. mBuffer.append(ch.out(), (U8*)ignore.c_str(), ignore.length());
  408. mBuffer.append(ch.in(), (U8*)part3.c_str(), part3.length());
  409. std::string eat;
  410. std::string my;
  411. std::string shorts;
  412. std::string homer;
  413. str >> eat >> my >> shorts >> homer;
  414. ensure_equals("word1", eat, std::string("Eat"));
  415. ensure_equals("word2", my, std::string("my"));
  416. ensure_equals("word3", shorts, std::string("shorts"));
  417. ensure_equals("word4", homer, std::string("homer"));
  418. }
  419. template<> template<>
  420. void bas_object::test<3>()
  421. {
  422. std::string part1("junk in ");
  423. std::string part2("the trunk");
  424. const S32 CHANNEL = 0;
  425. mBuffer.append(CHANNEL, (U8*)part1.c_str(), part1.length());
  426. mBuffer.append(CHANNEL, (U8*)part2.c_str(), part2.length());
  427. U8* last = 0;
  428. const S32 BUF_LEN = 128;
  429. char buf[BUF_LEN];
  430. S32 len = 11;
  431. last = mBuffer.readAfter(CHANNEL, last, (U8*)buf, len);
  432. buf[len] = '\0';
  433. std::string actual(buf);
  434. ensure_equals("first read", actual, std::string("junk in the"));
  435. last = mBuffer.seek(CHANNEL, last, -6);
  436. len = 12;
  437. last = mBuffer.readAfter(CHANNEL, last, (U8*)buf, len);
  438. buf[len] = '\0';
  439. actual.assign(buf);
  440. ensure_equals("seek and read", actual, std::string("in the trunk"));
  441. }
  442. template<> template<>
  443. void bas_object::test<4>()
  444. {
  445. std::string phrase("zippity do da!");
  446. const S32 CHANNEL = 0;
  447. mBuffer.append(CHANNEL, (U8*)phrase.c_str(), phrase.length());
  448. const S32 BUF_LEN = 128;
  449. char buf[BUF_LEN];
  450. S32 len = 7;
  451. U8* last = mBuffer.readAfter(CHANNEL, NULL, (U8*)buf, len);
  452. mBuffer.splitAfter(last);
  453. LLBufferArray::segment_iterator_t it = mBuffer.beginSegment();
  454. LLBufferArray::segment_iterator_t end = mBuffer.endSegment();
  455. std::string first((char*)((*it).data()), (*it).size());
  456. ensure_equals("first part", first, std::string("zippity"));
  457. ++it;
  458. std::string second((char*)((*it).data()), (*it).size());
  459. ensure_equals("second part", second, std::string(" do da!"));
  460. ++it;
  461. ensure("iterators equal", (it == end));
  462. }
  463. template<> template<>
  464. void bas_object::test<5>()
  465. {
  466. LLChannelDescriptors ch = mBuffer.nextChannel();
  467. LLBufferStream str(ch, &mBuffer);
  468. std::string h1("hello");
  469. std::string h2(", how are you doing?");
  470. std::string expected(h1);
  471. expected.append(h2);
  472. str << h1 << h2;
  473. str.flush();
  474. const S32 BUF_LEN = 128;
  475. char buf[BUF_LEN];
  476. S32 actual_len = BUF_LEN;
  477. S32 expected_len = h1.size() + h2.size();
  478. (void) mBuffer.readAfter(ch.out(), NULL, (U8*)buf, actual_len);
  479. ensure_equals("streamed size", actual_len, expected_len);
  480. buf[actual_len] = '\0';
  481. std::string actual(buf);
  482. ensure_equals("streamed to buf", actual, expected);
  483. }
  484. template<> template<>
  485. void bas_object::test<6>()
  486. {
  487. LLChannelDescriptors ch = mBuffer.nextChannel();
  488. LLBufferStream bstr(ch, &mBuffer);
  489. std::ostringstream ostr;
  490. std::vector<LLUUID> ids;
  491. LLUUID id;
  492. for(int i = 0; i < 5; ++i)
  493. {
  494. id.generate();
  495. ids.push_back(id);
  496. }
  497. bstr << "SELECT concat(u.username, ' ', l.name) "
  498. << "FROM user u, user_last_name l "
  499. << "WHERE u.last_name_id = l.last_name_id"
  500. << " AND u.agent_id IN ('";
  501. ostr << "SELECT concat(u.username, ' ', l.name) "
  502. << "FROM user u, user_last_name l "
  503. << "WHERE u.last_name_id = l.last_name_id"
  504. << " AND u.agent_id IN ('";
  505. std::copy(
  506. ids.begin(),
  507. ids.end(),
  508. std::ostream_iterator<LLUUID>(bstr, "','"));
  509. std::copy(
  510. ids.begin(),
  511. ids.end(),
  512. std::ostream_iterator<LLUUID>(ostr, "','"));
  513. bstr.seekp(-2, std::ios::cur);
  514. ostr.seekp(-2, std::ios::cur);
  515. bstr << ") ";
  516. ostr << ") ";
  517. bstr.flush();
  518. const S32 BUF_LEN = 512;
  519. char buf[BUF_LEN]; /* Flawfinder: ignore */
  520. S32 actual_len = BUF_LEN;
  521. (void) mBuffer.readAfter(ch.out(), NULL, (U8*)buf, actual_len);
  522. buf[actual_len] = '\0';
  523. std::string actual(buf);
  524. std::string expected(ostr.str());
  525. ensure_equals("size of string in seek",actual.size(),expected.size());
  526. ensure_equals("seek in ostream", actual, expected);
  527. }
  528. template<> template<>
  529. void bas_object::test<7>()
  530. {
  531. LLChannelDescriptors ch = mBuffer.nextChannel();
  532. LLBufferStream bstr(ch, &mBuffer);
  533. bstr << "1";
  534. bstr.flush();
  535. S32 count = mBuffer.countAfter(ch.out(), NULL);
  536. ensure_equals("buffer size 1", count, 1);
  537. LLBufferArray buffer;
  538. buffer.append(ch.out(), (U8*)"2", 1);
  539. mBuffer.takeContents(buffer);
  540. count = mBuffer.countAfter(ch.out(), NULL);
  541. ensure_equals("buffer size 2", count, 2);
  542. bstr << "3";
  543. bstr.flush();
  544. count = mBuffer.countAfter(ch.out(), NULL);
  545. ensure_equals("buffer size 3", count, 3);
  546. U8* temp = new U8[count];
  547. mBuffer.readAfter(ch.out(), NULL, temp, count);
  548. ensure("buffer content", (0 == memcmp(temp, (void*)"123", 3)));
  549. delete[] temp;
  550. }
  551. template<> template<>
  552. void bas_object::test<8>()
  553. {
  554. LLChannelDescriptors ch = mBuffer.nextChannel();
  555. LLBufferStream ostr(ch, &mBuffer);
  556. typedef std::vector<U8> buf_t;
  557. typedef std::vector<buf_t> actual_t;
  558. actual_t actual;
  559. buf_t source;
  560. bool need_comma = false;
  561. ostr << "[";
  562. S32 total_size = 1;
  563. for(S32 i = 2000; i < 2003; ++i)
  564. {
  565. if(need_comma)
  566. {
  567. ostr << ",";
  568. ++total_size;
  569. }
  570. need_comma = true;
  571. srand(69 + i); /* Flawfinder: ignore */
  572. S32 size = rand() % 1000 + 1000;
  573. std::generate_n(
  574. std::back_insert_iterator<buf_t>(source),
  575. size,
  576. rand);
  577. actual.push_back(source);
  578. ostr << "b(" << size << ")\"";
  579. total_size += 8;
  580. ostr.write((const char*)(&source[0]), size);
  581. total_size += size;
  582. source.clear();
  583. ostr << "\"";
  584. ++total_size;
  585. }
  586. ostr << "]";
  587. ++total_size;
  588. ostr.flush();
  589. // now that we have a bunch of data on a stream, parse it all.
  590. ch = mBuffer.nextChannel();
  591. S32 count = mBuffer.countAfter(ch.in(), NULL);
  592. ensure_equals("size of buffer", count, total_size);
  593. LLBufferStream istr(ch, &mBuffer);
  594. LLSD data;
  595. count = LLSDSerialize::fromNotation(data, istr, total_size);
  596. ensure("sd parsed", data.isDefined());
  597. for(S32 j = 0; j < 3; ++j)
  598. {
  599. std::ostringstream name;
  600. LLSD child(data[j]);
  601. name << "found buffer " << j;
  602. ensure(name.str(), child.isDefined());
  603. source = child.asBinary();
  604. name.str("");
  605. name << "buffer " << j << " size";
  606. ensure_equals(name.str().c_str(), source.size(), actual[j].size());
  607. name.str("");
  608. name << "buffer " << j << " contents";
  609. ensure(
  610. name.str(),
  611. (0 == memcmp(&source[0], &actual[j][0], source.size())));
  612. }
  613. }
  614. template<> template<>
  615. void bas_object::test<9>()
  616. {
  617. LLChannelDescriptors ch = mBuffer.nextChannel();
  618. LLBufferStream ostr(ch, &mBuffer);
  619. typedef std::vector<U8> buf_t;
  620. buf_t source;
  621. bool need_comma = false;
  622. ostr << "{";
  623. S32 total_size = 1;
  624. for(S32 i = 1000; i < 3000; ++i)
  625. {
  626. if(need_comma)
  627. {
  628. ostr << ",";
  629. ++total_size;
  630. }
  631. need_comma = true;
  632. ostr << "'" << i << "':";
  633. total_size += 7;
  634. srand(69 + i); /* Flawfinder: ignore */
  635. S32 size = rand() % 1000 + 1000;
  636. std::generate_n(
  637. std::back_insert_iterator<buf_t>(source),
  638. size,
  639. rand);
  640. ostr << "b(" << size << ")\"";
  641. total_size += 8;
  642. ostr.write((const char*)(&source[0]), size);
  643. total_size += size;
  644. source.clear();
  645. ostr << "\"";
  646. ++total_size;
  647. }
  648. ostr << "}";
  649. ++total_size;
  650. ostr.flush();
  651. // now that we have a bunch of data on a stream, parse it all.
  652. ch = mBuffer.nextChannel();
  653. S32 count = mBuffer.countAfter(ch.in(), NULL);
  654. ensure_equals("size of buffer", count, total_size);
  655. LLBufferStream istr(ch, &mBuffer);
  656. LLSD data;
  657. count = LLSDSerialize::fromNotation(data, istr, total_size);
  658. ensure("sd parsed", data.isDefined());
  659. }
  660. template<> template<>
  661. void bas_object::test<10>()
  662. {
  663. //#if LL_WINDOWS && _MSC_VER >= 1400
  664. // skip_fail("Fails on VS2005 due to broken LLSDSerialize::fromNotation() parser.");
  665. //#endif
  666. const char LOGIN_STREAM[] = "{'method':'login', 'parameter': [ {"
  667. "'uri': 'sl-am:kellys.region.siva.lindenlab.com/location?start=url&px=128&py=128&pz=128&lx=0&ly=0&lz=0'}, "
  668. "{'version': i1}, {'texture_data': [ '61d724fb-ad79-f637-2186-5cf457560daa', '6e38b9be-b7cc-e77a-8aec-029a42b0b416', "
  669. "'a9073524-e89b-2924-ca6e-a81944109a1a', '658f18b5-5f1e-e593-f5d5-36c3abc7249a', '0cc799f4-8c99-6b91-bd75-b179b12429e2', "
  670. "'59fd9b64-8300-a425-aad8-2ffcbe9a49d2', '59fd9b64-8300-a425-aad8-2ffcbe9a49d2', '5748decc-f629-461c-9a36-a35a221fe21f', "
  671. "'b8fc9be2-26a6-6b47-690b-0e902e983484', 'a13ca0fe-3802-dc97-e79a-70d12171c724', 'dd9643cf-fd5d-0376-ed4a-b1cc646a97d5', "
  672. "'4ad13ae9-a112-af09-210a-cf9353a7a9e7', 'c228d1cf-4b5d-4ba8-84f4-899a0796aa97', 'c228d1cf-4b5d-4ba8-84f4-899a0796aa97', "
  673. "'c228d1cf-4b5d-4ba8-84f4-899a0796aa97', 'c228d1cf-4b5d-4ba8-84f4-899a0796aa97', 'c228d1cf-4b5d-4ba8-84f4-899a0796aa97', "
  674. "'5748decc-f629-461c-9a36-a35a221fe21f', 'c228d1cf-4b5d-4ba8-84f4-899a0796aa97', 'c228d1cf-4b5d-4ba8-84f4-899a0796aa97'],"
  675. "'session_id': '324cfa9f-fe5d-4d1c-a317-35f20a86a4d1','position': [ i128, i128, i128],'last_name': 'Linden','group_title': '-> !BLING! <-','group_name': 'test!','agent_access': 'M',"
  676. "'attachment_data': [ {'asset_id': 'aaede2b1-9955-09d4-5c93-2b557c778cf3','attachment_point': i6,'item_id': 'f3694abc-5122-db33-73d9-e0f4288dc2bf'}],"
  677. "'buddy_ids': [ '101358d5-469d-4b24-9b85-4dc3c05e635d', '1b00fec7-6265-4875-acac-80d9cfe9295c', '203ad6df-b522-491d-ba48-4e24eb57aeff', "
  678. "'22d4dcdb-aebb-47fa-b925-a871cc75ee48','27da3df5-1339-4463-80aa-40504ee3b3e5', '299d1720-b61f-4268-8c29-9614aa2d44c2', "
  679. "'2b048a24-2737-4994-9fa5-becc8e466253', '2cd5dc14-a853-49a4-be3c-a5a7178e37bc', '3de548e1-57be-cfea-2b78-83ae3ad95998', "
  680. "'3dee98e4-a6a3-4543-91c3-bbd528447ba7', '3e2d81a3-6263-6ffe-ad5c-8ce04bee07e9', '40e70b98-fed7-47f3-9700-1bce93f9350b', "
  681. "'50a9b68e-b5aa-4d35-9137-3cfebda0a15c', '54295571-9357-43ff-ae74-a83b5138160f', '6191e2d7-5f96-4856-bdab-af0f79f47ae4', "
  682. "'63e577d8-cd34-4235-a0a3-de0500133364', '79cfb666-4fd0-4af7-95df-fb7d96b4e24d', '8121c2f3-4a88-4c33-9899-8fc1273f47ee', "
  683. "'909da964-ef23-4f2a-ba13-f2a8cfd454b6','a2e76fcd-9360-4f6d-a924-000000000001', 'aaa6d664-527e-4d83-9cbb-7ef79ccc7cc8', "
  684. "'b79bfb6c-23be-49eb-b35b-30ff2f501b37', 'ba0d9c79-148c-4a79-8e3c-0665eebe2427', 'bc9bda98-57cd-498f-b993-4ff1ac9dec93', "
  685. "'c62d16f6-81cb-419d-9cac-e46dc394084d', 'd48f8fa7-2512-4fe5-80c8-c0a923412e07', 'd77e3e24-7e6c-4c3f-96d0-a1746337f8fb', "
  686. "'da615c63-a84b-4592-a3d6-a90dd3e92e6e', 'df47190a-7eb7-4aff-985f-2d1d3ad6c6e9', 'e3380196-72cd-499c-a2ba-caa180bd5fe4', "
  687. "'e937863f-f134-4207-803b-d6e686651d6c', 'efcdf98b-5269-45ef-ac7a-0671f09ea9d9'],"
  688. "'circuit_code': i124,'group_id': '8615c885-9cf0-bf0a-6e40-0c11462aa652','limited_to_estate': i1,'look_at': [ i0, i0, i0],"
  689. "'agent_id': '0e346d8b-4433-4d66-a6b0-fd37083abc4c','first_name': 'Kelly','start': 'url'}]}";
  690. LLChannelDescriptors ch = mBuffer.nextChannel();
  691. mBuffer.append(ch.out(), (U8*)LOGIN_STREAM, strlen(LOGIN_STREAM)); /* Flawfinder: ignore */
  692. ch = mBuffer.nextChannel();
  693. LLBufferStream istr(ch, &mBuffer);
  694. LLSD data;
  695. S32 count = LLSDSerialize::fromNotation(
  696. data,
  697. istr,
  698. mBuffer.count(ch.in()));
  699. ensure("parsed something", (count > 0));
  700. ensure("sd parsed", data.isDefined());
  701. ensure_equals("sd type", data.type(), LLSD::TypeMap);
  702. ensure("has method", data.has("method"));
  703. ensure("has parameter", data.has("parameter"));
  704. LLSD parameter = data["parameter"];
  705. ensure_equals("parameter is array", parameter.type(), LLSD::TypeArray);
  706. LLSD agent_params = parameter[2];
  707. std::string s_value;
  708. s_value = agent_params["last_name"].asString();
  709. ensure_equals("last name", s_value, std::string("Linden"));
  710. s_value = agent_params["first_name"].asString();
  711. ensure_equals("first name", s_value, std::string("Kelly"));
  712. s_value = agent_params["agent_access"].asString();
  713. ensure_equals("agent access", s_value, std::string("M"));
  714. s_value = agent_params["group_name"].asString();
  715. ensure_equals("group name", s_value, std::string("test!"));
  716. s_value = agent_params["group_title"].asString();
  717. ensure_equals("group title", s_value, std::string("-> !BLING! <-"));
  718. LLUUID agent_id("0e346d8b-4433-4d66-a6b0-fd37083abc4c");
  719. LLUUID id = agent_params["agent_id"];
  720. ensure_equals("agent id", id, agent_id);
  721. LLUUID session_id("324cfa9f-fe5d-4d1c-a317-35f20a86a4d1");
  722. id = agent_params["session_id"];
  723. ensure_equals("session id", id, session_id);
  724. LLUUID group_id ("8615c885-9cf0-bf0a-6e40-0c11462aa652");
  725. id = agent_params["group_id"];
  726. ensure_equals("group id", id, group_id);
  727. S32 i_val = agent_params["limited_to_estate"];
  728. ensure_equals("limited to estate", i_val, 1);
  729. i_val = agent_params["circuit_code"];
  730. ensure_equals("circuit code", i_val, 124);
  731. }
  732. template<> template<>
  733. void bas_object::test<11>()
  734. {
  735. std::string val = "{!'foo'@:#'bar'}";
  736. std::istringstream istr;
  737. istr.str(val);
  738. LLSD sd;
  739. S32 count = LLSDSerialize::fromNotation(sd, istr, val.size());
  740. ensure_equals("parser error return value", count, -1);
  741. ensure("data undefined", sd.isUndefined());
  742. }
  743. template<> template<>
  744. void bas_object::test<12>()
  745. {
  746. //#if LL_WINDOWS && _MSC_VER >= 1400
  747. // skip_fail("Fails on VS2005 due to broken LLSDSerialize::fromNotation() parser.");
  748. //#endif
  749. std::string val = "{!'foo':[i1,'hi',{@'bar'#:[$i2%,^'baz'&]*}+]=}";
  750. std::istringstream istr;
  751. istr.str(val);
  752. LLSD sd;
  753. S32 count = LLSDSerialize::fromNotation(sd, istr, val.size());
  754. ensure_equals("parser error return value", count, -1);
  755. ensure("data undefined", sd.isUndefined());
  756. }
  757. /*
  758. template<> template<>
  759. void bas_object::test<13>()
  760. {
  761. }
  762. template<> template<>
  763. void bas_object::test<14>()
  764. {
  765. }
  766. template<> template<>
  767. void bas_object::test<15>()
  768. {
  769. }
  770. */
  771. }
  772. namespace tut
  773. {
  774. class PumpAndChainTestData
  775. {
  776. protected:
  777. apr_pool_t* mPool;
  778. LLPumpIO* mPump;
  779. LLPumpIO::chain_t mChain;
  780. public:
  781. PumpAndChainTestData()
  782. {
  783. apr_pool_create(&mPool, NULL);
  784. mPump = new LLPumpIO(mPool);
  785. }
  786. ~PumpAndChainTestData()
  787. {
  788. mChain.clear();
  789. delete mPump;
  790. apr_pool_destroy(mPool);
  791. }
  792. };
  793. typedef test_group<PumpAndChainTestData> PumpAndChainTestGroup;
  794. typedef PumpAndChainTestGroup::object PumpAndChainTestObject;
  795. PumpAndChainTestGroup pumpAndChainTestGroup("pump_and_chain");
  796. template<> template<>
  797. void PumpAndChainTestObject::test<1>()
  798. {
  799. LLPipeStringExtractor* extractor = new LLPipeStringExtractor();
  800. mChain.push_back(LLIOPipe::ptr_t(new LLIOFlush));
  801. mChain.push_back(LLIOPipe::ptr_t(extractor));
  802. LLTimer timer;
  803. timer.setTimerExpirySec(100.0f);
  804. mPump->addChain(mChain, DEFAULT_CHAIN_EXPIRY_SECS);
  805. while(!extractor->done() && !timer.hasExpired())
  806. {
  807. mPump->pump();
  808. mPump->callback();
  809. }
  810. ensure("reading string finished", extractor->done());
  811. ensure_equals("string was empty", extractor->string(), "");
  812. }
  813. }
  814. /*
  815. namespace tut
  816. {
  817. struct double_construct
  818. {
  819. public:
  820. double_construct()
  821. {
  822. llinfos << "constructed" << llendl;
  823. }
  824. ~double_construct()
  825. {
  826. llinfos << "destroyed" << llendl;
  827. }
  828. };
  829. typedef test_group<double_construct> double_construct_test_group;
  830. typedef double_construct_test_group::object dc_test_object;
  831. double_construct_test_group dctest("double construct");
  832. template<> template<>
  833. void dc_test_object::test<1>()
  834. {
  835. ensure("test 1", true);
  836. }
  837. }
  838. */
  839. namespace tut
  840. {
  841. /**
  842. * @brief we want to test the pipes & pumps under bad conditions.
  843. */
  844. struct pipe_and_pump_fitness
  845. {
  846. public:
  847. enum
  848. {
  849. SERVER_LISTEN_PORT = 13050
  850. };
  851. pipe_and_pump_fitness()
  852. {
  853. LLFrameTimer::updateFrameTime();
  854. apr_pool_create(&mPool, NULL);
  855. mPump = new LLPumpIO(mPool);
  856. mSocket = LLSocket::create(
  857. mPool,
  858. LLSocket::STREAM_TCP,
  859. SERVER_LISTEN_PORT);
  860. }
  861. ~pipe_and_pump_fitness()
  862. {
  863. mSocket.reset();
  864. delete mPump;
  865. apr_pool_destroy(mPool);
  866. }
  867. protected:
  868. apr_pool_t* mPool;
  869. LLPumpIO* mPump;
  870. LLSocket::ptr_t mSocket;
  871. };
  872. typedef test_group<pipe_and_pump_fitness> fitness_test_group;
  873. typedef fitness_test_group::object fitness_test_object;
  874. fitness_test_group fitness("pipe and pump fitness");
  875. template<> template<>
  876. void fitness_test_object::test<1>()
  877. {
  878. lldebugs << "fitness_test_object::test<1>()" << llendl;
  879. // Set up the server
  880. //lldebugs << "fitness_test_object::test<1> - setting up server."
  881. // << llendl;
  882. LLPumpIO::chain_t chain;
  883. typedef LLCloneIOFactory<LLPipeStringInjector> emitter_t;
  884. emitter_t* emitter = new emitter_t(
  885. new LLPipeStringInjector("suckers never play me"));
  886. boost::shared_ptr<LLChainIOFactory> factory(emitter);
  887. LLIOServerSocket* server = new LLIOServerSocket(
  888. mPool,
  889. mSocket,
  890. factory);
  891. server->setResponseTimeout(SHORT_CHAIN_EXPIRY_SECS);
  892. chain.push_back(LLIOPipe::ptr_t(server));
  893. mPump->addChain(chain, NEVER_CHAIN_EXPIRY_SECS);
  894. // We need to tickle the pump a little to set up the listen()
  895. //lldebugs << "fitness_test_object::test<1> - initializing server."
  896. // << llendl;
  897. pump_loop(mPump, 0.1f);
  898. // Set up the client
  899. //lldebugs << "fitness_test_object::test<1> - connecting client."
  900. // << llendl;
  901. LLSocket::ptr_t client = LLSocket::create(mPool, LLSocket::STREAM_TCP);
  902. LLHost server_host("127.0.0.1", SERVER_LISTEN_PORT);
  903. bool connected = client->blockingConnect(server_host);
  904. ensure("Connected to server", connected);
  905. lldebugs << "connected" << llendl;
  906. // We have connected, since the socket reader does not block,
  907. // the first call to read data will return EAGAIN, so we need
  908. // to write something.
  909. chain.clear();
  910. chain.push_back(LLIOPipe::ptr_t(new LLPipeStringInjector("hi")));
  911. chain.push_back(LLIOPipe::ptr_t(new LLIOSocketWriter(client)));
  912. chain.push_back(LLIOPipe::ptr_t(new LLIONull));
  913. mPump->addChain(chain, 1.0f);
  914. // Now, the server should immediately send the data, but we'll
  915. // never read it. pump for a bit
  916. F32 elapsed = pump_loop(mPump, 2.0f);
  917. ensure("Did not take too long", (elapsed < 3.0f));
  918. }
  919. template<> template<>
  920. void fitness_test_object::test<2>()
  921. {
  922. lldebugs << "fitness_test_object::test<2>()" << llendl;
  923. // Set up the server
  924. LLPumpIO::chain_t chain;
  925. typedef LLCloneIOFactory<LLIOFuzz> emitter_t;
  926. emitter_t* emitter = new emitter_t(new LLIOFuzz(1000000));
  927. boost::shared_ptr<LLChainIOFactory> factory(emitter);
  928. LLIOServerSocket* server = new LLIOServerSocket(
  929. mPool,
  930. mSocket,
  931. factory);
  932. server->setResponseTimeout(SHORT_CHAIN_EXPIRY_SECS);
  933. chain.push_back(LLIOPipe::ptr_t(server));
  934. mPump->addChain(chain, NEVER_CHAIN_EXPIRY_SECS);
  935. // We need to tickle the pump a little to set up the listen()
  936. pump_loop(mPump, 0.1f);
  937. // Set up the client
  938. LLSocket::ptr_t client = LLSocket::create(mPool, LLSocket::STREAM_TCP);
  939. LLHost server_host("127.0.0.1", SERVER_LISTEN_PORT);
  940. bool connected = client->blockingConnect(server_host);
  941. ensure("Connected to server", connected);
  942. lldebugs << "connected" << llendl;
  943. // We have connected, since the socket reader does not block,
  944. // the first call to read data will return EAGAIN, so we need
  945. // to write something.
  946. chain.clear();
  947. chain.push_back(LLIOPipe::ptr_t(new LLPipeStringInjector("hi")));
  948. chain.push_back(LLIOPipe::ptr_t(new LLIOSocketWriter(client)));
  949. chain.push_back(LLIOPipe::ptr_t(new LLIONull));
  950. mPump->addChain(chain, SHORT_CHAIN_EXPIRY_SECS / 2.0f);
  951. // Now, the server should immediately send the data, but we'll
  952. // never read it. pump for a bit
  953. F32 elapsed = pump_loop(mPump, SHORT_CHAIN_EXPIRY_SECS * 2.0f);
  954. ensure("Did not take too long", (elapsed < 3.0f));
  955. }
  956. template<> template<>
  957. void fitness_test_object::test<3>()
  958. {
  959. lldebugs << "fitness_test_object::test<3>()" << llendl;
  960. // Set up the server
  961. LLPumpIO::chain_t chain;
  962. typedef LLCloneIOFactory<LLIOFuzz> emitter_t;
  963. emitter_t* emitter = new emitter_t(new LLIOFuzz(1000000));
  964. boost::shared_ptr<LLChainIOFactory> factory(emitter);
  965. LLIOServerSocket* server = new LLIOServerSocket(
  966. mPool,
  967. mSocket,
  968. factory);
  969. server->setResponseTimeout(SHORT_CHAIN_EXPIRY_SECS);
  970. chain.push_back(LLIOPipe::ptr_t(server));
  971. mPump->addChain(chain, NEVER_CHAIN_EXPIRY_SECS);
  972. // We need to tickle the pump a little to set up the listen()
  973. pump_loop(mPump, 0.1f);
  974. // Set up the client
  975. LLSocket::ptr_t client = LLSocket::create(mPool, LLSocket::STREAM_TCP);
  976. LLHost server_host("127.0.0.1", SERVER_LISTEN_PORT);
  977. bool connected = client->blockingConnect(server_host);
  978. ensure("Connected to server", connected);
  979. lldebugs << "connected" << llendl;
  980. // We have connected, since the socket reader does not block,
  981. // the first call to read data will return EAGAIN, so we need
  982. // to write something.
  983. chain.clear();
  984. chain.push_back(LLIOPipe::ptr_t(new LLPipeStringInjector("hi")));
  985. chain.push_back(LLIOPipe::ptr_t(new LLIOSocketWriter(client)));
  986. chain.push_back(LLIOPipe::ptr_t(new LLIONull));
  987. mPump->addChain(chain, SHORT_CHAIN_EXPIRY_SECS * 2.0f);
  988. // Now, the server should immediately send the data, but we'll
  989. // never read it. pump for a bit
  990. F32 elapsed = pump_loop(mPump, SHORT_CHAIN_EXPIRY_SECS * 2.0f + 1.0f);
  991. ensure("Did not take too long", (elapsed < 4.0f));
  992. }
  993. template<> template<>
  994. void fitness_test_object::test<4>()
  995. {
  996. lldebugs << "fitness_test_object::test<4>()" << llendl;
  997. // Set up the server
  998. LLPumpIO::chain_t chain;
  999. typedef LLCloneIOFactory<LLIOFuzz> emitter_t;
  1000. emitter_t* emitter = new emitter_t(new LLIOFuzz(1000000));
  1001. boost::shared_ptr<LLChainIOFactory> factory(emitter);
  1002. LLIOServerSocket* server = new LLIOServerSocket(
  1003. mPool,
  1004. mSocket,
  1005. factory);
  1006. server->setResponseTimeout(SHORT_CHAIN_EXPIRY_SECS + 1.80f);
  1007. chain.push_back(LLIOPipe::ptr_t(server));
  1008. mPump->addChain(chain, NEVER_CHAIN_EXPIRY_SECS);
  1009. // We need to tickle the pump a little to set up the listen()
  1010. pump_loop(mPump, 0.1f);
  1011. // Set up the client
  1012. LLSocket::ptr_t client = LLSocket::create(mPool, LLSocket::STREAM_TCP);
  1013. LLHost server_host("127.0.0.1", SERVER_LISTEN_PORT);
  1014. bool connected = client->blockingConnect(server_host);
  1015. ensure("Connected to server", connected);
  1016. lldebugs << "connected" << llendl;
  1017. // We have connected, since the socket reader does not block,
  1018. // the first call to read data will return EAGAIN, so we need
  1019. // to write something.
  1020. chain.clear();
  1021. chain.push_back(LLIOPipe::ptr_t(new LLPipeStringInjector("hi")));
  1022. chain.push_back(LLIOPipe::ptr_t(new LLIOSocketWriter(client)));
  1023. chain.push_back(LLIOPipe::ptr_t(new LLIONull));
  1024. mPump->addChain(chain, NEVER_CHAIN_EXPIRY_SECS);
  1025. // Now, the server should immediately send the data, but we'll
  1026. // never read it. pump for a bit
  1027. F32 elapsed = pump_loop(mPump, SHORT_CHAIN_EXPIRY_SECS + 3.0f);
  1028. ensure("Did not take too long", (elapsed < DEFAULT_CHAIN_EXPIRY_SECS));
  1029. }
  1030. template<> template<>
  1031. void fitness_test_object::test<5>()
  1032. {
  1033. // Set up the server
  1034. LLPumpIO::chain_t chain;
  1035. typedef LLCloneIOFactory<LLIOSleeper> sleeper_t;
  1036. sleeper_t* sleeper = new sleeper_t(new LLIOSleeper);
  1037. boost::shared_ptr<LLChainIOFactory> factory(sleeper);
  1038. LLIOServerSocket* server = new LLIOServerSocket(
  1039. mPool,
  1040. mSocket,
  1041. factory);
  1042. server->setResponseTimeout(1.0);
  1043. chain.push_back(LLIOPipe::ptr_t(server));
  1044. mPump->addChain(chain, NEVER_CHAIN_EXPIRY_SECS);
  1045. // We need to tickle the pump a little to set up the listen()
  1046. pump_loop(mPump, 0.1f);
  1047. U32 count = mPump->runningChains();
  1048. ensure_equals("server chain onboard", count, 1);
  1049. lldebugs << "** Server is up." << llendl;
  1050. // Set up the client
  1051. LLSocket::ptr_t client = LLSocket::create(mPool, LLSocket::STREAM_TCP);
  1052. LLHost server_host("127.0.0.1", SERVER_LISTEN_PORT);
  1053. bool connected = client->blockingConnect(server_host);
  1054. ensure("Connected to server", connected);
  1055. lldebugs << "connected" << llendl;
  1056. F32 elapsed = pump_loop(mPump,0.1f);
  1057. count = mPump->runningChains();
  1058. ensure_equals("server chain onboard", count, 2);
  1059. lldebugs << "** Client is connected." << llendl;
  1060. // We have connected, since the socket reader does not block,
  1061. // the first call to read data will return EAGAIN, so we need
  1062. // to write something.
  1063. chain.clear();
  1064. chain.push_back(LLIOPipe::ptr_t(new LLPipeStringInjector("hi")));
  1065. chain.push_back(LLIOPipe::ptr_t(new LLIOSocketWriter(client)));
  1066. chain.push_back(LLIOPipe::ptr_t(new LLIONull));
  1067. mPump->addChain(chain, 0.2f);
  1068. chain.clear();
  1069. // pump for a bit and make sure all 3 chains are running
  1070. elapsed = pump_loop(mPump,0.1f);
  1071. count = mPump->runningChains();
  1072. ensure_equals("client chain onboard", count, 3);
  1073. lldebugs << "** request should have been sent." << llendl;
  1074. // pump for long enough the the client socket closes, and the
  1075. // server socket should not be closed yet.
  1076. elapsed = pump_loop(mPump,0.2f);
  1077. count = mPump->runningChains();
  1078. ensure_equals("client chain timed out ", count, 2);
  1079. lldebugs << "** client chain should be closed." << llendl;
  1080. // At this point, the socket should be closed by the timeout
  1081. elapsed = pump_loop(mPump,1.0f);
  1082. count = mPump->runningChains();
  1083. ensure_equals("accepted socked close", count, 1);
  1084. lldebugs << "** Sleeper should have timed out.." << llendl;
  1085. }
  1086. }
  1087. namespace tut
  1088. {
  1089. struct rpc_server_data
  1090. {
  1091. class LLSimpleRPCResponse : public LLSDRPCResponse
  1092. {
  1093. public:
  1094. LLSimpleRPCResponse(LLSD* response) :
  1095. mResponsePtr(response)
  1096. {
  1097. }
  1098. ~LLSimpleRPCResponse() {}
  1099. virtual bool response(LLPumpIO* pump)
  1100. {
  1101. *mResponsePtr = mReturnValue;
  1102. return true;
  1103. }
  1104. virtual bool fault(LLPumpIO* pump)
  1105. {
  1106. *mResponsePtr = mReturnValue;
  1107. return false;
  1108. }
  1109. virtual bool error(LLPumpIO* pump)
  1110. {
  1111. ensure("LLSimpleRPCResponse::error()", false);
  1112. return false;
  1113. }
  1114. public:
  1115. LLSD* mResponsePtr;
  1116. };
  1117. class LLSimpleRPCClient : public LLSDRPCClient
  1118. {
  1119. public:
  1120. LLSimpleRPCClient(LLSD* response) :
  1121. mResponsePtr(response)
  1122. {
  1123. }
  1124. ~LLSimpleRPCClient() {}
  1125. void echo(const LLSD& parameter)
  1126. {
  1127. LLSimpleRPCResponse* resp;
  1128. resp = new LLSimpleRPCResponse(mResponsePtr);
  1129. static const std::string URI_NONE;
  1130. static const std::string METHOD_ECHO("echo");
  1131. call(URI_NONE, METHOD_ECHO, parameter, resp, EPBQ_CALLBACK);
  1132. }
  1133. public:
  1134. LLSD* mResponsePtr;
  1135. };
  1136. class LLSimpleRPCServer : public LLSDRPCServer
  1137. {
  1138. public:
  1139. LLSimpleRPCServer()
  1140. {
  1141. mMethods["echo"] = new mem_fn_t(
  1142. this,
  1143. &LLSimpleRPCServer::rpc_Echo);
  1144. }
  1145. ~LLSimpleRPCServer() {}
  1146. protected:
  1147. typedef LLSDRPCMethodCall<LLSimpleRPCServer> mem_fn_t;
  1148. ESDRPCSStatus rpc_Echo(
  1149. const LLSD& parameter,
  1150. const LLChannelDescriptors& channels,
  1151. LLBufferArray* data)
  1152. {
  1153. buildResponse(channels, data, parameter);
  1154. return ESDRPCS_DONE;
  1155. }
  1156. };
  1157. apr_pool_t* mPool;
  1158. LLPumpIO* mPump;
  1159. LLPumpIO::chain_t mChain;
  1160. LLSimpleRPCClient* mClient;
  1161. LLSD mResponse;
  1162. rpc_server_data() :
  1163. mPool(NULL),
  1164. mPump(NULL),
  1165. mClient(NULL)
  1166. {
  1167. apr_pool_create(&mPool, NULL);
  1168. mPump = new LLPumpIO(mPool);
  1169. mClient = new LLSimpleRPCClient(&mResponse);
  1170. mChain.push_back(LLIOPipe::ptr_t(mClient));
  1171. mChain.push_back(LLIOPipe::ptr_t(new LLFilterSD2XMLRPCRequest));
  1172. mChain.push_back(LLIOPipe::ptr_t(new LLFilterXMLRPCRequest2LLSD));
  1173. mChain.push_back(LLIOPipe::ptr_t(new LLSimpleRPCServer));
  1174. mChain.push_back(LLIOPipe::ptr_t(new LLFilterSD2XMLRPCResponse));
  1175. mChain.push_back(LLIOPipe::ptr_t(new LLFilterXMLRPCResponse2LLSD));
  1176. mChain.push_back(LLIOPipe::ptr_t(mClient));
  1177. }
  1178. ~rpc_server_data()
  1179. {
  1180. mChain.clear();
  1181. delete mPump;
  1182. mPump = NULL;
  1183. apr_pool_destroy(mPool);
  1184. mPool = NULL;
  1185. }
  1186. void pump_loop(const LLSD& request)
  1187. {
  1188. LLTimer timer;
  1189. timer.setTimerExpirySec(1.0f);
  1190. mClient->echo(request);
  1191. mPump->addChain(mChain, DEFAULT_CHAIN_EXPIRY_SECS);
  1192. while(mResponse.isUndefined() && !timer.hasExpired())
  1193. {
  1194. mPump->pump();
  1195. mPump->callback();
  1196. }
  1197. }
  1198. };
  1199. typedef test_group<rpc_server_data> rpc_server_test;
  1200. typedef rpc_server_test::object rpc_server_object;
  1201. tut::rpc_server_test rpc("rpc_server");
  1202. template<> template<>
  1203. void rpc_server_object::test<1>()
  1204. {
  1205. LLSD request;
  1206. request = 1;
  1207. pump_loop(request);
  1208. //llinfos << "request: " << *request << llendl;
  1209. //llinfos << "response: " << *mResponse << llendl;
  1210. ensure_equals("integer request response", mResponse.asInteger(), 1);
  1211. }
  1212. template<> template<>
  1213. void rpc_server_object::test<2>()
  1214. {
  1215. //#if LL_WINDOWS && _MSC_VER >= 1400
  1216. // skip_fail("Fails on VS2005 due to broken LLSDSerialize::fromNotation() parser.");
  1217. //#endif
  1218. std::string uri("sl-am:66.150.244.180:12035/location?start=region&px=70.9247&py=254.378&pz=38.7304&lx=-0.043753&ly=-0.999042&lz=0");
  1219. std::stringstream stream;
  1220. stream << "{'task_id':ucc706f2d-0b68-68f8-11a4-f1043ff35ca0}\n{\n\tname\tObject|\n\tpermissions 0\n}";
  1221. std::vector<U8> expected_binary;
  1222. expected_binary.resize(stream.str().size());
  1223. memcpy(&expected_binary[0], stream.str().c_str(), stream.str().size()); /* Flawfinder: ignore */
  1224. stream.str("");
  1225. stream << "[{'uri':'" << uri << "'}, {'version':i1}, "
  1226. << "{'agent_id':'3c115e51-04f4-523c-9fa6-98aff1034730', 'session_id':'2c585cec-038c-40b0-b42e-a25ebab4d132', 'circuit_code':i1075, 'start':'region', 'limited_to_estate':i1 'first_name':'Phoenix', 'last_name':'Linden', 'group_title':'', 'group_id':u00000000-0000-0000-0000-000000000000, 'position':[r70.9247,r254.378,r38.7304], 'look_at':[r-0.043753,r-0.999042,r0], 'granters':[ua2e76fcd-9360-4f6d-a924-000000000003], 'texture_data':['5e481e8a-58a6-fc34-6e61-c7a36095c07f', 'c39675f5-ca90-a304-bb31-42cdb803a132', '5c989edf-88d1-b2ac-b00b-5ed4bab8e368', '6522e74d-1660-4e7f-b601-6f48c1659a77', '7ca39b4c-bd19-4699-aff7-f93fd03d3e7b', '41c58177-5eb6-5aeb-029d-bc4093f3c130', '97b75473-8b93-9b25-2a11-035b9ae93195', '1c2d8d9b-90eb-89d4-dea8-c1ed83990614', '69ec543f-e27b-c07c-9094-a8be6300f274', 'c9f8b80f-c629-4633-04ee-c566ce9fea4b', '989cddba-7ab6-01ed-67aa-74accd2a2a65', '45e319b2-6a8c-fa5c-895b-1a7149b88aef', '5748decc-f629-461c-9a36-a35a221fe21f', 'c228d1cf-4b5d-4ba8-84f4-899a0796aa97', 'c228d1cf-4b5d-4ba8-84f4-899a0796aa97', '685fbe10-ab40-f065-0aec-726cc6dfd7a1', '406f98fd-9c89-1d52-5f39-e67d508c5ee5', '685fbe10-ab40-f065-0aec-726cc6dfd7a1', 'c228d1cf-4b5d-4ba8-84f4-899a0796aa97', 'c228d1cf-4b5d-4ba8-84f4-899a0796aa97'], "
  1227. << "'attachment_data':["
  1228. << "{'attachment_point':i2, 'item_id':'d6852c11-a74e-309a-0462-50533f1ef9b3', 'asset_id':'c69b29b1-8944-58ae-a7c5-2ca7b23e22fb'},"
  1229. << "{'attachment_point':i10, 'item_id':'ff852c22-a74e-309a-0462-50533f1ef900', 'asset_data':b(" << expected_binary.size() << ")\"";
  1230. stream.write((const char*)&expected_binary[0], expected_binary.size());
  1231. stream << "\"}"
  1232. << "]"
  1233. << "}]";
  1234. LLSD request;
  1235. S32 count = LLSDSerialize::fromNotation(
  1236. request,
  1237. stream,
  1238. stream.str().size());
  1239. ensure("parsed something", (count > 0));
  1240. pump_loop(request);
  1241. ensure_equals("return type", mResponse.type(), LLSD::TypeArray);
  1242. ensure_equals("return size", mResponse.size(), 3);
  1243. ensure_equals(
  1244. "uri parameter type",
  1245. mResponse[0].type(),
  1246. LLSD::TypeMap);
  1247. ensure_equals(
  1248. "uri type",
  1249. mResponse[0]["uri"].type(),
  1250. LLSD::TypeString);
  1251. ensure_equals("uri value", mResponse[0]["uri"].asString(), uri);
  1252. ensure_equals(
  1253. "version parameter type",
  1254. mResponse[1].type(),
  1255. LLSD::TypeMap);
  1256. ensure_equals(
  1257. "version type",
  1258. mResponse[1]["version"].type(),
  1259. LLSD::TypeInteger);
  1260. ensure_equals(
  1261. "version value",
  1262. mResponse[1]["version"].asInteger(),
  1263. 1);
  1264. ensure_equals("agent params type", mResponse[2].type(), LLSD::TypeMap);
  1265. LLSD attachment_data = mResponse[2]["attachment_data"];
  1266. ensure("attachment data exists", attachment_data.isDefined());
  1267. ensure_equals(
  1268. "attachment type",
  1269. attachment_data.type(),
  1270. LLSD::TypeArray);
  1271. ensure_equals(
  1272. "attachment type 0",
  1273. attachment_data[0].type(),
  1274. LLSD::TypeMap);
  1275. ensure_equals(
  1276. "attachment type 1",
  1277. attachment_data[1].type(),
  1278. LLSD::TypeMap);
  1279. ensure_equals("attachment size 1", attachment_data[1].size(), 3);
  1280. ensure_equals(
  1281. "asset data type",
  1282. attachment_data[1]["asset_data"].type(),
  1283. LLSD::TypeBinary);
  1284. std::vector<U8> actual_binary;
  1285. actual_binary = attachment_data[1]["asset_data"].asBinary();
  1286. ensure_equals(
  1287. "binary data size",
  1288. actual_binary.size(),
  1289. expected_binary.size());
  1290. ensure(
  1291. "binary data",
  1292. (0 == memcmp(
  1293. &actual_binary[0],
  1294. &expected_binary[0],
  1295. expected_binary.size())));
  1296. }
  1297. template<> template<>
  1298. void rpc_server_object::test<3>()
  1299. {
  1300. //#if LL_WINDOWS && _MSC_VER >= 1400
  1301. // skip_fail("Fails on VS2005 due to broken LLSDSerialize::fromNotation() parser.");
  1302. //#endif
  1303. std::string uri("sl-am:66.150.244.180:12035/location?start=region&px=70.9247&py=254.378&pz=38.7304&lx=-0.043753&ly=-0.999042&lz=0");
  1304. LLBufferArray buffer;
  1305. LLChannelDescriptors buffer_channels = buffer.nextChannel();
  1306. LLBufferStream stream(buffer_channels, &buffer);
  1307. stream << "[{'uri':'" << uri << "'}, {'version':i1}, "
  1308. << "{'agent_id':'3c115e51-04f4-523c-9fa6-98aff1034730', 'session_id':'2c585cec-038c-40b0-b42e-a25ebab4d132', 'circuit_code':i1075, 'start':'region', 'limited_to_estate':i1 'first_name':'Phoenix', 'last_name':'Linden', 'group_title':'', 'group_id':u00000000-0000-0000-0000-000000000000, 'position':[r70.9247,r254.378,r38.7304], 'look_at':[r-0.043753,r-0.999042,r0], 'granters':[ua2e76fcd-9360-4f6d-a924-000000000003], 'texture_data':['5e481e8a-58a6-fc34-6e61-c7a36095c07f', 'c39675f5-ca90-a304-bb31-42cdb803a132', '5c989edf-88d1-b2ac-b00b-5ed4bab8e368', '6522e74d-1660-4e7f-b601-6f48c1659a77', '7ca39b4c-bd19-4699-aff7-f93fd03d3e7b', '41c58177-5eb6-5aeb-029d-bc4093f3c130', '97b75473-8b93-9b25-2a11-035b9ae93195', '1c2d8d9b-90eb-89d4-dea8-c1ed83990614', '69ec543f-e27b-c07c-9094-a8be6300f274', 'c9f8b80f-c629-4633-04ee-c566ce9fea4b', '989cddba-7ab6-01ed-67aa-74accd2a2a65', '45e319b2-6a8c-fa5c-895b-1a7149b88aef', '5748decc-f629-461c-9a36-a35a221fe21f', 'c228d1cf-4b5d-4ba8-84f4-899a0796aa97', 'c228d1cf-4b5d-4ba8-84f4-899a0796aa97', '685fbe10-ab40-f065-0aec-726cc6dfd7a1', '406f98fd-9c89-1d52-5f39-e67d508c5ee5', '685fbe10-ab40-f065-0aec-726cc6dfd7a1', 'c228d1cf-4b5d-4ba8-84f4-899a0796aa97', 'c228d1cf-4b5d-4ba8-84f4-899a0796aa97'], "
  1309. << "'attachment_data':["
  1310. << "{'attachment_point':i2, 'item_id':'d6852c11-a74e-309a-0462-50533f1ef9b3', 'asset_id':'c69b29b1-8944-58ae-a7c5-2ca7b23e22fb'},";
  1311. std::stringstream tmp_str;
  1312. tmp_str << "{'task_id':ucc706f2d-0b68-68f8-11a4-f1043ff35ca0}\n{\n\tname\tObject|\n\tpermissions 0\n}";
  1313. std::vector<U8> expected_binary;
  1314. expected_binary.resize(tmp_str.str().size());
  1315. memcpy( /* Flawfinder: ignore */
  1316. &expected_binary[0],
  1317. tmp_str.str().c_str(),
  1318. tmp_str.str().size());
  1319. LLBufferArray attachment_buffer;
  1320. LLChannelDescriptors attach_channels = attachment_buffer.nextChannel();
  1321. LLBufferStream attach_stream(attach_channels, &attachment_buffer);
  1322. attach_stream.write((const char*)&expected_binary[0], expected_binary.size());
  1323. attach_stream.flush();
  1324. S32 len = attachment_buffer.countAfter(attach_channels.out(), NULL);
  1325. stream << "{'attachment_point':i10, 'item_id':'ff852c22-a74e-309a-0462-50533f1ef900', 'asset_data':b(" << len << ")\"";
  1326. stream.flush();
  1327. buffer.takeContents(attachment_buffer);
  1328. stream << "\"}]}]";
  1329. stream.flush();
  1330. LLChannelDescriptors read_channel = buffer.nextChannel();
  1331. LLBufferStream read_stream(read_channel, &buffer);
  1332. LLSD request;
  1333. S32 count = LLSDSerialize::fromNotation(
  1334. request,
  1335. read_stream,
  1336. buffer.count(read_channel.in()));
  1337. ensure("parsed something", (count > 0));
  1338. ensure("deserialized", request.isDefined());
  1339. // do the rpc round trip
  1340. pump_loop(request);
  1341. ensure_equals("return type", mResponse.type(), LLSD::TypeArray);
  1342. ensure_equals("return size", mResponse.size(), 3);
  1343. LLSD child = mResponse[0];
  1344. ensure("uri map exists", child.isDefined());
  1345. ensure_equals("uri parameter type", child.type(), LLSD::TypeMap);
  1346. ensure("uri string exists", child.has("uri"));
  1347. ensure_equals("uri type", child["uri"].type(), LLSD::TypeString);
  1348. ensure_equals("uri value", child["uri"].asString(), uri);
  1349. child = mResponse[1];
  1350. ensure("version map exists", child.isDefined());
  1351. ensure_equals("version param type", child.type(), LLSD::TypeMap);
  1352. ensure_equals(
  1353. "version type",
  1354. child["version"].type(),
  1355. LLSD::TypeInteger);
  1356. ensure_equals("version value", child["version"].asInteger(), 1);
  1357. child = mResponse[2];
  1358. ensure("agent params map exists", child.isDefined());
  1359. ensure_equals("agent params type", child.type(), LLSD::TypeMap);
  1360. child = child["attachment_data"];
  1361. ensure("attachment data exists", child.isDefined());
  1362. ensure_equals("attachment type", child.type(), LLSD::TypeArray);
  1363. LLSD attachment = child[0];
  1364. ensure_equals("attachment type 0", attachment.type(), LLSD::TypeMap);
  1365. attachment = child[1];
  1366. ensure_equals("attachment type 1", attachment.type(), LLSD::TypeMap);
  1367. ensure_equals("attachment size 1", attachment.size(), 3);
  1368. ensure_equals(
  1369. "asset data type",
  1370. attachment["asset_data"].type(),
  1371. LLSD::TypeBinary);
  1372. std::vector<U8> actual_binary = attachment["asset_data"].asBinary();
  1373. ensure_equals(
  1374. "binary data size",
  1375. actual_binary.size(),
  1376. expected_binary.size());
  1377. ensure(
  1378. "binary data",
  1379. (0 == memcmp(
  1380. &actual_binary[0],
  1381. &expected_binary[0],
  1382. expected_binary.size())));
  1383. }
  1384. template<> template<>
  1385. void rpc_server_object::test<4>()
  1386. {
  1387. std::string message("parcel '' is naughty.");
  1388. std::stringstream str;
  1389. str << "{'message':'" << LLSDNotationFormatter::escapeString(message)
  1390. << "'}";
  1391. LLSD request;
  1392. S32 count = LLSDSerialize::fromNotation(
  1393. request,
  1394. str,
  1395. str.str().size());
  1396. ensure_equals("parse count", count, 2);
  1397. ensure_equals("request type", request.type(), LLSD::TypeMap);
  1398. pump_loop(request);
  1399. ensure("valid response", mResponse.isDefined());
  1400. ensure_equals("response type", mResponse.type(), LLSD::TypeMap);
  1401. std::string actual = mResponse["message"].asString();
  1402. ensure_equals("message contents", actual, message);
  1403. }
  1404. template<> template<>
  1405. void rpc_server_object::test<5>()
  1406. {
  1407. // test some of the problem cases with llsdrpc over xmlrpc -
  1408. // for example:
  1409. // * arrays are auto-converted to parameter lists, thus, this
  1410. // becomes one parameter.
  1411. // * undef goes over the wire as false (this might not be a good idea)
  1412. // * uuids are converted to string.
  1413. std::string val = "[{'failures':!,'successfuls':[u3c115e51-04f4-523c-9fa6-98aff1034730]}]";
  1414. std::istringstream istr;
  1415. istr.str(val);
  1416. LLSD sd;
  1417. LLSDSerialize::fromNotation(sd, istr, val.size());
  1418. pump_loop(sd);
  1419. ensure("valid response", mResponse.isDefined());
  1420. ensure_equals("parsed type", mResponse.type(), LLSD::TypeMap);
  1421. ensure_equals("parsed size", mResponse.size(), 2);
  1422. LLSD failures = mResponse["failures"];
  1423. ensure_equals("no failures.", failures.asBoolean(), false);
  1424. LLSD success = mResponse["successfuls"];
  1425. ensure_equals("success type", success.type(), LLSD::TypeArray);
  1426. ensure_equals("success size", success.size(), 1);
  1427. ensure_equals(
  1428. "success instance type",
  1429. success[0].type(),
  1430. LLSD::TypeString);
  1431. }
  1432. /*
  1433. template<> template<>
  1434. void rpc_server_object::test<5>()
  1435. {
  1436. std::string expected("\xf3");//\xffsomething");
  1437. LLSD* request = LLSD::createString(expected);
  1438. pump_loop(request);
  1439. std::string actual;
  1440. mResponse->getString(actual);
  1441. if(actual != expected)
  1442. {
  1443. //llwarns << "iteration " << i << llendl;
  1444. std::ostringstream e_str;
  1445. std::string::iterator iter = expected.begin();
  1446. std::string::iterator end = expected.end();
  1447. for(; iter != end; ++iter)
  1448. {
  1449. e_str << (S32)((U8)(*iter)) << " ";
  1450. }
  1451. e_str << std::endl;
  1452. llsd_serialize_string(e_str, expected);
  1453. llwarns << "expected size: " << expected.size() << llendl;
  1454. llwarns << "expected: " << e_str.str() << llendl;
  1455. std::ostringstream a_str;
  1456. iter = actual.begin();
  1457. end = actual.end();
  1458. for(; iter != end; ++iter)
  1459. {
  1460. a_str << (S32)((U8)(*iter)) << " ";
  1461. }
  1462. a_str << std::endl;
  1463. llsd_serialize_string(a_str, actual);
  1464. llwarns << "actual size: " << actual.size() << llendl;
  1465. llwarns << "actual: " << a_str.str() << llendl;
  1466. }
  1467. ensure_equals("binary string request response", actual, expected);
  1468. delete request;
  1469. }
  1470. template<> template<>
  1471. void rpc_server_object::test<5>()
  1472. {
  1473. }
  1474. */
  1475. }
  1476. /*
  1477. 'asset_data':b(12100)"{'task_id':ucc706f2d-0b68-68f8-11a4-f1043ff35ca0}\n{\n\tname\tObject|\n\tpermissions 0\n\t{\n\t\tbase_mask\t7fffffff\n\t\towner_mask\t7fffffff\n\t\tgroup_mask\t00000000\n\t\teveryone_mask\t00000000\n\t\tnext_owner_mask\t7fffffff\n\t\tcreator_id\t13fd9595-a47b-4d64-a5fb-6da645f038e0\n\t\towner_id\t3c115e51-04f4-523c-9fa6-98aff1034730\n\t\tlast_owner_id\t3c115e51-04f4-523c-9fa6-98aff1034730\n\t\tgroup_id\t00000000-0000-0000-0000-000000000000\n\t}\n\tlocal_id\t217444921\n\ttotal_crc\t323\n\ttype\t2\n\ttask_valid\t2\n\ttravel_access\t13\n\tdisplayopts\t2\n\tdisplaytype\tv\n\tpos\t-0.368634403\t0.00781063363\t-0.569040775\n\toldpos\t150.117996\t25.8658009\t8.19664001\n\trotation\t-0.06293071806430816650390625\t-0.6995697021484375\t-0.7002241611480712890625\t0.1277817934751510620117188\n\tchildpos\t-0.00499999989\t-0.0359999985\t0.307999998\n\tchildrot\t-0.515492737293243408203125\t-0.46601200103759765625\t0.529055416584014892578125\t0.4870323240756988525390625\n\tscale\t0.074629\t0.289956\t0.01\n\tsit_offset\t0\t0\t0\n\tcamera_eye_offset\t0\t0\t0\n\tcamera_at_offset\t0\t0\t0\n\tsit_quat\t0\t0\t0\t1\n\tsit_hint\t0\n\tstate\t160\n\tmaterial\t3\n\tsoundid\t00000000-0000-0000-0000-000000000000\n\tsoundgain\t0\n\tsoundradius\t0\n\tsoundflags\t0\n\ttextcolor\t0 0 0 1\n\tselected\t0\n\tselector\t00000000-0000-0000-0000-000000000000\n\tusephysics\t0\n\trotate_x\t1\n\trotate_y\t1\n\trotate_z\t1\n\tphantom\t0\n\tremote_script_access_pin\t0\n\tvolume_detect\t0\n\tblock_grabs\t0\n\tdie_at_edge\t0\n\treturn_at_edge\t0\n\ttemporary\t0\n\tsandbox\t0\n\tsandboxhome\t0\t0\t0\n\tshape 0\n\t{\n\t\tpath 0\n\t\t{\n\t\t\tcurve\t16\n\t\t\tbegin\t0\n\t\t\tend\t1\n\t\t\tscale_x\t1\n\t\t\tscale_y\t1\n\t\t\tshear_x\t0\n\t\t\tshear_y\t0\n\t\t\ttwist\t0\n\t\t\ttwist_begin\t0\n\t\t\tradius_offset\t0\n\t\t\ttaper_x\t0\n\t\t\ttaper_y\t0\n\t\t\trevolutions\t1\n\t\t\tskew\t0\n\t\t}\n\t\tprofile 0\n\t\t{\n\t\t\tcurve\t1\n\t\t\tbegin\t0\n\t\t\tend\t1\n\t\t\thollow\t0\n\t\t}\n\t}\n\tfaces\t6\n\t{\n\t\timageid\tddde1ffc-678b-3cda-1748-513086bdf01b\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\tf54a0c32-3cd1-d49a-5b4f-7b792bebc204\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\tf54a0c32-3cd1-d49a-5b4f-7b792bebc204\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\tf54a0c32-3cd1-d49a-5b4f-7b792bebc204\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\tf54a0c32-3cd1-d49a-5b4f-7b792bebc204\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\tddde1ffc-678b-3cda-1748-513086bdf01b\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t-1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\tps_next_crc\t1\n\tgpw_bias\t1\n\tip\t0\n\tcomplete\tTRUE\n\tdelay\t50000\n\tnextstart\t0\n\tbirthtime\t1061088050622956\n\treztime\t1094866329019785\n\tparceltime\t1133568981980596\n\ttax_rate\t1.00084\n\tscratchpad\t0\n\t{\n\t\n\t}\n\tsale_info\t0\n\t{\n\t\tsale_type\tnot\n\t\tsale_price\t10\n\t}\n\tcorrect_family_id\t00000000-0000-0000-0000-000000000000\n\thas_rezzed\t0\n\tpre_link_base_mask\t7fffffff\n\tlinked \tchild\n\tdefault_pay_price\t-2\t1\t5\t10\t20\n}\n{'task_id':u61fa7364-e151-0597-774c-523312dae31b}\n{\n\tname\tObject|\n\tpermissions 0\n\t{\n\t\tbase_mask\t7fffffff\n\t\towner_mask\t7fffffff\n\t\tgroup_mask\t00000000\n\t\teveryone_mask\t00000000\n\t\tnext_owner_mask\t7fffffff\n\t\tcreator_id\t13fd9595-a47b-4d64-a5fb-6da645f038e0\n\t\towner_id\t3c115e51-04f4-523c-9fa6-98aff1034730\n\t\tlast_owner_id\t3c115e51-04f4-523c-9fa6-98aff1034730\n\t\tgroup_id\t00000000-0000-0000-0000-000000000000\n\t}\n\tlocal_id\t217444922\n\ttotal_crc\t324\n\ttype\t2\n\ttask_valid\t2\n\ttravel_access\t13\n\tdisplayopts\t2\n\tdisplaytype\tv\n\tpos\t-0.367110789\t0.00780026987\t-0.566269755\n\toldpos\t150.115005\t25.8479004\t8.18669987\n\trotation\t0.47332942485809326171875\t-0.380102097988128662109375\t-0.5734078884124755859375\t0.550168216228485107421875\n\tchildpos\t-0.00499999989\t-0.0370000005\t0.305000007\n\tchildrot\t-0.736649334430694580078125\t-0.03042060509324073791503906\t-0.02784589119255542755126953\t0.67501628398895263671875\n\tscale\t0.074629\t0.289956\t0.01\n\tsit_offset\t0\t0\t0\n\tcamera_eye_offset\t0\t0\t0\n\tcamera_at_offset\t0\t0\t0\n\tsit_quat\t0\t0\t0\t1\n\tsit_hint\t0\n\tstate\t160\n\tmaterial\t3\n\tsoundid\t00000000-0000-0000-0000-000000000000\n\tsoundgain\t0\n\tsoundradius\t0\n\tsoundflags\t0\n\ttextcolor\t0 0 0 1\n\tselected\t0\n\tselector\t00000000-0000-0000-0000-000000000000\n\tusephysics\t0\n\trotate_x\t1\n\trotate_y\t1\n\trotate_z\t1\n\tphantom\t0\n\tremote_script_access_pin\t0\n\tvolume_detect\t0\n\tblock_grabs\t0\n\tdie_at_edge\t0\n\treturn_at_edge\t0\n\ttemporary\t0\n\tsandbox\t0\n\tsandboxhome\t0\t0\t0\n\tshape 0\n\t{\n\t\tpath 0\n\t\t{\n\t\t\tcurve\t16\n\t\t\tbegin\t0\n\t\t\tend\t1\n\t\t\tscale_x\t1\n\t\t\tscale_y\t1\n\t\t\tshear_x\t0\n\t\t\tshear_y\t0\n\t\t\ttwist\t0\n\t\t\ttwist_begin\t0\n\t\t\tradius_offset\t0\n\t\t\ttaper_x\t0\n\t\t\ttaper_y\t0\n\t\t\trevolutions\t1\n\t\t\tskew\t0\n\t\t}\n\t\tprofile 0\n\t\t{\n\t\t\tcurve\t1\n\t\t\tbegin\t0\n\t\t\tend\t1\n\t\t\thollow\t0\n\t\t}\n\t}\n\tfaces\t6\n\t{\n\t\timageid\tddde1ffc-678b-3cda-1748-513086bdf01b\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\tf54a0c32-3cd1-d49a-5b4f-7b792bebc204\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\tf54a0c32-3cd1-d49a-5b4f-7b792bebc204\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\tf54a0c32-3cd1-d49a-5b4f-7b792bebc204\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\tf54a0c32-3cd1-d49a-5b4f-7b792bebc204\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\tddde1ffc-678b-3cda-1748-513086bdf01b\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t-1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\tps_next_crc\t1\n\tgpw_bias\t1\n\tip\t0\n\tcomplete\tTRUE\n\tdelay\t50000\n\tnextstart\t0\n\tbirthtime\t1061087839248891\n\treztime\t1094866329020800\n\tparceltime\t1133568981981983\n\ttax_rate\t1.00084\n\tscratchpad\t0\n\t{\n\t\n\t}\n\tsale_info\t0\n\t{\n\t\tsale_type\tnot\n\t\tsale_price\t10\n\t}\n\tcorrect_family_id\t00000000-0000-0000-0000-000000000000\n\thas_rezzed\t0\n\tpre_link_base_mask\t7fffffff\n\tlinked \tchild\n\tdefault_pay_price\t-2\t1\t5\t10\t20\n}\n{'task_id':ub8d68643-7dd8-57af-0d24-8790032aed0c}\n{\n\tname\tObject|\n\tpermissions 0\n\t{\n\t\tbase_mask\t7fffffff\n\t\towner_mask\t7fffffff\n\t\tgroup_mask\t00000000\n\t\teveryone_mask\t00000000\n\t\tnext_owner_mask\t7fffffff\n\t\tcreator_id\t13fd9595-a47b-4d64-a5fb-6da645f038e0\n\t\towner_id\t3c115e51-04f4-523c-9fa6-98aff1034730\n\t\tlast_owner_id\t3c115e51-04f4-523c-9fa6-98aff1034730\n\t\tgroup_id\t00000000-0000-0000-0000-000000000000\n\t}\n\tlocal_id\t217444923\n\ttotal_crc\t235\n\ttype\t2\n\ttask_valid\t2\n\ttravel_access\t13\n\tdisplayopts\t2\n\tdisplaytype\tv\n\tpos\t-0.120029509\t-0.00284469454\t-0.0302077383\n\toldpos\t150.710999\t25.8584995\t8.19172001\n\trotation\t0.145459949970245361328125\t-0.1646589934825897216796875\t0.659558117389678955078125\t-0.718826770782470703125\n\tchildpos\t0\t-0.182999998\t-0.26699999\n\tchildrot\t0.991444766521453857421875\t3.271923924330621957778931e-05\t-0.0002416197530692443251609802\t0.1305266767740249633789062\n\tscale\t0.0382982\t0.205957\t0.368276\n\tsit_offset\t0\t0\t0\n\tcamera_eye_offset\t0\t0\t0\n\tcamera_at_offset\t0\t0\t0\n\tsit_quat\t0\t0\t0\t1\n\tsit_hint\t0\n\tstate\t160\n\tmaterial\t3\n\tsoundid\t00000000-0000-0000-0000-000000000000\n\tsoundgain\t0\n\tsoundradius\t0\n\tsoundflags\t0\n\ttextcolor\t0 0 0 1\n\tselected\t0\n\tselector\t00000000-0000-0000-0000-000000000000\n\tusephysics\t0\n\trotate_x\t1\n\trotate_y\t1\n\trotate_z\t1\n\tphantom\t0\n\tremote_script_access_pin\t0\n\tvolume_detect\t0\n\tblock_grabs\t0\n\tdie_at_edge\t0\n\treturn_at_edge\t0\n\ttemporary\t0\n\tsandbox\t0\n\tsandboxhome\t0\t0\t0\n\tshape 0\n\t{\n\t\tpath 0\n\t\t{\n\t\t\tcurve\t32\n\t\t\tbegin\t0.3\n\t\t\tend\t0.65\n\t\t\tscale_x\t1\n\t\t\tscale_y\t0.05\n\t\t\tshear_x\t0\n\t\t\tshear_y\t0\n\t\t\ttwist\t0\n\t\t\ttwist_begin\t0\n\t\t\tradius_offset\t0\n\t\t\ttaper_x\t0\n\t\t\ttaper_y\t0\n\t\t\trevolutions\t1\n\t\t\tskew\t0\n\t\t}\n\t\tprofile 0\n\t\t{\n\t\t\tcurve\t0\n\t\t\tbegin\t0\n\t\t\tend\t1\n\t\t\thollow\t0\n\t\t}\n\t}\n\tfaces\t3\n\t{\n\t\timageid\te7150bed-3e3e-c698-eb15-d17b178148af\n\t\tcolors\t0.843137 0.156863 0.156863 1\n\t\tscales\t15\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t-1.57084\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\te7150bed-3e3e-c698-eb15-d17b178148af\n\t\tcolors\t0.843137 0.156863 0.156863 1\n\t\tscales\t15\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t-1.57084\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\te7150bed-3e3e-c698-eb15-d17b178148af\n\t\tcolors\t0.843137 0.156863 0.156863 1\n\t\tscales\t15\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t-1.57084\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\tps_next_crc\t1\n\tgpw_bias\t1\n\tip\t0\n\tcomplete\tTRUE\n\tdelay\t50000\n\tnextstart\t0\n\tbirthtime\t1061087534454174\n\treztime\t1094866329021741\n\tparceltime\t1133568981982889\n\ttax_rate\t1.00326\n\tscratchpad\t0\n\t{\n\t\n\t}\n\tsale_info\t0\n\t{\n\t\tsale_type\tnot\n\t\tsale_price\t10\n\t}\n\tcorrect_family_id\t00000000-0000-0000-0000-000000000000\n\thas_rezzed\t0\n\tpre_link_base_mask\t7fffffff\n\tlinked \tchild\n\tdefault_pay_price\t-2\t1\t5\t10\t20\n}\n{'task_id':ue4b19200-9d33-962f-c8c5-6f25be3a3fd0}\n{\n\tname\tApotheosis_Immolaine_tail|\n\tpermissions 0\n\t{\n\t\tbase_mask\t7fffffff\n\t\towner_mask\t7fffffff\n\t\tgroup_mask\t00000000\n\t\teveryone_mask\t00000000\n\t\tnext_owner_mask\t7ff