PageRenderTime 67ms CodeModel.GetById 2ms app.highlight 59ms RepoModel.GetById 1ms app.codeStats 0ms

/indra/llcommon/tests/llstring_test.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 753 lines | 561 code | 115 blank | 77 comment | 111 complexity | a921848495f9aba721a88f16205b373c MD5 | raw file
  1/** 
  2 * @file llstring_test.cpp
  3 * @author Adroit, Steve Linden, Tofu Linden
  4 * @date 2006-12-24
  5 * @brief Test cases of llstring.cpp
  6 *
  7 * $LicenseInfo:firstyear=2007&license=viewerlgpl$
  8 * Second Life Viewer Source Code
  9 * Copyright (C) 2010, Linden Research, Inc.
 10 * 
 11 * This library is free software; you can redistribute it and/or
 12 * modify it under the terms of the GNU Lesser General Public
 13 * License as published by the Free Software Foundation;
 14 * version 2.1 of the License only.
 15 * 
 16 * This library is distributed in the hope that it will be useful,
 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 19 * Lesser General Public License for more details.
 20 * 
 21 * You should have received a copy of the GNU Lesser General Public
 22 * License along with this library; if not, write to the Free Software
 23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 24 * 
 25 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 26 * $/LicenseInfo$
 27 */
 28
 29#include "linden_common.h"
 30#include "../test/lltut.h"
 31
 32#include "../llstring.h"
 33
 34namespace tut
 35{
 36	struct string_index
 37	{
 38	};
 39	typedef test_group<string_index> string_index_t;
 40	typedef string_index_t::object string_index_object_t;
 41	tut::string_index_t tut_string_index("LLString");
 42
 43	template<> template<>
 44	void string_index_object_t::test<1>()
 45	{
 46		std::string llstr1;
 47		ensure("Empty std::string", (llstr1.size() == 0) && llstr1.empty());
 48
 49		std::string llstr2("Hello");
 50		ensure("std::string = Hello", (!strcmp(llstr2.c_str(), "Hello")) && (llstr2.size() == 5) && !llstr2.empty());
 51
 52		std::string llstr3(llstr2);
 53		ensure("std::string = std::string(std::string)", (!strcmp(llstr3.c_str(), "Hello")) && (llstr3.size() == 5) && !llstr3.empty());
 54
 55		std::string str("Hello World");
 56		std::string llstr4(str, 6);
 57		ensure("std::string = std::string(s, size_type pos, size_type n = npos)", (!strcmp(llstr4.c_str(), "World")) && (llstr4.size() == 5) && !llstr4.empty());
 58
 59		std::string llstr5(str, str.size());
 60		ensure("std::string = std::string(s, size_type pos, size_type n = npos)", (llstr5.size() == 0) && llstr5.empty());
 61
 62		std::string llstr6(5, 'A');
 63		ensure("std::string = std::string(count, c)", (!strcmp(llstr6.c_str(), "AAAAA")) && (llstr6.size() == 5) && !llstr6.empty());
 64
 65		std::string llstr7("Hello World", 5);
 66		ensure("std::string(s, n)", (!strcmp(llstr7.c_str(), "Hello")) && (llstr7.size() == 5) && !llstr7.empty());
 67
 68		std::string llstr8("Hello World", 6, 5);
 69		ensure("std::string(s, n, count)", (!strcmp(llstr8.c_str(), "World")) && (llstr8.size() == 5) && !llstr8.empty());
 70
 71		std::string llstr9("Hello World", sizeof("Hello World")-1, 5); // go past end
 72		ensure("std::string(s, n, count) goes past end", (llstr9.size() == 0) && llstr9.empty());
 73	}
 74
 75	template<> template<>
 76	void string_index_object_t::test<3>()
 77	{
 78		std::string str("Len=5");
 79		ensure("isValidIndex failed", LLStringUtil::isValidIndex(str, 0) == TRUE &&
 80									  LLStringUtil::isValidIndex(str, 5) == TRUE &&
 81									  LLStringUtil::isValidIndex(str, 6) == FALSE);
 82
 83		std::string str1;
 84		ensure("isValidIndex failed fo rempty string", LLStringUtil::isValidIndex(str1, 0) == FALSE);
 85	}
 86
 87	template<> template<>
 88	void string_index_object_t::test<4>()
 89	{
 90		std::string str_val("               Testing the extra whitespaces   ");
 91		LLStringUtil::trimHead(str_val);
 92		ensure_equals("1: trimHead failed", str_val, "Testing the extra whitespaces   ");
 93
 94		std::string str_val1("\n\t\r\n  Testing the extra whitespaces   ");
 95		LLStringUtil::trimHead(str_val1);
 96		ensure_equals("2: trimHead failed", str_val1, "Testing the extra whitespaces   ");
 97	}
 98
 99	template<> template<>
100	void string_index_object_t::test<5>()
101	{
102		std::string str_val("  Testing the   extra     whitespaces         ");
103		LLStringUtil::trimTail(str_val);
104		ensure_equals("1: trimTail failed", str_val, "  Testing the   extra     whitespaces");
105
106		std::string str_val1("\n  Testing the extra whitespaces  \n\t\r\n   ");
107		LLStringUtil::trimTail(str_val1);
108		ensure_equals("2: trimTail failed", str_val1, "\n  Testing the extra whitespaces");
109	}
110
111
112	template<> template<>
113	void string_index_object_t::test<6>()
114	{
115		std::string str_val("  \t \r Testing the   extra     \r\n whitespaces     \n \t    ");
116		LLStringUtil::trim(str_val);
117		ensure_equals("1: trim failed", str_val, "Testing the   extra     \r\n whitespaces");
118	}
119
120	template<> template<>
121	void string_index_object_t::test<7>()
122	{
123		std::string str("Second LindenLabs");
124		LLStringUtil::truncate(str, 6);
125		ensure_equals("1: truncate", str, "Second");
126
127		// further truncate more than the length
128		LLStringUtil::truncate(str, 0);
129		ensure_equals("2: truncate", str, "");
130	}
131
132	template<> template<>
133	void string_index_object_t::test<8>()
134	{
135		std::string str_val("SecondLife Source");
136		LLStringUtil::toUpper(str_val);
137		ensure_equals("toUpper failed", str_val, "SECONDLIFE SOURCE");
138	}
139
140	template<> template<>
141	void string_index_object_t::test<9>()
142	{
143		std::string str_val("SecondLife Source");
144		LLStringUtil::toLower(str_val);
145		ensure_equals("toLower failed", str_val, "secondlife source");
146	}
147
148	template<> template<>
149	void string_index_object_t::test<10>()
150	{
151		std::string str_val("Second");
152		ensure("1. isHead failed", LLStringUtil::isHead(str_val, "SecondLife Source") == TRUE);
153		ensure("2. isHead failed", LLStringUtil::isHead(str_val, " SecondLife Source") == FALSE);
154		std::string str_val2("");
155		ensure("3. isHead failed", LLStringUtil::isHead(str_val2, "") == FALSE);
156	}
157
158	template<> template<>
159	void string_index_object_t::test<11>()
160	{
161		std::string str_val("Hello.\n\n Lindenlabs. \n This is \na simple test.\n");
162		std::string orig_str_val(str_val);
163		LLStringUtil::addCRLF(str_val);
164		ensure_equals("addCRLF failed", str_val, "Hello.\r\n\r\n Lindenlabs. \r\n This is \r\na simple test.\r\n");
165		LLStringUtil::removeCRLF(str_val);
166		ensure_equals("removeCRLF failed", str_val, orig_str_val);
167	}
168
169	template<> template<>
170	void string_index_object_t::test<12>()
171	{
172		std::string str_val("Hello.\n\n\t \t Lindenlabs. \t\t");
173		std::string orig_str_val(str_val);
174		LLStringUtil::replaceTabsWithSpaces(str_val, 1);
175		ensure_equals("replaceTabsWithSpaces failed", str_val, "Hello.\n\n    Lindenlabs.   ");
176		LLStringUtil::replaceTabsWithSpaces(orig_str_val, 0);
177		ensure_equals("replaceTabsWithSpaces failed for 0", orig_str_val, "Hello.\n\n  Lindenlabs. ");
178
179		str_val = "\t\t\t\t";
180		LLStringUtil::replaceTabsWithSpaces(str_val, 0);
181		ensure_equals("replaceTabsWithSpaces failed for all tabs", str_val, "");
182	}
183
184	template<> template<>
185	void string_index_object_t::test<13>()
186	{
187		std::string str_val("Hello.\n\n\t\t\r\nLindenlabsX.");
188		LLStringUtil::replaceNonstandardASCII(str_val, 'X');
189		ensure_equals("replaceNonstandardASCII failed", str_val, "Hello.\n\nXXX\nLindenlabsX.");
190	}
191
192	template<> template<>
193	void string_index_object_t::test<14>()
194	{
195		std::string str_val("Hello.\n\t\r\nABCDEFGHIABABAB");
196		LLStringUtil::replaceChar(str_val, 'A', 'X');
197		ensure_equals("1: replaceChar failed", str_val, "Hello.\n\t\r\nXBCDEFGHIXBXBXB");
198		std::string str_val1("Hello.\n\t\r\nABCDEFGHIABABAB");
199	}
200
201	template<> template<>
202	void string_index_object_t::test<15>()
203	{
204		std::string str_val("Hello.\n\r\t");
205		ensure("containsNonprintable failed", LLStringUtil::containsNonprintable(str_val) == TRUE);
206
207		str_val = "ABC ";
208		ensure("containsNonprintable failed", LLStringUtil::containsNonprintable(str_val) == FALSE);
209	}
210
211	template<> template<>
212	void string_index_object_t::test<16>()
213	{
214		std::string str_val("Hello.\n\r\t Again!");
215		LLStringUtil::stripNonprintable(str_val);
216		ensure_equals("stripNonprintable failed", str_val, "Hello. Again!");
217
218		str_val = "\r\n\t\t";
219		LLStringUtil::stripNonprintable(str_val);
220		ensure_equals("stripNonprintable resulting in empty string failed", str_val, "");
221
222		str_val = "";
223		LLStringUtil::stripNonprintable(str_val);
224		ensure_equals("stripNonprintable of empty string resulting in empty string failed", str_val, "");
225	}
226
227	template<> template<>
228	void string_index_object_t::test<17>()
229	{
230		BOOL value;
231		std::string str_val("1");
232		ensure("convertToBOOL 1 failed", LLStringUtil::convertToBOOL(str_val, value) && value);
233		str_val = "T";
234		ensure("convertToBOOL T failed", LLStringUtil::convertToBOOL(str_val, value) && value);
235		str_val = "t";
236		ensure("convertToBOOL t failed", LLStringUtil::convertToBOOL(str_val, value) && value);
237		str_val = "TRUE";
238		ensure("convertToBOOL TRUE failed", LLStringUtil::convertToBOOL(str_val, value) && value);
239		str_val = "True";
240		ensure("convertToBOOL True failed", LLStringUtil::convertToBOOL(str_val, value) && value);
241		str_val = "true";
242		ensure("convertToBOOL true failed", LLStringUtil::convertToBOOL(str_val, value) && value);
243
244		str_val = "0";
245		ensure("convertToBOOL 0 failed", LLStringUtil::convertToBOOL(str_val, value) && !value);
246		str_val = "F";
247		ensure("convertToBOOL F failed", LLStringUtil::convertToBOOL(str_val, value) && !value);
248		str_val = "f";
249		ensure("convertToBOOL f failed", LLStringUtil::convertToBOOL(str_val, value) && !value);
250		str_val = "FALSE";
251		ensure("convertToBOOL FASLE failed", LLStringUtil::convertToBOOL(str_val, value) && !value);
252		str_val = "False";
253		ensure("convertToBOOL False failed", LLStringUtil::convertToBOOL(str_val, value) && !value);
254		str_val = "false";
255		ensure("convertToBOOL false failed", LLStringUtil::convertToBOOL(str_val, value) && !value);
256
257		str_val = "Tblah";
258		ensure("convertToBOOL false failed", !LLStringUtil::convertToBOOL(str_val, value));
259	}
260
261	template<> template<>
262	void string_index_object_t::test<18>()
263	{
264		U8 value;
265		std::string str_val("255");
266		ensure("1: convertToU8 failed", LLStringUtil::convertToU8(str_val, value) && value == 255);
267
268		str_val = "0";
269		ensure("2: convertToU8 failed", LLStringUtil::convertToU8(str_val, value) && value == 0);
270
271		str_val = "-1";
272		ensure("3: convertToU8 failed", !LLStringUtil::convertToU8(str_val, value));
273
274		str_val = "256"; // bigger than MAX_U8
275		ensure("4: convertToU8 failed", !LLStringUtil::convertToU8(str_val, value));
276	}
277
278	template<> template<>
279	void string_index_object_t::test<19>()
280	{
281		S8 value;
282		std::string str_val("127");
283		ensure("1: convertToS8 failed", LLStringUtil::convertToS8(str_val, value) && value == 127);
284
285		str_val = "0";
286		ensure("2: convertToS8 failed", LLStringUtil::convertToS8(str_val, value) && value == 0);
287
288		str_val = "-128";
289		ensure("3: convertToS8 failed", LLStringUtil::convertToS8(str_val, value) && value == -128);
290
291		str_val = "128"; // bigger than MAX_S8
292		ensure("4: convertToS8 failed", !LLStringUtil::convertToS8(str_val, value));
293
294		str_val = "-129"; 
295		ensure("5: convertToS8 failed", !LLStringUtil::convertToS8(str_val, value));
296	}
297
298	template<> template<>
299	void string_index_object_t::test<20>()
300	{
301		S16 value;
302		std::string str_val("32767"); 
303		ensure("1: convertToS16 failed", LLStringUtil::convertToS16(str_val, value) && value == 32767);
304
305		str_val = "0";
306		ensure("2: convertToS16 failed", LLStringUtil::convertToS16(str_val, value) && value == 0);
307
308		str_val = "-32768";
309		ensure("3: convertToS16 failed", LLStringUtil::convertToS16(str_val, value) && value == -32768);
310
311		str_val = "32768"; 
312		ensure("4: convertToS16 failed", !LLStringUtil::convertToS16(str_val, value));
313
314		str_val = "-32769";
315		ensure("5: convertToS16 failed", !LLStringUtil::convertToS16(str_val, value));
316	}
317
318	template<> template<>
319	void string_index_object_t::test<21>()
320	{
321		U16 value;
322		std::string str_val("65535"); //0xFFFF
323		ensure("1: convertToU16 failed", LLStringUtil::convertToU16(str_val, value) && value == 65535);
324
325		str_val = "0";
326		ensure("2: convertToU16 failed", LLStringUtil::convertToU16(str_val, value) && value == 0);
327
328		str_val = "-1"; 
329		ensure("3: convertToU16 failed", !LLStringUtil::convertToU16(str_val, value));
330
331		str_val = "65536"; 
332		ensure("4: convertToU16 failed", !LLStringUtil::convertToU16(str_val, value));
333	}
334
335	template<> template<>
336	void string_index_object_t::test<22>()
337	{
338		U32 value;
339		std::string str_val("4294967295"); //0xFFFFFFFF
340		ensure("1: convertToU32 failed", LLStringUtil::convertToU32(str_val, value) && value == 4294967295UL);
341
342		str_val = "0";
343		ensure("2: convertToU32 failed", LLStringUtil::convertToU32(str_val, value) && value == 0);
344
345		str_val = "4294967296"; 
346		ensure("3: convertToU32 failed", !LLStringUtil::convertToU32(str_val, value));
347	}
348
349	template<> template<>
350	void string_index_object_t::test<23>()
351	{
352		S32 value;
353		std::string str_val("2147483647"); //0x7FFFFFFF
354		ensure("1: convertToS32 failed", LLStringUtil::convertToS32(str_val, value) && value == 2147483647);
355
356		str_val = "0";
357		ensure("2: convertToS32 failed", LLStringUtil::convertToS32(str_val, value) && value == 0);
358
359		// Avoid "unary minus operator applied to unsigned type" warning on VC++. JC
360		S32 min_val = -2147483647 - 1;
361		str_val = "-2147483648"; 
362		ensure("3: convertToS32 failed", LLStringUtil::convertToS32(str_val, value)  && value == min_val);
363
364		str_val = "2147483648"; 
365		ensure("4: convertToS32 failed", !LLStringUtil::convertToS32(str_val, value));
366
367		str_val = "-2147483649"; 
368		ensure("5: convertToS32 failed", !LLStringUtil::convertToS32(str_val, value));
369	}
370
371	template<> template<>
372	void string_index_object_t::test<24>()
373	{
374		F32 value;
375		std::string str_val("2147483647"); //0x7FFFFFFF
376		ensure("1: convertToF32 failed", LLStringUtil::convertToF32(str_val, value) && value == 2147483647);
377
378		str_val = "0";
379		ensure("2: convertToF32 failed", LLStringUtil::convertToF32(str_val, value) && value == 0);
380
381		/* Need to find max/min F32 values
382		str_val = "-2147483648"; 
383		ensure("3: convertToF32 failed", LLStringUtil::convertToF32(str_val, value)  && value == -2147483648);
384
385		str_val = "2147483648"; 
386		ensure("4: convertToF32 failed", !LLStringUtil::convertToF32(str_val, value));
387
388		str_val = "-2147483649"; 
389		ensure("5: convertToF32 failed", !LLStringUtil::convertToF32(str_val, value));
390		*/
391	}
392
393	template<> template<>
394	void string_index_object_t::test<25>()
395	{
396		F64 value;
397		std::string str_val("9223372036854775807"); //0x7FFFFFFFFFFFFFFF
398		ensure("1: convertToF64 failed", LLStringUtil::convertToF64(str_val, value) && value == 9223372036854775807LL);
399
400		str_val = "0";
401		ensure("2: convertToF64 failed", LLStringUtil::convertToF64(str_val, value) && value == 0.0F);
402
403		/* Need to find max/min F64 values
404		str_val = "-2147483648"; 
405		ensure("3: convertToF32 failed", LLStringUtil::convertToF32(str_val, value)  && value == -2147483648);
406
407		str_val = "2147483648"; 
408		ensure("4: convertToF32 failed", !LLStringUtil::convertToF32(str_val, value));
409
410		str_val = "-2147483649"; 
411		ensure("5: convertToF32 failed", !LLStringUtil::convertToF32(str_val, value));
412		*/
413	}
414
415	template<> template<>
416	void string_index_object_t::test<26>()
417	{
418		const char* str1 = NULL;
419		const char* str2 = NULL;
420
421		ensure("1: compareStrings failed", LLStringUtil::compareStrings(str1, str2) == 0);
422		str2 = "A";
423		ensure("2: compareStrings failed", LLStringUtil::compareStrings(str1, str2) > 0);
424		ensure("3: compareStrings failed", LLStringUtil::compareStrings(str2, str1) < 0);
425		
426		str1 = "A is smaller than B";
427		str2 = "B is greater than A";
428		ensure("4: compareStrings failed", LLStringUtil::compareStrings(str1, str2) < 0);
429
430		str2 = "A is smaller than B";
431		ensure("5: compareStrings failed", LLStringUtil::compareStrings(str1, str2) == 0);
432	}
433
434	template<> template<>
435	void string_index_object_t::test<27>()
436	{
437		const char* str1 = NULL;
438		const char* str2 = NULL;
439
440		ensure("1: compareInsensitive failed", LLStringUtil::compareInsensitive(str1, str2) == 0);
441		str2 = "A";
442		ensure("2: compareInsensitive failed", LLStringUtil::compareInsensitive(str1, str2) > 0);
443		ensure("3: compareInsensitive failed", LLStringUtil::compareInsensitive(str2, str1) < 0);
444		
445		str1 = "A is equal to a";
446		str2 = "a is EQUAL to A";
447		ensure("4: compareInsensitive failed", LLStringUtil::compareInsensitive(str1, str2) == 0);
448	}
449
450	template<> template<>
451	void string_index_object_t::test<28>()
452	{
453		std::string lhs_str("PROgraM12files");
454		std::string rhs_str("PROgram12Files");
455		ensure("compareDict 1 failed", LLStringUtil::compareDict(lhs_str, rhs_str) < 0);
456		ensure("precedesDict 1 failed", LLStringUtil::precedesDict(lhs_str, rhs_str) == TRUE);
457		
458		lhs_str = "PROgram12Files";
459		rhs_str = "PROgram12Files";
460		ensure("compareDict 2 failed", LLStringUtil::compareDict(lhs_str, rhs_str) == 0);
461		ensure("precedesDict 2 failed", LLStringUtil::precedesDict(lhs_str, rhs_str) == FALSE);
462
463		lhs_str = "PROgram12Files";
464		rhs_str = "PROgRAM12FILES";
465		ensure("compareDict 3 failed", LLStringUtil::compareDict(lhs_str, rhs_str) > 0);
466		ensure("precedesDict 3 failed", LLStringUtil::precedesDict(lhs_str, rhs_str) == FALSE);
467	}
468
469	template<> template<>
470	void string_index_object_t::test<29>()
471	{
472		char str1[] = "First String...";
473		char str2[100];
474
475		LLStringUtil::copy(str2, str1, 100);
476		ensure("LLStringUtil::copy with enough dest length failed", strcmp(str2, str1) == 0);
477		LLStringUtil::copy(str2, str1, sizeof("First"));
478		ensure("LLStringUtil::copy with less dest length failed", strcmp(str2, "First") == 0);
479	}
480
481	template<> template<>
482	void string_index_object_t::test<30>()
483	{
484		std::string str1 = "This is the sentence...";
485		std::string str2 = "This is the ";
486		std::string str3 = "first ";
487		std::string str4 = "This is the first sentence...";
488		std::string str5 = "This is the sentence...first ";
489		std::string dest;
490
491		dest = str1;
492		LLStringUtil::copyInto(dest, str3, str2.length());
493		ensure("LLStringUtil::copyInto insert failed", dest == str4);
494
495		dest = str1;
496		LLStringUtil::copyInto(dest, str3, dest.length());
497		ensure("LLStringUtil::copyInto append failed", dest == str5);
498	}
499
500	template<> template<>
501	void string_index_object_t::test<31>()
502	{
503		std::string stripped;
504
505		// Plain US ASCII text, including spaces and punctuation,
506		// should not be altered.
507		std::string simple_text = "Hello, world!";
508		stripped = LLStringFn::strip_invalid_xml(simple_text);
509		ensure("Simple text passed unchanged", stripped == simple_text);
510
511		// Control characters should be removed
512		// except for 0x09, 0x0a, 0x0d
513		std::string control_chars;
514		for (char c = 0x01; c < 0x20; c++)
515		{
516			control_chars.push_back(c);
517		}
518		std::string allowed_control_chars;
519		allowed_control_chars.push_back( (char)0x09 );
520		allowed_control_chars.push_back( (char)0x0a );
521		allowed_control_chars.push_back( (char)0x0d );
522
523		stripped = LLStringFn::strip_invalid_xml(control_chars);
524		ensure("Only tab, LF, CR control characters allowed",
525			stripped == allowed_control_chars);
526
527		// UTF-8 should be passed intact, including high byte
528		// characters.  Try Francais (with C squiggle cedilla)
529		std::string french = "Fran";
530		french.push_back( (char)0xC3 );
531		french.push_back( (char)0xA7 );
532		french += "ais";
533		stripped = LLStringFn::strip_invalid_xml( french );
534		ensure("UTF-8 high byte text is allowed", french == stripped );
535	}
536
537	template<> template<>
538	void string_index_object_t::test<32>()
539	{
540		// Test LLStringUtil::format() string interpolation
541		LLStringUtil::format_map_t fmt_map;
542		std::string s;
543		int subcount;
544
545		fmt_map["[TRICK1]"] = "[A]";
546		fmt_map["[A]"] = "a";
547		fmt_map["[B]"] = "b";
548		fmt_map["[AAA]"] = "aaa";
549		fmt_map["[BBB]"] = "bbb";
550		fmt_map["[TRICK2]"] = "[A]";
551		fmt_map["[EXPLOIT]"] = "!!!!!!!!!!!![EXPLOIT]!!!!!!!!!!!!";
552		fmt_map["[KEYLONGER]"] = "short";
553		fmt_map["[KEYSHORTER]"] = "Am I not a long string?";
554		fmt_map["?"] = "?";
555		fmt_map["[DELETE]"] = "";
556		fmt_map["[]"] = "[]"; // doesn't do a substitution, but shouldn't crash either
557
558		for (LLStringUtil::format_map_t::const_iterator iter = fmt_map.begin(); iter != fmt_map.end(); ++iter)
559		{
560			// Test when source string is entirely one key
561			std::string s1 = (std::string)iter->first;
562			std::string s2 = (std::string)iter->second;
563			subcount = LLStringUtil::format(s1, fmt_map);
564			ensure_equals("LLStringUtil::format: Raw interpolation result", s1, s2);
565			if (s1 == "?" || s1 == "[]") // no interp expected
566			{
567				ensure_equals("LLStringUtil::format: Raw interpolation result count", 0, subcount);
568			}
569			else
570			{
571				ensure_equals("LLStringUtil::format: Raw interpolation result count", 1, subcount);
572			}
573		}
574
575		for (LLStringUtil::format_map_t::const_iterator iter = fmt_map.begin(); iter != fmt_map.end(); ++iter)
576		{
577			// Test when source string is one key, duplicated
578			std::string s1 = (std::string)iter->first;
579			std::string s2 = (std::string)iter->second;
580			s = s1 + s1 + s1 + s1;
581			subcount = LLStringUtil::format(s, fmt_map);
582			ensure_equals("LLStringUtil::format: Rawx4 interpolation result", s, s2 + s2 + s2 + s2);
583			if (s1 == "?" || s1 == "[]") // no interp expected
584			{
585				ensure_equals("LLStringUtil::format: Rawx4 interpolation result count", 0, subcount);
586			}
587			else
588			{
589				ensure_equals("LLStringUtil::format: Rawx4 interpolation result count", 4, subcount);
590			}
591		}
592
593		// Test when source string has no keys
594		std::string srcs = "!!!!!!!!!!!!!!!!";
595		s = srcs;
596		subcount = LLStringUtil::format(s, fmt_map);
597		ensure_equals("LLStringUtil::format: No key test result", s, srcs);
598		ensure_equals("LLStringUtil::format: No key test result count", 0, subcount);
599
600		// Test when source string has no keys and is empty
601		std::string srcs3;
602		s = srcs3;
603		subcount = LLStringUtil::format(s, fmt_map);
604		ensure("LLStringUtil::format: No key test3 result", s.empty());
605		ensure_equals("LLStringUtil::format: No key test3 result count", 0, subcount);
606
607		// Test a substitution where a key is substituted with blankness
608		std::string srcs2 = "[DELETE]";
609		s = srcs2;
610		subcount = LLStringUtil::format(s, fmt_map);
611		ensure("LLStringUtil::format: Delete key test2 result", s.empty());
612		ensure_equals("LLStringUtil::format: Delete key test2 result count", 1, subcount);
613
614		// Test an assorted substitution
615		std::string srcs4 = "[TRICK1][A][B][AAA][BBB][TRICK2][KEYLONGER][KEYSHORTER]?[DELETE]";
616		s = srcs4;
617		subcount = LLStringUtil::format(s, fmt_map);
618		ensure_equals("LLStringUtil::format: Assorted Test1 result", s, "[A]abaaabbb[A]shortAm I not a long string??");
619		ensure_equals("LLStringUtil::format: Assorted Test1 result count", 9, subcount);
620
621		// Test an assorted substitution
622		std::string srcs5 = "[DELETE]?[KEYSHORTER][KEYLONGER][TRICK2][BBB][AAA][B][A][TRICK1]";
623		s = srcs5;
624		subcount = LLStringUtil::format(s, fmt_map);
625		ensure_equals("LLStringUtil::format: Assorted Test2 result", s, "?Am I not a long string?short[A]bbbaaaba[A]");
626		ensure_equals("LLStringUtil::format: Assorted Test2 result count", 9, subcount);
627		
628		// Test on nested brackets
629		std::string srcs6 = "[[TRICK1]][[A]][[B]][[AAA]][[BBB]][[TRICK2]][[KEYLONGER]][[KEYSHORTER]]?[[DELETE]]";
630		s = srcs6;
631		subcount = LLStringUtil::format(s, fmt_map);
632		ensure_equals("LLStringUtil::format: Assorted Test2 result", s, "[[A]][a][b][aaa][bbb][[A]][short][Am I not a long string?]?[]");
633		ensure_equals("LLStringUtil::format: Assorted Test2 result count", 9, subcount);
634
635
636		// Test an assorted substitution
637		std::string srcs8 = "foo[DELETE]bar?";
638		s = srcs8;
639		subcount = LLStringUtil::format(s, fmt_map);
640		ensure_equals("LLStringUtil::format: Assorted Test3 result", s, "foobar?");
641		ensure_equals("LLStringUtil::format: Assorted Test3 result count", 1, subcount);		
642	}
643
644	template<> template<>
645	void string_index_object_t::test<33>()
646	{
647		// Test LLStringUtil::format() string interpolation
648		LLStringUtil::format_map_t blank_fmt_map;
649		std::string s;
650		int subcount;
651
652		// Test substituting out of a blank format_map
653		std::string srcs6 = "12345";
654		s = srcs6;
655		subcount = LLStringUtil::format(s, blank_fmt_map);
656		ensure_equals("LLStringUtil::format: Blankfmt Test1 result", s, "12345");
657		ensure_equals("LLStringUtil::format: Blankfmt Test1 result count", 0, subcount);
658		
659		// Test substituting a blank string out of a blank format_map
660		std::string srcs7;
661		s = srcs7;
662		subcount = LLStringUtil::format(s, blank_fmt_map);
663		ensure("LLStringUtil::format: Blankfmt Test2 result", s.empty());
664		ensure_equals("LLStringUtil::format: Blankfmt Test2 result count", 0, subcount);
665	}
666
667	template<> template<>
668	void string_index_object_t::test<34>()
669	{
670		// Test that incorrect LLStringUtil::format() use does not explode.
671		LLStringUtil::format_map_t nasty_fmt_map;
672		std::string s;
673		int subcount;
674
675		nasty_fmt_map[""] = "never used"; // see, this is nasty.
676
677		// Test substituting out of a nasty format_map
678		std::string srcs6 = "12345";
679		s = srcs6;
680		subcount = LLStringUtil::format(s, nasty_fmt_map);
681		ensure_equals("LLStringUtil::format: Nastyfmt Test1 result", s, "12345");
682		ensure_equals("LLStringUtil::format: Nastyfmt Test1 result count", 0, subcount);
683		
684		// Test substituting a blank string out of a nasty format_map
685		std::string srcs7;
686		s = srcs7;
687		subcount = LLStringUtil::format(s, nasty_fmt_map);
688		ensure("LLStringUtil::format: Nastyfmt Test2 result", s.empty());
689		ensure_equals("LLStringUtil::format: Nastyfmt Test2 result count", 0, subcount);
690	}
691
692	template<> template<>
693	void string_index_object_t::test<35>()
694	{
695		// Make sure startsWith works
696		std::string string("anybody in there?");
697		std::string substr("anybody");
698		ensure("startsWith works.", LLStringUtil::startsWith(string, substr));
699	}
700
701	template<> template<>
702	void string_index_object_t::test<36>()
703	{
704		// Make sure startsWith correctly fails
705		std::string string("anybody in there?");
706		std::string substr("there");
707		ensure("startsWith fails.", !LLStringUtil::startsWith(string, substr));
708	}
709
710	template<> template<>
711	void string_index_object_t::test<37>()
712	{
713		// startsWith fails on empty strings
714		std::string value("anybody in there?");
715		std::string empty;
716		ensure("empty string.", !LLStringUtil::startsWith(value, empty));
717		ensure("empty substr.", !LLStringUtil::startsWith(empty, value));
718		ensure("empty everything.", !LLStringUtil::startsWith(empty, empty));
719	}
720
721	template<> template<>
722	void string_index_object_t::test<38>()
723	{
724		// Make sure endsWith works correctly
725		std::string string("anybody in there?");
726		std::string substr("there?");
727		ensure("endsWith works.", LLStringUtil::endsWith(string, substr));
728	}
729
730	template<> template<>
731	void string_index_object_t::test<39>()
732	{
733		// Make sure endsWith correctly fails
734		std::string string("anybody in there?");
735		std::string substr("anybody");
736		ensure("endsWith fails.", !LLStringUtil::endsWith(string, substr));
737		substr = "there";
738		ensure("endsWith fails.", !LLStringUtil::endsWith(string, substr));
739		substr = "ther?";
740		ensure("endsWith fails.", !LLStringUtil::endsWith(string, substr));
741	}
742
743	template<> template<>
744	void string_index_object_t::test<40>()
745	{
746		// endsWith fails on empty strings
747		std::string value("anybody in there?");
748		std::string empty;
749		ensure("empty string.", !LLStringUtil::endsWith(value, empty));
750		ensure("empty substr.", !LLStringUtil::endsWith(empty, value));
751		ensure("empty everything.", !LLStringUtil::endsWith(empty, empty));
752	}
753}