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, total_size);
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, total_size);
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(
00739 data,
00740 istr,
00741 mBuffer.count(ch.in()));
00742 ensure("parsed something", (count > 0));
00743 ensure("sd parsed", data.isDefined());
00744 ensure_equals("sd type", data.type(), LLSD::TypeMap);
00745 ensure("has method", data.has("method"));
00746 ensure("has parameter", data.has("parameter"));
00747 LLSD parameter = data["parameter"];
00748 ensure_equals("parameter is array", parameter.type(), LLSD::TypeArray);
00749 LLSD agent_params = parameter[2];
00750 std::string s_value;
00751 s_value = agent_params["last_name"].asString();
00752 ensure_equals("last name", s_value, std::string("Linden"));
00753 s_value = agent_params["first_name"].asString();
00754 ensure_equals("first name", s_value, std::string("Kelly"));
00755 s_value = agent_params["agent_access"].asString();
00756 ensure_equals("agent access", s_value, std::string("M"));
00757 s_value = agent_params["group_name"].asString();
00758 ensure_equals("group name", s_value, std::string("test!"));
00759 s_value = agent_params["group_title"].asString();
00760 ensure_equals("group title", s_value, std::string("-> !BLING! <-"));
00761
00762 LLUUID agent_id("0e346d8b-4433-4d66-a6b0-fd37083abc4c");
00763 LLUUID id = agent_params["agent_id"];
00764 ensure_equals("agent id", id, agent_id);
00765 LLUUID session_id("324cfa9f-fe5d-4d1c-a317-35f20a86a4d1");
00766 id = agent_params["session_id"];
00767 ensure_equals("session id", id, session_id);
00768 LLUUID group_id ("8615c885-9cf0-bf0a-6e40-0c11462aa652");
00769 id = agent_params["group_id"];
00770 ensure_equals("group id", id, group_id);
00771
00772 S32 i_val = agent_params["limited_to_estate"];
00773 ensure_equals("limited to estate", i_val, 1);
00774 i_val = agent_params["circuit_code"];
00775 ensure_equals("circuit code", i_val, 124);
00776 }
00777
00778
00779 template<> template<>
00780 void bas_object::test<11>()
00781 {
00782 std::string val = "{!'foo'@:#'bar'}";
00783 std::istringstream istr;
00784 istr.str(val);
00785 LLSD sd;
00786 S32 count = LLSDSerialize::fromNotation(sd, istr, val.size());
00787 ensure_equals("parser error return value", count, -1);
00788 ensure("data undefined", sd.isUndefined());
00789 }
00790
00791 template<> template<>
00792 void bas_object::test<12>()
00793 {
00794 std::string val = "{!'foo':[i1,'hi',{@'bar'#:[$i2%,^'baz'&]*}+]=}";
00795 std::istringstream istr;
00796 istr.str(val);
00797 LLSD sd;
00798 S32 count = LLSDSerialize::fromNotation(sd, istr, val.size());
00799 ensure_equals("parser error return value", count, -1);
00800 ensure("data undefined", sd.isUndefined());
00801 }
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817 }
00818
00819
00820 namespace tut
00821 {
00822 class PumpAndChainTestData
00823 {
00824 protected:
00825 apr_pool_t* mPool;
00826 LLPumpIO* mPump;
00827 LLPumpIO::chain_t mChain;
00828
00829 public:
00830 PumpAndChainTestData()
00831 {
00832 apr_pool_create(&mPool, NULL);
00833 mPump = new LLPumpIO(mPool);
00834 }
00835
00836 ~PumpAndChainTestData()
00837 {
00838 mChain.clear();
00839 delete mPump;
00840 apr_pool_destroy(mPool);
00841 }
00842 };
00843 typedef test_group<PumpAndChainTestData> PumpAndChainTestGroup;
00844 typedef PumpAndChainTestGroup::object PumpAndChainTestObject;
00845 PumpAndChainTestGroup pumpAndChainTestGroup("pump_and_chain");
00846
00847 template<> template<>
00848 void PumpAndChainTestObject::test<1>()
00849 {
00850 LLPipeStringExtractor* extractor = new LLPipeStringExtractor();
00851
00852 mChain.push_back(LLIOPipe::ptr_t(new LLIOFlush));
00853 mChain.push_back(LLIOPipe::ptr_t(extractor));
00854
00855 LLTimer timer;
00856 timer.setTimerExpirySec(100.0f);
00857
00858 mPump->addChain(mChain, DEFAULT_CHAIN_EXPIRY_SECS);
00859 while(!extractor->done() && !timer.hasExpired())
00860 {
00861 mPump->pump();
00862 mPump->callback();
00863 }
00864
00865 ensure("reading string finished", extractor->done());
00866 ensure_equals("string was empty", extractor->string(), "");
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
00894
00895
00896 namespace tut
00897 {
00901 struct pipe_and_pump_fitness
00902 {
00903 public:
00904 enum
00905 {
00906 SERVER_LISTEN_PORT = 13050
00907 };
00908
00909 pipe_and_pump_fitness()
00910 {
00911 LLFrameTimer::updateFrameTime();
00912 apr_pool_create(&mPool, NULL);
00913 mPump = new LLPumpIO(mPool);
00914 mSocket = LLSocket::create(
00915 mPool,
00916 LLSocket::STREAM_TCP,
00917 SERVER_LISTEN_PORT);
00918 }
00919
00920 ~pipe_and_pump_fitness()
00921 {
00922 mSocket.reset();
00923 delete mPump;
00924 apr_pool_destroy(mPool);
00925 }
00926
00927 protected:
00928 apr_pool_t* mPool;
00929 LLPumpIO* mPump;
00930 LLSocket::ptr_t mSocket;
00931 };
00932 typedef test_group<pipe_and_pump_fitness> fitness_test_group;
00933 typedef fitness_test_group::object fitness_test_object;
00934 fitness_test_group fitness("pipe and pump fitness");
00935
00936 template<> template<>
00937 void fitness_test_object::test<1>()
00938 {
00939 lldebugs << "fitness_test_object::test<1>()" << llendl;
00940
00941
00942
00943
00944 LLPumpIO::chain_t chain;
00945 typedef LLCloneIOFactory<LLPipeStringInjector> emitter_t;
00946 emitter_t* emitter = new emitter_t(
00947 new LLPipeStringInjector("suckers never play me"));
00948 boost::shared_ptr<LLChainIOFactory> factory(emitter);
00949 LLIOServerSocket* server = new LLIOServerSocket(
00950 mPool,
00951 mSocket,
00952 factory);
00953 server->setResponseTimeout(SHORT_CHAIN_EXPIRY_SECS);
00954 chain.push_back(LLIOPipe::ptr_t(server));
00955 mPump->addChain(chain, NEVER_CHAIN_EXPIRY_SECS);
00956
00957
00958
00959
00960 pump_loop(mPump, 0.1f);
00961
00962
00963
00964
00965 LLSocket::ptr_t client = LLSocket::create(mPool, LLSocket::STREAM_TCP);
00966 LLHost server_host("127.0.0.1", SERVER_LISTEN_PORT);
00967 bool connected = client->blockingConnect(server_host);
00968 ensure("Connected to server", connected);
00969 lldebugs << "connected" << llendl;
00970
00971
00972
00973
00974 chain.clear();
00975 chain.push_back(LLIOPipe::ptr_t(new LLPipeStringInjector("hi")));
00976 chain.push_back(LLIOPipe::ptr_t(new LLIOSocketWriter(client)));
00977 chain.push_back(LLIOPipe::ptr_t(new LLIONull));
00978 mPump->addChain(chain, 1.0f);
00979
00980
00981
00982 F32 elapsed = pump_loop(mPump, 2.0f);
00983 ensure("Did not take too long", (elapsed < 3.0f));
00984 }
00985
00986 template<> template<>
00987 void fitness_test_object::test<2>()
00988 {
00989 lldebugs << "fitness_test_object::test<2>()" << llendl;
00990
00991
00992 LLPumpIO::chain_t chain;
00993 typedef LLCloneIOFactory<LLIOFuzz> emitter_t;
00994 emitter_t* emitter = new emitter_t(new LLIOFuzz(1000000));
00995 boost::shared_ptr<LLChainIOFactory> factory(emitter);
00996 LLIOServerSocket* server = new LLIOServerSocket(
00997 mPool,
00998 mSocket,
00999 factory);
01000 server->setResponseTimeout(SHORT_CHAIN_EXPIRY_SECS);
01001 chain.push_back(LLIOPipe::ptr_t(server));
01002 mPump->addChain(chain, NEVER_CHAIN_EXPIRY_SECS);
01003
01004
01005 pump_loop(mPump, 0.1f);
01006
01007
01008 LLSocket::ptr_t client = LLSocket::create(mPool, LLSocket::STREAM_TCP);
01009 LLHost server_host("127.0.0.1", SERVER_LISTEN_PORT);
01010 bool connected = client->blockingConnect(server_host);
01011 ensure("Connected to server", connected);
01012 lldebugs << "connected" << llendl;
01013
01014
01015
01016
01017 chain.clear();
01018 chain.push_back(LLIOPipe::ptr_t(new LLPipeStringInjector("hi")));
01019 chain.push_back(LLIOPipe::ptr_t(new LLIOSocketWriter(client)));
01020 chain.push_back(LLIOPipe::ptr_t(new LLIONull));
01021 mPump->addChain(chain, SHORT_CHAIN_EXPIRY_SECS / 2.0f);
01022
01023
01024
01025 F32 elapsed = pump_loop(mPump, SHORT_CHAIN_EXPIRY_SECS * 2.0f);
01026 ensure("Did not take too long", (elapsed < 3.0f));
01027 }
01028
01029 template<> template<>
01030 void fitness_test_object::test<3>()
01031 {
01032 lldebugs << "fitness_test_object::test<3>()" << llendl;
01033
01034
01035 LLPumpIO::chain_t chain;
01036 typedef LLCloneIOFactory<LLIOFuzz> emitter_t;
01037 emitter_t* emitter = new emitter_t(new LLIOFuzz(1000000));
01038 boost::shared_ptr<LLChainIOFactory> factory(emitter);
01039 LLIOServerSocket* server = new LLIOServerSocket(
01040 mPool,
01041 mSocket,
01042 factory);
01043 server->setResponseTimeout(SHORT_CHAIN_EXPIRY_SECS);
01044 chain.push_back(LLIOPipe::ptr_t(server));
01045 mPump->addChain(chain, NEVER_CHAIN_EXPIRY_SECS);
01046
01047
01048 pump_loop(mPump, 0.1f);
01049
01050
01051 LLSocket::ptr_t client = LLSocket::create(mPool, LLSocket::STREAM_TCP);
01052 LLHost server_host("127.0.0.1", SERVER_LISTEN_PORT);
01053 bool connected = client->blockingConnect(server_host);
01054 ensure("Connected to server", connected);
01055 lldebugs << "connected" << llendl;
01056
01057
01058
01059
01060 chain.clear();
01061 chain.push_back(LLIOPipe::ptr_t(new LLPipeStringInjector("hi")));
01062 chain.push_back(LLIOPipe::ptr_t(new LLIOSocketWriter(client)));
01063 chain.push_back(LLIOPipe::ptr_t(new LLIONull));
01064 mPump->addChain(chain, SHORT_CHAIN_EXPIRY_SECS * 2.0f);
01065
01066
01067
01068 F32 elapsed = pump_loop(mPump, SHORT_CHAIN_EXPIRY_SECS * 2.0f + 1.0f);
01069 ensure("Did not take too long", (elapsed < 4.0f));
01070 }
01071
01072 template<> template<>
01073 void fitness_test_object::test<4>()
01074 {
01075 lldebugs << "fitness_test_object::test<4>()" << llendl;
01076
01077
01078 LLPumpIO::chain_t chain;
01079 typedef LLCloneIOFactory<LLIOFuzz> emitter_t;
01080 emitter_t* emitter = new emitter_t(new LLIOFuzz(1000000));
01081 boost::shared_ptr<LLChainIOFactory> factory(emitter);
01082 LLIOServerSocket* server = new LLIOServerSocket(
01083 mPool,
01084 mSocket,
01085 factory);
01086 server->setResponseTimeout(SHORT_CHAIN_EXPIRY_SECS + 1.80f);
01087 chain.push_back(LLIOPipe::ptr_t(server));
01088 mPump->addChain(chain, NEVER_CHAIN_EXPIRY_SECS);
01089
01090
01091 pump_loop(mPump, 0.1f);
01092
01093
01094 LLSocket::ptr_t client = LLSocket::create(mPool, LLSocket::STREAM_TCP);
01095 LLHost server_host("127.0.0.1", SERVER_LISTEN_PORT);
01096 bool connected = client->blockingConnect(server_host);
01097 ensure("Connected to server", connected);
01098 lldebugs << "connected" << llendl;
01099
01100
01101
01102
01103 chain.clear();
01104 chain.push_back(LLIOPipe::ptr_t(new LLPipeStringInjector("hi")));
01105 chain.push_back(LLIOPipe::ptr_t(new LLIOSocketWriter(client)));
01106 chain.push_back(LLIOPipe::ptr_t(new LLIONull));
01107 mPump->addChain(chain, NEVER_CHAIN_EXPIRY_SECS);
01108
01109
01110
01111 F32 elapsed = pump_loop(mPump, SHORT_CHAIN_EXPIRY_SECS + 3.0f);
01112 ensure("Did not take too long", (elapsed < DEFAULT_CHAIN_EXPIRY_SECS));
01113 }
01114
01115 template<> template<>
01116 void fitness_test_object::test<5>()
01117 {
01118
01119 LLPumpIO::chain_t chain;
01120 typedef LLCloneIOFactory<LLIOSleeper> sleeper_t;
01121 sleeper_t* sleeper = new sleeper_t(new LLIOSleeper);
01122 boost::shared_ptr<LLChainIOFactory> factory(sleeper);
01123 LLIOServerSocket* server = new LLIOServerSocket(
01124 mPool,
01125 mSocket,
01126 factory);
01127 server->setResponseTimeout(1.0);
01128 chain.push_back(LLIOPipe::ptr_t(server));
01129 mPump->addChain(chain, NEVER_CHAIN_EXPIRY_SECS);
01130
01131 pump_loop(mPump, 0.1f);
01132 U32 count = mPump->runningChains();
01133 ensure_equals("server chain onboard", count, 1);
01134 lldebugs << "** Server is up." << llendl;
01135
01136
01137 LLSocket::ptr_t client = LLSocket::create(mPool, LLSocket::STREAM_TCP);
01138 LLHost server_host("127.0.0.1", SERVER_LISTEN_PORT);
01139 bool connected = client->blockingConnect(server_host);
01140 ensure("Connected to server", connected);
01141 lldebugs << "connected" << llendl;
01142 F32 elapsed = pump_loop(mPump,0.1f);
01143 count = mPump->runningChains();
01144 ensure_equals("server chain onboard", count, 2);
01145 lldebugs << "** Client is connected." << llendl;
01146
01147
01148
01149
01150 chain.clear();
01151 chain.push_back(LLIOPipe::ptr_t(new LLPipeStringInjector("hi")));
01152 chain.push_back(LLIOPipe::ptr_t(new LLIOSocketWriter(client)));
01153 chain.push_back(LLIOPipe::ptr_t(new LLIONull));
01154 mPump->addChain(chain, 0.2f);
01155 chain.clear();
01156
01157
01158 elapsed = pump_loop(mPump,0.1f);
01159 count = mPump->runningChains();
01160 ensure_equals("client chain onboard", count, 3);
01161 lldebugs << "** request should have been sent." << llendl;
01162
01163
01164
01165 elapsed = pump_loop(mPump,0.2f);
01166 count = mPump->runningChains();
01167 ensure_equals("client chain timed out ", count, 2);
01168 lldebugs << "** client chain should be closed." << llendl;
01169
01170
01171 elapsed = pump_loop(mPump,1.0f);
01172 count = mPump->runningChains();
01173 ensure_equals("accepted socked close", count, 1);
01174 lldebugs << "** Sleeper should have timed out.." << llendl;
01175 }
01176 }
01177
01178 namespace tut
01179 {
01180 struct rpc_server_data
01181 {
01182 class LLSimpleRPCResponse : public LLSDRPCResponse
01183 {
01184 public:
01185 LLSimpleRPCResponse(LLSD* response) :
01186 mResponsePtr(response)
01187 {
01188 }
01189 ~LLSimpleRPCResponse() {}
01190 virtual bool response(LLPumpIO* pump)
01191 {
01192 *mResponsePtr = mReturnValue;
01193 return true;
01194 }
01195 virtual bool fault(LLPumpIO* pump)
01196 {
01197 *mResponsePtr = mReturnValue;
01198 return false;
01199 }
01200 virtual bool error(LLPumpIO* pump)
01201 {
01202 ensure("LLSimpleRPCResponse::error()", false);
01203 return false;
01204 }
01205 public:
01206 LLSD* mResponsePtr;
01207 };
01208
01209 class LLSimpleRPCClient : public LLSDRPCClient
01210 {
01211 public:
01212 LLSimpleRPCClient(LLSD* response) :
01213 mResponsePtr(response)
01214 {
01215 }
01216 ~LLSimpleRPCClient() {}
01217 void echo(const LLSD& parameter)
01218 {
01219 LLSimpleRPCResponse* resp;
01220 resp = new LLSimpleRPCResponse(mResponsePtr);
01221 static const std::string URI_NONE;
01222 static const std::string METHOD_ECHO("echo");
01223 call(URI_NONE, METHOD_ECHO, parameter, resp, EPBQ_CALLBACK);
01224 }
01225 public:
01226 LLSD* mResponsePtr;
01227 };
01228
01229 class LLSimpleRPCServer : public LLSDRPCServer
01230 {
01231 public:
01232 LLSimpleRPCServer()
01233 {
01234 mMethods["echo"] = new mem_fn_t(
01235 this,
01236 &LLSimpleRPCServer::rpc_Echo);
01237 }
01238 ~LLSimpleRPCServer() {}
01239 protected:
01240 typedef LLSDRPCMethodCall<LLSimpleRPCServer> mem_fn_t;
01241 ESDRPCSStatus rpc_Echo(
01242 const LLSD& parameter,
01243 const LLChannelDescriptors& channels,
01244 LLBufferArray* data)
01245 {
01246 buildResponse(channels, data, parameter);
01247 return ESDRPCS_DONE;
01248 }
01249 };
01250
01251 apr_pool_t* mPool;
01252 LLPumpIO* mPump;
01253 LLPumpIO::chain_t mChain;
01254 LLSimpleRPCClient* mClient;
01255 LLSD mResponse;
01256
01257 rpc_server_data() :
01258 mPool(NULL),
01259 mPump(NULL),
01260 mClient(NULL)
01261 {
01262 apr_pool_create(&mPool, NULL);
01263 mPump = new LLPumpIO(mPool);
01264 mClient = new LLSimpleRPCClient(&mResponse);
01265 mChain.push_back(LLIOPipe::ptr_t(mClient));
01266 mChain.push_back(LLIOPipe::ptr_t(new LLFilterSD2XMLRPCRequest));
01267 mChain.push_back(LLIOPipe::ptr_t(new LLFilterXMLRPCRequest2LLSD));
01268 mChain.push_back(LLIOPipe::ptr_t(new LLSimpleRPCServer));
01269 mChain.push_back(LLIOPipe::ptr_t(new LLFilterSD2XMLRPCResponse));
01270 mChain.push_back(LLIOPipe::ptr_t(new LLFilterXMLRPCResponse2LLSD));
01271 mChain.push_back(LLIOPipe::ptr_t(mClient));
01272 }
01273 ~rpc_server_data()
01274 {
01275 mChain.clear();
01276 delete mPump;
01277 mPump = NULL;
01278 apr_pool_destroy(mPool);
01279 mPool = NULL;
01280 }
01281 void pump_loop(const LLSD& request)
01282 {
01283 LLTimer timer;
01284 timer.setTimerExpirySec(1.0f);
01285 mClient->echo(request);
01286 mPump->addChain(mChain, DEFAULT_CHAIN_EXPIRY_SECS);
01287 while(mResponse.isUndefined() && !timer.hasExpired())
01288 {
01289 mPump->pump();
01290 mPump->callback();
01291 }
01292 }
01293 };
01294 typedef test_group<rpc_server_data> rpc_server_test;
01295 typedef rpc_server_test::object rpc_server_object;
01296 tut::rpc_server_test rpc("rpc_server");
01297
01298 template<> template<>
01299 void rpc_server_object::test<1>()
01300 {
01301 LLSD request;
01302 request = 1;
01303 pump_loop(request);
01304
01305
01306 ensure_equals("integer request response", mResponse.asInteger(), 1);
01307 }
01308
01309 template<> template<>
01310 void rpc_server_object::test<2>()
01311 {
01312 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");
01313 std::stringstream stream;
01314 stream << "{'task_id':ucc706f2d-0b68-68f8-11a4-f1043ff35ca0}\n{\n\tname\tObject|\n\tpermissions 0\n}";
01315 std::vector<U8> expected_binary;
01316 expected_binary.resize(stream.str().size());
01317 memcpy(&expected_binary[0], stream.str().c_str(), stream.str().size());
01318 stream.str("");
01319 stream << "[{'uri':'" << uri << "'}, {'version':i1}, "
01320 << "{'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'], "
01321 << "'attachment_data':["
01322 << "{'attachment_point':i2, 'item_id':'d6852c11-a74e-309a-0462-50533f1ef9b3', 'asset_id':'c69b29b1-8944-58ae-a7c5-2ca7b23e22fb'},"
01323 << "{'attachment_point':i10, 'item_id':'ff852c22-a74e-309a-0462-50533f1ef900', 'asset_data':b(" << expected_binary.size() << ")\"";
01324 stream.write((const char*)&expected_binary[0], expected_binary.size());
01325 stream << "\"}"
01326 << "]"
01327 << "}]";
01328
01329 LLSD request;
01330 S32 count = LLSDSerialize::fromNotation(
01331 request,
01332 stream,
01333 stream.str().size());
01334 ensure("parsed something", (count > 0));
01335
01336 pump_loop(request);
01337 ensure_equals("return type", mResponse.type(), LLSD::TypeArray);
01338 ensure_equals("return size", mResponse.size(), 3);
01339
01340 ensure_equals(
01341 "uri parameter type",
01342 mResponse[0].type(),
01343 LLSD::TypeMap);
01344 ensure_equals(
01345 "uri type",
01346 mResponse[0]["uri"].type(),
01347 LLSD::TypeString);
01348 ensure_equals("uri value", mResponse[0]["uri"].asString(), uri);
01349
01350 ensure_equals(
01351 "version parameter type",
01352 mResponse[1].type(),
01353 LLSD::TypeMap);
01354 ensure_equals(
01355 "version type",
01356 mResponse[1]["version"].type(),
01357 LLSD::TypeInteger);
01358 ensure_equals(
01359 "version value",
01360 mResponse[1]["version"].asInteger(),
01361 1);
01362
01363 ensure_equals("agent params type", mResponse[2].type(), LLSD::TypeMap);
01364 LLSD attachment_data = mResponse[2]["attachment_data"];
01365 ensure("attachment data exists", attachment_data.isDefined());
01366 ensure_equals(
01367 "attachment type",
01368 attachment_data.type(),
01369 LLSD::TypeArray);
01370 ensure_equals(
01371 "attachment type 0",
01372 attachment_data[0].type(),
01373 LLSD::TypeMap);
01374 ensure_equals(
01375 "attachment type 1",
01376 attachment_data[1].type(),
01377 LLSD::TypeMap);
01378 ensure_equals("attachment size 1", attachment_data[1].size(), 3);
01379 ensure_equals(
01380 "asset data type",
01381 attachment_data[1]["asset_data"].type(),
01382 LLSD::TypeBinary);
01383 std::vector<U8> actual_binary;
01384 actual_binary = attachment_data[1]["asset_data"].asBinary();
01385 ensure_equals(
01386 "binary data size",
01387 actual_binary.size(),
01388 expected_binary.size());
01389 ensure(
01390 "binary data",
01391 (0 == memcmp(
01392 &actual_binary[0],
01393 &expected_binary[0],
01394 expected_binary.size())));
01395 }
01396
01397 template<> template<>
01398 void rpc_server_object::test<3>()
01399 {
01400 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");
01401
01402 LLBufferArray buffer;
01403 LLChannelDescriptors buffer_channels = buffer.nextChannel();
01404 LLBufferStream stream(buffer_channels, &buffer);
01405 stream << "[{'uri':'" << uri << "'}, {'version':i1}, "
01406 << "{'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'], "
01407 << "'attachment_data':["
01408 << "{'attachment_point':i2, 'item_id':'d6852c11-a74e-309a-0462-50533f1ef9b3', 'asset_id':'c69b29b1-8944-58ae-a7c5-2ca7b23e22fb'},";
01409
01410 std::stringstream tmp_str;
01411 tmp_str << "{'task_id':ucc706f2d-0b68-68f8-11a4-f1043ff35ca0}\n{\n\tname\tObject|\n\tpermissions 0\n}";
01412 std::vector<U8> expected_binary;
01413 expected_binary.resize(tmp_str.str().size());
01414 memcpy(
01415 &expected_binary[0],
01416 tmp_str.str().c_str(),
01417 tmp_str.str().size());
01418
01419 LLBufferArray attachment_buffer;
01420 LLChannelDescriptors attach_channels = attachment_buffer.nextChannel();
01421 LLBufferStream attach_stream(attach_channels, &attachment_buffer);
01422 attach_stream.write((const char*)&expected_binary[0], expected_binary.size());
01423 attach_stream.flush();
01424 S32 len = attachment_buffer.countAfter(attach_channels.out(), NULL);
01425 stream << "{'attachment_point':i10, 'item_id':'ff852c22-a74e-309a-0462-50533f1ef900', 'asset_data':b(" << len << ")\"";
01426 stream.flush();
01427 buffer.takeContents(attachment_buffer);
01428 stream << "\"}]}]";
01429 stream.flush();
01430
01431 LLChannelDescriptors read_channel = buffer.nextChannel();
01432 LLBufferStream read_stream(read_channel, &buffer);
01433 LLSD request;
01434 S32 count = LLSDSerialize::fromNotation(
01435 request,
01436 read_stream,
01437 buffer.count(read_channel.in()));
01438 ensure("parsed something", (count > 0));
01439 ensure("deserialized", request.isDefined());
01440
01441
01442 pump_loop(request);
01443
01444 ensure_equals("return type", mResponse.type(), LLSD::TypeArray);
01445 ensure_equals("return size", mResponse.size(), 3);
01446
01447 LLSD child = mResponse[0];
01448 ensure("uri map exists", child.isDefined());
01449 ensure_equals("uri parameter type", child.type(), LLSD::TypeMap);
01450 ensure("uri string exists", child.has("uri"));
01451 ensure_equals("uri type", child["uri"].type(), LLSD::TypeString);
01452 ensure_equals("uri value", child["uri"].asString(), uri);
01453
01454 child = mResponse[1];
01455 ensure("version map exists", child.isDefined());
01456 ensure_equals("version param type", child.type(), LLSD::TypeMap);
01457 ensure_equals(
01458 "version type",
01459 child["version"].type(),
01460 LLSD::TypeInteger);
01461 ensure_equals("version value", child["version"].asInteger(), 1);
01462
01463 child = mResponse[2];
01464 ensure("agent params map exists", child.isDefined());
01465 ensure_equals("agent params type", child.type(), LLSD::TypeMap);
01466 child = child["attachment_data"];
01467 ensure("attachment data exists", child.isDefined());
01468 ensure_equals("attachment type", child.type(), LLSD::TypeArray);
01469 LLSD attachment = child[0];
01470 ensure_equals("attachment type 0", attachment.type(), LLSD::TypeMap);
01471 attachment = child[1];
01472 ensure_equals("attachment type 1", attachment.type(), LLSD::TypeMap);
01473 ensure_equals("attachment size 1", attachment.size(), 3);
01474 ensure_equals(
01475 "asset data type",
01476 attachment["asset_data"].type(),
01477 LLSD::TypeBinary);
01478 std::vector<U8> actual_binary = attachment["asset_data"].asBinary();
01479 ensure_equals(
01480 "binary data size",
01481 actual_binary.size(),
01482 expected_binary.size());
01483 ensure(
01484 "binary data",
01485 (0 == memcmp(
01486 &actual_binary[0],
01487 &expected_binary[0],
01488 expected_binary.size())));
01489 }
01490
01491 template<> template<>
01492 void rpc_server_object::test<4>()
01493 {
01494 std::string message("parcel '' is naughty.");
01495 std::stringstream str;
01496 str << "{'message':'" << LLSDNotationFormatter::escapeString(message)
01497 << "'}";
01498 LLSD request;
01499 S32 count = LLSDSerialize::fromNotation(
01500 request,
01501 str,
01502 str.str().size());
01503 ensure_equals("parse count", count, 2);
01504 ensure_equals("request type", request.type(), LLSD::TypeMap);
01505 pump_loop(request);
01506 ensure("valid response", mResponse.isDefined());
01507 ensure_equals("response type", mResponse.type(), LLSD::TypeMap);
01508 std::string actual = mResponse["message"].asString();
01509 ensure_equals("message contents", actual, message);
01510 }
01511
01512 template<> template<>
01513 void rpc_server_object::test<5>()
01514 {
01515
01516
01517
01518
01519
01520
01521 std::string val = "[{'failures':!,'successfuls':[u3c115e51-04f4-523c-9fa6-98aff1034730]}]";
01522 std::istringstream istr;
01523 istr.str(val);
01524 LLSD sd;
01525 LLSDSerialize::fromNotation(sd, istr, val.size());
01526 pump_loop(sd);
01527 ensure("valid response", mResponse.isDefined());
01528 ensure_equals("parsed type", mResponse.type(), LLSD::TypeMap);
01529 ensure_equals("parsed size", mResponse.size(), 2);
01530 LLSD failures = mResponse["failures"];
01531 ensure_equals("no failures.", failures.asBoolean(), false);
01532 LLSD success = mResponse["successfuls"];
01533 ensure_equals("success type", success.type(), LLSD::TypeArray);
01534 ensure_equals("success size", success.size(), 1);
01535 ensure_equals(
01536 "success instance type",
01537 success[0].type(),
01538 LLSD::TypeString);
01539 }
01540
01541
01542
01543
01544
01545
01546
01547
01548
01549
01550
01551
01552
01553
01554
01555
01556
01557
01558
01559
01560
01561
01562
01563
01564
01565
01566
01567
01568
01569
01570
01571
01572
01573
01574
01575
01576
01577
01578
01579
01580
01581
01582
01583
01584
01585
01586 }
01587
01588
01589
01590
01591