|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7: * Reserved. This file contains Original Code and/or Modifications of
8: * Original Code as defined in and that are subject to the Apple Public
9: * Source License Version 1.0 (the 'License'). You may not use this file
10: * except in compliance with the License. Please obtain a copy of the
11: * License at http://www.apple.com/publicsource and read it before using
12: * this file.
13: *
14: * The Original Code and all software distributed under the License are
15: * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19: * License for the specific language governing rights and limitations
20: * under the License."
21: *
22: * @APPLE_LICENSE_HEADER_END@
23: */
24: /*
25: StringTest.m by Ali Ozer
26: Run with -v for verbose mode (where all results, successful or not, are shown).
27: */
28:
29: #ifdef TESTING
30: #define NXString NxString
31: #define NXMutableString NxMutableString
32: #define NXReadWriteString NxReadWriteString
33: #define NXReadOnlyString NxReadOnlyString
34: #define NXReadOnlySubstring NxReadOnlySubstring
35: #define NXSimpleReadOnlyString NxSimpleReadOnlyString
36: #define NXUniquedString NxUniquedString
37: #define NXGapString NxGapString
38: #define NXBigString NxBigString
39: #endif
40:
41: #import "NXString.h"
42:
43: #define TESTTESTEDSTUFF
44: // #define TESTGAPSTRING
45: // #define TESTBIGSTRING
46:
47: #ifdef TESTGAPSTRING
48: #import "NXGapString.h"
49: #endif
50: #ifdef TESTBIGSTRING
51: #import "NXBigString.h"
52: #endif
53:
54: #define TESTCONSTANTSTRING
55:
56: #import <stdio.h>
57: #import <streams/streams.h>
58: #import <appkit/nextstd.h>
59: #import <libc.h>
60:
61: #define CHARALLOC(zone, var, num) var = ((num) ? NXZoneMalloc((zone), sizeof(unichar) * (num)) : NULL)
62:
63: static int numErrors;
64: static BOOL verbose;
65:
66: @interface NXString (DebugStuff)
67:
68: - (void)verifyInt:(int)value :(int)desired;
69: - (void)verifyCStrings:(const char *)value :(const char *)desired;
70: - (void)verifyChars:(const char *)theRealThing;
71: - (void)verifyId:theRealThing;
72: - (void)verifyString:theRealThing;
73:
74: @end
75:
76: @implementation NXString (DebugStuff)
77:
78: static Err()
79: {
80: // Place to break on...
81: numErrors++;
82: }
83:
84: - (void)verifyChars:(const char *)theRealThing
85: {
86: unichar buffer[1000];
87: BOOL equal;
88:
89: [self getCharacters:buffer];
90:
91: if (equal = ([self length] == strlen(theRealThing))) {
92: int cnt, length = [self length];
93: for (cnt = 0; cnt < length; cnt++) {
94: if (buffer[cnt] != (unichar)theRealThing[cnt]) {
95: equal = NO;
96: break;
97: }
98: }
99: }
100:
101: if (verbose || !equal) {
102: fprintf (stderr, "%s:", equal ? "OK" : "*** NOT OK");
103: fprintf (stderr, " %p ", self);
104: [self printForDebugger: NXOpenFile (fileno (stderr), NX_WRITEONLY)];
105: fprintf (stderr, "\n");
106:
107: if (!equal) {
108: fprintf (stderr, "*** Should be: %s\n", theRealThing);
109: Err();
110: }
111: }
112: }
113:
114: - (void)verifyInt:(int)value :(int)desired
115: {
116: BOOL equal = (value == desired);
117:
118: if (verbose || !equal) {
119: fprintf (stderr, "%s:", equal ? "OK" : "*** NOT OK");
120: fprintf (stderr, " %p ", self);
121: [self printForDebugger: NXOpenFile (fileno (stderr), NX_WRITEONLY)];
122: fprintf (stderr, "\n");
123:
124: if (!equal) {
125: fprintf (stderr, "*** %d should be: %d\n", value, desired);
126: Err();
127: }
128: }
129: }
130:
131: - (void)verifyCStrings:(const char *)value :(const char *)desired
132: {
133: BOOL equal = !strcmp(value, desired);
134:
135: if (verbose || !equal) {
136: fprintf (stderr, "%s:", equal ? "OK" : "*** NOT OK");
137: fprintf (stderr, " %p ", self);
138: [self printForDebugger: NXOpenFile (fileno (stderr), NX_WRITEONLY)];
139: fprintf (stderr, "\n");
140:
141: if (!equal) {
142: fprintf (stderr, "*** %s should be: %s\n", value, desired);
143: Err();
144: }
145: }
146: }
147:
148: - (void)verifyId:theRealThing
149: {
150: BOOL equal = (theRealThing == self);
151:
152: if (verbose || !equal) {
153: fprintf (stderr, "%s:", equal ? "OK" : "*** NOT OK");
154: fprintf (stderr, " %p ", self);
155: [self printForDebugger: NXOpenFile (fileno (stderr), NX_WRITEONLY)];
156: fprintf (stderr, "\n");
157:
158: if (!equal) {
159: fprintf (stderr, "*** Should be: %p\n", theRealThing);
160: Err();
161: }
162: }
163: }
164:
165: - (void)verifyString:theRealThing
166: {
167: BOOL equal = ([self isEqual:theRealThing]);
168:
169: if (verbose || !equal) {
170: fprintf (stderr, "%s:", equal ? "OK" : "*** NOT OK");
171: fprintf (stderr, " %p ", self);
172: [self printForDebugger: NXOpenFile (fileno (stderr), NX_WRITEONLY)];
173: fprintf (stderr, "\n");
174:
175: if (!equal) {
176: fprintf (stderr, "*** Should be: ");
177: [theRealThing printForDebugger: NXOpenFile (fileno (stderr), NX_WRITEONLY)];
178: fprintf (stderr, "\n");
179: Err();
180: }
181: }
182: }
183:
184: @end
185:
186: #define TITLE(title) \
187: printf ("%s%s %s%s\n", \
188: verbose ? "\n" : "", \
189: [testClass name], \
190: (title), \
191: verbose ? ":" : "...")
192:
193: #define TITLE1(title) \
194: printf ("%s%s%s\n", \
195: verbose ? "\n" : "", \
196: (title), \
197: verbose ? ":" : "...")
198:
199: /* This function returns a string containing 200 occurences of "ab..yz"
200: */
201: static NXString *hugeString (id testClass)
202: {
203: #define HUGESTRINGLEN 5200
204: static char buf[HUGESTRINGLEN] = {'\0'};
205: if (buf[0] == '\0') {
206: int cnt;
207: for (cnt = 0; cnt < HUGESTRINGLEN; cnt++) buf[cnt] = ('a' + (cnt % 26));
208: }
209: return [[testClass alloc] initFromCString:buf];
210: }
211:
212: void testBasic /* create/read/copy/free */ (id testClass)
213: {
214: id str1, str2, str3;
215: unichar chars1[] = {'A', 'B', 'C', 'D', 'E'};
216: unichar chars2[] = {'F', 'G', 'H', 'I', 'J'};
217: unichar chars3[] = {'K', 'L', 'M', 'N', 'O'};
218: unichar *charPtr;
219: NXRange range = {1, 2};
220: NXRange tmpRange = {0, 0};
221:
222: TITLE ("basic create/read/copy/free test");
223:
224: str1 = [[testClass alloc] initFromCharacters:chars1 length:5];
225: str2 = [[testClass alloc] initFromString:str1];
226: str3 = [[testClass alloc] initFromString:str2 range:range];
227: [str3 verifyChars:"BC"];
228: [str3 free];
229: str3 = [str2 copy];
230: [str3 verifyChars:"ABCDE"];
231: [str2 free];
232: [str3 verifyChars:"ABCDE"];
233: [str3 free];
234:
235: str3 = [[testClass alloc] initFromCharacters:chars2 length:5];
236: CHARALLOC(NXDefaultMallocZone(), charPtr, NX_LENGTH(range));
237: [str3 getCharacters:charPtr range:range];
238: str2 = [[testClass alloc] initFromCharacters:charPtr length:NX_LENGTH(range)];
239: [str3 verifyChars:"FGHIJ"];
240: [str2 verifyChars:"GH"];
241: [str2 free];
242: NX_FREE (charPtr);
243:
244: NX_LOCATION(tmpRange) = 1;
245: NX_LENGTH(tmpRange) = [str3 length] - 1;
246: CHARALLOC(NXDefaultMallocZone(), charPtr, NX_LENGTH(tmpRange));
247: [str3 getCharacters:charPtr range:tmpRange];
248: str2 = [[testClass alloc] initFromCharacters:charPtr length:NX_LENGTH(tmpRange)];
249: [str2 verifyChars:"GHIJ"];
250: [str2 free];
251: [str3 free];
252: [str1 free];
253: NX_FREE (charPtr);
254:
255: str3 = [[testClass alloc] initFromCharacters:chars3 length:5];
256: str2 = [str3 copy];
257: NX_LOCATION(tmpRange) = 0;
258: NX_LENGTH(tmpRange) = [str2 length];
259: CHARALLOC(NXDefaultMallocZone(), charPtr, NX_LENGTH(tmpRange));
260: [str2 getCharacters:charPtr range:tmpRange];
261: str1 = [[testClass alloc] initFromCharactersNoCopy:charPtr length:NX_LENGTH(tmpRange)];
262: [str3 free];
263: [str2 verifyChars:"KLMNO"];
264: [str2 free];
265: [str1 verifyChars:"KLMNO"];
266: [str1 free];
267:
268: str1 = [[testClass alloc] init];
269: str2 = [[testClass alloc] init];
270: [str1 free];
271: str1 = [str2 copy];
272: str3 = [[testClass alloc] initFromCharacters:NULL length:0];
273: [str2 free];
274: [str3 verifyChars:""];
275: [str3 free];
276: [str1 verifyChars:""];
277: [str1 free];
278:
279: }
280:
281: void testCopy /* copy */ (id testClass)
282: {
283: id str1, str2, str3, str4;
284: unichar chars1[] = {'A', 'B', 'C', 'D', 'E'};
285: NXRange range = {1,3};
286:
287: TITLE ("mutable/immutable copy test");
288:
289: str1 = [[testClass alloc] initFromCharacters:chars1 length:5];
290: str2 = [str1 mutableCopy];
291: [str2 appendString:str1];
292: [str2 verifyChars:"ABCDEABCDE"];
293: str3 = [str1 copySubstring:range];
294: str4 = [str2 copySubstring:range];
295: [str4 appendString:str3];
296: [str4 verifyChars:"BCDBCD"];
297: [str1 free];
298: [str2 free];
299: str1 = [str3 mutableCopy];
300: [str1 insertString:str4 at:1];
301: [str1 verifyChars:"BBCDBCDCD"];
302: [str3 verifyChars:"BCD"];
303: [str4 verifyChars:"BCDBCD"];
304: [str3 free];
305: [str4 free];
306: [str1 verifyChars:"BBCDBCDCD"];
307: [str1 free];
308:
309: }
310:
311: void testRefCountedAndUniqued ()
312: {
313: id str1, str2, str3, str4;
314: unichar chars1[] = {'A', 'B', 'C', 'D', 'E'};
315: NXRange range = {1,3};
316: typedef struct {@defs(NXReadOnlyString);} ROString;
317:
318: TITLE1 ("NXReadOnlyString, NXReadWriteString, NXUniquedString tests");
319:
320: str1 = [[NXReadOnlyString alloc] initFromCharacters:chars1 length:5];
321: str2 = [str1 mutableCopy];
322: str3 = [str2 immutableCopy];
323: [str1 verifyInt:(int)str3 :(int)str1];
324: [str2 free];
325: str2 = [[NXReadWriteString alloc] initFromCharacters:chars1 length:3];
326: [str1 verifyInt:(int)str3 :(int)str1];
327: [str1 free];
328: [str3 verifyChars:"ABCDE"];
329: [str2 appendString:str3];
330: [str3 free];
331: [str2 verifyChars:"ABCABCDE"];
332:
333: str1 = [[NXReadOnlyString alloc] initFromCharactersNoCopy:chars1 length:5 freeWhenDone:NO];
334: str2 = [str1 mutableCopy];
335: str3 = [str2 immutableCopy];
336: [str2 free];
337: str2 = [str3 copySubstring:range];
338: [str1 verifyInt:(int)(((ROString *)str1)->characters)+1 :(int)(((ROString *)str2)->characters)];
339:
340: [str1 free];
341: [str3 verifyChars:"ABCDE"];
342: [str3 free];
343: str3 = [str2 mutableCopy];
344: [str3 insertString:str2 at:1];
345: [str3 verifyChars:"BBCDCD"];
346: [str3 deleteCharactersInRange:range];
347: [str3 verifyChars:"BCD"];
348: [str2 verifyChars:"BCD"];
349:
350: str1 = [NXUniquedString newFromString:str3];
351: str4 = [NXUniquedString newFromString:str2];
352: [str1 verifyInt:(int)str4 :(int)str1];
353: [str1 verifyInt:(int)[NXUniquedString newFromString:[str4 mutableCopy]] :(int)str1];
354:
355: }
356:
357:
358: void testEdit /* edit */ (id testClass)
359: {
360: id str1, str2, str3;
361: typedef struct _NXReadWriteStringKludge {
362: @defs(NXReadWriteString);
363: } NXReadWriteStringKludge;
364: typedef struct _NXReadOnlyStringKludge {
365: @defs(NXReadOnlyString);
366: } NXReadOnlyStringKludge;
367: unichar chars1[] = {'A', 'B', 'C', 'D', 'E'};
368: unichar chars2[] = {'F', 'G', 'H', 'I', 'J'};
369: unichar chars3[] = {'K', 'L', 'M', 'N', 'O'};
370: int addr = 0;
371: NXRange range = {1, 2};
372:
373: TITLE ("appendString/delete/insertString test");
374:
375: str1 = [[testClass alloc] initFromCharacters:chars1 length:5];
376: str2 = [[testClass alloc] initFromString:str1 range:range];
377: [str1 appendString:str2];
378: [str1 verifyChars:"ABCDEBC"];
379: [str2 verifyChars:"BC"];
380: [str1 insertString:str2 at:0];
381: [str1 insertString:str2 at:3];
382: [str1 deleteCharactersInRange:range];
383: [str1 verifyChars:"BBCBCDEBC"];
384: [str1 free];
385:
386: str1 = [[NXReadOnlyString alloc] initFromCharacters:chars3 length:5];
387: [str2 appendString:str1];
388: [str1 free];
389: [str2 verifyChars:"BCKLMNO"];
390: if (testClass == [NXReadWriteString class]) {
391: addr = (int)((NXReadOnlyStringKludge *)(((NXReadWriteStringKludge *)str2)->actualString))->characters;
392: }
393: str1 = [str2 copy];
394: str3 = [str1 copy];
395: [str2 free];
396: [str1 free];
397: str2 = [str3 copy];
398: [str3 verifyChars:"BCKLMNO"];
399: [str2 verifyChars:"BCKLMNO"];
400: if (testClass == [NXReadWriteString class]) {
401: [str2 verifyInt:(int)((NXReadOnlyStringKludge *)(((NXReadWriteStringKludge *)str2)->actualString))->characters :addr];
402: }
403: str1 = [[NXReadOnlyString alloc] initFromCharacters:chars2 length:1];
404: [str2 insertString:str1 at:2];
405: [str1 free];
406: [str3 verifyChars:"BCKLMNO"];
407: [str2 verifyChars:"BCFKLMNO"];
408: [str2 free];
409: [str3 free];
410:
411: str1 = [[testClass alloc] init];
412: str2 = [[testClass alloc] init];
413: [str1 appendString:@"Foo Bar"];
414: [str1 verifyChars:"Foo Bar"];
415: [str2 verifyChars:""];
416: [str1 free];
417: str1 = [[testClass alloc] init];
418: [str2 verifyChars:""];
419: [str1 appendString:str2];
420: [str2 free];
421: [str1 verifyChars:""];
422:
423: }
424:
425: void testLargeEdit /* large edit */ (id testClass)
426: {
427: int cnt;
428: id str1, str2, str3;
429: unichar chars1[] = {'A', 'B', 'C', 'D', 'E'};
430: NXRange range = {999, 25};
431: NXRange findRange;
432:
433: TITLE ("large appendString/delete/insertString test");
434:
435: str1 = [[testClass alloc] initFromCharacters:chars1 length:5];
436: str2 = [str1 copy];
437: for (cnt = 1; cnt < 64; cnt++) {
438: [str1 appendString:str2];
439: } // Resulting length is 320
440: [str2 free];
441: str2 = [str1 copy];
442: [str1 appendString:str2]; // 640
443: [str1 appendString:str2]; // 960
444: [str1 appendString:str2]; // 1280
445: [str2 free];
446: [str1 verifyInt:[str1 length] :1280];
447:
448: str2 = [[testClass alloc] initFromString:str1 range:range];
449: [str2 verifyChars:"EABCDEABCDEABCDEABCDEABCD"];
450: [str2 insertString:str1 at:2];
451: [str2 insertString:str1 at:[str2 length]];
452: [str1 free];
453: str3 = [str2 copySubstring:(NXRange){0, 10} fromZone:[str2 zone]];
454: [str3 verifyChars:"EAABCDEABC"];
455: str1 = [str2 copy];
456: [str2 replaceCharactersInRange:range withString:str1];
457: [str2 appendString:str3];
458: [str2 appendString:@"Howdy"];
459: [str3 free];
460: [str2 verifyInt:[str2 length] :5160];
461: findRange = [str2 findString:@"EAABCDEABCH"];
462: [str2 verifyInt:NX_LOCATION(findRange) :5145];
463: [str1 free];
464: NX_LOCATION(range) = 2;
465: NX_LENGTH(range) = [str2 length] - 4;
466: [str2 deleteCharactersInRange:range];
467: [str2 verifyChars:"EAdy"];
468: [str2 free];
469: }
470:
471: void testCompare /* compare */ (id testClass)
472: {
473: id str1, str2, str3, str4, str5;
474: unichar chars1[] = {'A', 'B', 'C', 'D', 'E'};
475: unichar chars2[] = {'F', 'G', 'h', 'f', 'g'};
476: unichar chars3[] = {'F', 'g', 'H', 'f', 'G'};
477:
478: TITLE ("compare test");
479:
480: str1 = [[testClass alloc] initFromCharacters:chars1 length:5];
481: str2 = [[testClass alloc] initFromCharacters:chars1 length:4];
482: str3 = [[testClass alloc] initFromCharacters:chars2 length:4];
483: [str1 verifyInt:[str1 compare:str1] :0];
484: [str1 verifyInt:[str1 compare:str2] :1];
485: [str1 verifyInt:[str1 compare:str3] :-1];
486: [str2 verifyInt:[str2 compare:str1] :-1];
487: [str2 verifyInt:[str2 compare:str3] :-1];
488: [str3 verifyInt:[str3 compare:str1] :1];
489: [str3 verifyInt:[str3 compare:str2] :1];
490: str4 = [[NXReadWriteString alloc] initFromString:str1];
491: str5 = [str4 copy];
492: [str1 verifyInt:[str1 compare:str4] :0];
493: [str5 verifyInt:[str5 compare:str1] :0];
494: [str4 appendString:str4];
495: [str1 verifyInt:[str1 compare:str4] :-1];
496: [str5 verifyInt:[str5 compare:str1] :0];
497: [str4 free];
498: [str5 free];
499: [str1 free];
500: [str2 free];
501: str4 = [[testClass alloc] initFromCharacters:chars3 length:4];
502: [str4 verifyInt:[str4 compare:str3] :1];
503: [str3 verifyInt:[str3 compare:str4] :-1];
504: [str4 verifyInt:[str4 compare:str3 mask:NX_CASE_INSENSITIVE table:NULL] :0];
505: [str3 verifyInt:[str3 compare:str4 mask:NX_CASE_INSENSITIVE table:NULL] :0];
506: str2 = [[NXReadOnlyString alloc] initFromString:str3];
507: [str4 verifyInt:[str4 compare:str2] :1];
508: [str2 verifyInt:[str2 compare:str4] :-1];
509: [str2 free];
510: [str3 free];
511: [str4 free];
512: }
513:
514: #define wholeRange(s) ((NXRange){0, [(s) length]})
515:
516: void testFind /* find */ (id testClass)
517: {
518: id str1, str2, str3, str4;
519: unichar chars1[] = {'A', 'B', 'C', 'D', 'E', 'F', 'g', 'h', 'a', 'b', 'B', 'C'};
520: unichar chars2[] = {'F', 'G', 'h', 'f', 'g'};
521: unichar chars3[] = {'F', 'g', 'H', 'f', 'G'};
522: NXRange findRange;
523:
524: TITLE ("find test");
525:
526: str1 = [[testClass alloc] initFromCharacters:chars1 length:12]; // ABCDEFghabBC
527: str2 = [[testClass alloc] initFromCharacters:chars1 length:2]; // AB
528: str3 = [[testClass alloc] initFromCharacters:chars2 length:2]; // FG
529: str4 = [[testClass alloc] initFromCharacters:chars3 length:2]; // Fg
530:
531: findRange = [str1 findString:str2];
532: [str1 verifyInt:NX_LOCATION(findRange) :0];
533: [str1 verifyInt:NX_LENGTH(findRange) :2];
534: findRange = [str1 findString:str3];
535: [str1 verifyInt:NX_LOCATION(findRange) :NX_STRING_NOT_FOUND];
536: [str1 verifyInt:NX_LENGTH(findRange) :0];
537: findRange = [str1 findString:str4];
538: [str1 verifyInt:NX_LOCATION(findRange) :5];
539: [str1 verifyInt:NX_LENGTH(findRange) :2];
540: findRange = [str1 findString:str3 range:wholeRange(str1) mask:NX_CASE_INSENSITIVE table:NULL];
541: [str1 verifyInt:NX_LOCATION(findRange) :5];
542: [str1 verifyInt:NX_LENGTH(findRange) :2];
543: findRange = [str1 findString:str2 range:wholeRange(str1) mask:NX_CASE_INSENSITIVE|NX_BACKWARDS_SEARCH table:NULL];
544: [str1 verifyInt:NX_LOCATION(findRange) :8];
545: [str1 verifyInt:NX_LENGTH(findRange) :2];
546: findRange = [str1 findString:str2 range:wholeRange(str1) mask:NX_BACKWARDS_SEARCH table:NULL];
547: [str1 verifyInt:NX_LOCATION(findRange) :0];
548: [str1 verifyInt:NX_LENGTH(findRange) :2];
549: findRange = [str3 findString:str4 range:wholeRange(str3) mask:NX_BACKWARDS_SEARCH table:NULL];
550: [str3 verifyInt:NX_LOCATION(findRange) :NX_STRING_NOT_FOUND];
551: [str3 verifyInt:NX_LENGTH(findRange) :0];
552: findRange = [str3 findString:str4 range:wholeRange(str3) mask:NX_CASE_INSENSITIVE|NX_BACKWARDS_SEARCH table:NULL];
553: [str3 verifyInt:NX_LOCATION(findRange) :0];
554: [str3 verifyInt:NX_LENGTH(findRange) :2];
555: findRange = [str3 findString:str4 range:wholeRange(str3) mask:NX_CASE_INSENSITIVE table:NULL];
556: [str3 verifyInt:NX_LOCATION(findRange) :0];
557: [str3 verifyInt:NX_LENGTH(findRange) :2];
558: findRange = [str2 findString:str1];
559: [str2 verifyInt:NX_LOCATION(findRange) :NX_STRING_NOT_FOUND];
560: [str2 verifyInt:NX_LENGTH(findRange) :0];
561:
562: NX_LOCATION(findRange) = 1;
563: NX_LENGTH(findRange) = [str1 length] - 1;
564: findRange = [str1 findString:str2 range:findRange mask:NX_CASE_INSENSITIVE table:NULL];
565: [str3 verifyInt:NX_LOCATION(findRange) :8];
566: [str3 verifyInt:NX_LENGTH(findRange) :2];
567:
568: }
569:
570: void testStream (id testClass)
571: {
572: const char *bytes = "Hello There. Hi There.";
573: unichar chars1[] = {'A', 'B', 'C', 0, 1, 2, '0', '1', '2'};
574: NXStream *stream;
575: id str1, str2, str3, str4;
576: NXCharacterSet *numberSet;
577:
578: TITLE ("stream test");
579:
580: numberSet = [[NXCharacterSet alloc] init];
581: [numberSet addRange:'0' :'9'];
582:
583: stream = NXOpenMemory(bytes, strlen(bytes), NX_READONLY);
584: str1 = [[testClass alloc] initFromCStringStream:stream untilOneOf:nil maxLength:1];
585: str2 = [[testClass alloc] initFromCStringStream:stream untilOneOf:nil maxLength:17];
586: str3 = [[testClass alloc] initFromCStringStream:stream untilOneOf:nil maxLength:120];
587:
588: [str1 verifyChars:"H"];
589: [str2 verifyChars:"ello There. Hi Th"];
590: [str3 verifyChars:"ere."];
591: [str1 free];
592: [str3 free];
593:
594: NXClose (stream);
595:
596: stream = NXOpenMemory(NULL, 0, NX_READWRITE);
597: [str2 writeCStringToStream:stream];
598: str1 = [[testClass alloc] initFromCharacters:chars1 length:9];
599: [str1 writeCStringToStream:stream];
600:
601: NXSeek(stream, 1, NX_FROMSTART);
602: str3 = [[testClass alloc] initFromCStringStream:stream untilOneOf:nil maxLength:NX_MAX_STRING_LENGTH];
603:
604: str4 = [[NXReadWriteString alloc] init];
605: [str4 append:str2];
606: [str4 deleteCharactersInRange:(NXRange){0,1}]; // Because we seeked to 1 above...
607: [str4 append:str1];
608:
609: [str3 verifyString:str4];
610: [str3 verifyInt:[str3 length] :[str2 length] - 1 + 9];
611:
612: [str3 free];
613:
614: NXSeek(stream, 1, NX_FROMSTART);
615: str3 = [[testClass alloc] initFromCStringStream:stream untilOneOf:numberSet maxLength:NX_MAX_STRING_LENGTH];
616:
617: [str4 deleteCharactersInRange:(NXRange){[str4 length]-3, 3}];
618: [str3 verifyString:str4];
619: [str3 verifyInt:[str3 length] :[str2 length] - 1 + 6];
620: [str3 free];
621:
622: NXSeek(stream, 1, NX_FROMSTART);
623: str3 = [[testClass alloc] initFromCStringStream:stream untilOneOf:numberSet maxLength:5];
624:
625: [str4 deleteCharactersInRange:(NXRange){5, [str4 length] - 5}];
626: [str3 verifyString:str4];
627: [str3 verifyInt:[str3 length] :5];
628: [str3 free];
629:
630: [str1 free];
631: [str2 free];
632: [str4 free];
633:
634: NXCloseMemory(stream, NX_FREEBUFFER);
635:
636: str1 = hugeString(testClass);
637:
638: stream = NXOpenMemory(NULL, 0, NX_READWRITE);
639: [str1 writeCStringToStream:stream];
640: NXSeek(stream, 0, NX_FROMSTART);
641: str2 = [[testClass alloc] initFromCStringStream:stream untilOneOf:nil maxLength:NX_MAX_STRING_LENGTH];
642: [str1 verifyString:str2];
643: [str2 free];
644: NXCloseMemory(stream, NX_FREEBUFFER);
645:
646: stream = NXOpenMemory(NULL, 0, NX_READWRITE);
647: [str1 writeToStream:stream];
648: NXSeek(stream, 0, NX_FROMSTART);
649: str2 = [[testClass alloc] initFromStream:stream untilOneOf:nil maxLength:NX_MAX_STRING_LENGTH];
650: [str1 verifyString:str2];
651: [str2 free];
652: NXCloseMemory(stream, NX_FREEBUFFER);
653:
654: [str1 free];
655: }
656:
657: void testHash (id testClass)
658: {
659: id str1;
660: unichar chars1[] = {'F', 'o', 'o'};
661:
662: TITLE ("hash test");
663:
664: str1 = [[testClass alloc] initFromCharacters:chars1 length:3];
665: [str1 verifyInt:[str1 hash] :32095];
666: [str1 verifyInt:[str1 hash] :[@"Foo" hash]];
667: [str1 free];
668:
669: str1 = [[testClass alloc] initFromString:@"Hello World"];
670: [str1 verifyInt:[str1 hash] :850486630];
671: [str1 free];
672: }
673:
674: void testFormat (id testClass)
675: {
676: id str1, str2, str3;
677: int cnt;
678: unichar chars1[] = {'F', 'o', 'o'};
679:
680: TITLE ("formatted create test");
681:
682: str1 = [[NXReadOnlyString alloc] initFromCString:"===%2.1f %d %s %@==="];
683: str2 = [[NXReadOnlyString alloc] initFromCharacters:chars1 length:3];
684: str3 = [[testClass alloc] initFromFormat:str1, 3.14, -42, "Hello World", str2];
685:
686: [str3 verifyChars:"===3.1 -42 Hello World Foo==="];
687:
688: [str1 free];
689: [str2 free];
690: [str3 free];
691:
692: str1 = [[NXReadOnlyString alloc] initFromCString:"Hello"];
693: str3 = [[NXReadWriteString alloc] initFromString:str1];
694: for (cnt = 0; cnt < 12; cnt++) {
695: str2 = [[testClass alloc] initFromFormat:@"%@*%@", str1, str1];
696: [str3 appendString:@"*"]; // Test string; we assume append works.
697: [str3 appendString:str1];
698: [str2 verifyString:str3];
699: [str1 free];
700: str1 = str2;
701: }
702: [str3 free];
703: str3 = [[NXReadOnlyString alloc] initFromString:str1 range:(NXRange){[str1 length] - 6, 6}];
704: [str3 verifyChars:"*Hello"];
705: [str1 free];
706: [str3 free];
707: }
708:
709: void testCStrings (id testClass)
710: {
711: id str1, str2;
712: char *cString;
713: NXAtom uString1, uString2;
714: #define CSTRBUFLEN 10
715: #define CSTRBIGBUFLEN 1000
716: char cStringBuffer[CSTRBIGBUFLEN+1];
717: int cnt;
718: NXRange range;
719:
720: TITLE ("CString test");
721:
722: str1 = [[NXReadOnlyString alloc] initFromCString:"Hello World"];
723: str2 = [str1 mutableCopy];
724: cString = [str1 cStringCopy];
725: [str1 verifyChars:cString];
726: free (cString);
727: uString1 = [str1 uniqueCStringCopy];
728: [str1 verifyChars:uString1];
729: uString2 = [str1 uniqueCStringCopy];
730: [str1 verifyInt:(int)uString1 :(int)uString2];
731: uString2 = [str2 uniqueCStringCopy];
732: [str1 verifyInt:(int)uString1 :(int)uString2];
733: [str2 appendString:@""];
734: uString2 = [str2 uniqueCStringCopy];
735: [str1 verifyInt:(int)uString1 :(int)uString2];
736: [str2 appendString:@" "];
737: uString1 = [str2 uniqueCStringCopy];
738: uString2 = [@"Hello World " uniqueCStringCopy];
739: [str2 verifyInt:(int)uString1 :(int)uString2];
740: [str1 free];
741: [str2 free];
742:
743: str1 = [[testClass alloc] initFromCString:"Bonjour Everyone"];
744: [str1 getCString:cStringBuffer maxLength:3];
745: [str1 verifyCStrings:cStringBuffer :"Bon"];
746: [str1 getCString:cStringBuffer maxLength:0];
747: [str1 verifyCStrings:cStringBuffer :""];
748: NX_LOCATION(range) = 8; NX_LENGTH(range) = 5;
749: [str1 getCString:cStringBuffer maxLength:NX_MAX_STRING_LENGTH range:range remainingRange:NULL];
750: [str1 verifyCStrings:cStringBuffer :"Every"];
751: [str1 getCString:cStringBuffer maxLength:2 range:range remainingRange:NULL];
752: [str1 verifyCStrings:cStringBuffer :"Ev"];
753: [str1 getCString:cStringBuffer maxLength:CSTRBUFLEN range:range remainingRange:NULL];
754: [str1 verifyCStrings:cStringBuffer :"Every"];
755: [str1 getCString:cStringBuffer maxLength:CSTRBUFLEN];
756: [str1 verifyCStrings:cStringBuffer :"Bonjour Ev"];
757: NX_LOCATION(range) = 0;
758: NX_LENGTH(range) = 11;
759: [str1 getCString:cStringBuffer maxLength:0 range:range remainingRange:&range];
760: [str1 verifyCStrings:cStringBuffer :""];
761: [str1 verifyInt:NX_LOCATION(range) :0];
762: [str1 verifyInt:NX_LENGTH(range) :11];
763: [str1 getCString:cStringBuffer maxLength:5 range:range remainingRange:&range];
764: [str1 verifyCStrings:cStringBuffer :"Bonjo"];
765: [str1 verifyInt:NX_LOCATION(range) :5];
766: [str1 verifyInt:NX_LENGTH(range) :6];
767: [str1 getCString:cStringBuffer maxLength:10 range:range remainingRange:&range];
768: [str1 verifyCStrings:cStringBuffer :"ur Eve"];
769: [str1 verifyInt:NX_LOCATION(range) :11];
770: [str1 verifyInt:NX_LENGTH(range) :0];
771: [str1 free];
772:
773: str1 = hugeString(testClass);
774: [str1 getCString:cStringBuffer maxLength:CSTRBIGBUFLEN range:(NXRange){0,[str1 length]} remainingRange:&range];
775: cnt = 26 * ((int)(CSTRBIGBUFLEN / 26) - 1);
776: cStringBuffer[cnt + 26] = '\0';
777: [str1 verifyCStrings:&cStringBuffer[cnt] :"abcdefghijklmnopqrstuvwxyz"];
778: [str1 verifyInt:NX_LOCATION(range) :CSTRBIGBUFLEN];
779: [str1 verifyInt:NX_LENGTH(range) :[str1 length] - CSTRBIGBUFLEN];
780: [str1 free];
781: }
782:
783: void testFindAndSets (id testClass)
784: {
785: id str1;
786: unichar chars1[] = {'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd', '1', 'h', '3'};
787: unichar chars2[] = {' ', '\t'};
788: NXCharacterSet *numberSet, *alphaSet, *spaceSet, *notAlphaSet, *numAndAlphaSet;
789:
790: TITLE ("find and NXCharacterSet test");
791:
792: numberSet = [[NXCharacterSet alloc] init];
793: [numberSet addRange:'0' :'9'];
794:
795: alphaSet = [[NXCharacterSet alloc] init];
796: [alphaSet addRange:'a' :'z'];
797: [alphaSet addRange:'A' :'Z'];
798:
799: notAlphaSet = [[NXCharacterSet alloc] init];
800: [notAlphaSet addRange:'a' :'z'];
801: [notAlphaSet addRange:'A' :'Z'];
802: [notAlphaSet invert];
803:
804: spaceSet = [[NXCharacterSet alloc] init];
805: [spaceSet addCharacters:chars2 length:2];
806: [spaceSet addCharacters:chars1 length:14];
807: [spaceSet removeCharacters:chars1 length:14];
808: [spaceSet addCharacters:chars2 length:2];
809:
810: numAndAlphaSet = [[NXCharacterSet alloc] init];
811: [numAndAlphaSet unionWith:alphaSet];
812: [numAndAlphaSet unionWith:numberSet];
813:
814: str1 = [[testClass alloc] initFromCharacters:chars1 length:14];
815: [str1 verifyInt:[str1 findCharacter:'l'] :2];
816: [str1 verifyInt:[str1 findCharacter:'l' range:wholeRange(str1) mask:NX_BACKWARDS_SEARCH table:NULL] :9];
817: [str1 verifyInt:[str1 findCharacter:'h' range:wholeRange(str1) mask:NX_CASE_INSENSITIVE table:NULL] :0];
818: [str1 verifyInt:[str1 findCharacter:'h' range:wholeRange(str1) mask:NX_BACKWARDS_SEARCH table:NULL] :12];
819:
820: [str1 verifyInt:[str1 findOneOf:alphaSet] :0];
821: [str1 verifyInt:[str1 findOneOf:notAlphaSet] :5];
822: [str1 verifyInt:[str1 findOneOf:spaceSet] :5];
823: [str1 verifyInt:[str1 findOneOf:numberSet] :11];
824: [str1 verifyInt:[str1 findOneOf:numberSet range:wholeRange(str1) mask:NX_BACKWARDS_SEARCH table:NULL] :13];
825: }
826:
827: #ifdef TESTCONSTANTSTRING
828: void testConstant /* basic constant string functionality */ ()
829: {
830: id str1, str2, str3;
831: unichar *charPtr;
832: NXRange range = {1, 2};
833: NXRange tmpRange = {0, 0};
834:
835: TITLE1 ("NXConstantString test");
836:
837: str1 = [[NXReadOnlyString alloc] initFromString:@"ABCDE"];
838: str2 = [[NXReadOnlyString alloc] initFromString:str1];
839: str3 = [[NXReadOnlyString alloc] initFromString:str2 range:range];
840: [str3 verifyChars:"BC"];
841: [str3 free];
842: str3 = [str2 copy];
843: [str3 verifyChars:"ABCDE"];
844: [str2 free];
845: [str3 verifyChars:"ABCDE"];
846: [str3 free];
847:
848: str3 = [[NXReadOnlyString alloc] initFromString:@"FGHIJ"];
849: CHARALLOC(NXDefaultMallocZone(), charPtr, NX_LENGTH(range));
850: [str3 getCharacters:charPtr range:range];
851: str2 = [[NXReadOnlyString alloc] initFromCharacters:charPtr length:NX_LENGTH(range)];
852: [str3 verifyChars:"FGHIJ"];
853: [str2 verifyChars:"GH"];
854: [str2 free];
855: NX_FREE (charPtr);
856:
857: NX_LOCATION(tmpRange) = 1;
858: NX_LENGTH(tmpRange) = [str3 length] - 1;
859: CHARALLOC(NXDefaultMallocZone(), charPtr, NX_LENGTH(tmpRange));
860: [str3 getCharacters:charPtr range:tmpRange];
861: str2 = [[NXReadOnlyString alloc] initFromCharacters:charPtr length:NX_LENGTH(tmpRange)];
862: [str2 verifyChars:"GHIJ"];
863: [str2 free];
864: [str3 free];
865: [str1 free];
866: NX_FREE (charPtr);
867:
868: str3 = [[NXReadOnlyString alloc] initFromString:@"KLM" @"NO"];
869: str2 = [str3 copy];
870: NX_LOCATION(tmpRange) = 0;
871: NX_LENGTH(tmpRange) = [str2 length];
872: CHARALLOC(NXDefaultMallocZone(), charPtr, NX_LENGTH(tmpRange));
873: [str2 getCharacters:charPtr range:tmpRange];
874: str1 = [[NXReadOnlyString alloc] initFromCharactersNoCopy:charPtr length:NX_LENGTH(tmpRange)];
875: [str3 free];
876: [str2 verifyChars:"KLMNO"];
877: [str2 free];
878: [str1 verifyChars:"KLMNO"];
879: [str1 free];
880:
881: str1 = [[NXReadWriteString alloc] init];
882: str2 = [str1 copy];
883: [str1 appendString:@"Foo"];
884: [str1 verifyInt:[str1 isEqual:@""] :NO];
885: [str2 verifyInt:[str2 isEqual:@""] :YES];
886: [str1 free];
887: [str2 verifyInt:[str2 isEqual:@""] :YES];
888: [str2 free];
889: }
890:
891:
892: #endif
893:
894: void main (int argc, char **argv)
895: {
896: numErrors = 0;
897: verbose = (argc > 1) && (strcmp(argv[1], "-v") == 0);
898:
899: #ifdef TESTTESTEDSTUFF
900: testBasic ([NXReadOnlyString class]);
901: testBasic ([NXReadWriteString class]);
902: testBasic ([NXUniquedString class]);
903: testBasic ([NXSimpleReadOnlyString class]);
904:
905: testCopy ([NXReadOnlyString class]);
906: testCopy ([NXReadWriteString class]);
907: testCopy ([NXUniquedString class]);
908: testCopy ([NXSimpleReadOnlyString class]);
909:
910: testRefCountedAndUniqued ();
911:
912: testEdit ([NXReadWriteString class]);
913: testLargeEdit ([NXReadWriteString class]);
914:
915: testCompare ([NXReadOnlyString class]);
916: testCompare ([NXReadWriteString class]);
917: testCompare ([NXUniquedString class]);
918: testCompare ([NXSimpleReadOnlyString class]);
919:
920: testFind ([NXReadOnlyString class]);
921: testFind ([NXReadWriteString class]);
922: testFind ([NXUniquedString class]);
923: testFind ([NXSimpleReadOnlyString class]);
924:
925: testStream ([NXReadOnlyString class]);
926: testStream ([NXReadWriteString class]);
927: testStream ([NXUniquedString class]);
928: testStream ([NXSimpleReadOnlyString class]);
929:
930: testFormat ([NXReadOnlyString class]);
931: testFormat ([NXReadWriteString class]);
932: testFormat ([NXUniquedString class]);
933: testFormat ([NXSimpleReadOnlyString class]);
934:
935: testFindAndSets ([NXReadOnlyString class]);
936: testFindAndSets ([NXReadWriteString class]);
937: testFindAndSets ([NXUniquedString class]);
938: testFindAndSets ([NXSimpleReadOnlyString class]);
939:
940: testCStrings ([NXReadOnlyString class]);
941: testCStrings ([NXReadWriteString class]);
942: testCStrings ([NXUniquedString class]);
943: testCStrings ([NXSimpleReadOnlyString class]);
944:
945: testHash ([NXReadOnlyString class]);
946: testHash ([NXReadWriteString class]);
947: testHash ([NXUniquedString class]);
948: testHash ([NXSimpleReadOnlyString class]);
949: #endif
950:
951: #ifdef TESTGAPSTRING
952: testBasic ([NXGapString class]);
953: testCopy ([NXGapString class]);
954: testEdit ([NXGapString class]);
955: testCompare ([NXGapString class]);
956: testFind ([NXGapString class]);
957: testLargeEdit ([NXGapString class]);
958: testStream ([NXGapString class]);
959: testFormat ([NXGapString class]);
960: testFindAndSets ([NXGapString class]);
961: testCStrings ([NXGapString class]);
962: testHash ([NXGapString class]);
963: #endif
964:
965: #ifdef TESTBIGSTRING
966: testBasic ([NXBigString class]);
967: testCopy ([NXBigString class]);
968: testEdit ([NXBigString class]);
969: testCompare ([NXBigString class]);
970: testFind ([NXBigString class]);
971: testLargeEdit ([NXBigString class]);
972: testStream ([NXBigString class]);
973: testFormat ([NXBigString class]);
974: testFindAndSets ([NXBigString class]);
975: testCStrings ([NXBigString class]);
976: testHash ([NXBigString class]);
977: #endif
978:
979: #ifdef TESTCONSTANTSTRING
980: testConstant();
981: #endif
982:
983: fprintf (stderr, "\n%s%d error%s.\n", numErrors ? "*** " : "", numErrors, numErrors == 1 ? "" : "s");
984: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.