io.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:68k
源码类别:

游戏引擎

开发平台:

C++ Builder

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