00001
00034 #include "linden_common.h"
00035 #include "lltut.h"
00036
00037 #include <iterator>
00038
00039 #include <apr-1/apr_pools.h>
00040
00041 #include "llbuffer.h"
00042 #include "llbufferstream.h"
00043 #include "lliosocket.h"
00044 #include "llioutil.h"
00045 #include "llmemorystream.h"
00046 #include "llpipeutil.h"
00047 #include "llpumpio.h"
00048 #include "llsd.h"
00049 #include "llsdrpcclient.h"
00050 #include "llsdrpcserver.h"
00051 #include "llsdserialize.h"
00052 #include "lluuid.h"
00053 #include "llinstantmessage.h"
00054
00055 namespace tut
00056 {
00057 struct heap_buffer_data
00058 {
00059 heap_buffer_data() : mBuffer(NULL) {}
00060 ~heap_buffer_data() { if(mBuffer) delete mBuffer; }
00061 LLHeapBuffer* mBuffer;
00062 };
00063 typedef test_group<heap_buffer_data> heap_buffer_test;
00064 typedef heap_buffer_test::object heap_buffer_object;
00065 tut::heap_buffer_test thb("heap_buffer");
00066
00067 template<> template<>
00068 void heap_buffer_object::test<1>()
00069 {
00070 const S32 BUF_SIZE = 100;
00071 mBuffer = new LLHeapBuffer(BUF_SIZE);
00072 ensure_equals("empty buffer capacity", mBuffer->capacity(), BUF_SIZE);
00073 const S32 SEGMENT_SIZE = 50;
00074 LLSegment segment;
00075 mBuffer->createSegment(0, SEGMENT_SIZE, segment);
00076 ensure_equals("used buffer capacity", mBuffer->capacity(), BUF_SIZE);
00077 }
00078
00079 template<> template<>
00080 void heap_buffer_object::test<2>()
00081 {
00082 const S32 BUF_SIZE = 10;
00083 mBuffer = new LLHeapBuffer(BUF_SIZE);
00084 LLSegment segment;
00085 mBuffer->createSegment(0, BUF_SIZE, segment);
00086 ensure("segment is in buffer", mBuffer->containsSegment(segment));
00087 ensure_equals("buffer consumed", mBuffer->bytesLeft(), 0);
00088 bool created;
00089 created = mBuffer->createSegment(0, 0, segment);
00090 ensure("Create zero size segment fails", !created);
00091 created = mBuffer->createSegment(0, BUF_SIZE, segment);
00092 ensure("Create segment fails", !created);
00093 }
00094
00095 template<> template<>
00096 void heap_buffer_object::test<3>()
00097 {
00098 const S32 BUF_SIZE = 10;
00099 mBuffer = new LLHeapBuffer(BUF_SIZE);
00100 LLSegment segment;
00101 mBuffer->createSegment(0, BUF_SIZE, segment);
00102 ensure("segment is in buffer", mBuffer->containsSegment(segment));
00103 ensure_equals("buffer consumed", mBuffer->bytesLeft(), 0);
00104 bool reclaimed = mBuffer->reclaimSegment(segment);
00105 ensure("buffer reclaimed.", reclaimed);
00106 ensure_equals("buffer available", mBuffer->bytesLeft(), BUF_SIZE);
00107 bool created;
00108 created = mBuffer->createSegment(0, 0, segment);
00109 ensure("Create zero size segment fails", !created);
00110 created = mBuffer->createSegment(0, BUF_SIZE, segment);
00111 ensure("Create another segment succeeds", created);
00112 }
00113
00114 template<> template<>
00115 void heap_buffer_object::test<4>()
00116 {
00117 const S32 BUF_SIZE = 10;
00118 const S32 SEGMENT_SIZE = 4;
00119 mBuffer = new LLHeapBuffer(BUF_SIZE);
00120 LLSegment seg1;
00121 mBuffer->createSegment(0, SEGMENT_SIZE, seg1);
00122 ensure("segment is in buffer", mBuffer->containsSegment(seg1));
00123 LLSegment seg2;
00124 mBuffer->createSegment(0, SEGMENT_SIZE, seg2);
00125 ensure("segment is in buffer", mBuffer->containsSegment(seg2));
00126 LLSegment seg3;
00127 mBuffer->createSegment(0, SEGMENT_SIZE, seg3);
00128 ensure("segment is in buffer", mBuffer->containsSegment(seg3));
00129 ensure_equals("segment is truncated", seg3.size(), 2);
00130 LLSegment seg4;
00131 bool created;
00132 created = mBuffer->createSegment(0, SEGMENT_SIZE, seg4);
00133 ensure("Create segment fails", !created);
00134 bool reclaimed;
00135 reclaimed = mBuffer->reclaimSegment(seg1);
00136 ensure("buffer reclaim succeed.", reclaimed);
00137 ensure_equals("no buffer available", mBuffer->bytesLeft(), 0);
00138 reclaimed = mBuffer->reclaimSegment(seg2);
00139 ensure("buffer reclaim succeed.", reclaimed);
00140 ensure_equals("buffer reclaimed", mBuffer->bytesLeft(), 0);
00141 reclaimed = mBuffer->reclaimSegment(seg3);
00142 ensure("buffer reclaim succeed.", reclaimed);
00143 ensure_equals("buffer reclaimed", mBuffer->bytesLeft(), BUF_SIZE);
00144 created = mBuffer->createSegment(0, SEGMENT_SIZE, seg1);
00145 ensure("segment is in buffer", mBuffer->containsSegment(seg1));
00146 ensure("Create segment succeds", created);
00147 }
00148 }
00149
00150 namespace tut
00151 {
00152 struct buffer_data
00153 {
00154 LLBufferArray mBuffer;
00155 };
00156 typedef test_group<buffer_data> buffer_test;
00157 typedef buffer_test::object buffer_object;
00158 tut::buffer_test tba("buffer_array");
00159
00160 template<> template<>
00161 void buffer_object::test<1>()
00162 {
00163 const char HELLO_WORLD[] = "hello world";
00164 const S32 str_len = strlen(HELLO_WORLD);
00165 LLChannelDescriptors ch = mBuffer.nextChannel();
00166 mBuffer.append(ch.in(), (U8*)HELLO_WORLD, str_len);
00167 S32 count = mBuffer.countAfter(ch.in(), NULL);
00168 ensure_equals("total append size", count, str_len);
00169 LLBufferArray::segment_iterator_t it = mBuffer.beginSegment();
00170 U8* first = (*it).data();
00171 count = mBuffer.countAfter(ch.in(), first);
00172 ensure_equals("offset append size", count, str_len - 1);
00173 }
00174
00175 template<> template<>
00176 void buffer_object::test<2>()
00177 {
00178 const char HELLO_WORLD[] = "hello world";
00179 const S32 str_len = strlen(HELLO_WORLD);
00180 LLChannelDescriptors ch = mBuffer.nextChannel();
00181 mBuffer.append(ch.in(), (U8*)HELLO_WORLD, str_len);
00182 mBuffer.append(ch.in(), (U8*)HELLO_WORLD, str_len);
00183 S32 count = mBuffer.countAfter(ch.in(), NULL);
00184 ensure_equals("total append size", count, 2 * str_len);
00185 LLBufferArray::segment_iterator_t it = mBuffer.beginSegment();
00186 U8* first = (*it).data();
00187 count = mBuffer.countAfter(ch.in(), first);
00188 ensure_equals("offset append size", count, (2 * str_len) - 1);
00189 }
00190
00191 template<> template<>
00192 void buffer_object::test<3>()
00193 {
00194 const char ONE[] = "one";
00195 const char TWO[] = "two";
00196 std::string expected(ONE);
00197 expected.append(TWO);
00198 LLChannelDescriptors ch = mBuffer.nextChannel();
00199 mBuffer.append(ch.in(), (U8*)ONE, 3);
00200 mBuffer.append(ch.in(), (U8*)TWO, 3);
00201 char buffer[255];
00202 S32 len = 6;
00203 mBuffer.readAfter(ch.in(), NULL, (U8*)buffer, len);
00204 ensure_equals(len, 6);
00205 buffer[len] = '\0';
00206 std::string actual(buffer);
00207 ensure_equals("read", actual, expected);
00208 }
00209
00210 template<> template<>
00211 void buffer_object::test<4>()
00212 {
00213 const char ONE[] = "one";
00214 const char TWO[] = "two";
00215 std::string expected(ONE);
00216 expected.append(TWO);
00217 LLChannelDescriptors ch = mBuffer.nextChannel();
00218 mBuffer.append(ch.in(), (U8*)TWO, 3);
00219 mBuffer.prepend(ch.in(), (U8*)ONE, 3);
00220 char buffer[255];
00221 S32 len = 6;
00222 mBuffer.readAfter(ch.in(), NULL, (U8*)buffer, len);
00223 ensure_equals(len, 6);
00224 buffer[len] = '\0';
00225 std::string actual(buffer);
00226 ensure_equals("read", actual, expected);
00227 }
00228
00229 template<> template<>
00230 void buffer_object::test<5>()
00231 {
00232 const char ONE[] = "one";
00233 const char TWO[] = "two";
00234 std::string expected("netwo");
00235 LLChannelDescriptors ch = mBuffer.nextChannel();
00236 mBuffer.append(ch.in(), (U8*)TWO, 3);
00237 mBuffer.prepend(ch.in(), (U8*)ONE, 3);
00238 char buffer[255];
00239 S32 len = 5;
00240 LLBufferArray::segment_iterator_t it = mBuffer.beginSegment();
00241 U8* addr = (*it).data();
00242 mBuffer.readAfter(ch.in(), addr, (U8*)buffer, len);
00243 ensure_equals(len, 5);
00244 buffer[len] = '\0';
00245 std::string actual(buffer);
00246 ensure_equals("read", actual, expected);
00247 }
00248
00249 template<> template<>
00250 void buffer_object::test<6>()
00251 {
00252 std::string request("The early bird catches the worm.");
00253 std::string response("If you're a worm, sleep late.");
00254 std::ostringstream expected;
00255 expected << "ContentLength: " << response.length() << "\r\n\r\n"
00256 << response;
00257 LLChannelDescriptors ch = mBuffer.nextChannel();
00258 mBuffer.append(ch.in(), (U8*)request.c_str(), request.length());
00259 mBuffer.append(ch.out(), (U8*)response.c_str(), response.length());
00260 S32 count = mBuffer.countAfter(ch.out(), NULL);
00261 std::ostringstream header;
00262 header << "ContentLength: " << count << "\r\n\r\n";
00263 std::string head(header.str());
00264 mBuffer.prepend(ch.out(), (U8*)head.c_str(), head.length());
00265 char buffer[1024];
00266 S32 len = response.size() + head.length();
00267 ensure_equals("same length", len, (S32)expected.str().length());
00268 mBuffer.readAfter(ch.out(), NULL, (U8*)buffer, len);
00269 buffer[len] = '\0';
00270 std::string actual(buffer);
00271 ensure_equals("threaded writes", actual, expected.str());
00272 }
00273
00274 template<> template<>
00275 void buffer_object::test<7>()
00276 {
00277 const S32 LINE_COUNT = 3;
00278 std::string lines[LINE_COUNT] =
00279 {
00280 std::string("GET /index.htm HTTP/1.0\r\n"),
00281 std::string("User-Agent: Wget/1.9.1\r\n"),
00282 std::string("Host: localhost:8008\r\n")
00283 };
00284 std::string text;
00285 S32 i;
00286 for(i = 0; i < LINE_COUNT; ++i)
00287 {
00288 text.append(lines[i]);
00289 }
00290 LLChannelDescriptors ch = mBuffer.nextChannel();
00291 mBuffer.append(ch.in(), (U8*)text.c_str(), text.length());
00292 const S32 BUFFER_LEN = 1024;
00293 char buf[BUFFER_LEN];
00294 S32 len;
00295 U8* last = NULL;
00296 std::string last_line;
00297 for(i = 0; i < LINE_COUNT; ++i)
00298 {
00299 len = BUFFER_LEN;
00300 last = mBuffer.readAfter(ch.in(), last, (U8*)buf, len);
00301 char* newline = strchr((char*)buf, '\n');
00302 S32 offset = -((len - 1) - (newline - buf));
00303 ++newline;
00304 *newline = '\0';
00305 last_line.assign(buf);
00306 std::ostringstream message;
00307 message << "line reads in line[" << i << "]";
00308 ensure_equals(message.str().c_str(), last_line, lines[i]);
00309 last = mBuffer.seek(ch.in(), last, offset);
00310 }
00311 }
00312
00313 template<> template<>
00314 void buffer_object::test<8>()
00315 {
00316 LLChannelDescriptors ch = mBuffer.nextChannel();
00317 mBuffer.append(ch.in(), (U8*)"1", 1);
00318 LLBufferArray buffer;
00319 buffer.append(ch.in(), (U8*)"2", 1);
00320 mBuffer.takeContents(buffer);
00321 mBuffer.append(ch.in(), (U8*)"3", 1);
00322 S32 count = mBuffer.countAfter(ch.in(), NULL);
00323 ensure_equals("buffer size", count, 3);
00324 U8* temp = new U8[count];
00325 mBuffer.readAfter(ch.in(), NULL, temp, count);
00326 ensure("buffer content", (0 == memcmp(temp, (void*)"123", 3)));
00327 delete[] temp;
00328 }
00329
00330 template<> template<>
00331 void buffer_object::test<9>()
00332 {
00333 LLChannelDescriptors ch = mBuffer.nextChannel();
00334 mBuffer.append(ch.in(), (U8*)"1", 1);
00335 S32 capacity = mBuffer.capacity();
00336 ensure("has capacity", capacity > 0);
00337 U8* temp = new U8[capacity - 1];
00338 mBuffer.append(ch.in(), temp, capacity - 1);
00339 capacity = mBuffer.capacity();
00340 ensure("has capacity when full", capacity > 0);
00341 S32 used = mBuffer.countAfter(ch.in(), NULL);
00342 ensure_equals("used equals capacity", used, capacity);
00343
00344 LLBufferArray::segment_iterator_t iter = mBuffer.beginSegment();
00345 while(iter != mBuffer.endSegment())
00346 {
00347 mBuffer.eraseSegment(iter++);
00348 }
00349
00350 used = mBuffer.countAfter(ch.in(), NULL);
00351 ensure_equals("used is zero", used, 0);
00352 S32 capacity2 = mBuffer.capacity();
00353 ensure_equals("capacity the same after erase", capacity2, capacity);
00354 mBuffer.append(ch.in(), temp, capacity - 1);
00355 capacity2 = mBuffer.capacity();
00356 ensure_equals("capacity the same after append", capacity2, capacity);
00357
00358 delete[] temp;
00359 }
00360
00361 #if 0
00362 template<> template<>
00363 void buffer_object::test<9>()
00364 {
00365 char buffer[1024];
00366 S32 size = sprintf(buffer,
00367 "%d|%d|%s|%s|%s|%s|%s|%x|%x|%x|%x|%x|%s|%s|%d|%d|%x",
00368 7,
00369 7,
00370 "Hang Glider INFO",
00371 "18e84d1e-04a4-4c0d-8cb6-6c73477f0a9a",
00372 "0e346d8b-4433-4d66-a6b0-fd37083abc4c",
00373 "0e346d8b-4433-4d66-a6b0-fd37083abc4c",
00374 "00000000-0000-0000-0000-000000000000",
00375 0x7fffffff,
00376 0x7fffffff,
00377 0,
00378 0,
00379 0x7fffffff,
00380 "69e0d357-2e7c-8990-a2bc-7f61c868e5a3",
00381 "2004-06-04 16:09:17 note card",
00382 0,
00383 10,
00384 0) + 1;
00385
00386
00387
00388 LLSD* bin_bucket = LLIMInfo::buildSDfrombuffer((U8*)buffer,size);
00389
00390 char post_buffer[1024];
00391 U32 post_size;
00392 LLIMInfo::getBinaryBucket(bin_bucket,(U8*)post_buffer,post_size);
00393 ensure_equals("Buffer sizes",size,(S32)post_size);
00394 ensure("Buffer content",!strcmp(buffer,post_buffer));
00395 }
00396 #endif
00397
00398
00399
00400
00401
00402
00403
00404 }
00405
00406 namespace tut
00407 {
00408 struct buffer_and_stream_data
00409 {
00410 LLBufferArray mBuffer;
00411 };
00412 typedef test_group<buffer_and_stream_data> bas_test;
00413 typedef bas_test::object bas_object;
00414 tut::bas_test tbs("buffer_stream");
00415
00416 template<> template<>
00417 void bas_object::test<1>()
00418 {
00419 const char HELLO_WORLD[] = "hello world";
00420 const S32 str_len = strlen(HELLO_WORLD);
00421 LLChannelDescriptors ch = mBuffer.nextChannel();
00422 LLBufferStream str(ch, &mBuffer);
00423 mBuffer.append(ch.in(), (U8*)HELLO_WORLD, str_len);
00424 std::string hello;
00425 std::string world;
00426 str >> hello >> world;
00427 ensure_equals("first word", hello, std::string("hello"));
00428 ensure_equals("second word", world, std::string("world"));
00429 }
00430
00431 template<> template<>
00432 void bas_object::test<2>()
00433 {
00434 std::string part1("Eat my shor");
00435 std::string part2("ts ho");
00436 std::string part3("mer");
00437 std::string ignore("ignore me");
00438 LLChannelDescriptors ch = mBuffer.nextChannel();
00439 LLBufferStream str(ch, &mBuffer);
00440 mBuffer.append(ch.in(), (U8*)part1.c_str(), part1.length());
00441 mBuffer.append(ch.in(), (U8*)part2.c_str(), part2.length());
00442 mBuffer.append(ch.out(), (U8*)ignore.c_str(), ignore.length());
00443 mBuffer.append(ch.in(), (U8*)part3.c_str(), part3.length());
00444 std::string eat;
00445 std::string my;
00446 std::string shorts;
00447 std::string homer;
00448 str >> eat >> my >> shorts >> homer;
00449 ensure_equals("word1", eat, std::string("Eat"));
00450 ensure_equals("word2", my, std::string("my"));
00451 ensure_equals("word3", shorts, std::string("shorts"));
00452 ensure_equals("word4", homer, std::string("homer"));
00453 }
00454
00455 template<> template<>
00456 void bas_object::test<3>()
00457 {
00458 std::string part1("junk in ");
00459 std::string part2("the trunk");
00460 const S32 CHANNEL = 0;
00461 mBuffer.append(CHANNEL, (U8*)part1.c_str(), part1.length());
00462 mBuffer.append(CHANNEL, (U8*)part2.c_str(), part2.length());
00463 U8* last = 0;
00464 const S32 BUF_LEN = 128;
00465 char buf[BUF_LEN];
00466 S32 len = 11;
00467 last = mBuffer.readAfter(CHANNEL, last, (U8*)buf, len);
00468 buf[len] = '\0';
00469 std::string actual(buf);
00470 ensure_equals("first read", actual, std::string("junk in the"));
00471 last = mBuffer.seek(CHANNEL, last, -6);
00472 len = 12;
00473 last = mBuffer.readAfter(CHANNEL, last, (U8*)buf, len);
00474 buf[len] = '\0';
00475 actual.assign(buf);
00476 ensure_equals("seek and read", actual, std::string("in the trunk"));
00477 }
00478
00479 template<> template<>
00480 void bas_object::test<4>()
00481 {
00482 std::string phrase("zippity do da!");
00483 const S32 CHANNEL = 0;
00484 mBuffer.append(CHANNEL, (U8*)phrase.c_str(), phrase.length());
00485 const S32 BUF_LEN = 128;
00486 char buf[BUF_LEN];
00487 S32 len = 7;
00488 U8* last = mBuffer.readAfter(CHANNEL, NULL, (U8*)buf, len);
00489 mBuffer.splitAfter(last);
00490 LLBufferArray::segment_iterator_t it = mBuffer.beginSegment();
00491 LLBufferArray::segment_iterator_t end = mBuffer.endSegment();
00492 std::string first((char*)((*it).data()), (*it).size());
00493 ensure_equals("first part", first, std::string("zippity"));
00494 ++it;
00495 std::string second((char*)((*it).data()), (*it).size());
00496 ensure_equals("second part", second, std::string(" do da!"));
00497 ++it;
00498 ensure("iterators equal", (it == end));
00499 }
00500
00501 template<> template<>
00502 void bas_object::test<5>()
00503 {
00504 LLChannelDescriptors ch = mBuffer.nextChannel();
00505 LLBufferStream str(ch, &mBuffer);
00506 std::string h1("hello");
00507 std::string h2(", how are you doing?");
00508 std::string expected(h1);
00509 expected.append(h2);
00510 str << h1 << h2;
00511 str.flush();
00512 const S32 BUF_LEN = 128;
00513 char buf[BUF_LEN];
00514 S32 actual_len = BUF_LEN;
00515 S32 expected_len = h1.size() + h2.size();
00516 (void) mBuffer.readAfter(ch.out(), NULL, (U8*)buf, actual_len);
00517 ensure_equals("streamed size", actual_len, expected_len);
00518 buf[actual_len] = '\0';
00519 std::string actual(buf);
00520 ensure_equals("streamed to buf", actual, expected);
00521 }
00522
00523 template<> template<>
00524 void bas_object::test<6>()
00525 {
00526 LLChannelDescriptors ch = mBuffer.nextChannel();
00527 LLBufferStream bstr(ch, &mBuffer);
00528 std::ostringstream ostr;
00529 std::vector<LLUUID> ids;
00530 LLUUID id;
00531 for(int i = 0; i < 5; ++i)
00532 {
00533 id.generate();
00534 ids.push_back(id);
00535 }
00536 bstr << "SELECT concat(u.username, ' ', l.name) "
00537 << "FROM user u, user_last_name l "
00538 << "WHERE u.last_name_id = l.last_name_id"
00539 << " AND u.agent_id IN ('";
00540 ostr << "SELECT concat(u.username, ' ', l.name) "
00541 << "FROM user u, user_last_name l "
00542 << "WHERE u.last_name_id = l.last_name_id"
00543 << " AND u.agent_id IN ('";
00544 std::copy(
00545 ids.begin(),
00546 ids.end(),
00547 std::ostream_iterator<LLUUID>(bstr, "','"));
00548 std::copy(
00549 ids.begin(),
00550 ids.end(),
00551 std::ostream_iterator<LLUUID>(ostr, "','"));
00552 bstr.seekp(-2, std::ios::cur);
00553 ostr.seekp(-2, std::ios::cur);
00554 bstr << ") ";
00555 ostr << ") ";
00556 bstr.flush();
00557 const S32 BUF_LEN = 512;
00558 char buf[BUF_LEN];
00559 S32 actual_len = BUF_LEN;
00560 (void) mBuffer.readAfter(ch.out(), NULL, (U8*)buf, actual_len);
00561 buf[actual_len] = '\0';
00562 std::string actual(buf);
00563 std::string expected(ostr.str());
00564 ensure_equals("size of string in seek",actual.size(),expected.size());
00565 ensure_equals("seek in ostream", actual, expected);
00566 }
00567
00568 template<> template<>
00569 void bas_object::test<7>()
00570 {
00571 LLChannelDescriptors ch = mBuffer.nextChannel();
00572 LLBufferStream bstr(ch, &mBuffer);
00573 bstr << "1";
00574 bstr.flush();
00575 S32 count = mBuffer.countAfter(ch.out(), NULL);
00576 ensure_equals("buffer size 1", count, 1);
00577 LLBufferArray buffer;
00578 buffer.append(ch.out(), (U8*)"2", 1);
00579 mBuffer.takeContents(buffer);
00580 count = mBuffer.countAfter(ch.out(), NULL);
00581 ensure_equals("buffer size 2", count, 2);
00582 bstr << "3";
00583 bstr.flush();
00584 count = mBuffer.countAfter(ch.out(), NULL);
00585 ensure_equals("buffer size 3", count, 3);
00586 U8* temp = new U8[count];
00587 mBuffer.readAfter(ch.out(), NULL, temp, count);
00588 ensure("buffer content", (0 == memcmp(temp, (void*)"123", 3)));
00589 delete[] temp;
00590 }
00591
00592 template<> template<>
00593 void bas_object::test<8>()
00594 {
00595 LLChannelDescriptors ch = mBuffer.nextChannel();
00596 LLBufferStream ostr(ch, &mBuffer);
00597 typedef std::vector<U8> buf_t;
00598 typedef std::vector<buf_t> actual_t;
00599 actual_t actual;
00600 buf_t source;
00601 bool need_comma = false;
00602 ostr << "[";
00603 S32 total_size = 1;
00604 for(S32 i = 2000; i < 2003; ++i)
00605 {
00606 if(need_comma)
00607 {
00608 ostr << ",";
00609 ++total_size;
00610 }
00611 need_comma = true;
00612 srand(69 + i);
00613 S32 size = rand() % 1000 + 1000;
00614 std::generate_n(
00615 std::back_insert_iterator<buf_t>(source),
00616 size,
00617 rand);
00618 actual.push_back(source);
00619 ostr << "b(" << size << ")\"";
00620 total_size += 8;
00621 ostr.write((const char*)(&source[0]), size);
00622 total_size += size;
00623 source.clear();
00624 ostr << "\"";
00625 ++total_size;
00626 }
00627 ostr << "]";
00628 ++total_size;
00629 ostr.flush();
00630
00631
00632 ch = mBuffer.nextChannel();
00633 S32 count = mBuffer.countAfter(ch.in(), NULL);
00634 ensure_equals("size of buffer", count, total_size);
00635 LLBufferStream istr(ch, &mBuffer);
00636 LLSD data;
00637 count = LLSDSerialize::fromNotation(data, istr);
00638 ensure("sd parsed", data.isDefined());
00639
00640 for(S32 j = 0; j < 3; ++j)
00641 {
00642 std::ostringstream name;
00643 LLSD child(data[j]);
00644 name << "found buffer " << j;
00645 ensure(name.str(), child.isDefined());
00646 source = child.asBinary();
00647 name.str("");
00648 name << "buffer " << j << " size";
00649 ensure_equals(name.str().c_str(), source.size(), actual[j].size());
00650 name.str("");
00651 name << "buffer " << j << " contents";
00652 ensure(
00653 name.str(),
00654 (0 == memcmp(&source[0], &actual[j][0], source.size())));
00655 }
00656 }
00657
00658 template<> template<>
00659 void bas_object::test<9>()
00660 {
00661 LLChannelDescriptors ch = mBuffer.nextChannel();
00662 LLBufferStream ostr(ch, &mBuffer);
00663 typedef std::vector<U8> buf_t;
00664 buf_t source;
00665 bool need_comma = false;
00666 ostr << "{";
00667 S32 total_size = 1;
00668 for(S32 i = 1000; i < 3000; ++i)
00669 {
00670 if(need_comma)
00671 {
00672 ostr << ",";
00673 ++total_size;
00674 }
00675 need_comma = true;
00676 ostr << "'" << i << "':";
00677 total_size += 7;
00678 srand(69 + i);
00679 S32 size = rand() % 1000 + 1000;
00680 std::generate_n(
00681 std::back_insert_iterator<buf_t>(source),
00682 size,
00683 rand);
00684 ostr << "b(" << size << ")\"";
00685 total_size += 8;
00686 ostr.write((const char*)(&source[0]), size);
00687 total_size += size;
00688 source.clear();
00689 ostr << "\"";
00690 ++total_size;
00691 }
00692 ostr << "}";
00693 ++total_size;
00694 ostr.flush();
00695
00696
00697 ch = mBuffer.nextChannel();
00698 S32 count = mBuffer.countAfter(ch.in(), NULL);
00699 ensure_equals("size of buffer", count, total_size);
00700 LLBufferStream istr(ch, &mBuffer);
00701 LLSD data;
00702 count = LLSDSerialize::fromNotation(data, istr);
00703 ensure("sd parsed", data.isDefined());
00704 }
00705
00706 template<> template<>
00707 void bas_object::test<10>()
00708 {
00709 const char LOGIN_STREAM[] = "{'method':'login', 'parameter': [ {"
00710 "'uri': 'sl-am:kellys.region.siva.lindenlab.com/location?start=url&px=128&py=128&pz=128&lx=0&ly=0&lz=0'}, "
00711 "{'version': i1}, {'texture_data': [ '61d724fb-ad79-f637-2186-5cf457560daa', '6e38b9be-b7cc-e77a-8aec-029a42b0b416', "
00712 "'a9073524-e89b-2924-ca6e-a81944109a1a', '658f18b5-5f1e-e593-f5d5-36c3abc7249a', '0cc799f4-8c99-6b91-bd75-b179b12429e2', "
00713 "'59fd9b64-8300-a425-aad8-2ffcbe9a49d2', '59fd9b64-8300-a425-aad8-2ffcbe9a49d2', '5748decc-f629-461c-9a36-a35a221fe21f', "
00714 "'b8fc9be2-26a6-6b47-690b-0e902e983484', 'a13ca0fe-3802-dc97-e79a-70d12171c724', 'dd9643cf-fd5d-0376-ed4a-b1cc646a97d5', "
00715 "'4ad13ae9-a112-af09-210a-cf9353a7a9e7', 'c228d1cf-4b5d-4ba8-84f4-899a0796aa97', 'c228d1cf-4b5d-4ba8-84f4-899a0796aa97', "
00716 "'c228d1cf-4b5d-4ba8-84f4-899a0796aa97', 'c228d1cf-4b5d-4ba8-84f4-899a0796aa97', 'c228d1cf-4b5d-4ba8-84f4-899a0796aa97', "
00717 "'5748decc-f629-461c-9a36-a35a221fe21f', 'c228d1cf-4b5d-4ba8-84f4-899a0796aa97', 'c228d1cf-4b5d-4ba8-84f4-899a0796aa97'],"
00718 "'session_id': '324cfa9f-fe5d-4d1c-a317-35f20a86a4d1','position': [ i128, i128, i128],'last_name': 'Linden','group_title': '-> !BLING! <-','group_name': 'test!','agent_access': 'M',"
00719 "'attachment_data': [ {'asset_id': 'aaede2b1-9955-09d4-5c93-2b557c778cf3','attachment_point': i6,'item_id': 'f3694abc-5122-db33-73d9-e0f4288dc2bf'}],"
00720 "'buddy_ids': [ '101358d5-469d-4b24-9b85-4dc3c05e635d', '1b00fec7-6265-4875-acac-80d9cfe9295c', '203ad6df-b522-491d-ba48-4e24eb57aeff', "
00721 "'22d4dcdb-aebb-47fa-b925-a871cc75ee48','27da3df5-1339-4463-80aa-40504ee3b3e5', '299d1720-b61f-4268-8c29-9614aa2d44c2', "
00722 "'2b048a24-2737-4994-9fa5-becc8e466253', '2cd5dc14-a853-49a4-be3c-a5a7178e37bc', '3de548e1-57be-cfea-2b78-83ae3ad95998', "
00723 "'3dee98e4-a6a3-4543-91c3-bbd528447ba7', '3e2d81a3-6263-6ffe-ad5c-8ce04bee07e9', '40e70b98-fed7-47f3-9700-1bce93f9350b', "
00724 "'50a9b68e-b5aa-4d35-9137-3cfebda0a15c', '54295571-9357-43ff-ae74-a83b5138160f', '6191e2d7-5f96-4856-bdab-af0f79f47ae4', "
00725 "'63e577d8-cd34-4235-a0a3-de0500133364', '79cfb666-4fd0-4af7-95df-fb7d96b4e24d', '8121c2f3-4a88-4c33-9899-8fc1273f47ee', "
00726 "'909da964-ef23-4f2a-ba13-f2a8cfd454b6','a2e76fcd-9360-4f6d-a924-000000000001', 'aaa6d664-527e-4d83-9cbb-7ef79ccc7cc8', "
00727 "'b79bfb6c-23be-49eb-b35b-30ff2f501b37', 'ba0d9c79-148c-4a79-8e3c-0665eebe2427', 'bc9bda98-57cd-498f-b993-4ff1ac9dec93', "
00728 "'c62d16f6-81cb-419d-9cac-e46dc394084d', 'd48f8fa7-2512-4fe5-80c8-c0a923412e07', 'd77e3e24-7e6c-4c3f-96d0-a1746337f8fb', "
00729 "'da615c63-a84b-4592-a3d6-a90dd3e92e6e', 'df47190a-7eb7-4aff-985f-2d1d3ad6c6e9', 'e3380196-72cd-499c-a2ba-caa180bd5fe4', "
00730 "'e937863f-f134-4207-803b-d6e686651d6c', 'efcdf98b-5269-45ef-ac7a-0671f09ea9d9'],"
00731 "'circuit_code': i124,'group_id': '8615c885-9cf0-bf0a-6e40-0c11462aa652','limited_to_estate': i1,'look_at': [ i0, i0, i0],"
00732 "'agent_id': '0e346d8b-4433-4d66-a6b0-fd37083abc4c','first_name': 'Kelly','start': 'url'}]}";
00733 LLChannelDescriptors ch = mBuffer.nextChannel();
00734 mBuffer.append(ch.out(), (U8*)LOGIN_STREAM, strlen(LOGIN_STREAM));
00735 ch = mBuffer.nextChannel();
00736 LLBufferStream istr(ch, &mBuffer);
00737 LLSD data;
00738 S32 count = LLSDSerialize::fromNotation(data, istr);
00739 ensure("parsed something", (count > 0));
00740 ensure("sd parsed", data.isDefined());
00741 ensure_equals("sd type", data.type(), LLSD::TypeMap);
00742 ensure("has method", data.has("method"));
00743 ensure("has parameter", data.has("parameter"));
00744 LLSD parameter = data["parameter"];
00745 ensure_equals("parameter is array", parameter.type(), LLSD::TypeArray);
00746 LLSD agent_params = parameter[2];
00747 std::string s_value;
00748 s_value = agent_params["last_name"].asString();
00749 ensure_equals("last name", s_value, std::string("Linden"));
00750 s_value = agent_params["first_name"].asString();
00751 ensure_equals("first name", s_value, std::string("Kelly"));
00752 s_value = agent_params["agent_access"].asString();
00753 ensure_equals("agent access", s_value, std::string("M"));
00754 s_value = agent_params["group_name"].asString();
00755 ensure_equals("group name", s_value, std::string("test!"));
00756 s_value = agent_params["group_title"].asString();
00757 ensure_equals("group title", s_value, std::string("-> !BLING! <-"));
00758
00759 LLUUID agent_id("0e346d8b-4433-4d66-a6b0-fd37083abc4c");
00760 LLUUID id = agent_params["agent_id"];
00761 ensure_equals("agent id", id, agent_id);
00762 LLUUID session_id("324cfa9f-fe5d-4d1c-a317-35f20a86a4d1");
00763 id = agent_params["session_id"];
00764 ensure_equals("session id", id, session_id);
00765 LLUUID group_id ("8615c885-9cf0-bf0a-6e40-0c11462aa652");
00766 id = agent_params["group_id"];
00767 ensure_equals("group id", id, group_id);
00768
00769 S32 i_val = agent_params["limited_to_estate"];
00770 ensure_equals("limited to estate", i_val, 1);
00771 i_val = agent_params["circuit_code"];
00772 ensure_equals("circuit code", i_val, 124);
00773 }
00774
00775
00776 template<> template<>
00777 void bas_object::test<11>()
00778 {
00779 std::string val = "{!'foo'@:#'bar'}";
00780 std::istringstream istr;
00781 istr.str(val);
00782 LLSD sd;
00783 S32 count = LLSDSerialize::fromNotation(sd, istr);
00784 ensure_equals("parser error return value", count, -1);
00785 ensure("data undefined", sd.isUndefined());
00786 }
00787
00788 template<> template<>
00789 void bas_object::test<12>()
00790 {
00791 std::string val = "{!'foo':[i1,'hi',{@'bar'#:[$i2%,^'baz'&]*}+]=}";
00792 std::istringstream istr;
00793 istr.str(val);
00794 LLSD sd;
00795 S32 count = LLSDSerialize::fromNotation(sd, istr);
00796 ensure_equals("parser error return value", count, -1);
00797 ensure("data undefined", sd.isUndefined());
00798 }
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814 }
00815
00816
00817 namespace tut
00818 {
00819 class PumpAndChainTestData
00820 {
00821 protected:
00822 apr_pool_t* mPool;
00823 LLPumpIO* mPump;
00824 LLPumpIO::chain_t mChain;
00825
00826 public:
00827 PumpAndChainTestData()
00828 {
00829 apr_pool_create(&mPool, NULL);
00830 mPump = new LLPumpIO(mPool);
00831 }
00832
00833 ~PumpAndChainTestData()
00834 {
00835 mChain.clear();
00836 delete mPump;
00837 apr_pool_destroy(mPool);
00838 }
00839 };
00840 typedef test_group<PumpAndChainTestData> PumpAndChainTestGroup;
00841 typedef PumpAndChainTestGroup::object PumpAndChainTestObject;
00842 PumpAndChainTestGroup pumpAndChainTestGroup("pump_and_chain");
00843
00844 template<> template<>
00845 void PumpAndChainTestObject::test<1>()
00846 {
00847 LLPipeStringExtractor* extractor = new LLPipeStringExtractor();
00848
00849 mChain.push_back(LLIOPipe::ptr_t(new LLIOFlush));
00850 mChain.push_back(LLIOPipe::ptr_t(extractor));
00851
00852 LLTimer timer;
00853 timer.setTimerExpirySec(100.0f);
00854
00855 mPump->addChain(mChain, DEFAULT_CHAIN_EXPIRY_SECS);
00856 while(!extractor->done() && !timer.hasExpired())
00857 {
00858 mPump->pump();
00859 mPump->callback();
00860 }
00861
00862 ensure("reading string finished", extractor->done());
00863 ensure_equals("string was empty", extractor->string(), "");
00864 }
00865 }
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893 namespace tut
00894 {
00898 struct pipe_and_pump_fitness
00899 {
00900 public:
00901 enum
00902 {
00903 SERVER_LISTEN_PORT = 13050
00904 };
00905
00906 pipe_and_pump_fitness()
00907 {
00908 LLFrameTimer::updateFrameTime();
00909 apr_pool_create(&mPool, NULL);
00910 mPump = new LLPumpIO(mPool);
00911 mSocket = LLSocket::create(
00912 mPool,
00913 LLSocket::STREAM_TCP,
00914 SERVER_LISTEN_PORT);
00915 }
00916
00917 ~pipe_and_pump_fitness()
00918 {
00919 mSocket.reset();
00920 delete mPump;
00921 apr_pool_destroy(mPool);
00922 }
00923
00924 protected:
00925 apr_pool_t* mPool;
00926 LLPumpIO* mPump;
00927 LLSocket::ptr_t mSocket;
00928 };
00929 typedef test_group<pipe_and_pump_fitness> fitness_test_group;
00930 typedef fitness_test_group::object fitness_test_object;
00931 fitness_test_group fitness("pipe and pump fitness");
00932
00933 template<> template<>
00934 void fitness_test_object::test<1>()
00935 {
00936 lldebugs << "fitness_test_object::test<1>()" << llendl;
00937
00938
00939
00940
00941 LLPumpIO::chain_t chain;
00942 typedef LLCloneIOFactory<LLPipeStringInjector> emitter_t;
00943 emitter_t* emitter = new emitter_t(
00944 new LLPipeStringInjector("suckers never play me"));
00945 boost::shared_ptr<LLChainIOFactory> factory(emitter);
00946 LLIOServerSocket* server = new LLIOServerSocket(
00947 mPool,
00948 mSocket,
00949 factory);
00950 server->setResponseTimeout(SHORT_CHAIN_EXPIRY_SECS);
00951 chain.push_back(LLIOPipe::ptr_t(server));
00952 mPump->addChain(chain, NEVER_CHAIN_EXPIRY_SECS);
00953
00954
00955
00956
00957 pump_loop(mPump, 0.1f);
00958
00959
00960
00961
00962 LLSocket::ptr_t client = LLSocket::create(mPool, LLSocket::STREAM_TCP);
00963 LLHost server_host("127.0.0.1", SERVER_LISTEN_PORT);
00964 bool connected = client->blockingConnect(server_host);
00965 ensure("Connected to server", connected);
00966 lldebugs << "connected" << llendl;
00967
00968
00969
00970
00971 chain.clear();
00972 chain.push_back(LLIOPipe::ptr_t(new LLPipeStringInjector("hi")));
00973 chain.push_back(LLIOPipe::ptr_t(new LLIOSocketWriter(client)));
00974 chain.push_back(LLIOPipe::ptr_t(new LLIONull));
00975 mPump->addChain(chain, 1.0f);
00976
00977
00978
00979 F32 elapsed = pump_loop(mPump, 2.0f);
00980 ensure("Did not take too long", (elapsed < 3.0f));
00981 }
00982
00983 template<> template<>
00984 void fitness_test_object::test<2>()
00985 {
00986 lldebugs << "fitness_test_object::test<2>()" << llendl;
00987
00988
00989 LLPumpIO::chain_t chain;
00990 typedef LLCloneIOFactory<LLIOFuzz> emitter_t;
00991 emitter_t* emitter = new emitter_t(new LLIOFuzz(1000000));
00992 boost::shared_ptr<LLChainIOFactory> factory(emitter);
00993 LLIOServerSocket* server = new LLIOServerSocket(
00994 mPool,
00995 mSocket,
00996 factory);
00997 server->setResponseTimeout(SHORT_CHAIN_EXPIRY_SECS);
00998 chain.push_back(LLIOPipe::ptr_t(server));
00999 mPump->addChain(chain, NEVER_CHAIN_EXPIRY_SECS);
01000
01001
01002 pump_loop(mPump, 0.1f);
01003
01004
01005 LLSocket::ptr_t client = LLSocket::create(mPool, LLSocket::STREAM_TCP);
01006 LLHost server_host("127.0.0.1", SERVER_LISTEN_PORT);
01007 bool connected = client->blockingConnect(server_host);
01008 ensure("Connected to server", connected);
01009 lldebugs << "connected" << llendl;
01010
01011
01012
01013
01014 chain.clear();
01015 chain.push_back(LLIOPipe::ptr_t(new LLPipeStringInjector("hi")));
01016 chain.push_back(LLIOPipe::ptr_t(new LLIOSocketWriter(client)));
01017 chain.push_back(LLIOPipe::ptr_t(new LLIONull));
01018 mPump->addChain(chain, SHORT_CHAIN_EXPIRY_SECS / 2.0f);
01019
01020
01021
01022 F32 elapsed = pump_loop(mPump, SHORT_CHAIN_EXPIRY_SECS * 2.0f);
01023 ensure("Did not take too long", (elapsed < 3.0f));
01024 }
01025
01026 template<> template<>
01027 void fitness_test_object::test<3>()
01028 {
01029 lldebugs << "fitness_test_object::test<3>()" << llendl;
01030
01031
01032 LLPumpIO::chain_t chain;
01033 typedef LLCloneIOFactory<LLIOFuzz> emitter_t;
01034 emitter_t* emitter = new emitter_t(new LLIOFuzz(1000000));
01035 boost::shared_ptr<LLChainIOFactory> factory(emitter);
01036 LLIOServerSocket* server = new LLIOServerSocket(
01037 mPool,
01038 mSocket,
01039 factory);
01040 server->setResponseTimeout(SHORT_CHAIN_EXPIRY_SECS);
01041 chain.push_back(LLIOPipe::ptr_t(server));
01042 mPump->addChain(chain, NEVER_CHAIN_EXPIRY_SECS);
01043
01044
01045 pump_loop(mPump, 0.1f);
01046
01047
01048 LLSocket::ptr_t client = LLSocket::create(mPool, LLSocket::STREAM_TCP);
01049 LLHost server_host("127.0.0.1", SERVER_LISTEN_PORT);
01050 bool connected = client->blockingConnect(server_host);
01051 ensure("Connected to server", connected);
01052 lldebugs << "connected" << llendl;
01053
01054
01055
01056
01057 chain.clear();
01058 chain.push_back(LLIOPipe::ptr_t(new LLPipeStringInjector("hi")));
01059 chain.push_back(LLIOPipe::ptr_t(new LLIOSocketWriter(client)));
01060 chain.push_back(LLIOPipe::ptr_t(new LLIONull));
01061 mPump->addChain(chain, SHORT_CHAIN_EXPIRY_SECS * 2.0f);
01062
01063
01064
01065 F32 elapsed = pump_loop(mPump, SHORT_CHAIN_EXPIRY_SECS * 2.0f + 1.0f);
01066 ensure("Did not take too long", (elapsed < 4.0f));
01067 }
01068
01069 template<> template<>
01070 void fitness_test_object::test<4>()
01071 {
01072 lldebugs << "fitness_test_object::test<4>()" << llendl;
01073
01074
01075 LLPumpIO::chain_t chain;
01076 typedef LLCloneIOFactory<LLIOFuzz> emitter_t;
01077 emitter_t* emitter = new emitter_t(new LLIOFuzz(1000000));
01078 boost::shared_ptr<LLChainIOFactory> factory(emitter);
01079 LLIOServerSocket* server = new LLIOServerSocket(
01080 mPool,
01081 mSocket,
01082 factory);
01083 server->setResponseTimeout(SHORT_CHAIN_EXPIRY_SECS + 2.0f);
01084 chain.push_back(LLIOPipe::ptr_t(server));
01085 mPump->addChain(chain, NEVER_CHAIN_EXPIRY_SECS);
01086
01087
01088 pump_loop(mPump, 0.1f);
01089
01090
01091 LLSocket::ptr_t client = LLSocket::create(mPool, LLSocket::STREAM_TCP);
01092 LLHost server_host("127.0.0.1", SERVER_LISTEN_PORT);
01093 bool connected = client->blockingConnect(server_host);
01094 ensure("Connected to server", connected);
01095 lldebugs << "connected" << llendl;
01096
01097
01098
01099
01100 chain.clear();
01101 chain.push_back(LLIOPipe::ptr_t(new LLPipeStringInjector("hi")));
01102 chain.push_back(LLIOPipe::ptr_t(new LLIOSocketWriter(client)));
01103 chain.push_back(LLIOPipe::ptr_t(new LLIONull));
01104 mPump->addChain(chain, NEVER_CHAIN_EXPIRY_SECS);
01105
01106
01107
01108 F32 elapsed = pump_loop(mPump, SHORT_CHAIN_EXPIRY_SECS + 3.0f);
01109 ensure("Did not take too long", (elapsed < DEFAULT_CHAIN_EXPIRY_SECS));
01110 }
01111 }
01112
01113 namespace tut
01114 {
01115 struct rpc_server_data
01116 {
01117 class LLSimpleRPCResponse : public LLSDRPCResponse
01118 {
01119 public:
01120 LLSimpleRPCResponse(LLSD* response) :
01121 mResponsePtr(response)
01122 {
01123 }
01124 ~LLSimpleRPCResponse() {}
01125 virtual bool response(LLPumpIO* pump)
01126 {
01127 *mResponsePtr = mReturnValue;
01128 return true;
01129 }
01130 virtual bool fault(LLPumpIO* pump)
01131 {
01132 *mResponsePtr = mReturnValue;
01133 return false;
01134 }
01135 virtual bool error(LLPumpIO* pump)
01136 {
01137 ensure("LLSimpleRPCResponse::error()", false);
01138 return false;
01139 }
01140 public:
01141 LLSD* mResponsePtr;
01142 };
01143
01144 class LLSimpleRPCClient : public LLSDRPCClient
01145 {
01146 public:
01147 LLSimpleRPCClient(LLSD* response) :
01148 mResponsePtr(response)
01149 {
01150 }
01151 ~LLSimpleRPCClient() {}
01152 void echo(const LLSD& parameter)
01153 {
01154 LLSimpleRPCResponse* resp;
01155 resp = new LLSimpleRPCResponse(mResponsePtr);
01156 static const std::string URI_NONE;
01157 static const std::string METHOD_ECHO("echo");
01158 call(URI_NONE, METHOD_ECHO, parameter, resp, EPBQ_CALLBACK);
01159 }
01160 public:
01161 LLSD* mResponsePtr;
01162 };
01163
01164 class LLSimpleRPCServer : public LLSDRPCServer
01165 {
01166 public:
01167 LLSimpleRPCServer()
01168 {
01169 mMethods["echo"] = new mem_fn_t(
01170 this,
01171 &LLSimpleRPCServer::rpc_Echo);
01172 }
01173 ~LLSimpleRPCServer() {}
01174 protected:
01175 typedef LLSDRPCMethodCall<LLSimpleRPCServer> mem_fn_t;
01176 ESDRPCSStatus rpc_Echo(
01177 const LLSD& parameter,
01178 const LLChannelDescriptors& channels,
01179 LLBufferArray* data)
01180 {
01181 buildResponse(channels, data, parameter);
01182 return ESDRPCS_DONE;
01183 }
01184 };
01185
01186 apr_pool_t* mPool;
01187 LLPumpIO* mPump;
01188 LLPumpIO::chain_t mChain;
01189 LLSimpleRPCClient* mClient;
01190 LLSD mResponse;
01191
01192 rpc_server_data() :
01193 mPool(NULL),
01194 mPump(NULL),
01195 mClient(NULL)
01196 {
01197 apr_pool_create(&mPool, NULL);
01198 mPump = new LLPumpIO(mPool);
01199 mClient = new LLSimpleRPCClient(&mResponse);
01200 mChain.push_back(LLIOPipe::ptr_t(mClient));
01201 mChain.push_back(LLIOPipe::ptr_t(new LLFilterSD2XMLRPCRequest));
01202 mChain.push_back(LLIOPipe::ptr_t(new LLFilterXMLRPCRequest2LLSD));
01203 mChain.push_back(LLIOPipe::ptr_t(new LLSimpleRPCServer));
01204 mChain.push_back(LLIOPipe::ptr_t(new LLFilterSD2XMLRPCResponse));
01205 mChain.push_back(LLIOPipe::ptr_t(new LLFilterXMLRPCResponse2LLSD));
01206 mChain.push_back(LLIOPipe::ptr_t(mClient));
01207 }
01208 ~rpc_server_data()
01209 {
01210 mChain.clear();
01211 delete mPump;
01212 mPump = NULL;
01213 apr_pool_destroy(mPool);
01214 mPool = NULL;
01215 }
01216 void pump_loop(const LLSD& request)
01217 {
01218 LLTimer timer;
01219 timer.setTimerExpirySec(1.0f);
01220 mClient->echo(request);
01221 mPump->addChain(mChain, DEFAULT_CHAIN_EXPIRY_SECS);
01222 while(mResponse.isUndefined() && !timer.hasExpired())
01223 {
01224 mPump->pump();
01225 mPump->callback();
01226 }
01227 }
01228 };
01229 typedef test_group<rpc_server_data> rpc_server_test;
01230 typedef rpc_server_test::object rpc_server_object;
01231 tut::rpc_server_test rpc("rpc_server");
01232
01233 template<> template<>
01234 void rpc_server_object::test<1>()
01235 {
01236 LLSD request;
01237 request = 1;
01238 pump_loop(request);
01239
01240
01241 ensure_equals("integer request response", mResponse.asInteger(), 1);
01242 }
01243
01244 template<> template<>
01245 void rpc_server_object::test<2>()
01246 {
01247 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");
01248 std::stringstream stream;
01249 stream << "{'task_id':ucc706f2d-0b68-68f8-11a4-f1043ff35ca0}\n{\n\tname\tObject|\n\tpermissions 0\n}";
01250 std::vector<U8> expected_binary;
01251 expected_binary.resize(stream.str().size());
01252 memcpy(&expected_binary[0], stream.str().c_str(), stream.str().size());
01253 stream.str("");
01254 stream << "[{'uri':'" << uri << "'}, {'version':i1}, "
01255 << "{'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'], "
01256 << "'attachment_data':["
01257 << "{'attachment_point':i2, 'item_id':'d6852c11-a74e-309a-0462-50533f1ef9b3', 'asset_id':'c69b29b1-8944-58ae-a7c5-2ca7b23e22fb'},"
01258 << "{'attachment_point':i10, 'item_id':'ff852c22-a74e-309a-0462-50533f1ef900', 'asset_data':b(" << expected_binary.size() << ")\"";
01259 stream.write((const char*)&expected_binary[0], expected_binary.size());
01260 stream << "\"}"
01261 << "]"
01262 << "}]";
01263
01264 LLSD request;
01265 S32 count = LLSDSerialize::fromNotation(request, stream);
01266 ensure("parsed something", (count > 0));
01267
01268 pump_loop(request);
01269 ensure_equals("return type", mResponse.type(), LLSD::TypeArray);
01270 ensure_equals("return size", mResponse.size(), 3);
01271
01272 ensure_equals(
01273 "uri parameter type",
01274 mResponse[0].type(),
01275 LLSD::TypeMap);
01276 ensure_equals(
01277 "uri type",
01278 mResponse[0]["uri"].type(),
01279 LLSD::TypeString);
01280 ensure_equals("uri value", mResponse[0]["uri"].asString(), uri);
01281
01282 ensure_equals(
01283 "version parameter type",
01284 mResponse[1].type(),
01285 LLSD::TypeMap);
01286 ensure_equals(
01287 "version type",
01288 mResponse[1]["version"].type(),
01289 LLSD::TypeInteger);
01290 ensure_equals(
01291 "version value",
01292 mResponse[1]["version"].asInteger(),
01293 1);
01294
01295 ensure_equals("agent params type", mResponse[2].type(), LLSD::TypeMap);
01296 LLSD attachment_data = mResponse[2]["attachment_data"];
01297 ensure("attachment data exists", attachment_data.isDefined());
01298 ensure_equals(
01299 "attachment type",
01300 attachment_data.type(),
01301 LLSD::TypeArray);
01302 ensure_equals(
01303 "attachment type 0",
01304 attachment_data[0].type(),
01305 LLSD::TypeMap);
01306 ensure_equals(
01307 "attachment type 1",
01308 attachment_data[1].type(),
01309 LLSD::TypeMap);
01310 ensure_equals("attachment size 1", attachment_data[1].size(), 3);
01311 ensure_equals(
01312 "asset data type",
01313 attachment_data[1]["asset_data"].type(),
01314 LLSD::TypeBinary);
01315 std::vector<U8> actual_binary;
01316 actual_binary = attachment_data[1]["asset_data"].asBinary();
01317 ensure_equals(
01318 "binary data size",
01319 actual_binary.size(),
01320 expected_binary.size());
01321 ensure(
01322 "binary data",
01323 (0 == memcmp(
01324 &actual_binary[0],
01325 &expected_binary[0],
01326 expected_binary.size())));
01327 }
01328
01329 template<> template<>
01330 void rpc_server_object::test<3>()
01331 {
01332 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");
01333
01334 LLBufferArray buffer;
01335 LLChannelDescriptors buffer_channels = buffer.nextChannel();
01336 LLBufferStream stream(buffer_channels, &buffer);
01337 stream << "[{'uri':'" << uri << "'}, {'version':i1}, "
01338 << "{'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'], "
01339 << "'attachment_data':["
01340 << "{'attachment_point':i2, 'item_id':'d6852c11-a74e-309a-0462-50533f1ef9b3', 'asset_id':'c69b29b1-8944-58ae-a7c5-2ca7b23e22fb'},";
01341
01342 std::stringstream tmp_str;
01343 tmp_str << "{'task_id':ucc706f2d-0b68-68f8-11a4-f1043ff35ca0}\n{\n\tname\tObject|\n\tpermissions 0\n}";
01344 std::vector<U8> expected_binary;
01345 expected_binary.resize(tmp_str.str().size());
01346 memcpy(
01347 &expected_binary[0],
01348 tmp_str.str().c_str(),
01349 tmp_str.str().size());
01350
01351 LLBufferArray attachment_buffer;
01352 LLChannelDescriptors attach_channels = attachment_buffer.nextChannel();
01353 LLBufferStream attach_stream(attach_channels, &attachment_buffer);
01354 attach_stream.write((const char*)&expected_binary[0], expected_binary.size());
01355 attach_stream.flush();
01356 S32 len = attachment_buffer.countAfter(attach_channels.out(), NULL);
01357 stream << "{'attachment_point':i10, 'item_id':'ff852c22-a74e-309a-0462-50533f1ef900', 'asset_data':b(" << len << ")\"";
01358 stream.flush();
01359 buffer.takeContents(attachment_buffer);
01360 stream << "\"}]}]";
01361 stream.flush();
01362
01363 LLChannelDescriptors read_channel = buffer.nextChannel();
01364 LLBufferStream read_stream(read_channel, &buffer);
01365 LLSD request;
01366 S32 count = LLSDSerialize::fromNotation(request, read_stream);
01367 ensure("parsed something", (count > 0));
01368 ensure("deserialized", request.isDefined());
01369
01370
01371 pump_loop(request);
01372
01373 ensure_equals("return type", mResponse.type(), LLSD::TypeArray);
01374 ensure_equals("return size", mResponse.size(), 3);
01375
01376 LLSD child = mResponse[0];
01377 ensure("uri map exists", child.isDefined());
01378 ensure_equals("uri parameter type", child.type(), LLSD::TypeMap);
01379 ensure("uri string exists", child.has("uri"));
01380 ensure_equals("uri type", child["uri"].type(), LLSD::TypeString);
01381 ensure_equals("uri value", child["uri"].asString(), uri);
01382
01383 child = mResponse[1];
01384 ensure("version map exists", child.isDefined());
01385 ensure_equals("version param type", child.type(), LLSD::TypeMap);
01386 ensure_equals(
01387 "version type",
01388 child["version"].type(),
01389 LLSD::TypeInteger);
01390 ensure_equals("version value", child["version"].asInteger(), 1);
01391
01392 child = mResponse[2];
01393 ensure("agent params map exists", child.isDefined());
01394 ensure_equals("agent params type", child.type(), LLSD::TypeMap);
01395 child = child["attachment_data"];
01396 ensure("attachment data exists", child.isDefined());
01397 ensure_equals("attachment type", child.type(), LLSD::TypeArray);
01398 LLSD attachment = child[0];
01399 ensure_equals("attachment type 0", attachment.type(), LLSD::TypeMap);
01400 attachment = child[1];
01401 ensure_equals("attachment type 1", attachment.type(), LLSD::TypeMap);
01402 ensure_equals("attachment size 1", attachment.size(), 3);
01403 ensure_equals(
01404 "asset data type",
01405 attachment["asset_data"].type(),
01406 LLSD::TypeBinary);
01407 std::vector<U8> actual_binary = attachment["asset_data"].asBinary();
01408 ensure_equals(
01409 "binary data size",
01410 actual_binary.size(),
01411 expected_binary.size());
01412 ensure(
01413 "binary data",
01414 (0 == memcmp(
01415 &actual_binary[0],
01416 &expected_binary[0],
01417 expected_binary.size())));
01418 }
01419
01420 template<> template<>
01421 void rpc_server_object::test<4>()
01422 {
01423 std::string message("parcel '' is naughty.");
01424 std::stringstream str;
01425 str << "{'message':'" << LLSDNotationFormatter::escapeString(message)
01426 << "'}";
01427 LLSD request;
01428 S32 count = LLSDSerialize::fromNotation(request, str);
01429 ensure_equals("parse count", count, 2);
01430 ensure_equals("request type", request.type(), LLSD::TypeMap);
01431 pump_loop(request);
01432 ensure("valid response", mResponse.isDefined());
01433 ensure_equals("response type", mResponse.type(), LLSD::TypeMap);
01434 std::string actual = mResponse["message"].asString();
01435 ensure_equals("message contents", actual, message);
01436 }
01437
01438 template<> template<>
01439 void rpc_server_object::test<5>()
01440 {
01441
01442
01443
01444
01445
01446
01447 std::string val = "[{'failures':!,'successfuls':[u3c115e51-04f4-523c-9fa6-98aff1034730]}]";
01448 std::istringstream istr;
01449 istr.str(val);
01450 LLSD sd;
01451 LLSDSerialize::fromNotation(sd, istr);
01452 pump_loop(sd);
01453 ensure("valid response", mResponse.isDefined());
01454 ensure_equals("parsed type", mResponse.type(), LLSD::TypeMap);
01455 ensure_equals("parsed size", mResponse.size(), 2);
01456 LLSD failures = mResponse["failures"];
01457 ensure_equals("no failures.", failures.asBoolean(), false);
01458 LLSD success = mResponse["successfuls"];
01459 ensure_equals("success type", success.type(), LLSD::TypeArray);
01460 ensure_equals("success size", success.size(), 1);
01461 ensure_equals(
01462 "success instance type",
01463 success[0].type(),
01464 LLSD::TypeString);
01465 }
01466
01467
01468
01469
01470
01471
01472
01473
01474
01475
01476
01477
01478
01479
01480
01481
01482
01483
01484
01485
01486
01487
01488
01489
01490
01491
01492
01493
01494
01495
01496
01497
01498
01499
01500
01501
01502
01503
01504
01505
01506
01507
01508
01509
01510
01511
01512 }
01513
01514
01515
01516
01517