04c7f0d2defa55c52883c59919264418c86ddcb4
[feisty_meow.git] / nucleus / library / tests_basis / test_string.cpp
1 /*****************************************************************************\
2 *                                                                             *
3 *  Name   : test_string                                                       *
4 *  Author : Chris Koeritz                                                     *
5 *                                                                             *
6 *******************************************************************************
7 * Copyright (c) 1992-$now By Author.  This program is free software; you can  *
8 * redistribute it and/or modify it under the terms of the GNU General Public  *
9 * License as published by the Free Software Foundation; either version 2 of   *
10 * the License or (at your option) any later version.  This is online at:      *
11 *     http://www.fsf.org/copyleft/gpl.html                                    *
12 * Please send any updates to: fred@gruntose.com                               *
13 \*****************************************************************************/
14
15 //#define DEBUG_STRING
16   // set this to enable debugging features of the string class.
17
18 #include <application/hoople_main.h>
19 #include <basis/astring.h>
20 #include <basis/enhance_cpp.h>
21 #include <basis/functions.h>
22 #include <basis/guards.h>
23 #include <loggers/critical_events.h>
24 #include <loggers/file_logger.h>
25 #include <mathematics/chaos.h>
26 #include <structures/object_packers.h>
27 #include <structures/string_array.h>
28 #include <structures/static_memory_gremlin.h>
29 #include <textual/byte_formatter.h>
30 #include <textual/string_convert.h>
31 #include <textual/string_manipulation.h>
32 #include <timely/earth_time.h>
33 #include <timely/time_stamp.h>
34 #include <unit_test/unit_base.h>
35
36 #ifdef _MSC_VER
37   #include <comdef.h>
38 #endif
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42
43 using namespace application;
44 using namespace basis;
45 using namespace loggers;
46 using namespace mathematics;
47 using namespace structures;
48 using namespace textual;
49 using namespace timely;
50 using namespace unit_test;
51
52 //HOOPLE_STARTUP_CODE;
53
54 //#define DEBUG_STRING_TEST
55   // uncomment for testing version.
56
57 const float TEST_RUNTIME_DEFAULT = .02 * MINUTE_ms;
58   // the test, by default, will run for this long.
59
60 //////////////
61
62 class test_string : public application_shell, public unit_base
63 {
64 public:
65   test_string() {}
66   ~test_string() {}
67
68   DEFINE_CLASS_NAME("test_string");
69
70   virtual int execute();
71
72   void run_test_01();
73   void run_test_02();
74   void run_test_03();
75   void run_test_04();
76   void run_test_05();
77   void run_test_06();
78   void run_test_07();
79   void run_test_08();
80   void run_test_09();
81   void run_test_10();
82   void run_test_11();
83   void run_test_12();
84   void run_test_13();
85   void run_test_14();
86   void run_test_15();
87   void run_test_16();
88   void run_test_17();
89   void run_test_18();
90   void run_test_19();
91   void run_test_20();
92   void run_test_21();
93   void run_test_22();
94   void run_test_23();
95   void run_test_24();
96   void run_test_25();
97   void run_test_26();
98   void run_test_27();
99   void run_test_28();
100   void run_test_29();
101   void run_test_30();
102   void run_test_31();
103   void run_test_32();
104   void run_test_33();
105   void run_test_34();
106   void run_test_35();
107   void run_test_36();
108   void run_test_37();
109   void run_test_38();
110   void run_test_39();
111   void run_test_40();
112   void run_test_41();
113   void run_test_42();
114 };
115
116 //////////////
117
118 chaos rando;
119
120 #define LOG(s) EMERGENCY_LOG(program_wide_logger::get(), s)
121
122 #define WHERE __WHERE__.s()
123
124 // test: reports an error if the condition evaluates to non-zero.
125 #define test(expr) { \
126   ASSERT_FALSE(expr, astring("operator test should work: ") + #expr); \
127 }
128
129 static basis::astring staticity_test("yo!");
130   // used below to check whether static strings are looking right.
131
132 //////////////
133
134 void test_string::run_test_01()
135 {
136   FUNCDEF("run_test_01");
137
138 //  const int TEST_EMPTY = 10000000;
139 //  time_stamp started;
140 //  for (int i = 0; i < TEST_EMPTY; i++) {
141 //    astring glob = astring::empty_string();
142 //  }
143 //  int duration = int(time_stamp().value() - started.value());
144 //  LOG(a_sprintf("duration of empty string test=%d ms", duration));
145
146   // test simple string operations, like construction, length, equality.
147   astring fred1("hyeargh!");
148   astring fred2("matey.");
149   astring fred3;
150   fred3 = fred1;
151   fred3 += fred2;
152   astring fred4(fred2);
153
154   ASSERT_EQUAL(fred1.length(), int(strlen(fred1.s())), "length should be correct (a).");
155   ASSERT_EQUAL(fred2.length(), int(strlen(fred2.s())), "length should be correct (b).");
156   ASSERT_EQUAL(fred3.length(), int(strlen(fred3.s())), "length should be correct (c).");
157   ASSERT_EQUAL(fred4.length(), int(strlen(fred4.s())), "length should be correct (d).");
158
159 #ifdef DEBUG_STRING_TEST
160   LOG("[ " + fred1 + " & " + fred2 + "] -> " + fred3);
161 #endif
162
163   ASSERT_EQUAL(fred1, astring("hyeargh!"), "failure in comparison (a).");
164   ASSERT_EQUAL(fred2, astring("matey."), "failure in comparison (b).");
165   ASSERT_EQUAL(fred3, astring("hyeargh!matey."), "failure in comparison (c).");
166   ASSERT_EQUAL(fred4, astring("matey."), "failure in comparison (d-1).");
167   ASSERT_EQUAL(fred4, fred2, "failure in comparison (d-2).");
168
169   a_sprintf nullo;
170   ASSERT_EQUAL(nullo, astring(), "forward blank a_sprintf isn't blank.");
171   ASSERT_EQUAL(astring(), nullo, "backward blank a_sprintf isn't blank.");
172   ASSERT_EQUAL(nullo, astring::empty_string(), "forward blank a_sprintf isn't empty.");
173   ASSERT_EQUAL(astring::empty_string(), nullo, "backward blank a_sprintf isn't empty.");
174 }
175
176 void test_string::run_test_02()
177 {
178   FUNCDEF("run_test_02");
179   // assorted tests involving strings as pointers.
180   astring *fred1 = new astring("flipper ate");
181   astring *fred2 = new astring(" my sandwich.");
182   astring *fred3 = new astring;
183   *fred3 = *fred1;
184   *fred3 += *fred2;
185
186   // testing adding a null to a string.
187   *fred2 += (char *)NULL_POINTER;
188   *fred3 += (char *)NULL_POINTER;
189
190 #ifdef DEBUG_STRING_TEST
191   LOG(astring("[ ") + *fred1 + " & " + *fred2 + "] -> " + *fred3);
192 #endif
193
194   ASSERT_EQUAL(*fred1, astring("flipper ate"), "flipper A failure in comparison");
195   ASSERT_EQUAL(*fred2, astring(" my sandwich."), "sandwich A failure in comparison");
196   ASSERT_EQUAL(*fred3, astring("flipper ate my sandwich."), "full f-s A failure in comparison");
197   delete fred1;
198   delete fred2;
199   delete fred3;
200 }
201
202 void test_string::run_test_03()
203 {
204   FUNCDEF("run_test_03");
205   // tests some things about zap.
206   astring fleermipe("hello my frobious.");
207   fleermipe.zap(0, fleermipe.length() - 1);
208   ASSERT_EQUAL(fleermipe.length(), 0, "length not 0 after deleting entire astring");
209 }
210
211 void test_string::run_test_04()
212 {
213   FUNCDEF("run_test_04");
214   astring test_string("this test string will be chopped up.");
215 #ifdef DEBUG_STRING_TEST
216   LOG(astring("original is: ") + test_string);
217 #endif
218   astring fred(test_string.s());
219   fred.zap(0, fred.find('w'));
220
221 #ifdef DEBUG_STRING_TEST
222   LOG(astring("now, the one chopped through 'w' is: ") + fred);
223 #endif
224
225   ASSERT_EQUAL(fred, astring("ill be chopped up."), "first zap failed");
226
227   astring blorg(test_string);
228   blorg.zap(blorg.find('p'), blorg.length() - 1);
229 #ifdef DEBUG_STRING_TEST
230   LOG(astring("now the one chopped from p to the end: ") + blorg);
231 #endif
232
233   ASSERT_EQUAL(blorg, astring("this test string will be cho"), "second zap failed");
234
235   astring fleen;
236   fleen += test_string;
237   fleen.zap(7, 14);
238 #ifdef DEBUG_STRING_TEST
239   LOG(astring("now the one with 7 through 14 missing: ") + fleen);
240 #endif
241
242   ASSERT_EQUAL(fleen, astring("this teg will be chopped up."), "third zap failed");
243
244 #ifdef DEBUG_STRING_TEST
245   LOG(astring("original astring is now: ") + test_string);
246 #endif
247   ASSERT_EQUAL(test_string, astring("this test string will be chopped up."),
248       "original astring was changed");
249 }
250
251 void test_string::run_test_05()
252 {
253   FUNCDEF("run_test_05");
254 #ifdef DEBUG_STRING_TEST
255   LOG("about to test weird things:");
256 #endif
257   astring frieda("glorp");
258   astring jorb(frieda);
259   astring *kleeg = new astring(jorb.s());
260   astring plok = frieda;
261   test(frieda != jorb);
262   test(jorb != *kleeg);
263   test(*kleeg != plok);
264   test(plok != frieda);
265   astring glorp("glorp");
266   test(frieda != glorp);
267
268   WHACK(kleeg);
269
270 #ifdef DEBUG_STRING_TEST
271   LOG("strings matched up okay.");
272 #endif
273
274   // test new features sprintf is relying upon.
275   astring bubba("gumpternations");
276   bubba += "_02193";
277 #ifdef DEBUG_STRING_TEST
278   LOG(astring("bubba = ") + bubba);
279 #endif
280   ASSERT_EQUAL(bubba, astring("gumpternations_02193"), "+= on char pointer failed.");
281
282   astring bubelah("laksos");
283   bubelah += '3';
284   bubelah += '8';
285   bubelah += '2';
286 #ifdef DEBUG_STRING_TEST
287   LOG(astring("bubelah = ") + bubelah);
288 #endif
289   ASSERT_EQUAL(bubelah, astring("laksos382"), "+= on char failed.");
290
291   astring simple_spr0(astring::SPRINTF, "%% yoga splorch %%");
292 #ifdef DEBUG_STRING_TEST
293   LOG(astring("simple sprintf 0 = ") + simple_spr0);
294 #endif
295   ASSERT_EQUAL(simple_spr0, astring("% yoga splorch %"), "simple sprintf 0 is wrong");
296   astring simple_spr1(astring::SPRINTF, "%d", 23);
297 #ifdef DEBUG_STRING_TEST
298   LOG(astring("simple sprintf 1 = ") + simple_spr1);
299 #endif
300   ASSERT_EQUAL(simple_spr1, astring("23"), "simple sprintf 1 is wrong");
301   astring simple_spr2(astring::SPRINTF, "%s", "yoyo");
302 #ifdef DEBUG_STRING_TEST
303   LOG(astring("simple sprintf 2 = ") + simple_spr2);
304 #endif
305   ASSERT_EQUAL(simple_spr2, astring("yoyo"), "simple sprintf 2 is wrong");
306
307   astring sprintest(astring::SPRINTF, "%s has got me up the %s some %d "
308      "times, in %p with %d and %lu.", "marge", "ladder", 32, &kleeg,
309      812377487L, 213123123L);
310   astring sprintest2;
311   sprintest2.reset(astring::SPRINTF, "%s has got me up the %s some %d "
312      "times, in %p with %d and %lu.", "marge", "ladder", 32, &kleeg,
313      812377487L, 213123123L);
314   astring addr(astring::SPRINTF, "%p", &kleeg);
315 #ifdef DEBUG_STRING_TEST
316   LOG("here is your astring sir...");
317   LOG(sprintest);
318   LOG("and addr we will see is...");
319   LOG(addr);
320 #endif
321   if (sprintest != astring(astring::SPRINTF, "marge has got me up the "
322       "ladder some 32 times, in %s with 812377487 and 213123123.", addr.s()))
323     "constructed astring is wrong";
324   if (sprintest2 != astring(astring::SPRINTF, "marge has got me up the "
325       "ladder some 32 times, in %s with 812377487 and 213123123.", addr.s()))
326     "reset astring is wrong";
327 }
328
329 void test_string::run_test_06()
330 {
331   FUNCDEF("run_test_06");
332   astring bungee;
333   bungee += "this astring";
334   bungee += " has been constructed gradua";
335   bungee += 'l';
336   bungee += 'l';
337   bungee += 'y';
338   astring blorpun(astring::SPRINTF, " out of severa%c", 'l');
339   bungee += blorpun;
340   bungee += " different bits,\nincluding";
341   astring freeple(astring::SPRINTF, "%s constructed %s blarg from %f ", " this", "silly", 3.14159265358);
342   bungee += freeple;
343   bungee += "radians awa";
344   bungee += 'y';
345   bungee += '.';
346   bungee += "\nhow does it look?\n";
347 #ifdef DEBUG_STRING_TEST
348   LOG(bungee);
349 #endif
350
351 //MessageBox(0, bungee.s(), "yo, got this", MB_ICONINFORMATION | MB_OK);
352   ASSERT_EQUAL(bungee, astring("this astring has been constructed gradually out of several different bits,\nincluding this constructed silly blarg from 3.141593 radians away.\nhow does it look?\n"), "constructed astring is wrong");
353 }
354
355 void test_string::run_test_07()
356 {
357   FUNCDEF("run_test_07");
358   astring a("axes");
359   astring b("bakesales");
360   astring x("xylophone");
361
362   test(a >= x);
363   test(a == b);
364   test(a > b);
365   test(b >= x);
366   test(x <= a);
367   test(x != x);
368   test(a != a);
369 #ifdef DEBUG_STRING_TEST
370   LOG("comparisons worked");
371 #endif
372 }
373
374 void test_string::run_test_08()
375 {
376   FUNCDEF("run_test_08");
377 #ifdef DEBUG_STRING_TEST
378   LOG("now testing + operator");
379 #endif
380   astring a("fred");
381   astring b(" is");
382   astring c(" his");
383   astring d(" name.");
384   astring e;
385   e = a + b + c + d;
386 #ifdef DEBUG_STRING_TEST
387   LOG(astring("result is: ") + e);
388 #endif
389   astring f;
390   f = d + c + b + a;
391 #ifdef DEBUG_STRING_TEST
392   LOG(astring("reverse is: ") + f);
393 #endif
394   astring g;
395   g = a + c + d + b;
396 #ifdef DEBUG_STRING_TEST
397   LOG(astring("tibetan style is: ") + g);
398 #endif
399   ASSERT_EQUAL(e, astring("fred is his name."), "astring looks wrong");
400   ASSERT_EQUAL(f, astring(" name. his isfred"), "astring looks wrong");
401   ASSERT_EQUAL(g, astring("fred his name. is"), "astring looks wrong");
402 }
403
404 void test_string::run_test_09()
405 {
406   FUNCDEF("run_test_09");
407   astring bleer(astring::SPRINTF, "urghla burgla #%d\n", 23);
408   char holder[50];
409   for (int i = 0; i < bleer.length(); i++) {
410     bleer.stuff(holder, i);
411 #ifdef DEBUG_STRING_TEST
412     LOG(astring(astring::SPRINTF, "%d", i) + " has: " + holder);
413 #endif
414     astring my_copy(bleer);
415     my_copy.zap(i, bleer.length() - 1);
416     ASSERT_EQUAL(my_copy, astring(holder), "should see no inaccurate stuff() call");
417   }
418 }
419
420 void test_string::run_test_10()
421 {
422   FUNCDEF("run_test_10");
423 #ifdef DEBUG_STRING_TEST
424   LOG("The tenth ones:");
425 #endif
426   astring george("this one will be mangled.");
427   ASSERT_EQUAL(george.length(), int(strlen(george.s())), "length is incorrect (q).");
428   astring tmp1(george.substring(1, 7));  // constructor.
429   astring tmp2 = george.substring(10, george.length() - 1);  // constructor.
430 #ifdef DEBUG_STRING_TEST
431   LOG(tmp1 + "... " + tmp2);
432 #endif
433   ASSERT_INEQUAL(tmp1, tmp2, "bizarre equality occurred!");
434   ASSERT_FALSE( (tmp1 > tmp2) || (tmp2 < tmp1), "bizarre comparison error.");
435   ASSERT_EQUAL(george.length(), int(strlen(george.s())), "length is incorrect (z).");
436 #ifdef DEBUG_STRING_TEST
437   LOG(george.substring(1, 7));
438   LOG("... ");
439   LOG(george.substring(10, george.length() - 1));
440 #endif
441   ASSERT_EQUAL(george.length(), int(strlen(george.s())), "length is incorrect (a).");
442   george.insert(14, "terribly ");
443   ASSERT_EQUAL(george.length(), int(strlen(george.s())), "length is incorrect (b).");
444 #ifdef DEBUG_STRING_TEST
445   LOG(george);
446 #endif
447   astring chunky;
448   astring mssr_boef_la_tet("eeyoy eye eye capn");
449   mssr_boef_la_tet.substring(chunky, 2, 7);
450   ASSERT_EQUAL(chunky, astring("yoy ey"), "contents wrong after substring");
451
452   astring fred(george);
453   ASSERT_TRUE(george.compare(fred, 0, 0, george.length() - 1, true), "did not work");
454   ASSERT_TRUE(george.compare(fred, 8, 8, george.length() - 1 - 8, true), "partial did not work");
455
456   astring taco1("iLikeTacosNSuch");
457   astring taco2("iLikeTaCosNSuch");
458   ASSERT_TRUE(taco1.compare(taco2, 0, 0, taco1.length() - 1, false),
459       "tacos case-insensitive compare A did not work");
460   ASSERT_FALSE(taco1.compare(taco2, 0, 0, taco1.length() - 1, true),
461       "tacos case-sensitive compare B did not work");
462
463   ASSERT_EQUAL(george.length(), int(strlen(george.s())), "length is incorrect (c).");
464   george.zap(14, 22);
465 #ifdef DEBUG_STRING_TEST
466   LOG(george);
467 #endif
468   astring fred_part;
469   fred_part = fred.substring(0, 13);
470   ASSERT_EQUAL(fred_part.length(), int(strlen(fred_part.s())), "length incorrect (d).");
471   ASSERT_TRUE(george.compare(fred_part, 0, 0, 13, true), "did not work");
472   fred_part = fred.substring(23, fred.length() - 1);
473   ASSERT_EQUAL(fred_part.length(), int(strlen(fred_part.s())), "length incorrect (e).");
474   ASSERT_TRUE(george.compare(fred_part, 14, 0, fred_part.length() - 1, true), "did not work");
475 #ifdef DEBUG_STRING_TEST
476   LOG("compares okay");
477 #endif
478 }
479
480 void test_string::run_test_11()
481 {
482   FUNCDEF("run_test_11");
483   astring empty;
484   ASSERT_FALSE(empty.length(), "empty string judged not");
485   ASSERT_TRUE(!empty, "not on empty string doesn't work");
486   astring non_empty("grungee");
487   ASSERT_TRUE(non_empty.length(), "non-empty string judged empty");
488   ASSERT_FALSE(!non_empty, "not on non-empty string doesn't work");
489 }
490
491 void test_string::run_test_12()
492 {
493   FUNCDEF("run_test_12");
494   astring elf0(astring::SPRINTF, "%%_%%_%%");
495   ASSERT_FALSE(strcmp(elf0.s(), "%_%_%"), "failed %% printing");
496
497   char fred[6] = { 'h', 'y', 'a', 'r', 'g', '\0' };
498   astring fred_copy(astring::UNTERMINATED, fred, 5);
499   ASSERT_EQUAL(fred_copy.length(), 5, "length of copy is wrong");
500   ASSERT_EQUAL(fred_copy, astring("hyarg"), "length of copy is wrong");
501
502   char hugh[6] = { 'o', 'y', 'o', 'b', 'o', 'y' };
503   astring hugh_copy(astring::UNTERMINATED, hugh, 3);
504   ASSERT_EQUAL(hugh_copy.length(), 3, "length of copy is wrong");
505   ASSERT_EQUAL(hugh_copy, astring("oyo"), "length of copy is wrong");
506
507   astring another_copy;
508   another_copy.reset(astring::UNTERMINATED, fred, strlen(fred));
509   ASSERT_EQUAL(another_copy.length(), 5, "length of reset copy is wrong");
510   ASSERT_EQUAL(another_copy, astring("hyarg"), "length of reset copy is wrong");
511 }
512
513 void test_string::run_test_13()
514 {
515   FUNCDEF("run_test_13");
516   // check for possible memory leaks in these combined ops....  13th.
517   const astring churg("borjh sjh oiweoklj");
518   astring pud = churg;
519   astring flug = "kase iqk aksjir kljasdo";
520   const char *nerf = "ausd qwoeui sof zjh qwei";
521   astring snorp = nerf;
522   pud = "snugbo";
523   snorp = flug;
524   astring pundit("murph");
525   pundit = nerf;
526 }
527
528 void test_string::run_test_14()
529 {
530   FUNCDEF("run_test_14");
531   // test the new dynamic sprintf'ing for long strings... 14th.
532   const int longish_size = 5000;
533   char temp[longish_size];
534   for (int i = 0; i < longish_size; i++)
535     temp[i] = char(rando.inclusive(1, 255));
536   temp[longish_size - 1] = '\0';
537   a_sprintf longish("this is a really darned long string of stuff: %s,\nbut doesn't it look interesting?", temp);
538   // still with us?
539   longish.zap(longish.length() / 3, 2 * longish.length() / 3);
540   longish += longish;
541   ASSERT_EQUAL(longish.length(), int(strlen(longish.s())), "length is incorrect.");
542 }
543
544 void test_string::run_test_15()
545 {
546   FUNCDEF("run_test_15");
547   // test the new dynamic sprintf'ing for long strings... 15th.
548   int try_1 = 32767;
549   astring testy(astring::SPRINTF, "%d", try_1);
550   ASSERT_INEQUAL(testy.convert(95), 95, "default value returned, so it failed.");
551   ASSERT_EQUAL(testy.convert(95), try_1, "correct value was not returned.");
552
553   long try_2 = 2938754L;
554   testy = astring(astring::SPRINTF, "%ld", try_2);
555   ASSERT_INEQUAL((double)testy.convert(98L), (double)98L, "default value returned, so it failed.");
556   ASSERT_EQUAL((double)testy.convert(98L), (double)try_2, "correct value was not returned.");
557
558   testy = astring(astring::SPRINTF, "%ld", try_2);
559   ASSERT_INEQUAL((double)testy.convert(98L), (double)98L, "default value returned, so it failed.");
560   ASSERT_EQUAL((double)testy.convert(98L), (double)try_2, "correct value was not returned.");
561
562   float try_3 = float(2938.754);  // weird msvcpp error if don't cast.
563   testy = astring(astring::SPRINTF, "%f", try_3);
564   float found = testy.convert(float(98.6));
565   ASSERT_INEQUAL(found, 98.6, "default value returned, so it failed.");
566   ASSERT_EQUAL(found, try_3, "correct value was not returned.");
567
568   {
569     double try_4 = 25598437.712385;
570     testy = astring(astring::SPRINTF, "%f", try_4);
571     double found2 = testy.convert(double(98.6));
572     ASSERT_INEQUAL(found2, 98.6, "default value returned, so it failed.");
573     ASSERT_EQUAL(found2, try_4, "correct value was not returned.");
574   }
575
576   {
577     double try_4 = 25598437.712385e38;
578     testy = astring(astring::SPRINTF, "%f", try_4);
579     double found2 = testy.convert(double(98.6));
580     ASSERT_INEQUAL(found2, 98.6, "default value returned, so it failed.");
581     ASSERT_EQUAL(found2, try_4, "correct value was not returned.");
582   }
583 }
584
585 void test_string::run_test_16()
586 {
587   FUNCDEF("run_test_16");
588   // the 16th test group tests boundary checking.
589   astring gorf("abc");
590   for (int i = -3; i < 25; i++) gorf[i] = 't';
591   ASSERT_EQUAL(gorf, astring("ttt"), "correct value was not returned (a).");
592   ASSERT_EQUAL(gorf.length(), 3, "length is incorrect (a).");
593   gorf.insert(3, astring("bru"));
594   ASSERT_EQUAL(gorf, astring("tttbru"), "correct value was not returned (b).");
595   ASSERT_EQUAL(gorf.length(), 6, "length is incorrect (b).");
596   gorf.insert(35, astring("snu"));
597   ASSERT_EQUAL(gorf, astring("tttbru"), "correct value was not returned (c).");
598   ASSERT_EQUAL(gorf.length(), 6, "length is incorrect (c).");
599   gorf.insert(-30, astring("eep"));
600   ASSERT_EQUAL(gorf, astring("tttbru"), "correct value was not returned (d).");
601   ASSERT_EQUAL(gorf.length(), 6, "length is incorrect (d).");
602 }
603
604 void test_string::run_test_17()
605 {
606   FUNCDEF("run_test_17");
607   // 17th test checks construction of temporaries.
608 /* this test set causes the obnoxious 16 bit codeguard error from hell, as
609    does use of temporary objects in ostream << operators.  argh! */
610   astring("jubjo");
611   astring("obo");
612   astring("flrrpominort").substring(3, 6);
613 }
614
615 void test_string::run_test_18()
616 {
617 #ifdef DEBUG_STRING_TEST
618   FUNCDEF("run_test_18");
619 #endif
620   // 18th test group checks windows related functions.
621 #ifdef AFXDLL
622   AfxSetResourceHandle(GET_INSTANCE_HANDLE());
623     // required for mfc to see the proper instance handle.
624
625   // this tests the "constructor from resource".
626   astring libname = rc_string(IDS_BASIS_NAME);
627   ASSERT_EQUAL(libname, astring("Basis Library"),
628       astring("library name is a mismatch: comes out as \"") + libname + "\".");
629   #define IDS_SOME_BAD_UNKNOWN_STRING_HANDLE 30802
630   astring bogus_name = rc_string(IDS_SOME_BAD_UNKNOWN_STRING_HANDLE);
631   ASSERT_FALSE(bogus_name.length(), "bogus rc string had length");
632
633   // tests conversions from CString to astring and back.
634   astring george("yo yo yo");
635   CString hal = convert(george);
636   astring borgia = convert(hal);
637
638 #ifdef DEBUG_STRING_TEST
639   LOG(astring("cstringy conversions: ") + george);
640   LOG((const char *)hal);
641   LOG(borgia);
642 #endif
643
644   ASSERT_EQUAL(borgia, george, "got the wrong value");
645 #endif
646 }
647
648 void test_string::run_test_19()
649 {
650   FUNCDEF("run_test_19");
651   // 19th test group is devoted to anthony wenzel's % printing bug.
652   astring problematic_example(astring::SPRINTF, "this should have %d% more "
653       "stuffing than before!", 20);
654 //MessageBox(0, astring("got a string of \"%s!\"", problematic_example.s()).s(), "yo!", MB_OK);
655   ASSERT_EQUAL(problematic_example, astring("this should have 20% more stuffing than before!"), "failure to print correct phrase");
656 }
657
658 void test_string::run_test_20()
659 {
660 #ifdef DEBUG_STRING_TEST
661   FUNCDEF("run_test_20");
662 #endif
663   // 20th test group is devoted to another wenzelbug.
664
665   // Hey, I just found out (in an ugly way) that the following doesn't work:
666   char myText[] = "OK";
667   astring myString(astring::SPRINTF, "%04s", myText);
668 #ifdef DEBUG_STRING_TEST
669   LOG(astring("first try gets: ") + myString);
670 #endif
671
672   char myText8[] = "OK";
673   char my_text_4[90];
674   sprintf(my_text_4, "%4s", myText8);
675 #ifdef DEBUG_STRING_TEST
676   LOG(astring("second try gets: ") + astring(my_text_4));
677 #endif
678
679   // Looks like you don't handle the "%04s" arguments properly.  I can make
680   // it work as follows:
681   char myText2[] = "OK";
682   char myText3[50];
683   sprintf(myText3, "%4s", myText2);
684   astring myString2(myText3);
685 #ifdef DEBUG_STRING_TEST
686   LOG(astring("third try gets: ") + myString2);
687 #endif
688 }
689
690 void test_string::run_test_21()
691 {
692   FUNCDEF("run_test_21");
693   // 21st test group checks out the strip spaces and replace functions.
694   astring spacey("   dufunk  ");
695   astring temp = spacey;
696   temp.strip_spaces(astring::FROM_FRONT);
697   ASSERT_EQUAL(temp, astring("dufunk  "), "created wrong string");
698   temp = spacey;
699   temp.strip_spaces(astring::FROM_END);
700   ASSERT_EQUAL(temp, astring("   dufunk"), "created wrong string");
701   temp = spacey;
702   temp.strip_spaces(astring::FROM_BOTH_SIDES);
703   ASSERT_EQUAL(temp, astring("dufunk"), "created wrong string");
704
705   astring placemat("mary had a red hooded cobra she kept around her neck "
706       "and it hissed at the people as they walked by her tent.");
707   ASSERT_TRUE(placemat.replace("had", "bought"), "replace failed");
708   ASSERT_TRUE(!placemat.replace("hoded", "bought"), "replace didn't fail but should have");
709   ASSERT_TRUE(placemat.replace("she", "funkateria"), "replace failed");
710   ASSERT_TRUE(placemat.replace("hooded", "hood"), "replace failed");
711   ASSERT_TRUE(placemat.replace("cobra", "in the"), "replace failed");
712
713   int indy = placemat.find("kept");
714   ASSERT_FALSE(negative(indy), "couldn't find string");
715   placemat[indy - 1] = '.';
716   placemat.zap(indy, placemat.end());
717   ASSERT_EQUAL(placemat, astring("mary bought a red hood in the funkateria."), "got wrong result string");
718 }
719
720 void test_string::run_test_22()
721 {
722   FUNCDEF("run_test_22");
723   // 22nd test: morgan's find bug.
724   astring B("buzz*buzz*");
725   {
726     int x = B.find('*');  // correctly finds the first *.
727     ASSERT_EQUAL(x, 4, "got wrong index for first");
728     x++;   
729     x = B.find('*', x);  // correctly finds the second *.
730     ASSERT_EQUAL(x, 9, "got wrong index for second");
731     x++;  // now x == B.length().
732     x = B.find('*', x);
733       // error was: finds the second * again (and again and again and 
734       // again...).  At this point it should return OUT_OF_RANGE.
735     ASSERT_FALSE(x > 0, "got wrong outcome for third");
736   }
737   {
738     int x = B.find("z*");  // correctly finds the first z*.
739     ASSERT_EQUAL(x, 3, "got wrong index for fourth");
740     x++;   
741     x = B.find("z*", x);  // correctly finds the second *.
742     ASSERT_EQUAL(x, 8, "got wrong index for fifth");
743     x++;  // now x == B.length().
744     x = B.find("z*", x);
745       // error was: finds the second * again (and again and again and 
746       // again...).  At this point it should return OUT_OF_RANGE.
747     ASSERT_FALSE(x > 0, "got wrong outcome for sixth");
748   }
749 }
750
751 void test_string::run_test_23()
752 {
753   FUNCDEF("run_test_23");
754   // 23rd test: test the new strip function.
755   astring strip_string("!@#$%^&*()");
756   
757   astring no_stripper("this shouldn't change");
758   no_stripper.strip(strip_string, astring::FROM_BOTH_SIDES);
759   ASSERT_EQUAL(no_stripper, astring("this shouldn't change"), "first test failed comparison");
760
761   astring strippee_orig("&$(*(@&@*()()!()@*(@(*fudge#((@(*@**#)(@#)(#");
762   astring strippee(strippee_orig);
763   strippee.strip(strip_string, astring::FROM_BOTH_SIDES);
764   ASSERT_EQUAL(strippee, astring("fudge"), "second test failed comparison");
765
766   strippee = strippee_orig;
767   strippee.strip(strip_string, astring::FROM_FRONT);
768   ASSERT_EQUAL(strippee, astring("fudge#((@(*@**#)(@#)(#"), "third test failed comparison");
769
770   strippee = strippee_orig;
771   strippee.strip(strip_string, astring::FROM_END);
772   ASSERT_EQUAL(strippee, astring("&$(*(@&@*()()!()@*(@(*fudge"), "fourth test failed comparison");
773 }
774
775 void test_string::run_test_24()
776 {
777   FUNCDEF("run_test_24");
778 #ifndef __GNU_WINDOWS__
779 #ifdef __WIN32__
780   // 24th test group tests _bstr_t conversions.
781   _bstr_t beast("abcdefgh");
782 #ifdef DEBUG_STRING_TEST
783   LOG(astring("the beast is ") + beast.operator char *() +
784       astring(astring::SPRINTF, " with length %d", beast.length()));
785 #endif
786   astring convert = beast;
787 #ifdef DEBUG_STRING_TEST
788   LOG(astring("the convert is ") + convert
789       + astring(astring::SPRINTF, " with length %d", convert.length()));
790 #endif
791   ASSERT_EQUAL(convert, astring("abcdefgh"), "first test failed comparison");
792
793   astring jethro("i want a hog sandwich");
794   _bstr_t pork = string_convert::to_bstr_t(jethro);
795   ASSERT_FALSE(strcmp(pork.operator char *(), jethro.s()), "second test failed comparison");
796 #endif
797 #endif
798 }
799
800 void test_string::run_test_25()
801 {
802   FUNCDEF("run_test_25");
803   // 25th test group tests simple comparisons.
804   astring fred = "asdoiuaoisud";
805   ASSERT_INEQUAL(fred, astring(), "first test failed comparison");
806   astring bub = fred;
807   ASSERT_EQUAL(fred, bub, "second test failed comparison");
808   fred = "";
809   ASSERT_EQUAL(fred, astring(), "third test failed comparison");
810   ASSERT_FALSE(fred.length(), "fourth test failed comparison");
811 }
812
813 void test_string::run_test_26()
814 {
815   FUNCDEF("run_test_26");
816   // 26th test group does simple time_stamp::notarize operations.  these are more for
817   // ensuring boundschecker gets to see some of this.
818   astring t2 = time_stamp::notarize(false);
819   astring t4 = time_stamp::notarize(true);
820 }
821
822 void test_string::run_test_27()
823 {
824   FUNCDEF("run_test_27");
825   // 27th test group plays around with idate in an attempt to get
826   // boundschecker to complain.
827   timely::day_in_year d1 = date_now();
828   timely::clock_time t1 = time_now();
829   timely::time_locus dt1 = now();
830   astring sd1 = d1.text_form();
831   astring st1 = t1.text_form();
832   astring sdt1 = dt1.text_form_long();
833 }
834
835 void test_string::run_test_28()
836 {
837   FUNCDEF("run_test_28");
838   // 28th test group does sprintfs on shorts and such.
839   basis::un_int in1 = 27;
840   basis::un_short in2 = 39;
841   char in3 = 'Q';
842   astring testy(astring::SPRINTF, "%u:%hu:%c", in1, in2, in3);
843   ASSERT_EQUAL(testy, astring("27:39:Q"), "fourth test failed comparison");
844 }
845
846 void test_string::run_test_29()
847 {
848   FUNCDEF("run_test_29");
849   // 29th test group tries out the packing support.
850   astring a("would an onion smell so sweet?");
851   byte_array p1;
852   a.pack(p1);
853   astring b;
854   ASSERT_TRUE(b.unpack(p1), "first unpack failed");
855   ASSERT_EQUAL(b, a, "first comparison failed");
856   a = "128 salamanders cannot be wrong.";
857   a.pack(p1);
858   ASSERT_TRUE(b.unpack(p1), "second unpack failed");
859   ASSERT_EQUAL(b, a, "second comparison failed");
860 }
861
862 void standard_sprintf_test(const char *parm_string)
863 {
864   FUNCDEF("standard_sprintf_test");
865   astring print_into(' ', 20000);
866   print_into[0] = '\0';
867 //check these!!!:
868   int i1 = int(rando.inclusive(0, 23945));
869   long l1 = long(rando.inclusive(-2394, 2998238));
870   un_int u1 = basis::un_int(rando.inclusive(0, 124395));
871   un_short s1 = basis::un_short(rando.inclusive(0, 65535));
872   sprintf(print_into.s(), "%d %ld %u %hu %s", i1, l1, u1, s1, parm_string);
873   sprintf(print_into.s(), "%c %d %c %s %s %lu", char(rando.inclusive('a', 'z')),
874       int(rando.inclusive(0, 23945)), char(rando.inclusive('A', 'Z')),
875       parm_string, parm_string, basis::un_long(rando.inclusive(0, 2998238)));
876 }
877
878 void test_string::run_test_30()
879 {
880   // 30th test group checks astring sprintf.
881   FUNCDEF("run_test_30");
882   astring parm_string = string_manipulation::make_random_name(40, 140);
883   astring print_into(' ', 20000);
884   print_into[0] = '\0';
885   int i1 = int(rando.inclusive(0, 23945));
886   long l1 = long(rando.inclusive(-2394, 2998238));
887   un_int u1 = basis::un_int(rando.inclusive(0, 124395));
888   un_short s1 = basis::un_short(rando.inclusive(0, 65535));
889   char test_same[20010];
890   sprintf(test_same, "%d %ld %u %hu %s", i1, l1, u1, s1, parm_string.s());
891   print_into.sprintf("%d %ld %u %hu %s", i1, l1, u1, s1, parm_string.s());
892   ASSERT_EQUAL(astring(test_same), print_into, "sprintf should get same results as standard");
893 //do test for this one too.
894   print_into.sprintf("%c %d %c %s %s %lu", char(rando.inclusive('a', 'z')),
895       int(rando.inclusive(0, 23945)), char(rando.inclusive('A', 'Z')),
896       parm_string.observe(), parm_string.s(), basis::un_long(rando.inclusive(0, 2998238)));
897 }
898
899 void test_string::run_test_31()
900 {
901   FUNCDEF("run_test_31");
902   // testing of character repeat constructor.
903   astring dashes('-', 20);
904   astring non_plusses('+', 0);
905   astring plusses('+', 1);
906   ASSERT_EQUAL(dashes.length(), 20, astring("dashes has wrong length!"));
907   ASSERT_EQUAL(dashes, astring("--------------------"), astring("dashes has wrong contents!  '") + dashes + "' vs. '" + astring("--------------------'"));
908   ASSERT_FALSE(non_plusses.length(), astring("non_plusses has wrong length!"));
909   ASSERT_EQUAL(plusses.length(), 1, astring("plusses has wrong length!"));
910   ASSERT_EQUAL(plusses, astring("+"), astring("plusses has wrong contents!"));
911   ASSERT_EQUAL(plusses, astring('+', 1), astring("plusses second compare failed!"));
912 }
913
914 void test_string::run_test_32()
915 {
916   FUNCDEF("run_test_32");
917   // tests creating a huge string and ripping it apart.
918
919   const int CHUNK_SIZE = 2 * MEGABYTE;
920     // the block factor for our string.  we expect not to go above this during
921     // the testing.
922   const int MIN_ADDITION = 10000;  const int MAX_ADDITION = 80000;
923     // these are the largest chunk we add to a string at a time.
924   const int BUILD_AND_BURN_ITERATIONS = 1;
925     // number of times to test building up and tearing down.
926
927   // the string we build up and tear down.
928   astring slab;
929
930 //hmmm: maybe have a mixed phase where tearing and adding
931 //      happens frequently and interspersed.
932
933   for (int iters = 0; iters < BUILD_AND_BURN_ITERATIONS; iters++) {
934
935     int size = 0;  // independent count of expected size.
936     // we don't want to bother allocating the big chunk more than once, so
937     // we'll add to the string until it's within range of going over.
938     while (slab.length() < CHUNK_SIZE - MAX_ADDITION - 20) {
939 //make this into add_a_chunk
940       astring addition = string_manipulation::make_random_name(MIN_ADDITION,
941           MAX_ADDITION);
942       slab += addition;
943       size += addition.length();
944       ASSERT_EQUAL(size, slab.length(), astring("size is incorrect after add!"));
945     }
946
947     // now we eat it up.
948     while (slab.length()) {
949 //make this into zap_a_chunk
950       int zap_start = rando.inclusive(0, slab.end());
951       int zap_end = rando.inclusive(0, slab.end());
952       flip_increasing(zap_start, zap_end);
953       int range_length = zap_end - zap_start + 1;
954       ASSERT_FALSE(negative(range_length), astring("flip_increasing failed!"));
955       slab.zap(zap_start, zap_end);
956       size -= range_length;
957       ASSERT_EQUAL(size, slab.length(), astring("size is incorrect after zap!"));
958     }
959   }
960 }
961
962 void test_string::run_test_33()
963 {
964   FUNCDEF("run_test_33");
965   // 33rd test group exercises the replace functions.
966   {
967     astring to_modify("\\\\feeby\\path\\yo");
968     ASSERT_TRUE(to_modify.replace("\\", "/"), "failed to replace the string");
969     ASSERT_EQUAL(to_modify, astring("/\\feeby\\path\\yo"), "produced wrong resultant string");
970     while (to_modify.replace("\\", "/")) {}
971     ASSERT_EQUAL(to_modify, astring("//feeby/path/yo"), "produced wrong final string");
972   }
973   {
974     astring to_modify("\\superduper\\dynamo\\looper");
975     ASSERT_TRUE(to_modify.replace("\\", "/"), "failed to replace the string");
976     ASSERT_EQUAL(to_modify, astring("/superduper\\dynamo\\looper"), "produced wrong resultant string");
977     while (to_modify.replace("\\", "/")) {}
978     ASSERT_EQUAL(to_modify, astring("/superduper/dynamo/looper"), "produced wrong final string");
979   }
980   {
981     astring id = "/SRV=1/SRC=1";
982     astring id1 = id;
983     while (id1.replace("/", " ")) {}
984 //    LOG(astring("replacing / with ' ' in first test (was ") + id +
985 //        ") gives " + id1);
986     ASSERT_EQUAL(id1, astring(" SRV=1 SRC=1"), "produced wrong final string");
987
988     astring id2 = id;
989     while (id2.replace("=", ":")) {}
990 //    LOG(astring("replacing = with : in second test (was ") + id +
991 //        ") gives " + id2);
992     ASSERT_EQUAL(id2, astring("/SRV:1/SRC:1"), "produced wrong final string");
993   }
994 }
995
996 void test_string::run_test_34()
997 {
998   FUNCDEF("run_test_34");
999
1000 //not in use right now.
1001
1002 }
1003
1004 void test_string::run_test_35()
1005 {
1006   FUNCDEF("run_test_35");
1007   // test the shrink method.
1008   astring termo('R', 2812);
1009   ASSERT_EQUAL(termo.length(), 2812, "length should be as requested");
1010   termo[1008] = '\0';
1011   termo.shrink();
1012   ASSERT_EQUAL(termo.get_implementation().internal_real_length(), 1010, a_sprintf("failure in shrunken size: " "wanted 1010 and got %d.", termo.get_implementation().internal_real_length()));
1013   astring termo2('R', 1008);
1014   ASSERT_EQUAL(termo, termo2, "wrong value produced");
1015 }
1016
1017 void test_string::run_test_36()
1018 {
1019   FUNCDEF("run_test_36");
1020   // test the text form on a string array (which is mildly related to strings;
1021   // this could be moved to a common templates test someday).
1022   string_array torpid;
1023   torpid += "york";
1024   torpid += "burger";
1025   torpid += "petunia";
1026   torpid += "dumptruck";
1027   ASSERT_EQUAL(torpid.text_form(), astring("\"york\",\"burger\",\"petunia\",\"dumptruck\""), "wrong value computed");
1028   string_array sacral;
1029   sacral += "gumboat";
1030   ASSERT_EQUAL(sacral.text_form(), astring("\"gumboat\""), "wrong value computed");
1031
1032   string_array paknid;
1033   paknid += "gorboochy";
1034   paknid += "rangolent";
1035   byte_array packed;
1036   structures::pack_array(packed, paknid);
1037
1038   string_array upnort;
1039   ASSERT_TRUE(structures::unpack_array(packed, upnort), "failed to unpack");
1040   ASSERT_FALSE(packed.length(), "array still has bytes!");
1041
1042   string_array stongent;
1043   stongent += "pemulack";
1044   stongent += "bluzzent";
1045   stongent += "crupto";
1046   stongent += "floonack";
1047   stongent += "atoona";
1048   packed.reset();
1049   structures::pack_array(packed, stongent);
1050
1051   string_array belzorp;
1052   ASSERT_TRUE(structures::unpack_array(packed, belzorp), "failed to unpack");
1053   ASSERT_FALSE(packed.length(), "array still has bytes!");
1054 }
1055
1056 void test_string::run_test_37()
1057 {
1058   FUNCDEF("run_test_37");
1059   // 37th test group used to try out the old packing support, but now is
1060   // just the same as test 29.  it would be good to make this different.
1061   astring a("would an onion smell so sweet?");
1062   byte_array p1;
1063   a.pack(p1);
1064   astring b;
1065   ASSERT_TRUE(b.unpack(p1), "first unpack failed");
1066   ASSERT_EQUAL(b, a, "first comparison failed");
1067   a = "128 salamanders cannot be wrong.";
1068   a.pack(p1);
1069   ASSERT_TRUE(b.unpack(p1), "second unpack failed");
1070   ASSERT_EQUAL(b, a, "second comparison failed");
1071 }
1072
1073 void test_string::run_test_38()
1074 {
1075   FUNCDEF("run_test_38");
1076   double to_print = 2.345;
1077   a_sprintf non_deadly("%.1f", to_print);
1078 ///  LOG(astring("printed: ") + non_deadly);
1079
1080   to_print = 1.797E+254;
1081     // this value breaks things.
1082
1083   char bucket[2000];
1084   bucket[0] = '\0';
1085   sprintf(bucket, "%.1f", to_print);
1086 ///  LOG(astring("sprintf printed: ") + bucket);
1087
1088   a_sprintf deadly("%.1f", to_print);
1089 ///  LOG(astring("printed: ") + deadly);
1090 }
1091
1092 void test_string::run_test_39()
1093 {
1094   FUNCDEF("run_test_39");
1095   const char *find_set = "!?.;";
1096   astring test_1 = "how do i get to balthazar square?  it stinks!";
1097   ASSERT_EQUAL(test_1.find_any(find_set), 32, "first find returned wrong result");
1098   ASSERT_EQUAL(test_1.find_any(find_set, 33), 44, "second find returned wrong result");
1099   ASSERT_EQUAL(test_1.find_any(find_set, 40, true), 32, "third find returned wrong result");
1100 }
1101
1102 void test_string::run_test_40()
1103 {
1104   FUNCDEF("run_test_40");
1105   int test_num = 1;
1106   #define test_name() a_sprintf("test %d: ", test_num)
1107   {
1108     astring target = "xabab";
1109     astring from = "ab";
1110     astring to = "dc";
1111     ASSERT_TRUE(target.replace_all(from, to), test_name() + "didn't find from string");
1112     ASSERT_EQUAL(target, astring("xdcdc"), test_name() + "didn't replace properly");
1113     test_num++;
1114   }
1115   {
1116     astring target = "xabab";
1117     astring from = "ab";
1118     astring to = "ab";
1119     ASSERT_TRUE(target.replace_all(from, to), test_name() + "didn't find from string");
1120     ASSERT_EQUAL(target, astring("xabab"), test_name() + "didn't replace properly");
1121     test_num++;
1122   }
1123   {
1124     astring target = "xabab";
1125     astring from = "ab";
1126     astring to = "a";
1127     ASSERT_TRUE(target.replace_all(from, to), test_name() + "didn't find from string");
1128     ASSERT_EQUAL(target, astring("xaa"), test_name() + "didn't replace properly");
1129     test_num++;
1130   }
1131   {
1132     astring target = "ababx";
1133     astring from = "ab";
1134     astring to = "a";
1135     ASSERT_TRUE(target.replace_all(from, to), test_name() + "didn't find from string");
1136     ASSERT_EQUAL(target, astring("aax"), test_name() + "didn't replace properly");
1137     test_num++;
1138   }
1139   {
1140     astring target = "suzzle rumpetzzes gnargle rezztor";
1141     astring from = "zz";
1142     astring to = "zzz";
1143     ASSERT_TRUE(target.replace_all(from, to), test_name() + "didn't find from string");
1144     ASSERT_EQUAL(target, astring("suzzzle rumpetzzzes gnargle rezzztor"), test_name() + "didn't replace properly");
1145     test_num++;
1146   }
1147   {
1148     astring target = "qqqq";
1149     astring from = "q";
1150     astring to = "qqq";
1151     ASSERT_TRUE(target.replace_all(from, to), test_name() + "didn't find from string");
1152     ASSERT_EQUAL(target, astring("qqqqqqqqqqqq"), test_name() + "didn't replace properly");
1153     test_num++;
1154   }
1155   {
1156     astring target = "glorg snorp pendle funk";
1157     astring from = " ";
1158     astring to = "";
1159     ASSERT_TRUE(target.replace_all(from, to), test_name() + "didn't find from string");
1160     ASSERT_EQUAL(target, astring("glorgsnorppendlefunk"), test_name() + "didn't replace properly");
1161     test_num++;
1162   }
1163 }
1164
1165 void test_string::run_test_41()
1166 {
1167   FUNCDEF("run_test_41");
1168   int test_num = 0;
1169   #define test_name() a_sprintf("test %d: ", test_num)
1170   {
1171     test_num++;
1172     astring target = "xabab";
1173     const char *finding1 = "ab";
1174     ASSERT_EQUAL(target.find_non_match(finding1, 0, false), 0, test_name() + "didn't find right location A");
1175     const char *finding2 = "xb";
1176     ASSERT_EQUAL(target.find_non_match(finding2, target.length() - 1, true), 3, test_name() + "didn't find right location B");
1177     const char *finding3 = "c";
1178     ASSERT_EQUAL(target.find_non_match(finding3, 0, false), 0, test_name() + "wrong answer for test C");
1179     ASSERT_EQUAL(target.find_non_match(finding3, target.length() - 1, true), target.length() - 1, 
1180       test_name() + "wrong answer for test D");
1181   }
1182   {
1183     test_num++;
1184     astring target = "abcadefghoota";
1185     const char *finding1 = "bcdfghot";
1186     ASSERT_EQUAL(target.find_non_match(finding1, 0, false), 0, test_name() + "didn't find right location A");
1187     ASSERT_EQUAL(target.find_non_match(finding1, 1, false), 3, test_name() + "didn't find right location B");
1188     ASSERT_EQUAL(target.find_non_match(finding1, target.length() - 1, true), target.length() - 1, test_name() + "didn't find right location C");
1189     ASSERT_EQUAL(target.find_non_match(finding1, target.length() - 2, true), 5, test_name() + "didn't find right location D");
1190     ASSERT_EQUAL(target.find_non_match(finding1, 3, false), 3, test_name() + "didn't find right location E");
1191     ASSERT_EQUAL(target.find_non_match(finding1, 4, false), 5, test_name() + "didn't find right location F");
1192
1193   }
1194
1195 }
1196
1197 // exercise the middle, right and left methods.
1198 void test_string::run_test_42()
1199 {
1200   FUNCDEF("run_test_42");
1201
1202   astring hobnob("all the best robots are bending robots");
1203
1204   ASSERT_EQUAL(hobnob.middle(5, 7), astring("he best"), "failed to find middle of string");
1205   ASSERT_EQUAL(hobnob.right(10), astring("ing robots"), "failed to find right side of string");
1206   ASSERT_EQUAL(hobnob.left(6), astring("all th"), "failed to find right side of string");
1207 }
1208
1209 //////////////
1210
1211 int test_string::execute()
1212 {
1213   FUNCDEF("execute");
1214
1215 //  ASSERT_EQUAL(0, 1, "fake assertion to test jenkins log parsing");
1216   ASSERT_EQUAL(1, 1, "non-fake assertion to test jenkins log parsing");
1217
1218   ASSERT_EQUAL(staticity_test, astring("yo!"), "wrong contents");
1219
1220   time_stamp end_time(TEST_RUNTIME_DEFAULT);
1221     // when we're done testing.
1222
1223   int i = 0;  // iteration counter.
1224   while (time_stamp() < end_time) {
1225     // we run the test until our time runs out.
1226     i++;  // next iteration.
1227 #ifdef DEBUG_STRING_TEST
1228     LOG(astring(astring::SPRINTF, "index %d", i));
1229 #endif
1230
1231     // beginning of test sets.
1232     run_test_01();
1233     run_test_02();
1234     run_test_03();
1235     run_test_04();
1236     run_test_05();
1237     run_test_06();
1238     run_test_07();
1239     run_test_08();
1240     run_test_09();
1241     run_test_10();
1242     run_test_11();
1243     run_test_12();
1244     run_test_13();
1245     run_test_14();
1246     run_test_15();
1247     run_test_16();
1248     run_test_17();
1249     run_test_18();
1250     run_test_19();
1251     run_test_20();
1252     run_test_21();
1253     run_test_22();
1254     run_test_23();
1255     run_test_24();
1256     run_test_25();
1257     run_test_26();
1258     run_test_27();
1259     run_test_28();
1260     run_test_29();
1261 //too slow    run_test_30();
1262     run_test_31();
1263     run_test_32();
1264     run_test_33();
1265 //retired    run_test_34();
1266     run_test_35();
1267     run_test_36();
1268     run_test_37();
1269     run_test_38();
1270     run_test_39();
1271     run_test_40();
1272     run_test_41();
1273     run_test_42();
1274   }
1275
1276   return final_report();
1277 }
1278
1279 HOOPLE_MAIN(test_string, )
1280
1281