summaryrefslogtreecommitdiff
path: root/indra/llmessage/tests
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llmessage/tests')
-rw-r--r--indra/llmessage/tests/io_test.cpp1181
-rw-r--r--indra/llmessage/tests/llbuffer_test.cpp271
-rw-r--r--indra/llmessage/tests/llcurl_stub.cpp99
-rw-r--r--indra/llmessage/tests/lldatapacker_test.cpp572
-rw-r--r--indra/llmessage/tests/llhttpclient_test.cpp311
-rw-r--r--indra/llmessage/tests/llhttpnode_test.cpp428
-rw-r--r--indra/llmessage/tests/lliohttpserver_test.cpp350
-rw-r--r--indra/llmessage/tests/llmessageconfig_test.cpp236
-rw-r--r--indra/llmessage/tests/llmessagetemplateparser_test.cpp368
-rw-r--r--indra/llmessage/tests/llpipeutil.cpp183
-rw-r--r--indra/llmessage/tests/llpipeutil.h163
-rw-r--r--indra/llmessage/tests/llsdmessagebuilder_test.cpp837
-rw-r--r--indra/llmessage/tests/llsdmessagereader_test.cpp324
-rw-r--r--indra/llmessage/tests/llservicebuilder_test.cpp173
-rw-r--r--indra/llmessage/tests/lltemplatemessagebuilder_test.cpp971
-rw-r--r--indra/llmessage/tests/llxorcipher_test.cpp131
-rw-r--r--indra/llmessage/tests/message_test.cpp147
17 files changed, 6335 insertions, 410 deletions
diff --git a/indra/llmessage/tests/io_test.cpp b/indra/llmessage/tests/io_test.cpp
new file mode 100644
index 0000000000..f77402065a
--- /dev/null
+++ b/indra/llmessage/tests/io_test.cpp
@@ -0,0 +1,1181 @@
+/**
+ * @file io.cpp
+ * @author Phoenix
+ * @date 2005-10-02
+ * @brief Tests for io classes and helpers
+ *
+ * $LicenseInfo:firstyear=2005&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include "lltut.h"
+
+#include <iterator>
+
+#include "apr_pools.h"
+
+#include "llbuffer.h"
+#include "llbufferstream.h"
+#include "lliosocket.h"
+#include "llioutil.h"
+#include "llmemorystream.h"
+#include "llpipeutil.h"
+#include "llpumpio.h"
+#include "llsd.h"
+#include "llsdserialize.h"
+#include "llcommon.h"
+#include "lluuid.h"
+#include "llinstantmessage.h"
+
+namespace tut
+{
+ struct heap_buffer_data
+ {
+ heap_buffer_data() : mBuffer(NULL) {}
+ ~heap_buffer_data() { if(mBuffer) delete mBuffer; }
+ LLHeapBuffer* mBuffer;
+ };
+ typedef test_group<heap_buffer_data> heap_buffer_test;
+ typedef heap_buffer_test::object heap_buffer_object;
+ tut::heap_buffer_test thb("heap_buffer");
+
+ template<> template<>
+ void heap_buffer_object::test<1>()
+ {
+ const S32 BUF_SIZE = 100;
+ mBuffer = new LLHeapBuffer(BUF_SIZE);
+ ensure_equals("empty buffer capacity", mBuffer->capacity(), BUF_SIZE);
+ const S32 SEGMENT_SIZE = 50;
+ LLSegment segment;
+ mBuffer->createSegment(0, SEGMENT_SIZE, segment);
+ ensure_equals("used buffer capacity", mBuffer->capacity(), BUF_SIZE);
+ }
+
+ template<> template<>
+ void heap_buffer_object::test<2>()
+ {
+ const S32 BUF_SIZE = 10;
+ mBuffer = new LLHeapBuffer(BUF_SIZE);
+ LLSegment segment;
+ mBuffer->createSegment(0, BUF_SIZE, segment);
+ ensure("segment is in buffer", mBuffer->containsSegment(segment));
+ ensure_equals("buffer consumed", mBuffer->bytesLeft(), 0);
+ bool created;
+ created = mBuffer->createSegment(0, 0, segment);
+ ensure("Create zero size segment fails", !created);
+ created = mBuffer->createSegment(0, BUF_SIZE, segment);
+ ensure("Create segment fails", !created);
+ }
+
+ template<> template<>
+ void heap_buffer_object::test<3>()
+ {
+ const S32 BUF_SIZE = 10;
+ mBuffer = new LLHeapBuffer(BUF_SIZE);
+ LLSegment segment;
+ mBuffer->createSegment(0, BUF_SIZE, segment);
+ ensure("segment is in buffer", mBuffer->containsSegment(segment));
+ ensure_equals("buffer consumed", mBuffer->bytesLeft(), 0);
+ bool reclaimed = mBuffer->reclaimSegment(segment);
+ ensure("buffer reclaimed.", reclaimed);
+ ensure_equals("buffer available", mBuffer->bytesLeft(), BUF_SIZE);
+ bool created;
+ created = mBuffer->createSegment(0, 0, segment);
+ ensure("Create zero size segment fails", !created);
+ created = mBuffer->createSegment(0, BUF_SIZE, segment);
+ ensure("Create another segment succeeds", created);
+ }
+
+ template<> template<>
+ void heap_buffer_object::test<4>()
+ {
+ const S32 BUF_SIZE = 10;
+ const S32 SEGMENT_SIZE = 4;
+ mBuffer = new LLHeapBuffer(BUF_SIZE);
+ LLSegment seg1;
+ mBuffer->createSegment(0, SEGMENT_SIZE, seg1);
+ ensure("segment is in buffer", mBuffer->containsSegment(seg1));
+ LLSegment seg2;
+ mBuffer->createSegment(0, SEGMENT_SIZE, seg2);
+ ensure("segment is in buffer", mBuffer->containsSegment(seg2));
+ LLSegment seg3;
+ mBuffer->createSegment(0, SEGMENT_SIZE, seg3);
+ ensure("segment is in buffer", mBuffer->containsSegment(seg3));
+ ensure_equals("segment is truncated", seg3.size(), 2);
+ LLSegment seg4;
+ bool created;
+ created = mBuffer->createSegment(0, SEGMENT_SIZE, seg4);
+ ensure("Create segment fails", !created);
+ bool reclaimed;
+ reclaimed = mBuffer->reclaimSegment(seg1);
+ ensure("buffer reclaim succeed.", reclaimed);
+ ensure_equals("no buffer available", mBuffer->bytesLeft(), 0);
+ reclaimed = mBuffer->reclaimSegment(seg2);
+ ensure("buffer reclaim succeed.", reclaimed);
+ ensure_equals("buffer reclaimed", mBuffer->bytesLeft(), 0);
+ reclaimed = mBuffer->reclaimSegment(seg3);
+ ensure("buffer reclaim succeed.", reclaimed);
+ ensure_equals("buffer reclaimed", mBuffer->bytesLeft(), BUF_SIZE);
+ created = mBuffer->createSegment(0, SEGMENT_SIZE, seg1);
+ ensure("segment is in buffer", mBuffer->containsSegment(seg1));
+ ensure("Create segment succeds", created);
+ }
+}
+
+namespace tut
+{
+ struct buffer_data
+ {
+ LLBufferArray mBuffer;
+ };
+ typedef test_group<buffer_data> buffer_test;
+ typedef buffer_test::object buffer_object;
+ tut::buffer_test tba("buffer_array");
+
+ template<> template<>
+ void buffer_object::test<1>()
+ {
+ const char HELLO_WORLD[] = "hello world";
+ const S32 str_len = static_cast<S32>(strlen(HELLO_WORLD));
+ LLChannelDescriptors ch = mBuffer.nextChannel();
+ mBuffer.append(ch.in(), (U8*)HELLO_WORLD, str_len);
+ S32 count = mBuffer.countAfter(ch.in(), NULL);
+ ensure_equals("total append size", count, str_len);
+ LLBufferArray::segment_iterator_t it = mBuffer.beginSegment();
+ U8* first = (*it).data();
+ count = mBuffer.countAfter(ch.in(), first);
+ ensure_equals("offset append size", count, str_len - 1);
+ }
+
+ template<> template<>
+ void buffer_object::test<2>()
+ {
+ const char HELLO_WORLD[] = "hello world";
+ const S32 str_len = static_cast<S32>(strlen(HELLO_WORLD)); /* Flawfinder: ignore */
+ LLChannelDescriptors ch = mBuffer.nextChannel();
+ mBuffer.append(ch.in(), (U8*)HELLO_WORLD, str_len);
+ mBuffer.append(ch.in(), (U8*)HELLO_WORLD, str_len);
+ S32 count = mBuffer.countAfter(ch.in(), NULL);
+ ensure_equals("total append size", count, 2 * str_len);
+ LLBufferArray::segment_iterator_t it = mBuffer.beginSegment();
+ U8* first = (*it).data();
+ count = mBuffer.countAfter(ch.in(), first);
+ ensure_equals("offset append size", count, (2 * str_len) - 1);
+ }
+
+ template<> template<>
+ void buffer_object::test<3>()
+ {
+ const char ONE[] = "one";
+ const char TWO[] = "two";
+ std::string expected(ONE);
+ expected.append(TWO);
+ LLChannelDescriptors ch = mBuffer.nextChannel();
+ mBuffer.append(ch.in(), (U8*)ONE, 3);
+ mBuffer.append(ch.in(), (U8*)TWO, 3);
+ char buffer[255]; /* Flawfinder: ignore */
+ S32 len = 6;
+ mBuffer.readAfter(ch.in(), NULL, (U8*)buffer, len);
+ ensure_equals(len, 6);
+ buffer[len] = '\0';
+ std::string actual(buffer);
+ ensure_equals("read", actual, expected);
+ }
+
+ template<> template<>
+ void buffer_object::test<4>()
+ {
+ const char ONE[] = "one";
+ const char TWO[] = "two";
+ std::string expected(ONE);
+ expected.append(TWO);
+ LLChannelDescriptors ch = mBuffer.nextChannel();
+ mBuffer.append(ch.in(), (U8*)TWO, 3);
+ mBuffer.prepend(ch.in(), (U8*)ONE, 3);
+ char buffer[255]; /* Flawfinder: ignore */
+ S32 len = 6;
+ mBuffer.readAfter(ch.in(), NULL, (U8*)buffer, len);
+ ensure_equals(len, 6);
+ buffer[len] = '\0';
+ std::string actual(buffer);
+ ensure_equals("read", actual, expected);
+ }
+
+ template<> template<>
+ void buffer_object::test<5>()
+ {
+ const char ONE[] = "one";
+ const char TWO[] = "two";
+ std::string expected("netwo");
+ LLChannelDescriptors ch = mBuffer.nextChannel();
+ mBuffer.append(ch.in(), (U8*)TWO, 3);
+ mBuffer.prepend(ch.in(), (U8*)ONE, 3);
+ char buffer[255]; /* Flawfinder: ignore */
+ S32 len = 5;
+ LLBufferArray::segment_iterator_t it = mBuffer.beginSegment();
+ U8* addr = (*it).data();
+ mBuffer.readAfter(ch.in(), addr, (U8*)buffer, len);
+ ensure_equals(len, 5);
+ buffer[len] = '\0';
+ std::string actual(buffer);
+ ensure_equals("read", actual, expected);
+ }
+
+ template<> template<>
+ void buffer_object::test<6>()
+ {
+ std::string request("The early bird catches the worm.");
+ std::string response("If you're a worm, sleep late.");
+ std::ostringstream expected;
+ expected << "ContentLength: " << response.length() << "\r\n\r\n"
+ << response;
+ LLChannelDescriptors ch = mBuffer.nextChannel();
+ mBuffer.append(ch.in(), (U8*)request.c_str(), static_cast<S32>(request.length()));
+ mBuffer.append(ch.out(), (U8*)response.c_str(), static_cast<S32>(response.length()));
+ S32 count = mBuffer.countAfter(ch.out(), NULL);
+ std::ostringstream header;
+ header << "ContentLength: " << count << "\r\n\r\n";
+ std::string head(header.str());
+ mBuffer.prepend(ch.out(), (U8*)head.c_str(), static_cast<S32>(head.length()));
+ char buffer[1024]; /* Flawfinder: ignore */
+ S32 len = static_cast<S32>(response.size() + head.length());
+ ensure_equals("same length", len, (S32)expected.str().length());
+ mBuffer.readAfter(ch.out(), NULL, (U8*)buffer, len);
+ buffer[len] = '\0';
+ std::string actual(buffer);
+ ensure_equals("threaded writes", actual, expected.str());
+ }
+
+ template<> template<>
+ void buffer_object::test<7>()
+ {
+ const S32 LINE_COUNT = 3;
+ std::string lines[LINE_COUNT] =
+ {
+ std::string("GET /index.htm HTTP/1.0\r\n"),
+ std::string("User-Agent: Wget/1.9.1\r\n"),
+ std::string("Host: localhost:8008\r\n")
+ };
+ std::string text;
+ S32 i;
+ for(i = 0; i < LINE_COUNT; ++i)
+ {
+ text.append(lines[i]);
+ }
+ LLChannelDescriptors ch = mBuffer.nextChannel();
+ mBuffer.append(ch.in(), (U8*)text.c_str(), static_cast<S32>(text.length()));
+ const S32 BUFFER_LEN = 1024;
+ char buf[BUFFER_LEN];
+ S32 len;
+ U8* last = NULL;
+ std::string last_line;
+ for(i = 0; i < LINE_COUNT; ++i)
+ {
+ len = BUFFER_LEN;
+ last = mBuffer.readAfter(ch.in(), last, (U8*)buf, len);
+ char* newline = strchr((char*)buf, '\n');
+ S32 offset = -((len - 1) - (S32)(newline - buf));
+ ++newline;
+ *newline = '\0';
+ last_line.assign(buf);
+ std::ostringstream message;
+ message << "line reads in line[" << i << "]";
+ ensure_equals(message.str().c_str(), last_line, lines[i]);
+ last = mBuffer.seek(ch.in(), last, offset);
+ }
+ }
+
+ template<> template<>
+ void buffer_object::test<8>()
+ {
+ LLChannelDescriptors ch = mBuffer.nextChannel();
+ mBuffer.append(ch.in(), (U8*)"1", 1);
+ LLBufferArray buffer;
+ buffer.append(ch.in(), (U8*)"2", 1);
+ mBuffer.takeContents(buffer);
+ mBuffer.append(ch.in(), (U8*)"3", 1);
+ S32 count = mBuffer.countAfter(ch.in(), NULL);
+ ensure_equals("buffer size", count, 3);
+ U8* temp = new U8[count];
+ mBuffer.readAfter(ch.in(), NULL, temp, count);
+ ensure("buffer content", (0 == memcmp(temp, (void*)"123", 3)));
+ delete[] temp;
+ }
+
+ template<> template<>
+ void buffer_object::test<9>()
+ {
+ LLChannelDescriptors ch = mBuffer.nextChannel();
+ mBuffer.append(ch.in(), (U8*)"1", 1);
+ S32 capacity = mBuffer.capacity();
+ ensure("has capacity", capacity > 0);
+ U8* temp = new U8[capacity - 1];
+ mBuffer.append(ch.in(), temp, capacity - 1);
+ capacity = mBuffer.capacity();
+ ensure("has capacity when full", capacity > 0);
+ S32 used = mBuffer.countAfter(ch.in(), NULL);
+ ensure_equals("used equals capacity", used, capacity);
+
+ LLBufferArray::segment_iterator_t iter = mBuffer.beginSegment();
+ while(iter != mBuffer.endSegment())
+ {
+ mBuffer.eraseSegment(iter++);
+ }
+
+ used = mBuffer.countAfter(ch.in(), NULL);
+ ensure_equals("used is zero", used, 0);
+ S32 capacity2 = mBuffer.capacity();
+ ensure_equals("capacity the same after erase", capacity2, capacity);
+ mBuffer.append(ch.in(), temp, capacity - 1);
+ capacity2 = mBuffer.capacity();
+ ensure_equals("capacity the same after append", capacity2, capacity);
+
+ delete[] temp;
+ }
+
+#if 0
+ template<> template<>
+ void buffer_object::test<9>()
+ {
+ char buffer[1024]; /* Flawfinder: ignore */
+ S32 size = sprintf(buffer,
+ "%d|%d|%s|%s|%s|%s|%s|%x|%x|%x|%x|%x|%s|%s|%d|%d|%x",
+ 7,
+ 7,
+ "Hang Glider INFO",
+ "18e84d1e-04a4-4c0d-8cb6-6c73477f0a9a",
+ "0e346d8b-4433-4d66-a6b0-fd37083abc4c",
+ "0e346d8b-4433-4d66-a6b0-fd37083abc4c",
+ "00000000-0000-0000-0000-000000000000",
+ 0x7fffffff,
+ 0x7fffffff,
+ 0,
+ 0,
+ 0x7fffffff,
+ "69e0d357-2e7c-8990-a2bc-7f61c868e5a3",
+ "2004-06-04 16:09:17 note card",
+ 0,
+ 10,
+ 0) + 1;
+
+ //const char* expected = "7|7|Hang Glider INFO|18e84d1e-04a4-4c0d-8cb6-6c73477f0a9a|0e346d8b-4433-4d66-a6b0-fd37083abc4c|0e346d8b-4433-4d66-a6b0-fd37083abc4c|00000000-0000-0000-0000-000000000000|7fffffff|7fffffff|0|0|7fffffff|69e0d357-2e7c-8990-a2bc-7f61c868e5a3|2004-06-04 16:09:17 note card|0|10|0\0";
+
+ LLSD* bin_bucket = LLIMInfo::buildSDfrombuffer((U8*)buffer,size);
+
+ char post_buffer[1024];
+ U32 post_size;
+ LLIMInfo::getBinaryBucket(bin_bucket,(U8*)post_buffer,post_size);
+ ensure_equals("Buffer sizes",size,(S32)post_size);
+ ensure("Buffer content",!strcmp(buffer,post_buffer));
+ }
+#endif
+
+ /*
+ template<> template<>
+ void buffer_object::test<>()
+ {
+ }
+ */
+}
+
+namespace tut
+{
+ struct buffer_and_stream_data
+ {
+ LLBufferArray mBuffer;
+ };
+ typedef test_group<buffer_and_stream_data> bas_test;
+ typedef bas_test::object bas_object;
+ tut::bas_test tbs("buffer_stream");
+
+ template<> template<>
+ void bas_object::test<1>()
+ {
+ const char HELLO_WORLD[] = "hello world";
+ const S32 str_len = static_cast<S32>(strlen(HELLO_WORLD)); /* Flawfinder: ignore */
+ LLChannelDescriptors ch = mBuffer.nextChannel();
+ LLBufferStream str(ch, &mBuffer);
+ mBuffer.append(ch.in(), (U8*)HELLO_WORLD, str_len);
+ std::string hello;
+ std::string world;
+ str >> hello >> world;
+ ensure_equals("first word", hello, std::string("hello"));
+ ensure_equals("second word", world, std::string("world"));
+ }
+
+ template<> template<>
+ void bas_object::test<2>()
+ {
+ std::string part1("Eat my shor");
+ std::string part2("ts ho");
+ std::string part3("mer");
+ std::string ignore("ignore me");
+ LLChannelDescriptors ch = mBuffer.nextChannel();
+ LLBufferStream str(ch, &mBuffer);
+ mBuffer.append(ch.in(), (U8*)part1.c_str(), static_cast<S32>(part1.length()));
+ mBuffer.append(ch.in(), (U8*)part2.c_str(), static_cast<S32>(part2.length()));
+ mBuffer.append(ch.out(), (U8*)ignore.c_str(), static_cast<S32>(ignore.length()));
+ mBuffer.append(ch.in(), (U8*)part3.c_str(), static_cast<S32>(part3.length()));
+ std::string eat;
+ std::string my;
+ std::string shorts;
+ std::string homer;
+ str >> eat >> my >> shorts >> homer;
+ ensure_equals("word1", eat, std::string("Eat"));
+ ensure_equals("word2", my, std::string("my"));
+ ensure_equals("word3", shorts, std::string("shorts"));
+ ensure_equals("word4", homer, std::string("homer"));
+ }
+
+ template<> template<>
+ void bas_object::test<3>()
+ {
+ std::string part1("junk in ");
+ std::string part2("the trunk");
+ const S32 CHANNEL = 0;
+ mBuffer.append(CHANNEL, (U8*)part1.c_str(), static_cast<S32>(part1.length()));
+ mBuffer.append(CHANNEL, (U8*)part2.c_str(), static_cast<S32>(part2.length()));
+ U8* last = 0;
+ const S32 BUF_LEN = 128;
+ char buf[BUF_LEN];
+ S32 len = 11;
+ last = mBuffer.readAfter(CHANNEL, last, (U8*)buf, len);
+ buf[len] = '\0';
+ std::string actual(buf);
+ ensure_equals("first read", actual, std::string("junk in the"));
+ last = mBuffer.seek(CHANNEL, last, -6);
+ len = 12;
+ last = mBuffer.readAfter(CHANNEL, last, (U8*)buf, len);
+ buf[len] = '\0';
+ actual.assign(buf);
+ ensure_equals("seek and read", actual, std::string("in the trunk"));
+ }
+
+ template<> template<>
+ void bas_object::test<4>()
+ {
+ std::string phrase("zippity do da!");
+ const S32 CHANNEL = 0;
+ mBuffer.append(CHANNEL, (U8*)phrase.c_str(), static_cast<S32>(phrase.length()));
+ const S32 BUF_LEN = 128;
+ char buf[BUF_LEN];
+ S32 len = 7;
+ U8* last = mBuffer.readAfter(CHANNEL, NULL, (U8*)buf, len);
+ mBuffer.splitAfter(last);
+ LLBufferArray::segment_iterator_t it = mBuffer.beginSegment();
+ LLBufferArray::segment_iterator_t end = mBuffer.endSegment();
+ std::string first((char*)((*it).data()), (*it).size());
+ ensure_equals("first part", first, std::string("zippity"));
+ ++it;
+ std::string second((char*)((*it).data()), (*it).size());
+ ensure_equals("second part", second, std::string(" do da!"));
+ ++it;
+ ensure("iterators equal", (it == end));
+ }
+
+ template<> template<>
+ void bas_object::test<5>()
+ {
+ LLChannelDescriptors ch = mBuffer.nextChannel();
+ LLBufferStream str(ch, &mBuffer);
+ std::string h1("hello");
+ std::string h2(", how are you doing?");
+ std::string expected(h1);
+ expected.append(h2);
+ str << h1 << h2;
+ str.flush();
+ const S32 BUF_LEN = 128;
+ char buf[BUF_LEN];
+ S32 actual_len = BUF_LEN;
+ S32 expected_len = static_cast<S32>(h1.size() + h2.size());
+ (void) mBuffer.readAfter(ch.out(), NULL, (U8*)buf, actual_len);
+ ensure_equals("streamed size", actual_len, expected_len);
+ buf[actual_len] = '\0';
+ std::string actual(buf);
+ ensure_equals("streamed to buf", actual, expected);
+ }
+
+ template<> template<>
+ void bas_object::test<6>()
+ {
+ LLChannelDescriptors ch = mBuffer.nextChannel();
+ LLBufferStream bstr(ch, &mBuffer);
+ std::ostringstream ostr;
+ std::vector<LLUUID> ids;
+ LLUUID id;
+ for(int i = 0; i < 5; ++i)
+ {
+ id.generate();
+ ids.push_back(id);
+ }
+ bstr << "SELECT concat(u.username, ' ', l.name) "
+ << "FROM user u, user_last_name l "
+ << "WHERE u.last_name_id = l.last_name_id"
+ << " AND u.agent_id IN ('";
+ ostr << "SELECT concat(u.username, ' ', l.name) "
+ << "FROM user u, user_last_name l "
+ << "WHERE u.last_name_id = l.last_name_id"
+ << " AND u.agent_id IN ('";
+ std::copy(
+ ids.begin(),
+ ids.end(),
+ std::ostream_iterator<LLUUID>(bstr, "','"));
+ std::copy(
+ ids.begin(),
+ ids.end(),
+ std::ostream_iterator<LLUUID>(ostr, "','"));
+ bstr.seekp(-2, std::ios::cur);
+ ostr.seekp(-2, std::ios::cur);
+ bstr << ") ";
+ ostr << ") ";
+ bstr.flush();
+ const S32 BUF_LEN = 512;
+ char buf[BUF_LEN]; /* Flawfinder: ignore */
+ S32 actual_len = BUF_LEN;
+ (void) mBuffer.readAfter(ch.out(), NULL, (U8*)buf, actual_len);
+ buf[actual_len] = '\0';
+ std::string actual(buf);
+ std::string expected(ostr.str());
+ ensure_equals("size of string in seek",actual.size(),expected.size());
+ ensure_equals("seek in ostream", actual, expected);
+ }
+
+ template<> template<>
+ void bas_object::test<7>()
+ {
+ LLChannelDescriptors ch = mBuffer.nextChannel();
+ LLBufferStream bstr(ch, &mBuffer);
+ bstr << "1";
+ bstr.flush();
+ S32 count = mBuffer.countAfter(ch.out(), NULL);
+ ensure_equals("buffer size 1", count, 1);
+ LLBufferArray buffer;
+ buffer.append(ch.out(), (U8*)"2", 1);
+ mBuffer.takeContents(buffer);
+ count = mBuffer.countAfter(ch.out(), NULL);
+ ensure_equals("buffer size 2", count, 2);
+ bstr << "3";
+ bstr.flush();
+ count = mBuffer.countAfter(ch.out(), NULL);
+ ensure_equals("buffer size 3", count, 3);
+ U8* temp = new U8[count];
+ mBuffer.readAfter(ch.out(), NULL, temp, count);
+ ensure("buffer content", (0 == memcmp(temp, (void*)"123", 3)));
+ delete[] temp;
+ }
+
+ template<> template<>
+ void bas_object::test<8>()
+ {
+ LLChannelDescriptors ch = mBuffer.nextChannel();
+ LLBufferStream ostr(ch, &mBuffer);
+ typedef std::vector<U8> buf_t;
+ typedef std::vector<buf_t> actual_t;
+ actual_t actual;
+ buf_t source;
+ bool need_comma = false;
+ ostr << "[";
+ S32 total_size = 1;
+ for(S32 i = 2000; i < 2003; ++i)
+ {
+ if(need_comma)
+ {
+ ostr << ",";
+ ++total_size;
+ }
+ need_comma = true;
+ srand(69 + i); /* Flawfinder: ignore */
+ S32 size = rand() % 1000 + 1000;
+ std::generate_n(
+ std::back_insert_iterator<buf_t>(source),
+ size,
+ rand);
+ actual.push_back(source);
+ ostr << "b(" << size << ")\"";
+ total_size += 8;
+ ostr.write((const char*)(&source[0]), size);
+ total_size += size;
+ source.clear();
+ ostr << "\"";
+ ++total_size;
+ }
+ ostr << "]";
+ ++total_size;
+ ostr.flush();
+
+ // now that we have a bunch of data on a stream, parse it all.
+ ch = mBuffer.nextChannel();
+ S32 count = mBuffer.countAfter(ch.in(), NULL);
+ ensure_equals("size of buffer", count, total_size);
+ LLBufferStream istr(ch, &mBuffer);
+ LLSD data;
+ count = LLSDSerialize::fromNotation(data, istr, total_size);
+ ensure("sd parsed", data.isDefined());
+
+ for(S32 j = 0; j < 3; ++j)
+ {
+ std::ostringstream name;
+ LLSD child(data[j]);
+ name << "found buffer " << j;
+ ensure(name.str(), child.isDefined());
+ source = child.asBinary();
+ name.str("");
+ name << "buffer " << j << " size";
+ ensure_equals(name.str().c_str(), source.size(), actual[j].size());
+ name.str("");
+ name << "buffer " << j << " contents";
+ ensure(
+ name.str(),
+ (0 == memcmp(&source[0], &actual[j][0], source.size())));
+ }
+ }
+
+ template<> template<>
+ void bas_object::test<9>()
+ {
+ LLChannelDescriptors ch = mBuffer.nextChannel();
+ LLBufferStream ostr(ch, &mBuffer);
+ typedef std::vector<U8> buf_t;
+ buf_t source;
+ bool need_comma = false;
+ ostr << "{";
+ S32 total_size = 1;
+ for(S32 i = 1000; i < 3000; ++i)
+ {
+ if(need_comma)
+ {
+ ostr << ",";
+ ++total_size;
+ }
+ need_comma = true;
+ ostr << "'" << i << "':";
+ total_size += 7;
+ srand(69 + i); /* Flawfinder: ignore */
+ S32 size = rand() % 1000 + 1000;
+ std::generate_n(
+ std::back_insert_iterator<buf_t>(source),
+ size,
+ rand);
+ ostr << "b(" << size << ")\"";
+ total_size += 8;
+ ostr.write((const char*)(&source[0]), size);
+ total_size += size;
+ source.clear();
+ ostr << "\"";
+ ++total_size;
+ }
+ ostr << "}";
+ ++total_size;
+ ostr.flush();
+
+ // now that we have a bunch of data on a stream, parse it all.
+ ch = mBuffer.nextChannel();
+ S32 count = mBuffer.countAfter(ch.in(), NULL);
+ ensure_equals("size of buffer", count, total_size);
+ LLBufferStream istr(ch, &mBuffer);
+ LLSD data;
+ count = LLSDSerialize::fromNotation(data, istr, total_size);
+ ensure("sd parsed", data.isDefined());
+ }
+
+ template<> template<>
+ void bas_object::test<10>()
+ {
+//#if LL_WINDOWS && _MSC_VER >= 1400
+// skip_fail("Fails on VS2005 due to broken LLSDSerialize::fromNotation() parser.");
+//#endif
+ const char LOGIN_STREAM[] = "{'method':'login', 'parameter': [ {"
+ "'uri': 'sl-am:kellys.region.siva.lindenlab.com/location?start=url&px=128&py=128&pz=128&lx=0&ly=0&lz=0'}, "
+ "{'version': i1}, {'texture_data': [ '61d724fb-ad79-f637-2186-5cf457560daa', '6e38b9be-b7cc-e77a-8aec-029a42b0b416', "
+ "'a9073524-e89b-2924-ca6e-a81944109a1a', '658f18b5-5f1e-e593-f5d5-36c3abc7249a', '0cc799f4-8c99-6b91-bd75-b179b12429e2', "
+ "'59fd9b64-8300-a425-aad8-2ffcbe9a49d2', '59fd9b64-8300-a425-aad8-2ffcbe9a49d2', '5748decc-f629-461c-9a36-a35a221fe21f', "
+ "'b8fc9be2-26a6-6b47-690b-0e902e983484', 'a13ca0fe-3802-dc97-e79a-70d12171c724', 'dd9643cf-fd5d-0376-ed4a-b1cc646a97d5', "
+ "'4ad13ae9-a112-af09-210a-cf9353a7a9e7', 'c228d1cf-4b5d-4ba8-84f4-899a0796aa97', 'c228d1cf-4b5d-4ba8-84f4-899a0796aa97', "
+ "'c228d1cf-4b5d-4ba8-84f4-899a0796aa97', 'c228d1cf-4b5d-4ba8-84f4-899a0796aa97', 'c228d1cf-4b5d-4ba8-84f4-899a0796aa97', "
+ "'5748decc-f629-461c-9a36-a35a221fe21f', 'c228d1cf-4b5d-4ba8-84f4-899a0796aa97', 'c228d1cf-4b5d-4ba8-84f4-899a0796aa97'],"
+ "'session_id': '324cfa9f-fe5d-4d1c-a317-35f20a86a4d1','position': [ i128, i128, i128],'last_name': 'Linden','group_title': '-> !BLING! <-','group_name': 'test!','agent_access': 'M',"
+ "'attachment_data': [ {'asset_id': 'aaede2b1-9955-09d4-5c93-2b557c778cf3','attachment_point': i6,'item_id': 'f3694abc-5122-db33-73d9-e0f4288dc2bf'}],"
+ "'buddy_ids': [ '101358d5-469d-4b24-9b85-4dc3c05e635d', '1b00fec7-6265-4875-acac-80d9cfe9295c', '203ad6df-b522-491d-ba48-4e24eb57aeff', "
+ "'22d4dcdb-aebb-47fa-b925-a871cc75ee48','27da3df5-1339-4463-80aa-40504ee3b3e5', '299d1720-b61f-4268-8c29-9614aa2d44c2', "
+ "'2b048a24-2737-4994-9fa5-becc8e466253', '2cd5dc14-a853-49a4-be3c-a5a7178e37bc', '3de548e1-57be-cfea-2b78-83ae3ad95998', "
+ "'3dee98e4-a6a3-4543-91c3-bbd528447ba7', '3e2d81a3-6263-6ffe-ad5c-8ce04bee07e9', '40e70b98-fed7-47f3-9700-1bce93f9350b', "
+ "'50a9b68e-b5aa-4d35-9137-3cfebda0a15c', '54295571-9357-43ff-ae74-a83b5138160f', '6191e2d7-5f96-4856-bdab-af0f79f47ae4', "
+ "'63e577d8-cd34-4235-a0a3-de0500133364', '79cfb666-4fd0-4af7-95df-fb7d96b4e24d', '8121c2f3-4a88-4c33-9899-8fc1273f47ee', "
+ "'909da964-ef23-4f2a-ba13-f2a8cfd454b6','a2e76fcd-9360-4f6d-a924-000000000001', 'aaa6d664-527e-4d83-9cbb-7ef79ccc7cc8', "
+ "'b79bfb6c-23be-49eb-b35b-30ff2f501b37', 'ba0d9c79-148c-4a79-8e3c-0665eebe2427', 'bc9bda98-57cd-498f-b993-4ff1ac9dec93', "
+ "'c62d16f6-81cb-419d-9cac-e46dc394084d', 'd48f8fa7-2512-4fe5-80c8-c0a923412e07', 'd77e3e24-7e6c-4c3f-96d0-a1746337f8fb', "
+ "'da615c63-a84b-4592-a3d6-a90dd3e92e6e', 'df47190a-7eb7-4aff-985f-2d1d3ad6c6e9', 'e3380196-72cd-499c-a2ba-caa180bd5fe4', "
+ "'e937863f-f134-4207-803b-d6e686651d6c', 'efcdf98b-5269-45ef-ac7a-0671f09ea9d9'],"
+ "'circuit_code': i124,'group_id': '8615c885-9cf0-bf0a-6e40-0c11462aa652','limited_to_estate': i1,'look_at': [ i0, i0, i0],"
+ "'agent_id': '0e346d8b-4433-4d66-a6b0-fd37083abc4c','first_name': 'Kelly','start': 'url'}]}";
+ LLChannelDescriptors ch = mBuffer.nextChannel();
+ mBuffer.append(ch.out(), (U8*)LOGIN_STREAM, static_cast<S32>(strlen(LOGIN_STREAM))); /* Flawfinder: ignore */
+ ch = mBuffer.nextChannel();
+ LLBufferStream istr(ch, &mBuffer);
+ LLSD data;
+ S32 count = LLSDSerialize::fromNotation(
+ data,
+ istr,
+ mBuffer.count(ch.in()));
+ ensure("parsed something", (count > 0));
+ ensure("sd parsed", data.isDefined());
+ ensure_equals("sd type", data.type(), LLSD::TypeMap);
+ ensure("has method", data.has("method"));
+ ensure("has parameter", data.has("parameter"));
+ LLSD parameter = data["parameter"];
+ ensure_equals("parameter is array", parameter.type(), LLSD::TypeArray);
+ LLSD agent_params = parameter[2];
+ std::string s_value;
+ s_value = agent_params["last_name"].asString();
+ ensure_equals("last name", s_value, std::string("Linden"));
+ s_value = agent_params["first_name"].asString();
+ ensure_equals("first name", s_value, std::string("Kelly"));
+ s_value = agent_params["agent_access"].asString();
+ ensure_equals("agent access", s_value, std::string("M"));
+ s_value = agent_params["group_name"].asString();
+ ensure_equals("group name", s_value, std::string("test!"));
+ s_value = agent_params["group_title"].asString();
+ ensure_equals("group title", s_value, std::string("-> !BLING! <-"));
+
+ LLUUID agent_id("0e346d8b-4433-4d66-a6b0-fd37083abc4c");
+ LLUUID id = agent_params["agent_id"];
+ ensure_equals("agent id", id, agent_id);
+ LLUUID session_id("324cfa9f-fe5d-4d1c-a317-35f20a86a4d1");
+ id = agent_params["session_id"];
+ ensure_equals("session id", id, session_id);
+ LLUUID group_id ("8615c885-9cf0-bf0a-6e40-0c11462aa652");
+ id = agent_params["group_id"];
+ ensure_equals("group id", id, group_id);
+
+ S32 i_val = agent_params["limited_to_estate"];
+ ensure_equals("limited to estate", i_val, 1);
+ i_val = agent_params["circuit_code"];
+ ensure_equals("circuit code", i_val, 124);
+ }
+
+
+ template<> template<>
+ void bas_object::test<11>()
+ {
+ std::string val = "{!'foo'@:#'bar'}";
+ std::istringstream istr;
+ istr.str(val);
+ LLSD sd;
+ S32 count = LLSDSerialize::fromNotation(sd, istr, val.size());
+ ensure_equals("parser error return value", count, -1);
+ ensure("data undefined", sd.isUndefined());
+ }
+
+ template<> template<>
+ void bas_object::test<12>()
+ {
+//#if LL_WINDOWS && _MSC_VER >= 1400
+// skip_fail("Fails on VS2005 due to broken LLSDSerialize::fromNotation() parser.");
+//#endif
+ std::string val = "{!'foo':[i1,'hi',{@'bar'#:[$i2%,^'baz'&]*}+]=}";
+ std::istringstream istr;
+ istr.str(val);
+ LLSD sd;
+ S32 count = LLSDSerialize::fromNotation(sd, istr, val.size());
+ ensure_equals("parser error return value", count, -1);
+ ensure("data undefined", sd.isUndefined());
+ }
+
+/*
+ template<> template<>
+ void bas_object::test<13>()
+ {
+ }
+ template<> template<>
+ void bas_object::test<14>()
+ {
+ }
+ template<> template<>
+ void bas_object::test<15>()
+ {
+ }
+*/
+}
+
+
+namespace tut
+{
+ class PumpAndChainTestData
+ {
+ protected:
+ apr_pool_t* mPool;
+ LLPumpIO* mPump;
+ LLPumpIO::chain_t mChain;
+
+ public:
+ PumpAndChainTestData()
+ {
+ apr_pool_create(&mPool, NULL);
+ mPump = new LLPumpIO(mPool);
+ }
+
+ ~PumpAndChainTestData()
+ {
+ mChain.clear();
+ delete mPump;
+ apr_pool_destroy(mPool);
+ }
+ };
+ typedef test_group<PumpAndChainTestData> PumpAndChainTestGroup;
+ typedef PumpAndChainTestGroup::object PumpAndChainTestObject;
+ PumpAndChainTestGroup pumpAndChainTestGroup("pump_and_chain");
+
+ template<> template<>
+ void PumpAndChainTestObject::test<1>()
+ {
+ LLPipeStringExtractor* extractor = new LLPipeStringExtractor();
+
+ mChain.push_back(LLIOPipe::ptr_t(new LLIOFlush));
+ mChain.push_back(LLIOPipe::ptr_t(extractor));
+
+ LLTimer timer;
+ timer.setTimerExpirySec(100.0f);
+
+ mPump->addChain(mChain, DEFAULT_CHAIN_EXPIRY_SECS);
+ while(!extractor->done() && !timer.hasExpired())
+ {
+ mPump->pump();
+ mPump->callback();
+ }
+
+ ensure("reading string finished", extractor->done());
+ ensure_equals("string was empty", extractor->string(), "");
+ }
+}
+
+/*
+namespace tut
+{
+ struct double_construct
+ {
+ public:
+ double_construct()
+ {
+ LL_INFOS() << "constructed" << LL_ENDL;
+ }
+ ~double_construct()
+ {
+ LL_INFOS() << "destroyed" << LL_ENDL;
+ }
+ };
+ typedef test_group<double_construct> double_construct_test_group;
+ typedef double_construct_test_group::object dc_test_object;
+ double_construct_test_group dctest("double construct");
+ template<> template<>
+ void dc_test_object::test<1>()
+ {
+ ensure("test 1", true);
+ }
+}
+*/
+
+namespace tut
+{
+ /**
+ * @brief we want to test the pipes & pumps under bad conditions.
+ */
+ struct pipe_and_pump_fitness
+ {
+ public:
+ enum
+ {
+ SERVER_LISTEN_PORT = 13050
+ };
+
+ pipe_and_pump_fitness()
+ {
+ LLFrameTimer::updateFrameTime();
+ apr_pool_create(&mPool, NULL);
+ mPump = new LLPumpIO(mPool);
+ mSocket = LLSocket::create(
+ mPool,
+ LLSocket::STREAM_TCP,
+ SERVER_LISTEN_PORT,
+ "127.0.0.1");
+ }
+
+ ~pipe_and_pump_fitness()
+ {
+ mSocket.reset();
+ delete mPump;
+ apr_pool_destroy(mPool);
+ }
+
+ protected:
+ apr_pool_t* mPool;
+ LLPumpIO* mPump;
+ LLSocket::ptr_t mSocket;
+ };
+ typedef test_group<pipe_and_pump_fitness> fitness_test_group;
+ typedef fitness_test_group::object fitness_test_object;
+ fitness_test_group fitness("pipe and pump fitness");
+
+ template<> template<>
+ void fitness_test_object::test<1>()
+ {
+ LL_DEBUGS() << "fitness_test_object::test<1>()" << LL_ENDL;
+
+ // Set up the server
+ //LL_DEBUGS() << "fitness_test_object::test<1> - setting up server."
+ // << LL_ENDL;
+ LLPumpIO::chain_t chain;
+ typedef LLCloneIOFactory<LLPipeStringInjector> emitter_t;
+ emitter_t* emitter = new emitter_t(
+ new LLPipeStringInjector("suckers never play me"));
+ std::shared_ptr<LLChainIOFactory> factory(emitter);
+ LLIOServerSocket* server = new LLIOServerSocket(
+ mPool,
+ mSocket,
+ factory);
+ server->setResponseTimeout(SHORT_CHAIN_EXPIRY_SECS);
+ chain.push_back(LLIOPipe::ptr_t(server));
+ mPump->addChain(chain, NEVER_CHAIN_EXPIRY_SECS);
+
+ // We need to tickle the pump a little to set up the listen()
+ //LL_DEBUGS() << "fitness_test_object::test<1> - initializing server."
+ // << LL_ENDL;
+ pump_loop(mPump, 0.1f);
+
+ // Set up the client
+ //LL_DEBUGS() << "fitness_test_object::test<1> - connecting client."
+ // << LL_ENDL;
+ LLSocket::ptr_t client = LLSocket::create(mPool, LLSocket::STREAM_TCP);
+ LLHost server_host("127.0.0.1", SERVER_LISTEN_PORT);
+ bool connected = client->blockingConnect(server_host);
+ ensure("Connected to server", connected);
+ LL_DEBUGS() << "connected" << LL_ENDL;
+
+ // We have connected, since the socket reader does not block,
+ // the first call to read data will return EAGAIN, so we need
+ // to write something.
+ chain.clear();
+ chain.push_back(LLIOPipe::ptr_t(new LLPipeStringInjector("hi")));
+ chain.push_back(LLIOPipe::ptr_t(new LLIOSocketWriter(client)));
+ chain.push_back(LLIOPipe::ptr_t(new LLIONull));
+ mPump->addChain(chain, 1.0f);
+
+ // Now, the server should immediately send the data, but we'll
+ // never read it. pump for a bit
+ F32 elapsed = pump_loop(mPump, 2.0f);
+ ensure("Did not take too long", (elapsed < 3.0f));
+ }
+
+ template<> template<>
+ void fitness_test_object::test<2>()
+ {
+ LL_DEBUGS() << "fitness_test_object::test<2>()" << LL_ENDL;
+
+ // Set up the server
+ LLPumpIO::chain_t chain;
+ typedef LLCloneIOFactory<LLIOFuzz> emitter_t;
+ emitter_t* emitter = new emitter_t(new LLIOFuzz(1000000));
+ std::shared_ptr<LLChainIOFactory> factory(emitter);
+ LLIOServerSocket* server = new LLIOServerSocket(
+ mPool,
+ mSocket,
+ factory);
+ server->setResponseTimeout(SHORT_CHAIN_EXPIRY_SECS);
+ chain.push_back(LLIOPipe::ptr_t(server));
+ mPump->addChain(chain, NEVER_CHAIN_EXPIRY_SECS);
+
+ // We need to tickle the pump a little to set up the listen()
+ pump_loop(mPump, 0.1f);
+
+ // Set up the client
+ LLSocket::ptr_t client = LLSocket::create(mPool, LLSocket::STREAM_TCP);
+ LLHost server_host("127.0.0.1", SERVER_LISTEN_PORT);
+ bool connected = client->blockingConnect(server_host);
+ ensure("Connected to server", connected);
+ LL_DEBUGS() << "connected" << LL_ENDL;
+
+ // We have connected, since the socket reader does not block,
+ // the first call to read data will return EAGAIN, so we need
+ // to write something.
+ chain.clear();
+ chain.push_back(LLIOPipe::ptr_t(new LLPipeStringInjector("hi")));
+ chain.push_back(LLIOPipe::ptr_t(new LLIOSocketWriter(client)));
+ chain.push_back(LLIOPipe::ptr_t(new LLIONull));
+ mPump->addChain(chain, SHORT_CHAIN_EXPIRY_SECS / 2.0f);
+
+ // Now, the server should immediately send the data, but we'll
+ // never read it. pump for a bit
+ F32 elapsed = pump_loop(mPump, SHORT_CHAIN_EXPIRY_SECS * 2.0f);
+ ensure("Did not take too long", (elapsed < 3.0f));
+ }
+
+ template<> template<>
+ void fitness_test_object::test<3>()
+ {
+ LL_DEBUGS() << "fitness_test_object::test<3>()" << LL_ENDL;
+
+ // Set up the server
+ LLPumpIO::chain_t chain;
+ typedef LLCloneIOFactory<LLIOFuzz> emitter_t;
+ emitter_t* emitter = new emitter_t(new LLIOFuzz(1000000));
+ std::shared_ptr<LLChainIOFactory> factory(emitter);
+ LLIOServerSocket* server = new LLIOServerSocket(
+ mPool,
+ mSocket,
+ factory);
+ server->setResponseTimeout(SHORT_CHAIN_EXPIRY_SECS);
+ chain.push_back(LLIOPipe::ptr_t(server));
+ mPump->addChain(chain, NEVER_CHAIN_EXPIRY_SECS);
+
+ // We need to tickle the pump a little to set up the listen()
+ pump_loop(mPump, 0.1f);
+
+ // Set up the client
+ LLSocket::ptr_t client = LLSocket::create(mPool, LLSocket::STREAM_TCP);
+ LLHost server_host("127.0.0.1", SERVER_LISTEN_PORT);
+ bool connected = client->blockingConnect(server_host);
+ ensure("Connected to server", connected);
+ LL_DEBUGS() << "connected" << LL_ENDL;
+
+ // We have connected, since the socket reader does not block,
+ // the first call to read data will return EAGAIN, so we need
+ // to write something.
+ chain.clear();
+ chain.push_back(LLIOPipe::ptr_t(new LLPipeStringInjector("hi")));
+ chain.push_back(LLIOPipe::ptr_t(new LLIOSocketWriter(client)));
+ chain.push_back(LLIOPipe::ptr_t(new LLIONull));
+ mPump->addChain(chain, SHORT_CHAIN_EXPIRY_SECS * 2.0f);
+
+ // Now, the server should immediately send the data, but we'll
+ // never read it. pump for a bit
+ F32 elapsed = pump_loop(mPump, SHORT_CHAIN_EXPIRY_SECS * 2.0f + 1.0f);
+ ensure("Did not take too long", (elapsed < 4.0f));
+ }
+
+ template<> template<>
+ void fitness_test_object::test<4>()
+ {
+ LL_DEBUGS() << "fitness_test_object::test<4>()" << LL_ENDL;
+
+ // Set up the server
+ LLPumpIO::chain_t chain;
+ typedef LLCloneIOFactory<LLIOFuzz> emitter_t;
+ emitter_t* emitter = new emitter_t(new LLIOFuzz(1000000));
+ std::shared_ptr<LLChainIOFactory> factory(emitter);
+ LLIOServerSocket* server = new LLIOServerSocket(
+ mPool,
+ mSocket,
+ factory);
+ server->setResponseTimeout(SHORT_CHAIN_EXPIRY_SECS + 1.80f);
+ chain.push_back(LLIOPipe::ptr_t(server));
+ mPump->addChain(chain, NEVER_CHAIN_EXPIRY_SECS);
+
+ // We need to tickle the pump a little to set up the listen()
+ pump_loop(mPump, 0.1f);
+
+ // Set up the client
+ LLSocket::ptr_t client = LLSocket::create(mPool, LLSocket::STREAM_TCP);
+ LLHost server_host("127.0.0.1", SERVER_LISTEN_PORT);
+ bool connected = client->blockingConnect(server_host);
+ ensure("Connected to server", connected);
+ LL_DEBUGS() << "connected" << LL_ENDL;
+
+ // We have connected, since the socket reader does not block,
+ // the first call to read data will return EAGAIN, so we need
+ // to write something.
+ chain.clear();
+ chain.push_back(LLIOPipe::ptr_t(new LLPipeStringInjector("hi")));
+ chain.push_back(LLIOPipe::ptr_t(new LLIOSocketWriter(client)));
+ chain.push_back(LLIOPipe::ptr_t(new LLIONull));
+ mPump->addChain(chain, NEVER_CHAIN_EXPIRY_SECS);
+
+ // Now, the server should immediately send the data, but we'll
+ // never read it. pump for a bit
+ F32 elapsed = pump_loop(mPump, SHORT_CHAIN_EXPIRY_SECS + 3.0f);
+ ensure("Did not take too long", (elapsed < DEFAULT_CHAIN_EXPIRY_SECS));
+ }
+
+ template<> template<>
+ void fitness_test_object::test<5>()
+ {
+ // Set up the server
+ LLPumpIO::chain_t chain;
+ typedef LLCloneIOFactory<LLIOSleeper> sleeper_t;
+ sleeper_t* sleeper = new sleeper_t(new LLIOSleeper);
+ std::shared_ptr<LLChainIOFactory> factory(sleeper);
+ LLIOServerSocket* server = new LLIOServerSocket(
+ mPool,
+ mSocket,
+ factory);
+ server->setResponseTimeout(1.0);
+ chain.push_back(LLIOPipe::ptr_t(server));
+ mPump->addChain(chain, NEVER_CHAIN_EXPIRY_SECS);
+ // We need to tickle the pump a little to set up the listen()
+ pump_loop(mPump, 0.1f);
+ auto count = mPump->runningChains();
+ ensure_equals("server chain onboard", count, 1);
+ LL_DEBUGS() << "** Server is up." << LL_ENDL;
+
+ // Set up the client
+ LLSocket::ptr_t client = LLSocket::create(mPool, LLSocket::STREAM_TCP);
+ LLHost server_host("127.0.0.1", SERVER_LISTEN_PORT);
+ bool connected = client->blockingConnect(server_host);
+ ensure("Connected to server", connected);
+ LL_DEBUGS() << "connected" << LL_ENDL;
+ pump_loop(mPump,0.1f);
+ count = mPump->runningChains();
+ ensure_equals("server chain onboard", count, 2);
+ LL_DEBUGS() << "** Client is connected." << LL_ENDL;
+
+ // We have connected, since the socket reader does not block,
+ // the first call to read data will return EAGAIN, so we need
+ // to write something.
+ chain.clear();
+ chain.push_back(LLIOPipe::ptr_t(new LLPipeStringInjector("hi")));
+ chain.push_back(LLIOPipe::ptr_t(new LLIOSocketWriter(client)));
+ chain.push_back(LLIOPipe::ptr_t(new LLIONull));
+ mPump->addChain(chain, 0.2f);
+ chain.clear();
+
+ // pump for a bit and make sure all 3 chains are running
+ pump_loop(mPump,0.1f);
+ count = mPump->runningChains();
+ // ensure_equals("client chain onboard", count, 3); commented out because it fails frequently - appears to be timing sensitive
+ LL_DEBUGS() << "** request should have been sent." << LL_ENDL;
+
+ // pump for long enough the the client socket closes, and the
+ // server socket should not be closed yet.
+ pump_loop(mPump,0.2f);
+ count = mPump->runningChains();
+ ensure_equals("client chain timed out ", count, 2);
+ LL_DEBUGS() << "** client chain should be closed." << LL_ENDL;
+
+ // At this point, the socket should be closed by the timeout
+ pump_loop(mPump,1.0f);
+ count = mPump->runningChains();
+ ensure_equals("accepted socked close", count, 1);
+ LL_DEBUGS() << "** Sleeper should have timed out.." << LL_ENDL;
+ }
+}
+
+/*
+'asset_data':b(12100)"{'task_id':ucc706f2d-0b68-68f8-11a4-f1043ff35ca0}\n{\n\tname\tObject|\n\tpermissions 0\n\t{\n\t\tbase_mask\t7fffffff\n\t\towner_mask\t7fffffff\n\t\tgroup_mask\t00000000\n\t\teveryone_mask\t00000000\n\t\tnext_owner_mask\t7fffffff\n\t\tcreator_id\t13fd9595-a47b-4d64-a5fb-6da645f038e0\n\t\towner_id\t3c115e51-04f4-523c-9fa6-98aff1034730\n\t\tlast_owner_id\t3c115e51-04f4-523c-9fa6-98aff1034730\n\t\tgroup_id\t00000000-0000-0000-0000-000000000000\n\t}\n\tlocal_id\t217444921\n\ttotal_crc\t323\n\ttype\t2\n\ttask_valid\t2\n\ttravel_access\t13\n\tdisplayopts\t2\n\tdisplaytype\tv\n\tpos\t-0.368634403\t0.00781063363\t-0.569040775\n\toldpos\t150.117996\t25.8658009\t8.19664001\n\trotation\t-0.06293071806430816650390625\t-0.6995697021484375\t-0.7002241611480712890625\t0.1277817934751510620117188\n\tchildpos\t-0.00499999989\t-0.0359999985\t0.307999998\n\tchildrot\t-0.515492737293243408203125\t-0.46601200103759765625\t0.529055416584014892578125\t0.4870323240756988525390625\n\tscale\t0.074629\t0.289956\t0.01\n\tsit_offset\t0\t0\t0\n\tcamera_eye_offset\t0\t0\t0\n\tcamera_at_offset\t0\t0\t0\n\tsit_quat\t0\t0\t0\t1\n\tsit_hint\t0\n\tstate\t160\n\tmaterial\t3\n\tsoundid\t00000000-0000-0000-0000-000000000000\n\tsoundgain\t0\n\tsoundradius\t0\n\tsoundflags\t0\n\ttextcolor\t0 0 0 1\n\tselected\t0\n\tselector\t00000000-0000-0000-0000-000000000000\n\tusephysics\t0\n\trotate_x\t1\n\trotate_y\t1\n\trotate_z\t1\n\tphantom\t0\n\tremote_script_access_pin\t0\n\tvolume_detect\t0\n\tblock_grabs\t0\n\tdie_at_edge\t0\n\treturn_at_edge\t0\n\ttemporary\t0\n\tsandbox\t0\n\tsandboxhome\t0\t0\t0\n\tshape 0\n\t{\n\t\tpath 0\n\t\t{\n\t\t\tcurve\t16\n\t\t\tbegin\t0\n\t\t\tend\t1\n\t\t\tscale_x\t1\n\t\t\tscale_y\t1\n\t\t\tshear_x\t0\n\t\t\tshear_y\t0\n\t\t\ttwist\t0\n\t\t\ttwist_begin\t0\n\t\t\tradius_offset\t0\n\t\t\ttaper_x\t0\n\t\t\ttaper_y\t0\n\t\t\trevolutions\t1\n\t\t\tskew\t0\n\t\t}\n\t\tprofile 0\n\t\t{\n\t\t\tcurve\t1\n\t\t\tbegin\t0\n\t\t\tend\t1\n\t\t\thollow\t0\n\t\t}\n\t}\n\tfaces\t6\n\t{\n\t\timageid\tddde1ffc-678b-3cda-1748-513086bdf01b\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\tf54a0c32-3cd1-d49a-5b4f-7b792bebc204\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\tf54a0c32-3cd1-d49a-5b4f-7b792bebc204\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\tf54a0c32-3cd1-d49a-5b4f-7b792bebc204\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\tf54a0c32-3cd1-d49a-5b4f-7b792bebc204\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\tddde1ffc-678b-3cda-1748-513086bdf01b\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t-1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\tps_next_crc\t1\n\tgpw_bias\t1\n\tip\t0\n\tcomplete\tTRUE\n\tdelay\t50000\n\tnextstart\t0\n\tbirthtime\t1061088050622956\n\treztime\t1094866329019785\n\tparceltime\t1133568981980596\n\ttax_rate\t1.00084\n\tscratchpad\t0\n\t{\n\t\n\t}\n\tsale_info\t0\n\t{\n\t\tsale_type\tnot\n\t\tsale_price\t10\n\t}\n\tcorrect_family_id\t00000000-0000-0000-0000-000000000000\n\thas_rezzed\t0\n\tpre_link_base_mask\t7fffffff\n\tlinked \tchild\n\tdefault_pay_price\t-2\t1\t5\t10\t20\n}\n{'task_id':u61fa7364-e151-0597-774c-523312dae31b}\n{\n\tname\tObject|\n\tpermissions 0\n\t{\n\t\tbase_mask\t7fffffff\n\t\towner_mask\t7fffffff\n\t\tgroup_mask\t00000000\n\t\teveryone_mask\t00000000\n\t\tnext_owner_mask\t7fffffff\n\t\tcreator_id\t13fd9595-a47b-4d64-a5fb-6da645f038e0\n\t\towner_id\t3c115e51-04f4-523c-9fa6-98aff1034730\n\t\tlast_owner_id\t3c115e51-04f4-523c-9fa6-98aff1034730\n\t\tgroup_id\t00000000-0000-0000-0000-000000000000\n\t}\n\tlocal_id\t217444922\n\ttotal_crc\t324\n\ttype\t2\n\ttask_valid\t2\n\ttravel_access\t13\n\tdisplayopts\t2\n\tdisplaytype\tv\n\tpos\t-0.367110789\t0.00780026987\t-0.566269755\n\toldpos\t150.115005\t25.8479004\t8.18669987\n\trotation\t0.47332942485809326171875\t-0.380102097988128662109375\t-0.5734078884124755859375\t0.550168216228485107421875\n\tchildpos\t-0.00499999989\t-0.0370000005\t0.305000007\n\tchildrot\t-0.736649334430694580078125\t-0.03042060509324073791503906\t-0.02784589119255542755126953\t0.67501628398895263671875\n\tscale\t0.074629\t0.289956\t0.01\n\tsit_offset\t0\t0\t0\n\tcamera_eye_offset\t0\t0\t0\n\tcamera_at_offset\t0\t0\t0\n\tsit_quat\t0\t0\t0\t1\n\tsit_hint\t0\n\tstate\t160\n\tmaterial\t3\n\tsoundid\t00000000-0000-0000-0000-000000000000\n\tsoundgain\t0\n\tsoundradius\t0\n\tsoundflags\t0\n\ttextcolor\t0 0 0 1\n\tselected\t0\n\tselector\t00000000-0000-0000-0000-000000000000\n\tusephysics\t0\n\trotate_x\t1\n\trotate_y\t1\n\trotate_z\t1\n\tphantom\t0\n\tremote_script_access_pin\t0\n\tvolume_detect\t0\n\tblock_grabs\t0\n\tdie_at_edge\t0\n\treturn_at_edge\t0\n\ttemporary\t0\n\tsandbox\t0\n\tsandboxhome\t0\t0\t0\n\tshape 0\n\t{\n\t\tpath 0\n\t\t{\n\t\t\tcurve\t16\n\t\t\tbegin\t0\n\t\t\tend\t1\n\t\t\tscale_x\t1\n\t\t\tscale_y\t1\n\t\t\tshear_x\t0\n\t\t\tshear_y\t0\n\t\t\ttwist\t0\n\t\t\ttwist_begin\t0\n\t\t\tradius_offset\t0\n\t\t\ttaper_x\t0\n\t\t\ttaper_y\t0\n\t\t\trevolutions\t1\n\t\t\tskew\t0\n\t\t}\n\t\tprofile 0\n\t\t{\n\t\t\tcurve\t1\n\t\t\tbegin\t0\n\t\t\tend\t1\n\t\t\thollow\t0\n\t\t}\n\t}\n\tfaces\t6\n\t{\n\t\timageid\tddde1ffc-678b-3cda-1748-513086bdf01b\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\tf54a0c32-3cd1-d49a-5b4f-7b792bebc204\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\tf54a0c32-3cd1-d49a-5b4f-7b792bebc204\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\tf54a0c32-3cd1-d49a-5b4f-7b792bebc204\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\tf54a0c32-3cd1-d49a-5b4f-7b792bebc204\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\tddde1ffc-678b-3cda-1748-513086bdf01b\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t-1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\tps_next_crc\t1\n\tgpw_bias\t1\n\tip\t0\n\tcomplete\tTRUE\n\tdelay\t50000\n\tnextstart\t0\n\tbirthtime\t1061087839248891\n\treztime\t1094866329020800\n\tparceltime\t1133568981981983\n\ttax_rate\t1.00084\n\tscratchpad\t0\n\t{\n\t\n\t}\n\tsale_info\t0\n\t{\n\t\tsale_type\tnot\n\t\tsale_price\t10\n\t}\n\tcorrect_family_id\t00000000-0000-0000-0000-000000000000\n\thas_rezzed\t0\n\tpre_link_base_mask\t7fffffff\n\tlinked \tchild\n\tdefault_pay_price\t-2\t1\t5\t10\t20\n}\n{'task_id':ub8d68643-7dd8-57af-0d24-8790032aed0c}\n{\n\tname\tObject|\n\tpermissions 0\n\t{\n\t\tbase_mask\t7fffffff\n\t\towner_mask\t7fffffff\n\t\tgroup_mask\t00000000\n\t\teveryone_mask\t00000000\n\t\tnext_owner_mask\t7fffffff\n\t\tcreator_id\t13fd9595-a47b-4d64-a5fb-6da645f038e0\n\t\towner_id\t3c115e51-04f4-523c-9fa6-98aff1034730\n\t\tlast_owner_id\t3c115e51-04f4-523c-9fa6-98aff1034730\n\t\tgroup_id\t00000000-0000-0000-0000-000000000000\n\t}\n\tlocal_id\t217444923\n\ttotal_crc\t235\n\ttype\t2\n\ttask_valid\t2\n\ttravel_access\t13\n\tdisplayopts\t2\n\tdisplaytype\tv\n\tpos\t-0.120029509\t-0.00284469454\t-0.0302077383\n\toldpos\t150.710999\t25.8584995\t8.19172001\n\trotation\t0.145459949970245361328125\t-0.1646589934825897216796875\t0.659558117389678955078125\t-0.718826770782470703125\n\tchildpos\t0\t-0.182999998\t-0.26699999\n\tchildrot\t0.991444766521453857421875\t3.271923924330621957778931e-05\t-0.0002416197530692443251609802\t0.1305266767740249633789062\n\tscale\t0.0382982\t0.205957\t0.368276\n\tsit_offset\t0\t0\t0\n\tcamera_eye_offset\t0\t0\t0\n\tcamera_at_offset\t0\t0\t0\n\tsit_quat\t0\t0\t0\t1\n\tsit_hint\t0\n\tstate\t160\n\tmaterial\t3\n\tsoundid\t00000000-0000-0000-0000-000000000000\n\tsoundgain\t0\n\tsoundradius\t0\n\tsoundflags\t0\n\ttextcolor\t0 0 0 1\n\tselected\t0\n\tselector\t00000000-0000-0000-0000-000000000000\n\tusephysics\t0\n\trotate_x\t1\n\trotate_y\t1\n\trotate_z\t1\n\tphantom\t0\n\tremote_script_access_pin\t0\n\tvolume_detect\t0\n\tblock_grabs\t0\n\tdie_at_edge\t0\n\treturn_at_edge\t0\n\ttemporary\t0\n\tsandbox\t0\n\tsandboxhome\t0\t0\t0\n\tshape 0\n\t{\n\t\tpath 0\n\t\t{\n\t\t\tcurve\t32\n\t\t\tbegin\t0.3\n\t\t\tend\t0.65\n\t\t\tscale_x\t1\n\t\t\tscale_y\t0.05\n\t\t\tshear_x\t0\n\t\t\tshear_y\t0\n\t\t\ttwist\t0\n\t\t\ttwist_begin\t0\n\t\t\tradius_offset\t0\n\t\t\ttaper_x\t0\n\t\t\ttaper_y\t0\n\t\t\trevolutions\t1\n\t\t\tskew\t0\n\t\t}\n\t\tprofile 0\n\t\t{\n\t\t\tcurve\t0\n\t\t\tbegin\t0\n\t\t\tend\t1\n\t\t\thollow\t0\n\t\t}\n\t}\n\tfaces\t3\n\t{\n\t\timageid\te7150bed-3e3e-c698-eb15-d17b178148af\n\t\tcolors\t0.843137 0.156863 0.156863 1\n\t\tscales\t15\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t-1.57084\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\te7150bed-3e3e-c698-eb15-d17b178148af\n\t\tcolors\t0.843137 0.156863 0.156863 1\n\t\tscales\t15\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t-1.57084\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\te7150bed-3e3e-c698-eb15-d17b178148af\n\t\tcolors\t0.843137 0.156863 0.156863 1\n\t\tscales\t15\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t-1.57084\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\tps_next_crc\t1\n\tgpw_bias\t1\n\tip\t0\n\tcomplete\tTRUE\n\tdelay\t50000\n\tnextstart\t0\n\tbirthtime\t1061087534454174\n\treztime\t1094866329021741\n\tparceltime\t1133568981982889\n\ttax_rate\t1.00326\n\tscratchpad\t0\n\t{\n\t\n\t}\n\tsale_info\t0\n\t{\n\t\tsale_type\tnot\n\t\tsale_price\t10\n\t}\n\tcorrect_family_id\t00000000-0000-0000-0000-000000000000\n\thas_rezzed\t0\n\tpre_link_base_mask\t7fffffff\n\tlinked \tchild\n\tdefault_pay_price\t-2\t1\t5\t10\t20\n}\n{'task_id':ue4b19200-9d33-962f-c8c5-6f25be3a3fd0}\n{\n\tname\tApotheosis_Immolaine_tail|\n\tpermissions 0\n\t{\n\t\tbase_mask\t7fffffff\n\t\towner_mask\t7fffffff\n\t\tgroup_mask\t00000000\n\t\teveryone_mask\t00000000\n\t\tnext_owner_mask\t7fffffff\n\t\tcreator_id\t13fd9595-a47b-4d64-a5fb-6da645f038e0\n\t\towner_id\t3c115e51-04f4-523c-9fa6-98aff1034730\n\t\tlast_owner_id\t3c115e51-04f4-523c-9fa6-98aff1034730\n\t\tgroup_id\t00000000-0000-0000-0000-000000000000\n\t}\n\tlocal_id\t217444924\n\ttotal_crc\t675\n\ttype\t1\n\ttask_valid\t2\n\ttravel_access\t13\n\tdisplayopts\t2\n\tdisplaytype\tv\n\tpos\t-0.34780401\t-0.00968400016\t-0.260098994\n\toldpos\t0\t0\t0\n\trotation\t0.73164522647857666015625\t-0.67541944980621337890625\t-0.07733880728483200073242188\t0.05022468417882919311523438\n\tvelocity\t0\t0\t0\n\tangvel\t0\t0\t0\n\tscale\t0.0382982\t0.32228\t0.383834\n\tsit_offset\t0\t0\t0\n\tcamera_eye_offset\t0\t0\t0\n\tcamera_at_offset\t0\t0\t0\n\tsit_quat\t0\t0\t0\t1\n\tsit_hint\t0\n\tstate\t160\n\tmaterial\t3\n\tsoundid\t00000000-0000-0000-0000-000000000000\n\tsoundgain\t0\n\tsoundradius\t0\n\tsoundflags\t0\n\ttextcolor\t0 0 0 1\n\tselected\t0\n\tselector\t00000000-0000-0000-0000-000000000000\n\tusephysics\t0\n\trotate_x\t1\n\trotate_y\t1\n\trotate_z\t1\n\tphantom\t0\n\tremote_script_access_pin\t0\n\tvolume_detect\t0\n\tblock_grabs\t0\n\tdie_at_edge\t0\n\treturn_at_edge\t0\n\ttemporary\t0\n\tsandbox\t0\n\tsandboxhome\t0\t0\t0\n\tshape 0\n\t{\n\t\tpath 0\n\t\t{\n\t\t\tcurve\t32\n\t\t\tbegin\t0.3\n\t\t\tend\t0.65\n\t\t\tscale_x\t1\n\t\t\tscale_y\t0.05\n\t\t\tshear_x\t0\n\t\t\tshear_y\t0\n\t\t\ttwist\t0\n\t\t\ttwist_begin\t0\n\t\t\tradius_offset\t0\n\t\t\ttaper_x\t0\n\t\t\ttaper_y\t0\n\t\t\trevolutions\t1\n\t\t\tskew\t0\n\t\t}\n\t\tprofile 0\n\t\t{\n\t\t\tcurve\t0\n\t\t\tbegin\t0\n\t\t\tend\t1\n\t\t\thollow\t0\n\t\t}\n\t}\n\tfaces\t3\n\t{\n\t\timageid\te7150bed-3e3e-c698-eb15-d17b178148af\n\t\tcolors\t0.843137 0.156863 0.156863 1\n\t\tscales\t15\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t-1.57084\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\te7150bed-3e3e-c698-eb15-d17b178148af\n\t\tcolors\t0.843137 0.156863 0.156863 1\n\t\tscales\t15\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t-1.57084\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\te7150bed-3e3e-c698-eb15-d17b178148af\n\t\tcolors\t0.843137 0.156863 0.156863 1\n\t\tscales\t15\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t-1.57084\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\tps_next_crc\t1\n\tgpw_bias\t1\n\tip\t0\n\tcomplete\tTRUE\n\tdelay\t50000\n\tnextstart\t0\n\tbirthtime\t1061087463950186\n\treztime\t1094866329022555\n\tparceltime\t1133568981984359\n\tdescription\t(No Description)|\n\ttax_rate\t1.01736\n\tnamevalue\tAttachPt U32 RW S 10\n\tnamevalue\tAttachmentOrientation VEC3 RW DS -3.110088, -0.182018, 1.493795\n\tnamevalue\tAttachmentOffset VEC3 RW DS -0.347804, -0.009684, -0.260099\n\tnamevalue\tAttachItemID STRING RW SV 20f36c3a-b44b-9bc7-87f3-018bfdfc8cda\n\tscratchpad\t0\n\t{\n\t\n\t}\n\tsale_info\t0\n\t{\n\t\tsale_type\tnot\n\t\tsale_price\t10\n\t}\n\torig_asset_id\t8747acbc-d391-1e59-69f1-41d06830e6c0\n\torig_item_id\t20f36c3a-b44b-9bc7-87f3-018bfdfc8cda\n\tfrom_task_id\t3c115e51-04f4-523c-9fa6-98aff1034730\n\tcorrect_family_id\t00000000-0000-0000-0000-000000000000\n\thas_rezzed\t0\n\tpre_link_base_mask\t7fffffff\n\tlinked \tlinked\n\tdefault_pay_price\t-2\t1\t5\t10\t20\n}\n"
+*/
diff --git a/indra/llmessage/tests/llbuffer_test.cpp b/indra/llmessage/tests/llbuffer_test.cpp
new file mode 100644
index 0000000000..330a4f288f
--- /dev/null
+++ b/indra/llmessage/tests/llbuffer_test.cpp
@@ -0,0 +1,271 @@
+/**
+ * @file llbuffer_tut.cpp
+ * @author Adroit
+ * @date 2007-03
+ * @brief llbuffer test cases.
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include <tut/tut.hpp>
+
+#include "linden_common.h"
+#include "lltut.h"
+#include "llbuffer.h"
+#include "llerror.h"
+
+
+namespace tut
+{
+ struct buffer
+ {
+ };
+
+ typedef test_group<buffer> buffer_t;
+ typedef buffer_t::object buffer_object_t;
+ tut::buffer_t tut_buffer("buffer");
+
+ template<> template<>
+ void buffer_object_t::test<1>()
+ {
+ LLChannelDescriptors channelDescriptors;
+ ensure("in() and out() functions Failed", (0 == channelDescriptors.in() && 1 == channelDescriptors.out()));
+
+ S32 val = 50;
+ LLChannelDescriptors channelDescriptors1(val);
+ ensure("LLChannelDescriptors in() and out() functions Failed", (50 == channelDescriptors1.in() && 51 == channelDescriptors1.out()));
+ }
+
+ template<> template<>
+ void buffer_object_t::test<2>()
+ {
+ LLSegment segment;
+ ensure("LLSegment get functions failed", (0 == segment.getChannel() && NULL == segment.data() && 0 == segment.size()));
+ segment.setChannel(50);
+ ensure_equals("LLSegment setChannel() function failed", segment.getChannel(), 50);
+ ensure("LLSegment isOnChannel() function failed", (true == segment.isOnChannel(50)));
+ }
+
+ template<> template<>
+ void buffer_object_t::test<3>()
+ {
+ S32 channel = 30;
+ const char str[] = "SecondLife";
+ S32 len = sizeof(str);
+ LLSegment segment(channel, (U8*)str, len);
+ ensure("LLSegment get functions failed", (30 == segment.getChannel() && len == segment.size() && (U8*)str == segment.data()));
+ ensure_memory_matches("LLSegment::data() failed", segment.data(), segment.size(), (U8*)str, len);
+ ensure("LLSegment isOnChannel() function failed", (true == segment.isOnChannel(channel)));
+ }
+
+ template<> template<>
+ void buffer_object_t::test<4>()
+ {
+ S32 channel = 50;
+ S32 bigSize = 16384*2;
+ char str[] = "SecondLife";
+ S32 smallSize = sizeof(str);
+
+ LLSegment segment;
+ LLHeapBuffer buf; // use default size of DEFAULT_HEAP_BUFFER_SIZE = 16384
+
+ S32 requestSize;
+
+ requestSize = 16384-1;
+ ensure("1. LLHeapBuffer createSegment failed", (true == buf.createSegment(channel, requestSize, segment)) && segment.size() == requestSize);
+ // second request for remainign 1 byte
+
+ requestSize = 1;
+ ensure("2. LLHeapBuffer createSegment failed", (true == buf.createSegment(channel, requestSize, segment)) && segment.size() == requestSize);
+
+ // it should fail now.
+ requestSize = 1;
+ ensure("3. LLHeapBuffer createSegment failed", (false == buf.createSegment(channel, requestSize, segment)));
+
+ LLHeapBuffer buf1(bigSize);
+
+ // requst for more than default size but less than total sizeit should fail now.
+ requestSize = 16384 + 1;
+ ensure("4. LLHeapBuffer createSegment failed", (true == buf1.createSegment(channel, requestSize, segment)) && segment.size() == requestSize);
+
+ LLHeapBuffer buf2((U8*) str, smallSize);
+ requestSize = smallSize;
+ ensure("5. LLHeapBuffer createSegment failed", (true == buf2.createSegment(channel, requestSize, segment)) && segment.size() == requestSize && memcmp(segment.data(), (U8*) str, requestSize) == 0);
+ requestSize = smallSize+1;
+ ensure("6. LLHeapBuffer createSegment failed", (false == buf2.createSegment(channel, requestSize, segment)));
+ }
+
+ //makeChannelConsumer()
+ template<> template<>
+ void buffer_object_t::test<5>()
+ {
+ LLChannelDescriptors inchannelDescriptors(20);
+ LLChannelDescriptors outchannelDescriptors = LLBufferArray::makeChannelConsumer(inchannelDescriptors);
+ ensure("LLBufferArray::makeChannelConsumer() function Failed", (21 == outchannelDescriptors.in()));
+ }
+
+ template<> template<>
+ void buffer_object_t::test<6>()
+ {
+ LLBufferArray bufferArray;
+ const char array[] = "SecondLife";
+ S32 len = static_cast<S32>(strlen(array));
+ LLChannelDescriptors channelDescriptors = bufferArray.nextChannel();
+ bufferArray.append(channelDescriptors.in(), (U8*)array, len);
+ S32 count = bufferArray.countAfter(channelDescriptors.in(), NULL);
+ ensure_equals("Appended size is:", count, len);
+ }
+
+ //append() and prepend()
+ template<> template<>
+ void buffer_object_t::test<7>()
+ {
+ LLBufferArray bufferArray;
+ const char array[] = "SecondLife";
+ S32 len = static_cast<S32>(strlen(array));
+ const char array1[] = "LindenLabs";
+ S32 len1 = static_cast<S32>(strlen(array1));
+
+ std::string str(array1);
+ str.append(array);
+
+ LLChannelDescriptors channelDescriptors = bufferArray.nextChannel();
+ bufferArray.append(channelDescriptors.in(), (U8*)array, len);
+ bufferArray.prepend(channelDescriptors.in(), (U8*)array1, len1);
+ char buf[100];
+ S32 len2 = 20;
+ bufferArray.readAfter(channelDescriptors.in(), NULL, (U8*)buf, len2);
+ ensure_equals("readAfter length failed", len2, 20);
+
+ buf[len2] = '\0';
+ ensure_equals("readAfter/prepend/append failed", buf, str);
+ }
+
+ //append()
+ template<> template<>
+ void buffer_object_t::test<8>()
+ {
+ LLBufferArray bufferArray;
+ const char array[] = "SecondLife";
+ S32 len = static_cast<S32>(strlen(array));
+ const char array1[] = "LindenLabs";
+ S32 len1 = static_cast<S32>(strlen(array1));
+
+ std::string str(array);
+ str.append(array1);
+
+ LLChannelDescriptors channelDescriptors = bufferArray.nextChannel();
+ bufferArray.append(channelDescriptors.in(), (U8*)array, len);
+ bufferArray.append(channelDescriptors.in(), (U8*)array1, len1);
+ char buf[100];
+ S32 len2 = 20;
+ bufferArray.readAfter(channelDescriptors.in(), NULL, (U8*)buf, len2);
+ ensure_equals("readAfter length failed", len2, 20);
+
+ buf[len2] = '\0';
+ ensure_equals("readAfter/append/append failed", buf, str);
+ }
+
+ template<> template<>
+ void buffer_object_t::test<9>()
+ {
+ LLBufferArray bufferArray;
+ const char array[] = "SecondLife";
+ S32 len = static_cast<S32>(strlen(array)) + 1;
+ std::string str(array);
+ LLChannelDescriptors channelDescriptors = bufferArray.nextChannel();
+ bufferArray.append(channelDescriptors.in(), (U8*)array, len);
+ LLBufferArray bufferArray1;
+ ensure("Contents are not copied and the source buffer is not empty", (1 == bufferArray1.takeContents(bufferArray)));
+
+ char buf[100];
+ S32 len2 = len;
+ bufferArray1.readAfter(channelDescriptors.in(), NULL, (U8*)buf, len2);
+ ensure_equals("takeContents failed to copy", buf, str);
+ }
+
+ //seek()
+ template<> template<>
+ void buffer_object_t::test<10>()
+ {
+ const char array[] = "SecondLife is a Virtual World";
+ S32 len = static_cast<S32>(strlen(array));
+ LLBufferArray bufferArray;
+ bufferArray.append(0, (U8*)array, len);
+
+ char buf[255];
+ S32 len1 = 16;
+ U8* last = bufferArray.readAfter(0, 0, (U8*)buf, len1);
+ buf[len1] = '\0';
+ last = bufferArray.seek(0, last, -2);
+
+ len1 = 15;
+ last = bufferArray.readAfter(0, last, (U8*)buf, len1);
+ buf[len1] = '\0';
+ std::string str(buf);
+ ensure_equals("Seek does'nt worked", str, std::string("a Virtual World"));
+ }
+
+ template<> template<>
+ void buffer_object_t::test<11>()
+ {
+ const char array[] = "SecondLife is a Virtual World";
+ S32 len = static_cast<S32>(strlen(array));
+ LLBufferArray bufferArray;
+ bufferArray.append(0, (U8*)array, len);
+
+ char buf[255];
+ S32 len1 = 10;
+ U8* last = bufferArray.readAfter(0, 0, (U8*)buf, len1);
+ bufferArray.splitAfter(last);
+ LLBufferArray::segment_iterator_t iterator = bufferArray.beginSegment();
+ ++iterator;
+ std::string str(((char*)(*iterator).data()), (*iterator).size());
+ ensure_equals("Strings are not equal;splitAfter() operation failed", str, std::string(" is a Virtual World"));
+ }
+
+ //makeSegment()->eraseSegment()
+ template<> template<>
+ void buffer_object_t::test<12>()
+ {
+ LLBufferArray bufferArray;
+ LLChannelDescriptors channelDescriptors;
+ LLBufferArray::segment_iterator_t it;
+ S32 length = 1000;
+ it = bufferArray.makeSegment(channelDescriptors.out(), length);
+ ensure("makeSegment() function failed", (it != bufferArray.endSegment()));
+ ensure("eraseSegment() function failed", bufferArray.eraseSegment(it));
+ ensure("eraseSegment() begin/end should now be same", bufferArray.beginSegment() == bufferArray.endSegment());
+ }
+
+ // constructSegmentAfter()
+ template<> template<>
+ void buffer_object_t::test<13>()
+ {
+ LLBufferArray bufferArray;
+ LLBufferArray::segment_iterator_t it;
+ LLSegment segment;
+ LLBufferArray::segment_iterator_t end = bufferArray.endSegment();
+ it = bufferArray.constructSegmentAfter(NULL, segment);
+ ensure("constructSegmentAfter() function failed", (it == end));
+ }
+}
diff --git a/indra/llmessage/tests/llcurl_stub.cpp b/indra/llmessage/tests/llcurl_stub.cpp
deleted file mode 100644
index 78c195580c..0000000000
--- a/indra/llmessage/tests/llcurl_stub.cpp
+++ /dev/null
@@ -1,99 +0,0 @@
-/**
- * @file llcurl_stub.cpp
- * @brief stub class to allow unit testing
- *
- * $LicenseInfo:firstyear=2008&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_CURL_STUB_CPP
-#define LL_CURL_STUB_CPP
-
-
-#include "linden_common.h"
-#include "llcurl.h"
-#include "llhttpconstants.cpp"
-
-LLCurl::Responder::Responder()
-{
-}
-
-void LLCurl::Responder::httpCompleted()
-{
- if (isGoodStatus())
- {
- httpSuccess();
- }
- else
- {
- httpFailure();
- }
-}
-
-void LLCurl::Responder::completedRaw(LLChannelDescriptors const&,
- std::shared_ptr<LLBufferArray> const&)
-{
-}
-
-void LLCurl::Responder::httpFailure()
-{
-}
-
-LLCurl::Responder::~Responder ()
-{
-}
-
-void LLCurl::Responder::httpSuccess()
-{
-}
-
-std::string LLCurl::Responder::dumpResponse() const
-{
- return "dumpResponse()";
-}
-
-void LLCurl::Responder::successResult(const LLSD& content)
-{
- setResult(HTTP_OK, "", content);
- httpSuccess();
-}
-
-void LLCurl::Responder::failureResult(S32 status, const std::string& reason, const LLSD& content)
-{
- setResult(status, reason, content);
- httpFailure();
-}
-
-
-void LLCurl::Responder::completeResult(S32 status, const std::string& reason, const LLSD& content)
-{
- setResult(status, reason, content);
- httpCompleted();
-}
-
-void LLCurl::Responder::setResult(S32 status, const std::string& reason, const LLSD& content /* = LLSD() */)
-{
- mStatus = status;
- mReason = reason;
- mContent = content;
-}
-
-#endif
diff --git a/indra/llmessage/tests/lldatapacker_test.cpp b/indra/llmessage/tests/lldatapacker_test.cpp
new file mode 100644
index 0000000000..e4253ab140
--- /dev/null
+++ b/indra/llmessage/tests/lldatapacker_test.cpp
@@ -0,0 +1,572 @@
+/**
+ * @file lldatapacker_tut.cpp
+ * @author Adroit
+ * @date 2007-02
+ * @brief LLDataPacker test cases.
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "lltut.h"
+
+#include "lldatapacker.h"
+#include "v4color.h"
+#include "v4coloru.h"
+#include "v2math.h"
+#include "v3math.h"
+#include "v4math.h"
+#include "llsdserialize.h"
+
+#define TEST_FILE_NAME "datapacker_test.txt"
+
+namespace tut
+{
+ struct datapacker_test
+ {
+ };
+ typedef test_group<datapacker_test> datapacker_test_t;
+ typedef datapacker_test_t::object datapacker_test_object_t;
+ tut::datapacker_test_t tut_datapacker_test("datapacker_test");
+
+ //*********LLDataPackerBinaryBuffer
+ template<> template<>
+ void datapacker_test_object_t::test<1>()
+ {
+ U8 packbuf[128];
+ F32 f_val1 = 44.44f, f_unpkval1;
+ F32 f_val2 = 12344.443232f, f_unpkval2;
+ F32 f_val3 = 44.4456789f, f_unpkval3;
+ LLDataPackerBinaryBuffer lldp(packbuf,128);
+ lldp.packFixed( f_val1, "linden_lab", FALSE, 8, 8);
+ lldp.packFixed( f_val2, "linden_lab", FALSE, 14, 16);
+ lldp.packFixed( f_val3, "linden_lab", FALSE, 8, 23);
+
+ LLDataPackerBinaryBuffer lldp1(packbuf, lldp.getCurrentSize());
+ lldp1.unpackFixed(f_unpkval1, "linden_lab", FALSE, 8, 8);
+ lldp1.unpackFixed(f_unpkval2, "linden_lab", FALSE, 14, 16);
+ lldp1.unpackFixed(f_unpkval3, "linden_lab", FALSE, 8, 23);
+ ensure_approximately_equals("LLDataPackerBinaryBuffer::packFixed 8 failed", f_val1, f_unpkval1, 8);
+ ensure_approximately_equals("LLDataPackerBinaryBuffer::packFixed 16 failed", f_val2, f_unpkval2, 16);
+ ensure_approximately_equals("LLDataPackerBinaryBuffer::packFixed 23 failed", f_val3, f_unpkval3, 31);
+ }
+
+ template<> template<>
+ void datapacker_test_object_t::test<2>()
+ {
+ U8 packbuf[1024];
+
+ char str[] = "SecondLife is virtual World\0";
+ char strBinary[] = "SecondLife is virtual World";
+ char strBinaryFixed[] = "Fixed Data";
+ S32 sizeBinaryFixed = sizeof(strBinaryFixed);
+ U8 valU8 = 'C';
+ U16 valU16 = 0xFFFF;
+ U32 valU32 = 0xFFFFFFFF;
+ S32 valS32 = -94967295;
+ F32 valF32 = 4354355.44f ;
+ LLColor4 llcol4(3.3f, 0, 4.4f, 5.5f);
+ LLColor4U llcol4u(3, 128, 24, 33);
+ LLVector2 llvec2(333.33f, 444.44f);
+ LLVector3 llvec3(333.33f, 444.44f, 555.55f);
+ LLVector4 llvec4(333.33f, 444.44f, 555.55f, 666.66f);
+ LLUUID uuid;
+
+ std::string unpkstr;
+ char unpkstrBinary[256];
+ char unpkstrBinaryFixed[256];
+ S32 unpksizeBinary;
+ U8 unpkvalU8;
+ U16 unpkvalU16;
+ U32 unpkvalU32;
+ S32 unpkvalS32;
+ F32 unpkvalF32;
+ LLColor4 unpkllcol4;
+ LLColor4U unpkllcol4u;
+ LLVector2 unpkllvec2;
+ LLVector3 unpkllvec3;
+ LLVector4 unpkllvec4;
+ LLUUID unpkuuid;
+
+ LLDataPackerBinaryBuffer lldp(packbuf,1024);
+ lldp.packString(str , "linden_lab_str");
+ lldp.packBinaryData((U8*)strBinary, sizeof(strBinary), "linden_lab_bd");
+ lldp.packBinaryDataFixed((U8*)strBinaryFixed, sizeBinaryFixed, "linden_lab_bdf");
+ lldp.packU8(valU8,"linden_lab_u8");
+ lldp.packU16(valU16,"linden_lab_u16");
+ lldp.packU32(valU32, "linden_lab_u32");
+ lldp.packS32(valS32, "linden_lab_s32");
+ lldp.packF32(valF32, "linden_lab_f32");
+ lldp.packColor4(llcol4, "linden_lab_col4");
+ lldp.packColor4U(llcol4u, "linden_lab_col4u");
+ lldp.packVector2(llvec2, "linden_lab_vec2");
+ lldp.packVector3(llvec3, "linden_lab_vec3");
+ lldp.packVector4(llvec4, "linden_lab_vec4");
+ uuid.generate();
+ lldp.packUUID(uuid, "linden_lab_uuid");
+
+ S32 cur_size = lldp.getCurrentSize();
+
+ LLDataPackerBinaryBuffer lldp1(packbuf, cur_size);
+ lldp1.unpackString(unpkstr , "linden_lab_str");
+ lldp1.unpackBinaryData((U8*)unpkstrBinary, 256, unpksizeBinary, "linden_lab_bd");
+ lldp1.unpackBinaryDataFixed((U8*)unpkstrBinaryFixed, sizeBinaryFixed, "linden_lab_bdf");
+ lldp1.unpackU8(unpkvalU8,"linden_lab_u8");
+ lldp1.unpackU16(unpkvalU16,"linden_lab_u16");
+ lldp1.unpackU32(unpkvalU32, "linden_lab_u32");
+ lldp1.unpackS32(unpkvalS32, "linden_lab_s32");
+ lldp1.unpackF32(unpkvalF32, "linden_lab_f32");
+ lldp1.unpackColor4(unpkllcol4, "linden_lab_col4");
+ lldp1.unpackColor4U(unpkllcol4u, "linden_lab_col4u");
+ lldp1.unpackVector2(unpkllvec2, "linden_lab_vec2");
+ lldp1.unpackVector3(unpkllvec3, "linden_lab_vec3");
+ lldp1.unpackVector4(unpkllvec4, "linden_lab_vec4");
+ lldp1.unpackUUID(unpkuuid, "linden_lab_uuid");
+
+ ensure("LLDataPackerBinaryBuffer::packString failed", strcmp(str, unpkstr.c_str()) == 0);
+ ensure("LLDataPackerBinaryBuffer::packBinaryData failed", strcmp(strBinary, unpkstrBinary) == 0);
+ ensure("LLDataPackerBinaryBuffer::packBinaryDataFixed failed", strcmp(strBinaryFixed, unpkstrBinaryFixed) == 0);
+ ensure_equals("LLDataPackerBinaryBuffer::packU8 failed", valU8, unpkvalU8);
+ ensure_equals("LLDataPackerBinaryBuffer::packU16 failed", valU16, unpkvalU16);
+ ensure_equals("LLDataPackerBinaryBuffer::packU32 failed", valU32, unpkvalU32);
+ ensure_equals("LLDataPackerBinaryBuffer::packS32 failed", valS32, unpkvalS32);
+ ensure("LLDataPackerBinaryBuffer::packF32 failed", is_approx_equal(valF32, unpkvalF32));
+ ensure_equals("LLDataPackerBinaryBuffer::packColor4 failed", llcol4, unpkllcol4);
+ ensure_equals("LLDataPackerBinaryBuffer::packColor4U failed", llcol4u, unpkllcol4u);
+ ensure_equals("LLDataPackerBinaryBuffer::packVector2 failed", llvec2, unpkllvec2);
+ ensure_equals("LLDataPackerBinaryBuffer::packVector3 failed", llvec3, unpkllvec3);
+ ensure_equals("LLDataPackerBinaryBuffer::packVector4 failed", llvec4, unpkllvec4);
+ ensure_equals("LLDataPackerBinaryBuffer::packUUID failed", uuid, unpkuuid);
+ }
+
+ template<> template<>
+ void datapacker_test_object_t::test<3>()
+ {
+ U8 packbuf[128];
+ char str[] = "SecondLife is virtual World";
+ S32 strSize = sizeof(str); // include '\0'
+ LLDataPackerBinaryBuffer lldp(packbuf, 128);
+ lldp.packString(str , "linden_lab");
+
+ ensure("LLDataPackerBinaryBuffer: current size is wrong", strSize == lldp.getCurrentSize());
+ ensure("LLDataPackerBinaryBuffer: buffer size is wrong", 128 == lldp.getBufferSize());
+
+ lldp.reset();
+ ensure("LLDataPackerBinaryBuffer::reset failed",0 == lldp.getCurrentSize());
+ }
+
+ template<> template<>
+ void datapacker_test_object_t::test<4>()
+ {
+ U8* packbuf = new U8[128];
+ char str[] = "SecondLife is virtual World";
+ LLDataPackerBinaryBuffer lldp(packbuf, 128);
+ lldp.packString(str , "linden_lab");
+ lldp.freeBuffer();
+ ensure("LLDataPackerBinaryBuffer.freeBuffer failed" , 0 == lldp.getBufferSize());
+
+ }
+
+ template<> template<>
+ void datapacker_test_object_t::test<5>()
+ {
+ U8* buf = new U8[]("SecondLife is virtual World");
+ S32 size = sizeof(buf);
+ LLDataPackerBinaryBuffer lldp(buf, size);
+ U8* new_buf = new U8[]("Its Amazing");
+ size = sizeof(new_buf)-1;
+ lldp.assignBuffer(new_buf, size);
+ ensure("LLDataPackerBinaryBuffer::assignBuffer failed" , ((lldp.getBufferSize() == size) && (0 == lldp.getCurrentSize()))) ;
+ }
+
+ template<> template<>
+ void datapacker_test_object_t::test<6>()
+ {
+ U8 packbuf[128];
+ char str[] = "SecondLife is virtual World";
+ LLDataPackerBinaryBuffer lldp(packbuf, 128);
+ lldp.packString(str , "linden_lab");
+ U8 new_buffer[128];
+ std::string unpkbuf;
+ LLDataPackerBinaryBuffer lldp1(new_buffer,128);
+ lldp1 = lldp;
+ lldp1.unpackString(unpkbuf, "linden_lab");
+ ensure("1. LLDataPackerBinaryBuffer::operator= failed" , lldp1.getBufferSize() == lldp.getBufferSize());
+ ensure_equals("2.LLDataPackerBinaryBuffer::operator= failed", str,unpkbuf);
+ }
+
+ //*********LLDataPackerAsciiBuffer
+
+ template<> template<>
+ void datapacker_test_object_t::test<7>()
+ {
+ char packbuf[128];
+ F32 f_val = 44.44f, f_unpkval;
+ LLDataPackerAsciiBuffer lldp(packbuf,128);
+ lldp.packFixed( f_val, "linden_lab", FALSE, 8, 8);
+
+ LLDataPackerAsciiBuffer lldp1(packbuf, lldp.getCurrentSize());
+ lldp1.unpackFixed(f_unpkval, "linden_lab", FALSE, 8, 8);
+ ensure_approximately_equals("LLDataPackerAsciiBuffer::packFixed failed", f_val, f_unpkval, 8);
+ }
+
+ template<> template<>
+ void datapacker_test_object_t::test<8>()
+ {
+ char packbuf[1024];
+
+ char str[] = "SecondLife is virtual World\0";
+ char strBinary[] = "SecondLife is virtual World";
+ char strBinaryFixed[] = "Fixed Data";
+ S32 sizeBinaryFixed = sizeof(strBinaryFixed);
+ U8 valU8 = 'C';
+ U16 valU16 = 0xFFFF;
+ U32 valU32 = 0xFFFFFFFF;
+ S32 valS32 = -94967295;
+ F32 valF32 = 4354355.44f ;
+ LLColor4 llcol4(3.3f, 0, 4.4f, 5.5f);
+ LLColor4U llcol4u(3, 128, 24, 33);
+ LLVector2 llvec2(333.33f, 444.44f);
+ LLVector3 llvec3(333.33f, 444.44f, 555.55f);
+ LLVector4 llvec4(4354355.44f, 444.44f, 555.55f, 666.66f);
+ LLUUID uuid;
+
+ std::string unpkstr;
+ char unpkstrBinary[256];
+ char unpkstrBinaryFixed[256];
+ S32 unpksizeBinary;
+ U8 unpkvalU8;
+ U16 unpkvalU16;
+ U32 unpkvalU32;
+ S32 unpkvalS32;
+ F32 unpkvalF32;
+ LLColor4 unpkllcol4;
+ LLColor4U unpkllcol4u;
+ LLVector2 unpkllvec2;
+ LLVector3 unpkllvec3;
+ LLVector4 unpkllvec4;
+ LLUUID unpkuuid;
+
+ LLDataPackerAsciiBuffer lldp(packbuf,1024);
+ lldp.packString(str , "linden_lab_str");
+ lldp.packBinaryData((U8*)strBinary, sizeof(strBinary), "linden_lab_bd");
+ lldp.packBinaryDataFixed((U8*)strBinaryFixed, sizeBinaryFixed, "linden_lab_bdf");
+ lldp.packU8(valU8,"linden_lab_u8");
+ lldp.packU16(valU16,"linden_lab_u16");
+ lldp.packU32(valU32, "linden_lab_u32");
+ lldp.packS32(valS32, "linden_lab_s32");
+ lldp.packF32(valF32, "linden_lab_f32");
+ lldp.packColor4(llcol4, "linden_lab_col4");
+ lldp.packColor4U(llcol4u, "linden_lab_col4u");
+ lldp.packVector2(llvec2, "linden_lab_vec2");
+ lldp.packVector3(llvec3, "linden_lab_vec3");
+ lldp.packVector4(llvec4, "linden_lab_vec4");
+ uuid.generate();
+ lldp.packUUID(uuid, "linden_lab_uuid");
+
+ S32 cur_size = lldp.getCurrentSize();
+
+ LLDataPackerAsciiBuffer lldp1(packbuf, cur_size);
+ lldp1.unpackString(unpkstr , "linden_lab_str");
+ lldp1.unpackBinaryData((U8*)unpkstrBinary, 256, unpksizeBinary, "linden_lab_bd");
+ lldp1.unpackBinaryDataFixed((U8*)unpkstrBinaryFixed, sizeBinaryFixed, "linden_lab_bdf");
+ lldp1.unpackU8(unpkvalU8,"linden_lab_u8");
+ lldp1.unpackU16(unpkvalU16,"linden_lab_u16");
+ lldp1.unpackU32(unpkvalU32, "linden_lab_u32");
+ lldp1.unpackS32(unpkvalS32, "linden_lab_s32");
+ lldp1.unpackF32(unpkvalF32, "linden_lab_f32");
+ lldp1.unpackColor4(unpkllcol4, "linden_lab_col4");
+ lldp1.unpackColor4U(unpkllcol4u, "linden_lab_col4u");
+ lldp1.unpackVector2(unpkllvec2, "linden_lab_vec2");
+ lldp1.unpackVector3(unpkllvec3, "linden_lab_vec3");
+ lldp1.unpackVector4(unpkllvec4, "linden_lab_vec4");
+ lldp1.unpackUUID(unpkuuid, "linden_lab_uuid");
+
+ ensure("LLDataPackerAsciiBuffer::packString failed", strcmp(str, unpkstr.c_str()) == 0);
+ ensure("LLDataPackerAsciiBuffer::packBinaryData failed", strcmp(strBinary, unpkstrBinary) == 0);
+ ensure("LLDataPackerAsciiBuffer::packBinaryDataFixed failed", strcmp(strBinaryFixed, unpkstrBinaryFixed) == 0);
+ ensure_equals("LLDataPackerAsciiBuffer::packU8 failed", valU8, unpkvalU8);
+ ensure_equals("LLDataPackerAsciiBuffer::packU16 failed", valU16, unpkvalU16);
+ ensure_equals("LLDataPackerAsciiBuffer::packU32 failed", valU32, unpkvalU32);
+ ensure_equals("LLDataPackerAsciiBuffer::packS32 failed", valS32, unpkvalS32);
+ ensure("LLDataPackerAsciiBuffer::packF32 failed", is_approx_equal(valF32, unpkvalF32));
+ ensure_equals("LLDataPackerAsciiBuffer::packColor4 failed", llcol4, unpkllcol4);
+ ensure_equals("LLDataPackerAsciiBuffer::packColor4U failed", llcol4u, unpkllcol4u);
+ ensure_equals("LLDataPackerAsciiBuffer::packVector2 failed", llvec2, unpkllvec2);
+ ensure_equals("LLDataPackerAsciiBuffer::packVector3 failed", llvec3, unpkllvec3);
+ ensure_equals("LLDataPackerAsciiBuffer::packVector4 failed", llvec4, unpkllvec4);
+ ensure_equals("LLDataPackerAsciiBuffer::packUUID failed", uuid, unpkuuid);
+ }
+
+ template<> template<>
+ void datapacker_test_object_t::test<9>()
+ {
+ char* packbuf = new char[128];
+ char str[] = "SecondLife is virtual World";
+ LLDataPackerAsciiBuffer lldp(packbuf, 128);
+ lldp.packString(str , "linden_lab");
+ lldp.freeBuffer();
+ ensure("LLDataPackerAsciiBuffer::freeBuffer failed" , 0 == lldp.getBufferSize());
+ }
+
+ template<> template<>
+ void datapacker_test_object_t::test<10>()
+ {
+ char buf[] = "SecondLife is virtual World";
+ S32 size = sizeof(buf);
+ LLDataPackerAsciiBuffer lldp(buf, size);
+ char new_buf[] = "Its Amazing";
+ size = sizeof(new_buf);
+ lldp.assignBuffer(new_buf, size);
+ ensure("LLDataPackerAsciiBuffer::assignBuffer failed" , ((lldp.getBufferSize() == size) && (1 == lldp.getCurrentSize()))) ;
+ }
+
+ //*********LLDataPackerAsciiFile
+
+ template<> template<>
+ void datapacker_test_object_t::test<11>()
+ {
+ F32 f_val = 44.44f, f_unpkval;
+
+ LLFILE* fp = LLFile::fopen(TEST_FILE_NAME, LLFILE_MODE("w+"));
+ if(!fp)
+ {
+ LL_ERRS() << "File couldnt be open" << LL_ENDL;
+ return;
+ }
+
+ LLDataPackerAsciiFile lldp(fp,2);
+ lldp.packFixed( f_val, "linden_lab", FALSE, 8, 8);
+
+ fflush(fp);
+ fseek(fp,0,SEEK_SET);
+ LLDataPackerAsciiFile lldp1(fp,2);
+
+ lldp1.unpackFixed(f_unpkval, "linden_lab", FALSE, 8, 8);
+ fclose(fp);
+
+ ensure_approximately_equals("LLDataPackerAsciiFile::packFixed failed", f_val, f_unpkval, 8);
+ }
+
+ template<> template<>
+ void datapacker_test_object_t::test<12>()
+ {
+ char str[] = "SecondLife is virtual World\0";
+ char strBinary[] = "SecondLife is virtual World";
+ char strBinaryFixed[] = "Fixed Data";
+ S32 sizeBinaryFixed = sizeof(strBinaryFixed);
+ U8 valU8 = 'C';
+ U16 valU16 = 0xFFFF;
+ U32 valU32 = 0xFFFFFFFF;
+ S32 valS32 = -94967295;
+ F32 valF32 = 4354355.44f ;
+ LLColor4 llcol4(3.3f, 0, 4.4f, 5.5f);
+ LLColor4U llcol4u(3, 128, 24, 33);
+ LLVector2 llvec2(333.33f, 444.44f);
+ LLVector3 llvec3(333.33f, 444.44f, 555.55f);
+ LLVector4 llvec4(333.33f, 444.44f, 555.55f, 666.66f);
+ LLUUID uuid;
+
+ std::string unpkstr;
+ char unpkstrBinary[256];
+ char unpkstrBinaryFixed[256];
+ S32 unpksizeBinary;
+ U8 unpkvalU8;
+ U16 unpkvalU16;
+ U32 unpkvalU32;
+ S32 unpkvalS32;
+ F32 unpkvalF32;
+ LLColor4 unpkllcol4;
+ LLColor4U unpkllcol4u;
+ LLVector2 unpkllvec2;
+ LLVector3 unpkllvec3;
+ LLVector4 unpkllvec4;
+ LLUUID unpkuuid;
+
+ LLFILE* fp = LLFile::fopen(TEST_FILE_NAME, LLFILE_MODE("w+"));
+ if(!fp)
+ {
+ LL_ERRS() << "File couldnt be open" << LL_ENDL;
+ return;
+ }
+
+ LLDataPackerAsciiFile lldp(fp,2);
+
+ lldp.packString(str , "linden_lab_str");
+ lldp.packBinaryData((U8*)strBinary, sizeof(strBinary), "linden_lab_bd");
+ lldp.packBinaryDataFixed((U8*)strBinaryFixed, sizeBinaryFixed, "linden_lab_bdf");
+ lldp.packU8(valU8,"linden_lab_u8");
+ lldp.packU16(valU16,"linden_lab_u16");
+ lldp.packU32(valU32, "linden_lab_u32");
+ lldp.packS32(valS32, "linden_lab_s32");
+ lldp.packF32(valF32, "linden_lab_f32");
+ lldp.packColor4(llcol4, "linden_lab_col4");
+ lldp.packColor4U(llcol4u, "linden_lab_col4u");
+ lldp.packVector2(llvec2, "linden_lab_vec2");
+ lldp.packVector3(llvec3, "linden_lab_vec3");
+ lldp.packVector4(llvec4, "linden_lab_vec4");
+ uuid.generate();
+ lldp.packUUID(uuid, "linden_lab_uuid");
+
+ fflush(fp);
+ fseek(fp,0,SEEK_SET);
+ LLDataPackerAsciiFile lldp1(fp,2);
+
+ lldp1.unpackString(unpkstr , "linden_lab_str");
+ lldp1.unpackBinaryData((U8*)unpkstrBinary, 256, unpksizeBinary, "linden_lab_bd");
+ lldp1.unpackBinaryDataFixed((U8*)unpkstrBinaryFixed, sizeBinaryFixed, "linden_lab_bdf");
+ lldp1.unpackU8(unpkvalU8,"linden_lab_u8");
+ lldp1.unpackU16(unpkvalU16,"linden_lab_u16");
+ lldp1.unpackU32(unpkvalU32, "linden_lab_u32");
+ lldp1.unpackS32(unpkvalS32, "linden_lab_s32");
+ lldp1.unpackF32(unpkvalF32, "linden_lab_f32");
+ lldp1.unpackColor4(unpkllcol4, "linden_lab_col4");
+ lldp1.unpackColor4U(unpkllcol4u, "linden_lab_col4u");
+ lldp1.unpackVector2(unpkllvec2, "linden_lab_vec2");
+ lldp1.unpackVector3(unpkllvec3, "linden_lab_vec3");
+ lldp1.unpackVector4(unpkllvec4, "linden_lab_vec4");
+ lldp1.unpackUUID(unpkuuid, "linden_lab_uuid");
+
+ fclose(fp);
+
+ ensure("LLDataPackerAsciiFile::packString failed", strcmp(str, unpkstr.c_str()) == 0);
+ ensure("LLDataPackerAsciiFile::packBinaryData failed", strcmp(strBinary, unpkstrBinary) == 0);
+ ensure("LLDataPackerAsciiFile::packBinaryDataFixed failed", strcmp(strBinaryFixed, unpkstrBinaryFixed) == 0);
+ ensure_equals("LLDataPackerAsciiFile::packU8 failed", valU8, unpkvalU8);
+ ensure_equals("LLDataPackerAsciiFile::packU16 failed", valU16, unpkvalU16);
+ ensure_equals("LLDataPackerAsciiFile::packU32 failed", valU32, unpkvalU32);
+ ensure_equals("LLDataPackerAsciiFile::packS32 failed", valS32, unpkvalS32);
+ ensure("LLDataPackerAsciiFile::packF32 failed", is_approx_equal(valF32, unpkvalF32));
+ ensure_equals("LLDataPackerAsciiFile::packColor4 failed", llcol4, unpkllcol4);
+ ensure_equals("LLDataPackerAsciiFile::packColor4U failed", llcol4u, unpkllcol4u);
+ ensure_equals("LLDataPackerAsciiFile::packVector2 failed", llvec2, unpkllvec2);
+ ensure_equals("LLDataPackerAsciiFile::packVector3 failed", llvec3, unpkllvec3);
+ ensure_equals("LLDataPackerAsciiFile::packVector4 failed", llvec4, unpkllvec4);
+ ensure_equals("LLDataPackerAsciiFile::packUUID failed", uuid, unpkuuid);
+ }
+
+ template<> template<>
+ void datapacker_test_object_t::test<13>()
+ {
+ F32 f_val = 44.44f, f_unpkval;
+
+ std::ostringstream ostr;
+ LLDataPackerAsciiFile lldp(ostr,2);
+ lldp.packFixed( f_val, "linden_lab", FALSE, 8, 8);
+
+ std::istringstream istr(ostr.str());
+ LLDataPackerAsciiFile lldp1(istr,2);
+
+ lldp1.unpackFixed(f_unpkval, "linden_lab", FALSE, 8, 8);
+
+ ensure_approximately_equals("LLDataPackerAsciiFile::packFixed (iostring) failed", f_val, f_unpkval, 8);
+ }
+
+ template<> template<>
+ void datapacker_test_object_t::test<14>()
+ {
+ char str[] = "SecondLife is virtual World\0";
+ char strBinary[] = "SecondLife is virtual World";
+ char strBinaryFixed[] = "Fixed Data";
+ S32 sizeBinaryFixed = sizeof(strBinaryFixed);
+ U8 valU8 = 'C';
+ U16 valU16 = 0xFFFF;
+ U32 valU32 = 0xFFFFFFFF;
+ S32 valS32 = -94967295;
+ F32 valF32 = 4354355.44f ;
+ LLColor4 llcol4(3.3f, 0, 4.4f, 5.5f);
+ LLColor4U llcol4u(3, 128, 24, 33);
+ LLVector2 llvec2(3333333.33f, 444.333344f);
+ LLVector3 llvec3(3323233.33f, 444.4324f, 555.553232f);
+ LLVector4 llvec4(333.33233f, 444.4323234f, 55323225.55f, 6323236.66f);
+ LLUUID uuid;
+
+ std::string unpkstr;
+ char unpkstrBinary[256];
+ char unpkstrBinaryFixed[256];
+ S32 unpksizeBinary;
+ U8 unpkvalU8;
+ U16 unpkvalU16;
+ U32 unpkvalU32;
+ S32 unpkvalS32;
+ F32 unpkvalF32;
+ LLColor4 unpkllcol4;
+ LLColor4U unpkllcol4u;
+ LLVector2 unpkllvec2;
+ LLVector3 unpkllvec3;
+ LLVector4 unpkllvec4;
+ LLUUID unpkuuid;
+
+ std::ostringstream ostr;
+ LLDataPackerAsciiFile lldp(ostr,2);
+
+ lldp.packString(str , "linden_lab_str");
+ lldp.packBinaryData((U8*)strBinary, sizeof(strBinary), "linden_lab_bd");
+ lldp.packBinaryDataFixed((U8*)strBinaryFixed, sizeBinaryFixed, "linden_lab_bdf");
+ lldp.packU8(valU8,"linden_lab_u8");
+ lldp.packU16(valU16,"linden_lab_u16");
+ lldp.packU32(valU32, "linden_lab_u32");
+ lldp.packS32(valS32, "linden_lab_s32");
+ lldp.packF32(valF32, "linden_lab_f32");
+ lldp.packColor4(llcol4, "linden_lab_col4");
+ lldp.packColor4U(llcol4u, "linden_lab_col4u");
+ lldp.packVector2(llvec2, "linden_lab_vec2");
+ lldp.packVector3(llvec3, "linden_lab_vec3");
+ lldp.packVector4(llvec4, "linden_lab_vec4");
+ uuid.generate();
+ lldp.packUUID(uuid, "linden_lab_uuid");
+
+ std::istringstream istr(ostr.str());
+ LLDataPackerAsciiFile lldp1(istr,2);
+
+ lldp1.unpackString(unpkstr , "linden_lab_str");
+ lldp1.unpackBinaryData((U8*)unpkstrBinary, 256, unpksizeBinary, "linden_lab_bd");
+ lldp1.unpackBinaryDataFixed((U8*)unpkstrBinaryFixed, sizeBinaryFixed, "linden_lab_bdf");
+ lldp1.unpackU8(unpkvalU8,"linden_lab_u8");
+ lldp1.unpackU16(unpkvalU16,"linden_lab_u16");
+ lldp1.unpackU32(unpkvalU32, "linden_lab_u32");
+ lldp1.unpackS32(unpkvalS32, "linden_lab_s32");
+ lldp1.unpackF32(unpkvalF32, "linden_lab_f32");
+ lldp1.unpackColor4(unpkllcol4, "linden_lab_col4");
+ lldp1.unpackColor4U(unpkllcol4u, "linden_lab_col4u");
+ lldp1.unpackVector2(unpkllvec2, "linden_lab_vec2");
+ lldp1.unpackVector3(unpkllvec3, "linden_lab_vec3");
+ lldp1.unpackVector4(unpkllvec4, "linden_lab_vec4");
+ lldp1.unpackUUID(unpkuuid, "linden_lab_uuid");
+
+ ensure("LLDataPackerAsciiFile::packString (iostring) failed", strcmp(str, unpkstr.c_str()) == 0);
+ ensure("LLDataPackerAsciiFile::packBinaryData (iostring) failed", strcmp(strBinary, unpkstrBinary) == 0);
+ ensure("LLDataPackerAsciiFile::packBinaryDataFixed (iostring) failed", strcmp(strBinaryFixed, unpkstrBinaryFixed) == 0);
+ ensure_equals("LLDataPackerAsciiFile::packU8 (iostring) failed", valU8, unpkvalU8);
+ ensure_equals("LLDataPackerAsciiFile::packU16 (iostring) failed", valU16, unpkvalU16);
+ ensure_equals("LLDataPackerAsciiFile::packU32 (iostring) failed", valU32, unpkvalU32);
+ ensure_equals("LLDataPackerAsciiFile::packS32 (iostring) failed", valS32, unpkvalS32);
+ ensure("LLDataPackerAsciiFile::packF32 (iostring) failed", is_approx_equal(valF32, unpkvalF32));
+ ensure_equals("LLDataPackerAsciiFile::packColor4 (iostring) failed", llcol4, unpkllcol4);
+ ensure_equals("LLDataPackerAsciiFile::packColor4U (iostring) failed", llcol4u, unpkllcol4u);
+ ensure_equals("LLDataPackerAsciiFile::packVector2 (iostring) failed", llvec2, unpkllvec2);
+ ensure_equals("LLDataPackerAsciiFile::packVector3 (iostring) failed", llvec3, unpkllvec3);
+ ensure_equals("LLDataPackerAsciiFile::packVector4 (iostring) failed", llvec4, unpkllvec4);
+ ensure_equals("LLDataPackerAsciiFile::packUUID (iostring) failed", uuid, unpkuuid);
+ }
+}
diff --git a/indra/llmessage/tests/llhttpclient_test.cpp b/indra/llmessage/tests/llhttpclient_test.cpp
deleted file mode 100644
index 1881144d3e..0000000000
--- a/indra/llmessage/tests/llhttpclient_test.cpp
+++ /dev/null
@@ -1,311 +0,0 @@
-/**
- * @file llhttpclient_test.cpp
- * @brief Testing the HTTP client classes.
- *
- * $LicenseInfo:firstyear=2006&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-/**
- *
- * These classes test the HTTP client framework.
- *
- */
-
-#include <tut/tut.hpp>
-#include "linden_common.h"
-
-#include "lltut.h"
-#include "llhttpclient.h"
-#include "llformat.h"
-#include "llpipeutil.h"
-#include "llproxy.h"
-#include "llpumpio.h"
-
-#include "lliosocket.h"
-#include "llstring.h"
-#include "stringize.h"
-#include "llcleanup.h"
-
-namespace tut
-{
- struct HTTPClientTestData
- {
- public:
- HTTPClientTestData():
- PORT(LLStringUtil::getenv("PORT")),
- // Turning NULL PORT into empty string doesn't make things work;
- // that's just to keep this initializer from blowing up. We test
- // PORT separately in the constructor body.
- local_server(STRINGIZE("http://127.0.0.1:" << PORT << "/"))
- {
- ensure("Set environment variable PORT to local test server port", !PORT.empty());
- apr_pool_create(&mPool, NULL);
- LLCurl::initClass(false);
- mClientPump = new LLPumpIO(mPool);
-
- LLHTTPClient::setPump(*mClientPump);
- }
-
- ~HTTPClientTestData()
- {
- delete mClientPump;
- SUBSYSTEM_CLEANUP(LLProxy);
- apr_pool_destroy(mPool);
- }
-
- void runThePump(float timeout = 100.0f)
- {
- LLTimer timer;
- timer.setTimerExpirySec(timeout);
-
- while(!mSawCompleted && !mSawCompletedHeader && !timer.hasExpired())
- {
- LLFrameTimer::updateFrameTime();
- if (mClientPump)
- {
- mClientPump->pump();
- mClientPump->callback();
- }
- }
- }
-
- const std::string PORT;
- const std::string local_server;
-
- private:
- apr_pool_t* mPool;
- LLPumpIO* mClientPump;
-
- protected:
- void ensureStatusOK()
- {
- if (mSawError)
- {
- std::string msg =
- llformat("httpFailure() called when not expected, status %d",
- mStatus);
- fail(msg);
- }
- }
-
- void ensureStatusError()
- {
- if (!mSawError)
- {
- fail("httpFailure() wasn't called");
- }
- }
-
- LLSD getResult()
- {
- return mResult;
- }
- LLSD getHeader()
- {
- return mHeader;
- }
-
- protected:
- bool mSawError;
- U32 mStatus;
- std::string mReason;
- bool mSawCompleted;
- bool mSawCompletedHeader;
- LLSD mResult;
- LLSD mHeader;
- bool mResultDeleted;
-
- class Result : public LLHTTPClient::Responder
- {
- protected:
- Result(HTTPClientTestData& client)
- : mClient(client)
- {
- }
-
- public:
- static Result* build(HTTPClientTestData& client)
- {
- return new Result(client);
- }
-
- ~Result()
- {
- mClient.mResultDeleted = true;
- }
-
- protected:
- virtual void httpFailure()
- {
- mClient.mSawError = true;
- mClient.mStatus = getStatus();
- mClient.mReason = getReason();
- }
-
- virtual void httpSuccess()
- {
- mClient.mResult = getContent();
- }
-
- virtual void httpCompleted()
- {
- LLHTTPClient::Responder::httpCompleted();
-
- mClient.mSawCompleted = true;
- mClient.mSawCompletedHeader = true;
- mClient.mHeader = getResponseHeaders();
- }
-
- private:
- HTTPClientTestData& mClient;
- };
-
- friend class Result;
-
- protected:
- LLHTTPClient::ResponderPtr newResult()
- {
- mSawError = false;
- mStatus = 0;
- mSawCompleted = false;
- mSawCompletedHeader = false;
- mResult.clear();
- mHeader.clear();
- mResultDeleted = false;
-
- return Result::build(*this);
- }
- };
-
-
- typedef test_group<HTTPClientTestData> HTTPClientTestGroup;
- typedef HTTPClientTestGroup::object HTTPClientTestObject;
- HTTPClientTestGroup httpClientTestGroup("http_client");
-
- template<> template<>
- void HTTPClientTestObject::test<1>()
- {
- LLHTTPClient::get(local_server, newResult());
- runThePump();
- ensureStatusOK();
- ensure("result object wasn't destroyed", mResultDeleted);
- }
-
- template<> template<>
- void HTTPClientTestObject::test<2>()
- {
- // Please nobody listen on this particular port...
- LLHTTPClient::get("http://127.0.0.1:7950", newResult());
- runThePump();
- ensureStatusError();
- }
-
- template<> template<>
- void HTTPClientTestObject::test<3>()
- {
- LLSD sd;
-
- sd["list"][0]["one"] = 1;
- sd["list"][0]["two"] = 2;
- sd["list"][1]["three"] = 3;
- sd["list"][1]["four"] = 4;
-
- LLHTTPClient::post(local_server + "web/echo", sd, newResult());
- runThePump();
- ensureStatusOK();
- ensure_equals("echoed result matches", getResult(), sd);
- }
-
- template<> template<>
- void HTTPClientTestObject::test<4>()
- {
- LLSD sd;
-
- sd["message"] = "This is my test message.";
-
- LLHTTPClient::put(local_server + "test/storage", sd, newResult());
- runThePump();
- ensureStatusOK();
-
- LLHTTPClient::get(local_server + "test/storage", newResult());
- runThePump();
- ensureStatusOK();
- ensure_equals("echoed result matches", getResult(), sd);
-
- }
-
- template<> template<>
- void HTTPClientTestObject::test<5>()
- {
- LLSD sd;
- sd["status"] = 543;
- sd["reason"] = "error for testing";
-
- LLHTTPClient::post(local_server + "test/error", sd, newResult());
- runThePump();
- ensureStatusError();
- ensure_contains("reason", mReason, sd["reason"]);
- }
-
- template<> template<>
- void HTTPClientTestObject::test<6>()
- {
- const F32 timeout = 1.0f;
- LLHTTPClient::get(local_server + "test/timeout", newResult(), LLSD(), timeout);
- runThePump(timeout * 5.0f);
- ensureStatusError();
- ensure_equals("reason", mReason, "STATUS_EXPIRED");
- }
-
- template<> template<>
- void HTTPClientTestObject::test<7>()
- {
- LLHTTPClient::get(local_server, newResult());
- runThePump();
- ensureStatusOK();
- LLSD expected = getResult();
-
- LLSD result;
- result = LLHTTPClient::blockingGet(local_server);
- LLSD body = result["body"];
- ensure_equals("echoed result matches", body.size(), expected.size());
- }
- template<> template<>
- void HTTPClientTestObject::test<8>()
- {
- // This is testing for the presence of the Header in the returned results
- // from an HTTP::get call.
- LLHTTPClient::get(local_server, newResult());
- runThePump();
- ensureStatusOK();
- LLSD header = getHeader();
- ensure("got a header", ! header.emptyMap().asBoolean());
- }
- template<> template<>
- void HTTPClientTestObject::test<9>()
- {
- LLHTTPClient::head(local_server, newResult());
- runThePump();
- ensureStatusOK();
- ensure("result object wasn't destroyed", mResultDeleted);
- }
-}
diff --git a/indra/llmessage/tests/llhttpnode_test.cpp b/indra/llmessage/tests/llhttpnode_test.cpp
new file mode 100644
index 0000000000..c38dee120b
--- /dev/null
+++ b/indra/llmessage/tests/llhttpnode_test.cpp
@@ -0,0 +1,428 @@
+/**
+ * @file lliohttpnode_tut.cpp
+ * @date May 2006
+ * @brief HTTP server unit tests
+ *
+ * $LicenseInfo:firstyear=2006&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include "lltut.h"
+#include "llhttpnode.h"
+#include "llsdhttpserver.h"
+
+namespace tut
+{
+ struct HTTPNodeTestData
+ {
+ LLHTTPNode mRoot;
+ LLSD mContext;
+
+ const LLSD& context() { return mContext; }
+
+ std::string remainderPath()
+ {
+ std::ostringstream pathOutput;
+ bool addSlash = false;
+
+ LLSD& remainder = mContext[CONTEXT_REQUEST]["remainder"];
+ for (LLSD::array_const_iterator i = remainder.beginArray();
+ i != remainder.endArray();
+ ++i)
+ {
+ if (addSlash) { pathOutput << '/'; }
+ pathOutput << i->asString();
+ addSlash = true;
+ }
+
+ return pathOutput.str();
+ }
+
+ void ensureRootTraversal(const std::string& path,
+ const LLHTTPNode* expectedNode,
+ const char* expectedRemainder)
+ {
+ mContext.clear();
+
+ const LLHTTPNode* actualNode = mRoot.traverse(path, mContext);
+
+ ensure_equals("traverse " + path + " node",
+ actualNode, expectedNode);
+ ensure_equals("traverse " + path + " remainder",
+ remainderPath(), expectedRemainder);
+ }
+
+ class Response : public LLHTTPNode::Response
+ {
+ public:
+ static LLPointer<Response> create() {return new Response();}
+
+ LLSD mResult;
+
+ void result(const LLSD& result) { mResult = result; }
+ void status(S32 code, const std::string& message) { }
+ void extendedResult(S32 code, const std::string& message, const LLSD& headers) { }
+ void extendedResult(S32 code, const LLSD& result, const LLSD& headers) { }
+
+ private:
+ Response() {;} // Must be accessed through LLPointer.
+ };
+
+ typedef LLPointer<Response> ResponsePtr;
+
+ LLSD get(const std::string& path)
+ {
+ mContext.clear();
+ const LLHTTPNode* node = mRoot.traverse(path, mContext);
+ ensure(path + " found", node != NULL);
+
+ ResponsePtr response = Response::create();
+ node->get(LLHTTPNode::ResponsePtr(response), mContext);
+ return response->mResult;
+ }
+
+ LLSD post(const std::string& path, const LLSD& input)
+ {
+ mContext.clear();
+ const LLHTTPNode* node = mRoot.traverse(path, mContext);
+ ensure(path + " found", node != NULL);
+
+ ResponsePtr response = Response::create();
+ node->post(LLHTTPNode::ResponsePtr(response), mContext, input);
+ return response->mResult;
+ }
+
+ void ensureMemberString(const std::string& name,
+ const LLSD& actualMap, const std::string& member,
+ const std::string& expectedValue)
+ {
+ ensure_equals(name + " " + member,
+ actualMap[member].asString(), expectedValue);
+ }
+
+
+ void ensureInArray(const LLSD& actualArray,
+ const std::string& expectedValue)
+ {
+ LLSD::array_const_iterator i = actualArray.beginArray();
+ LLSD::array_const_iterator end = actualArray.endArray();
+
+ for (; i != end; ++i)
+ {
+ std::string path = i->asString();
+
+ if (path == expectedValue)
+ {
+ return;
+ }
+ }
+
+ fail("didn't find " + expectedValue);
+ }
+
+ };
+
+ typedef test_group<HTTPNodeTestData> HTTPNodeTestGroup;
+ typedef HTTPNodeTestGroup::object HTTPNodeTestObject;
+ HTTPNodeTestGroup httpNodeTestGroup("http node");
+
+ template<> template<>
+ void HTTPNodeTestObject::test<1>()
+ {
+ // traversal of the lone node
+
+ ensureRootTraversal("", &mRoot, "");
+ ensureRootTraversal("/", &mRoot, "");
+ ensureRootTraversal("foo", NULL, "foo");
+ ensureRootTraversal("foo/bar", NULL, "foo/bar");
+
+ ensure_equals("root of root", mRoot.rootNode(), &mRoot);
+ }
+
+ template<> template<>
+ void HTTPNodeTestObject::test<2>()
+ {
+ // simple traversal of a single node
+
+ LLHTTPNode* helloNode = new LLHTTPNode;
+ mRoot.addNode("hello", helloNode);
+
+ ensureRootTraversal("hello", helloNode, "");
+ ensureRootTraversal("/hello", helloNode, "");
+ ensureRootTraversal("hello/", helloNode, "");
+ ensureRootTraversal("/hello/", helloNode, "");
+
+ ensureRootTraversal("hello/there", NULL, "there");
+
+ ensure_equals("root of hello", helloNode->rootNode(), &mRoot);
+ }
+
+ template<> template<>
+ void HTTPNodeTestObject::test<3>()
+ {
+ // traversal of mutli-branched tree
+
+ LLHTTPNode* greekNode = new LLHTTPNode;
+ LLHTTPNode* alphaNode = new LLHTTPNode;
+ LLHTTPNode* betaNode = new LLHTTPNode;
+ LLHTTPNode* gammaNode = new LLHTTPNode;
+
+ greekNode->addNode("alpha", alphaNode);
+ greekNode->addNode("beta", betaNode);
+ greekNode->addNode("gamma", gammaNode);
+ mRoot.addNode("greek", greekNode);
+
+ LLHTTPNode* hebrewNode = new LLHTTPNode;
+ LLHTTPNode* alephNode = new LLHTTPNode;
+
+ hebrewNode->addNode("aleph", alephNode);
+ mRoot.addNode("hebrew", hebrewNode);
+
+ ensureRootTraversal("greek/alpha", alphaNode, "");
+ ensureRootTraversal("greek/beta", betaNode, "");
+ ensureRootTraversal("greek/delta", NULL, "delta");
+ ensureRootTraversal("greek/gamma", gammaNode, "");
+ ensureRootTraversal("hebrew/aleph", alephNode, "");
+
+ ensure_equals("root of greek", greekNode->rootNode(), &mRoot);
+ ensure_equals("root of alpha", alphaNode->rootNode(), &mRoot);
+ ensure_equals("root of beta", betaNode->rootNode(), &mRoot);
+ ensure_equals("root of gamma", gammaNode->rootNode(), &mRoot);
+ ensure_equals("root of hebrew", hebrewNode->rootNode(), &mRoot);
+ ensure_equals("root of aleph", alephNode->rootNode(), &mRoot);
+ }
+
+ template<> template<>
+ void HTTPNodeTestObject::test<4>()
+ {
+ // automatic creation of parent nodes and not overriding existing nodes
+
+ LLHTTPNode* alphaNode = new LLHTTPNode;
+ LLHTTPNode* betaNode = new LLHTTPNode;
+ LLHTTPNode* gammaNode = new LLHTTPNode;
+ LLHTTPNode* gamma2Node = new LLHTTPNode;
+
+ mRoot.addNode("greek/alpha", alphaNode);
+ mRoot.addNode("greek/beta", betaNode);
+
+ mRoot.addNode("greek/gamma", gammaNode);
+ mRoot.addNode("greek/gamma", gamma2Node);
+
+ LLHTTPNode* alephNode = new LLHTTPNode;
+
+ mRoot.addNode("hebrew/aleph", alephNode);
+
+ ensureRootTraversal("greek/alpha", alphaNode, "");
+ ensureRootTraversal("greek/beta", betaNode, "");
+ ensureRootTraversal("greek/delta", NULL, "delta");
+ ensureRootTraversal("greek/gamma", gammaNode, "");
+ ensureRootTraversal("hebrew/aleph", alephNode, "");
+
+ ensure_equals("root of alpha", alphaNode->rootNode(), &mRoot);
+ ensure_equals("root of beta", betaNode->rootNode(), &mRoot);
+ ensure_equals("root of gamma", gammaNode->rootNode(), &mRoot);
+ ensure_equals("root of aleph", alephNode->rootNode(), &mRoot);
+ }
+
+ class IntegerNode : public LLHTTPNode
+ {
+ public:
+ virtual void get(ResponsePtr response, const LLSD& context) const
+ {
+ int n = context["extra"]["value"];
+
+ LLSD info;
+ info["value"] = n;
+ info["positive"] = n > 0;
+ info["zero"] = n == 0;
+ info["negative"] = n < 0;
+
+ response->result(info);
+ }
+
+ virtual bool validate(const std::string& name, LLSD& context) const
+ {
+ int n;
+ std::istringstream i_stream(name);
+ i_stream >> n;
+
+ if (i_stream.fail() || i_stream.get() != EOF)
+ {
+ return false;
+ }
+
+ context["extra"]["value"] = n;
+ return true;
+ }
+ };
+
+ class SquareNode : public LLHTTPNode
+ {
+ public:
+ virtual void get(ResponsePtr response, const LLSD& context) const
+ {
+ int n = context["extra"]["value"];
+ response->result(n*n);
+ }
+ };
+
+ template<> template<>
+ void HTTPNodeTestObject::test<5>()
+ {
+ // wildcard nodes
+
+ LLHTTPNode* miscNode = new LLHTTPNode;
+ LLHTTPNode* iNode = new IntegerNode;
+ LLHTTPNode* sqNode = new SquareNode;
+
+ mRoot.addNode("test/misc", miscNode);
+ mRoot.addNode("test/<int>", iNode);
+ mRoot.addNode("test/<int>/square", sqNode);
+
+ ensureRootTraversal("test/42", iNode, "");
+ ensure_equals("stored integer",
+ context()["extra"]["value"].asInteger(), 42);
+
+ ensureRootTraversal("test/bob", NULL, "bob");
+ ensure("nothing stored",
+ context()["extra"]["value"].isUndefined());
+
+ ensureRootTraversal("test/3/square", sqNode, "");
+ ResponsePtr response = Response::create();
+ sqNode->get(LLHTTPNode::ResponsePtr(response), context());
+ ensure_equals("square result", response->mResult.asInteger(), 9);
+ }
+
+ class AlphaNode : public LLHTTPNode
+ {
+ public:
+ virtual bool handles(const LLSD& remainder, LLSD& context) const
+ {
+ LLSD::array_const_iterator i = remainder.beginArray();
+ LLSD::array_const_iterator end = remainder.endArray();
+
+ for (; i != end; ++i)
+ {
+ std::string s = i->asString();
+ if (s.empty() || s[0] != 'a')
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+ };
+
+ template<> template<>
+ void HTTPNodeTestObject::test<6>()
+ {
+ // nodes that handle remainders
+
+ LLHTTPNode* miscNode = new LLHTTPNode;
+ LLHTTPNode* aNode = new AlphaNode;
+ LLHTTPNode* zNode = new LLHTTPNode;
+
+ mRoot.addNode("test/misc", miscNode);
+ mRoot.addNode("test/alpha", aNode);
+ mRoot.addNode("test/alpha/zebra", zNode);
+
+ ensureRootTraversal("test/alpha", aNode, "");
+ ensureRootTraversal("test/alpha/abe", aNode, "abe");
+ ensureRootTraversal("test/alpha/abe/amy", aNode, "abe/amy");
+ ensureRootTraversal("test/alpha/abe/bea", NULL, "abe/bea");
+ ensureRootTraversal("test/alpha/bob", NULL, "bob");
+ ensureRootTraversal("test/alpha/zebra", zNode, "");
+ }
+
+ template<> template<>
+ void HTTPNodeTestObject::test<7>()
+ {
+ // test auto registration
+
+ LLHTTPStandardServices::useServices();
+ LLHTTPRegistrar::buildAllServices(mRoot);
+
+ {
+ LLSD result = get("web/hello");
+ ensure_equals("hello result", result.asString(), "hello");
+ }
+ {
+ LLSD stuff = 3.14159;
+ LLSD result = post("web/echo", stuff);
+ ensure_equals("echo result", result, stuff);
+ }
+ }
+
+ template<> template<>
+ void HTTPNodeTestObject::test<8>()
+ {
+ // test introspection
+
+ LLHTTPRegistrar::buildAllServices(mRoot);
+
+ mRoot.addNode("test/misc", new LLHTTPNode);
+ mRoot.addNode("test/<int>", new IntegerNode);
+ mRoot.addNode("test/<int>/square", new SquareNode);
+
+ const LLSD result = get("web/server/api");
+
+ ensure("result is array", result.isArray());
+ ensure("result size", result.size() >= 2);
+
+ ensureInArray(result, "web/echo");
+ ensureInArray(result, "web/hello");
+ ensureInArray(result, "test/misc");
+ ensureInArray(result, "test/<int>");
+ ensureInArray(result, "test/<int>/square");
+ }
+
+ template<> template<>
+ void HTTPNodeTestObject::test<9>()
+ {
+ // test introspection details
+
+ LLHTTPRegistrar::buildAllServices(mRoot);
+
+ const LLSD helloDetails = get("web/server/api/web/hello");
+
+ ensure_contains("hello description",
+ helloDetails["description"].asString(), "hello");
+ ensure_equals("method name", helloDetails["api"][0].asString(), std::string("GET"));
+ ensureMemberString("hello", helloDetails, "output", "\"hello\"");
+ ensure_contains("hello __file__",
+ helloDetails["__file__"].asString(), "llsdhttpserver.cpp");
+ ensure("hello line", helloDetails["__line__"].isInteger());
+
+
+ const LLSD echoDetails = get("web/server/api/web/echo");
+
+ ensure_contains("echo description",
+ echoDetails["description"].asString(), "echo");
+ ensure_equals("method name", echoDetails["api"][0].asString(), std::string("POST"));
+ ensureMemberString("echo", echoDetails, "input", "<any>");
+ ensureMemberString("echo", echoDetails, "output", "<the input>");
+ ensure_contains("echo __file__",
+ echoDetails["__file__"].asString(), "llsdhttpserver.cpp");
+ ensure("echo", echoDetails["__line__"].isInteger());
+ }
+}
diff --git a/indra/llmessage/tests/lliohttpserver_test.cpp b/indra/llmessage/tests/lliohttpserver_test.cpp
new file mode 100644
index 0000000000..7034f4a063
--- /dev/null
+++ b/indra/llmessage/tests/lliohttpserver_test.cpp
@@ -0,0 +1,350 @@
+/**
+ * @file lliohttpserver_tut.cpp
+ * @date May 2006
+ * @brief HTTP server unit tests
+ *
+ * $LicenseInfo:firstyear=2006&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include "lltut.h"
+#include "llbufferstream.h"
+#include "lliohttpserver.h"
+#include "llsdhttpserver.h"
+#include "llsdserialize.h"
+#include "llcommon.h"
+
+#include "llpipeutil.h"
+
+
+namespace tut
+{
+ class HTTPServiceTestData
+ {
+ public:
+ class DelayedEcho : public LLHTTPNode
+ {
+ HTTPServiceTestData* mTester;
+
+ public:
+ DelayedEcho(HTTPServiceTestData* tester) : mTester(tester) { }
+
+ void post(ResponsePtr response, const LLSD& context, const LLSD& input) const
+ {
+ ensure("response already set", mTester->mResponse == ResponsePtr(NULL));
+ mTester->mResponse = response;
+ mTester->mResult = input;
+ }
+ };
+
+ class WireHello : public LLIOPipe
+ {
+ protected:
+ virtual EStatus process_impl(
+ const LLChannelDescriptors& channels,
+ buffer_ptr_t& buffer,
+ bool& eos,
+ LLSD& context,
+ LLPumpIO* pump)
+ {
+ if(!eos) return STATUS_BREAK;
+ LLSD sd = "yo!";
+ LLBufferStream ostr(channels, buffer.get());
+ ostr << LLSDXMLStreamer(sd);
+ return STATUS_DONE;
+ }
+ };
+
+ HTTPServiceTestData()
+ : mResponse(NULL)
+ {
+ LLHTTPStandardServices::useServices();
+ LLHTTPRegistrar::buildAllServices(mRoot);
+ mRoot.addNode("/delayed/echo", new DelayedEcho(this));
+ mRoot.addNode("/wire/hello", new LLHTTPNodeForPipe<WireHello>);
+ }
+
+ ~HTTPServiceTestData()
+ {
+ }
+
+ LLHTTPNode mRoot;
+ LLHTTPNode::ResponsePtr mResponse;
+ LLSD mResult;
+
+ void pumpPipe(LLPumpIO* pump, S32 iterations)
+ {
+ while(iterations > 0)
+ {
+ pump->pump();
+ pump->callback();
+ --iterations;
+ }
+ }
+
+ std::string makeRequest(
+ const std::string& name,
+ const std::string& httpRequest,
+ bool timeout = false)
+ {
+ LLPipeStringInjector* injector = new LLPipeStringInjector(httpRequest);
+ LLPipeStringExtractor* extractor = new LLPipeStringExtractor();
+
+ apr_pool_t* pool;
+ apr_pool_create(&pool, NULL);
+
+ LLPumpIO* pump;
+ pump = new LLPumpIO(pool);
+
+ LLPumpIO::chain_t chain;
+ LLSD context;
+
+ chain.push_back(LLIOPipe::ptr_t(injector));
+ LLIOHTTPServer::createPipe(chain, mRoot, LLSD());
+ chain.push_back(LLIOPipe::ptr_t(extractor));
+
+ pump->addChain(chain, DEFAULT_CHAIN_EXPIRY_SECS);
+
+ pumpPipe(pump, 10);
+ if(mResponse.notNull() && (! timeout))
+ {
+ mResponse->result(mResult);
+ mResponse = NULL;
+ }
+ pumpPipe(pump, 10);
+
+ std::string httpResult = extractor->string();
+
+ chain.clear();
+ delete pump;
+ apr_pool_destroy(pool);
+
+ if(mResponse.notNull() && timeout)
+ {
+ mResponse->result(mResult);
+ mResponse = NULL;
+ }
+
+ return httpResult;
+ }
+
+ std::string httpGET(const std::string& uri,
+ bool timeout = false)
+ {
+ std::string httpRequest = "GET " + uri + " HTTP/1.0\r\n\r\n";
+ return makeRequest(uri, httpRequest, timeout);
+ }
+
+ std::string httpPOST(const std::string& uri,
+ const std::string& body,
+ bool timeout,
+ const std::string& evilExtra = "")
+ {
+ std::ostringstream httpRequest;
+ httpRequest << "POST " + uri + " HTTP/1.0\r\n";
+ httpRequest << "Content-Length: " << body.size() << "\r\n";
+ httpRequest << "\r\n";
+ httpRequest << body;
+ httpRequest << evilExtra;
+
+ return makeRequest(uri, httpRequest.str(), timeout);
+ }
+
+ std::string httpPOST(const std::string& uri,
+ const std::string& body,
+ const std::string& evilExtra = "")
+ {
+ bool timeout = false;
+ return httpPOST(uri, body, timeout, evilExtra);
+ }
+ };
+
+ typedef test_group<HTTPServiceTestData> HTTPServiceTestGroup;
+ typedef HTTPServiceTestGroup::object HTTPServiceTestObject;
+ HTTPServiceTestGroup httpServiceTestGroup("http service");
+
+ template<> template<>
+ void HTTPServiceTestObject::test<1>()
+ {
+ std::string result = httpGET("web/hello");
+
+ ensure_starts_with("web/hello status", result,
+ "HTTP/1.0 200 OK\r\n");
+
+ ensure_contains("web/hello content type", result,
+ "Content-Type: application/llsd+xml\r\n");
+
+ ensure_contains("web/hello content length", result,
+ "Content-Length: 36\r\n");
+
+ ensure_contains("web/hello content", result,
+ "\r\n"
+ "<llsd><string>hello</string></llsd>"
+ );
+ }
+
+ template<> template<>
+ void HTTPServiceTestObject::test<2>()
+ {
+ // test various HTTP errors
+
+ std::string actual;
+
+ actual = httpGET("web/missing");
+ ensure_starts_with("web/missing 404", actual,
+ "HTTP/1.0 404 Not Found\r\n");
+
+ actual = httpGET("web/echo");
+ ensure_starts_with("web/echo 405", actual,
+ "HTTP/1.0 405 Method Not Allowed\r\n");
+ }
+
+ template<> template<>
+ void HTTPServiceTestObject::test<3>()
+ {
+ // test POST & content-length handling
+
+ std::string result;
+
+ result = httpPOST("web/echo",
+ "<llsd><integer>42</integer></llsd>");
+
+ ensure_starts_with("web/echo status", result,
+ "HTTP/1.0 200 OK\r\n");
+
+ ensure_contains("web/echo content type", result,
+ "Content-Type: application/llsd+xml\r\n");
+
+ ensure_contains("web/echo content length", result,
+ "Content-Length: 35\r\n");
+
+ ensure_contains("web/hello content", result,
+ "\r\n"
+ "<llsd><integer>42</integer></llsd>"
+ );
+
+/* TO DO: this test doesn't pass!!
+
+ result = httpPOST("web/echo",
+ "<llsd><string>evil</string></llsd>",
+ "really! evil!!!");
+
+ ensure_equals("web/echo evil result", result,
+ "HTTP/1.0 200 OK\r\n"
+ "Content-Length: 34\r\n"
+ "\r\n"
+ "<llsd><string>evil</string></llsd>"
+ );
+*/
+ }
+
+ template<> template<>
+ void HTTPServiceTestObject::test<4>()
+ {
+ // test calling things based on pipes
+
+ std::string result;
+
+ result = httpGET("wire/hello");
+
+ ensure_contains("wire/hello", result, "yo!");
+ }
+
+ template<> template<>
+ void HTTPServiceTestObject::test<5>()
+ {
+ // test timeout before async response
+ std::string result;
+
+ bool timeout = true;
+ result = httpPOST("delayed/echo",
+ "<llsd><string>agent99</string></llsd>", timeout);
+
+ ensure_equals("timeout delayed/echo status", result, std::string(""));
+ }
+
+ template<> template<>
+ void HTTPServiceTestObject::test<6>()
+ {
+ // test delayed service
+ std::string result;
+
+ result = httpPOST("delayed/echo",
+ "<llsd><string>agent99</string></llsd>");
+
+ ensure_starts_with("delayed/echo status", result,
+ "HTTP/1.0 200 OK\r\n");
+
+ ensure_contains("delayed/echo content", result,
+ "\r\n"
+ "<llsd><string>agent99</string></llsd>"
+ );
+ }
+
+ template<> template<>
+ void HTTPServiceTestObject::test<7>()
+ {
+ // test large request
+ std::stringstream stream;
+
+ //U32 size = 36 * 1024 * 1024;
+ //U32 size = 36 * 1024;
+ //std::vector<char> data(size);
+ //memset(&(data[0]), '1', size);
+ //data[size - 1] = '\0';
+
+
+ //std::string result = httpPOST("web/echo", &(data[0]));
+
+ stream << "<llsd><array>";
+ for(U32 i = 0; i < 1000000; ++i)
+ {
+ stream << "<integer>42</integer>";
+ }
+ stream << "</array></llsd>";
+ LL_INFOS() << "HTTPServiceTestObject::test<7>"
+ << stream.str().length() << LL_ENDL;
+ std::string result = httpPOST("web/echo", stream.str());
+ ensure_starts_with("large echo status", result, "HTTP/1.0 200 OK\r\n");
+ }
+
+ template<> template<>
+ void HTTPServiceTestObject::test<8>()
+ {
+ // test the OPTIONS http method -- the default implementation
+ // should return the X-Documentation-URL
+ std::ostringstream http_request;
+ http_request << "OPTIONS / HTTP/1.0\r\nHost: localhost\r\n\r\n";
+ bool timeout = false;
+ std::string result = makeRequest("/", http_request.str(), timeout);
+ ensure_starts_with("OPTIONS verb ok", result, "HTTP/1.0 200 OK\r\n");
+ ensure_contains(
+ "Doc url header exists",
+ result,
+ "X-Documentation-URL: http://localhost");
+ }
+
+
+ /* TO DO:
+ test generation of not found and method not allowed errors
+ */
+}
diff --git a/indra/llmessage/tests/llmessageconfig_test.cpp b/indra/llmessage/tests/llmessageconfig_test.cpp
new file mode 100644
index 0000000000..b8942e99b3
--- /dev/null
+++ b/indra/llmessage/tests/llmessageconfig_test.cpp
@@ -0,0 +1,236 @@
+/**
+ * @file llmessageconfig_tut.cpp
+ * @date March 2007
+ * @brief LLMessageConfig unit tests
+ *
+ * $LicenseInfo:firstyear=2006&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include "llmessageconfig.h"
+#include "lltut.h"
+#include "llsdserialize.h"
+#include "llfile.h"
+#include "lltimer.h"
+#include "llframetimer.h"
+#include "llsdutil.h"
+
+namespace tut
+{
+ struct LLMessageConfigTestData {
+ std::string mTestConfigDir;
+
+ LLMessageConfigTestData()
+ {
+ LLUUID random;
+ random.generate();
+ // generate temp dir
+ std::ostringstream oStr;
+#if LL_WINDOWS
+ oStr << "llmessage-config-test-" << random;
+#else
+ oStr << "/tmp/llmessage-config-test-" << random;
+#endif
+ mTestConfigDir = oStr.str();
+ LLFile::mkdir(mTestConfigDir);
+ writeConfigFile(LLSD());
+ LLMessageConfig::initClass("simulator", mTestConfigDir);
+ }
+
+ ~LLMessageConfigTestData()
+ {
+ // rm contents of temp dir
+ int rmfile = LLFile::remove((mTestConfigDir + "/message.xml"));
+ ensure_equals("rmfile value", rmfile, 0);
+ // rm temp dir
+ int rmdir = LLFile::remove(mTestConfigDir);
+ ensure_equals("rmdir value", rmdir, 0);
+ }
+
+ void writeConfigFile(const LLSD& config)
+ {
+ llofstream file((mTestConfigDir + "/message.xml").c_str());
+ if (file.is_open())
+ {
+ LLSDSerialize::toPrettyXML(config, file);
+ }
+ file.close();
+ }
+ };
+
+ typedef test_group<LLMessageConfigTestData> LLMessageConfigTestGroup;
+ typedef LLMessageConfigTestGroup::object LLMessageConfigTestObject;
+ LLMessageConfigTestGroup llMessageConfigTestGroup("LLMessageConfig");
+
+ template<> template<>
+ void LLMessageConfigTestObject::test<1>()
+ // tests server defaults
+ {
+ LLSD config;
+ config["serverDefaults"]["simulator"] = "template";
+ LLMessageConfig::useConfig(config);
+ ensure_equals("Ensure server default is not template",
+ LLMessageConfig::getServerDefaultFlavor(),
+ LLMessageConfig::TEMPLATE_FLAVOR);
+ }
+
+ template<> template<>
+ void LLMessageConfigTestObject::test<2>()
+ // tests message flavors
+ {
+ LLSD config;
+ config["serverDefaults"]["simulator"] = "template";
+ config["messages"]["msg1"]["flavor"] = "template";
+ config["messages"]["msg2"]["flavor"] = "llsd";
+ LLMessageConfig::useConfig(config);
+ ensure_equals("Ensure msg template flavor",
+ LLMessageConfig::getMessageFlavor("msg1"),
+ LLMessageConfig::TEMPLATE_FLAVOR);
+ ensure_equals("Ensure msg llsd flavor",
+ LLMessageConfig::getMessageFlavor("msg2"),
+ LLMessageConfig::LLSD_FLAVOR);
+ }
+
+ template<> template<>
+ void LLMessageConfigTestObject::test<4>()
+ // tests message flavor defaults
+ {
+ LLSD config;
+ config["serverDefaults"]["simulator"] = "llsd";
+ config["messages"]["msg1"]["trusted-sender"] = true;
+ LLMessageConfig::useConfig(config);
+ ensure_equals("Ensure missing message gives no flavor",
+ LLMessageConfig::getMessageFlavor("Test"),
+ LLMessageConfig::NO_FLAVOR);
+ ensure_equals("Ensure missing flavor is NO_FLAVOR even with sender trustedness set",
+ LLMessageConfig::getMessageFlavor("msg1"),
+ LLMessageConfig::NO_FLAVOR);
+ ensure_equals("Ensure server default is llsd",
+ LLMessageConfig::getServerDefaultFlavor(),
+ LLMessageConfig::LLSD_FLAVOR);
+ }
+
+ template<> template<>
+ void LLMessageConfigTestObject::test<3>()
+ // tests trusted/untrusted senders
+ {
+ LLSD config;
+ config["serverDefaults"]["simulator"] = "template";
+ config["messages"]["msg1"]["flavor"] = "llsd";
+ config["messages"]["msg1"]["trusted-sender"] = false;
+ config["messages"]["msg2"]["flavor"] = "llsd";
+ config["messages"]["msg2"]["trusted-sender"] = true;
+ LLMessageConfig::useConfig(config);
+ ensure_equals("Ensure untrusted is untrusted",
+ LLMessageConfig::getSenderTrustedness("msg1"),
+ LLMessageConfig::UNTRUSTED);
+ ensure_equals("Ensure trusted is trusted",
+ LLMessageConfig::getSenderTrustedness("msg2"),
+ LLMessageConfig::TRUSTED);
+ ensure_equals("Ensure missing trustedness is NOT_SET",
+ LLMessageConfig::getSenderTrustedness("msg3"),
+ LLMessageConfig::NOT_SET);
+ }
+
+ template<> template<>
+ void LLMessageConfigTestObject::test<5>()
+ // tests trusted/untrusted without flag, only flavor
+ {
+ LLSD config;
+ config["serverDefaults"]["simulator"] = "template";
+ config["messages"]["msg1"]["flavor"] = "llsd";
+ LLMessageConfig::useConfig(config);
+ ensure_equals("Ensure msg1 exists, has llsd flavor",
+ LLMessageConfig::getMessageFlavor("msg1"),
+ LLMessageConfig::LLSD_FLAVOR);
+ ensure_equals("Ensure missing trusted is not set",
+ LLMessageConfig::getSenderTrustedness("msg1"),
+ LLMessageConfig::NOT_SET);
+ }
+
+ template<> template<>
+ void LLMessageConfigTestObject::test<6>()
+ {
+ LLSD config;
+ config["capBans"]["MapLayer"] = true;
+ config["capBans"]["MapLayerGod"] = false;
+ LLMessageConfig::useConfig(config);
+ ensure_equals("Ensure cap ban true MapLayer",
+ LLMessageConfig::isCapBanned("MapLayer"),
+ true);
+ ensure_equals("Ensure cap ban false",
+ LLMessageConfig::isCapBanned("MapLayerGod"),
+ false);
+ }
+
+ template<> template<>
+ void LLMessageConfigTestObject::test<7>()
+ // tests that config changes are picked up/refreshed periodically
+ {
+ LLSD config;
+ config["serverDefaults"]["simulator"] = "llsd";
+ writeConfigFile(config);
+
+ // wait for it to reload after N seconds
+ ms_sleep(6*1000);
+ LLFrameTimer::updateFrameTime();
+ ensure_equals("Ensure reload after 6 seconds",
+ LLMessageConfig::getServerDefaultFlavor(),
+ LLMessageConfig::LLSD_FLAVOR);
+ }
+
+ template<> template<>
+ void LLMessageConfigTestObject::test<8>()
+ // tests that config changes are picked up/refreshed periodically
+ {
+ LLSD config;
+ config["serverDefaults"]["simulator"] = "template";
+ config["messages"]["msg1"]["flavor"] = "llsd";
+ config["messages"]["msg1"]["only-send-latest"] = true;
+ config["messages"]["msg2"]["flavor"] = "llsd";
+ config["messages"]["msg2"]["only-send-latest"] = false;
+ LLMessageConfig::useConfig(config);
+ ensure_equals("Ensure msg1 exists, sent latest-only",
+ LLMessageConfig::onlySendLatest("msg1"),
+ true);
+ ensure_equals("Ensure msg2 exists, sent latest-only",
+ LLMessageConfig::onlySendLatest("msg2"),
+ false);
+ }
+
+ template<> template<>
+ void LLMessageConfigTestObject::test<9>()
+ // tests that event queue max is reloaded
+ {
+ LLSD config;
+ config["maxQueuedEvents"] = 200;
+ LLMessageConfig::useConfig(config);
+ ensure_equals("Ensure setting maxQueuedEvents",
+ LLMessageConfig::getMaxQueuedEvents(),
+ 200);
+
+ LLMessageConfig::useConfig(LLSD());
+ ensure_equals("Ensure default of event queue max 100",
+ LLMessageConfig::getMaxQueuedEvents(),
+ 100);
+ }
+}
diff --git a/indra/llmessage/tests/llmessagetemplateparser_test.cpp b/indra/llmessage/tests/llmessagetemplateparser_test.cpp
new file mode 100644
index 0000000000..f665fdde4d
--- /dev/null
+++ b/indra/llmessage/tests/llmessagetemplateparser_test.cpp
@@ -0,0 +1,368 @@
+/**
+ * @file llmessagetemplateparser_tut.cpp
+ * @date April 2007
+ * @brief LLMessageTemplateParser unit tests
+ *
+ * $LicenseInfo:firstyear=2006&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include "llmessagetemplateparser.h"
+#include "lltut.h"
+
+namespace tut
+{
+ struct LLMessageTemplateParserTestData {
+ LLMessageTemplateParserTestData() : mMessage("unset message")
+ {
+ }
+
+ ~LLMessageTemplateParserTestData()
+ {
+ }
+
+ void ensure_next(LLTemplateTokenizer & tokens,
+ std::string value,
+ U32 line)
+ {
+ std::string next = tokens.next();
+ ensure_equals(mMessage + " token matches", next, value);
+ ensure_equals(mMessage + " line matches", tokens.line(), line);
+ }
+
+ char * prehash(const char * name)
+ {
+ return LLMessageStringTable::getInstance()->getString(name);
+ }
+
+ void ensure_block_attributes(std::string identifier,
+ const LLMessageTemplate * message,
+ const char * name,
+ EMsgBlockType type,
+ S32 number,
+ S32 total_size)
+ {
+ const LLMessageBlock * block = message->getBlock(prehash(name));
+ identifier = identifier + ":" + message->mName + ":" + name + " block";
+ ensure(identifier + " exists", block != NULL);
+ ensure_equals(identifier + " name", block->mName, prehash(name));
+ ensure_equals(identifier + " type", block->mType, type);
+ ensure_equals(identifier + " number", block->mNumber, number);
+ ensure_equals(identifier + " total size", block->mTotalSize, total_size);
+ }
+
+ void ensure_variable_attributes(std::string identifier,
+ const LLMessageBlock * block,
+ const char * name,
+ EMsgVariableType type,
+ S32 size)
+ {
+ const LLMessageVariable * var = block->getVariable(prehash(name));
+ identifier = identifier + ":" + block->mName + ":" + name + " variable";
+ ensure(identifier + " exists", var != NULL);
+ ensure_equals(
+ identifier + " name", var->getName(), prehash(name));
+ ensure_equals(
+ identifier + " type", var->getType(), type);
+ ensure_equals(identifier + " size", var->getSize(), size);
+ }
+
+ std::string mMessage;
+
+ };
+
+ typedef test_group<LLMessageTemplateParserTestData> LLMessageTemplateParserTestGroup;
+ typedef LLMessageTemplateParserTestGroup::object LLMessageTemplateParserTestObject;
+ LLMessageTemplateParserTestGroup llMessageTemplateParserTestGroup("LLMessageTemplateParser");
+
+ template<> template<>
+ void LLMessageTemplateParserTestObject::test<1>()
+ // tests tokenizer constructor and next methods
+ {
+ mMessage = "test method 1 walkthrough";
+ LLTemplateTokenizer tokens("first line\nnext\t line\n\nfourth");
+ ensure_next(tokens, "first", 1);
+ ensure_next(tokens, "line", 1);
+ ensure_next(tokens, "next", 2);
+ ensure_next(tokens, "line", 2);
+ ensure_next(tokens, "fourth", 4);
+
+ tokens = LLTemplateTokenizer("\n\t{ \t Test1 Fixed \n 523 }\n\n");
+ ensure(tokens.want("{"));
+ ensure_next(tokens, "Test1", 2);
+ ensure_next(tokens, "Fixed", 2);
+ ensure_next(tokens, "523", 3);
+ ensure(tokens.want("}"));
+
+ tokens = LLTemplateTokenizer("first line\nnext\t line\n\nfourth");
+ ensure(tokens.want("first"));
+ ensure_next(tokens, "line", 1);
+ ensure_next(tokens, "next", 2);
+ ensure_next(tokens, "line", 2);
+ ensure(tokens.want("fourth"));
+ }
+
+ template<> template<>
+ void LLMessageTemplateParserTestObject::test<2>()
+ // tests tokenizer want method
+ {
+ // *NOTE: order matters
+ LLTemplateTokenizer tokens("first line\nnext\t line\n\nfourth");
+ ensure_equals("wants first token", tokens.want("first"), true);
+ ensure_equals("doesn't want blar token", tokens.want("blar"), false);
+ ensure_equals("wants line token", tokens.want("line"), true);
+ }
+
+ template<> template<>
+ void LLMessageTemplateParserTestObject::test<3>()
+ // tests tokenizer eof methods
+ {
+ LLTemplateTokenizer tokens("single\n\n");
+ ensure_equals("is not at eof at beginning", tokens.atEOF(), false);
+ ensure_equals("doesn't want eof", tokens.wantEOF(), false);
+ ensure_equals("wants the first token just to consume it",
+ tokens.want("single"), true);
+ ensure_equals("is not at eof in middle", tokens.atEOF(), false);
+ ensure_equals("wants eof", tokens.wantEOF(), true);
+ ensure_equals("is at eof at end", tokens.atEOF(), true);
+ }
+
+ template<> template<>
+ void LLMessageTemplateParserTestObject::test<4>()
+ // tests variable parsing method
+ {
+ LLTemplateTokenizer tokens(std::string("{ Test0 \n\t\n U32 \n\n }"));
+ LLMessageVariable * var = LLTemplateParser::parseVariable(tokens);
+
+ ensure("test0 var parsed", var != 0);
+ ensure_equals("name of variable", std::string(var->getName()), std::string("Test0"));
+ ensure_equals("type of variable is U32", var->getType(), MVT_U32);
+ ensure_equals("size of variable", var->getSize(), 4);
+
+ delete var;
+
+ std::string message_string("\n\t{ \t Test1 Fixed \n 523 }\n\n");
+ tokens = LLTemplateTokenizer(message_string);
+ var = LLTemplateParser::parseVariable(tokens);
+
+ ensure("test1 var parsed", var != 0);
+ ensure_equals("name of variable", std::string(var->getName()), std::string("Test1"));
+ ensure_equals("type of variable is Fixed", var->getType(), MVT_FIXED);
+ ensure_equals("size of variable", var->getSize(), 523);
+
+ delete var;
+
+ // *NOTE: the parsers call LL_ERRS() on invalid input, so we can't really
+ // test that :-(
+ }
+
+ template<> template<>
+ void LLMessageTemplateParserTestObject::test<5>()
+ // tests block parsing method
+ {
+ LLTemplateTokenizer tokens("{ BlockA Single { VarX F32 } }");
+ LLMessageBlock * block = LLTemplateParser::parseBlock(tokens);
+
+ ensure("blockA block parsed", block != 0);
+ ensure_equals("name of block", std::string(block->mName), std::string("BlockA"));
+ ensure_equals("type of block is Single", block->mType, MBT_SINGLE);
+ ensure_equals("total size of block", block->mTotalSize, 4);
+ ensure_equals("number of block defaults to 1", block->mNumber, 1);
+ ensure_equals("variable type of VarX is F32",
+ block->getVariableType(prehash("VarX")), MVT_F32);
+ ensure_equals("variable size of VarX",
+ block->getVariableSize(prehash("VarX")), 4);
+
+ delete block;
+
+ tokens = LLTemplateTokenizer("{ Stuff Variable { Id LLUUID } }");
+ block = LLTemplateParser::parseBlock(tokens);
+
+ ensure("stuff block parsed", block != 0);
+ ensure_equals("name of block", std::string(block->mName), std::string("Stuff"));
+ ensure_equals("type of block is Multiple", block->mType, MBT_VARIABLE);
+ ensure_equals("total size of block", block->mTotalSize, 16);
+ ensure_equals("number of block defaults to 1", block->mNumber, 1);
+ ensure_equals("variable type of Id is LLUUID",
+ block->getVariableType(prehash("Id")), MVT_LLUUID);
+ ensure_equals("variable size of Id",
+ block->getVariableSize(prehash("Id")), 16);
+
+ delete block;
+
+ tokens = LLTemplateTokenizer("{ Stuff2 Multiple 45 { Shid LLVector3d } }");
+ block = LLTemplateParser::parseBlock(tokens);
+
+ ensure("stuff2 block parsed", block != 0);
+ ensure_equals("name of block", std::string(block->mName), std::string("Stuff2"));
+ ensure_equals("type of block is Multiple", block->mType, MBT_MULTIPLE);
+ ensure_equals("total size of block", block->mTotalSize, 24);
+ ensure_equals("number of blocks", block->mNumber, 45);
+ ensure_equals("variable type of Shid is Vector3d",
+ block->getVariableType(prehash("Shid")), MVT_LLVector3d);
+ ensure_equals("variable size of Shid",
+ block->getVariableSize(prehash("Shid")), 24);
+
+ delete block;
+ }
+
+ template<> template<>
+ void LLMessageTemplateParserTestObject::test<6>()
+ // tests message parsing method on a simple message
+ {
+ std::string message_skel(
+ "{\n"
+ "TestMessage Low 1 NotTrusted Zerocoded\n"
+ "// comment \n"
+ " {\n"
+ "TestBlock1 Single\n"
+ " { Test1 U32 }\n"
+ " }\n"
+ " {\n"
+ " NeighborBlock Multiple 4\n"
+ " { Test0 U32 }\n"
+ " { Test1 U32 }\n"
+ " { Test2 U32 }\n"
+ " }\n"
+ "}");
+ LLTemplateTokenizer tokens(message_skel);
+ LLMessageTemplate * message = LLTemplateParser::parseMessage(tokens);
+
+ ensure("simple message parsed", message != 0);
+ ensure_equals("name of message", std::string(message->mName), std::string("TestMessage"));
+ ensure_equals("frequency is Low", message->mFrequency, MFT_LOW);
+ ensure_equals("trust is untrusted", message->mTrust, MT_NOTRUST);
+ ensure_equals("message number", message->mMessageNumber, (U32)((255 << 24) | (255 << 16) | 1));
+ ensure_equals("message encoding is zerocoded", message->mEncoding, ME_ZEROCODED);
+ ensure_equals("message deprecation is notdeprecated", message->mDeprecation, MD_NOTDEPRECATED);
+
+ LLMessageBlock * block = message->getBlock(prehash("NonexistantBlock"));
+ ensure("Nonexistant block does not exist", block == 0);
+
+ delete message;
+ }
+
+ template<> template<>
+ void LLMessageTemplateParserTestObject::test<7>()
+ // tests message parsing method on a deprecated message
+ {
+ std::string message_skel(
+ "{\n"
+ "TestMessageDeprecated High 34 Trusted Unencoded Deprecated\n"
+ " {\n"
+ "TestBlock2 Single\n"
+ " { Test2 S32 }\n"
+ " }\n"
+ "}");
+ LLTemplateTokenizer tokens(message_skel);
+ LLMessageTemplate * message = LLTemplateParser::parseMessage(tokens);
+
+ ensure("deprecated message parsed", message != 0);
+ ensure_equals("name of message", std::string(message->mName), std::string("TestMessageDeprecated"));
+ ensure_equals("frequency is High", message->mFrequency, MFT_HIGH);
+ ensure_equals("trust is trusted", message->mTrust, MT_TRUST);
+ ensure_equals("message number", message->mMessageNumber, (U32)34);
+ ensure_equals("message encoding is unencoded", message->mEncoding, ME_UNENCODED);
+ ensure_equals("message deprecation is deprecated", message->mDeprecation, MD_DEPRECATED);
+
+ delete message;
+ }
+
+ template<> template<> void LLMessageTemplateParserTestObject::test<8>()
+ // tests message parsing on RezMultipleAttachmentsFromInv, a possibly-faulty message
+ {
+ std::string message_skel(
+ "{\n\
+ RezMultipleAttachmentsFromInv Low 452 NotTrusted Zerocoded\n\
+ {\n\
+ AgentData Single\n\
+ { AgentID LLUUID }\n\
+ { SessionID LLUUID }\n\
+ } \n\
+ {\n\
+ HeaderData Single\n\
+ { CompoundMsgID LLUUID } // All messages a single \"compound msg\" must have the same id\n\
+ { TotalObjects U8 }\n\
+ { FirstDetachAll BOOL }\n\
+ }\n\
+ {\n\
+ ObjectData Variable // 1 to 4 of these per packet\n\
+ { ItemID LLUUID }\n\
+ { OwnerID LLUUID }\n\
+ { AttachmentPt U8 } // 0 for default\n\
+ { ItemFlags U32 }\n\
+ { GroupMask U32 }\n\
+ { EveryoneMask U32 }\n\
+ { NextOwnerMask U32 }\n\
+ { Name Variable 1 }\n\
+ { Description Variable 1 }\n\
+ }\n\
+ }\n\
+ ");
+ LLTemplateTokenizer tokens(message_skel);
+ LLMessageTemplate * message = LLTemplateParser::parseMessage(tokens);
+
+ ensure("RezMultipleAttachmentsFromInv message parsed", message != 0);
+ ensure_equals("name of message", message->mName, prehash("RezMultipleAttachmentsFromInv"));
+ ensure_equals("frequency is low", message->mFrequency, MFT_LOW);
+ ensure_equals("trust is not trusted", message->mTrust, MT_NOTRUST);
+ ensure_equals("message number", message->mMessageNumber, (U32)((255 << 24) | (255 << 16) | 452));
+ ensure_equals("message encoding is zerocoded", message->mEncoding, ME_ZEROCODED);
+
+ ensure_block_attributes(
+ "RMAFI", message, "AgentData", MBT_SINGLE, 1, 16+16);
+ LLMessageBlock * block = message->getBlock(prehash("AgentData"));
+ ensure_variable_attributes("RMAFI",
+ block, "AgentID", MVT_LLUUID, 16);
+ ensure_variable_attributes("RMAFI",
+ block, "SessionID", MVT_LLUUID, 16);
+
+ ensure_block_attributes(
+ "RMAFI", message, "HeaderData", MBT_SINGLE, 1, 16+1+1);
+ block = message->getBlock(prehash("HeaderData"));
+ ensure_variable_attributes(
+ "RMAFI", block, "CompoundMsgID", MVT_LLUUID, 16);
+ ensure_variable_attributes(
+ "RMAFI", block, "TotalObjects", MVT_U8, 1);
+ ensure_variable_attributes(
+ "RMAFI", block, "FirstDetachAll", MVT_BOOL, 1);
+
+
+ ensure_block_attributes(
+ "RMAFI", message, "ObjectData", MBT_VARIABLE, 1, -1);
+ block = message->getBlock(prehash("ObjectData"));
+ ensure_variable_attributes("RMAFI", block, "ItemID", MVT_LLUUID, 16);
+ ensure_variable_attributes("RMAFI", block, "OwnerID", MVT_LLUUID, 16);
+ ensure_variable_attributes("RMAFI", block, "AttachmentPt", MVT_U8, 1);
+ ensure_variable_attributes("RMAFI", block, "ItemFlags", MVT_U32, 4);
+ ensure_variable_attributes("RMAFI", block, "GroupMask", MVT_U32, 4);
+ ensure_variable_attributes("RMAFI", block, "EveryoneMask", MVT_U32, 4);
+ ensure_variable_attributes("RMAFI", block, "NextOwnerMask", MVT_U32, 4);
+ ensure_variable_attributes("RMAFI", block, "Name", MVT_VARIABLE, 1);
+ ensure_variable_attributes("RMAFI", block, "Description", MVT_VARIABLE, 1);
+
+ delete message;
+ }
+
+
+
+}
diff --git a/indra/llmessage/tests/llpipeutil.cpp b/indra/llmessage/tests/llpipeutil.cpp
new file mode 100644
index 0000000000..1dd4bdfa3c
--- /dev/null
+++ b/indra/llmessage/tests/llpipeutil.cpp
@@ -0,0 +1,183 @@
+/**
+ * @file llpipeutil.cpp
+ * @date 2006-05-18
+ * @brief Utility pipe fittings for injecting and extracting strings
+ *
+ * $LicenseInfo:firstyear=2006&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+
+#include "linden_common.h"
+#include "llpipeutil.h"
+
+#include <stdlib.h>
+#include <sstream>
+
+#include "llbufferstream.h"
+#include "lldefs.h"
+#include "llframetimer.h"
+#include "llpumpio.h"
+#include "llrand.h"
+#include "lltimer.h"
+
+F32 pump_loop(LLPumpIO* pump, F32 seconds)
+{
+ LLTimer timer;
+ timer.setTimerExpirySec(seconds);
+ while(!timer.hasExpired())
+ {
+ LLFrameTimer::updateFrameTime();
+ pump->pump();
+ pump->callback();
+ }
+ return timer.getElapsedTimeF32();
+}
+
+//virtual
+LLIOPipe::EStatus LLPipeStringInjector::process_impl(
+ const LLChannelDescriptors& channels,
+ buffer_ptr_t& buffer,
+ bool& eos,
+ LLSD& context,
+ LLPumpIO* pump)
+{
+ buffer->append(channels.out(), (U8*) mString.data(), static_cast<S32>(mString.size()));
+ eos = true;
+ return STATUS_DONE;
+}
+
+
+LLIOPipe::EStatus LLPipeStringExtractor::process_impl(
+ const LLChannelDescriptors& channels,
+ buffer_ptr_t& buffer,
+ bool& eos,
+ LLSD& context,
+ LLPumpIO* pump)
+{
+ if(!eos) return STATUS_BREAK;
+ if(!pump || !buffer) return STATUS_PRECONDITION_NOT_MET;
+
+ LLBufferStream istr(channels, buffer.get());
+ std::ostringstream ostr;
+ while (istr.good())
+ {
+ char buf[1024]; /* Flawfinder: ignore */
+ istr.read(buf, sizeof(buf)); /* Flawfinder: ignore */
+ ostr.write(buf, istr.gcount());
+ }
+ mString = ostr.str();
+ mDone = true;
+
+ return STATUS_DONE;
+}
+
+
+// virtual
+LLIOPipe::EStatus LLIOFuzz::process_impl(
+ const LLChannelDescriptors& channels,
+ buffer_ptr_t& buffer,
+ bool& eos,
+ LLSD& context,
+ LLPumpIO* pump)
+{
+ while(mByteCount)
+ {
+ std::vector<U8> data;
+ data.reserve(10000);
+ int size = llmin(10000, mByteCount);
+ std::generate_n(
+ std::back_insert_iterator< std::vector<U8> >(data),
+ size,
+ rand);
+ buffer->append(channels.out(), &data[0], size);
+ mByteCount -= size;
+ }
+ return STATUS_OK;
+}
+
+struct random_ascii_generator
+{
+ random_ascii_generator() {}
+ U8 operator()()
+ {
+ int rv = rand();
+ rv %= (127 - 32);
+ rv += 32;
+ return rv;
+ }
+};
+
+// virtual
+LLIOPipe::EStatus LLIOASCIIFuzz::process_impl(
+ const LLChannelDescriptors& channels,
+ buffer_ptr_t& buffer,
+ bool& eos,
+ LLSD& context,
+ LLPumpIO* pump)
+{
+ while(mByteCount)
+ {
+ std::vector<U8> data;
+ data.reserve(10000);
+ int size = llmin(10000, mByteCount);
+ std::generate_n(
+ std::back_insert_iterator< std::vector<U8> >(data),
+ size,
+ random_ascii_generator());
+ buffer->append(channels.out(), &data[0], size);
+ mByteCount -= size;
+ }
+ return STATUS_OK;
+}
+
+// virtual
+LLIOPipe::EStatus LLIONull::process_impl(
+ const LLChannelDescriptors& channels,
+ buffer_ptr_t& buffer,
+ bool& eos,
+ LLSD& context,
+ LLPumpIO* pump)
+{
+ return STATUS_OK;
+}
+
+// virtual
+LLIOPipe::EStatus LLIOSleeper::process_impl(
+ const LLChannelDescriptors& channels,
+ buffer_ptr_t& buffer,
+ bool& eos,
+ LLSD& context,
+ LLPumpIO* pump)
+{
+ if(!mRespond)
+ {
+ LL_DEBUGS() << "LLIOSleeper::process_impl() sleeping." << LL_ENDL;
+ mRespond = true;
+ static const F64 SLEEP_TIME = 2.0;
+ pump->sleepChain(SLEEP_TIME);
+ return STATUS_BREAK;
+ }
+ LL_DEBUGS() << "LLIOSleeper::process_impl() responding." << LL_ENDL;
+ LLBufferStream ostr(channels, buffer.get());
+ ostr << "huh? sorry, I was sleeping." << std::endl;
+ return STATUS_DONE;
+}
diff --git a/indra/llmessage/tests/llpipeutil.h b/indra/llmessage/tests/llpipeutil.h
new file mode 100644
index 0000000000..97d9e1c85c
--- /dev/null
+++ b/indra/llmessage/tests/llpipeutil.h
@@ -0,0 +1,163 @@
+/**
+ * @file llpipeutil.h
+ * @date 2006-05-18
+ * @brief Utility pipe fittings for injecting and extracting strings
+ *
+ * $LicenseInfo:firstyear=2006&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLPIPEUTIL_H
+#define LL_LLPIPEUTIL_H
+
+#include "lliopipe.h"
+
+
+/**
+ * @brief Simple function which pumps for the specified time.
+ */
+F32 pump_loop(LLPumpIO* pump, F32 seconds);
+
+/**
+ * @brief Simple class which writes a string and then marks the stream
+ * as done.
+ */
+class LLPipeStringInjector : public LLIOPipe
+{
+public:
+ LLPipeStringInjector(const std::string& string)
+ : mString(string)
+ { }
+
+protected:
+ virtual EStatus process_impl(
+ const LLChannelDescriptors& channels,
+ buffer_ptr_t& buffer,
+ bool& eos,
+ LLSD& context,
+ LLPumpIO* pump);
+
+private:
+ std::string mString;
+};
+
+
+class LLPipeStringExtractor : public LLIOPipe
+{
+public:
+ LLPipeStringExtractor() : mDone(false) { }
+
+ bool done() { return mDone; }
+ std::string string() { return mString; }
+
+protected:
+ // LLIOPipe API implementation.
+ virtual EStatus process_impl(
+ const LLChannelDescriptors& channels,
+ LLIOPipe::buffer_ptr_t& buffer,
+ bool& eos,
+ LLSD& context,
+ LLPumpIO* pump);
+
+private:
+ bool mDone;
+ std::string mString;
+};
+
+/**
+ * @brief Generate a specified number of bytes of random data
+ */
+class LLIOFuzz : public LLIOPipe
+{
+public:
+ LLIOFuzz(int byte_count) : mByteCount(byte_count) {}
+
+protected:
+ virtual EStatus process_impl(
+ const LLChannelDescriptors& channels,
+ buffer_ptr_t& buffer,
+ bool& eos,
+ LLSD& context,
+ LLPumpIO* pump);
+
+private:
+ int mByteCount;
+};
+
+/**
+ * @brief Generate some ascii fuz
+ */
+class LLIOASCIIFuzz : public LLIOPipe
+{
+public:
+ LLIOASCIIFuzz(int byte_count) : mByteCount(byte_count) {}
+
+protected:
+ virtual EStatus process_impl(
+ const LLChannelDescriptors& channels,
+ buffer_ptr_t& buffer,
+ bool& eos,
+ LLSD& context,
+ LLPumpIO* pump);
+
+private:
+ int mByteCount;
+};
+
+
+/**
+ * @brief Pipe that does nothing except return STATUS_OK
+ */
+class LLIONull : public LLIOPipe
+{
+public:
+ LLIONull() {}
+
+protected:
+ virtual EStatus process_impl(
+ const LLChannelDescriptors& channels,
+ buffer_ptr_t& buffer,
+ bool& eos,
+ LLSD& context,
+ LLPumpIO* pump);
+};
+
+/**
+ * @brief Pipe that sleeps, and then responds later.
+ */
+class LLIOSleeper : public LLIOPipe
+{
+public:
+ LLIOSleeper() : mRespond(false) {}
+
+protected:
+ virtual EStatus process_impl(
+ const LLChannelDescriptors& channels,
+ buffer_ptr_t& buffer,
+ bool& eos,
+ LLSD& context,
+ LLPumpIO* pump);
+private:
+ bool mRespond;
+
+};
+
+#endif // LL_LLPIPEUTIL_H
diff --git a/indra/llmessage/tests/llsdmessagebuilder_test.cpp b/indra/llmessage/tests/llsdmessagebuilder_test.cpp
new file mode 100644
index 0000000000..6804c3e29e
--- /dev/null
+++ b/indra/llmessage/tests/llsdmessagebuilder_test.cpp
@@ -0,0 +1,837 @@
+/**
+ * @file llsdmessagebuilder_tut.cpp
+ * @date February 2006
+ * @brief LLSDMessageBuilder unit tests
+ *
+ * $LicenseInfo:firstyear=2006&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include <tut/tut.hpp>
+
+#include "linden_common.h"
+#include "lltut.h"
+#include "llmessagetemplate.h"
+#include "llsdmessagebuilder.h"
+#include "llsdmessagereader.h"
+#include "llsdtraits.h"
+#include "llmath.h"
+#include "llquaternion.h"
+#include "u64.h"
+#include "v3dmath.h"
+#include "v3math.h"
+#include "v4math.h"
+#include "llsdutil.h"
+//#include "llsdutil.cpp"
+#include "llsdutil_math.cpp"
+#include "lltemplatemessagebuilder.h"
+
+namespace tut
+{
+ static LLTemplateMessageBuilder::message_template_name_map_t templateNameMap;
+
+ LLMsgData* messageData = NULL;
+ LLMsgBlkData* messageBlockData = NULL;
+
+ struct LLSDMessageBuilderTestData {
+
+ LLSDMessageBuilderTestData()
+ {
+ messageData = new LLMsgData("testMessage");
+ messageBlockData = new LLMsgBlkData("testBlock", 0);
+ }
+
+ static LLSDMessageBuilder defaultBuilder()
+ {
+ LLSDMessageBuilder builder;
+ builder.newMessage("name");
+ builder.nextBlock("block");
+ return builder;
+ }
+
+ static LLSDMessageReader setReader(const LLSDMessageBuilder& builder)
+ {
+ LLSDMessageReader reader;
+ reader.setMessage("name", builder.getMessage());
+ return reader;
+ }
+
+ static void addValue(LLMsgBlkData* mbd, char* name, void* v, EMsgVariableType type, int size, int data_size = -1)
+ {
+ LLMsgVarData tmp(name, type);
+ tmp.addData(v, size, type, data_size);
+ mbd->mMemberVarData[name] = tmp;
+ }
+
+
+ static LLMessageBlock* defaultTemplateBlock(const EMsgVariableType type = MVT_NULL, const S32 size = 0, EMsgBlockType block = MBT_VARIABLE)
+ {
+ return createTemplateBlock(_PREHASH_Test0, type, size, block);
+ }
+
+ static LLMessageBlock* createTemplateBlock(const char* name, const EMsgVariableType type = MVT_NULL, const S32 size = 0, EMsgBlockType block = MBT_VARIABLE)
+ {
+ LLMessageBlock* result = new LLMessageBlock(name, block);
+ if(type != MVT_NULL)
+ {
+ result->addVariable(const_cast<char*>(_PREHASH_Test0), type, size);
+ }
+ return result;
+ }
+
+ static LLTemplateMessageBuilder* defaultTemplateBuilder(LLMessageTemplate& messageTemplate, char* name = const_cast<char*>(_PREHASH_Test0))
+ {
+ templateNameMap[_PREHASH_TestMessage] = &messageTemplate;
+ LLTemplateMessageBuilder* builder = new LLTemplateMessageBuilder(templateNameMap);
+ builder->newMessage(_PREHASH_TestMessage);
+ builder->nextBlock(name);
+ return builder;
+ }
+
+ static LLMessageTemplate defaultTemplate()
+ {
+ return LLMessageTemplate(_PREHASH_TestMessage, 1, MFT_HIGH);
+ }
+ };
+
+ typedef test_group<LLSDMessageBuilderTestData> LLSDMessageBuilderTestGroup;
+ typedef LLSDMessageBuilderTestGroup::object LLSDMessageBuilderTestObject;
+ LLSDMessageBuilderTestGroup llsdMessageBuilderTestGroup("LLSDMessageBuilder");
+
+ template<> template<>
+ void LLSDMessageBuilderTestObject::test<1>()
+ // construction and test of undefined
+ {
+ LLSDMessageBuilder builder = defaultBuilder();
+ LLSDMessageReader reader = setReader(builder);
+ }
+
+ template<> template<>
+ void LLSDMessageBuilderTestObject::test<2>()
+ // bool
+ {
+ bool outValue, inValue = true;
+ LLSDMessageBuilder builder = defaultBuilder();
+ builder.addBOOL("var", inValue);
+ LLSDMessageReader reader = setReader(builder);
+ reader.getBOOL("block", "var", outValue);
+ ensure_equals("Ensure bool", inValue, outValue);
+ }
+
+ template<> template<>
+ void LLSDMessageBuilderTestObject::test<3>()
+ // U8
+ {
+ U8 outValue, inValue = 2;
+ LLSDMessageBuilder builder = defaultBuilder();
+ builder.addU8("var", inValue);
+ LLSDMessageReader reader = setReader(builder);
+ reader.getU8("block", "var", outValue);
+ ensure_equals("Ensure U8", inValue, outValue);
+ }
+
+ template<> template<>
+ void LLSDMessageBuilderTestObject::test<4>()
+ // S16
+ {
+ S16 outValue, inValue = 90;
+ LLSDMessageBuilder builder = defaultBuilder();
+ builder.addS16("var", inValue);
+ LLSDMessageReader reader = setReader(builder);
+ reader.getS16("block", "var", outValue);
+ ensure_equals("Ensure S16", inValue, outValue);
+ }
+
+ template<> template<>
+ void LLSDMessageBuilderTestObject::test<5>()
+ // U16
+ {
+ U16 outValue, inValue = 3;
+ LLSDMessageBuilder builder = defaultBuilder();
+ builder.addU16("var", inValue);
+ LLSDMessageReader reader = setReader(builder);
+ reader.getU16("block", "var", outValue);
+ ensure_equals("Ensure U16", inValue, outValue);
+ }
+
+ template<> template<>
+ void LLSDMessageBuilderTestObject::test<6>()
+ // S32
+ {
+ S32 outValue, inValue = 44;
+ LLSDMessageBuilder builder = defaultBuilder();
+ builder.addS32("var", inValue);
+ LLSDMessageReader reader = setReader(builder);
+ reader.getS32("block", "var", outValue);
+ ensure_equals("Ensure S32", inValue, outValue);
+ }
+
+ template<> template<>
+ void LLSDMessageBuilderTestObject::test<7>()
+ // F32
+ {
+ F32 outValue, inValue = 121.44f;
+ LLSDMessageBuilder builder = defaultBuilder();
+ builder.addF32("var", inValue);
+ LLSDMessageReader reader = setReader(builder);
+ reader.getF32("block", "var", outValue);
+ ensure_equals("Ensure F32", inValue, outValue);
+ }
+
+ template<> template<>
+ void LLSDMessageBuilderTestObject::test<8>()
+ // U32
+ {
+ U32 outValue, inValue = 88;
+ LLSDMessageBuilder builder = defaultBuilder();
+ builder.addU32("var", inValue);
+ LLSDMessageReader reader = setReader(builder);
+ reader.getU32("block", "var", outValue);
+ ensure_equals("Ensure U32", inValue, outValue);
+ }
+
+ template<> template<>
+ void LLSDMessageBuilderTestObject::test<9>()
+ // U64
+ {
+ U64 outValue, inValue = 121;
+ LLSDMessageBuilder builder = defaultBuilder();
+ builder.addU64("var", inValue);
+ LLSDMessageReader reader = setReader(builder);
+ reader.getU64("block", "var", outValue);
+ ensure_equals("Ensure U64", inValue, outValue);
+ }
+
+ template<> template<>
+ void LLSDMessageBuilderTestObject::test<10>()
+ // F64
+ {
+ F64 outValue, inValue = 3232143.33;
+ LLSDMessageBuilder builder = defaultBuilder();
+ builder.addF64("var", inValue);
+ LLSDMessageReader reader = setReader(builder);
+ reader.getF64("block", "var", outValue);
+ ensure_equals("Ensure F64", inValue, outValue);
+ }
+
+ template<> template<>
+ void LLSDMessageBuilderTestObject::test<11>()
+ // Vector3
+ {
+ LLVector3 outValue, inValue = LLVector3(1,2,3);
+ LLSDMessageBuilder builder = defaultBuilder();
+ builder.addVector3("var", inValue);
+ LLSDMessageReader reader = setReader(builder);
+ reader.getVector3("block", "var", outValue);
+ ensure_equals("Ensure Vector3", inValue, outValue);
+ }
+
+ template<> template<>
+ void LLSDMessageBuilderTestObject::test<12>()
+ // Vector4
+ {
+ LLVector4 outValue, inValue = LLVector4(1,2,3,4);
+ LLSDMessageBuilder builder = defaultBuilder();
+ builder.addVector4("var", inValue);
+ LLSDMessageReader reader = setReader(builder);
+ reader.getVector4("block", "var", outValue);
+ ensure_equals("Ensure Vector4", inValue, outValue);
+ }
+
+ template<> template<>
+ void LLSDMessageBuilderTestObject::test<13>()
+ // Vector3d
+ {
+ LLVector3d outValue, inValue = LLVector3d(1,2,3);
+ LLSDMessageBuilder builder = defaultBuilder();
+ builder.addVector3d("var", inValue);
+ LLSDMessageReader reader = setReader(builder);
+ reader.getVector3d("block", "var", outValue);
+ ensure_equals("Ensure Vector3d", inValue, outValue);
+ }
+
+ template<> template<>
+ void LLSDMessageBuilderTestObject::test<14>()
+ // Quaternion
+ {
+ LLQuaternion outValue, inValue = LLQuaternion(1,LLVector3(2,3,4));
+ LLSDMessageBuilder builder = defaultBuilder();
+ builder.addQuat("var", inValue);
+ LLSDMessageReader reader = setReader(builder);
+ reader.getQuat("block", "var", outValue);
+ ensure_equals("Ensure Quaternion", inValue, outValue);
+ }
+
+ template<> template<>
+ void LLSDMessageBuilderTestObject::test<15>()
+ // UUID
+ {
+ LLUUID outValue, inValue;
+ inValue.generate();
+ LLSDMessageBuilder builder = defaultBuilder();
+ builder.addUUID("var", inValue);
+ LLSDMessageReader reader = setReader(builder);
+ reader.getUUID("block", "var", outValue);
+ ensure_equals("Ensure UUID", inValue, outValue);
+ }
+
+ template<> template<>
+ void LLSDMessageBuilderTestObject::test<16>()
+ // IPAddr
+ {
+ U32 outValue, inValue = 12344556;
+ LLSDMessageBuilder builder = defaultBuilder();
+ builder.addIPAddr("var", inValue);
+ LLSDMessageReader reader = setReader(builder);
+ reader.getIPAddr("block", "var", outValue);
+ ensure_equals("Ensure IPAddr", inValue, outValue);
+ }
+
+ template<> template<>
+ void LLSDMessageBuilderTestObject::test<17>()
+ // IPPort
+ {
+ U16 outValue, inValue = 80;
+ LLSDMessageBuilder builder = defaultBuilder();
+ builder.addIPPort("var", inValue);
+ LLSDMessageReader reader = setReader(builder);
+ reader.getIPPort("block", "var", outValue);
+ ensure_equals("Ensure IPPort", inValue, outValue);
+ }
+
+ template<> template<>
+ void LLSDMessageBuilderTestObject::test<18>()
+ {
+ std::string outValue, inValue = "testing";
+ LLSDMessageBuilder builder = defaultBuilder();
+ builder.addString("var", inValue.c_str());
+ LLSDMessageReader reader = setReader(builder);
+ char buffer[MAX_STRING];
+ reader.getString("block", "var", MAX_STRING, buffer);
+ outValue = buffer;
+ ensure_equals("Ensure String", inValue, outValue);
+ }
+
+ template<> template<>
+ void LLSDMessageBuilderTestObject::test<19>()
+ {
+ LLMsgBlkData* mbd = new LLMsgBlkData("testBlock", 0);
+ LLMsgData* md = new LLMsgData("testMessage");
+ md->addBlock(mbd);
+ LLSDMessageBuilder builder = defaultBuilder();
+
+ builder.copyFromMessageData(*md);
+ LLSD output = builder.getMessage();
+
+ ensure("Ensure message block created when copied from legacy message to llsd", output["testBlock"].isDefined());
+ }
+
+ // MVT_FIXED
+ template<> template<>
+ void LLSDMessageBuilderTestObject::test<20>()
+ {
+ char binData[] = "abcdefghijklmnop";
+
+ addValue(messageBlockData, (char *)"testBinData", &binData, MVT_FIXED, sizeof(binData));
+ messageData->addBlock(messageBlockData);
+ LLSDMessageBuilder builder = defaultBuilder();
+
+ builder.copyFromMessageData(*messageData);
+ LLSD output = builder.getMessage();
+
+ std::vector<U8> v = output["testBlock"][0]["testBinData"].asBinary();
+ ensure("Ensure MVT_S16Array data copied from legacy to llsd give a valid vector", v.size() > 0);
+
+ ensure_memory_matches("Ensure fixed binary data works in a message copied from legacy to llsd",
+ &v[0], sizeof(binData), binData, sizeof(binData));
+ }
+
+ // MVT_VARIABLE data_size 1 (U8's)
+ template<> template<>
+ void LLSDMessageBuilderTestObject::test<21>()
+ {
+ /* U8 binData[] = "abcdefghijklmnop";
+
+ addValue(messageBlockData, "testBinData", &binData, MVT_VARIABLE, sizeof(binData), 1);
+ messageData->addBlock(messageBlockData);
+ LLSDMessageBuilder builder = defaultBuilder();
+
+ builder.copyFromMessageData(*messageData);
+ LLSD output = builder.getMessage();
+
+ std::vector<U8> v = output["testBlock"][0]["testBinData"].asBinary();
+ ensure("Ensure MVT_S16Array data copied from legacy to llsd give a valid vector", v.size() > 0);
+
+ ensure_memory_matches("Ensure MVT_VARIABLE U8 binary data works in a message copied from legacy to llsd",
+ &v[0], sizeof(binData), binData, sizeof(binData));*/
+ }
+
+ // MVT_VARIABLE data_size 2 (U16's)
+ template<> template<>
+ void LLSDMessageBuilderTestObject::test<22>()
+ {
+ U16 binData[] = {1,2,3,4,5,6,7,8,9}; //9 shorts
+
+ addValue(messageBlockData, (char *)"testBinData", &binData, MVT_VARIABLE, sizeof(binData) >> 1, 2);
+ messageData->addBlock(messageBlockData);
+ LLSDMessageBuilder builder = defaultBuilder();
+
+ builder.copyFromMessageData(*messageData);
+ LLSD output = builder.getMessage();
+
+ std::vector<U8> v = output["testBlock"][0]["testBinData"].asBinary();
+ ensure("Ensure MVT_S16Array data copied from legacy to llsd give a valid vector", v.size() > 0);
+
+ ensure_memory_matches("Ensure MVT_VARIABLE U16 binary data works in a message copied from legacy to llsd",
+ &v[0], sizeof(binData) >> 1, binData, sizeof(binData) >> 1);
+ }
+
+ // MVT_VARIABLE data_size 4 (S32's)
+ template<> template<>
+ void LLSDMessageBuilderTestObject::test<23>()
+ {
+ U32 binData[] = {9,8,7,6,5,4,3,2,1};
+
+ addValue(messageBlockData, (char *)"testBinData", &binData, MVT_VARIABLE, sizeof(binData) >> 2, 4);
+ messageData->addBlock(messageBlockData);
+ LLSDMessageBuilder builder = defaultBuilder();
+
+ builder.copyFromMessageData(*messageData);
+ LLSD output = builder.getMessage();
+
+ std::vector<U8> v = output["testBlock"][0]["testBinData"].asBinary();
+ ensure("Ensure MVT_S16Array data copied from legacy to llsd give a valid vector", v.size() > 0);
+
+ ensure_memory_matches("Ensure MVT_VARIABLE S32 binary data works in a message copied from legacy to llsd",
+ &v[0], sizeof(binData) >> 2, binData, sizeof(binData) >> 2);
+ }
+
+ // MVT_U8
+ template<> template<>
+ void LLSDMessageBuilderTestObject::test<24>()
+ {
+ U8 data = 0xa5;
+
+ addValue(messageBlockData, (char *)"testBinData", &data, MVT_U8, sizeof(data));
+ messageData->addBlock(messageBlockData);
+ LLSDMessageBuilder builder = defaultBuilder();
+
+ builder.copyFromMessageData(*messageData);
+ LLSD output = builder.getMessage();
+
+ ensure_equals("Ensure MVT_U8 data works in a message copied from legacy to llsd",
+ output["testBlock"][0]["testBinData"].asInteger(), data);
+ }
+
+ // MVT_U16
+ template<> template<>
+ void LLSDMessageBuilderTestObject::test<25>()
+ {
+ U16 data = 0xa55a;
+
+ addValue(messageBlockData, (char *)"testBinData", &data, MVT_U16, sizeof(data));
+ messageData->addBlock(messageBlockData);
+ LLSDMessageBuilder builder = defaultBuilder();
+
+ builder.copyFromMessageData(*messageData);
+ LLSD output = builder.getMessage();
+
+ ensure_equals("Ensure MVT_U16 data works in a message copied from legacy to llsd",
+ output["testBlock"][0]["testBinData"].asInteger(), data);
+ }
+
+ // MVT_U32
+ template<> template<>
+ void LLSDMessageBuilderTestObject::test<26>()
+ {
+ U32 data = 0xa55a7117;
+
+ addValue(messageBlockData, (char *)"testBinData", &data, MVT_U32, sizeof(data));
+ messageData->addBlock(messageBlockData);
+ LLSDMessageBuilder builder = defaultBuilder();
+
+ builder.copyFromMessageData(*messageData);
+ LLSD output = builder.getMessage();
+
+ ensure_equals("Ensure MVT_U32 data works in a message copied from legacy to llsd",
+ ll_U32_from_sd(output["testBlock"][0]["testBinData"]), data);
+ }
+
+ // MVT_U64 - crush into an s32: LLSD does not support 64 bit values
+ template<> template<>
+ void LLSDMessageBuilderTestObject::test<27>()
+ {
+ U64 data = U64L(0xa55a711711223344);
+ addValue(messageBlockData, (char *)"testBinData", &data, MVT_U64, sizeof(data));
+ messageData->addBlock(messageBlockData);
+ LLSDMessageBuilder builder = defaultBuilder();
+
+ builder.copyFromMessageData(*messageData);
+ LLSD output = builder.getMessage();
+
+ ensure_equals("Ensure MVT_U64 data works in a message copied from legacy to llsd",
+ ll_U64_from_sd(output["testBlock"][0]["testBinData"]), data);
+ }
+
+ // MVT_S8
+ template<> template<>
+ void LLSDMessageBuilderTestObject::test<28>()
+ {
+ S8 data = -31;
+
+ addValue(messageBlockData, (char *)"testBinData", &data, MVT_S8, sizeof(data));
+ messageData->addBlock(messageBlockData);
+ LLSDMessageBuilder builder = defaultBuilder();
+
+ builder.copyFromMessageData(*messageData);
+ LLSD output = builder.getMessage();
+
+ ensure_equals("Ensure MVT_S8 data works in a message copied from legacy to llsd",
+ output["testBlock"][0]["testBinData"].asInteger(), data);
+ }
+
+ // MVT_S16
+ template<> template<>
+ void LLSDMessageBuilderTestObject::test<29>()
+ {
+ S16 data = -31;
+
+ addValue(messageBlockData, (char *)"testBinData", &data, MVT_S16, sizeof(data));
+ messageData->addBlock(messageBlockData);
+ LLSDMessageBuilder builder = defaultBuilder();
+
+ builder.copyFromMessageData(*messageData);
+ LLSD output = builder.getMessage();
+
+ ensure_equals("Ensure MVT_S16 data works in a message copied from legacy to llsd",
+ output["testBlock"][0]["testBinData"].asInteger(), data);
+ }
+
+ // MVT_S32
+ template<> template<>
+ void LLSDMessageBuilderTestObject::test<30>()
+ {
+ S32 data = -3100;
+
+ addValue(messageBlockData, (char *)"testBinData", &data, MVT_S32, sizeof(data));
+ messageData->addBlock(messageBlockData);
+ LLSDMessageBuilder builder = defaultBuilder();
+
+ builder.copyFromMessageData(*messageData);
+ LLSD output = builder.getMessage();
+
+ ensure_equals("Ensure MVT_S32 data works in a message copied from legacy to llsd",
+ output["testBlock"][0]["testBinData"].asInteger(), data);
+ }
+
+ // MVT_S64 - crush into an s32: LLSD does not support 64 bit values
+ template<> template<>
+ void LLSDMessageBuilderTestObject::test<31>()
+ {
+ S64 data = -31003100;
+
+ addValue(messageBlockData, (char *)"testBinData", &data, MVT_S64, sizeof(data));
+ messageData->addBlock(messageBlockData);
+ LLSDMessageBuilder builder = defaultBuilder();
+
+ builder.copyFromMessageData(*messageData);
+ LLSD output = builder.getMessage();
+
+ ensure_equals("Ensure MVT_S64 data works in a message copied from legacy to llsd",
+ output["testBlock"][0]["testBinData"].asInteger(), (S32)data);
+ }
+
+ // MVT_F32
+ template<> template<>
+ void LLSDMessageBuilderTestObject::test<32>()
+ {
+ F32 data = 1234.1234f;
+
+ addValue(messageBlockData, (char *)"testBinData", &data, MVT_F32, sizeof(data));
+ messageData->addBlock(messageBlockData);
+ LLSDMessageBuilder builder = defaultBuilder();
+
+ builder.copyFromMessageData(*messageData);
+ LLSD output = builder.getMessage();
+
+ ensure_equals("Ensure MVT_F32 data works in a message copied from legacy to llsd",
+ output["testBlock"][0]["testBinData"].asReal(), data);
+ }
+
+ // MVT_F64
+ template<> template<>
+ void LLSDMessageBuilderTestObject::test<33>()
+ {
+ F64 data = 1234.1234;
+
+ addValue(messageBlockData, (char *)"testBinData", &data, MVT_F64, sizeof(data));
+ messageData->addBlock(messageBlockData);
+ LLSDMessageBuilder builder = defaultBuilder();
+
+ builder.copyFromMessageData(*messageData);
+ LLSD output = builder.getMessage();
+
+ ensure_equals("Ensure MVT_F64 data works in a message copied from legacy to llsd",
+ output["testBlock"][0]["testBinData"].asReal(), data);
+ }
+
+ // MVT_LLVector3
+ template<> template<>
+ void LLSDMessageBuilderTestObject::test<34>()
+ {
+ LLVector3 data(1,2,3);
+
+ addValue(messageBlockData, (char *)"testBinData", &data, MVT_LLVector3, sizeof(data));
+ messageData->addBlock(messageBlockData);
+ LLSDMessageBuilder builder = defaultBuilder();
+
+ builder.copyFromMessageData(*messageData);
+ LLSD output = builder.getMessage();
+
+ ensure_equals("Ensure MVT_LLVector3 data works in a message copied from legacy to llsd",
+ ll_vector3_from_sd(output["testBlock"][0]["testBinData"]), data);
+ }
+
+ // MVT_LLVector3d
+ template<> template<>
+ void LLSDMessageBuilderTestObject::test<35>()
+ {
+ LLVector3d data(1,2,3);
+
+ addValue(messageBlockData, (char *)"testBinData", &data, MVT_LLVector3d, sizeof(data));
+ messageData->addBlock(messageBlockData);
+ LLSDMessageBuilder builder = defaultBuilder();
+
+ builder.copyFromMessageData(*messageData);
+ LLSD output = builder.getMessage();
+
+ ensure_equals("Ensure MVT_LLVector3 data works in a message copied from legacy to llsd",
+ ll_vector3d_from_sd(output["testBlock"][0]["testBinData"]), data);
+ }
+
+ // MVT_LLVector4
+ template<> template<>
+ void LLSDMessageBuilderTestObject::test<36>()
+ {
+ LLVector4 data(1,2,3,4);
+ LLSD v = ll_sd_from_vector4(data);
+
+ addValue(messageBlockData, (char *)"testBinData", &data, MVT_LLVector4, sizeof(data));
+ messageData->addBlock(messageBlockData);
+ LLSDMessageBuilder builder = defaultBuilder();
+
+ builder.copyFromMessageData(*messageData);
+ LLSD output = builder.getMessage();
+
+ ensure_equals("Ensure MVT_LLVector4 data works in a message copied from legacy to llsd",
+ output["testBlock"][0]["testBinData"], v);
+ }
+
+ // MVT_LLQuaternion
+ template<> template<>
+ void LLSDMessageBuilderTestObject::test<37>()
+ {
+ LLQuaternion data(0.3713907f, 0.5570861f, 0.7427813f,0.0f);
+
+ //we send a quaternion packed into a vec3 (w is infered) - so sizeof(vec) == 12 bytes not 16.
+ LLVector3 vec = data.packToVector3();
+
+ addValue(messageBlockData, (char *)"testBinData", &vec, MVT_LLQuaternion, sizeof(vec));
+ messageData->addBlock(messageBlockData);
+ LLSDMessageBuilder builder = defaultBuilder();
+
+ builder.copyFromMessageData(*messageData);
+ LLSD output = builder.getMessage();
+
+ ensure_equals("Ensure MVT_LLQuaternion data works in a message copied from legacy to llsd",
+ ll_quaternion_from_sd(output["testBlock"][0]["testBinData"]), data);
+ }
+
+ // MVT_LLUUID
+ template<> template<>
+ void LLSDMessageBuilderTestObject::test<38>()
+ {
+ LLUUID data("01234567-0123-0123-0123-234567abcdef");
+
+ addValue(messageBlockData, (char *)"testBinData", &data, MVT_LLUUID, sizeof(data));
+ messageData->addBlock(messageBlockData);
+ LLSDMessageBuilder builder = defaultBuilder();
+
+ builder.copyFromMessageData(*messageData);
+ LLSD output = builder.getMessage();
+
+ std::string v = output["testBlock"][0]["testBinData"].asUUID().asString();
+
+ ensure_equals("Ensure MVT_LLUUID data works in a message copied from legacy to llsd",
+ output["testBlock"][0]["testBinData"].asUUID(), data);
+ }
+
+ // MVT_BOOL
+ template<> template<>
+ void LLSDMessageBuilderTestObject::test<39>()
+ {
+ bool valueTrue = true;
+ bool valueFalse = false;
+
+ LLMsgData* md = new LLMsgData("testMessage");
+ LLMsgBlkData* mbd = new LLMsgBlkData("testBlock", 0);
+ addValue(mbd, (char *)"testBoolFalse", &valueFalse, MVT_BOOL, sizeof(bool));
+ addValue(mbd, (char *)"testBoolTrue", &valueTrue, MVT_BOOL, sizeof(bool));
+ md->addBlock(mbd);
+ LLSDMessageBuilder builder = defaultBuilder();
+
+ builder.copyFromMessageData(*md);
+ LLSD output = builder.getMessage();
+
+ ensure("Ensure bools work in a message copied from legacy to llsd",
+ output["testBlock"][0]["testBoolTrue"].asBoolean() && !output["testBlock"][0]["testBoolFalse"].asBoolean());
+ }
+
+ // MVT_IP_ADDR
+ template<> template<>
+ void LLSDMessageBuilderTestObject::test<40>()
+ {
+ U32 data(0xff887766);
+ LLSD v = ll_sd_from_ipaddr(data);
+
+ addValue(messageBlockData, (char *)"testBinData", &data, MVT_IP_ADDR, sizeof(data));
+ messageData->addBlock(messageBlockData);
+ LLSDMessageBuilder builder = defaultBuilder();
+
+ builder.copyFromMessageData(*messageData);
+ LLSD output = builder.getMessage();
+
+ ensure_equals("Ensure MVT_IP_ADDR data works in a message copied from legacy to llsd",
+ output["testBlock"][0]["testBinData"], v);
+ }
+
+ // MVT_IP_PORT
+ template<> template<>
+ void LLSDMessageBuilderTestObject::test<41>()
+ {
+ U16 data = 0xff88;
+
+ addValue(messageBlockData, (char *)"testBinData", &data, MVT_IP_PORT, sizeof(data));
+ messageData->addBlock(messageBlockData);
+ LLSDMessageBuilder builder = defaultBuilder();
+
+ builder.copyFromMessageData(*messageData);
+ LLSD output = builder.getMessage();
+
+ ensure_equals("Ensure MVT_IP_PORT data works in a message copied from legacy to llsd",
+ output["testBlock"][0]["testBinData"].asInteger(), data);
+ }
+
+ // MVT_U16Vec3
+ template<> template<>
+ void LLSDMessageBuilderTestObject::test<42>()
+ {
+ U16 data[3] = {0,1,2};
+
+ addValue(messageBlockData, (char *)"testBinData", &data, MVT_U16Vec3, sizeof(data));
+ messageData->addBlock(messageBlockData);
+ LLSDMessageBuilder builder = defaultBuilder();
+
+ builder.copyFromMessageData(*messageData);
+ LLSD output = builder.getMessage();
+
+ std::vector<U8> v = output["testBlock"][0]["testBinData"].asBinary();
+ ensure("Ensure MVT_U16Vec3 data copied from legacy to llsd give a valid vector", v.size() > 0);
+
+ ensure_memory_matches("Ensure MVT_U16Vec3 data works in a message copied from legacy to llsd",
+ (U16*)&v[0], 6, data, 6);
+ }
+
+ // MVT_U16Quat
+ template<> template<>
+ void LLSDMessageBuilderTestObject::test<43>()
+ {
+ U16 data[4] = {0,1,2,4};
+
+ addValue(messageBlockData, (char *)"testBinData", &data, MVT_U16Quat, sizeof(data));
+ messageData->addBlock(messageBlockData);
+ LLSDMessageBuilder builder = defaultBuilder();
+
+ builder.copyFromMessageData(*messageData);
+ LLSD output = builder.getMessage();
+
+ std::vector<U8> v = output["testBlock"][0]["testBinData"].asBinary();
+ ensure("Ensure MVT_U16Quat data copied from legacy to llsd give a valid vector", v.size() > 0);
+
+ ensure_memory_matches("Ensure MVT_U16Quat data works in a message copied from legacy to llsd",
+ (U16*)&v[0], 8, data, 8);
+ }
+
+ // MVT_S16Array
+ template<> template<>
+ void LLSDMessageBuilderTestObject::test<44>()
+ {
+ S16 data[19] = {0,-1,2,-4,5,-6,7,-8,9,-10,11,-12,13,-14,15,16,17,18};
+
+ addValue(messageBlockData, (char *)"testBinData", &data, MVT_S16Array, sizeof(data));
+ messageData->addBlock(messageBlockData);
+ LLSDMessageBuilder builder = defaultBuilder();
+
+ builder.copyFromMessageData(*messageData);
+ LLSD output = builder.getMessage();
+
+ std::vector<U8> v = output["testBlock"][0]["testBinData"].asBinary();
+ ensure("Ensure MVT_S16Array data copied from legacy to llsd give a valid vector", v.size() > 0);
+
+ ensure_memory_matches("Ensure MVT_S16Array data works in a message copied from legacy to llsd",
+ (U16*)&v[0], 19, data, 19);
+ }
+
+ template<> template<>
+ void LLSDMessageBuilderTestObject::test<45>()
+ {
+ LLMessageTemplate messageTemplate = defaultTemplate();
+ messageTemplate.addBlock(defaultTemplateBlock(MVT_U8, 1));
+ U8 inValue = 2;
+ LLTemplateMessageBuilder* template_builder = defaultTemplateBuilder(messageTemplate);
+ template_builder->addU8(_PREHASH_Test0, inValue);
+
+ LLSDMessageBuilder builder;
+ builder.copyFromMessageData(*template_builder->getCurrentMessage());
+ LLSD output = builder.getMessage();
+
+ ensure_equals(output["Test0"][0]["Test0"].asInteger(), 2);
+
+ }
+
+ template<> template<>
+ void LLSDMessageBuilderTestObject::test<46>()
+ {
+ LLMessageTemplate messageTemplate = defaultTemplate();
+ messageTemplate.addBlock(defaultTemplateBlock(MVT_VARIABLE, 1));
+ std::string inValue = "testing";
+ LLTemplateMessageBuilder* builder = defaultTemplateBuilder(messageTemplate);
+ builder->addString(_PREHASH_Test0, inValue.c_str());
+
+ LLSDMessageBuilder sd_builder;
+ sd_builder.copyFromMessageData(*builder->getCurrentMessage());
+ LLSD output = sd_builder.getMessage();
+
+ ensure_equals(output["Test0"][0]["Test0"].asString(), std::string("testing"));
+ }
+
+}
+
diff --git a/indra/llmessage/tests/llsdmessagereader_test.cpp b/indra/llmessage/tests/llsdmessagereader_test.cpp
new file mode 100644
index 0000000000..dd6520ea33
--- /dev/null
+++ b/indra/llmessage/tests/llsdmessagereader_test.cpp
@@ -0,0 +1,324 @@
+/**
+ * @file llsdmessagereader_tut.cpp
+ * @date February 2006
+ * @brief LLSDMessageReader unit tests
+ *
+ * $LicenseInfo:firstyear=2006&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include <tut/tut.hpp>
+#include "linden_common.h"
+#include "lltut.h"
+#include "v3dmath.h"
+#include "v3math.h"
+#include "v4math.h"
+#include "llquaternion.h"
+
+#include "message.h"
+#include "llsdmessagereader.h"
+#include "llsdutil.h"
+#include "llsdutil_math.h"
+
+namespace tut
+{
+ struct LLSDMessageReaderTestData {
+ static void ensureMessageName(const std::string& msg_name,
+ const LLSD& msg_data,
+ const std::string& expected_name)
+ {
+ LLSDMessageReader msg;
+ msg.setMessage(LLMessageStringTable::getInstance()->getString(msg_name.c_str()), msg_data);
+ ensure_equals("Ensure name", std::string(msg.getMessageName()),
+ expected_name);
+ }
+
+ static void ensureNumberOfBlocks(const LLSD& msg_data,
+ const std::string& block,
+ S32 expected_number)
+ {
+ LLSDMessageReader msg;
+ msg.setMessage("fakename", msg_data);
+ ensure_equals("Ensure number of blocks", msg.getNumberOfBlocks(block.c_str()),
+ expected_number);
+ }
+
+ static void ensureMessageSize(const LLSD& msg_data,
+ S32 expected_size)
+ {
+ LLSDMessageReader msg;
+ msg.setMessage("fakename", msg_data);
+ ensure_equals( "Ensure size", msg.getMessageSize(), expected_size);
+ }
+
+ static void ensureBool(const LLSD& msg_data,
+ const std::string& block,
+ const std::string& var,
+ S32 blocknum,
+ bool expected)
+ {
+ LLSDMessageReader msg;
+ msg.setMessage("fakename", msg_data);
+ bool test_data;
+ msg.getBOOL(block.c_str(), var.c_str(), test_data, blocknum);
+ ensure_equals( "Ensure bool field", test_data, expected);
+ }
+ };
+
+ typedef test_group<LLSDMessageReaderTestData> LLSDMessageReaderTestGroup;
+ typedef LLSDMessageReaderTestGroup::object LLSDMessageReaderTestObject;
+ LLSDMessageReaderTestGroup llsdMessageReaderTestGroup("LLSDMessageReader");
+
+ template<> template<>
+ void LLSDMessageReaderTestObject::test<1>()
+ // construction and test of empty LLSD
+ {
+ LLSD message = LLSD::emptyMap();
+
+ ensureMessageName("", message, "");
+ ensureNumberOfBlocks(message, "Fakeblock", 0);
+ ensureMessageSize(message, 0);
+ }
+
+ template<> template<>
+ void LLSDMessageReaderTestObject::test<2>()
+ // construction and test of simple message with one block
+ {
+ LLSD message = LLSD::emptyMap();
+ message["block1"] = LLSD::emptyArray();
+ message["block1"][0] = LLSD::emptyMap();
+ message["block1"][0]["Field1"] = 0;
+
+ ensureMessageName("name2", message, "name2");
+ ensureNumberOfBlocks(message, "block1", 1);
+ ensureMessageSize(message, 0);
+ }
+
+ template<> template<>
+ void LLSDMessageReaderTestObject::test<3>()
+ // multiple blocks
+ {
+ LLSD message = LLSD::emptyMap();
+ message["block1"] = LLSD::emptyArray();
+ bool bool_true = true;
+ bool bool_false = false;
+ message["block1"][0] = LLSD::emptyMap();
+ message["block1"][0]["BoolField1"] = bool_true;
+ message["block1"][1] = LLSD::emptyMap();
+ message["block1"][1]["BoolField1"] = bool_false;
+ message["block1"][1]["BoolField2"] = bool_true;
+
+ ensureMessageName("name3", message, "name3");
+ ensureBool(message, "block1", "BoolField1", 0, true);
+ ensureBool(message, "block1", "BoolField1", 1, false);
+ ensureBool(message, "block1", "BoolField2", 1, true);
+ ensureNumberOfBlocks(message, "block1", 2);
+ ensureMessageSize(message, 0);
+ }
+
+ template<typename T>
+ LLSDMessageReader testType(const T& value)
+ {
+ LLSD message = LLSD::emptyMap();
+ message["block"][0]["var"] = value;
+ LLSDMessageReader msg;
+ msg.setMessage("fakename", message);
+ return msg;
+ }
+
+ template<> template<>
+ void LLSDMessageReaderTestObject::test<4>()
+ // S8
+ {
+ S8 outValue, inValue = -3;
+ LLSDMessageReader msg = testType(inValue);
+ msg.getS8("block", "var", outValue);
+ ensure_equals("Ensure S8", outValue, inValue);
+ }
+ template<> template<>
+ void
+ LLSDMessageReaderTestObject::test<5>()
+ // U8
+ {
+ U8 outValue, inValue = 2;
+ LLSDMessageReader msg = testType(inValue);
+ msg.getU8("block", "var", outValue);
+ ensure_equals("Ensure U8", outValue, inValue);
+ }
+ template<> template<>
+ void LLSDMessageReaderTestObject::test<6>()
+ // S16
+ {
+ S16 outValue, inValue = 90;
+ LLSDMessageReader msg = testType(inValue);
+ msg.getS16("block", "var", outValue);
+ ensure_equals("Ensure S16", outValue, inValue);
+ }
+ template<> template<>
+ void LLSDMessageReaderTestObject::test<7>()
+ // U16
+ {
+ U16 outValue, inValue = 3;
+ LLSDMessageReader msg = testType(inValue);
+ msg.getU16("block", "var", outValue);
+ ensure_equals("Ensure S16", outValue, inValue);
+ }
+ template<> template<>
+ void LLSDMessageReaderTestObject::test<8>()
+ // S32
+ {
+ S32 outValue, inValue = 44;
+ LLSDMessageReader msg = testType(inValue);
+ msg.getS32("block", "var", outValue);
+ ensure_equals("Ensure S32", outValue, inValue);
+ }
+ template<> template<>
+ void LLSDMessageReaderTestObject::test<9>()
+ // F32
+ {
+ F32 outValue, inValue = 121.44f;
+ LLSDMessageReader msg = testType(inValue);
+ msg.getF32("block", "var", outValue);
+ ensure_equals("Ensure F32", outValue, inValue);
+ }
+ template<> template<>
+ void LLSDMessageReaderTestObject::test<10>()
+ // U32
+ {
+ U32 outValue, inValue = 88;
+ LLSD sdValue = ll_sd_from_U32(inValue);
+ LLSDMessageReader msg = testType(sdValue);
+ msg.getU32("block", "var", outValue);
+ ensure_equals("Ensure U32", outValue, inValue);
+ }
+ template<> template<>
+ void LLSDMessageReaderTestObject::test<11>()
+ // U64
+ {
+ U64 outValue, inValue = 121;
+ LLSD sdValue = ll_sd_from_U64(inValue);
+ LLSDMessageReader msg = testType(sdValue);
+ msg.getU64("block", "var", outValue);
+ ensure_equals("Ensure U64", outValue, inValue);
+ }
+ template<> template<>
+ void LLSDMessageReaderTestObject::test<12>()
+ // F64
+ {
+ F64 outValue, inValue = 3232143.33;
+ LLSDMessageReader msg = testType(inValue);
+ msg.getF64("block", "var", outValue);
+ ensure_equals("Ensure F64", outValue, inValue);
+ }
+ template<> template<>
+ void LLSDMessageReaderTestObject::test<13>()
+ // String
+ {
+ std::string outValue, inValue = "testing";
+ LLSDMessageReader msg = testType<std::string>(inValue.c_str());
+
+ char buffer[MAX_STRING];
+ msg.getString("block", "var", MAX_STRING, buffer);
+ outValue = buffer;
+ ensure_equals("Ensure String", outValue, inValue);
+ }
+ template<> template<>
+ void LLSDMessageReaderTestObject::test<14>()
+ // Vector3
+ {
+ LLVector3 outValue, inValue = LLVector3(1,2,3);
+ LLSD sdValue = ll_sd_from_vector3(inValue);
+ LLSDMessageReader msg = testType(sdValue);
+ msg.getVector3("block", "var", outValue);
+ ensure_equals("Ensure Vector3", outValue, inValue);
+ }
+ template<> template<>
+ void LLSDMessageReaderTestObject::test<15>()
+ // Vector4
+ {
+ LLVector4 outValue, inValue = LLVector4(1,2,3,4);
+ LLSD sdValue = ll_sd_from_vector4(inValue);
+ LLSDMessageReader msg = testType(sdValue);
+ msg.getVector4("block", "var", outValue);
+ ensure_equals("Ensure Vector4", outValue, inValue);
+ }
+ template<> template<>
+ void LLSDMessageReaderTestObject::test<16>()
+ // Vector3d
+ {
+ LLVector3d outValue, inValue = LLVector3d(1,2,3);
+ LLSD sdValue = ll_sd_from_vector3d(inValue);
+ LLSDMessageReader msg = testType(sdValue);
+ msg.getVector3d("block", "var", outValue);
+ ensure_equals("Ensure Vector3d", outValue, inValue);
+ }
+ template<> template<>
+ void LLSDMessageReaderTestObject::test<17>()
+ // Quaternion
+ {
+ LLQuaternion outValue, inValue = LLQuaternion(1,LLVector3(2,3,4));
+ LLSD sdValue = ll_sd_from_quaternion(inValue);
+ LLSDMessageReader msg = testType(sdValue);
+ msg.getQuat("block", "var", outValue);
+ ensure_equals("Ensure Quaternion", outValue, inValue);
+ }
+ template<> template<>
+ void LLSDMessageReaderTestObject::test<18>()
+ // UUID
+ {
+ LLUUID outValue, inValue;
+ inValue.generate();
+ LLSDMessageReader msg = testType(inValue);
+ msg.getUUID("block", "var", outValue);
+ ensure_equals("Ensure UUID", outValue, inValue);
+ }
+ template<> template<>
+ void LLSDMessageReaderTestObject::test<19>()
+ // IPAddr
+ {
+ U32 outValue, inValue = 12344556;
+ LLSD sdValue = ll_sd_from_ipaddr(inValue);
+ LLSDMessageReader msg = testType(sdValue);
+ msg.getIPAddr("block", "var", outValue);
+ ensure_equals("Ensure IPAddr", outValue, inValue);
+ }
+ template<> template<>
+ void LLSDMessageReaderTestObject::test<20>()
+ // IPPort
+ {
+ U16 outValue, inValue = 80;
+ LLSDMessageReader msg = testType(inValue);
+ msg.getIPPort("block", "var", outValue);
+ ensure_equals("Ensure IPPort", outValue, inValue);
+ }
+ template<> template<>
+ void LLSDMessageReaderTestObject::test<21>()
+ // Binary
+ {
+ std::vector<U8> outValue(2), inValue(2);
+ inValue[0] = 0;
+ inValue[1] = 1;
+
+ LLSDMessageReader msg = testType(inValue);
+ msg.getBinaryData("block", "var", &(outValue[0]), static_cast<S32>(inValue.size()));
+ ensure_equals("Ensure Binary", outValue, inValue);
+ }
+}
diff --git a/indra/llmessage/tests/llservicebuilder_test.cpp b/indra/llmessage/tests/llservicebuilder_test.cpp
new file mode 100644
index 0000000000..0bc17865d6
--- /dev/null
+++ b/indra/llmessage/tests/llservicebuilder_test.cpp
@@ -0,0 +1,173 @@
+/**
+* @file llservicebuilder_tut.cpp
+* @brief LLServiceBuilder unit tests
+* @date March 2007
+*
+* $LicenseInfo:firstyear=2006&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2010, Linden Research, Inc.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation;
+* version 2.1 of the License only.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*
+* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+* $/LicenseInfo$
+*/
+
+#include <tut/tut.hpp>
+
+#include "linden_common.h"
+#include "lltut.h"
+#include "llsd.h"
+#include "llservicebuilder.h"
+
+namespace tut
+{
+
+ struct ServiceBuilderTestData {
+ LLServiceBuilder mServiceBuilder;
+ };
+
+ typedef test_group<ServiceBuilderTestData> ServiceBuilderTestGroup;
+ typedef ServiceBuilderTestGroup::object ServiceBuilderTestObject;
+
+ ServiceBuilderTestGroup serviceBuilderTestGroup("ServiceBuilder");
+
+ template<> template<>
+ void ServiceBuilderTestObject::test<1>()
+ {
+ //Simple service build and reply with no mapping
+ LLSD test_block;
+ test_block["service-builder"] = "/agent/name";
+ mServiceBuilder.createServiceDefinition("ServiceBuilderTest", test_block["service-builder"]);
+ std::string test_url = mServiceBuilder.buildServiceURI("ServiceBuilderTest");
+ ensure_equals("Basic URL Creation", test_url , "/agent/name");
+ }
+
+ template<> template<>
+ void ServiceBuilderTestObject::test<2>()
+ {
+ //Simple replace test
+ LLSD test_block;
+ test_block["service-builder"] = "/agent/{$agent-id}/name";
+ mServiceBuilder.createServiceDefinition("ServiceBuilderTest", test_block["service-builder"]);
+ LLSD data_map;
+ data_map["agent-id"] = "257c631f-a0c5-4f29-8a9f-9031feaae6c6";
+ std::string test_url = mServiceBuilder.buildServiceURI("ServiceBuilderTest", data_map);
+ ensure_equals("Replacement URL Creation", test_url , "/agent/257c631f-a0c5-4f29-8a9f-9031feaae6c6/name");
+ }
+
+ template<> template<>
+ void ServiceBuilderTestObject::test<3>()
+ {
+ //Incorrect service test
+ LLSD test_block;
+ test_block["service-builder"] = "/agent/{$agent-id}/name";
+ mServiceBuilder.createServiceDefinition("ServiceBuilderTest", test_block["service-builder"]);
+ std::string test_url = mServiceBuilder.buildServiceURI("ServiceBuilder");
+ ensure_equals("Replacement URL Creation for Non-existant Service", test_url , "");
+ }
+
+ template<> template<>
+ void ServiceBuilderTestObject::test<4>()
+ {
+ //Incorrect service test
+ LLSD test_block;
+ test_block["service-builder"] = "/agent/{$agent-id}/name";
+ mServiceBuilder.createServiceDefinition("ServiceBuilderTest", test_block["service-builder"]);
+ LLSD data_map;
+ data_map["agent_id"] = "257c631f-a0c5-4f29-8a9f-9031feaae6c6";
+ std::string test_url = mServiceBuilder.buildServiceURI("ServiceBuilderTest", data_map);
+ ensure_equals("Replacement URL Creation for Non-existant Service", test_url , "/agent/{$agent-id}/name");
+ }
+
+ template<> template<>
+ void ServiceBuilderTestObject::test<5>()
+ {
+ LLSD test_block;
+ test_block["service-builder"] = "/proc/{$proc}{%params}";
+ mServiceBuilder.createServiceDefinition("ServiceBuilderTest", test_block["service-builder"]);
+ LLSD data_map;
+ data_map["proc"] = "do/something/useful";
+ data_map["params"]["estate_id"] = 1;
+ data_map["params"]["query"] = "public";
+ std::string test_url = mServiceBuilder.buildServiceURI("ServiceBuilderTest", data_map);
+ ensure_equals(
+ "two part URL Creation",
+ test_url ,
+ "/proc/do/something/useful?estate_id=1&query=public");
+ }
+
+ template<> template<>
+ void ServiceBuilderTestObject::test<6>()
+ {
+ LLSD test_block;
+ test_block["service-builder"] = "Which way to the {${$baz}}?";
+ mServiceBuilder.createServiceDefinition(
+ "ServiceBuilderTest",
+ test_block["service-builder"]);
+
+ LLSD data_map;
+ data_map["foo"] = "bar";
+ data_map["baz"] = "foo";
+ std::string test_url = mServiceBuilder.buildServiceURI(
+ "ServiceBuilderTest",
+ data_map);
+ ensure_equals(
+ "recursive url creation",
+ test_url ,
+ "Which way to the bar?");
+ }
+
+ template<> template<>
+ void ServiceBuilderTestObject::test<7>()
+ {
+ LLSD test_block;
+ test_block["service-builder"] = "Which way to the {$foo}?";
+ mServiceBuilder.createServiceDefinition(
+ "ServiceBuilderTest",
+ test_block["service-builder"]);
+
+ LLSD data_map;
+ data_map["baz"] = "foo";
+ std::string test_url = mServiceBuilder.buildServiceURI(
+ "ServiceBuilderTest",
+ data_map);
+ ensure_equals(
+ "fails to do replacement",
+ test_url ,
+ "Which way to the {$foo}?");
+ }
+
+ template<> template<>
+ void ServiceBuilderTestObject::test<8>()
+ {
+ LLSD test_block;
+ test_block["service-builder"] = "/proc/{$proc}{%params}";
+ mServiceBuilder.createServiceDefinition(
+ "ServiceBuilderTest",
+ test_block["service-builder"]);
+ LLSD data_map;
+ data_map["proc"] = "do/something/useful";
+ data_map["params"] = LLSD();
+ std::string test_url = mServiceBuilder.buildServiceURI(
+ "ServiceBuilderTest",
+ data_map);
+ ensure_equals(
+ "strip params",
+ test_url ,
+ "/proc/do/something/useful");
+ }
+}
+
diff --git a/indra/llmessage/tests/lltemplatemessagebuilder_test.cpp b/indra/llmessage/tests/lltemplatemessagebuilder_test.cpp
new file mode 100644
index 0000000000..ddf1c3dbcc
--- /dev/null
+++ b/indra/llmessage/tests/lltemplatemessagebuilder_test.cpp
@@ -0,0 +1,971 @@
+/**
+ * @file lltemplatemessagebuilder_tut.cpp
+ * @date 2007-04
+ * @brief Tests for building messages.
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include <tut/tut.hpp>
+#include "linden_common.h"
+#include "lltut.h"
+
+#include "llapr.h"
+#include "llmessagetemplate.h"
+#include "llmath.h"
+#include "llquaternion.h"
+#include "lltemplatemessagebuilder.h"
+#include "lltemplatemessagereader.h"
+#include "message_prehash.h"
+#include "u64.h"
+#include "v3dmath.h"
+#include "v3math.h"
+#include "v4math.h"
+
+namespace tut
+{
+ static LLTemplateMessageBuilder::message_template_name_map_t nameMap;
+ static LLTemplateMessageReader::message_template_number_map_t numberMap;
+
+ struct LLTemplateMessageBuilderTestData
+ {
+ static LLMessageTemplate defaultTemplate()
+ {
+ static bool init = false;
+ if(! init)
+ {
+ ll_init_apr();
+ const F32 circuit_heartbeat_interval=5;
+ const F32 circuit_timeout=100;
+
+ start_messaging_system("notafile", 13035,
+ 1,
+ 0,
+ 0,
+ false,
+ "notasharedsecret",
+ NULL,
+ false,
+ circuit_heartbeat_interval,
+ circuit_timeout);
+ //init_prehash_data();
+ init = true;
+ }
+ return LLMessageTemplate(_PREHASH_TestMessage, 1, MFT_HIGH);
+ }
+
+ static LLMessageBlock* defaultBlock(const EMsgVariableType type = MVT_NULL, const S32 size = 0, EMsgBlockType block = MBT_VARIABLE)
+ {
+ return createBlock(const_cast<char*>(_PREHASH_Test0), type, size, block);
+ }
+
+ static LLMessageBlock* createBlock(char* name, const EMsgVariableType type = MVT_NULL, const S32 size = 0, EMsgBlockType block = MBT_VARIABLE)
+ {
+ LLMessageBlock* result = new LLMessageBlock(name, block);
+ if(type != MVT_NULL)
+ {
+ result->addVariable(const_cast<char*>(_PREHASH_Test0), type, size);
+ }
+ return result;
+ }
+
+ static LLTemplateMessageBuilder* defaultBuilder(LLMessageTemplate& messageTemplate, char* name = const_cast<char*>(_PREHASH_Test0))
+ {
+ nameMap[_PREHASH_TestMessage] = &messageTemplate;
+ LLTemplateMessageBuilder* builder = new LLTemplateMessageBuilder(nameMap);
+ builder->newMessage(_PREHASH_TestMessage);
+ builder->nextBlock(name);
+ return builder;
+ }
+
+ /** Takes ownership of builder */
+ static LLTemplateMessageReader* setReader(
+ LLMessageTemplate& messageTemplate,
+ LLTemplateMessageBuilder* builder,
+ U8 offset = 0)
+ {
+ numberMap[1] = &messageTemplate;
+ const U32 bufferSize = 1024;
+ U8 buffer[bufferSize];
+ // zero out the packet ID field
+ memset(buffer, 0, LL_PACKET_ID_SIZE);
+ U32 builtSize = builder->buildMessage(buffer, bufferSize, offset);
+ delete builder;
+ LLTemplateMessageReader* reader = new LLTemplateMessageReader(numberMap);
+ reader->validateMessage(buffer, builtSize, LLHost());
+ reader->readMessage(buffer, LLHost());
+ return reader;
+ }
+
+ };
+
+ typedef test_group<LLTemplateMessageBuilderTestData> LLTemplateMessageBuilderTestGroup;
+ typedef LLTemplateMessageBuilderTestGroup::object LLTemplateMessageBuilderTestObject;
+ LLTemplateMessageBuilderTestGroup templateMessageBuilderTestGroup("LLTemplateMessageBuilder");
+
+ template<> template<>
+ void LLTemplateMessageBuilderTestObject::test<1>()
+ // construction and test of undefined
+ {
+ LLMessageTemplate messageTemplate = defaultTemplate();
+ messageTemplate.addBlock(defaultBlock());
+ LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
+ LLTemplateMessageReader* reader = setReader(messageTemplate, builder);
+ delete reader;
+ }
+
+ template<> template<>
+ void LLTemplateMessageBuilderTestObject::test<2>()
+ // bool
+ {
+ LLMessageTemplate messageTemplate = defaultTemplate();
+ messageTemplate.addBlock(defaultBlock(MVT_BOOL, 1));
+ bool outValue, inValue = true;
+ LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
+ builder->addBOOL(_PREHASH_Test0, inValue);
+ LLTemplateMessageReader* reader = setReader(messageTemplate, builder);
+ reader->getBOOL(_PREHASH_Test0, _PREHASH_Test0, outValue);
+ ensure_equals("Ensure bool", inValue, outValue);
+ delete reader;
+ }
+
+ template<> template<>
+ void LLTemplateMessageBuilderTestObject::test<3>()
+ // U8
+ {
+ LLMessageTemplate messageTemplate = defaultTemplate();
+ messageTemplate.addBlock(defaultBlock(MVT_U8, 1));
+ U8 outValue, inValue = 2;
+ LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
+ builder->addU8(_PREHASH_Test0, inValue);
+ LLTemplateMessageReader* reader = setReader(messageTemplate, builder);
+ reader->getU8(_PREHASH_Test0, _PREHASH_Test0, outValue);
+ ensure_equals("Ensure U8", inValue, outValue);
+ delete reader;
+ }
+
+ template<> template<>
+ void LLTemplateMessageBuilderTestObject::test<4>()
+ // S16
+ {
+ LLMessageTemplate messageTemplate = defaultTemplate();
+ messageTemplate.addBlock(defaultBlock(MVT_S16, 2));
+ S16 outValue, inValue = 90;
+ LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
+ builder->addS16(_PREHASH_Test0, inValue);
+ LLTemplateMessageReader* reader = setReader(messageTemplate, builder);
+ reader->getS16(_PREHASH_Test0, _PREHASH_Test0, outValue);
+ ensure_equals("Ensure S16", inValue, outValue);
+ delete reader;
+ }
+
+ template<> template<>
+ void LLTemplateMessageBuilderTestObject::test<5>()
+ // U16
+ {
+ LLMessageTemplate messageTemplate = defaultTemplate();
+ messageTemplate.addBlock(defaultBlock(MVT_U16, 2));
+ U16 outValue, inValue = 3;
+ LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
+ builder->addU16(_PREHASH_Test0, inValue);
+ LLTemplateMessageReader* reader = setReader(messageTemplate, builder);
+ reader->getU16(_PREHASH_Test0, _PREHASH_Test0, outValue);
+ ensure_equals("Ensure U16", inValue, outValue);
+ delete reader;
+ }
+
+ template<> template<>
+ void LLTemplateMessageBuilderTestObject::test<6>()
+ // S32
+ {
+ LLMessageTemplate messageTemplate = defaultTemplate();
+ messageTemplate.addBlock(defaultBlock(MVT_S32, 4));
+ S32 outValue, inValue = 44;
+ LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
+ builder->addS32(_PREHASH_Test0, inValue);
+ LLTemplateMessageReader* reader = setReader(messageTemplate, builder);
+ reader->getS32(_PREHASH_Test0, _PREHASH_Test0, outValue);
+ ensure_equals("Ensure S32", inValue, outValue);
+ delete reader;
+ }
+
+ template<> template<>
+ void LLTemplateMessageBuilderTestObject::test<7>()
+ // F32
+ {
+ LLMessageTemplate messageTemplate = defaultTemplate();
+ messageTemplate.addBlock(defaultBlock(MVT_F32, 4));
+ F32 outValue, inValue = 121.44f;
+ LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
+ builder->addF32(_PREHASH_Test0, inValue);
+ LLTemplateMessageReader* reader = setReader(messageTemplate, builder);
+ reader->getF32(_PREHASH_Test0, _PREHASH_Test0, outValue);
+ ensure_equals("Ensure F32", inValue, outValue);
+ delete reader;
+ }
+
+ template<> template<>
+ void LLTemplateMessageBuilderTestObject::test<8>()
+ // U32
+ {
+ LLMessageTemplate messageTemplate = defaultTemplate();
+ messageTemplate.addBlock(defaultBlock(MVT_U32, 4));
+ U32 outValue, inValue = 88;
+ LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
+ builder->addU32(_PREHASH_Test0, inValue);
+ LLTemplateMessageReader* reader = setReader(messageTemplate, builder);
+ reader->getU32(_PREHASH_Test0, _PREHASH_Test0, outValue);
+ ensure_equals("Ensure U32", inValue, outValue);
+ delete reader;
+ }
+
+ template<> template<>
+ void LLTemplateMessageBuilderTestObject::test<9>()
+ // U64
+ {
+ LLMessageTemplate messageTemplate = defaultTemplate();
+ messageTemplate.addBlock(defaultBlock(MVT_U64, 8));
+ U64 outValue, inValue = 121;
+ LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
+ builder->addU64(_PREHASH_Test0, inValue);
+ LLTemplateMessageReader* reader = setReader(messageTemplate, builder);
+ reader->getU64(_PREHASH_Test0, _PREHASH_Test0, outValue);
+ ensure_equals("Ensure U64", inValue, outValue);
+ delete reader;
+ }
+
+ template<> template<>
+ void LLTemplateMessageBuilderTestObject::test<10>()
+ // F64
+ {
+ LLMessageTemplate messageTemplate = defaultTemplate();
+ messageTemplate.addBlock(defaultBlock(MVT_F64, 8));
+ F64 outValue, inValue = 3232143.33;
+ LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
+ builder->addF64(_PREHASH_Test0, inValue);
+ LLTemplateMessageReader* reader = setReader(messageTemplate, builder);
+ reader->getF64(_PREHASH_Test0, _PREHASH_Test0, outValue);
+ ensure_equals("Ensure F64", inValue, outValue);
+ delete reader;
+ }
+
+ template<> template<>
+ void LLTemplateMessageBuilderTestObject::test<11>()
+ // Vector3
+ {
+ LLMessageTemplate messageTemplate = defaultTemplate();
+ messageTemplate.addBlock(defaultBlock(MVT_LLVector3, 12));
+ LLVector3 outValue, inValue = LLVector3(1,2,3);
+ LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
+ builder->addVector3(_PREHASH_Test0, inValue);
+ LLTemplateMessageReader* reader = setReader(messageTemplate, builder);
+ reader->getVector3(_PREHASH_Test0, _PREHASH_Test0, outValue);
+ ensure_equals("Ensure LLVector3", inValue, outValue);
+ delete reader;
+ }
+
+ template<> template<>
+ void LLTemplateMessageBuilderTestObject::test<12>()
+ // Vector4
+ {
+ LLMessageTemplate messageTemplate = defaultTemplate();
+ messageTemplate.addBlock(defaultBlock(MVT_LLVector4, 16));
+ LLVector4 outValue, inValue = LLVector4(1,2,3,4);
+ LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
+ builder->addVector4(_PREHASH_Test0, inValue);
+ LLTemplateMessageReader* reader = setReader(messageTemplate, builder);
+ reader->getVector4(_PREHASH_Test0, _PREHASH_Test0, outValue);
+ ensure_equals("Ensure LLVector4", inValue, outValue);
+ delete reader;
+ }
+
+ template<> template<>
+ void LLTemplateMessageBuilderTestObject::test<13>()
+ // Vector3d
+ {
+ LLMessageTemplate messageTemplate = defaultTemplate();
+ messageTemplate.addBlock(defaultBlock(MVT_LLVector3d, 24));
+ LLVector3d outValue, inValue = LLVector3d(1,2,3);
+ LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
+ builder->addVector3d(_PREHASH_Test0, inValue);
+ LLTemplateMessageReader* reader = setReader(messageTemplate, builder);
+ reader->getVector3d(_PREHASH_Test0, _PREHASH_Test0, outValue);
+ ensure_equals("Ensure LLVector3d", inValue, outValue);
+ delete reader;
+ }
+
+ template<> template<>
+ void LLTemplateMessageBuilderTestObject::test<14>()
+ // Quaternion
+ {
+ LLMessageTemplate messageTemplate = defaultTemplate();
+ messageTemplate.addBlock(defaultBlock(MVT_LLQuaternion, 12));
+ LLQuaternion outValue, inValue = LLQuaternion(0.0f, LLVector3(0.3713907f, 0.5570861f, 0.7427813f));
+
+ LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
+ builder->addQuat(_PREHASH_Test0, inValue);
+ LLTemplateMessageReader* reader = setReader(messageTemplate, builder);
+ reader->getQuat(_PREHASH_Test0, _PREHASH_Test0, outValue);
+ ensure_equals("Ensure LLQuaternion", inValue, outValue);
+ delete reader;
+ }
+
+ template<> template<>
+ void LLTemplateMessageBuilderTestObject::test<15>()
+ // UUID
+ {
+ LLMessageTemplate messageTemplate = defaultTemplate();
+ messageTemplate.addBlock(defaultBlock(MVT_LLUUID, 16));
+ LLUUID outValue, inValue;
+ inValue.generate();
+ LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
+ builder->addUUID(_PREHASH_Test0, inValue);
+ LLTemplateMessageReader* reader = setReader(messageTemplate, builder);
+ reader->getUUID(_PREHASH_Test0, _PREHASH_Test0, outValue);
+ ensure_equals("Ensure UUID", inValue, outValue);
+ delete reader;
+ }
+
+ template<> template<>
+ void LLTemplateMessageBuilderTestObject::test<16>()
+ // IPAddr
+ {
+ LLMessageTemplate messageTemplate = defaultTemplate();
+ messageTemplate.addBlock(defaultBlock(MVT_IP_ADDR, 4));
+ U32 outValue, inValue = 12344556;
+ LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
+ builder->addIPAddr(_PREHASH_Test0, inValue);
+ LLTemplateMessageReader* reader = setReader(messageTemplate, builder);
+ reader->getIPAddr(_PREHASH_Test0, _PREHASH_Test0, outValue);
+ ensure_equals("Ensure IPAddr", inValue, outValue);
+ delete reader;
+ }
+
+ template<> template<>
+ void LLTemplateMessageBuilderTestObject::test<17>()
+ // IPPort
+ {
+ LLMessageTemplate messageTemplate = defaultTemplate();
+ messageTemplate.addBlock(defaultBlock(MVT_IP_PORT, 2));
+ U16 outValue, inValue = 80;
+ LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
+ builder->addIPPort(_PREHASH_Test0, inValue);
+ LLTemplateMessageReader* reader = setReader(messageTemplate, builder);
+ reader->getIPPort(_PREHASH_Test0, _PREHASH_Test0, outValue);
+ ensure_equals("Ensure IPPort", inValue, outValue);
+ delete reader;
+ }
+
+ template<> template<>
+ void LLTemplateMessageBuilderTestObject::test<18>()
+ // String
+ {
+ LLMessageTemplate messageTemplate = defaultTemplate();
+ messageTemplate.addBlock(defaultBlock(MVT_VARIABLE, 1));
+ std::string outValue, inValue = "testing";
+ LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
+ builder->addString(_PREHASH_Test0, inValue.c_str());
+ LLTemplateMessageReader* reader = setReader(messageTemplate, builder);
+ char buffer[MAX_STRING];
+ reader->getString(_PREHASH_Test0, _PREHASH_Test0, MAX_STRING, buffer);
+ outValue = buffer;
+ ensure_equals("Ensure String", inValue, outValue);
+ delete reader;
+ }
+
+ template<> template<>
+ void LLTemplateMessageBuilderTestObject::test<19>()
+ // block name !-> binary order
+ {
+ U8 buffer1[MAX_BUFFER_SIZE];
+ memset(buffer1, 0, MAX_BUFFER_SIZE);
+ U8 buffer2[MAX_BUFFER_SIZE];
+ memset(buffer2, 0, MAX_BUFFER_SIZE);
+ U32 bufferSize1, bufferSize2;
+
+ // build template: Test0 before Test1
+ LLMessageTemplate messageTemplate = defaultTemplate();
+ messageTemplate.addBlock(createBlock(const_cast<char*>(_PREHASH_Test0), MVT_U32, 4, MBT_SINGLE));
+ messageTemplate.addBlock(createBlock(const_cast<char*>(_PREHASH_Test1), MVT_U32, 4, MBT_SINGLE));
+
+ // build message: 1st declared block var == 0xaaaa, 2nd declared block var == 0xbbbb
+ LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate, const_cast<char*>(_PREHASH_Test0));
+ builder->addU32(_PREHASH_Test0, 0xaaaa);
+ builder->nextBlock(_PREHASH_Test1);
+ builder->addU32(_PREHASH_Test0, 0xbbbb);
+ bufferSize1 = builder->buildMessage(buffer1, MAX_BUFFER_SIZE, 0);
+ delete builder;
+
+ // build template: Test1 before Test0
+ messageTemplate = defaultTemplate();
+ messageTemplate.addBlock(createBlock(const_cast<char*>(_PREHASH_Test1), MVT_U32, 4, MBT_SINGLE));
+ messageTemplate.addBlock(createBlock(const_cast<char*>(_PREHASH_Test0), MVT_U32, 4, MBT_SINGLE));
+
+ // build message: 1st declared block var == 0xaaaa, 2nd declared block var == 0xbbbb
+ builder = defaultBuilder(messageTemplate, const_cast<char*>(_PREHASH_Test1));
+ builder->addU32(_PREHASH_Test0, 0xaaaa);
+ builder->nextBlock(_PREHASH_Test0);
+ builder->addU32(_PREHASH_Test0, 0xbbbb);
+ bufferSize2 = builder->buildMessage(buffer2, MAX_BUFFER_SIZE, 0);
+ delete builder;
+
+ ensure_equals("Ensure Buffer Sizes Equal", bufferSize1, bufferSize2);
+ ensure_equals("Ensure Buffer Contents Equal", memcmp(buffer1, buffer2, bufferSize1), 0);
+ }
+
+ template<> template<>
+ void LLTemplateMessageBuilderTestObject::test<20>()
+ // block build order !-> binary order
+ {
+ U8 buffer1[MAX_BUFFER_SIZE];
+ memset(buffer1, 0, MAX_BUFFER_SIZE);
+ U8 buffer2[MAX_BUFFER_SIZE];
+ memset(buffer2, 0, MAX_BUFFER_SIZE);
+ U32 bufferSize1, bufferSize2;
+
+ // build template: Test0 before Test1
+ LLMessageTemplate messageTemplate = defaultTemplate();
+ messageTemplate.addBlock(createBlock(const_cast<char*>(_PREHASH_Test0), MVT_U32, 4, MBT_SINGLE));
+ messageTemplate.addBlock(createBlock(const_cast<char*>(_PREHASH_Test1), MVT_U32, 4, MBT_SINGLE));
+
+ // build message: 1st declared block var == 0xaaaa, 2nd declared block var == 0xbbbb
+ LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate, const_cast<char*>(_PREHASH_Test0));
+ builder->addU32(_PREHASH_Test0, 0xaaaa);
+ builder->nextBlock(_PREHASH_Test1);
+ builder->addU32(_PREHASH_Test0, 0xbbbb);
+ bufferSize1 = builder->buildMessage(buffer1, MAX_BUFFER_SIZE, 0);
+ delete builder;
+
+ // build message: 1st declared block var == 0xaaaa, 2nd declared block var == 0xbbbb
+ builder = defaultBuilder(messageTemplate, const_cast<char*>(_PREHASH_Test1));
+ builder->addU32(_PREHASH_Test0, 0xbbbb);
+ builder->nextBlock(_PREHASH_Test0);
+ builder->addU32(_PREHASH_Test0, 0xaaaa);
+ bufferSize2 = builder->buildMessage(buffer2, MAX_BUFFER_SIZE, 0);
+ delete builder;
+
+ ensure_equals("Ensure Buffer Sizes Equal", bufferSize1, bufferSize2);
+ ensure_equals("Ensure Buffer Contents Equal", memcmp(buffer1, buffer2, bufferSize1), 0);
+ }
+
+ template<> template<>
+ void LLTemplateMessageBuilderTestObject::test<21>()
+ // block appended in declaration -> data appended in binary
+ {
+ U8 buffer1[MAX_BUFFER_SIZE];
+ memset(buffer1, 0, MAX_BUFFER_SIZE);
+ U8 buffer2[MAX_BUFFER_SIZE];
+ memset(buffer2, 0, MAX_BUFFER_SIZE);
+ U32 bufferSize1, bufferSize2;
+
+ // Build template: Test0 only
+ LLMessageTemplate messageTemplate = defaultTemplate();
+ messageTemplate.addBlock(createBlock(const_cast<char*>(_PREHASH_Test0), MVT_U32, 4, MBT_SINGLE));
+
+ // Build message
+ LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate, const_cast<char*>(_PREHASH_Test0));
+ builder->addU32(_PREHASH_Test0, 0xaaaa);
+ bufferSize1 = builder->buildMessage(buffer1, MAX_BUFFER_SIZE, 0);
+ delete builder;
+
+ // Build template: Test0 before Test1
+ messageTemplate = defaultTemplate();
+ messageTemplate.addBlock(createBlock(const_cast<char*>(_PREHASH_Test0), MVT_U32, 4, MBT_SINGLE));
+ messageTemplate.addBlock(createBlock(const_cast<char*>(_PREHASH_Test1), MVT_U32, 4, MBT_SINGLE));
+
+ // Build message
+ builder = defaultBuilder(messageTemplate, const_cast<char*>(_PREHASH_Test0));
+ builder->addU32(_PREHASH_Test0, 0xaaaa);
+ builder->nextBlock(_PREHASH_Test1);
+ builder->addU32(_PREHASH_Test0, 0xbbbb);
+ bufferSize2 = builder->buildMessage(buffer2, MAX_BUFFER_SIZE, 0);
+ delete builder;
+
+ ensure_not_equals("Ensure Buffer Sizes Not Equal", bufferSize1, bufferSize2);
+ ensure_equals("Ensure Buffer Prefix Equal", memcmp(buffer1, buffer2, bufferSize1), 0);
+ ensure_not_equals("Ensure Buffer Contents Not Equal", memcmp(buffer1, buffer2, bufferSize2), 0);
+ }
+
+ template<> template<>
+ void LLTemplateMessageBuilderTestObject::test<22>()
+ // repeated penultimate block (crashes when data in LLDynamicArrayIndexed)
+ {
+ U32 inTest00 = 0, inTest01 = 1, inTest1 = 2;
+ U32 outTest00, outTest01, outTest1;
+ LLMessageTemplate messageTemplate = defaultTemplate();
+ messageTemplate.addBlock(createBlock(const_cast<char*>(_PREHASH_Test0), MVT_U32, 4));
+ messageTemplate.addBlock(createBlock(const_cast<char*>(_PREHASH_Test1), MVT_U32, 4));
+ LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
+ builder->addU32(_PREHASH_Test0, inTest00);
+ builder->nextBlock(_PREHASH_Test0);
+ builder->addU32(_PREHASH_Test0, inTest01);
+ builder->nextBlock(_PREHASH_Test1);
+ builder->addU32(_PREHASH_Test0, inTest1);
+ LLTemplateMessageReader* reader = setReader(messageTemplate, builder);
+ reader->getU32(_PREHASH_Test0, _PREHASH_Test0, outTest00, 0);
+ reader->getU32(_PREHASH_Test0, _PREHASH_Test0, outTest01, 1);
+ reader->getU32(_PREHASH_Test1, _PREHASH_Test0, outTest1);
+ ensure_equals("Ensure Test0[0]", inTest00, outTest00);
+ ensure_equals("Ensure Test0[1]", inTest01, outTest01);
+ ensure_equals("Ensure Test1", inTest1, outTest1);
+ delete reader;
+ }
+
+ template<> template<>
+ void LLTemplateMessageBuilderTestObject::test<23>()
+ // variable repeated block name never accessed
+ {
+ U32 inTest = 1, outTest;
+ LLMessageTemplate messageTemplate = defaultTemplate();
+ messageTemplate.addBlock(
+ createBlock(const_cast<char*>(_PREHASH_Test0), MVT_U32, 4, MBT_SINGLE));
+ messageTemplate.addBlock(createBlock(const_cast<char*>(_PREHASH_Test1), MVT_U32, 4));
+
+ LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
+ builder->addU32(_PREHASH_Test0, inTest);
+
+ LLTemplateMessageReader* reader = setReader(messageTemplate, builder);
+ reader->getU32(_PREHASH_Test0, _PREHASH_Test0, outTest);
+ S32 blockCount = reader->getNumberOfBlocks(const_cast<char*>(_PREHASH_Test1));
+ ensure_equals("Ensure block count", blockCount, 0);
+ ensure_equals("Ensure Test0", inTest, outTest);
+ delete reader;
+ }
+
+ template<> template<>
+ void LLTemplateMessageBuilderTestObject::test<24>()
+ // forwarding message
+ {
+ // build template
+ LLMessageTemplate messageTemplate = defaultTemplate();
+ messageTemplate.addBlock(createBlock(const_cast<char*>(_PREHASH_Test0), MVT_U32, 4));
+
+ // build message
+ LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
+ builder->addU32(_PREHASH_Test0, 42);
+
+ // read message
+ LLTemplateMessageReader* reader = setReader(messageTemplate, builder);
+
+ // forward message
+ builder = defaultBuilder(messageTemplate);
+ builder->newMessage(_PREHASH_TestMessage);
+ reader->copyToBuilder(*builder);
+ U8 buffer[MAX_BUFFER_SIZE];
+ builder->buildMessage(buffer, MAX_BUFFER_SIZE, 0);
+
+ delete builder;
+ delete reader;
+ }
+
+ template<> template<>
+ void LLTemplateMessageBuilderTestObject::test<25>()
+ // non-zero offset with undefined
+ {
+ LLMessageTemplate messageTemplate = defaultTemplate();
+ messageTemplate.addBlock(defaultBlock());
+ LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
+ LLTemplateMessageReader* reader = setReader(
+ messageTemplate, builder, 10);
+ delete reader;
+ }
+
+ template<> template<>
+ void LLTemplateMessageBuilderTestObject::test<26>()
+ // non-zero offset with bool
+ {
+ LLMessageTemplate messageTemplate = defaultTemplate();
+ messageTemplate.addBlock(defaultBlock(MVT_BOOL, 1));
+ bool outValue, inValue = true;
+ LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
+ builder->addBOOL(_PREHASH_Test0, inValue);
+ LLTemplateMessageReader* reader = setReader(
+ messageTemplate, builder, 1);
+ reader->getBOOL(_PREHASH_Test0, _PREHASH_Test0, outValue);
+ ensure_equals("Ensure bool", inValue, outValue);
+ delete reader;
+ }
+
+ template<> template<>
+ void LLTemplateMessageBuilderTestObject::test<27>()
+ // non-zero offset with U8
+ {
+ LLMessageTemplate messageTemplate = defaultTemplate();
+ messageTemplate.addBlock(defaultBlock(MVT_U8, 1));
+ U8 outValue, inValue = 2;
+ LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
+ builder->addU8(_PREHASH_Test0, inValue);
+ LLTemplateMessageReader* reader = setReader(
+ messageTemplate, builder, 255);
+ reader->getU8(_PREHASH_Test0, _PREHASH_Test0, outValue);
+ ensure_equals("Ensure U8", inValue, outValue);
+ delete reader;
+ }
+
+ template<> template<>
+ void LLTemplateMessageBuilderTestObject::test<28>()
+ // non-zero offset with S16
+ {
+ LLMessageTemplate messageTemplate = defaultTemplate();
+ messageTemplate.addBlock(defaultBlock(MVT_S16, 2));
+ S16 outValue, inValue = 90;
+ LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
+ builder->addS16(_PREHASH_Test0, inValue);
+ LLTemplateMessageReader* reader = setReader(
+ messageTemplate, builder, 2);
+ reader->getS16(_PREHASH_Test0, _PREHASH_Test0, outValue);
+ ensure_equals("Ensure S16", inValue, outValue);
+ delete reader;
+ }
+
+ template<> template<>
+ void LLTemplateMessageBuilderTestObject::test<29>()
+ // non-zero offset with U16
+ {
+ LLMessageTemplate messageTemplate = defaultTemplate();
+ messageTemplate.addBlock(defaultBlock(MVT_U16, 2));
+ U16 outValue, inValue = 3;
+ LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
+ builder->addU16(_PREHASH_Test0, inValue);
+ LLTemplateMessageReader* reader = setReader(
+ messageTemplate, builder, 4);
+ reader->getU16(_PREHASH_Test0, _PREHASH_Test0, outValue);
+ ensure_equals("Ensure U16", inValue, outValue);
+ delete reader;
+ }
+
+ template<> template<>
+ void LLTemplateMessageBuilderTestObject::test<30>()
+ // non-zero offset with S32
+ {
+ LLMessageTemplate messageTemplate = defaultTemplate();
+ messageTemplate.addBlock(defaultBlock(MVT_S32, 4));
+ S32 outValue, inValue = 44;
+ LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
+ builder->addS32(_PREHASH_Test0, inValue);
+ LLTemplateMessageReader* reader = setReader(
+ messageTemplate, builder, 4);
+ reader->getS32(_PREHASH_Test0, _PREHASH_Test0, outValue);
+ ensure_equals("Ensure S32", inValue, outValue);
+ delete reader;
+ }
+
+ template<> template<>
+ void LLTemplateMessageBuilderTestObject::test<31>()
+ // non-zero offset with F32
+ {
+ LLMessageTemplate messageTemplate = defaultTemplate();
+ messageTemplate.addBlock(defaultBlock(MVT_F32, 4));
+ F32 outValue, inValue = 121.44f;
+ LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
+ builder->addF32(_PREHASH_Test0, inValue);
+ LLTemplateMessageReader* reader = setReader(
+ messageTemplate, builder, 16);
+ reader->getF32(_PREHASH_Test0, _PREHASH_Test0, outValue);
+ ensure_equals("Ensure F32", inValue, outValue);
+ delete reader;
+ }
+
+ template<> template<>
+ void LLTemplateMessageBuilderTestObject::test<32>()
+ // non-zero offset with U32
+ {
+ LLMessageTemplate messageTemplate = defaultTemplate();
+ messageTemplate.addBlock(defaultBlock(MVT_U32, 4));
+ U32 outValue, inValue = 88;
+ LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
+ builder->addU32(_PREHASH_Test0, inValue);
+ LLTemplateMessageReader* reader = setReader(
+ messageTemplate, builder, 127);
+ reader->getU32(_PREHASH_Test0, _PREHASH_Test0, outValue);
+ ensure_equals("Ensure U32", inValue, outValue);
+ delete reader;
+ }
+
+ template<> template<>
+ void LLTemplateMessageBuilderTestObject::test<33>()
+ // non-zero offset with U64
+ {
+ LLMessageTemplate messageTemplate = defaultTemplate();
+ messageTemplate.addBlock(defaultBlock(MVT_U64, 8));
+ U64 outValue, inValue = 121;
+ LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
+ builder->addU64(_PREHASH_Test0, inValue);
+ LLTemplateMessageReader* reader = setReader(
+ messageTemplate, builder, 32);
+ reader->getU64(_PREHASH_Test0, _PREHASH_Test0, outValue);
+ ensure_equals("Ensure U64", inValue, outValue);
+ delete reader;
+ }
+
+ template<> template<>
+ void LLTemplateMessageBuilderTestObject::test<34>()
+ // non-zero offset with F64
+ {
+ LLMessageTemplate messageTemplate = defaultTemplate();
+ messageTemplate.addBlock(defaultBlock(MVT_F64, 8));
+ F64 outValue, inValue = 3232143.33;
+ LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
+ builder->addF64(_PREHASH_Test0, inValue);
+ LLTemplateMessageReader* reader = setReader(
+ messageTemplate, builder, 128);
+ reader->getF64(_PREHASH_Test0, _PREHASH_Test0, outValue);
+ ensure_equals("Ensure F64", inValue, outValue);
+ delete reader;
+ }
+
+ template<> template<>
+ void LLTemplateMessageBuilderTestObject::test<35>()
+ // non-zero offset with Vector3
+ {
+ LLMessageTemplate messageTemplate = defaultTemplate();
+ messageTemplate.addBlock(defaultBlock(MVT_LLVector3, 12));
+ LLVector3 outValue, inValue = LLVector3(1,2,3);
+ LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
+ builder->addVector3(_PREHASH_Test0, inValue);
+ LLTemplateMessageReader* reader = setReader(
+ messageTemplate, builder, 63);
+ reader->getVector3(_PREHASH_Test0, _PREHASH_Test0, outValue);
+ ensure_equals("Ensure LLVector3", inValue, outValue);
+ delete reader;
+ }
+
+ template<> template<>
+ void LLTemplateMessageBuilderTestObject::test<36>()
+ // non-zero offset with Vector4
+ {
+ LLMessageTemplate messageTemplate = defaultTemplate();
+ messageTemplate.addBlock(defaultBlock(MVT_LLVector4, 16));
+ LLVector4 outValue, inValue = LLVector4(1,2,3,4);
+ LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
+ builder->addVector4(_PREHASH_Test0, inValue);
+ LLTemplateMessageReader* reader = setReader(
+ messageTemplate, builder, 64);
+ reader->getVector4(_PREHASH_Test0, _PREHASH_Test0, outValue);
+ ensure_equals("Ensure LLVector4", inValue, outValue);
+ delete reader;
+ }
+
+ template<> template<>
+ void LLTemplateMessageBuilderTestObject::test<37>()
+ // non-zero offset with Vector3d
+ {
+ LLMessageTemplate messageTemplate = defaultTemplate();
+ messageTemplate.addBlock(defaultBlock(MVT_LLVector3d, 24));
+ LLVector3d outValue, inValue = LLVector3d(1,2,3);
+ LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
+ builder->addVector3d(_PREHASH_Test0, inValue);
+ LLTemplateMessageReader* reader = setReader(
+ messageTemplate, builder, 64);
+ reader->getVector3d(_PREHASH_Test0, _PREHASH_Test0, outValue);
+ ensure_equals("Ensure LLVector3d", inValue, outValue);
+ delete reader;
+ }
+
+ template<> template<>
+ void LLTemplateMessageBuilderTestObject::test<38>()
+ // non-zero offset with Quaternion
+ {
+ LLMessageTemplate messageTemplate = defaultTemplate();
+ messageTemplate.addBlock(defaultBlock(MVT_LLQuaternion, 12));
+ LLQuaternion outValue, inValue = LLQuaternion(0.0f, LLVector3(0.3713907f, 0.5570861f, 0.7427813f));
+ LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
+ builder->addQuat(_PREHASH_Test0, inValue);
+ LLTemplateMessageReader* reader = setReader(
+ messageTemplate, builder, 12);
+ reader->getQuat(_PREHASH_Test0, _PREHASH_Test0, outValue);
+ ensure_equals("Ensure LLQuaternion", inValue, outValue);
+ delete reader;
+ }
+
+ template<> template<>
+ void LLTemplateMessageBuilderTestObject::test<39>()
+ // non-zero offset with UUID
+ {
+ LLMessageTemplate messageTemplate = defaultTemplate();
+ messageTemplate.addBlock(defaultBlock(MVT_LLUUID, 16));
+ LLUUID outValue, inValue;
+ inValue.generate();
+ LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
+ builder->addUUID(_PREHASH_Test0, inValue);
+ LLTemplateMessageReader* reader = setReader(
+ messageTemplate, builder, 31);
+ reader->getUUID(_PREHASH_Test0, _PREHASH_Test0, outValue);
+ ensure_equals("Ensure UUID", inValue, outValue);
+ delete reader;
+ }
+
+ template<> template<>
+ void LLTemplateMessageBuilderTestObject::test<40>()
+ // non-zero offset with IPAddr
+ {
+ LLMessageTemplate messageTemplate = defaultTemplate();
+ messageTemplate.addBlock(defaultBlock(MVT_IP_ADDR, 4));
+ U32 outValue, inValue = 12344556;
+ LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
+ builder->addIPAddr(_PREHASH_Test0, inValue);
+ LLTemplateMessageReader* reader = setReader(
+ messageTemplate, builder, 32);
+ reader->getIPAddr(_PREHASH_Test0, _PREHASH_Test0, outValue);
+ ensure_equals("Ensure IPAddr", inValue, outValue);
+ delete reader;
+ }
+
+ template<> template<>
+ void LLTemplateMessageBuilderTestObject::test<41>()
+ // non-zero offset with IPPort
+ {
+ LLMessageTemplate messageTemplate = defaultTemplate();
+ messageTemplate.addBlock(defaultBlock(MVT_IP_PORT, 2));
+ U16 outValue, inValue = 80;
+ LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
+ builder->addIPPort(_PREHASH_Test0, inValue);
+ LLTemplateMessageReader* reader = setReader(
+ messageTemplate, builder, 6);
+ reader->getIPPort(_PREHASH_Test0, _PREHASH_Test0, outValue);
+ ensure_equals("Ensure IPPort", inValue, outValue);
+ delete reader;
+ }
+
+ template<> template<>
+ void LLTemplateMessageBuilderTestObject::test<42>()
+ // non-zero offset with String
+ {
+ LLMessageTemplate messageTemplate = defaultTemplate();
+ messageTemplate.addBlock(defaultBlock(MVT_VARIABLE, 1));
+ std::string outValue, inValue = "testing";
+ LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
+ builder->addString(_PREHASH_Test0, inValue.c_str());
+ LLTemplateMessageReader* reader = setReader(
+ messageTemplate, builder, 255);
+ char buffer[MAX_STRING];
+ reader->getString(_PREHASH_Test0, _PREHASH_Test0, MAX_STRING, buffer);
+ outValue = buffer;
+ ensure_equals("Ensure String", inValue, outValue);
+ delete reader;
+ }
+
+ template<> template<>
+ void LLTemplateMessageBuilderTestObject::test<43>()
+ // read past end of message -> default values (forward compatibility)
+ {
+ // build message with single block
+ LLMessageTemplate messageTemplate = defaultTemplate();
+ messageTemplate.addBlock(defaultBlock(MVT_U32, 4, MBT_SINGLE));
+ U32 outValue, outValue2, inValue = 0xbbbbbbbb;
+ LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
+ builder->addU32(_PREHASH_Test0, inValue);
+ const U32 bufferSize = 1024;
+ U8 buffer[bufferSize];
+ memset(buffer, 0xaa, bufferSize);
+ memset(buffer, 0, LL_PACKET_ID_SIZE);
+ U32 builtSize = builder->buildMessage(buffer, bufferSize, 0);
+ delete builder;
+
+ // add block to reader template
+ messageTemplate.addBlock(createBlock(const_cast<char*>(_PREHASH_Test1), MVT_U32, 4, MBT_SINGLE));
+
+ // read message value and default value
+ numberMap[1] = &messageTemplate;
+ LLTemplateMessageReader* reader =
+ new LLTemplateMessageReader(numberMap);
+ reader->validateMessage(buffer, builtSize, LLHost());
+ reader->readMessage(buffer, LLHost());
+ reader->getU32(_PREHASH_Test0, _PREHASH_Test0, outValue);
+ reader->getU32(_PREHASH_Test1, _PREHASH_Test0, outValue2);
+ ensure_equals("Ensure present value ", outValue, inValue);
+ ensure_equals("Ensure default value ", outValue2, 0);
+ delete reader;
+ }
+
+ template<> template<>
+ void LLTemplateMessageBuilderTestObject::test<44>()
+ // read variable block past end of message -> 0 repeats
+ {
+ // build message with single block
+ LLMessageTemplate messageTemplate = defaultTemplate();
+ messageTemplate.addBlock(defaultBlock(MVT_U32, 4, MBT_SINGLE));
+ U32 outValue, outValue2, inValue = 0xbbbbbbbb;
+ LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
+ builder->addU32(_PREHASH_Test0, inValue);
+ const U32 bufferSize = 1024;
+ U8 buffer[bufferSize];
+ memset(buffer, 0xaa, bufferSize);
+ memset(buffer, 0, LL_PACKET_ID_SIZE);
+ U32 builtSize = builder->buildMessage(buffer, bufferSize, 0);
+ delete builder;
+
+ // add variable block to reader template
+ messageTemplate.addBlock(createBlock(const_cast<char*>(_PREHASH_Test1), MVT_U32, 4));
+
+ // read message value and check block repeat count
+ numberMap[1] = &messageTemplate;
+ LLTemplateMessageReader* reader =
+ new LLTemplateMessageReader(numberMap);
+ reader->validateMessage(buffer, builtSize, LLHost());
+ reader->readMessage(buffer, LLHost());
+ reader->getU32(_PREHASH_Test0, _PREHASH_Test0, outValue);
+ outValue2 = reader->getNumberOfBlocks(_PREHASH_Test1);
+ ensure_equals("Ensure present value ", outValue, inValue);
+ ensure_equals("Ensure 0 repeats ", outValue2, 0);
+ delete reader;
+ }
+
+ template<> template<>
+ void LLTemplateMessageBuilderTestObject::test<45>()
+ // read variable length data past end of message -> 0 length
+ {
+ // build message with single block
+ LLMessageTemplate messageTemplate = defaultTemplate();
+ messageTemplate.addBlock(defaultBlock(MVT_U32, 4, MBT_SINGLE));
+ U32 outValue, inValue = 0xbbbbbbbb;
+ LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
+ builder->addU32(_PREHASH_Test0, inValue);
+ const U32 bufferSize = 1024;
+ U8 buffer[bufferSize];
+ memset(buffer, 0xaa, bufferSize);
+ memset(buffer, 0, LL_PACKET_ID_SIZE);
+ U32 builtSize = builder->buildMessage(buffer, bufferSize, 0);
+ delete builder;
+
+ // add variable block to reader template
+ messageTemplate.addBlock(createBlock(const_cast<char*>(_PREHASH_Test1), MVT_VARIABLE, 4,
+ MBT_SINGLE));
+
+ // read message value and default string
+ numberMap[1] = &messageTemplate;
+ LLTemplateMessageReader* reader =
+ new LLTemplateMessageReader(numberMap);
+ reader->validateMessage(buffer, builtSize, LLHost());
+ reader->readMessage(buffer, LLHost());
+ reader->getU32(_PREHASH_Test0, _PREHASH_Test0, outValue);
+ (void)outValue;
+ char outBuffer[bufferSize];
+ memset(buffer, 0xcc, bufferSize);
+ reader->getString(_PREHASH_Test1, _PREHASH_Test0, bufferSize,
+ outBuffer);
+ ensure_equals("Ensure present value ", outValue, inValue);
+ ensure_equals("Ensure unchanged buffer ", strlen(outBuffer), 0);
+ delete reader;
+ }
+}
+
diff --git a/indra/llmessage/tests/llxorcipher_test.cpp b/indra/llmessage/tests/llxorcipher_test.cpp
new file mode 100644
index 0000000000..9acac53604
--- /dev/null
+++ b/indra/llmessage/tests/llxorcipher_test.cpp
@@ -0,0 +1,131 @@
+/**
+ * @file llxorcipher_tut.cpp
+ * @author Adroit
+ * @date 2007-03
+ * @brief llxorcipher, llnullcipher test cases.
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include "lltut.h"
+#include "llxorcipher.h"
+#include "llnullcipher.h"
+
+namespace tut
+{
+ struct cipher
+ {
+ };
+ typedef test_group<cipher> cipher_t;
+ typedef cipher_t::object cipher_object_t;
+ tut::cipher_t tut_cipher("cipher");
+
+ //encrypt->decrypt
+ template<> template<>
+ void cipher_object_t::test<1>()
+ {
+ const U32 len = 3;
+ const U8 pad[] = "abc";
+ const char str[] = "SecondLife";
+ const S32 str_len = sizeof(str);
+ U8 encrypted[str_len];
+ U8 decrypted[str_len];
+ LLXORCipher xorCipher(pad, len);
+ LLXORCipher xorCipher1(pad, len);
+
+ U32 length = xorCipher.requiredEncryptionSpace(50);
+ ensure("requiredEncryptionSpace() function failed", (length == 50));
+
+ U32 lenEncrypted = xorCipher.encrypt((U8 *) str, str_len, encrypted, str_len);
+ ensure("Encryption failed", (lenEncrypted == str_len));
+ U32 lenDecrypted = xorCipher1.decrypt(encrypted, str_len, decrypted, str_len);
+ ensure("Decryption failed", (lenDecrypted == str_len));
+ ensure_memory_matches("LLXORCipher Encrypt/Decrypt failed", str, str_len, decrypted, lenDecrypted);
+ }
+
+ // operator=
+ template<> template<>
+ void cipher_object_t::test<2>()
+ {
+ const U8 pad[] = "ABCDEFGHIJKLMNOPQ"; // pad len longer than data to be ciphered
+ const U32 pad_len = sizeof(pad);
+ const U8 pad1[] = "SecondLife";
+ const U32 pad_len1 = sizeof(pad1);
+ const char str[] = "To Be Ciphered";
+ const S32 str_len = sizeof(str);
+ U8 encrypted[str_len];
+ U8 decrypted[str_len];
+
+ LLXORCipher xorCipher(pad, pad_len);
+ LLXORCipher xorCipher1(pad1, pad_len1);
+
+ xorCipher.encrypt((U8 *) str, str_len, encrypted, str_len);
+ // make xorCipher1 same as xorCipher..so that xorCipher1 can decrypt what was
+ // encrypted using xorCipher
+ xorCipher1 = xorCipher;
+ U32 lenDecrypted = xorCipher1.decrypt(encrypted, str_len, decrypted, str_len);
+ ensure_memory_matches("LLXORCipher operator= failed", str, str_len, decrypted, lenDecrypted);
+ }
+
+ //in place encrypt->decrypt
+ template<> template<>
+ void cipher_object_t::test<3>()
+ {
+ U32 padNum = 0x12349087;
+ const U8* pad = (U8*) &padNum;
+ const U32 pad_len = sizeof(U32);
+ char str[] = "To Be Ciphered a long string.........!!!.";
+ char str1[] = "To Be Ciphered a long string.........!!!."; // same as str
+ const S32 str_len = sizeof(str);
+
+ LLXORCipher xorCipher(pad, pad_len);
+ LLXORCipher xorCipher1(pad, pad_len);
+ xorCipher.encrypt((U8 *) str, str_len);
+ // it should not be the same as original data!
+ ensure("LLXORCipher: In Place encrypt failed", memcmp(str, str1, str_len) != 0);
+ xorCipher1.decrypt((U8 *) str, str_len);
+ // it should not be the same as original data!
+ ensure_memory_matches("LLXORCipher: In Place decrypt failed", str, str_len, str1, str_len);
+ }
+
+ //LLNullCipher encrypt->decrypt
+ template<> template<>
+ void cipher_object_t::test<4>()
+ {
+ const char str[] = "SecondLife";
+ const S32 str_len = sizeof(str);
+ U8 encrypted[str_len];
+ U8 decrypted[str_len];
+ LLNullCipher nullCipher;
+ LLNullCipher nullCipher1;
+
+ U32 length = nullCipher.requiredEncryptionSpace(50);
+ ensure("LLNullCipher::requiredEncryptionSpace() function failed", (length == 50));
+
+ U32 len1 = nullCipher.encrypt((U8 *) str, str_len, encrypted, str_len);
+ ensure_memory_matches("LLNullCipher - Source transformed during encryption.", encrypted, len1, str, str_len);
+
+ U32 len2 = nullCipher1.decrypt(encrypted, str_len, decrypted, str_len);
+ ensure_memory_matches("LLNullCipher - Decryption failed", decrypted, len2, str, str_len);
+ }
+}
diff --git a/indra/llmessage/tests/message_test.cpp b/indra/llmessage/tests/message_test.cpp
new file mode 100644
index 0000000000..6fb2b92803
--- /dev/null
+++ b/indra/llmessage/tests/message_test.cpp
@@ -0,0 +1,147 @@
+/**
+ * @file lldatapacker_tut.cpp
+ * @date 2007-04
+ * @brief LLDataPacker test cases.
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include <tut/tut.hpp>
+#include "linden_common.h"
+#include "lltut.h"
+#include "llhttpconstants.h"
+#include "llapr.h"
+#include "llmessageconfig.h"
+#include "llsdserialize.h"
+#include "message.h"
+#include "message_prehash.h"
+
+namespace
+{
+ struct Response : public LLHTTPNode::Response
+ {
+ virtual void result(const LLSD&) {}
+ virtual void status(S32 code, const std::string& message)
+ {
+ mStatus = code;
+ }
+ virtual void extendedResult(S32 code, const std::string& message, const LLSD& headers) { }
+ virtual void extendedResult(S32 code, const LLSD& result, const LLSD& headers) { }
+ S32 mStatus;
+ };
+}
+
+namespace tut
+{
+ struct LLMessageSystemTestData
+ {
+ std::string mTestConfigDir;
+ std::string mSep;
+
+ LLMessageSystemTestData()
+ {
+ static bool init = false;
+ if(!init)
+ {
+ ll_init_apr();
+ //init_prehash_data();
+ init = true;
+ }
+ const F32 circuit_heartbeat_interval=5;
+ const F32 circuit_timeout=100;
+
+
+ // currently test disconnected message system
+ start_messaging_system("notafile", 13035,
+ 1,
+ 0,
+ 0,
+ false,
+ "notasharedsecret",
+ NULL,
+ false,
+ circuit_heartbeat_interval,
+ circuit_timeout
+ );
+ // generate temp dir
+ std::ostringstream ostr;
+#if LL_WINDOWS
+ mSep = "\\";
+ ostr << "C:" << mSep;
+#else
+ mSep = "/";
+ ostr << mSep << "tmp" << mSep;
+#endif
+ LLUUID random;
+ random.generate();
+ ostr << "message-test-" << random;
+ mTestConfigDir = ostr.str();
+ LLFile::mkdir(mTestConfigDir);
+ writeConfigFile(LLSD());
+ LLMessageConfig::initClass("simulator", ostr.str());
+ }
+
+ ~LLMessageSystemTestData()
+ {
+ // not end_messaging_system()
+ delete static_cast<LLMessageSystem*>(gMessageSystem);
+ gMessageSystem = NULL;
+
+ // rm contents of temp dir
+ std::ostringstream ostr;
+ ostr << mTestConfigDir << mSep << "message.xml";
+ int rmfile = LLFile::remove(ostr.str());
+ ensure_equals("rmfile value", rmfile, 0);
+
+ // rm temp dir
+ int rmdir = LLFile::remove(mTestConfigDir);
+ ensure_equals("rmdir value", rmdir, 0);
+ }
+
+ void writeConfigFile(const LLSD& config)
+ {
+ std::string ostr(mTestConfigDir + mSep + "message.xml");
+ llofstream file(ostr.c_str());
+ if (file.is_open())
+ {
+ LLSDSerialize::toPrettyXML(config, file);
+ }
+ file.close();
+ }
+ };
+
+ typedef test_group<LLMessageSystemTestData> LLMessageSystemTestGroup;
+ typedef LLMessageSystemTestGroup::object LLMessageSystemTestObject;
+ LLMessageSystemTestGroup messageTestGroup("LLMessageSystem");
+
+ template<> template<>
+ void LLMessageSystemTestObject::test<1>()
+ // dispatch unknown message
+ {
+ const char* name = "notamessasge";
+ const LLSD message;
+ const LLPointer<Response> response = new Response();
+ gMessageSystem->dispatch(name, message, response);
+ ensure_equals(response->mStatus, HTTP_NOT_FOUND);
+ }
+}
+