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