PageRenderTime 77ms CodeModel.GetById 9ms app.highlight 61ms RepoModel.GetById 1ms app.codeStats 0ms

/indra/test/llsd_new_tut.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 854 lines | 613 code | 153 blank | 88 comment | 6 complexity | d9334b91dea1f331636c7e3544192877 MD5 | raw file
  1/** 
  2 * @file llsd_new_tut.cpp
  3 * @date   February 2006
  4 * @brief LLSD unit tests
  5 *
  6 * $LicenseInfo:firstyear=2006&license=viewerlgpl$
  7 * Second Life Viewer Source Code
  8 * Copyright (C) 2006-2011, Linden Research, Inc.
  9 * 
 10 * This library is free software; you can redistribute it and/or
 11 * modify it under the terms of the GNU Lesser General Public
 12 * License as published by the Free Software Foundation;
 13 * version 2.1 of the License only.
 14 * 
 15 * This library is distributed in the hope that it will be useful,
 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 18 * Lesser General Public License for more details.
 19 * 
 20 * You should have received a copy of the GNU Lesser General Public
 21 * License along with this library; if not, write to the Free Software
 22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 23 * 
 24 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 25 * $/LicenseInfo$
 26 */
 27
 28#define LLSD_DEBUG_INFO
 29#include <tut/tut.hpp>
 30#include "linden_common.h"
 31#include "lltut.h"
 32
 33#include "llsdtraits.h"
 34#include "llstring.h"
 35
 36#if LL_WINDOWS
 37#include <float.h>
 38namespace
 39{
 40	int fpclassify(double x)
 41	{
 42		return _fpclass(x);
 43	}
 44}
 45#else
 46using std::fpclassify;
 47#endif
 48
 49namespace tut
 50{
 51	class SDCleanupCheck
 52	{
 53	private:
 54		U32	mOutstandingAtStart;
 55	public:
 56		SDCleanupCheck() : mOutstandingAtStart(llsd::outstandingCount()) { }
 57		~SDCleanupCheck()
 58		{
 59			ensure_equals("SDCleanupCheck",
 60				llsd::outstandingCount(), mOutstandingAtStart);
 61		}
 62	};
 63
 64	class SDAllocationCheck : public SDCleanupCheck
 65	{
 66	private:
 67		std::string mMessage;
 68		U32 mExpectedAllocations;
 69		U32 mAllocationAtStart;
 70	public:
 71		SDAllocationCheck(const std::string& message, int expectedAllocations)
 72			: mMessage(message),
 73			mExpectedAllocations(expectedAllocations),
 74			mAllocationAtStart(llsd::allocationCount())
 75			{ }
 76		~SDAllocationCheck()
 77		{
 78			ensure_equals(mMessage + " SDAllocationCheck",
 79				llsd::allocationCount() - mAllocationAtStart,
 80				mExpectedAllocations);
 81		}
 82	};
 83	
 84	struct SDTestData {
 85		template<class T>
 86		static void ensureTypeAndValue(const char* msg, const LLSD& actual,
 87			T expectedValue)
 88		{
 89			LLSDTraits<T> traits;
 90			
 91			std::string s(msg);
 92			
 93			ensure(			s + " type",	traits.checkType(actual));
 94			ensure_equals(	s + " value",	traits.get(actual), expectedValue);
 95		}
 96	};
 97	
 98	typedef test_group<SDTestData>	SDTestGroup;
 99	typedef SDTestGroup::object		SDTestObject;
100
101	SDTestGroup sdTestGroup("LLSD(new)");
102	
103	template<> template<>
104	void SDTestObject::test<1>()
105		// construction and test of undefined
106	{
107		SDCleanupCheck check;
108		
109		LLSD u;
110		ensure("is undefined", u.isUndefined());
111	}
112	
113	template<> template<>
114	void SDTestObject::test<2>()
115		// setting and fetching scalar types
116	{
117		SDCleanupCheck check;
118		
119		LLSD v;
120
121		v = true;		ensureTypeAndValue("set true", v, true);
122		v = false;		ensureTypeAndValue("set false", v, false);
123		v = true;		ensureTypeAndValue("set true again", v, true);
124		
125		v = 42;			ensureTypeAndValue("set to 42", v, 42);
126		v = 0;			ensureTypeAndValue("set to zero", v, 0);
127		v = -12345;		ensureTypeAndValue("set to neg", v, -12345);
128		v = 2000000000;	ensureTypeAndValue("set to big", v, 2000000000);
129		
130		v = 3.14159265359;
131						ensureTypeAndValue("set to pi", v, 3.14159265359);
132						ensure_not_equals("isn't float", v.asReal(),
133							(float)3.14159265359);
134		v = 6.7e256;	ensureTypeAndValue("set to big", v, 6.7e256);
135		
136		LLUUID nullUUID;
137		LLUUID newUUID;
138		newUUID.generate();
139		
140		v = nullUUID;	ensureTypeAndValue("set to null UUID", v, nullUUID);
141		v = newUUID;	ensureTypeAndValue("set to new UUID", v, newUUID);
142		v = nullUUID;	ensureTypeAndValue("set to null again", v, nullUUID);
143		
144		// strings must be tested with two types of string objects
145		std::string s = "now is the time";
146		const char* cs = "for all good zorks";
147
148		v = s;			ensureTypeAndValue("set to std::string", v, s);		
149		v = cs;			ensureTypeAndValue("set to const char*", v, cs);
150	
151		LLDate epoch;
152		LLDate aDay("2001-10-22T10:11:12.00Z");
153		
154		v = epoch;		ensureTypeAndValue("set to epoch", v, epoch);
155		v = aDay;		ensureTypeAndValue("set to a day", v, aDay);
156		
157		LLURI path("http://slurl.com/secondlife/Ambleside/57/104/26/");
158		
159		v = path;		ensureTypeAndValue("set to a uri", v, path);
160		
161		const char source[] = "once in a blue moon";
162		std::vector<U8> data;
163		copy(&source[0], &source[sizeof(source)], back_inserter(data));
164		
165		v = data;		ensureTypeAndValue("set to data", v, data);
166		
167		v.clear();
168		ensure("reset to undefined", v.type() == LLSD::TypeUndefined);
169	}
170	
171	template<> template<>
172	void SDTestObject::test<3>()
173		// construction via scalar values
174		// tests both constructor and initialize forms
175	{
176		SDCleanupCheck check;
177		
178		LLSD b1(true);	ensureTypeAndValue("construct boolean", b1, true);
179		LLSD b2 = true;	ensureTypeAndValue("initialize  boolean", b2, true);
180		LLSD i1(42);	ensureTypeAndValue("construct int", i1, 42);
181		LLSD i2 =42;	ensureTypeAndValue("initialize  int", i2, 42);
182		LLSD d1(1.2);	ensureTypeAndValue("construct double", d1, 1.2);
183		LLSD d2 = 1.2;	ensureTypeAndValue("initialize double", d2, 1.2);
184		
185		LLUUID newUUID;
186		newUUID.generate();
187		LLSD u1(newUUID);
188						ensureTypeAndValue("construct UUID", u1, newUUID);
189		LLSD u2 = newUUID;
190						ensureTypeAndValue("initialize UUID", u2, newUUID);
191		
192		LLSD ss1(std::string("abc"));
193						ensureTypeAndValue("construct std::string", ss1, "abc");
194		LLSD ss2 = std::string("abc");
195						ensureTypeAndValue("initialize std::string",ss2, "abc");
196		LLSD sl1(std::string("def"));
197						ensureTypeAndValue("construct std::string", sl1, "def");
198		LLSD sl2 = std::string("def");
199						ensureTypeAndValue("initialize std::string", sl2, "def");
200		LLSD sc1("ghi");
201						ensureTypeAndValue("construct const char*", sc1, "ghi");
202		LLSD sc2 = "ghi";
203						ensureTypeAndValue("initialize const char*",sc2, "ghi");
204
205		LLDate aDay("2001-10-22T10:11:12.00Z");
206		LLSD t1(aDay);	ensureTypeAndValue("construct LLDate", t1, aDay);
207		LLSD t2 = aDay;	ensureTypeAndValue("initialize LLDate", t2, aDay);
208
209		LLURI path("http://slurl.com/secondlife/Ambleside/57/104/26/");
210		LLSD p1(path);	ensureTypeAndValue("construct LLURI", p1, path);
211		LLSD p2 = path;	ensureTypeAndValue("initialize LLURI", p2, path);
212
213		const char source[] = "once in a blue moon";
214		std::vector<U8> data;
215		copy(&source[0], &source[sizeof(source)], back_inserter(data));
216		LLSD x1(data);	ensureTypeAndValue("construct vector<U8>", x1, data);
217		LLSD x2 = data;	ensureTypeAndValue("initialize vector<U8>", x2, data);
218	}
219	
220	void checkConversions(const char* msg, const LLSD& v,
221		LLSD::Boolean eBoolean, LLSD::Integer eInteger,
222		LLSD::Real eReal, const LLSD::String& eString)
223	{
224		std::string s(msg);
225		
226		ensure_equals(s+" to bool",	v.asBoolean(),	eBoolean);
227		ensure_equals(s+" to int",	v.asInteger(),	eInteger);
228		if (eReal == eReal)
229		{
230			ensure_equals(s+" to real",	v.asReal(),		eReal);
231			ensure_equals(s+" to string",	v.asString(),	eString);
232		}
233		else
234		{
235			int left  = fpclassify(v.asReal());
236			int right = fpclassify(eReal);
237
238			ensure_equals(s+" to real", 	left, 			right);
239			// ensure_equals(s+" to string", v.asString(), eString);
240			// I've commented this check out, since there doesn't
241			// seem to be uniform string representation for NaN on
242			// all platforms. For example, on my Ubuntu 8.10 laptop
243			// with libc 2.11.1, sqrt(-1.0) will return '-nan', not
244			// 'nan'.
245		}
246	}
247	
248	template<> template<>
249	void SDTestObject::test<4>()
250		// conversion between undefined and basic scalar types:
251		//	boolean, integer, real and string
252	{
253		SDCleanupCheck check;
254		
255		LLSD v;			checkConversions("untitled", v, false, 0, 0.0, "");
256		
257		v = false;		checkConversions("false", v, false, 0, 0.0, "");
258		v = true;		checkConversions("true", v, true, 1, 1.0, "true");
259		
260		v = 0;			checkConversions("zero", v, false, 0, 0.0, "0");
261		v = 1;			checkConversions("one", v, true, 1, 1.0, "1");
262		v = -33;		checkConversions("neg33", v, true, -33, -33.0, "-33");
263		
264		v = 0.0;		checkConversions("0.0", v, false, 0, 0.0, "0");
265		v = 0.5;		checkConversions("point5", v, true, 0, 0.5, "0.5");
266		v = 0.9;		checkConversions("point9", v, true, 0, 0.9, "0.9");
267		v = -3.9;		checkConversions("neg3dot9", v, true, -3, -3.9, "-3.9");
268		v = sqrt(-1.0);	checkConversions("NaN", v, false, 0, sqrt(-1.0), "nan");
269		
270		v = "";			checkConversions("empty", v, false, 0, 0.0, "");
271		v = "0";		checkConversions("digit0", v, true, 0, 0.0, "0");
272		v = "10";		checkConversions("digit10", v, true, 10, 10.0, "10");
273		v = "-2.345";	checkConversions("decdigits", v,
274							true, -2, -2.345, "-2.345");
275		v = "apple";	checkConversions("apple", v, true, 0, 0.0, "apple");
276		v = "33bob";	checkConversions("digialpha", v, true, 0, 0.0, "33bob");
277		v = " ";		checkConversions("space", v, true, 0, 0.0, " ");
278		v = "\n";		checkConversions("newline", v, true, 0, 0.0, "\n");
279	}
280	
281	template<class T>
282	void checkRoundTrip(const std::string& msg, const LLSD& actual,
283		const char* sExpected, T vExpected)
284	{
285		std::string str = actual.asString();
286		
287		if (sExpected) {
288			ensure_equals(msg + " string", str, sExpected);
289		}
290		
291		LLSD u(str);
292		LLSDTraits<T> traits;
293		
294		ensure_equals(msg + " value", traits.get(u), vExpected);
295	}
296	
297	
298	template<> template<>
299	void SDTestObject::test<5>()
300		// conversion of String to and from UUID, Date and URI.
301	{
302		SDCleanupCheck check;
303		
304		LLSD v;
305		
306		LLUUID nullUUID;
307		LLUUID someUUID;
308		someUUID.generate();
309		
310		v = nullUUID;	checkRoundTrip("null uuid", v,
311							"00000000-0000-0000-0000-000000000000", nullUUID);
312		v = someUUID;	checkRoundTrip("random uuid", v, 0, someUUID);
313		
314		LLDate epoch;
315		LLDate beta("2003-04-30T04:00:00Z");
316		LLDate oneOh("2003-06-23T04:00:00Z");
317		
318		v = epoch;		checkRoundTrip("epoch date", v, 0, epoch);
319		v = beta;		checkRoundTrip("beta date", v,
320							"2003-04-30T04:00:00Z", beta);
321		v = oneOh;		checkRoundTrip("1.0 date", v,
322							"2003-06-23T04:00:00Z", oneOh);
323		
324		LLURI empty;
325		LLURI path("http://slurl.com/secondlife/Ambleside/57/104/26/");
326		LLURI mail("mailto:zero.linden@secondlife.com");
327		
328		v = empty;		checkRoundTrip("empty URI", v, 0, empty);
329		v = path;		checkRoundTrip("path URI", v,
330							"http://slurl.com/secondlife/Ambleside/57/104/26/",
331							path);
332		v = mail;		checkRoundTrip("mail URI", v,
333							"mailto:zero.linden@secondlife.com", mail);
334	}
335	
336	template<> template<>
337	void SDTestObject::test<6>()
338		// copy construction and assignment
339		// checking for shared values after constr. or assignment
340		// checking in both the same type and change of type case
341	{
342		SDCleanupCheck check;
343		
344		{
345			LLSD v = 42;
346		
347			LLSD w0(v);
348			ensureTypeAndValue("int constr.", w0, 42);
349			
350			LLSD w1(v);
351			w1 = 13;
352			ensureTypeAndValue("int constr. change case 1", w1, 13);
353			ensureTypeAndValue("int constr. change case 2", v, 42);
354			
355			LLSD w2(v);
356			v = 7;
357			ensureTypeAndValue("int constr. change case 3", w2, 42);
358			ensureTypeAndValue("int constr. change case 4", v, 7);
359		}
360
361		{
362			LLSD v = 42;
363		
364			LLSD w1(v);
365			w1 = "bob";
366			ensureTypeAndValue("string constr. change case 1", w1, "bob");
367			ensureTypeAndValue("string constr. change case 2", v, 42);
368			
369			LLSD w2(v);
370			v = "amy";
371			ensureTypeAndValue("string constr. change case 3", w2, 42);
372			ensureTypeAndValue("string constr. change case 4", v, "amy");
373		}
374
375		{
376			LLSD v = 42;
377		
378			LLSD w0;
379			w0 = v;
380			ensureTypeAndValue("int assign", w0, 42);
381			
382			LLSD w1;
383			w1 = v;
384			w1 = 13;
385			ensureTypeAndValue("int assign change case 1", w1, 13);
386			ensureTypeAndValue("int assign change case 2", v, 42);
387			
388			LLSD w2;
389			w2 = v;
390			v = 7;
391			ensureTypeAndValue("int assign change case 3", w2, 42);
392			ensureTypeAndValue("int assign change case 4", v, 7);
393		}
394
395		{
396			LLSD v = 42;
397		
398			LLSD w1;
399			w1 = v;
400			w1 = "bob";
401			ensureTypeAndValue("string assign change case 1", w1, "bob");
402			ensureTypeAndValue("string assign change case 2", v, 42);
403			
404			LLSD w2;
405			w2 = v;
406			v = "amy";
407			ensureTypeAndValue("string assign change case 3", w2, 42);
408			ensureTypeAndValue("string assign change case 4", v, "amy");
409		}
410	}
411	
412	
413	template<> template<>
414	void SDTestObject::test<7>()
415		// Test assignment and casting to various scalar types.  These
416		// assignments should invoke the right conversion without it being
417		// mentioned explicitly.  The few exceptions are marked SAD.
418	{
419		SDCleanupCheck check;
420		
421		LLSD v("  42.375");
422		
423		bool b = false;
424		b = v;				ensure_equals("assign to bool", b, true);
425		b = (bool)v;		ensure_equals("cast to bool", b, true);
426		
427		int i = 99;
428		i = v;				ensure_equals("assign to int", i, 42);
429		i = (int)v;			ensure_equals("cast to int", i, 42);
430		
431		double d = 3.14159;
432		d = v;				ensure_equals("assign to double", d, 42.375);
433		d = (double)v;		ensure_equals("cast to double", d, 42.375);
434		
435		std::string s = "yo";
436// SAD	s = v;				ensure_equals("assign to string", s, "  42.375");
437		s = (std::string)v;	ensure_equals("cast to string", s, "  42.375");
438
439		std::string uuidStr = "b1e50c2b-b627-4d23-8a86-a65d97b6319b";
440		v = uuidStr;
441		LLUUID u;
442		u = v;
443					ensure_equals("assign to LLUUID", u, LLUUID(uuidStr));
444// SAD	u = (LLUUID)v;
445//					ensure_equals("cast to LLUUID", u, LLUUID(uuidStr));
446		
447		std::string dateStr = "2005-10-24T15:00:00Z";
448		v = dateStr;
449		LLDate date;
450		date = v;
451					ensure_equals("assign to LLDate", date.asString(), dateStr);
452// SAD	date = (LLDate)v;
453//					ensure_equals("cast to LLDate", date.asString(), dateStr);
454		
455		std::string uriStr = "http://secondlife.com";
456		v = uriStr;
457		LLURI uri;
458		uri = v;
459					ensure_equals("assign to LLURI", uri.asString(), uriStr);
460// SAD 	uri = (LLURI)v;
461//					ensure_equals("cast to LLURI", uri.asString(), uriStr);
462	}
463	
464	template<> template<>
465	void SDTestObject::test<8>()
466		// Test construction of various scalar types from LLSD.
467		// Test both construction and initialization forms.
468		// These should invoke the right conversion without it being
469		// mentioned explicitly.  The few exceptions are marked SAD.
470	{
471		SDCleanupCheck check;
472		
473		LLSD v("  42.375");
474		
475		bool b1(v);		ensure_equals("contruct bool", b1, true);
476		bool b2 = v;	ensure_equals("initialize bool", b2, true);
477				
478		int i1(v);		ensure_equals("contruct int", i1, 42);
479		int i2 = v;		ensure_equals("initialize int", i2, 42);
480		
481		double d1(v);	ensure_equals("contruct double", d1, 42.375);
482		double d2 = v;	ensure_equals("initialize double", d2, 42.375);
483		
484		std::string s1(v);
485		std::string s2 = v;
486						ensure_equals("contruct string", s1, "  42.375");
487						ensure_equals("initialize string", s2, "  42.375");
488
489		std::string t1(v);
490		std::string t2 = v.asString();		// SAD
491						ensure_equals("contruct std::string", t1, "  42.375");
492						ensure_equals("initialize std::string", t2, "  42.375");
493
494		std::string uuidStr = "b1e50c2b-b627-4d23-8a86-a65d97b6319b";
495		v = uuidStr;
496		LLUUID uuid1(v.asUUID());		// SAD
497		LLUUID uuid2 = v;
498				ensure_equals("contruct LLUUID", uuid1, LLUUID(uuidStr));
499				ensure_equals("initialize LLUUID", uuid2, LLUUID(uuidStr));
500
501		std::string dateStr = "2005-10-24T15:00:00Z";
502		v = dateStr;
503		LLDate date1(v.asDate());		// SAD
504		LLDate date2 = v;
505				ensure_equals("contruct LLDate", date1.asString(), dateStr);
506				ensure_equals("initialize LLDate", date2.asString(), dateStr);
507				
508		std::string uriStr = "http://secondlife.com";
509		v = uriStr;
510		LLURI uri1(v.asURI());			// SAD
511		LLURI uri2 = v;
512				ensure_equals("contruct LLURI", uri1.asString(), uriStr);
513				ensure_equals("initialize LLURI", uri2.asString(), uriStr);
514	}
515	
516	
517	template<> template<>
518	void SDTestObject::test<9>()
519		// test to make sure v is interpreted as a bool in a various
520		// scenarios.
521	{
522		SDCleanupCheck check;
523		
524		LLSD v = "0";
525		// magic value that is interpreted as boolean true, but integer false!
526		
527		ensure_equals("trinary operator bool", (v ? true : false), true);
528		ensure_equals("convert to int, then bool",
529											((int)v ? true : false), false);
530
531		if(v)
532		{
533			ensure("if converted to bool", true);
534		}
535		else
536		{
537			fail("bool did not convert to a bool in if statement.");
538		}
539
540		if(!v)
541		{
542			fail("bool did not convert to a bool in negated if statement.");
543		}
544	}
545	
546	template<> template<>
547	void SDTestObject::test<10>()
548		// map operations
549	{
550		SDCleanupCheck check;
551		
552		LLSD v;
553		ensure("undefined has no members", !v.has("amy"));
554		ensure("undefined get() is undefined", v.get("bob").isUndefined());
555		
556		v = LLSD::emptyMap();
557		ensure("empty map is a map", v.isMap());
558		ensure("empty map has no members", !v.has("cam"));
559		ensure("empty map get() is undefined", v.get("don").isUndefined());
560		
561		v.clear();
562		v.insert("eli", 43);
563		ensure("insert converts to map", v.isMap());
564		ensure("inserted key is present", v.has("eli"));
565		ensureTypeAndValue("inserted value", v.get("eli"), 43);
566		
567		v.insert("fra", false);
568		ensure("first key still present", v.has("eli"));
569		ensure("second key is present", v.has("fra"));
570		ensureTypeAndValue("first value", v.get("eli"), 43);
571		ensureTypeAndValue("second value", v.get("fra"), false);
572		
573		v.erase("eli");
574		ensure("first key now gone", !v.has("eli"));
575		ensure("second key still present", v.has("fra"));
576		ensure("first value gone", v.get("eli").isUndefined());
577		ensureTypeAndValue("second value sill there", v.get("fra"), false);
578		
579		v.erase("fra");
580		ensure("second key now gone", !v.has("fra"));
581		ensure("second value gone", v.get("fra").isUndefined());
582		
583		v["gil"] = (std::string)"good morning";
584		ensure("third key present", v.has("gil"));
585		ensureTypeAndValue("third key value", v.get("gil"), "good morning");
586		
587		const LLSD& cv = v;	// FIX ME IF POSSIBLE
588		ensure("missing key", cv["ham"].isUndefined());
589		ensure("key not present", !v.has("ham"));
590	
591		LLSD w = 43;
592		const LLSD& cw = w;	// FIX ME IF POSSIBLE
593		int i = cw["ian"];
594		ensureTypeAndValue("other missing value", i, 0);
595		ensure("other missing key", !w.has("ian"));
596		ensure("no conversion", w.isInteger());
597		
598		LLSD x;
599		x = v;
600		ensure("copy map type", x.isMap());
601		ensureTypeAndValue("copy map value gil", x.get("gil"), "good morning");
602	}
603	
604	
605	template<> template<>
606	void SDTestObject::test<11>()
607		// array operations
608	{
609		SDCleanupCheck check;
610		
611		LLSD v;
612		ensure_equals("undefined has no size", v.size(), 0);
613		ensure("undefined get() is undefined", v.get(0).isUndefined());
614		
615		v = LLSD::emptyArray();
616		ensure("empty array is an array", v.isArray());
617		ensure_equals("empty array has no size", v.size(), 0);
618		ensure("empty map get() is undefined", v.get(0).isUndefined());
619		
620		v.clear();
621		v.append(88);
622		v.append("noodle");
623		v.append(true);
624		ensure_equals("appened array size", v.size(), 3);
625		ensure("append array is an array", v.isArray());
626		ensureTypeAndValue("append 0", v[0], 88);
627		ensureTypeAndValue("append 1", v[1], "noodle");
628		ensureTypeAndValue("append 2", v[2], true);
629		
630		v.insert(0, 77);
631		v.insert(2, "soba");
632		v.insert(4, false);
633		ensure_equals("inserted array size", v.size(), 6);
634		ensureTypeAndValue("post insert 0", v[0], 77);
635		ensureTypeAndValue("post insert 1", v[1], 88);
636		ensureTypeAndValue("post insert 2", v[2], "soba");
637		ensureTypeAndValue("post insert 3", v[3], "noodle");
638		ensureTypeAndValue("post insert 4", v[4], false);
639		ensureTypeAndValue("post insert 5", v[5], true);
640		
641		ensureTypeAndValue("get 1", v.get(1), 88);
642		v.set(1, "hot");
643		ensureTypeAndValue("set 1", v.get(1), "hot");
644		
645		v.erase(3);
646		ensure_equals("post erase array size", v.size(), 5);
647		ensureTypeAndValue("post erase 0", v[0], 77);
648		ensureTypeAndValue("post erase 1", v[1], "hot");
649		ensureTypeAndValue("post erase 2", v[2], "soba");
650		ensureTypeAndValue("post erase 3", v[3], false);
651		ensureTypeAndValue("post erase 4", v[4], true);
652		
653		v.append(34);
654		ensure_equals("size after append", v.size(), 6);
655		ensureTypeAndValue("post append 5", v[5], 34);
656
657		LLSD w;
658		w = v;
659		ensure("copy array type", w.isArray());
660		ensure_equals("copy array size", w.size(), 6);
661		ensureTypeAndValue("copy array 0", w[0], 77);
662		ensureTypeAndValue("copy array 1", w[1], "hot");
663		ensureTypeAndValue("copy array 2", w[2], "soba");
664		ensureTypeAndValue("copy array 3", w[3], false);
665		ensureTypeAndValue("copy array 4", w[4], true);
666		ensureTypeAndValue("copy array 5", w[5], 34);
667	}
668
669
670	template<> template<>
671	void SDTestObject::test<12>()
672		// no sharing
673	{
674		SDCleanupCheck check;
675		
676		LLSD a = 99;
677		LLSD b = a;
678		a = 34;
679		ensureTypeAndValue("top level original changed",	a, 34);
680		ensureTypeAndValue("top level copy unaltered",		b, 99);
681		b = a;
682		b = 66;
683		ensureTypeAndValue("top level original unaltered",	a, 34);
684		ensureTypeAndValue("top level copy changed",		b, 66);
685
686		a[0] = "uno";
687		a[1] = 99;
688		a[2] = 1.414;
689		b = a;
690		a[1] = 34;
691		ensureTypeAndValue("array member original changed",	a[1], 34);
692		ensureTypeAndValue("array member copy unaltered",	b[1], 99);
693		b = a;
694		b[1] = 66;
695		ensureTypeAndValue("array member original unaltered", a[1], 34);
696		ensureTypeAndValue("array member copy changed",		b[1], 66);
697		
698		a["alpha"] = "uno";
699		a["beta"] = 99;
700		a["gamma"] = 1.414;
701		b = a;
702		a["beta"] = 34;
703		ensureTypeAndValue("map member original changed",	a["beta"], 34);
704		ensureTypeAndValue("map member copy unaltered",		b["beta"], 99);
705		b = a;
706		b["beta"] = 66;
707		ensureTypeAndValue("map member original unaltered",	a["beta"], 34);
708		ensureTypeAndValue("map member copy changed",		b["beta"], 66);
709	}
710	
711	template<> template<>
712	void SDTestObject::test<13>()
713		// sharing implementation
714	{
715		SDCleanupCheck check;
716		
717		{
718			SDAllocationCheck check("copy construct undefinded", 0);
719			LLSD v;
720			LLSD w = v;
721		}
722		
723		{
724			SDAllocationCheck check("assign undefined", 0);
725			LLSD v;
726			LLSD w;
727			w = v;
728		}
729		
730		{
731			SDAllocationCheck check("assign integer value", 1);
732			LLSD v = 45;
733			v = 33;
734			v = 0;
735		}
736
737		{
738			SDAllocationCheck check("copy construct integer", 1);
739			LLSD v = 45;
740			LLSD w = v;
741		}
742
743		{
744			SDAllocationCheck check("assign integer", 1);
745			LLSD v = 45;
746			LLSD w;
747			w = v;
748		}
749		
750		{
751			SDAllocationCheck check("avoids extra clone", 2);
752			LLSD v = 45;
753			LLSD w = v;
754			w = "nice day";
755		}
756
757		{
758			SDAllocationCheck check("shared values test for threaded work", 9);
759
760			//U32 start_llsd_count = llsd::outstandingCount();
761
762			LLSD m = LLSD::emptyMap();
763
764			m["one"] = 1;
765			m["two"] = 2;
766			m["one_copy"] = m["one"];			// 3 (m, "one" and "two")
767
768			m["undef_one"] = LLSD();
769			m["undef_two"] = LLSD();
770			m["undef_one_copy"] = m["undef_one"];
771
772			{	// Ensure first_array gets freed to avoid counting it
773				LLSD first_array = LLSD::emptyArray();
774				first_array.append(1.0f);
775				first_array.append(2.0f);			
776				first_array.append(3.0f);			// 7
777
778				m["array"] = first_array;
779				m["array_clone"] = first_array;
780				m["array_copy"] = m["array"];		// 7
781			}
782
783			m["string_one"] = "string one value";
784			m["string_two"] = "string two value";
785			m["string_one_copy"] = m["string_one"];		// 9
786
787			//U32 llsd_object_count = llsd::outstandingCount();
788			//std::cout << "Using " << (llsd_object_count - start_llsd_count) << " LLSD objects" << std::endl;
789
790			//m.dumpStats();
791		}
792
793		{
794			SDAllocationCheck check("shared values test for threaded work", 9);
795
796			//U32 start_llsd_count = LLSD::outstandingCount();
797
798			LLSD m = LLSD::emptyMap();
799
800			m["one"] = 1;
801			m["two"] = 2;
802			m["one_copy"] = m["one"];			// 3 (m, "one" and "two")
803
804			m["undef_one"] = LLSD();
805			m["undef_two"] = LLSD();
806			m["undef_one_copy"] = m["undef_one"];
807
808			{	// Ensure first_array gets freed to avoid counting it
809				LLSD first_array = LLSD::emptyArray();
810				first_array.append(1.0f);
811				first_array.append(2.0f);			
812				first_array.append(3.0f);			// 7
813
814				m["array"] = first_array;
815				m["array_clone"] = first_array;
816				m["array_copy"] = m["array"];		// 7
817			}
818
819			m["string_one"] = "string one value";
820			m["string_two"] = "string two value";
821			m["string_one_copy"] = m["string_one"];		// 9
822
823			//U32 llsd_object_count = LLSD::outstandingCount();
824			//std::cout << "Using " << (llsd_object_count - start_llsd_count) << " LLSD objects" << std::endl;
825
826			//m.dumpStats();
827		}
828	}
829
830	template<> template<>
831	void SDTestObject::test<14>()
832		// make sure that assignment of char* NULL in a string does not crash.
833	{
834		LLSD v;
835		v = (const char*)NULL;
836		ensure("type is a string", v.isString());
837	}
838
839	/* TO DO:
840		conversion of undefined to UUID, Date, URI and Binary
841		conversion of undefined to map and array
842		test map operations
843		test array operations
844		test array extension
845		
846		test copying and assign maps and arrays (clone)
847		test iteration over map
848		test iteration over array
849		test iteration over scalar
850
851		test empty map and empty array are indeed shared
852		test serializations
853	*/
854}