ObjFW  Check-in [14f1e22d79]

Overview
Comment:tests: Align more with ObjFW style

ObjFW's style changed over the years, but the tests were never adjusted
to it.

Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 14f1e22d793de670611ef0469b12438473976cd8546d2b6f07be1318f1cc5e37
User & Date: js on 2021-05-08 23:22:59
Other Links: manifest | tags
Context
2021-05-08
23:29
tests: Minor const improvement check-in: c8663697ae user: js tags: trunk
23:22
tests: Align more with ObjFW style check-in: 14f1e22d79 user: js tags: trunk
20:07
Treat EWOULDBLOCK equal to EINPROGRESS on Windows check-in: f3ca0f6a2c user: js tags: trunk
Changes

Modified tests/ForwardingTests.m from [243d088ca9] to [4df4ada152].

15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
..
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
...
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186

187
188
189
190
191
192
193

194
195
196
197
198
199
200
201
202
203

204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234

#include "config.h"

#include <string.h>

#import "TestsAppDelegate.h"

#define FMT @"%@ %@ %@ %@ %@ %@ %@ %@ %@ %g %g %g %g %g %g %g %g %g"
#define ARGS @"a", @"b", @"c", @"d", @"e", @"f", @"g", @"h", @"i", \
	    1.5, 2.25, 3.125, 4.0625, 5.03125, 6.5, 7.25, 8.0, 9.0
#define RESULT @"a b c d e f g h i 1.5 2.25 3.125 4.0625 5.03125 6.5 7.25 8 9"

static OFString *module = @"Forwarding";
static size_t forwardings = 0;
static bool success = false;
static id target = nil;

struct stret_test {
	char s[1024];
};

@interface ForwardingTest: OFObject
@end

@interface ForwardingTest (Test)
+ (void)test;
- (void)test;
- (uint32_t)forwardingTargetTest: (intptr_t)a0
				: (intptr_t)a1
				: (double)a2
				: (double)a3;
- (OFString *)forwardingTargetVarArgTest: (OFConstantString *)fmt, ...;
- (long double)forwardingTargetFPRetTest;
- (struct stret_test)forwardingTargetStRetTest;
- (void)forwardingTargetNilTest;
- (void)forwardingTargetSelfTest;
- (struct stret_test)forwardingTargetNilStRetTest;
- (struct stret_test)forwardingTargetSelfStRetTest;
@end

@interface ForwardingTarget: OFObject
@end

static void
test(id self, SEL _cmd)
................................................................................
{
	success = true;
}

@implementation ForwardingTest
+ (bool)resolveClassMethod: (SEL)selector
{
	forwardings++;

	if (sel_isEqual(selector, @selector(test))) {
		class_replaceMethod(object_getClass(self), @selector(test),
		    (IMP)test, "v#:");
		return YES;
	}

	return NO;
}

+ (bool)resolveInstanceMethod: (SEL)selector
{
	forwardings++;

	if (sel_isEqual(selector, @selector(test))) {
		class_replaceMethod(self, @selector(test), (IMP)test, "v@:");
		return YES;
	}

	return NO;
................................................................................
		return 0;
	if (a3 != 2.75)
		return 0;

	return 0x12345678;
}

- (OFString *)forwardingTargetVarArgTest: (OFConstantString *)fmt, ...
{
	va_list args;
	OFString *ret;

	OFEnsure(self == target);

	va_start(args, fmt);
	ret = [[[OFString alloc] initWithFormat: fmt
				      arguments: args] autorelease];
	va_end(args);

	return ret;
}

- (long double)forwardingTargetFPRetTest
{
	OFEnsure(self == target);

	return 12345678.00006103515625;
}

- (struct stret_test)forwardingTargetStRetTest
{
	struct stret_test ret = { { 0 } };

	OFEnsure(self == target);

	memcpy(ret.s, "abcdefghijklmnopqrstuvwxyz", 27);

	return ret;
}
@end

@implementation TestsAppDelegate (ForwardingTests)
- (void)forwardingTests
{
	void *pool = objc_autoreleasePoolPush();

	TEST(@"Forwarding a message and adding a class method",
	    R([ForwardingTest test]) && success &&
	    R([ForwardingTest test]) && forwardings == 1);


	ForwardingTest *t = [[[ForwardingTest alloc] init] autorelease];

	success = false;
	forwardings = 0;

	TEST(@"Forwarding a message and adding an instance method",
	    R([t test]) && success && R([t test]) && forwardings == 1);


#ifdef OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR
	target = [[[ForwardingTarget alloc] init] autorelease];
	TEST(@"-[forwardingTargetForSelector:]",
	    [t forwardingTargetTest: 0xDEADBEEF
				   : -1
				   : 1.25
				   : 2.75] == 0x12345678)
	TEST(@"-[forwardingTargetForSelector:] variable arguments",
	    [[t forwardingTargetVarArgTest: FMT, ARGS] isEqual: RESULT])

	/*
	 * Don't try fpret on Win64 if we don't have stret forwarding, as
	 * long double is handled as a struct there.
	 */
# if !defined(OF_WINDOWS) || !defined(OF_X86_64) || \
	defined(OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR_STRET)
	TEST(@"-[forwardingTargetForSelector:] fp return",
	    [t forwardingTargetFPRetTest] == 12345678.00006103515625)
# endif
# ifdef OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR_STRET
	TEST(@"-[forwardingTargetForSelector:] struct return",
	    !memcmp([t forwardingTargetStRetTest].s,
	    "abcdefghijklmnopqrstuvwxyz", 27))
# endif
	EXPECT_EXCEPTION(@"-[forwardingTargetForSelector:] nil target",
	    OFNotImplementedException, [t forwardingTargetNilTest])
	EXPECT_EXCEPTION(@"-[forwardingTargetForSelector:] self target",
	    OFNotImplementedException, [t forwardingTargetSelfTest])
# ifdef OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR_STRET
	EXPECT_EXCEPTION(@"-[forwardingTargetForSelector:] nil target + "
	    @"stret", OFNotImplementedException,
	    [t forwardingTargetNilStRetTest])
	EXPECT_EXCEPTION(@"-[forwardingTargetForSelector:] self target + "
	    @"stret", OFNotImplementedException,
	    [t forwardingTargetSelfStRetTest])
# endif
#endif

	objc_autoreleasePoolPop(pool);
}
@end







|




|
|



|
|












|

|


|
|







 







|












|







 







|






|
|













|

|



|












|

>
|


|


|
>




|
|
|
|

|
>







|



|



|

|



|


|






15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
..
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
...
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237

#include "config.h"

#include <string.h>

#import "TestsAppDelegate.h"

#define FORMAT @"%@ %@ %@ %@ %@ %@ %@ %@ %@ %g %g %g %g %g %g %g %g %g"
#define ARGS @"a", @"b", @"c", @"d", @"e", @"f", @"g", @"h", @"i", \
	    1.5, 2.25, 3.125, 4.0625, 5.03125, 6.5, 7.25, 8.0, 9.0
#define RESULT @"a b c d e f g h i 1.5 2.25 3.125 4.0625 5.03125 6.5 7.25 8 9"

static OFString *const module = @"Forwarding";
static size_t forwardingsCount = 0;
static bool success = false;
static id target = nil;

struct StretTest {
	char buffer[1024];
};

@interface ForwardingTest: OFObject
@end

@interface ForwardingTest (Test)
+ (void)test;
- (void)test;
- (uint32_t)forwardingTargetTest: (intptr_t)a0
				: (intptr_t)a1
				: (double)a2
				: (double)a3;
- (OFString *)forwardingTargetVarArgTest: (OFConstantString *)format, ...;
- (long double)forwardingTargetFPRetTest;
- (struct StretTest)forwardingTargetStRetTest;
- (void)forwardingTargetNilTest;
- (void)forwardingTargetSelfTest;
- (struct StretTest)forwardingTargetNilStRetTest;
- (struct StretTest)forwardingTargetSelfStRetTest;
@end

@interface ForwardingTarget: OFObject
@end

static void
test(id self, SEL _cmd)
................................................................................
{
	success = true;
}

@implementation ForwardingTest
+ (bool)resolveClassMethod: (SEL)selector
{
	forwardingsCount++;

	if (sel_isEqual(selector, @selector(test))) {
		class_replaceMethod(object_getClass(self), @selector(test),
		    (IMP)test, "v#:");
		return YES;
	}

	return NO;
}

+ (bool)resolveInstanceMethod: (SEL)selector
{
	forwardingsCount++;

	if (sel_isEqual(selector, @selector(test))) {
		class_replaceMethod(self, @selector(test), (IMP)test, "v@:");
		return YES;
	}

	return NO;
................................................................................
		return 0;
	if (a3 != 2.75)
		return 0;

	return 0x12345678;
}

- (OFString *)forwardingTargetVarArgTest: (OFConstantString *)format, ...
{
	va_list args;
	OFString *ret;

	OFEnsure(self == target);

	va_start(args, format);
	ret = [[[OFString alloc] initWithFormat: format
				      arguments: args] autorelease];
	va_end(args);

	return ret;
}

- (long double)forwardingTargetFPRetTest
{
	OFEnsure(self == target);

	return 12345678.00006103515625;
}

- (struct StretTest)forwardingTargetStRetTest
{
	struct StretTest ret = { { 0 } };

	OFEnsure(self == target);

	memcpy(ret.buffer, "abcdefghijklmnopqrstuvwxyz", 27);

	return ret;
}
@end

@implementation TestsAppDelegate (ForwardingTests)
- (void)forwardingTests
{
	void *pool = objc_autoreleasePoolPush();

	TEST(@"Forwarding a message and adding a class method",
	    R([ForwardingTest test]) && success &&
	    R([ForwardingTest test]) && forwardingsCount == 1);

	ForwardingTest *testObject =
	    [[[ForwardingTest alloc] init] autorelease];

	success = false;
	forwardingsCount = 0;

	TEST(@"Forwarding a message and adding an instance method",
	    R([testObject test]) && success && R([testObject test]) &&
	    forwardingsCount == 1);

#ifdef OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR
	target = [[[ForwardingTarget alloc] init] autorelease];
	TEST(@"-[forwardingTargetForSelector:]",
	    [testObject forwardingTargetTest: 0xDEADBEEF
					    : -1
					    : 1.25
					    : 2.75] == 0x12345678)
	TEST(@"-[forwardingTargetForSelector:] variable arguments",
	    [[testObject forwardingTargetVarArgTest: FORMAT, ARGS]
	    isEqual: RESULT])
	/*
	 * Don't try fpret on Win64 if we don't have stret forwarding, as
	 * long double is handled as a struct there.
	 */
# if !defined(OF_WINDOWS) || !defined(OF_X86_64) || \
	defined(OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR_STRET)
	TEST(@"-[forwardingTargetForSelector:] fp return",
	    [testObject forwardingTargetFPRetTest] == 12345678.00006103515625)
# endif
# ifdef OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR_STRET
	TEST(@"-[forwardingTargetForSelector:] struct return",
	    !memcmp([testObject forwardingTargetStRetTest].buffer,
	    "abcdefghijklmnopqrstuvwxyz", 27))
# endif
	EXPECT_EXCEPTION(@"-[forwardingTargetForSelector:] nil target",
	    OFNotImplementedException, [testObject forwardingTargetNilTest])
	EXPECT_EXCEPTION(@"-[forwardingTargetForSelector:] self target",
	    OFNotImplementedException, [testObject forwardingTargetSelfTest])
# ifdef OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR_STRET
	EXPECT_EXCEPTION(@"-[forwardingTargetForSelector:] nil target + "
	    @"stret", OFNotImplementedException,
	    [testObject forwardingTargetNilStRetTest])
	EXPECT_EXCEPTION(@"-[forwardingTargetForSelector:] self target + "
	    @"stret", OFNotImplementedException,
	    [testObject forwardingTargetSelfStRetTest])
# endif
#endif

	objc_autoreleasePoolPop(pool);
}
@end

Modified tests/Makefile from [829b5974ca] to [c2c3a7e8c9].

20
21
22
23
24
25
26

27

28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
..
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
       OFInvocationTests.m		\
       OFJSONTests.m			\
       OFListTests.m			\
       OFLocaleTests.m			\
       OFMethodSignatureTests.m		\
       OFNumberTests.m			\
       OFObjectTests.m			\

       OFPropertyListTests.m		\

       OFSetTests.m			\
       OFStreamTests.m			\
       OFStringTests.m			\
       OFSystemInfoTests.m		\
       OFURLTests.m			\
       OFValueTests.m			\
       OFXMLElementBuilderTests.m	\
       OFXMLNodeTests.m			\
       OFXMLParserTests.m		\
       PBKDF2Tests.m			\
       RuntimeTests.m			\
       ${RUNTIME_ARC_TESTS_M}		\
       ScryptTests.m			\
       TestsAppDelegate.m		\
       ${USE_SRCS_FILES}		\
       ${USE_SRCS_PLUGINS}		\
       ${USE_SRCS_SOCKETS}		\
       ${USE_SRCS_THREADS}		\
       ${USE_SRCS_WINDOWS}
SRCS_FILES = OFHMACTests.m		\
................................................................................
	   OFSPXStreamSocketTests.m
SRCS_PLUGINS = OFPluginTests.m
SRCS_SOCKETS = OFDNSResolverTests.m		\
	       ${OF_HTTP_CLIENT_TESTS_M}	\
	       OFHTTPCookieTests.m		\
	       OFHTTPCookieManagerTests.m	\
	       OFKernelEventObserverTests.m	\
	       OFTCPSocketTests.m		\
	       OFUDPSocketTests.m		\
	       SocketTests.m			\
	       ${USE_SRCS_IPX}
SRCS_THREADS = OFThreadTests.m
SRCS_WINDOWS = OFWindowsRegistryKeyTests.m

IOS_USER ?= mobile
IOS_TMP ?= /tmp/objfw-test








>

>









<


<







 







|
|
|







20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

39
40

41
42
43
44
45
46
47
..
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
       OFInvocationTests.m		\
       OFJSONTests.m			\
       OFListTests.m			\
       OFLocaleTests.m			\
       OFMethodSignatureTests.m		\
       OFNumberTests.m			\
       OFObjectTests.m			\
       OFPBKDF2Tests.m			\
       OFPropertyListTests.m		\
       OFScryptTests.m			\
       OFSetTests.m			\
       OFStreamTests.m			\
       OFStringTests.m			\
       OFSystemInfoTests.m		\
       OFURLTests.m			\
       OFValueTests.m			\
       OFXMLElementBuilderTests.m	\
       OFXMLNodeTests.m			\
       OFXMLParserTests.m		\

       RuntimeTests.m			\
       ${RUNTIME_ARC_TESTS_M}		\

       TestsAppDelegate.m		\
       ${USE_SRCS_FILES}		\
       ${USE_SRCS_PLUGINS}		\
       ${USE_SRCS_SOCKETS}		\
       ${USE_SRCS_THREADS}		\
       ${USE_SRCS_WINDOWS}
SRCS_FILES = OFHMACTests.m		\
................................................................................
	   OFSPXStreamSocketTests.m
SRCS_PLUGINS = OFPluginTests.m
SRCS_SOCKETS = OFDNSResolverTests.m		\
	       ${OF_HTTP_CLIENT_TESTS_M}	\
	       OFHTTPCookieTests.m		\
	       OFHTTPCookieManagerTests.m	\
	       OFKernelEventObserverTests.m	\
	       OFSocketTests.m			\
	       OFTCPSocketTests.m		\
	       OFUDPSocketTests.m		\
	       ${USE_SRCS_IPX}
SRCS_THREADS = OFThreadTests.m
SRCS_WINDOWS = OFWindowsRegistryKeyTests.m

IOS_USER ?= mobile
IOS_TMP ?= /tmp/objfw-test

Modified tests/OFArrayTests.m from [f58673a4b1] to [a384e7dc9e].

14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
...
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139

140
141
142
143
144
145
146
147
148
149

150
151
152
153

154
155

156
157

158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189

190
191
192
193
194
195

196
197
198
199
200
201
202
203
204
205
206
207


208
209
210

211
212
213


214
215
216
217
218

219
220
221
222
223
224

225
226
227
228
229
230
231

232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271

272
273
274

275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339

340
341
342
343
344
345
346
347
348
349
350

351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370

371
372
373
374
375
376
377
378
379
380
381
382

383
384
385
386
387
388
389
390
391
392
393
394

395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
 */

#include "config.h"

#import "TestsAppDelegate.h"

static OFString *module = nil;
static OFString *c_ary[] = {
	@"Foo",
	@"Bar",
	@"Baz"
};

@interface SimpleArray: OFArray
{
................................................................................
@end

@implementation TestsAppDelegate (OFArrayTests)
- (void)arrayTestsWithClass: (Class)arrayClass
	       mutableClass: (Class)mutableArrayClass
{
	void *pool = objc_autoreleasePoolPush();
	OFArray *a[3];
	OFMutableArray *m[2];
	OFEnumerator *enumerator;
	id obj;
	bool ok;
	size_t i;

	TEST(@"+[array]", (m[0] = [mutableArrayClass array]))

	TEST(@"+[arrayWithObjects:]",

	    (a[0] = [arrayClass arrayWithObjects: @"Foo", @"Bar", @"Baz", nil]))

	TEST(@"+[arrayWithObjects:count:]",
	    (a[1] = [arrayClass arrayWithObjects: c_ary count: 3]) &&
	    [a[1] isEqual: a[0]])

	TEST(@"-[description]",
	    [a[0].description isEqual: @"(\n\tFoo,\n\tBar,\n\tBaz\n)"])

	TEST(@"-[addObject:]", R([m[0] addObject: c_ary[0]]) &&

	    R([m[0] addObject: c_ary[2]]))

	TEST(@"-[insertObject:atIndex:]",
	    R([m[0] insertObject: c_ary[1] atIndex: 1]))


	TEST(@"-[count]", m[0].count == 3 && a[0].count == 3 && a[1].count == 3)


	TEST(@"-[isEqual:]", [m[0] isEqual: a[0]] && [a[0] isEqual: a[1]])


	TEST(@"-[objectAtIndex:]",
	    [[m[0] objectAtIndex: 0] isEqual: c_ary[0]] &&
	    [[m[0] objectAtIndex: 1] isEqual: c_ary[1]] &&
	    [[m[0] objectAtIndex: 2] isEqual: c_ary[2]] &&
	    [[a[0] objectAtIndex: 0] isEqual: c_ary[0]] &&
	    [[a[0] objectAtIndex: 1] isEqual: c_ary[1]] &&
	    [[a[0] objectAtIndex: 2] isEqual: c_ary[2]] &&
	    [[a[1] objectAtIndex: 0] isEqual: c_ary[0]] &&
	    [[a[1] objectAtIndex: 1] isEqual: c_ary[1]] &&
	    [[a[1] objectAtIndex: 2] isEqual: c_ary[2]])

	TEST(@"-[containsObject:]",
	    [a[0] containsObject: c_ary[1]] &&
	    ![a[0] containsObject: @"nonexistent"])

	TEST(@"-[containsObjectIdenticalTo:]",
	    [a[0] containsObjectIdenticalTo: c_ary[1]] &&
	    ![a[0] containsObjectIdenticalTo:
	    [OFString stringWithString: c_ary[1]]])

	TEST(@"-[indexOfObject:]", [a[0] indexOfObject: c_ary[1]] == 1)

	TEST(@"-[indexOfObjectIdenticalTo:]",
	    [a[1] indexOfObjectIdenticalTo: c_ary[1]] == 1)

	TEST(@"-[objectsInRange:]",
	    [[a[0] objectsInRange: OFRangeMake(1, 2)] isEqual:
	    [arrayClass arrayWithObjects: c_ary[1], c_ary[2], nil]])

	TEST(@"-[replaceObject:withObject:]",
	    R([m[0] replaceObject: c_ary[1] withObject: c_ary[0]]) &&

	    [[m[0] objectAtIndex: 0] isEqual: c_ary[0]] &&
	    [[m[0] objectAtIndex: 1] isEqual: c_ary[0]] &&
	    [[m[0] objectAtIndex: 2] isEqual: c_ary[2]])

	TEST(@"-[replaceObject:identicalTo:]",
	    R([m[0] replaceObjectIdenticalTo: c_ary[0] withObject: c_ary[1]]) &&

	    [[m[0] objectAtIndex: 0] isEqual: c_ary[1]] &&
	    [[m[0] objectAtIndex: 1] isEqual: c_ary[0]] &&
	    [[m[0] objectAtIndex: 2] isEqual: c_ary[2]])

	TEST(@"-[replaceObjectAtIndex:withObject:]",
	    R([m[0] replaceObjectAtIndex: 0 withObject: c_ary[0]]) &&
	    [[m[0] objectAtIndex: 0] isEqual: c_ary[0]] &&
	    [[m[0] objectAtIndex: 1] isEqual: c_ary[0]] &&
	    [[m[0] objectAtIndex: 2] isEqual: c_ary[2]])

	TEST(@"-[removeObject:]",
	    R([m[0] removeObject: c_ary[0]]) && m[0].count == 2)



	TEST(@"-[removeObjectIdenticalTo:]",
	    R([m[0] removeObjectIdenticalTo: c_ary[2]]) && m[0].count == 1)


	m[1] = [[a[0] mutableCopy] autorelease];
	TEST(@"-[removeObjectAtIndex:]", R([m[1] removeObjectAtIndex: 1]) &&


	    m[1].count == 2 && [[m[1] objectAtIndex: 1] isEqual: c_ary[2]])

	m[1] = [[a[0] mutableCopy] autorelease];
	TEST(@"-[removeObjectsInRange:]",
	    R([m[1] removeObjectsInRange: OFRangeMake(0, 2)]) &&

	    m[1].count == 1 && [[m[1] objectAtIndex: 0] isEqual: c_ary[2]])

	m[1] = [[a[0] mutableCopy] autorelease];
	[m[1] addObject: @"qux"];
	[m[1] addObject: @"last"];
	TEST(@"-[reverse]",

	    R([m[1] reverse]) && [m[1] isEqual: [arrayClass arrayWithObjects:
	    @"last", @"qux", @"Baz", @"Bar", @"Foo", nil]])

	m[1] = [[a[0] mutableCopy] autorelease];
	[m[1] addObject: @"qux"];
	[m[1] addObject: @"last"];
	TEST(@"-[reversedArray]",

	    [[m[1] reversedArray] isEqual: [arrayClass arrayWithObjects:
	    @"last", @"qux", @"Baz", @"Bar", @"Foo", nil]])

	m[1] = [[a[0] mutableCopy] autorelease];
	[m[1] addObject: @"0"];
	[m[1] addObject: @"z"];
	TEST(@"-[sortedArray]",
	    [[m[1] sortedArray] isEqual: [arrayClass arrayWithObjects:
	    @"0", @"Bar", @"Baz", @"Foo", @"z", nil]] &&
	    [[m[1] sortedArrayUsingSelector: @selector(compare:)
				    options: OFArraySortDescending]
	    isEqual: [arrayClass arrayWithObjects:
	    @"z", @"Foo", @"Baz", @"Bar", @"0", nil]])

	EXPECT_EXCEPTION(@"Detect out of range in -[objectAtIndex:]",
	    OFOutOfRangeException, [a[0] objectAtIndex: a[0].count])

	EXPECT_EXCEPTION(@"Detect out of range in -[removeObjectsInRange:]",
	    OFOutOfRangeException, [m[0] removeObjectsInRange:
		OFRangeMake(0, m[0].count + 1)])

	TEST(@"-[componentsJoinedByString:]",
	    (a[1] = [arrayClass arrayWithObjects: @"", @"a", @"b", @"c",
	    nil]) &&
	    [[a[1] componentsJoinedByString: @" "] isEqual: @" a b c"] &&
	    (a[1] = [arrayClass arrayWithObject: @"foo"]) &&
	    [[a[1] componentsJoinedByString: @" "] isEqual: @"foo"])

	TEST(@"-[componentsJoinedByString:options]",
	    (a[1] = [arrayClass arrayWithObjects: @"", @"foo", @"", @"", @"bar",
	    @"", nil]) &&
	    [[a[1] componentsJoinedByString: @" "
				    options: OFArraySkipEmptyComponents]
	    isEqual: @"foo bar"])

	m[0] = [[a[0] mutableCopy] autorelease];
	ok = true;
	i = 0;

	TEST(@"-[objectEnumerator]", (enumerator = [m[0] objectEnumerator]))


	while ((obj = [enumerator nextObject]) != nil) {
		if (![obj isEqual: c_ary[i]])

			ok = false;
		[m[0] replaceObjectAtIndex: i withObject: @""];
		i++;
	}

	if (m[0].count != i)
		ok = false;

	TEST(@"OFEnumerator's -[nextObject]", ok)

	[m[0] removeObjectAtIndex: 0];

	EXPECT_EXCEPTION(@"Detection of mutation during enumeration",
	    OFEnumerationMutationException, [enumerator nextObject])

	m[0] = [[a[0] mutableCopy] autorelease];
	ok = true;
	i = 0;

	for (OFString *s in m[0]) {
		if (![s isEqual: c_ary[i]])
			ok = false;
		[m[0] replaceObjectAtIndex: i withObject: @""];
		i++;
	}

	if (m[0].count != i)
		ok = false;

	TEST(@"Fast Enumeration", ok)

	[m[0] replaceObjectAtIndex: 0 withObject: c_ary[0]];
	[m[0] replaceObjectAtIndex: 1 withObject: c_ary[1]];
	[m[0] replaceObjectAtIndex: 2 withObject: c_ary[2]];

	ok = false;
	i = 0;
	@try {
		for (OFString *s in m[0]) {
			(void)s;

			if (i == 0)
				[m[0] addObject: @""];

			i++;
		}
	} @catch (OFEnumerationMutationException *e) {
		ok = true;
	}

	TEST(@"Detection of mutation during Fast Enumeration", ok)

	[m[0] removeLastObject];

#ifdef OF_HAVE_BLOCKS
	{
		__block bool blockOk = true;
		__block size_t count = 0;
		OFArray *cmp = a[0];
		OFMutableArray *a2;

		m[0] = [[a[0] mutableCopy] autorelease];
		[m[0] enumerateObjectsUsingBlock:
		    ^ (id object, size_t idx, bool *stop) {
			    count++;

			    if (![object isEqual: [cmp objectAtIndex: idx]])
				    blockOk = false;
		}];

		if (count != cmp.count)
			blockOk = false;

		TEST(@"Enumeration using blocks", blockOk)

		blockOk = false;
		a2 = m[0];

		@try {
			[a2 enumerateObjectsUsingBlock:
			    ^ (id object, size_t idx, bool *stop) {
				[a2 removeObjectAtIndex: idx];
			}];
		} @catch (OFEnumerationMutationException *e) {
			blockOk = true;
		} @catch (OFOutOfRangeException *e) {
			/*
			 * Out of bounds access due to enumeration not being
			 * detected.
			 */
		}

		TEST(@"Detection of mutation during enumeration using blocks",
		    blockOk)
	}

	TEST(@"-[replaceObjectsUsingBlock:]",
	    R([m[0] replaceObjectsUsingBlock: ^ id (id object, size_t idx) {

		switch (idx) {
		case 0:
			return @"foo";
		case 1:
			return @"bar";
		}

		return nil;
	    }]) && [m[0].description isEqual: @"(\n\tfoo,\n\tbar\n)"])

	TEST(@"-[mappedArrayUsingBlock:]",
	    [[m[0] mappedArrayUsingBlock: ^ id (id object, size_t idx) {

		switch (idx) {
		case 0:
			return @"foobar";
		case 1:
			return @"qux";
		}

		return nil;
	    }].description isEqual: @"(\n\tfoobar,\n\tqux\n)"])

	TEST(@"-[filteredArrayUsingBlock:]",
	    [[m[0] filteredArrayUsingBlock: ^ bool (id object, size_t idx) {

		return [object isEqual: @"foo"];
	    }].description isEqual: @"(\n\tfoo\n)"])

	TEST(@"-[foldUsingBlock:]",
	    [[arrayClass arrayWithObjects: [OFMutableString string], @"foo",
	    @"bar", @"baz", nil] foldUsingBlock: ^ id (id left, id right) {
		[left appendString: right];
		return left;
	    }])
#endif

	TEST(@"-[valueForKey:]",
	    [[[arrayClass arrayWithObjects: @"foo", @"bar", @"quxqux", nil]
	    valueForKey: @"length"] isEqual:
	    [arrayClass arrayWithObjects: [OFNumber numberWithInt: 3],
	    [OFNumber numberWithInt: 3], [OFNumber numberWithInt: 6], nil]] &&
	    [[[arrayClass arrayWithObjects: @"1", @"2", nil]
	    valueForKey: @"@count"] isEqual: [OFNumber numberWithInt: 2]])

	m[0] = [mutableArrayClass arrayWithObjects:
	    [OFMutableURL URLWithString: @"http://foo.bar/"],
	    [OFMutableURL URLWithString: @"http://bar.qux/"],
	    [OFMutableURL URLWithString: @"http://qux.quxqux/"], nil];
	TEST(@"-[setValue:forKey:]",
	    R([m[0] setValue: [OFNumber numberWithShort: 1234]
		      forKey: @"port"]) &&
	    [m[0] isEqual: [arrayClass arrayWithObjects:
	    [OFURL URLWithString: @"http://foo.bar:1234/"],
	    [OFURL URLWithString: @"http://bar.qux:1234/"],
	    [OFURL URLWithString: @"http://qux.quxqux:1234/"], nil]])

	objc_autoreleasePoolPop(pool);
}








|







 







|
|

|



|


>
|


|
|


|

|
>
|


<
>

|
>

|
>


|
|
|
|
|
|
|
|
|


|
|


|
|
|

|


|


|
|


<
>
|
|
|


|
>
|
|
|


|
|
|
|


<
>
>


|
>

|
|
>
>
|

|

|
>
|

|
|
|

>
|


|
|
|

>
|


|
|
|

|

|
|




|


|
|


|

|
|
|


|
|
|
|


|



|
>

|
<
>

|



|




|




|



|
|

|



|




|
|
|




|
|


|









|



|

|
|

|
|
|
|
>
|
|


|
|

|

|
<
>

|
|
|


|








|



|
>
|
|
|
|
|
|

|
|


|
>
|
|
|
|
|
|

|



|
>
|





|
|











|




|
|
|







14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
...
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154

155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192

193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211

212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286

287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363

364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
 */

#include "config.h"

#import "TestsAppDelegate.h"

static OFString *module = nil;
static OFString *const cArray[] = {
	@"Foo",
	@"Bar",
	@"Baz"
};

@interface SimpleArray: OFArray
{
................................................................................
@end

@implementation TestsAppDelegate (OFArrayTests)
- (void)arrayTestsWithClass: (Class)arrayClass
	       mutableClass: (Class)mutableArrayClass
{
	void *pool = objc_autoreleasePoolPush();
	OFArray *array1, *array2;
	OFMutableArray *mutableArray1, *mutableArray2;
	OFEnumerator *enumerator;
	id object;
	bool ok;
	size_t i;

	TEST(@"+[array]", (mutableArray1 = [mutableArrayClass array]))

	TEST(@"+[arrayWithObjects:]",
	    (array1 =
	    [arrayClass arrayWithObjects: @"Foo", @"Bar", @"Baz", nil]))

	TEST(@"+[arrayWithObjects:count:]",
	    (array2 = [arrayClass arrayWithObjects: cArray count: 3]) &&
	    [array2 isEqual: array1])

	TEST(@"-[description]",
	    [array1.description isEqual: @"(\n\tFoo,\n\tBar,\n\tBaz\n)"])

	TEST(@"-[addObject:]",
	    R([mutableArray1 addObject: cArray[0]]) &&
	    R([mutableArray1 addObject: cArray[2]]))

	TEST(@"-[insertObject:atIndex:]",

	    R([mutableArray1 insertObject: cArray[1] atIndex: 1]))

	TEST(@"-[count]",
	    mutableArray1.count == 3 && array1.count == 3 && array2.count == 3)

	TEST(@"-[isEqual:]",
	    [mutableArray1 isEqual: array1] && [array1 isEqual: array2])

	TEST(@"-[objectAtIndex:]",
	    [[mutableArray1 objectAtIndex: 0] isEqual: cArray[0]] &&
	    [[mutableArray1 objectAtIndex: 1] isEqual: cArray[1]] &&
	    [[mutableArray1 objectAtIndex: 2] isEqual: cArray[2]] &&
	    [[array1 objectAtIndex: 0] isEqual: cArray[0]] &&
	    [[array1 objectAtIndex: 1] isEqual: cArray[1]] &&
	    [[array1 objectAtIndex: 2] isEqual: cArray[2]] &&
	    [[array2 objectAtIndex: 0] isEqual: cArray[0]] &&
	    [[array2 objectAtIndex: 1] isEqual: cArray[1]] &&
	    [[array2 objectAtIndex: 2] isEqual: cArray[2]])

	TEST(@"-[containsObject:]",
	    [array1 containsObject: cArray[1]] &&
	    ![array1 containsObject: @"nonexistent"])

	TEST(@"-[containsObjectIdenticalTo:]",
	    [array1 containsObjectIdenticalTo: cArray[1]] &&
	    ![array1 containsObjectIdenticalTo:
	    [OFString stringWithString: cArray[1]]])

	TEST(@"-[indexOfObject:]", [array1 indexOfObject: cArray[1]] == 1)

	TEST(@"-[indexOfObjectIdenticalTo:]",
	    [array2 indexOfObjectIdenticalTo: cArray[1]] == 1)

	TEST(@"-[objectsInRange:]",
	    [[array1 objectsInRange: OFRangeMake(1, 2)] isEqual:
	    [arrayClass arrayWithObjects: cArray[1], cArray[2], nil]])

	TEST(@"-[replaceObject:withObject:]",

	    R([mutableArray1 replaceObject: cArray[1] withObject: cArray[0]]) &&
	    [[mutableArray1 objectAtIndex: 0] isEqual: cArray[0]] &&
	    [[mutableArray1 objectAtIndex: 1] isEqual: cArray[0]] &&
	    [[mutableArray1 objectAtIndex: 2] isEqual: cArray[2]])

	TEST(@"-[replaceObject:identicalTo:]",
	    R([mutableArray1 replaceObjectIdenticalTo: cArray[0]
					   withObject: cArray[1]]) &&
	    [[mutableArray1 objectAtIndex: 0] isEqual: cArray[1]] &&
	    [[mutableArray1 objectAtIndex: 1] isEqual: cArray[0]] &&
	    [[mutableArray1 objectAtIndex: 2] isEqual: cArray[2]])

	TEST(@"-[replaceObjectAtIndex:withObject:]",
	    R([mutableArray1 replaceObjectAtIndex: 0 withObject: cArray[0]]) &&
	    [[mutableArray1 objectAtIndex: 0] isEqual: cArray[0]] &&
	    [[mutableArray1 objectAtIndex: 1] isEqual: cArray[0]] &&
	    [[mutableArray1 objectAtIndex: 2] isEqual: cArray[2]])

	TEST(@"-[removeObject:]",

	    R([mutableArray1 removeObject: cArray[0]]) &&
	    mutableArray1.count == 2)

	TEST(@"-[removeObjectIdenticalTo:]",
	    R([mutableArray1 removeObjectIdenticalTo: cArray[2]]) &&
	    mutableArray1.count == 1)

	mutableArray2 = [[array1 mutableCopy] autorelease];
	TEST(@"-[removeObjectAtIndex:]",
	    R([mutableArray2 removeObjectAtIndex: 1]) &&
	    mutableArray2.count == 2 &&
	    [[mutableArray2 objectAtIndex: 1] isEqual: cArray[2]])

	mutableArray2 = [[array1 mutableCopy] autorelease];
	TEST(@"-[removeObjectsInRange:]",
	    R([mutableArray2 removeObjectsInRange: OFRangeMake(0, 2)]) &&
	    mutableArray2.count == 1 &&
	    [[mutableArray2 objectAtIndex: 0] isEqual: cArray[2]])

	mutableArray2 = [[array1 mutableCopy] autorelease];
	[mutableArray2 addObject: @"qux"];
	[mutableArray2 addObject: @"last"];
	TEST(@"-[reverse]",
	    R([mutableArray2 reverse]) &&
	    [mutableArray2 isEqual: [arrayClass arrayWithObjects:
	    @"last", @"qux", @"Baz", @"Bar", @"Foo", nil]])

	mutableArray2 = [[array1 mutableCopy] autorelease];
	[mutableArray2 addObject: @"qux"];
	[mutableArray2 addObject: @"last"];
	TEST(@"-[reversedArray]",
	    [[mutableArray2 reversedArray] isEqual:
	    [arrayClass arrayWithObjects:
	    @"last", @"qux", @"Baz", @"Bar", @"Foo", nil]])

	mutableArray2 = [[array1 mutableCopy] autorelease];
	[mutableArray2 addObject: @"0"];
	[mutableArray2 addObject: @"z"];
	TEST(@"-[sortedArray]",
	    [[mutableArray2 sortedArray] isEqual: [arrayClass arrayWithObjects:
	    @"0", @"Bar", @"Baz", @"Foo", @"z", nil]] &&
	    [[mutableArray2 sortedArrayUsingSelector: @selector(compare:)
					     options: OFArraySortDescending]
	    isEqual: [arrayClass arrayWithObjects:
	    @"z", @"Foo", @"Baz", @"Bar", @"0", nil]])

	EXPECT_EXCEPTION(@"Detect out of range in -[objectAtIndex:]",
	    OFOutOfRangeException, [array1 objectAtIndex: array1.count])

	EXPECT_EXCEPTION(@"Detect out of range in -[removeObjectsInRange:]",
	    OFOutOfRangeException, [mutableArray1 removeObjectsInRange:
		OFRangeMake(0, mutableArray1.count + 1)])

	TEST(@"-[componentsJoinedByString:]",
	    (array2 = [arrayClass arrayWithObjects: @"", @"a", @"b", @"c",
	    nil]) &&
	    [[array2 componentsJoinedByString: @" "] isEqual: @" a b c"] &&
	    (array2 = [arrayClass arrayWithObject: @"foo"]) &&
	    [[array2 componentsJoinedByString: @" "] isEqual: @"foo"])

	TEST(@"-[componentsJoinedByString:options]",
	    (array2 = [arrayClass arrayWithObjects: @"", @"foo", @"", @"",
	    @"bar", @"", nil]) &&
	    [[array2 componentsJoinedByString: @" "
				      options: OFArraySkipEmptyComponents]
	    isEqual: @"foo bar"])

	mutableArray1 = [[array1 mutableCopy] autorelease];
	ok = true;
	i = 0;

	TEST(@"-[objectEnumerator]",
	    (enumerator = [mutableArray1 objectEnumerator]))

	while ((object = [enumerator nextObject]) != nil) {

		if (![object isEqual: cArray[i]])
			ok = false;
		[mutableArray1 replaceObjectAtIndex: i withObject: @""];
		i++;
	}

	if (mutableArray1.count != i)
		ok = false;

	TEST(@"OFEnumerator's -[nextObject]", ok)

	[mutableArray1 removeObjectAtIndex: 0];

	EXPECT_EXCEPTION(@"Detection of mutation during enumeration",
	    OFEnumerationMutationException, [enumerator nextObject])

	mutableArray1 = [[array1 mutableCopy] autorelease];
	ok = true;
	i = 0;

	for (OFString *string in mutableArray1) {
		if (![string isEqual: cArray[i]])
			ok = false;
		[mutableArray1 replaceObjectAtIndex: i withObject: @""];
		i++;
	}

	if (mutableArray1.count != i)
		ok = false;

	TEST(@"Fast Enumeration", ok)

	[mutableArray1 replaceObjectAtIndex: 0 withObject: cArray[0]];
	[mutableArray1 replaceObjectAtIndex: 1 withObject: cArray[1]];
	[mutableArray1 replaceObjectAtIndex: 2 withObject: cArray[2]];

	ok = false;
	i = 0;
	@try {
		for (OFString *string in mutableArray1) {
			(void)string;

			if (i == 0)
				[mutableArray1 addObject: @""];

			i++;
		}
	} @catch (OFEnumerationMutationException *e) {
		ok = true;
	}

	TEST(@"Detection of mutation during Fast Enumeration", ok)

	[mutableArray1 removeLastObject];

#ifdef OF_HAVE_BLOCKS
	{
		__block bool blockOK = true;
		__block size_t count = 0;
		OFArray *compareArray = array1;
		OFMutableArray *mutableArray3;

		mutableArray1 = [[array1 mutableCopy] autorelease];
		[mutableArray1 enumerateObjectsUsingBlock:
		    ^ (id object_, size_t idx, bool *stop) {
			count++;
			if (![object_ isEqual:
			    [compareArray objectAtIndex: idx]])
				blockOK = false;
		}];

		if (count != compareArray.count)
			blockOK = false;

		TEST(@"Enumeration using blocks", blockOK)

		blockOK = false;

		mutableArray3 = mutableArray1;
		@try {
			[mutableArray3 enumerateObjectsUsingBlock:
			    ^ (id object_, size_t idx, bool *stop) {
				[mutableArray3 removeObjectAtIndex: idx];
			}];
		} @catch (OFEnumerationMutationException *e) {
			blockOK = true;
		} @catch (OFOutOfRangeException *e) {
			/*
			 * Out of bounds access due to enumeration not being
			 * detected.
			 */
		}

		TEST(@"Detection of mutation during enumeration using blocks",
		    blockOK)
	}

	TEST(@"-[replaceObjectsUsingBlock:]",
	    R([mutableArray1 replaceObjectsUsingBlock:
		^ id (id object_, size_t idx) {
		    switch (idx) {
		    case 0:
			    return @"foo";
		    case 1:
			    return @"bar";
		    }

		    return nil;
	    }]) && [mutableArray1.description isEqual: @"(\n\tfoo,\n\tbar\n)"])

	TEST(@"-[mappedArrayUsingBlock:]",
	    [[mutableArray1 mappedArrayUsingBlock:
		^ id (id object_, size_t idx) {
		    switch (idx) {
		    case 0:
			    return @"foobar";
		    case 1:
			    return @"qux";
		    }

		    return nil;
	    }].description isEqual: @"(\n\tfoobar,\n\tqux\n)"])

	TEST(@"-[filteredArrayUsingBlock:]",
	    [[mutableArray1 filteredArrayUsingBlock:
		^ bool (id object_, size_t idx) {
		    return [object_ isEqual: @"foo"];
	    }].description isEqual: @"(\n\tfoo\n)"])

	TEST(@"-[foldUsingBlock:]",
	    [[arrayClass arrayWithObjects: [OFMutableString string], @"foo",
	    @"bar", @"baz", nil] foldUsingBlock: ^ id (id left, id right) {
		    [left appendString: right];
		    return left;
	    }])
#endif

	TEST(@"-[valueForKey:]",
	    [[[arrayClass arrayWithObjects: @"foo", @"bar", @"quxqux", nil]
	    valueForKey: @"length"] isEqual:
	    [arrayClass arrayWithObjects: [OFNumber numberWithInt: 3],
	    [OFNumber numberWithInt: 3], [OFNumber numberWithInt: 6], nil]] &&
	    [[[arrayClass arrayWithObjects: @"1", @"2", nil]
	    valueForKey: @"@count"] isEqual: [OFNumber numberWithInt: 2]])

	mutableArray1 = [mutableArrayClass arrayWithObjects:
	    [OFMutableURL URLWithString: @"http://foo.bar/"],
	    [OFMutableURL URLWithString: @"http://bar.qux/"],
	    [OFMutableURL URLWithString: @"http://qux.quxqux/"], nil];
	TEST(@"-[setValue:forKey:]",
	    R([mutableArray1 setValue: [OFNumber numberWithShort: 1234]
			       forKey: @"port"]) &&
	    [mutableArray1 isEqual: [arrayClass arrayWithObjects:
	    [OFURL URLWithString: @"http://foo.bar:1234/"],
	    [OFURL URLWithString: @"http://bar.qux:1234/"],
	    [OFURL URLWithString: @"http://qux.quxqux:1234/"], nil]])

	objc_autoreleasePoolPop(pool);
}

Modified tests/OFBlockTests.m from [dc2e6666e8] to [52123616f6].

13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91

92
93

94
95
96

97
98
99
100
101
102
103
104
105
106
107
108
109
110
 * file.
 */

#include "config.h"

#import "TestsAppDelegate.h"

static OFString *module = @"OFBlock";

#if defined(OF_OBJFW_RUNTIME)
extern struct objc_class _NSConcreteStackBlock;
extern struct objc_class _NSConcreteGlobalBlock;
extern struct objc_class _NSConcreteMallocBlock;
#elif defined(OF_APPLE_RUNTIME)
extern void *_NSConcreteStackBlock;
extern void *_NSConcreteGlobalBlock;
extern void *_NSConcreteMallocBlock;
#endif

static void (^g)(void) = ^ {};

static int
(^returnStackBlock(void))(void)
{
	__block int i = 42;

	return [Block_copy(^ int { return ++i; }) autorelease];
}

static double
forwardTest(void)
{
	__block double d;
	void (^b)(void) = Block_copy(^ {
		d = 5;
	});

	b();
	Block_release(b);

	return d;
}

@implementation TestsAppDelegate (OFBlockTests)
- (void)blockTests
{
	void *pool = objc_autoreleasePoolPush();
	__block int x;
	void (^s)(void) = ^ { x = 0; };
	void (^m)(void);
	int (^v)(void);

	TEST(@"Class of stack block",
	    (Class)&_NSConcreteStackBlock == objc_getClass("OFStackBlock") &&
	    [s isKindOfClass: [OFBlock class]])

#if !defined(OF_WINDOWS) || !defined(__clang__) || !defined(OF_NO_SHARED)
	/*
	 * Causes a linker error on Windows with Clang when compiling as a
	 * static library. This is a bug in Clang.
	 */
	TEST(@"Class of global block",
	    (Class)&_NSConcreteGlobalBlock == objc_getClass("OFGlobalBlock") &&
	    [g isKindOfClass: [OFBlock class]])
#endif

	TEST(@"Class of a malloc block",
	    (Class)&_NSConcreteMallocBlock == objc_getClass("OFMallocBlock"))

	TEST(@"Copying a stack block",
	    (m = [[s copy] autorelease]) &&
	    [m class] == objc_getClass("OFMallocBlock") &&
	    [m isKindOfClass: [OFBlock class]])

	TEST(@"Copying a stack block and referencing its variable",
	    forwardTest() == 5)

	TEST(@"Copying a stack block and using its copied variable",
	    (v = returnStackBlock()) && v() == 43 && v() == 44 && v() == 45)


	TEST(@"Copying a global block", (id)g == [[g copy] autorelease])


#ifndef __clang_analyzer__
	TEST(@"Copying a malloc block",

	    (id)m == [m copy] && [m retainCount] == 2)
#endif

	TEST(@"Autorelease a stack block", R([s autorelease]))

	TEST(@"Autorelease a global block", R([g autorelease]))

#ifndef __clang_analyzer__
	TEST(@"Autorelease a malloc block", R([m autorelease]))
#endif

	objc_autoreleasePoolPop(pool);
}
@end







|











|













|



|
|









|
|
|



|








|






|
|
|





|
>

|
>



>
|


|

|


|





13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
 * file.
 */

#include "config.h"

#import "TestsAppDelegate.h"

static OFString *const module = @"OFBlock";

#if defined(OF_OBJFW_RUNTIME)
extern struct objc_class _NSConcreteStackBlock;
extern struct objc_class _NSConcreteGlobalBlock;
extern struct objc_class _NSConcreteMallocBlock;
#elif defined(OF_APPLE_RUNTIME)
extern void *_NSConcreteStackBlock;
extern void *_NSConcreteGlobalBlock;
extern void *_NSConcreteMallocBlock;
#endif

static void (^globalBlock)(void) = ^ {};

static int
(^returnStackBlock(void))(void)
{
	__block int i = 42;

	return [Block_copy(^ int { return ++i; }) autorelease];
}

static double
forwardTest(void)
{
	__block double d;
	void (^block)(void) = Block_copy(^ {
		d = 5;
	});

	block();
	Block_release(block);

	return d;
}

@implementation TestsAppDelegate (OFBlockTests)
- (void)blockTests
{
	void *pool = objc_autoreleasePoolPush();
	__block int x;
	void (^stackBlock)(void) = ^ { x = 0; };
	void (^mallocBlock)(void);
	int (^voidBlock)(void);

	TEST(@"Class of stack block",
	    (Class)&_NSConcreteStackBlock == objc_getClass("OFStackBlock") &&
	    [stackBlock isKindOfClass: [OFBlock class]])

#if !defined(OF_WINDOWS) || !defined(__clang__) || !defined(OF_NO_SHARED)
	/*
	 * Causes a linker error on Windows with Clang when compiling as a
	 * static library. This is a bug in Clang.
	 */
	TEST(@"Class of global block",
	    (Class)&_NSConcreteGlobalBlock == objc_getClass("OFGlobalBlock") &&
	    [globalBlock isKindOfClass: [OFBlock class]])
#endif

	TEST(@"Class of a malloc block",
	    (Class)&_NSConcreteMallocBlock == objc_getClass("OFMallocBlock"))

	TEST(@"Copying a stack block",
	    (mallocBlock = [[stackBlock copy] autorelease]) &&
	    [mallocBlock class] == objc_getClass("OFMallocBlock") &&
	    [mallocBlock isKindOfClass: [OFBlock class]])

	TEST(@"Copying a stack block and referencing its variable",
	    forwardTest() == 5)

	TEST(@"Copying a stack block and using its copied variable",
	    (voidBlock = returnStackBlock()) && voidBlock() == 43 &&
	    voidBlock() == 44 && voidBlock() == 45)

	TEST(@"Copying a global block",
	    (id)globalBlock == [[globalBlock copy] autorelease])

#ifndef __clang_analyzer__
	TEST(@"Copying a malloc block",
	    (id)mallocBlock == [mallocBlock copy] &&
	    [mallocBlock retainCount] == 2)
#endif

	TEST(@"Autorelease a stack block", R([stackBlock autorelease]))

	TEST(@"Autorelease a global block", R([globalBlock autorelease]))

#ifndef __clang_analyzer__
	TEST(@"Autorelease a malloc block", R([mallocBlock autorelease]))
#endif

	objc_autoreleasePoolPop(pool);
}
@end

Modified tests/OFCharacterSetTests.m from [f4f81f5355] to [dab7b0f641].

33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
}
@end

@implementation TestsAppDelegate (OFCharacterSetTests)
- (void)characterSetTests
{
	void *pool = objc_autoreleasePoolPush();
	OFCharacterSet *cs, *ics;
	bool ok;

	module = @"OFCharacterSet";

	cs = [[[SimpleCharacterSet alloc] init] autorelease];

	ok = true;
	for (OFUnichar c = 0; c < 65536; c++) {
		if (c % 2 == 0) {
			if (![cs characterIsMember: c])
				ok = false;
		} else if ([cs characterIsMember: c])
			ok = false;
	}
	TEST(@"-[characterIsMember:]", ok);

	module = @"OFBitSetCharacterSet";

	TEST(@"+[characterSetWithCharactersInString:]",
	    (cs = [OFCharacterSet characterSetWithCharactersInString:
	    @"0123456789"]) &&
	    [cs isKindOfClass: [OFBitSetCharacterSet class]])

	ok = true;
	for (OFUnichar c = 0; c < 65536; c++) {
		if (c >= '0' && c <= '9') {
			if (![cs characterIsMember: c])
				ok = false;
		} else if ([cs characterIsMember: c])
			ok = false;
	}
	TEST(@"-[characterIsMember:]", ok);

	module = @"OFRangeCharacterSet";

	TEST(@"+[characterSetWithRange:]",
	    (cs = [OFCharacterSet
	    characterSetWithRange: OFRangeMake('0', 10)]) &&
	    [cs isKindOfClass: [OFRangeCharacterSet class]])

	ok = true;
	for (OFUnichar c = 0; c < 65536; c++) {
		if (c >= '0' && c <= '9') {
			if (![cs characterIsMember: c])
				ok = false;
		} else if ([cs characterIsMember: c])
			ok = false;
	}
	TEST(@"-[characterIsMember:]", ok);

	ok = true;
	ics = cs.invertedSet;
	for (OFUnichar c = 0; c < 65536; c++) {
		if (c >= '0' && c <= '9') {
			if ([ics characterIsMember: c])
				ok = false;
		} else if (![ics characterIsMember: c])
			ok = false;
	}
	TEST(@"-[invertedSet]", ok);

	TEST(@"Inverting -[invertedSet] returns original set",
	    ics.invertedSet == cs)

	objc_autoreleasePoolPop(pool);
}
@end







|




|




|

|







|

|




|

|







|

|




|

|





|


|

|





|




33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
}
@end

@implementation TestsAppDelegate (OFCharacterSetTests)
- (void)characterSetTests
{
	void *pool = objc_autoreleasePoolPush();
	OFCharacterSet *characterSet, *invertedCharacterSet;
	bool ok;

	module = @"OFCharacterSet";

	characterSet = [[[SimpleCharacterSet alloc] init] autorelease];

	ok = true;
	for (OFUnichar c = 0; c < 65536; c++) {
		if (c % 2 == 0) {
			if (![characterSet characterIsMember: c])
				ok = false;
		} else if ([characterSet characterIsMember: c])
			ok = false;
	}
	TEST(@"-[characterIsMember:]", ok);

	module = @"OFBitSetCharacterSet";

	TEST(@"+[characterSetWithCharactersInString:]",
	    (characterSet = [OFCharacterSet characterSetWithCharactersInString:
	    @"0123456789"]) &&
	    [characterSet isKindOfClass: [OFBitSetCharacterSet class]])

	ok = true;
	for (OFUnichar c = 0; c < 65536; c++) {
		if (c >= '0' && c <= '9') {
			if (![characterSet characterIsMember: c])
				ok = false;
		} else if ([characterSet characterIsMember: c])
			ok = false;
	}
	TEST(@"-[characterIsMember:]", ok);

	module = @"OFRangeCharacterSet";

	TEST(@"+[characterSetWithRange:]",
	    (characterSet = [OFCharacterSet
	    characterSetWithRange: OFRangeMake('0', 10)]) &&
	    [characterSet isKindOfClass: [OFRangeCharacterSet class]])

	ok = true;
	for (OFUnichar c = 0; c < 65536; c++) {
		if (c >= '0' && c <= '9') {
			if (![characterSet characterIsMember: c])
				ok = false;
		} else if ([characterSet characterIsMember: c])
			ok = false;
	}
	TEST(@"-[characterIsMember:]", ok);

	ok = true;
	invertedCharacterSet = characterSet.invertedSet;
	for (OFUnichar c = 0; c < 65536; c++) {
		if (c >= '0' && c <= '9') {
			if ([invertedCharacterSet characterIsMember: c])
				ok = false;
		} else if (![invertedCharacterSet characterIsMember: c])
			ok = false;
	}
	TEST(@"-[invertedSet]", ok);

	TEST(@"Inverting -[invertedSet] returns original set",
	    invertedCharacterSet.invertedSet == characterSet)

	objc_autoreleasePoolPop(pool);
}
@end

Modified tests/OFDataTests.m from [6024274dc3] to [def38bc628].

15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75

76
77
78
79
80
81
82
83

84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173

174
175
176

177
178
179

180
181
182

183
184
185
186

187
188
189
190

191
192
193
194

195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214

215
216
217
218
219
220
221
222
223
224
225
226

#include "config.h"

#include <string.h>

#import "TestsAppDelegate.h"

static OFString *module = @"OFData";
const char *str = "Hello!";

@implementation TestsAppDelegate (OFDataTests)
- (void)dataTests
{
	void *pool = objc_autoreleasePoolPush();
	OFMutableData *mutable;
	OFData *immutable;
	void *raw[2];
	OFRange range;

	TEST(@"+[dataWithItemSize:]",
	    (mutable = [OFMutableData dataWithItemSize: 4096]))

	raw[0] = OFAllocMemory(1, 4096);
	raw[1] = OFAllocMemory(1, 4096);
	memset(raw[0], 0xFF, 4096);
	memset(raw[1], 0x42, 4096);

	TEST(@"-[addItem:]", R([mutable addItem: raw[0]]) &&
	    R([mutable addItem: raw[1]]))

	TEST(@"-[itemAtIndex:]",
	    memcmp([mutable itemAtIndex: 0], raw[0], 4096) == 0 &&
	    memcmp([mutable itemAtIndex: 1], raw[1], 4096) == 0)

	TEST(@"-[lastItem]", memcmp(mutable.lastItem, raw[1], 4096) == 0)

	TEST(@"-[count]", mutable.count == 2)

	TEST(@"-[isEqual:]",
	    (immutable = [OFData dataWithItems: mutable.items
					 count: mutable.count
				      itemSize: mutable.itemSize]) &&
	    [immutable isEqual: mutable] &&
	    R([mutable removeLastItem]) && ![mutable isEqual: immutable])

	TEST(@"-[mutableCopy]",
	    (mutable = [[immutable mutableCopy] autorelease]) &&
	    [mutable isEqual: immutable])

	TEST(@"-[compare]", [mutable compare: immutable] == 0 &&
	    R([mutable removeLastItem]) &&
	    [immutable compare: mutable] == OFOrderedDescending &&
	    [mutable compare: immutable] == OFOrderedAscending &&
	    [[OFData dataWithItems: "aa" count: 2] compare:
	    [OFData dataWithItems: "z" count: 1]] == OFOrderedAscending)

	TEST(@"-[hash]", immutable.hash == 0x634A529F)

	mutable = [OFMutableData dataWithItems: "abcdef" count: 6];

	TEST(@"-[removeLastItem]", R([mutable removeLastItem]) &&

	    mutable.count == 5 && memcmp(mutable.items, "abcde", 5) == 0)

	TEST(@"-[removeItemsInRange:]",
	    R([mutable removeItemsInRange: OFRangeMake(1, 2)]) &&
	    mutable.count == 3 && memcmp(mutable.items, "ade", 3) == 0)

	TEST(@"-[insertItems:atIndex:count:]",
	    R([mutable insertItems: "bc" atIndex: 1 count: 2]) &&

	    mutable.count == 5 && memcmp(mutable.items, "abcde", 5) == 0)

	immutable = [OFData dataWithItems: "aaabaccdacaabb"
				    count: 7
				 itemSize: 2];

	range = [immutable rangeOfData: [OFData dataWithItems: "aa"
							count: 1
						     itemSize: 2]
			       options: 0
				 range: OFRangeMake(0, 7)];
	TEST(@"-[rangeOfData:options:range:] #1",
	    range.location == 0 && range.length == 1)

	range = [immutable rangeOfData: [OFData dataWithItems: "aa"
							count: 1
						     itemSize: 2]
			       options: OFDataSearchBackwards
				 range: OFRangeMake(0, 7)];
	TEST(@"-[rangeOfData:options:range:] #2",
	    range.location == 5 && range.length == 1)

	range = [immutable rangeOfData: [OFData dataWithItems: "ac"
							count: 1
						     itemSize: 2]
			       options: 0
				 range: OFRangeMake(0, 7)];
	TEST(@"-[rangeOfData:options:range:] #3",
	    range.location == 2 && range.length == 1)

	range = [immutable rangeOfData: [OFData dataWithItems: "aabb"
							count: 2
						     itemSize: 2]
			       options: 0
				 range: OFRangeMake(0, 7)];
	TEST(@"-[rangeOfData:options:range:] #4",
	    range.location == 5 && range.length == 2)

	TEST(@"-[rangeOfData:options:range:] #5",
	    R(range = [immutable rangeOfData: [OFData dataWithItems: "aa"
							      count: 1
							   itemSize: 2]
				     options: 0
				       range: OFRangeMake(1, 6)]) &&
	    range.location == 5 && range.length == 1)

	range = [immutable rangeOfData: [OFData dataWithItems: "aa"
							count: 1
						     itemSize: 2]
			       options: OFDataSearchBackwards
				 range: OFRangeMake(0, 5)];
	TEST(@"-[rangeOfData:options:range:] #6",
	    range.location == 0 && range.length == 1)

	EXPECT_EXCEPTION(
	    @"-[rangeOfData:options:range:] failing on different itemSize",
	    OFInvalidArgumentException,
	    [immutable rangeOfData: [OFData dataWithItems: "aaa"
						    count: 1
						 itemSize: 3]
			   options: 0
			     range: OFRangeMake(0, 1)])

	EXPECT_EXCEPTION(
	    @"-[rangeOfData:options:range:] failing on out of range",
	    OFOutOfRangeException,
	    [immutable rangeOfData: [OFData dataWithItems: ""
						    count: 0
						 itemSize: 2]
			   options: 0
			     range: OFRangeMake(8, 1)])

	TEST(@"-[subdataWithRange:]",
	    [[immutable subdataWithRange: OFRangeMake(2, 4)]
	    isEqual: [OFData dataWithItems: "accdacaa"
				     count: 4
				  itemSize: 2]] &&
	    [[mutable subdataWithRange: OFRangeMake(2, 3)]
	    isEqual: [OFData dataWithItems: "cde"
				     count: 3]])

	EXPECT_EXCEPTION(@"-[subdataWithRange:] failing on out of range #1",
	    OFOutOfRangeException,
	    [immutable subdataWithRange: OFRangeMake(7, 1)])

	EXPECT_EXCEPTION(@"-[subdataWithRange:] failing on out of range #2",
	    OFOutOfRangeException,
	    [mutable subdataWithRange: OFRangeMake(6, 1)])

	TEST(@"-[stringByMD5Hashing]", [mutable.stringByMD5Hashing

	    isEqual: @"ab56b4d92b40713acc5af89985d4b786"])

	TEST(@"-[stringByRIPEMD160Hashing]", [mutable.stringByRIPEMD160Hashing

	    isEqual: @"973398b6e6c6cfa6b5e6a5173f195ce3274bf828"])

	TEST(@"-[stringBySHA1Hashing]", [mutable.stringBySHA1Hashing

	    isEqual: @"03de6c570bfe24bfc328ccd7ca46b76eadaf4334"])

	TEST(@"-[stringBySHA224Hashing]", [mutable.stringBySHA224Hashing

	    isEqual: @"bdd03d560993e675516ba5a50638b6531ac2ac3d5847c61916cfced6"
	    ])

	TEST(@"-[stringBySHA256Hashing]", [mutable.stringBySHA256Hashing

	    isEqual: @"36bbe50ed96841d10443bcb670d6554f0a34b761be67ec9c4a8ad2c0"
		     @"c44ca42c"])

	TEST(@"-[stringBySHA384Hashing]", [mutable.stringBySHA384Hashing

	    isEqual: @"4c525cbeac729eaf4b4665815bc5db0c84fe6300068a727cf74e2813"
		     @"521565abc0ec57a37ee4d8be89d097c0d2ad52f0"])

	TEST(@"-[stringBySHA512Hashing]", [mutable.stringBySHA512Hashing

	    isEqual: @"878ae65a92e86cac011a570d4c30a7eaec442b85ce8eca0c2952b5e3"
		     @"cc0628c2e79d889ad4d5c7c626986d452dd86374b6ffaa7cd8b67665"
		     @"bef2289a5c70b0a1"])

	TEST(@"-[stringByBase64Encoding]",
	    [mutable.stringByBase64Encoding isEqual: @"YWJjZGU="])

	TEST(@"+[dataWithBase64EncodedString:]",
	    memcmp([[OFData dataWithBase64EncodedString: @"YWJjZGU="]
	    items], "abcde", 5) == 0)

	TEST(@"Building strings",
	    (mutable = [OFMutableData dataWithItems: str count: 6]) &&
	    R([mutable addItem: ""]) &&
	    strcmp(mutable.items, str) == 0)

	EXPECT_EXCEPTION(@"Detect out of range in -[itemAtIndex:]",
	    OFOutOfRangeException, [mutable itemAtIndex: mutable.count])

	EXPECT_EXCEPTION(@"Detect out of range in -[addItems:count:]",

	    OFOutOfRangeException, [mutable addItems: raw[0] count: SIZE_MAX])

	EXPECT_EXCEPTION(@"Detect out of range in -[removeItemsInRange:]",
	    OFOutOfRangeException,
	    [mutable removeItemsInRange: OFRangeMake(mutable.count, 1)])

	OFFreeMemory(raw[0]);
	OFFreeMemory(raw[1]);

	objc_autoreleasePoolPop(pool);
}
@end







|
<





|
|




|






|
|


|
|

|

|


|
|
|
|
|


|
|

|
|
|
|



|

|

|
>
|


|
|


|
>
|

|
<
<

|
|
|
|
|



|
|
|
|
|



|
|
|
|
|



|
|
|
|
|




|
|
|
|
|


|
|
|
|
|






|
|
|
|
|




|
<
<
|
|


|
|
<
<
|
|
<



|



|

|
>


|
>


|
>


|
>



|
>



|
>



|
>





|


|
|


|
|
|


|


>
|



|







15
16
17
18
19
20
21
22

23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87


88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149


150
151
152
153
154
155


156
157

158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228

#include "config.h"

#include <string.h>

#import "TestsAppDelegate.h"

static OFString *const module = @"OFData";


@implementation TestsAppDelegate (OFDataTests)
- (void)dataTests
{
	void *pool = objc_autoreleasePoolPush();
	OFMutableData *mutableData;
	OFData *data;
	void *raw[2];
	OFRange range;

	TEST(@"+[dataWithItemSize:]",
	    (mutableData = [OFMutableData dataWithItemSize: 4096]))

	raw[0] = OFAllocMemory(1, 4096);
	raw[1] = OFAllocMemory(1, 4096);
	memset(raw[0], 0xFF, 4096);
	memset(raw[1], 0x42, 4096);

	TEST(@"-[addItem:]", R([mutableData addItem: raw[0]]) &&
	    R([mutableData addItem: raw[1]]))

	TEST(@"-[itemAtIndex:]",
	    memcmp([mutableData itemAtIndex: 0], raw[0], 4096) == 0 &&
	    memcmp([mutableData itemAtIndex: 1], raw[1], 4096) == 0)

	TEST(@"-[lastItem]", memcmp(mutableData.lastItem, raw[1], 4096) == 0)

	TEST(@"-[count]", mutableData.count == 2)

	TEST(@"-[isEqual:]",
	    (data = [OFData dataWithItems: mutableData.items
				    count: mutableData.count
				 itemSize: mutableData.itemSize]) &&
	    [data isEqual: mutableData] &&
	    R([mutableData removeLastItem]) && ![mutableData isEqual: data])

	TEST(@"-[mutableCopy]",
	    (mutableData = [[data mutableCopy] autorelease]) &&
	    [mutableData isEqual: data])

	TEST(@"-[compare]", [mutableData compare: data] == 0 &&
	    R([mutableData removeLastItem]) &&
	    [data compare: mutableData] == OFOrderedDescending &&
	    [mutableData compare: data] == OFOrderedAscending &&
	    [[OFData dataWithItems: "aa" count: 2] compare:
	    [OFData dataWithItems: "z" count: 1]] == OFOrderedAscending)

	TEST(@"-[hash]", data.hash == 0x634A529F)

	mutableData = [OFMutableData dataWithItems: "abcdef" count: 6];

	TEST(@"-[removeLastItem]",
	    R([mutableData removeLastItem]) && mutableData.count == 5 &&
	    memcmp(mutableData.items, "abcde", 5) == 0)

	TEST(@"-[removeItemsInRange:]",
	    R([mutableData removeItemsInRange: OFRangeMake(1, 2)]) &&
	    mutableData.count == 3 && memcmp(mutableData.items, "ade", 3) == 0)

	TEST(@"-[insertItems:atIndex:count:]",
	    R([mutableData insertItems: "bc" atIndex: 1 count: 2]) &&
	    mutableData.count == 5 &&
	    memcmp(mutableData.items, "abcde", 5) == 0)

	data = [OFData dataWithItems: "aaabaccdacaabb" count: 7 itemSize: 2];



	range = [data rangeOfData: [OFData dataWithItems: "aa"
						   count: 1
						itemSize: 2]
			  options: 0
			    range: OFRangeMake(0, 7)];
	TEST(@"-[rangeOfData:options:range:] #1",
	    range.location == 0 && range.length == 1)

	range = [data rangeOfData: [OFData dataWithItems: "aa"
						   count: 1
						itemSize: 2]
			  options: OFDataSearchBackwards
			    range: OFRangeMake(0, 7)];
	TEST(@"-[rangeOfData:options:range:] #2",
	    range.location == 5 && range.length == 1)

	range = [data rangeOfData: [OFData dataWithItems: "ac"
						   count: 1
						itemSize: 2]
			  options: 0
			    range: OFRangeMake(0, 7)];
	TEST(@"-[rangeOfData:options:range:] #3",
	    range.location == 2 && range.length == 1)

	range = [data rangeOfData: [OFData dataWithItems: "aabb"
						   count: 2
						itemSize: 2]
			  options: 0
			    range: OFRangeMake(0, 7)];
	TEST(@"-[rangeOfData:options:range:] #4",
	    range.location == 5 && range.length == 2)

	TEST(@"-[rangeOfData:options:range:] #5",
	    R(range = [data rangeOfData: [OFData dataWithItems: "aa"
							 count: 1
						      itemSize: 2]
				options: 0
				  range: OFRangeMake(1, 6)]) &&
	    range.location == 5 && range.length == 1)

	range = [data rangeOfData: [OFData dataWithItems: "aa"
						   count: 1
						itemSize: 2]
			  options: OFDataSearchBackwards
			    range: OFRangeMake(0, 5)];
	TEST(@"-[rangeOfData:options:range:] #6",
	    range.location == 0 && range.length == 1)

	EXPECT_EXCEPTION(
	    @"-[rangeOfData:options:range:] failing on different itemSize",
	    OFInvalidArgumentException,
	    [data rangeOfData: [OFData dataWithItems: "aaa"
					       count: 1
					    itemSize: 3]
		      options: 0
			range: OFRangeMake(0, 1)])

	EXPECT_EXCEPTION(
	    @"-[rangeOfData:options:range:] failing on out of range",
	    OFOutOfRangeException,
	    [data rangeOfData: [OFData dataWithItems: "" count: 0 itemSize: 2]


		      options: 0
			range: OFRangeMake(8, 1)])

	TEST(@"-[subdataWithRange:]",
	    [[data subdataWithRange: OFRangeMake(2, 4)]
	    isEqual: [OFData dataWithItems: "accdacaa" count: 4 itemSize: 2]] &&


	    [[mutableData subdataWithRange: OFRangeMake(2, 3)]
	    isEqual: [OFData dataWithItems: "cde" count: 3]])


	EXPECT_EXCEPTION(@"-[subdataWithRange:] failing on out of range #1",
	    OFOutOfRangeException,
	    [data subdataWithRange: OFRangeMake(7, 1)])

	EXPECT_EXCEPTION(@"-[subdataWithRange:] failing on out of range #2",
	    OFOutOfRangeException,
	    [mutableData subdataWithRange: OFRangeMake(6, 1)])

	TEST(@"-[stringByMD5Hashing]",
	    [mutableData.stringByMD5Hashing
	    isEqual: @"ab56b4d92b40713acc5af89985d4b786"])

	TEST(@"-[stringByRIPEMD160Hashing]",
	    [mutableData.stringByRIPEMD160Hashing
	    isEqual: @"973398b6e6c6cfa6b5e6a5173f195ce3274bf828"])

	TEST(@"-[stringBySHA1Hashing]",
	    [mutableData.stringBySHA1Hashing
	    isEqual: @"03de6c570bfe24bfc328ccd7ca46b76eadaf4334"])

	TEST(@"-[stringBySHA224Hashing]",
	    [mutableData.stringBySHA224Hashing
	    isEqual: @"bdd03d560993e675516ba5a50638b6531ac2ac3d5847c61916cfced6"
	    ])

	TEST(@"-[stringBySHA256Hashing]",
	    [mutableData.stringBySHA256Hashing
	    isEqual: @"36bbe50ed96841d10443bcb670d6554f0a34b761be67ec9c4a8ad2c0"
		     @"c44ca42c"])

	TEST(@"-[stringBySHA384Hashing]",
	    [mutableData.stringBySHA384Hashing
	    isEqual: @"4c525cbeac729eaf4b4665815bc5db0c84fe6300068a727cf74e2813"
		     @"521565abc0ec57a37ee4d8be89d097c0d2ad52f0"])

	TEST(@"-[stringBySHA512Hashing]",
	    [mutableData.stringBySHA512Hashing
	    isEqual: @"878ae65a92e86cac011a570d4c30a7eaec442b85ce8eca0c2952b5e3"
		     @"cc0628c2e79d889ad4d5c7c626986d452dd86374b6ffaa7cd8b67665"
		     @"bef2289a5c70b0a1"])

	TEST(@"-[stringByBase64Encoding]",
	    [mutableData.stringByBase64Encoding isEqual: @"YWJjZGU="])

	TEST(@"+[dataWithBase64EncodedString:]",
	    memcmp([[OFData dataWithBase64EncodedString: @"YWJjZGU="] items],
	    "abcde", 5) == 0)

	TEST(@"Building strings",
	    (mutableData = [OFMutableData dataWithItems: "Hello!" count: 6]) &&
	    R([mutableData addItem: ""]) &&
	    strcmp(mutableData.items, "Hello!") == 0)

	EXPECT_EXCEPTION(@"Detect out of range in -[itemAtIndex:]",
	    OFOutOfRangeException, [mutableData itemAtIndex: mutableData.count])

	EXPECT_EXCEPTION(@"Detect out of range in -[addItems:count:]",
	    OFOutOfRangeException,
	    [mutableData addItems: raw[0] count: SIZE_MAX])

	EXPECT_EXCEPTION(@"Detect out of range in -[removeItemsInRange:]",
	    OFOutOfRangeException,
	    [mutableData removeItemsInRange: OFRangeMake(mutableData.count, 1)])

	OFFreeMemory(raw[0]);
	OFFreeMemory(raw[1]);

	objc_autoreleasePoolPop(pool);
}
@end

Modified tests/OFDateTests.m from [ad515445a9] to [7e834c33fc].

15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
..
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87

88
89
90
91
92
93

94
95

96
97

98
99

100
101

102
103
104
105
106
107
108
109

#include "config.h"

#include <time.h>

#import "TestsAppDelegate.h"

static OFString *module = @"OFDate";

@implementation TestsAppDelegate (OFDateTests)
- (void)dateTests
{
	void *pool = objc_autoreleasePoolPush();
	OFDate *d1, *d2;

	struct tm tm;
	int16_t tz;
	const char *dstr = "Wed, 09 Jun 2021 +0200x";
	TEST(@"OFStrPTime()",
	    OFStrPTime(dstr, "%a, %d %b %Y %z", &tm, &tz) == dstr + 22 &&
	    tm.tm_wday == 3 && tm.tm_mday == 9 && tm.tm_mon == 5 &&
	    tm.tm_year == 2021 - 1900 && tz == 2 * 60)

	TEST(@"+[dateWithTimeIntervalSince1970:]",
	    (d1 = [OFDate dateWithTimeIntervalSince1970: 0]))

	TEST(@"-[dateByAddingTimeInterval:]",
	    (d2 = [d1 dateByAddingTimeInterval: 3600 * 25 + 5.000002]))

	TEST(@"-[description]",
	    [d1.description isEqual: @"1970-01-01T00:00:00Z"] &&
	    [d2.description isEqual: @"1970-01-02T01:00:05Z"])

	TEST(@"+[dateWithDateString:format:]",
	    [[[OFDate dateWithDateString: @"2000-06-20T12:34:56+0200"
				  format: @"%Y-%m-%dT%H:%M:%S%z"] description]
	    isEqual: @"2000-06-20T10:34:56Z"]);

	EXPECT_EXCEPTION(@"Detection of unparsed in "
................................................................................

	EXPECT_EXCEPTION(@"Detection of unparsed in "
	    @"+[dateWithLocalDateString:format:] #2", OFInvalidFormatException,
	    [OFDate dateWithLocalDateString: @"2000-06-20T12:34:56+0200x"
				     format: @"%Y-%m-%dT%H:%M:%S%z"])

	TEST(@"-[isEqual:]",
	    [d1 isEqual: [OFDate dateWithTimeIntervalSince1970: 0]] &&
	    ![d1 isEqual: [OFDate dateWithTimeIntervalSince1970: 0.0000001]])

	TEST(@"-[compare:]", [d1 compare: d2] == OFOrderedAscending)

	TEST(@"-[second]", d1.second == 0 && d2.second == 5)

	TEST(@"-[microsecond]", d1.microsecond == 0 && d2.microsecond == 2)


	TEST(@"-[minute]", d1.minute == 0 && d2.minute == 0)

	TEST(@"-[hour]", d1.hour == 0 && d2.hour == 1)

	TEST(@"-[dayOfMonth]", d1.dayOfMonth == 1 && d2.dayOfMonth == 2)


	TEST(@"-[monthOfYear]", d1.monthOfYear == 1 && d2.monthOfYear == 1)


	TEST(@"-[year]", d1.year == 1970 && d2.year == 1970)


	TEST(@"-[dayOfWeek]", d1.dayOfWeek == 4 && d2.dayOfWeek == 5)


	TEST(@"-[dayOfYear]", d1.dayOfYear == 1 && d2.dayOfYear == 2)


	TEST(@"-[earlierDate:]", [[d1 earlierDate: d2] isEqual: d1])

	TEST(@"-[laterDate:]", [[d1 laterDate: d2] isEqual: d2])

	objc_autoreleasePoolPop(pool);
}
@end







|





|










|


|


|
|







 







|
|

|

|

|
>

|

|

<
>

|
>

<
>

<
>

<
>

|

|




15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
..
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93

94
95
96
97
98

99
100

101
102

103
104
105
106
107
108
109
110
111

#include "config.h"

#include <time.h>

#import "TestsAppDelegate.h"

static OFString *const module = @"OFDate";

@implementation TestsAppDelegate (OFDateTests)
- (void)dateTests
{
	void *pool = objc_autoreleasePoolPush();
	OFDate *date1, *date2;

	struct tm tm;
	int16_t tz;
	const char *dstr = "Wed, 09 Jun 2021 +0200x";
	TEST(@"OFStrPTime()",
	    OFStrPTime(dstr, "%a, %d %b %Y %z", &tm, &tz) == dstr + 22 &&
	    tm.tm_wday == 3 && tm.tm_mday == 9 && tm.tm_mon == 5 &&
	    tm.tm_year == 2021 - 1900 && tz == 2 * 60)

	TEST(@"+[dateWithTimeIntervalSince1970:]",
	    (date1 = [OFDate dateWithTimeIntervalSince1970: 0]))

	TEST(@"-[dateByAddingTimeInterval:]",
	    (date2 = [date1 dateByAddingTimeInterval: 3600 * 25 + 5.000002]))

	TEST(@"-[description]",
	    [date1.description isEqual: @"1970-01-01T00:00:00Z"] &&
	    [date2.description isEqual: @"1970-01-02T01:00:05Z"])

	TEST(@"+[dateWithDateString:format:]",
	    [[[OFDate dateWithDateString: @"2000-06-20T12:34:56+0200"
				  format: @"%Y-%m-%dT%H:%M:%S%z"] description]
	    isEqual: @"2000-06-20T10:34:56Z"]);

	EXPECT_EXCEPTION(@"Detection of unparsed in "
................................................................................

	EXPECT_EXCEPTION(@"Detection of unparsed in "
	    @"+[dateWithLocalDateString:format:] #2", OFInvalidFormatException,
	    [OFDate dateWithLocalDateString: @"2000-06-20T12:34:56+0200x"
				     format: @"%Y-%m-%dT%H:%M:%S%z"])

	TEST(@"-[isEqual:]",
	    [date1 isEqual: [OFDate dateWithTimeIntervalSince1970: 0]] &&
	    ![date1 isEqual: [OFDate dateWithTimeIntervalSince1970: 0.0000001]])

	TEST(@"-[compare:]", [date1 compare: date2] == OFOrderedAscending)

	TEST(@"-[second]", date1.second == 0 && date2.second == 5)

	TEST(@"-[microsecond]",
	    date1.microsecond == 0 && date2.microsecond == 2)

	TEST(@"-[minute]", date1.minute == 0 && date2.minute == 0)

	TEST(@"-[hour]", date1.hour == 0 && date2.hour == 1)


	TEST(@"-[dayOfMonth]", date1.dayOfMonth == 1 && date2.dayOfMonth == 2)

	TEST(@"-[monthOfYear]",
	    date1.monthOfYear == 1 && date2.monthOfYear == 1)


	TEST(@"-[year]", date1.year == 1970 && date2.year == 1970)


	TEST(@"-[dayOfWeek]", date1.dayOfWeek == 4 && date2.dayOfWeek == 5)


	TEST(@"-[dayOfYear]", date1.dayOfYear == 1 && date2.dayOfYear == 2)

	TEST(@"-[earlierDate:]", [[date1 earlierDate: date2] isEqual: date1])

	TEST(@"-[laterDate:]", [[date1 laterDate: date2] isEqual: date2])

	objc_autoreleasePoolPop(pool);
}
@end

Modified tests/OFDictionaryTests.m from [fdcd71652e] to [1f9b9cab2d].

100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
...
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233

234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307

308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
...
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
- (id)objectForKey: (id)key
{
	return [_dictionary objectForKey: key];
}

- (size_t)count
{
	return [_dictionary count];
}

- (OFEnumerator *)keyEnumerator
{
	return [_dictionary keyEnumerator];
}
@end
................................................................................
@end

@implementation TestsAppDelegate (OFDictionaryTests)
- (void)dictionaryTestsWithClass: (Class)dictionaryClass
		    mutableClass: (Class)mutableDictionaryClass
{
	void *pool = objc_autoreleasePoolPush();
	OFMutableDictionary *mutDict = [mutableDictionaryClass dictionary];
	OFDictionary *dict;
	OFEnumerator *keyEnumerator, *objectEnumerator;
	OFArray *keysArray, *valuesArray;

	[mutDict setObject: values[0] forKey: keys[0]];
	[mutDict setValue: values[1] forKey: keys[1]];

	TEST(@"-[objectForKey:]",
	    [[mutDict objectForKey: keys[0]] isEqual: values[0]] &&
	    [[mutDict objectForKey: keys[1]] isEqual: values[1]] &&
	    [mutDict objectForKey: @"key3"] == nil)

	TEST(@"-[valueForKey:]",
	    [[mutDict valueForKey: keys[0]] isEqual: values[0]] &&
	    [[mutDict valueForKey: @"@count"] isEqual:
	    [OFNumber numberWithInt: 2]])

	EXPECT_EXCEPTION(@"Catching -[setValue:forKey:] on immutable "
	    @"dictionary", OFUndefinedKeyException,
	    [[dictionaryClass dictionary] setValue: @"x" forKey: @"x"])

	TEST(@"-[containsObject:]",
	    [mutDict containsObject: values[0]] &&
	    ![mutDict containsObject: @"nonexistent"])

	TEST(@"-[containsObjectIdenticalTo:]",
	    [mutDict containsObjectIdenticalTo: values[0]] &&
	    ![mutDict containsObjectIdenticalTo:
	    [OFString stringWithString: values[0]]])

	TEST(@"-[description]",
	    [[mutDict description] isEqual:
	    @"{\n\tkey1 = value1;\n\tkey2 = value2;\n}"])

	TEST(@"-[allKeys]",
	    [[mutDict allKeys] isEqual: [OFArray arrayWithObjects: keys[0],
	    keys[1], nil]])

	TEST(@"-[allObjects]",
	    [[mutDict allObjects] isEqual: [OFArray arrayWithObjects: values[0],
	    values[1], nil]])

	TEST(@"-[keyEnumerator]", (keyEnumerator = [mutDict keyEnumerator]))
	TEST(@"-[objectEnumerator]",
	    (objectEnumerator = [mutDict objectEnumerator]))

	TEST(@"OFEnumerator's -[nextObject]",
	    [[keyEnumerator nextObject] isEqual: keys[0]] &&
	    [[objectEnumerator nextObject] isEqual: values[0]] &&
	    [[keyEnumerator nextObject] isEqual: keys[1]] &&
	    [[objectEnumerator nextObject] isEqual: values[1]] &&
	    [keyEnumerator nextObject] == nil &&
	    [objectEnumerator nextObject] == nil)

	[mutDict removeObjectForKey: keys[0]];

	EXPECT_EXCEPTION(@"Detection of mutation during enumeration",
	    OFEnumerationMutationException, [keyEnumerator nextObject]);

	[mutDict setObject: values[0] forKey: keys[0]];

	size_t i = 0;
	bool ok = true;

	for (OFString *key in mutDict) {
		if (i > 1 || ![key isEqual: keys[i]]) {
			ok = false;
			break;
		}

		[mutDict setObject: [mutDict objectForKey: key] forKey: key];

		i++;
	}

	TEST(@"Fast Enumeration", ok)

	ok = false;
	@try {
		for (OFString *key in mutDict) {
			(void)key;
			[mutDict setObject: @"" forKey: @""];
		}
	} @catch (OFEnumerationMutationException *e) {
		ok = true;
	}

	TEST(@"Detection of mutation during Fast Enumeration", ok)

	[mutDict removeObjectForKey: @""];

	TEST(@"-[stringByURLEncoding]",
	    [[[OFDictionary dictionaryWithKeysAndObjects: @"foo", @"bar",
							  @"q&x", @"q=x", nil]
	    stringByURLEncoding] isEqual: @"q%26x=q%3Dx&foo=bar"])

#ifdef OF_HAVE_BLOCKS
	{
		__block size_t j = 0;
		__block bool blockOk = true;

		[mutDict enumerateKeysAndObjectsUsingBlock:
		    ^ (id key, id object, bool *stop) {
			if (j > 1 || ![key isEqual: keys[j]]) {
				blockOk = false;
				*stop = true;
				return;
			}

			[mutDict setObject: [mutDict objectForKey: key]
				    forKey: key];
			j++;
		}];

		TEST(@"Enumeration using blocks", blockOk)

		blockOk = false;
		@try {
			[mutDict enumerateKeysAndObjectsUsingBlock:
			    ^ (id key, id object, bool *stop) {
				[mutDict setObject: @""
					    forKey: @""];
			}];
		} @catch (OFEnumerationMutationException *e) {
			blockOk = true;
		}

		TEST(@"Detection of mutation during enumeration using blocks",
		    blockOk)

		[mutDict removeObjectForKey: @""];
	}

	TEST(@"-[replaceObjectsUsingBlock:]",
	    R([mutDict replaceObjectsUsingBlock: ^ id (id key, id object) {
		if ([key isEqual: keys[0]])
			return @"value_1";
		if ([key isEqual: keys[1]])
			return @"value_2";

		return nil;
	    }]) && [[mutDict objectForKey: keys[0]] isEqual: @"value_1"] &&
	    [[mutDict objectForKey: keys[1]] isEqual: @"value_2"])

	TEST(@"-[mappedDictionaryUsingBlock:]",
	    [[[mutDict mappedDictionaryUsingBlock: ^ id (id key, id object) {

		if ([key isEqual: keys[0]])
			return @"val1";
		if ([key isEqual: keys[1]])
			return @"val2";

		return nil;
	    }] description] isEqual: @"{\n\tkey1 = val1;\n\tkey2 = val2;\n}"])

	TEST(@"-[filteredDictionaryUsingBlock:]",
	    [[[mutDict filteredDictionaryUsingBlock:
	    ^ bool (id key, id object) {
		return [key isEqual: keys[0]];
	    }] description] isEqual: @"{\n\tkey1 = value_1;\n}"])
#endif

	TEST(@"-[count]", mutDict.count == 2)

	TEST(@"+[dictionaryWithKeysAndObjects:]",
	    (dict = [dictionaryClass dictionaryWithKeysAndObjects:
	    @"foo", @"bar", @"baz", @"qux", nil]) &&
	    [[dict objectForKey: @"foo"] isEqual: @"bar"] &&
	    [[dict objectForKey: @"baz"] isEqual: @"qux"])

................................................................................

	TEST(@"-[copy]",
	    (dict = [[dict copy] autorelease]) &&
	    [[dict objectForKey: keys[0]] isEqual: values[0]] &&
	    [[dict objectForKey: keys[1]] isEqual: values[1]])

	TEST(@"-[mutableCopy]",
	    (mutDict = [[dict mutableCopy] autorelease]) &&
	    mutDict.count == dict.count &&
	    [[mutDict objectForKey: keys[0]] isEqual: values[0]] &&
	    [[mutDict objectForKey: keys[1]] isEqual: values[1]] &&
	    R([mutDict setObject: @"value3" forKey: @"key3"]) &&
	    [[mutDict objectForKey: @"key3"] isEqual: @"value3"] &&
	    [[mutDict objectForKey: keys[0]] isEqual: values[0]] &&
	    R([mutDict setObject: @"foo" forKey: keys[0]]) &&
	    [[mutDict objectForKey: keys[0]] isEqual: @"foo"])

	TEST(@"-[removeObjectForKey:]",
	    R([mutDict removeObjectForKey: keys[0]]) &&
	    [mutDict objectForKey: keys[0]] == nil)

	[mutDict setObject: @"foo" forKey: keys[0]];
	TEST(@"-[isEqual:]", ![mutDict isEqual: dict] &&
	    R([mutDict removeObjectForKey: @"key3"]) &&
	    ![mutDict isEqual: dict] &&
	    R([mutDict setObject: values[0] forKey: keys[0]]) &&
	    [mutDict isEqual: dict])

	objc_autoreleasePoolPop(pool);
}

- (void)dictionaryTests
{
	module = @"OFDictionary";







|







 







|




|
|


|
|
|


|
|







|
|


|
|



|



|
|


|
|

|

|









|




|




|





|
>







|

|







|











|







|
|







|

|
<








|



|
|
|
|
|

|
|
|


|
>
|
|
|
|





|
|
|



|







 







|
|
|
|
|
|
|
|
|


|
|

|
|
|
|
|
|







100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
...
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283

284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
...
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
- (id)objectForKey: (id)key
{
	return [_dictionary objectForKey: key];
}

- (size_t)count
{
	return _dictionary.count;
}

- (OFEnumerator *)keyEnumerator
{
	return [_dictionary keyEnumerator];
}
@end
................................................................................
@end

@implementation TestsAppDelegate (OFDictionaryTests)
- (void)dictionaryTestsWithClass: (Class)dictionaryClass
		    mutableClass: (Class)mutableDictionaryClass
{
	void *pool = objc_autoreleasePoolPush();
	OFMutableDictionary *mutableDict = [mutableDictionaryClass dictionary];
	OFDictionary *dict;
	OFEnumerator *keyEnumerator, *objectEnumerator;
	OFArray *keysArray, *valuesArray;

	[mutableDict setObject: values[0] forKey: keys[0]];
	[mutableDict setValue: values[1] forKey: keys[1]];

	TEST(@"-[objectForKey:]",
	    [[mutableDict objectForKey: keys[0]] isEqual: values[0]] &&
	    [[mutableDict objectForKey: keys[1]] isEqual: values[1]] &&
	    [mutableDict objectForKey: @"key3"] == nil)

	TEST(@"-[valueForKey:]",
	    [[mutableDict valueForKey: keys[0]] isEqual: values[0]] &&
	    [[mutableDict valueForKey: @"@count"] isEqual:
	    [OFNumber numberWithInt: 2]])

	EXPECT_EXCEPTION(@"Catching -[setValue:forKey:] on immutable "
	    @"dictionary", OFUndefinedKeyException,
	    [[dictionaryClass dictionary] setValue: @"x" forKey: @"x"])

	TEST(@"-[containsObject:]",
	    [mutableDict containsObject: values[0]] &&
	    ![mutableDict containsObject: @"nonexistent"])

	TEST(@"-[containsObjectIdenticalTo:]",
	    [mutableDict containsObjectIdenticalTo: values[0]] &&
	    ![mutableDict containsObjectIdenticalTo:
	    [OFString stringWithString: values[0]]])

	TEST(@"-[description]",
	    [[mutableDict description] isEqual:
	    @"{\n\tkey1 = value1;\n\tkey2 = value2;\n}"])

	TEST(@"-[allKeys]",
	    [[mutableDict allKeys] isEqual:
	    [OFArray arrayWithObjects: keys[0], keys[1], nil]])

	TEST(@"-[allObjects]",
	    [[mutableDict allObjects] isEqual:
	    [OFArray arrayWithObjects: values[0], values[1], nil]])

	TEST(@"-[keyEnumerator]", (keyEnumerator = [mutableDict keyEnumerator]))
	TEST(@"-[objectEnumerator]",
	    (objectEnumerator = [mutableDict objectEnumerator]))

	TEST(@"OFEnumerator's -[nextObject]",
	    [[keyEnumerator nextObject] isEqual: keys[0]] &&
	    [[objectEnumerator nextObject] isEqual: values[0]] &&
	    [[keyEnumerator nextObject] isEqual: keys[1]] &&
	    [[objectEnumerator nextObject] isEqual: values[1]] &&
	    [keyEnumerator nextObject] == nil &&
	    [objectEnumerator nextObject] == nil)

	[mutableDict removeObjectForKey: keys[0]];

	EXPECT_EXCEPTION(@"Detection of mutation during enumeration",
	    OFEnumerationMutationException, [keyEnumerator nextObject]);

	[mutableDict setObject: values[0] forKey: keys[0]];

	size_t i = 0;
	bool ok = true;

	for (OFString *key in mutableDict) {
		if (i > 1 || ![key isEqual: keys[i]]) {
			ok = false;
			break;
		}

		[mutableDict setObject: [mutableDict objectForKey: key]
				forKey: key];
		i++;
	}

	TEST(@"Fast Enumeration", ok)

	ok = false;
	@try {
		for (OFString *key in mutableDict) {
			(void)key;
			[mutableDict setObject: @"" forKey: @""];
		}
	} @catch (OFEnumerationMutationException *e) {
		ok = true;
	}

	TEST(@"Detection of mutation during Fast Enumeration", ok)

	[mutableDict removeObjectForKey: @""];

	TEST(@"-[stringByURLEncoding]",
	    [[[OFDictionary dictionaryWithKeysAndObjects: @"foo", @"bar",
							  @"q&x", @"q=x", nil]
	    stringByURLEncoding] isEqual: @"q%26x=q%3Dx&foo=bar"])

#ifdef OF_HAVE_BLOCKS
	{
		__block size_t j = 0;
		__block bool blockOk = true;

		[mutableDict enumerateKeysAndObjectsUsingBlock:
		    ^ (id key, id object, bool *stop) {
			if (j > 1 || ![key isEqual: keys[j]]) {
				blockOk = false;
				*stop = true;
				return;
			}

			[mutableDict setObject: [mutableDict objectForKey: key]
					forKey: key];
			j++;
		}];

		TEST(@"Enumeration using blocks", blockOk)

		blockOk = false;
		@try {
			[mutableDict enumerateKeysAndObjectsUsingBlock:
			    ^ (id key, id object, bool *stop) {
				[mutableDict setObject: @"" forKey: @""];

			}];
		} @catch (OFEnumerationMutationException *e) {
			blockOk = true;
		}

		TEST(@"Detection of mutation during enumeration using blocks",
		    blockOk)

		[mutableDict removeObjectForKey: @""];
	}

	TEST(@"-[replaceObjectsUsingBlock:]",
	    R([mutableDict replaceObjectsUsingBlock: ^ id (id key, id object) {
		    if ([key isEqual: keys[0]])
			    return @"value_1";
		    if ([key isEqual: keys[1]])
			    return @"value_2";

		    return nil;
	    }]) && [[mutableDict objectForKey: keys[0]] isEqual: @"value_1"] &&
	    [[mutableDict objectForKey: keys[1]] isEqual: @"value_2"])

	TEST(@"-[mappedDictionaryUsingBlock:]",
	    [[[mutableDict mappedDictionaryUsingBlock:
		^ id (id key, id object) {
		    if ([key isEqual: keys[0]])
			    return @"val1";
		    if ([key isEqual: keys[1]])
			    return @"val2";

		return nil;
	    }] description] isEqual: @"{\n\tkey1 = val1;\n\tkey2 = val2;\n}"])

	TEST(@"-[filteredDictionaryUsingBlock:]",
	    [[[mutableDict filteredDictionaryUsingBlock:
		^ bool (id key, id object) {
		    return [key isEqual: keys[0]];
	    }] description] isEqual: @"{\n\tkey1 = value_1;\n}"])
#endif

	TEST(@"-[count]", mutableDict.count == 2)

	TEST(@"+[dictionaryWithKeysAndObjects:]",
	    (dict = [dictionaryClass dictionaryWithKeysAndObjects:
	    @"foo", @"bar", @"baz", @"qux", nil]) &&
	    [[dict objectForKey: @"foo"] isEqual: @"bar"] &&
	    [[dict objectForKey: @"baz"] isEqual: @"qux"])

................................................................................

	TEST(@"-[copy]",
	    (dict = [[dict copy] autorelease]) &&
	    [[dict objectForKey: keys[0]] isEqual: values[0]] &&
	    [[dict objectForKey: keys[1]] isEqual: values[1]])

	TEST(@"-[mutableCopy]",
	    (mutableDict = [[dict mutableCopy] autorelease]) &&
	    mutableDict.count == dict.count &&
	    [[mutableDict objectForKey: keys[0]] isEqual: values[0]] &&
	    [[mutableDict objectForKey: keys[1]] isEqual: values[1]] &&
	    R([mutableDict setObject: @"value3" forKey: @"key3"]) &&
	    [[mutableDict objectForKey: @"key3"] isEqual: @"value3"] &&
	    [[mutableDict objectForKey: keys[0]] isEqual: values[0]] &&
	    R([mutableDict setObject: @"foo" forKey: keys[0]]) &&
	    [[mutableDict objectForKey: keys[0]] isEqual: @"foo"])

	TEST(@"-[removeObjectForKey:]",
	    R([mutableDict removeObjectForKey: keys[0]]) &&
	    [mutableDict objectForKey: keys[0]] == nil)

	[mutableDict setObject: @"foo" forKey: keys[0]];
	TEST(@"-[isEqual:]", ![mutableDict isEqual: dict] &&
	    R([mutableDict removeObjectForKey: @"key3"]) &&
	    ![mutableDict isEqual: dict] &&
	    R([mutableDict setObject: values[0] forKey: keys[0]]) &&
	    [mutableDict isEqual: dict])

	objc_autoreleasePoolPop(pool);
}

- (void)dictionaryTests
{
	module = @"OFDictionary";

Modified tests/OFHMACTests.m from [51628de7e9] to [f54d111cd0].

15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118

119
120
121

122
123
124
125

#include "config.h"

#include <string.h>

#import "TestsAppDelegate.h"

static OFString *module = @"OFHMAC";
static const uint8_t key[] =
    "yM9h8K6IWnJRvxC/0F8XRWG7RnACDBz8wqK2tbXrYVLoKC3vPLeJikyJSM47tVHc"
    "DlXHww9zULAC2sJUlm2Kg1z4oz2aXY3Y1PQSB4VkC/m0DQ7hCI6cAg4TWnKdzWTy"
    "cvYGX+Y6HWeDY79/PGSd8fNItme6I8w4HDBqU7BP2sum3jbePJqoiSnhcyJZQTeZ"
    "jw0ZXoyrfHgOYD2M+NsTDaGpLblFtQ7n5CczjKtafG40PkEwx1dcrd46U9i3GyTK";
static const size_t key_length = sizeof(key);
static const uint8_t digest_md5[] =
    "\xCC\x1F\xEF\x09\x29\xA3\x25\x1A\x06\xA9\x83\x99\xF9\xBC\x8F\x42";
static const uint8_t digest_sha1[] =
    "\x94\xB9\x0A\x6F\xFB\xA7\x13\x6A\x75\x55"
    "\xD5\x7F\x5D\xB7\xF4\xCA\xEB\x4A\xDE\xBF";
static const uint8_t digest_rmd160[] =
    "\x2C\xE1\xED\x41\xC6\xF3\x51\xA8\x04\xD2"
    "\xC3\x9B\x08\x33\x3B\xD5\xC9\x00\x39\x50";
static const uint8_t digest_sha256[] =
    "\xFB\x8C\xDA\x88\xB3\x81\x32\x16\xD7\xD8\x62\xD4\xA6\x26\x9D\x77"
    "\x01\x99\x62\x65\x29\x02\x41\xE6\xEF\xA1\x02\x31\xA8\x9D\x77\x5D";
static const uint8_t digest_sha384[] =
    "\x2F\x4A\x47\xAE\x13\x8E\x96\x52\xF1\x8F\x05\xFD\x65\xCD\x9A\x97"
    "\x93\x2F\xC9\x02\xD6\xC6\xAB\x2E\x15\x76\xC0\xA7\xA0\x05\xF4\xEF"
    "\x14\x52\x33\x4B\x9C\x5F\xD8\x07\x4E\x98\xAE\x97\x46\x29\x24\xB4";
static const uint8_t digest_sha512[] =
    "\xF5\x8C\x3F\x9C\xA2\x2F\x0A\xF3\x26\xD8\xC0\x7E\x20\x63\x88\x61"
    "\xC9\xE1\x1F\xD7\xC7\xE5\x59\x33\xD5\x2F\xAF\x56\x1C\x94\xC8\xA4"
    "\x61\xB3\xF9\x1A\xE3\x09\x43\xA6\x5B\x85\xB1\x50\x5B\xCB\x1A\x2E"
    "\xB7\xE8\x87\xC1\x73\x19\x63\xF6\xA2\x91\x8D\x7E\x2E\xCC\xEC\x99";

@implementation TestsAppDelegate (OFHMACTests)
- (void)HMACTests
{
	void *pool = objc_autoreleasePoolPush();
	OFFile *f = [OFFile fileWithPath: @"testfile.bin" mode: @"r"];
	OFHMAC *HMAC_MD5, *HMAC_SHA1, *HMAC_RMD160;
	OFHMAC *HMAC_SHA256, *HMAC_SHA384, *HMAC_SHA512;

	TEST(@"+[HMACWithHashClass:] with MD5",
	    (HMAC_MD5 = [OFHMAC HMACWithHashClass: [OFMD5Hash class]
			    allowsSwappableMemory: true]))
	TEST(@"+[HMACWithHashClass:] with SHA-1",
	    (HMAC_SHA1 = [OFHMAC HMACWithHashClass: [OFSHA1Hash class]
			     allowsSwappableMemory: true]))
	TEST(@"+[HMACWithHashClass:] with RIPEMD-160",
	    (HMAC_RMD160 = [OFHMAC HMACWithHashClass: [OFRIPEMD160Hash class]
			       allowsSwappableMemory: true]))
	TEST(@"+[HMACWithHashClass:] with SHA-256",
	    (HMAC_SHA256 = [OFHMAC HMACWithHashClass: [OFSHA256Hash class]
			       allowsSwappableMemory: true]))
	TEST(@"+[HMACWithHashClass:] with SHA-384",
	    (HMAC_SHA384 = [OFHMAC HMACWithHashClass: [OFSHA384Hash class]
			       allowsSwappableMemory: true]))
	TEST(@"+[HMACWithHashClass:] with SHA-512",
	    (HMAC_SHA512 = [OFHMAC HMACWithHashClass: [OFSHA512Hash class]
			       allowsSwappableMemory: true]))

	EXPECT_EXCEPTION(@"Detection of missing key",
	    OFInvalidArgumentException, [HMAC_MD5 updateWithBuffer: ""
							    length: 0])

	TEST(@"-[setKey:length:] with MD5",
	    R([HMAC_MD5 setKey: key length: key_length]))
	TEST(@"-[setKey:length:] with SHA-1",
	    R([HMAC_SHA1 setKey: key length: key_length]))
	TEST(@"-[setKey:length:] with RIPEMD-160",
	    R([HMAC_RMD160 setKey: key length: key_length]))
	TEST(@"-[setKey:length:] with SHA-256",
	    R([HMAC_SHA256 setKey: key length: key_length]))
	TEST(@"-[setKey:length:] with SHA-384",
	    R([HMAC_SHA384 setKey: key length: key_length]))
	TEST(@"-[setKey:length:] with SHA-512",
	    R([HMAC_SHA512 setKey: key length: key_length]))

	while (!f.atEndOfStream) {
		char buf[64];
		size_t len = [f readIntoBuffer: buf length: 64];
		[HMAC_MD5 updateWithBuffer: buf length: len];
		[HMAC_SHA1 updateWithBuffer: buf length: len];
		[HMAC_RMD160 updateWithBuffer: buf length: len];
		[HMAC_SHA256 updateWithBuffer: buf length: len];
		[HMAC_SHA384 updateWithBuffer: buf length: len];
		[HMAC_SHA512 updateWithBuffer: buf length: len];
	}
	[f close];

	TEST(@"-[digest] with MD5",
	    memcmp(HMAC_MD5.digest, digest_md5, HMAC_MD5.digestSize) == 0)
	TEST(@"-[digest] with SHA-1",
	    memcmp(HMAC_SHA1.digest, digest_sha1, HMAC_SHA1.digestSize) == 0)
	TEST(@"-[digest] with RIPEMD-160",
	    memcmp(HMAC_RMD160.digest, digest_rmd160,
	    HMAC_RMD160.digestSize) == 0)
	TEST(@"-[digest] with SHA-256",
	    memcmp(HMAC_SHA256.digest, digest_sha256,
	    HMAC_SHA256.digestSize) == 0)
	TEST(@"-[digest] with SHA-384",
	    memcmp(HMAC_SHA384.digest, digest_sha384,
	    HMAC_SHA384.digestSize) == 0)

	TEST(@"-[digest] with SHA-512",
	    memcmp(HMAC_SHA512.digest, digest_sha512,
	    HMAC_SHA512.digestSize) == 0)


	objc_autoreleasePoolPop(pool);
}
@end







|





|
|

|


|


|


|



|









|
|
|


|
|

|
|

|
|

|
|

|
|

|
|


|
|


|

|

|

|

|

|

|
|
|
|
|
|
|
|
|

|


|

|

|
|

|
<

<
<
>

<
<
>




15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114

115


116
117


118
119
120
121
122

#include "config.h"

#include <string.h>

#import "TestsAppDelegate.h"

static OFString *const module = @"OFHMAC";
static const uint8_t key[] =
    "yM9h8K6IWnJRvxC/0F8XRWG7RnACDBz8wqK2tbXrYVLoKC3vPLeJikyJSM47tVHc"
    "DlXHww9zULAC2sJUlm2Kg1z4oz2aXY3Y1PQSB4VkC/m0DQ7hCI6cAg4TWnKdzWTy"
    "cvYGX+Y6HWeDY79/PGSd8fNItme6I8w4HDBqU7BP2sum3jbePJqoiSnhcyJZQTeZ"
    "jw0ZXoyrfHgOYD2M+NsTDaGpLblFtQ7n5CczjKtafG40PkEwx1dcrd46U9i3GyTK";
static const size_t keyLength = sizeof(key);
static const uint8_t MD5Digest[] =
    "\xCC\x1F\xEF\x09\x29\xA3\x25\x1A\x06\xA9\x83\x99\xF9\xBC\x8F\x42";
static const uint8_t SHA1Digest[] =
    "\x94\xB9\x0A\x6F\xFB\xA7\x13\x6A\x75\x55"
    "\xD5\x7F\x5D\xB7\xF4\xCA\xEB\x4A\xDE\xBF";
static const uint8_t RIPEMD160Digest[] =
    "\x2C\xE1\xED\x41\xC6\xF3\x51\xA8\x04\xD2"
    "\xC3\x9B\x08\x33\x3B\xD5\xC9\x00\x39\x50";
static const uint8_t SHA256Digest[] =
    "\xFB\x8C\xDA\x88\xB3\x81\x32\x16\xD7\xD8\x62\xD4\xA6\x26\x9D\x77"
    "\x01\x99\x62\x65\x29\x02\x41\xE6\xEF\xA1\x02\x31\xA8\x9D\x77\x5D";
static const uint8_t SHA384Digest[] =
    "\x2F\x4A\x47\xAE\x13\x8E\x96\x52\xF1\x8F\x05\xFD\x65\xCD\x9A\x97"
    "\x93\x2F\xC9\x02\xD6\xC6\xAB\x2E\x15\x76\xC0\xA7\xA0\x05\xF4\xEF"
    "\x14\x52\x33\x4B\x9C\x5F\xD8\x07\x4E\x98\xAE\x97\x46\x29\x24\xB4";
static const uint8_t SHA512Digest[] =
    "\xF5\x8C\x3F\x9C\xA2\x2F\x0A\xF3\x26\xD8\xC0\x7E\x20\x63\x88\x61"
    "\xC9\xE1\x1F\xD7\xC7\xE5\x59\x33\xD5\x2F\xAF\x56\x1C\x94\xC8\xA4"
    "\x61\xB3\xF9\x1A\xE3\x09\x43\xA6\x5B\x85\xB1\x50\x5B\xCB\x1A\x2E"
    "\xB7\xE8\x87\xC1\x73\x19\x63\xF6\xA2\x91\x8D\x7E\x2E\xCC\xEC\x99";

@implementation TestsAppDelegate (OFHMACTests)
- (void)HMACTests
{
	void *pool = objc_autoreleasePoolPush();
	OFFile *file = [OFFile fileWithPath: @"testfile.bin" mode: @"r"];
	OFHMAC *HMACMD5, *HMACSHA1, *HMACRMD160;
	OFHMAC *HMACSHA256, *HMACSHA384, *HMACSHA512;

	TEST(@"+[HMACWithHashClass:] with MD5",
	    (HMACMD5 = [OFHMAC HMACWithHashClass: [OFMD5Hash class]
			   allowsSwappableMemory: true]))
	TEST(@"+[HMACWithHashClass:] with SHA-1",
	    (HMACSHA1 = [OFHMAC HMACWithHashClass: [OFSHA1Hash class]
			    allowsSwappableMemory: true]))
	TEST(@"+[HMACWithHashClass:] with RIPEMD-160",
	    (HMACRMD160 = [OFHMAC HMACWithHashClass: [OFRIPEMD160Hash class]
			      allowsSwappableMemory: true]))
	TEST(@"+[HMACWithHashClass:] with SHA-256",
	    (HMACSHA256 = [OFHMAC HMACWithHashClass: [OFSHA256Hash class]
			      allowsSwappableMemory: true]))
	TEST(@"+[HMACWithHashClass:] with SHA-384",
	    (HMACSHA384 = [OFHMAC HMACWithHashClass: [OFSHA384Hash class]
			      allowsSwappableMemory: true]))
	TEST(@"+[HMACWithHashClass:] with SHA-512",
	    (HMACSHA512 = [OFHMAC HMACWithHashClass: [OFSHA512Hash class]
			      allowsSwappableMemory: true]))

	EXPECT_EXCEPTION(@"Detection of missing key",
	    OFInvalidArgumentException,
	    [HMACMD5 updateWithBuffer: "" length: 0])

	TEST(@"-[setKey:length:] with MD5",
	    R([HMACMD5 setKey: key length: keyLength]))
	TEST(@"-[setKey:length:] with SHA-1",
	    R([HMACSHA1 setKey: key length: keyLength]))
	TEST(@"-[setKey:length:] with RIPEMD-160",
	    R([HMACRMD160 setKey: key length: keyLength]))
	TEST(@"-[setKey:length:] with SHA-256",
	    R([HMACSHA256 setKey: key length: keyLength]))
	TEST(@"-[setKey:length:] with SHA-384",
	    R([HMACSHA384 setKey: key length: keyLength]))
	TEST(@"-[setKey:length:] with SHA-512",
	    R([HMACSHA512 setKey: key length: keyLength]))

	while (!file.atEndOfStream) {
		char buffer[64];
		size_t length = [file readIntoBuffer: buffer length: 64];
		[HMACMD5 updateWithBuffer: buffer length: length];
		[HMACSHA1 updateWithBuffer: buffer length: length];
		[HMACRMD160 updateWithBuffer: buffer length: length];
		[HMACSHA256 updateWithBuffer: buffer length: length];
		[HMACSHA384 updateWithBuffer: buffer length: length];
		[HMACSHA512 updateWithBuffer: buffer length: length];
	}
	[file close];

	TEST(@"-[digest] with MD5",
	    memcmp(HMACMD5.digest, MD5Digest, HMACMD5.digestSize) == 0)
	TEST(@"-[digest] with SHA-1",
	    memcmp(HMACSHA1.digest, SHA1Digest, HMACSHA1.digestSize) == 0)
	TEST(@"-[digest] with RIPEMD-160",
	    memcmp(HMACRMD160.digest, RIPEMD160Digest,
	    HMACRMD160.digestSize) == 0)
	TEST(@"-[digest] with SHA-256",
	    memcmp(HMACSHA256.digest, SHA256Digest, HMACSHA256.digestSize) == 0)

	TEST(@"-[digest] with SHA-384",


	    memcmp(HMACSHA384.digest, SHA384Digest, HMACSHA384.digestSize) == 0)
	TEST(@"-[digest] with SHA-512",


	    memcmp(HMACSHA512.digest, SHA512Digest, HMACSHA512.digestSize) == 0)

	objc_autoreleasePoolPop(pool);
}
@end

Modified tests/OFHTTPClientTests.m from [76a48837cf] to [1197c752e1].

16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
..
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
...
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
#include "config.h"

#include <inttypes.h>
#include <string.h>

#import "TestsAppDelegate.h"

static OFString *module = @"OFHTTPClient";
static OFCondition *cond;
static OFHTTPResponse *response = nil;

@interface TestsAppDelegate (HTTPClientTests) <OFHTTPClientDelegate>
@end

@interface HTTPClientTestsServer: OFThread
{
................................................................................

@implementation HTTPClientTestsServer
- (id)main
{
	OFTCPSocket *listener, *client;
	char buffer[5];

	[cond lock];

	listener = [OFTCPSocket socket];
	_port = [listener bindToHost: @"127.0.0.1" port: 0];
	[listener listen];

	[cond signal];
	[cond unlock];

	client = [listener accept];

	if (![[client readLine] isEqual: @"GET /foo HTTP/1.1"])
		OFEnsure(0);

	if (![[client readLine] hasPrefix: @"User-Agent:"])
		OFEnsure(0);

	if (![[client readLine] isEqual: @"Content-Length: 5"])
		OFEnsure(0);

	if (![[client readLine] isEqual:
	    @"Content-Type: application/x-www-form-urlencoded; charset=UTF-8"])
		OFEnsure(0);

	if (![[client readLine] isEqual:
	    [OFString stringWithFormat: @"Host: 127.0.0.1:%" @PRIu16, _port]])
		OFEnsure(0);

	if (![[client readLine] isEqual: @""])
		OFEnsure(0);

	[client readIntoBuffer: buffer exactLength: 5];
	if (memcmp(buffer, "Hello", 5) != 0)
		OFEnsure(0);

	[client writeString: @"HTTP/1.0 200 OK\r\n"
			     @"cONTeNT-lENgTH: 7\r\n"
			     @"\r\n"
			     @"foo\n"
			     @"bar"];
	[client close];
................................................................................
	void *pool = objc_autoreleasePoolPush();
	HTTPClientTestsServer *server;
	OFURL *URL;
	OFHTTPClient *client;
	OFHTTPRequest *request;
	OFData *data;

	cond = [OFCondition condition];
	[cond lock];

	server = [[[HTTPClientTestsServer alloc] init] autorelease];
	server.supportsSockets = true;
	[server start];

	[cond wait];
	[cond unlock];

	URL = [OFURL URLWithString:
	    [OFString stringWithFormat: @"http://127.0.0.1:%" @PRIu16 "/foo",
					server->_port]];

	TEST(@"-[asyncPerformRequest:]",
	    (client = [OFHTTPClient client]) && (client.delegate = self) &&







|
|







 







|





|
|



|
<
<
|
<
<
|
<
<
|
|
<





|
<


|
<







 







|
|





|
|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
..
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54


55


56


57
58

59
60
61
62
63
64

65
66
67

68
69
70
71
72
73
74
...
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#include "config.h"

#include <inttypes.h>
#include <string.h>

#import "TestsAppDelegate.h"

static OFString *const module = @"OFHTTPClient";
static OFCondition *condition;
static OFHTTPResponse *response = nil;

@interface TestsAppDelegate (HTTPClientTests) <OFHTTPClientDelegate>
@end

@interface HTTPClientTestsServer: OFThread
{
................................................................................

@implementation HTTPClientTestsServer
- (id)main
{
	OFTCPSocket *listener, *client;
	char buffer[5];

	[condition lock];

	listener = [OFTCPSocket socket];
	_port = [listener bindToHost: @"127.0.0.1" port: 0];
	[listener listen];

	[condition signal];
	[condition unlock];

	client = [listener accept];

	OFEnsure([[client readLine] isEqual: @"GET /foo HTTP/1.1"]);


	OFEnsure([[client readLine] hasPrefix: @"User-Agent:"]);


	OFEnsure([[client readLine] isEqual: @"Content-Length: 5"]);


	OFEnsure([[client readLine] isEqual:
	    @"Content-Type: application/x-www-form-urlencoded; charset=UTF-8"]);


	if (![[client readLine] isEqual:
	    [OFString stringWithFormat: @"Host: 127.0.0.1:%" @PRIu16, _port]])
		OFEnsure(0);

	OFEnsure([[client readLine] isEqual: @""]);


	[client readIntoBuffer: buffer exactLength: 5];
	OFEnsure(memcmp(buffer, "Hello", 5) == 0);


	[client writeString: @"HTTP/1.0 200 OK\r\n"
			     @"cONTeNT-lENgTH: 7\r\n"
			     @"\r\n"
			     @"foo\n"
			     @"bar"];
	[client close];
................................................................................
	void *pool = objc_autoreleasePoolPush();
	HTTPClientTestsServer *server;
	OFURL *URL;
	OFHTTPClient *client;
	OFHTTPRequest *request;
	OFData *data;

	condition = [OFCondition condition];
	[condition lock];

	server = [[[HTTPClientTestsServer alloc] init] autorelease];
	server.supportsSockets = true;
	[server start];

	[condition wait];
	[condition unlock];

	URL = [OFURL URLWithString:
	    [OFString stringWithFormat: @"http://127.0.0.1:%" @PRIu16 "/foo",
					server->_port]];

	TEST(@"-[asyncPerformRequest:]",
	    (client = [OFHTTPClient client]) && (client.delegate = self) &&

Modified tests/OFHTTPCookieManagerTests.m from [8226ed0409] to [d8c3ff9fea].

13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
 * file.
 */

#include "config.h"

#import "TestsAppDelegate.h"

static OFString *module = @"OFHTTPCookieManager";

@implementation TestsAppDelegate (OFHTTPCookieManagerTests)
- (void)HTTPCookieManagerTests
{
	void *pool = objc_autoreleasePoolPush();
	OFHTTPCookieManager *manager = [OFHTTPCookieManager manager];
	OFURL *URL[4];
	OFHTTPCookie *cookie[5];

	URL[0] = [OFURL URLWithString: @"http://nil.im/foo"];
	URL[1] = [OFURL URLWithString: @"https://nil.im/foo/bar"];
	URL[2] = [OFURL URLWithString: @"https://test.nil.im/foo/bar"];
	URL[3] = [OFURL URLWithString: @"http://webkeks.org/foo/bar"];

	cookie[0] = [OFHTTPCookie cookieWithName: @"test"
					   value: @"1"
					  domain: @"nil.im"];
	TEST(@"-[addCookie:forURL:] #1", R([manager addCookie: cookie[0]
						       forURL: URL[0]]))

	TEST(@"-[cookiesForURL:] #1",
	    [[manager cookiesForURL: URL[0]] isEqual:
	    [OFArray arrayWithObject: cookie[0]]])

	cookie[1] = [OFHTTPCookie cookieWithName: @"test"
					   value: @"2"
					  domain: @"webkeks.org"];
	TEST(@"-[addCookie:forURL:] #2",
	    R([manager addCookie: cookie[1] forURL: URL[0]]))

	TEST(@"-[cookiesForURL:] #2",
	    [[manager cookiesForURL: URL[0]] isEqual:
	    [OFArray arrayWithObject: cookie[0]]] &&
	    [[manager cookiesForURL: URL[3]] isEqual: [OFArray array]])

	cookie[2] = [OFHTTPCookie cookieWithName: @"test"
					   value: @"3"
					  domain: @"nil.im"];
	cookie[2].secure = true;
	TEST(@"-[addCookie:forURL:] #3",
	    R([manager addCookie: cookie[2] forURL: URL[1]]))

	TEST(@"-[cookiesForURL:] #3",
	    [[manager cookiesForURL: URL[1]] isEqual:
	    [OFArray arrayWithObject: cookie[2]]] &&
	    [[manager cookiesForURL: URL[0]] isEqual: [OFArray array]])

	cookie[2].expires = [OFDate dateWithTimeIntervalSinceNow: -1];
	cookie[3] = [OFHTTPCookie cookieWithName: @"test"
					   value: @"4"
					  domain: @"nil.im"];
	cookie[3].domain = @".nil.im";
	TEST(@"-[addCookie:forURL:] #4",
	    R([manager addCookie: cookie[3] forURL: URL[1]]))

	TEST(@"-[cookiesForURL:] #4",
	    [[manager cookiesForURL: URL[1]] isEqual:
	    [OFArray arrayWithObject: cookie[3]]] &&
	    [[manager cookiesForURL: URL[2]] isEqual:
	    [OFArray arrayWithObject: cookie[3]]])

	cookie[4] = [OFHTTPCookie cookieWithName: @"bar"
					   value: @"5"
					  domain: @"test.nil.im"];
	TEST(@"-[addCookie:forURL:] #5",
	    R([manager addCookie: cookie[4] forURL: URL[0]]))

	TEST(@"-[cookiesForURL:] #5",
	    [[manager cookiesForURL: URL[0]] isEqual:
	    [OFArray arrayWithObject: cookie[3]]] &&
	    [[manager cookiesForURL: URL[2]] isEqual:
	    [OFArray arrayWithObjects: cookie[3], cookie[4], nil]])

	TEST(@"-[purgeExpiredCookies]",
	    [manager.cookies isEqual:
	    [OFArray arrayWithObjects: cookie[2], cookie[3], cookie[4], nil]] &&
	    R([manager purgeExpiredCookies]) &&
	    [manager.cookies isEqual:
	    [OFArray arrayWithObjects: cookie[3], cookie[4], nil]])

	objc_autoreleasePoolPop(pool);
}
@end







|






|
|

|
|
|
|

|
|
|
|
|


|
|

|
|
|

|


|
|
|

|
|
|
|

|


|
|
|

|
|
|
|
|

|


|
|
|
|

|
|
|

|


|
|
|
|



|


|




13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
 * file.
 */

#include "config.h"

#import "TestsAppDelegate.h"

static OFString *const module = @"OFHTTPCookieManager";

@implementation TestsAppDelegate (OFHTTPCookieManagerTests)
- (void)HTTPCookieManagerTests
{
	void *pool = objc_autoreleasePoolPush();
	OFHTTPCookieManager *manager = [OFHTTPCookieManager manager];
	OFURL *URL1, *URL2, *URL3, *URL4;
	OFHTTPCookie *cookie1, *cookie2, *cookie3, *cookie4, *cookie5;

	URL1 = [OFURL URLWithString: @"http://nil.im/foo"];
	URL2 = [OFURL URLWithString: @"https://nil.im/foo/bar"];
	URL3 = [OFURL URLWithString: @"https://test.nil.im/foo/bar"];
	URL4 = [OFURL URLWithString: @"http://webkeks.org/foo/bar"];

	cookie1 = [OFHTTPCookie cookieWithName: @"test"
					 value: @"1"
					domain: @"nil.im"];
	TEST(@"-[addCookie:forURL:] #1",
	    R([manager addCookie: cookie1 forURL: URL1]))

	TEST(@"-[cookiesForURL:] #1",
	    [[manager cookiesForURL: URL1] isEqual:
	    [OFArray arrayWithObject: cookie1]])

	cookie2 = [OFHTTPCookie cookieWithName: @"test"
					 value: @"2"
					domain: @"webkeks.org"];
	TEST(@"-[addCookie:forURL:] #2",
	    R([manager addCookie: cookie2 forURL: URL1]))

	TEST(@"-[cookiesForURL:] #2",
	    [[manager cookiesForURL: URL1] isEqual:
	    [OFArray arrayWithObject: cookie1]] &&
	    [[manager cookiesForURL: URL4] isEqual: [OFArray array]])

	cookie3 = [OFHTTPCookie cookieWithName: @"test"
					 value: @"3"
					domain: @"nil.im"];
	cookie3.secure = true;
	TEST(@"-[addCookie:forURL:] #3",
	    R([manager addCookie: cookie3 forURL: URL2]))

	TEST(@"-[cookiesForURL:] #3",
	    [[manager cookiesForURL: URL2] isEqual:
	    [OFArray arrayWithObject: cookie3]] &&
	    [[manager cookiesForURL: URL1] isEqual: [OFArray array]])

	cookie3.expires = [OFDate dateWithTimeIntervalSinceNow: -1];
	cookie4 = [OFHTTPCookie cookieWithName: @"test"
					 value: @"4"
					domain: @"nil.im"];
	cookie4.domain = @".nil.im";
	TEST(@"-[addCookie:forURL:] #4",
	    R([manager addCookie: cookie4 forURL: URL2]))

	TEST(@"-[cookiesForURL:] #4",
	    [[manager cookiesForURL: URL2] isEqual:
	    [OFArray arrayWithObject: cookie4]] &&
	    [[manager cookiesForURL: URL3] isEqual:
	    [OFArray arrayWithObject: cookie4]])

	cookie5 = [OFHTTPCookie cookieWithName: @"bar"
					 value: @"5"
					domain: @"test.nil.im"];
	TEST(@"-[addCookie:forURL:] #5",
	    R([manager addCookie: cookie5 forURL: URL1]))

	TEST(@"-[cookiesForURL:] #5",
	    [[manager cookiesForURL: URL1] isEqual:
	    [OFArray arrayWithObject: cookie4]] &&
	    [[manager cookiesForURL: URL3] isEqual:
	    [OFArray arrayWithObjects: cookie4, cookie5, nil]])

	TEST(@"-[purgeExpiredCookies]",
	    [manager.cookies isEqual:
	    [OFArray arrayWithObjects: cookie3, cookie4, cookie5, nil]] &&
	    R([manager purgeExpiredCookies]) &&
	    [manager.cookies isEqual:
	    [OFArray arrayWithObjects: cookie4, cookie5, nil]])

	objc_autoreleasePoolPop(pool);
}
@end

Modified tests/OFHTTPCookieTests.m from [ea70ec9f7e] to [3f137e64cb].

13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
 * file.
 */

#include "config.h"

#import "TestsAppDelegate.h"

static OFString *module = @"OFHTTPCookie";

@implementation TestsAppDelegate (OFHTTPCookieTests)
- (void)HTTPCookieTests
{
	void *pool = objc_autoreleasePoolPush();
	OFURL *URL = [OFURL URLWithString: @"http://nil.im"];
	OFHTTPCookie *cookie[2];
	OFArray OF_GENERIC(OFHTTPCookie *) *cookies;

	cookie[0] = [OFHTTPCookie cookieWithName: @"foo"
					   value: @"bar"
					  domain: @"nil.im"];
	TEST(@"+[cookiesWithResponseHeaderFields:forURL:] #1",
	    [[OFHTTPCookie cookiesWithResponseHeaderFields: [OFDictionary
	    dictionaryWithObject: @"foo=bar"
	    forKey: @"Set-Cookie"] forURL: URL]
	    isEqual: [OFArray arrayWithObject: cookie[0]]])

	cookie[1] = [OFHTTPCookie cookieWithName: @"qux"
					   value: @"cookie"
					  domain: @"nil.im"];
	TEST(@"+[cookiesWithResponseHeaderFields:forURL:] #2",
	    [[OFHTTPCookie cookiesWithResponseHeaderFields: [OFDictionary
	    dictionaryWithObject: @"foo=bar,qux=cookie"
	    forKey: @"Set-Cookie"] forURL: URL]
	    isEqual: [OFArray arrayWithObjects: cookie[0], cookie[1], nil]])

	cookie[0].expires = [OFDate dateWithTimeIntervalSince1970: 1234567890];
	cookie[1].expires = [OFDate dateWithTimeIntervalSince1970: 1234567890];
	cookie[0].path = @"/x";
	cookie[1].domain = @"webkeks.org";
	cookie[1].path = @"/objfw";
	cookie[1].secure = true;
	cookie[1].HTTPOnly = true;
	[cookie[1].extensions addObject: @"foo"];
	[cookie[1].extensions addObject: @"bar"];
	TEST(@"+[cookiesWithResponseHeaderFields:forURL:] #3",
	    [(cookies = [OFHTTPCookie cookiesWithResponseHeaderFields:
	    [OFDictionary dictionaryWithObject:
	    @"foo=bar; Expires=Fri, 13 Feb 2009 23:31:30 GMT; Path=/x,"
	    @"qux=cookie; Expires=Fri, 13 Feb 2009 23:31:30 GMT; "
	    @"Domain=webkeks.org; Path=/objfw; Secure; HTTPOnly; foo; bar"
	    forKey: @"Set-Cookie"] forURL: URL]) isEqual:
	    [OFArray arrayWithObjects: cookie[0], cookie[1], nil]])

	TEST(@"+[requestHeaderFieldsWithCookies:]",
	    [[OFHTTPCookie requestHeaderFieldsWithCookies: cookies] isEqual:
	    [OFDictionary dictionaryWithObject: @"foo=bar; qux=cookie"
					forKey: @"Cookie"]])

	objc_autoreleasePoolPop(pool);
}
@end







|






|


|
|
|




|

|
|
|




|

|
|
|
|
|
|
|
|
|







|









13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
 * file.
 */

#include "config.h"

#import "TestsAppDelegate.h"

static OFString *const module = @"OFHTTPCookie";

@implementation TestsAppDelegate (OFHTTPCookieTests)
- (void)HTTPCookieTests
{
	void *pool = objc_autoreleasePoolPush();
	OFURL *URL = [OFURL URLWithString: @"http://nil.im"];
	OFHTTPCookie *cookie1, *cookie2;
	OFArray OF_GENERIC(OFHTTPCookie *) *cookies;

	cookie1 = [OFHTTPCookie cookieWithName: @"foo"
					 value: @"bar"
					domain: @"nil.im"];
	TEST(@"+[cookiesWithResponseHeaderFields:forURL:] #1",
	    [[OFHTTPCookie cookiesWithResponseHeaderFields: [OFDictionary
	    dictionaryWithObject: @"foo=bar"
	    forKey: @"Set-Cookie"] forURL: URL]
	    isEqual: [OFArray arrayWithObject: cookie1]])

	cookie2 = [OFHTTPCookie cookieWithName: @"qux"
					 value: @"cookie"
					domain: @"nil.im"];
	TEST(@"+[cookiesWithResponseHeaderFields:forURL:] #2",
	    [[OFHTTPCookie cookiesWithResponseHeaderFields: [OFDictionary
	    dictionaryWithObject: @"foo=bar,qux=cookie"
	    forKey: @"Set-Cookie"] forURL: URL]
	    isEqual: [OFArray arrayWithObjects: cookie1, cookie2, nil]])

	cookie1.expires = [OFDate dateWithTimeIntervalSince1970: 1234567890];
	cookie2.expires = [OFDate dateWithTimeIntervalSince1970: 1234567890];
	cookie1.path = @"/x";
	cookie2.domain = @"webkeks.org";
	cookie2.path = @"/objfw";
	cookie2.secure = true;
	cookie2.HTTPOnly = true;
	[cookie2.extensions addObject: @"foo"];
	[cookie2.extensions addObject: @"bar"];
	TEST(@"+[cookiesWithResponseHeaderFields:forURL:] #3",
	    [(cookies = [OFHTTPCookie cookiesWithResponseHeaderFields:
	    [OFDictionary dictionaryWithObject:
	    @"foo=bar; Expires=Fri, 13 Feb 2009 23:31:30 GMT; Path=/x,"
	    @"qux=cookie; Expires=Fri, 13 Feb 2009 23:31:30 GMT; "
	    @"Domain=webkeks.org; Path=/objfw; Secure; HTTPOnly; foo; bar"
	    forKey: @"Set-Cookie"] forURL: URL]) isEqual:
	    [OFArray arrayWithObjects: cookie1, cookie2, nil]])

	TEST(@"+[requestHeaderFieldsWithCookies:]",
	    [[OFHTTPCookie requestHeaderFieldsWithCookies: cookies] isEqual:
	    [OFDictionary dictionaryWithObject: @"foo=bar; qux=cookie"
					forKey: @"Cookie"]])

	objc_autoreleasePoolPop(pool);
}
@end

Modified tests/OFIPXSocketTests.m from [d96f547fea] to [a26f3af451].

15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

#include "config.h"

#include <errno.h>

#import "TestsAppDelegate.h"

static OFString *module = @"OFIPXSocket";

@implementation TestsAppDelegate (OFIPXSocketTests)
- (void)IPXSocketTests
{
	void *pool = objc_autoreleasePoolPush();
	OFIPXSocket *sock;
	OFSocketAddress address1, address2;







|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

#include "config.h"

#include <errno.h>

#import "TestsAppDelegate.h"

static OFString *const module = @"OFIPXSocket";

@implementation TestsAppDelegate (OFIPXSocketTests)
- (void)IPXSocketTests
{
	void *pool = objc_autoreleasePoolPush();
	OFIPXSocket *sock;
	OFSocketAddress address1, address2;

Modified tests/OFInvocationTests.m from [475125e587] to [a2e3d6960f].

20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56

#if defined(HAVE_COMPLEX_H) && !defined(__STDC_NO_COMPLEX__)
# include <complex.h>
#endif

#import "TestsAppDelegate.h"

static OFString *module = @"OFInvocation";

struct test_struct {
	unsigned char c;
	unsigned int i;
};

@implementation TestsAppDelegate (OFInvocationTests)
- (struct test_struct)invocationTestMethod1: (unsigned char)c
					   : (unsigned int)i
					   : (struct test_struct *)ptr
					   : (struct test_struct)st
{
	return st;
}

- (void)invocationTests
{
	void *pool = objc_autoreleasePoolPush();
	SEL selector = @selector(invocationTestMethod1::::);
	OFMethodSignature *sig = [self methodSignatureForSelector: selector];
	OFInvocation *invocation;
	struct test_struct st, st2, *stp = &st, *stp2;
	unsigned const char c = 0xAA;
	unsigned char c2;
	const unsigned int i = 0x55555555;
	unsigned int i2;

	memset(&st, '\xFF', sizeof(st));
	st.c = 0x55;







|

|





|
|
|
|










|







20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56

#if defined(HAVE_COMPLEX_H) && !defined(__STDC_NO_COMPLEX__)
# include <complex.h>
#endif

#import "TestsAppDelegate.h"

static OFString *const module = @"OFInvocation";

struct TestStruct {
	unsigned char c;
	unsigned int i;
};

@implementation TestsAppDelegate (OFInvocationTests)
- (struct TestStruct)invocationTestMethod1: (unsigned char)c
					  : (unsigned int)i
					  : (struct TestStruct *)ptr
					  : (struct TestStruct)st
{
	return st;
}

- (void)invocationTests
{
	void *pool = objc_autoreleasePoolPush();
	SEL selector = @selector(invocationTestMethod1::::);
	OFMethodSignature *sig = [self methodSignatureForSelector: selector];
	OFInvocation *invocation;
	struct TestStruct st, st2, *stp = &st, *stp2;
	unsigned const char c = 0xAA;
	unsigned char c2;
	const unsigned int i = 0x55555555;
	unsigned int i2;

	memset(&st, '\xFF', sizeof(st));
	st.c = 0x55;

Modified tests/OFJSONTests.m from [15d8e0cc74] to [4a647fbb7e].

13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

40
41

42
43
44
45

46
47
48
49
50

51
52
53
54
55
56
57
58
 * file.
 */

#include "config.h"

#import "TestsAppDelegate.h"

static OFString *module = @"OFJSON";

@implementation TestsAppDelegate (JSONTests)
- (void)JSONTests
{
	void *pool = objc_autoreleasePoolPush();
	OFString *s = @"{\"foo\"\t:'b\\na\\r', \"x\":/*foo*/ [.5\r,0xF,null"
	    @"//bar\n,\"foo\",false]}";
	OFDictionary *d = [OFDictionary dictionaryWithKeysAndObjects:
	    @"foo", @"b\na\r",
	    @"x", [OFArray arrayWithObjects:
	    [OFNumber numberWithFloat: .5f],
	    [OFNumber numberWithInt: 0xF],
	    [OFNull null],
	    @"foo",
	    [OFNumber numberWithBool: false],
	    nil],
	    nil];

	TEST(@"-[objectByParsingJSON] #1", [s.objectByParsingJSON isEqual: d])


	TEST(@"-[JSONRepresentation]", [[d JSONRepresentation] isEqual:

	    @"{\"x\":[0.5,15,null,\"foo\",false],\"foo\":\"b\\na\\r\"}"])

	TEST(@"OFJSONRepresentationOptionPretty",
	    [[d JSONRepresentationWithOptions: OFJSONRepresentationOptionPretty]

	    isEqual: @"{\n\t\"x\": [\n\t\t0.5,\n\t\t15,\n\t\tnull,\n\t\t"
		     @"\"foo\",\n\t\tfalse\n\t],\n\t\"foo\": \"b\\na\\r\"\n}"])

	TEST(@"OFJSONRepresentationOptionJSON5",
	    [[d JSONRepresentationWithOptions: OFJSONRepresentationOptionJSON5]

	    isEqual: @"{x:[0.5,15,null,\"foo\",false],foo:\"b\\\na\\r\"}"])

	EXPECT_EXCEPTION(@"-[objectByParsingJSON] #2", OFInvalidJSONException,
	    [@"{" objectByParsingJSON])
	EXPECT_EXCEPTION(@"-[objectByParsingJSON] #3", OFInvalidJSONException,
	    [@"]" objectByParsingJSON])
	EXPECT_EXCEPTION(@"-[objectByParsingJSON] #4", OFInvalidJSONException,
	    [@"bar" objectByParsingJSON])







|





|
|
|


|
|
|
|
|
|


|
>

|
>



|
>
|
|


|
>
|







13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
 * file.
 */

#include "config.h"

#import "TestsAppDelegate.h"

static OFString *const module = @"OFJSON";

@implementation TestsAppDelegate (JSONTests)
- (void)JSONTests
{
	void *pool = objc_autoreleasePoolPush();
	OFString *string = @"{\"foo\"\t:'b\\na\\r', \"x\":/*foo*/ [.5\r,0xF,"
	    @"null//bar\n,\"foo\",false]}";
	OFDictionary *dict = [OFDictionary dictionaryWithKeysAndObjects:
	    @"foo", @"b\na\r",
	    @"x", [OFArray arrayWithObjects:
		[OFNumber numberWithFloat: .5f],
		[OFNumber numberWithInt: 0xF],
		[OFNull null],
		@"foo",
		[OFNumber numberWithBool: false],
		nil],
	    nil];

	TEST(@"-[objectByParsingJSON] #1",
	    [string.objectByParsingJSON isEqual: dict])

	TEST(@"-[JSONRepresentation]",
	    [[dict JSONRepresentation] isEqual:
	    @"{\"x\":[0.5,15,null,\"foo\",false],\"foo\":\"b\\na\\r\"}"])

	TEST(@"OFJSONRepresentationOptionPretty",
	    [[dict JSONRepresentationWithOptions:
	    OFJSONRepresentationOptionPretty] isEqual:
	    @"{\n\t\"x\": [\n\t\t0.5,\n\t\t15,\n\t\tnull,\n\t\t"
	    @"\"foo\",\n\t\tfalse\n\t],\n\t\"foo\": \"b\\na\\r\"\n}"])

	TEST(@"OFJSONRepresentationOptionJSON5",
	    [[dict JSONRepresentationWithOptions:
	    OFJSONRepresentationOptionJSON5] isEqual:
	    @"{x:[0.5,15,null,\"foo\",false],foo:\"b\\\na\\r\"}"])

	EXPECT_EXCEPTION(@"-[objectByParsingJSON] #2", OFInvalidJSONException,
	    [@"{" objectByParsingJSON])
	EXPECT_EXCEPTION(@"-[objectByParsingJSON] #3", OFInvalidJSONException,
	    [@"]" objectByParsingJSON])
	EXPECT_EXCEPTION(@"-[objectByParsingJSON] #4", OFInvalidJSONException,
	    [@"bar" objectByParsingJSON])

Modified tests/OFKernelEventObserverTests.m from [e1e120ef88] to [f4ab45b387].

26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
..
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
...
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
...
145
146
147
148
149
150
151
152

153
154
155
156
157
158
159
...
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
#endif
#ifdef HAVE_SELECT
# import "OFSelectKernelEventObserver.h"
#endif

#import "TestsAppDelegate.h"

#define EXPECTED_EVENTS 3

static OFString *module;

@interface ObserverTest: OFObject <OFKernelEventObserverDelegate>
{
@public
	TestsAppDelegate *_testsAppDelegate;
................................................................................
	OFDate *deadline;
	bool deadlineExceeded = false;

	[_testsAppDelegate outputTesting: @"-[observe] with listening socket"
				inModule: module];

	deadline = [OFDate dateWithTimeIntervalSinceNow: 1];
	while (_events < EXPECTED_EVENTS) {
		if (deadline.timeIntervalSinceNow < 0) {
			deadlineExceeded = true;
			break;
		}

		[_observer observeForTimeInterval: 0.01];
	}
................................................................................
	else {
		[_testsAppDelegate
		    outputFailure: @"-[observe] not exceeding deadline"
			 inModule: module];
		_fails++;
	}

	if (_events == EXPECTED_EVENTS)
		[_testsAppDelegate
		    outputSuccess: @"-[observe] handling all events"
			 inModule: module];
	else {
		[_testsAppDelegate
		    outputFailure: @"-[observe] handling all events"
			 inModule: module];
		_fails++;
	}
}

- (void)objectIsReadyForReading: (id)object
{
	char buf;

	switch (_events++) {
	case 0:
		if (object == _server)
			[_testsAppDelegate
			    outputSuccess: @"-[observe] with listening socket"
				 inModule: module];
................................................................................
		[_testsAppDelegate
		    outputTesting: @"-[observe] with data ready to read"
			 inModule: module];

		break;
	case 1:
		if (object == _accepted &&
		    [object readIntoBuffer: &buf length: 1] == 1 && buf == '0')

			[_testsAppDelegate
			    outputSuccess: @"-[observe] with data ready to read"
				 inModule: module];
		else {
			[_testsAppDelegate
			    outputFailure: @"-[observe] with data ready to read"
				 inModule: module];
................................................................................
		[_testsAppDelegate
		    outputTesting: @"-[observe] with closed connection"
			 inModule: module];

		break;
	case 2:
		if (object == _accepted &&
		    [object readIntoBuffer: &buf length: 1] == 0)
			[_testsAppDelegate
			    outputSuccess: @"-[observe] with closed connection"
				 inModule: module];
		else {
			[_testsAppDelegate
			    outputFailure: @"-[observe] with closed connection"
				 inModule: module];







|







 







|







 







|













|







 







|
>







 







|







26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
..
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
...
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
...
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
...
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
#endif
#ifdef HAVE_SELECT
# import "OFSelectKernelEventObserver.h"
#endif

#import "TestsAppDelegate.h"

static const size_t numExpectedEvents = 3;

static OFString *module;

@interface ObserverTest: OFObject <OFKernelEventObserverDelegate>
{
@public
	TestsAppDelegate *_testsAppDelegate;
................................................................................
	OFDate *deadline;
	bool deadlineExceeded = false;

	[_testsAppDelegate outputTesting: @"-[observe] with listening socket"
				inModule: module];

	deadline = [OFDate dateWithTimeIntervalSinceNow: 1];
	while (_events < numExpectedEvents) {
		if (deadline.timeIntervalSinceNow < 0) {
			deadlineExceeded = true;
			break;
		}

		[_observer observeForTimeInterval: 0.01];
	}
................................................................................
	else {
		[_testsAppDelegate
		    outputFailure: @"-[observe] not exceeding deadline"
			 inModule: module];
		_fails++;
	}

	if (_events == numExpectedEvents)
		[_testsAppDelegate
		    outputSuccess: @"-[observe] handling all events"
			 inModule: module];
	else {
		[_testsAppDelegate
		    outputFailure: @"-[observe] handling all events"
			 inModule: module];
		_fails++;
	}
}

- (void)objectIsReadyForReading: (id)object
{
	char buffer;

	switch (_events++) {
	case 0:
		if (object == _server)
			[_testsAppDelegate
			    outputSuccess: @"-[observe] with listening socket"
				 inModule: module];
................................................................................
		[_testsAppDelegate
		    outputTesting: @"-[observe] with data ready to read"
			 inModule: module];

		break;
	case 1:
		if (object == _accepted &&
		    [object readIntoBuffer: &buffer length: 1] == 1 &&
		    buffer == '0')
			[_testsAppDelegate
			    outputSuccess: @"-[observe] with data ready to read"
				 inModule: module];
		else {
			[_testsAppDelegate
			    outputFailure: @"-[observe] with data ready to read"
				 inModule: module];
................................................................................
		[_testsAppDelegate
		    outputTesting: @"-[observe] with closed connection"
			 inModule: module];

		break;
	case 2:
		if (object == _accepted &&
		    [object readIntoBuffer: &buffer length: 1] == 0)
			[_testsAppDelegate
			    outputSuccess: @"-[observe] with closed connection"
				 inModule: module];
		else {
			[_testsAppDelegate
			    outputFailure: @"-[observe] with closed connection"
				 inModule: module];

Modified tests/OFListTests.m from [ede47645fa] to [8b9464c149].

27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
..
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
...
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
@implementation TestsAppDelegate (OFListTests)
- (void)listTests
{
	void *pool = objc_autoreleasePoolPush();
	OFList *list;
	OFEnumerator *enumerator;
	OFListItem iter;
	OFString *obj;
	size_t i;
	bool ok;

	TEST(@"+[list]", (list = [OFList list]))

	TEST(@"-[appendObject:]", [list appendObject: strings[0]] &&
	    [list appendObject: strings[1]] && [list appendObject: strings[2]])
................................................................................
	    [list.description isEqual: @"[\n\tFoo,\n\tBar,\n\tBaz\n]"])

	TEST(@"-[objectEnumerator]", (enumerator = [list objectEnumerator]))

	iter = list.firstListItem;
	i = 0;
	ok = true;
	while ((obj = [enumerator nextObject]) != nil) {
		if (![obj isEqual: OFListItemObject(iter)])
			ok = false;

		iter = OFListItemNext(iter);
		i++;
	}

	if (list.count != i)
................................................................................

	[list prependObject: strings[0]];

	iter = list.firstListItem;
	i = 0;
	ok = true;

	for (OFString *object in list) {
		if (![object isEqual: OFListItemObject(iter)])
			ok = false;

		iter = OFListItemNext(iter);
		i++;
	}

	if (list.count != i)
		ok = false;

	TEST(@"Fast Enumeration", ok)

	ok = false;
	@try {
		for (OFString *object in list) {
			(void)object;

			[list removeListItem: list.lastListItem];
		}
	} @catch (OFEnumerationMutationException *e) {
		ok = true;
	}

	TEST(@"Detection of mutation during Fast Enumeration", ok)

	objc_autoreleasePoolPop(pool);
}
@end







|







 







|
|







 







|
|













|
|












27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
..
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
...
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
@implementation TestsAppDelegate (OFListTests)
- (void)listTests
{
	void *pool = objc_autoreleasePoolPush();
	OFList *list;
	OFEnumerator *enumerator;
	OFListItem iter;
	OFString *object;
	size_t i;
	bool ok;

	TEST(@"+[list]", (list = [OFList list]))

	TEST(@"-[appendObject:]", [list appendObject: strings[0]] &&
	    [list appendObject: strings[1]] && [list appendObject: strings[2]])
................................................................................
	    [list.description isEqual: @"[\n\tFoo,\n\tBar,\n\tBaz\n]"])

	TEST(@"-[objectEnumerator]", (enumerator = [list objectEnumerator]))

	iter = list.firstListItem;
	i = 0;
	ok = true;
	while ((object = [enumerator nextObject]) != nil) {
		if (![object isEqual: OFListItemObject(iter)])
			ok = false;

		iter = OFListItemNext(iter);
		i++;
	}

	if (list.count != i)
................................................................................

	[list prependObject: strings[0]];

	iter = list.firstListItem;
	i = 0;
	ok = true;

	for (OFString *object_ in list) {
		if (![object_ isEqual: OFListItemObject(iter)])
			ok = false;

		iter = OFListItemNext(iter);
		i++;
	}

	if (list.count != i)
		ok = false;

	TEST(@"Fast Enumeration", ok)

	ok = false;
	@try {
		for (OFString *object_ in list) {
			(void)object_;

			[list removeListItem: list.lastListItem];
		}
	} @catch (OFEnumerationMutationException *e) {
		ok = true;
	}

	TEST(@"Detection of mutation during Fast Enumeration", ok)

	objc_autoreleasePoolPop(pool);
}
@end

Modified tests/OFMD5HashTests.m from [73092aedf1] to [28e9fd3aee].

17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56

#include <string.h>

#import "TestsAppDelegate.h"

static OFString *module = @"OFMD5Hash";

const uint8_t testfile_md5[16] =
	"\x00\x8B\x9D\x1B\x58\xDF\xF8\xFE\xEE\xF3\xAE\x8D\xBB\x68\x2D\x38";

@implementation TestsAppDelegate (OFMD5HashTests)
- (void)MD5HashTests
{
	void *pool = objc_autoreleasePoolPush();
	OFMD5Hash *md5, *copy;
	OFFile *f = [OFFile fileWithPath: @"testfile.bin" mode: @"r"];

	TEST(@"+[hashWithAllowsSwappableMemory:]",
	    (md5 = [OFMD5Hash hashWithAllowsSwappableMemory: true]))

	while (!f.atEndOfStream) {
		char buf[64];
		size_t len = [f readIntoBuffer: buf length: 64];
		[md5 updateWithBuffer: buf length: len];
	}
	[f close];

	TEST(@"-[copy]", (copy = [[md5 copy] autorelease]))

	TEST(@"-[digest]",
	    memcmp(md5.digest, testfile_md5, 16) == 0 &&
	    memcmp(copy.digest, testfile_md5, 16) == 0)

	EXPECT_EXCEPTION(@"Detect invalid call of "
	    @"-[updateWithBuffer:length]", OFHashAlreadyCalculatedException,
	    [md5 updateWithBuffer: "" length: 1])

	objc_autoreleasePoolPop(pool);
}
@end







|
|





|
|


|

|
|
|
|

|

|


|
|



|




17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56

#include <string.h>

#import "TestsAppDelegate.h"

static OFString *module = @"OFMD5Hash";

const uint8_t testFileMD5[16] =
    "\x00\x8B\x9D\x1B\x58\xDF\xF8\xFE\xEE\xF3\xAE\x8D\xBB\x68\x2D\x38";

@implementation TestsAppDelegate (OFMD5HashTests)
- (void)MD5HashTests
{
	void *pool = objc_autoreleasePoolPush();
	OFMD5Hash *MD5, *MD5Copy;
	OFFile *file = [OFFile fileWithPath: @"testfile.bin" mode: @"r"];

	TEST(@"+[hashWithAllowsSwappableMemory:]",
	    (MD5 = [OFMD5Hash hashWithAllowsSwappableMemory: true]))

	while (!file.atEndOfStream) {
		char buffer[64];
		size_t length = [file readIntoBuffer: buffer length: 64];
		[MD5 updateWithBuffer: buffer length: length];
	}
	[file close];

	TEST(@"-[copy]", (MD5Copy = [[MD5 copy] autorelease]))

	TEST(@"-[digest]",
	    memcmp(MD5.digest, testFileMD5, 16) == 0 &&
	    memcmp(MD5Copy.digest, testFileMD5, 16) == 0)

	EXPECT_EXCEPTION(@"Detect invalid call of "
	    @"-[updateWithBuffer:length]", OFHashAlreadyCalculatedException,
	    [MD5 updateWithBuffer: "" length: 1])

	objc_autoreleasePoolPop(pool);
}
@end

Modified tests/OFMethodSignatureTests.m from [364a3b706f] to [ebd654aa45].

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
..
69
70
71
72
73
74
75
76
77
78
79
80

81
82
83
84
85

86
87
88
89
90
91
92
93
94
95

96
97
98
99
100

101
102
103
104
105
106
107
108
109
110
...
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177

#if !defined(__STDC_NO_COMPLEX__) && defined(HAVE_COMPLEX_H)
# include <complex.h>
#endif

#import "TestsAppDelegate.h"

static OFString *module = @"OFMethodSignature";

struct test1_struct {
	char c;
	int i;
	char d;
};

struct test2_struct {
	char c;
	struct {
		short s;
		int i;
	} st;
	union {
		char c;
		int i;
	} u;
	double d;
};

#if !defined(__STDC_NO_COMPLEX__) && defined(HAVE_COMPLEX_H)
struct test3_struct {
	char c;
	complex double cd;
};
#endif

union test3_union {
	char c;
	int i;
	double d;
};

union test4_union {
	char c;
	struct {
		short x, y;
	} st;
	int i;
	union {
		float f;
................................................................................
	} u;
};

@implementation TestsAppDelegate (OFMethodSignatureTests)
- (void)methodSignatureTests
{
	void *pool = objc_autoreleasePoolPush();
	OFMethodSignature *ms;

	TEST(@"-[signatureWithObjCTypes:] #1",
	    (ms = [OFMethodSignature signatureWithObjCTypes:
	    "i28@0:8S16*20"]) && ms.numberOfArguments == 4 &&

	    strcmp(ms.methodReturnType, "i") == 0 &&
	    strcmp([ms argumentTypeAtIndex: 0], "@") == 0 &&
	    strcmp([ms argumentTypeAtIndex: 1], ":") == 0 &&
	    strcmp([ms argumentTypeAtIndex: 2], "S") == 0 &&
	    strcmp([ms argumentTypeAtIndex: 3], "*") == 0 &&

	    ms.frameLength == 28 && [ms argumentOffsetAtIndex: 0] == 0 &&
	    [ms argumentOffsetAtIndex: 1] == 8 &&
	    [ms argumentOffsetAtIndex: 2] == 16 &&
	    [ms argumentOffsetAtIndex: 3] == 20)

	TEST(@"-[signatureWithObjCTypes:] #2",
	    (ms = [OFMethodSignature signatureWithObjCTypes:
	    "{s0=csi(u1={s2=iii{s3=(u4=ic^v*)}})}24@0:8"
	    "^{s0=csi(u1={s2=iii{s3=(u4=ic^v*)}})}16"]) &&
	    ms.numberOfArguments == 3 && strcmp(ms.methodReturnType,

	    "{s0=csi(u1={s2=iii{s3=(u4=ic^v*)}})}") == 0 &&
	    strcmp([ms argumentTypeAtIndex: 0], "@") == 0 &&
	    strcmp([ms argumentTypeAtIndex: 1], ":") == 0 &&
	    strcmp([ms argumentTypeAtIndex: 2],
	    "^{s0=csi(u1={s2=iii{s3=(u4=ic^v*)}})}") == 0 &&

	    ms.frameLength == 24 && [ms argumentOffsetAtIndex: 0] == 0 &&
	    [ms argumentOffsetAtIndex: 1] == 8 &&
	    [ms argumentOffsetAtIndex: 2] == 16)

	EXPECT_EXCEPTION(@"-[signatureWithObjCTypes:] #3",
	    OFInvalidFormatException,
	    [OFMethodSignature signatureWithObjCTypes: "{ii"])

	EXPECT_EXCEPTION(@"-[signatureWithObjCTypes:] #4",
	    OFInvalidFormatException,
................................................................................
	    [OFMethodSignature signatureWithObjCTypes: "0"])

	EXPECT_EXCEPTION(@"-[signatureWithObjCTypes:] #6",
	    OFInvalidFormatException,
	    [OFMethodSignature signatureWithObjCTypes: "{{}0"])

	TEST(@"OFSizeOfTypeEncoding() #1",
	    OFSizeOfTypeEncoding(@encode(struct test1_struct)) ==
	    sizeof(struct test1_struct))

	TEST(@"OFSizeOfTypeEncoding() #2",
	    OFSizeOfTypeEncoding(@encode(struct test2_struct)) ==
	    sizeof(struct test2_struct))

#if !defined(__STDC_NO_COMPLEX__) && defined(HAVE_COMPLEX_H) && \
    OF_GCC_VERSION >= 402
	TEST(@"OFSizeOfTypeEncoding() #3",
	    OFSizeOfTypeEncoding(@encode(struct test3_struct)) ==
	    sizeof(struct test3_struct))
#endif

	TEST(@"OFSizeOfTypeEncoding() #4",
	    OFSizeOfTypeEncoding(@encode(union test3_union)) ==
	    sizeof(union test3_union))

	TEST(@"OFSizeOfTypeEncoding() #5",
	    OFSizeOfTypeEncoding(@encode(union test4_union)) ==
	    sizeof(union test4_union))

	TEST(@"OFSizeOfTypeEncoding() #6",
	    OFSizeOfTypeEncoding(@encode(struct test1_struct [5])) ==
	    sizeof(struct test1_struct [5]))

	TEST(@"OFAlignmentOfTypeEncoding() #1",
	    OFAlignmentOfTypeEncoding(@encode(struct test1_struct)) ==
	    OF_ALIGNOF(struct test1_struct))

	TEST(@"OFAlignmentOfTypeEncoding() #2",
	    OFAlignmentOfTypeEncoding(@encode(struct test2_struct)) ==
	    OF_ALIGNOF(struct test2_struct))

#if !defined(__STDC_NO_COMPLEX__) && defined(HAVE_COMPLEX_H) && \
    OF_GCC_VERSION >= 402
	TEST(@"OFAlignmentOfTypeEncoding() #3",
	    OFAlignmentOfTypeEncoding(@encode(struct test3_struct)) ==
	    OF_ALIGNOF(struct test3_struct))
#endif

	TEST(@"OFAlignmentOfTypeEncoding() #4",
	    OFAlignmentOfTypeEncoding(@encode(union test3_union)) ==
	    OF_ALIGNOF(union test3_union))

	TEST(@"OFAlignmentOfTypeEncoding() #5",
	    OFAlignmentOfTypeEncoding(@encode(union test4_union)) ==
	    OF_ALIGNOF(union test4_union))

	TEST(@"OFAlignmentOfTypeEncoding() #6",
	    OFAlignmentOfTypeEncoding(@encode(struct test1_struct [5])) ==
	    OF_ALIGNOF(struct test1_struct [5]))

	objc_autoreleasePoolPop(pool);
}
@end







|

|





|













|





|





|







 







|


|
|
>
|
|
|
|
|
>
|
|
|
|


|


|
>

|
|
|

>
|
|
|







 







|
|


|
|




|
|



|
|


|
|


|
|


|
|


|
|




|
|



|
|


|
|


|
|




19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
..
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
...
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181

#if !defined(__STDC_NO_COMPLEX__) && defined(HAVE_COMPLEX_H)
# include <complex.h>
#endif

#import "TestsAppDelegate.h"

static OFString *const module = @"OFMethodSignature";

struct Test1Struct {
	char c;
	int i;
	char d;
};

struct Test2Struct {
	char c;
	struct {
		short s;
		int i;
	} st;
	union {
		char c;
		int i;
	} u;
	double d;
};

#if !defined(__STDC_NO_COMPLEX__) && defined(HAVE_COMPLEX_H)
struct Test3Struct {
	char c;
	complex double cd;
};
#endif

union Test3Union {
	char c;
	int i;
	double d;
};

union Test4Union {
	char c;
	struct {
		short x, y;
	} st;
	int i;
	union {
		float f;
................................................................................
	} u;
};

@implementation TestsAppDelegate (OFMethodSignatureTests)
- (void)methodSignatureTests
{
	void *pool = objc_autoreleasePoolPush();
	OFMethodSignature *methodSignature;

	TEST(@"-[signatureWithObjCTypes:] #1",
	    (methodSignature = [OFMethodSignature signatureWithObjCTypes:
	    "i28@0:8S16*20"]) &&
	    methodSignature.numberOfArguments == 4 &&
	    strcmp(methodSignature.methodReturnType, "i") == 0 &&
	    strcmp([methodSignature argumentTypeAtIndex: 0], "@") == 0 &&
	    strcmp([methodSignature argumentTypeAtIndex: 1], ":") == 0 &&
	    strcmp([methodSignature argumentTypeAtIndex: 2], "S") == 0 &&
	    strcmp([methodSignature argumentTypeAtIndex: 3], "*") == 0 &&
	    methodSignature.frameLength == 28 &&
	    [methodSignature argumentOffsetAtIndex: 0] == 0 &&
	    [methodSignature argumentOffsetAtIndex: 1] == 8 &&
	    [methodSignature argumentOffsetAtIndex: 2] == 16 &&
	    [methodSignature argumentOffsetAtIndex: 3] == 20)

	TEST(@"-[signatureWithObjCTypes:] #2",
	    (methodSignature = [OFMethodSignature signatureWithObjCTypes:
	    "{s0=csi(u1={s2=iii{s3=(u4=ic^v*)}})}24@0:8"
	    "^{s0=csi(u1={s2=iii{s3=(u4=ic^v*)}})}16"]) &&
	    methodSignature.numberOfArguments == 3 &&
	    strcmp(methodSignature.methodReturnType,
	    "{s0=csi(u1={s2=iii{s3=(u4=ic^v*)}})}") == 0 &&
	    strcmp([methodSignature argumentTypeAtIndex: 0], "@") == 0 &&
	    strcmp([methodSignature argumentTypeAtIndex: 1], ":") == 0 &&
	    strcmp([methodSignature argumentTypeAtIndex: 2],
	    "^{s0=csi(u1={s2=iii{s3=(u4=ic^v*)}})}") == 0 &&
	    methodSignature.frameLength == 24 &&
	    [methodSignature argumentOffsetAtIndex: 0] == 0 &&
	    [methodSignature argumentOffsetAtIndex: 1] == 8 &&
	    [methodSignature argumentOffsetAtIndex: 2] == 16)

	EXPECT_EXCEPTION(@"-[signatureWithObjCTypes:] #3",
	    OFInvalidFormatException,
	    [OFMethodSignature signatureWithObjCTypes: "{ii"])

	EXPECT_EXCEPTION(@"-[signatureWithObjCTypes:] #4",
	    OFInvalidFormatException,
................................................................................
	    [OFMethodSignature signatureWithObjCTypes: "0"])

	EXPECT_EXCEPTION(@"-[signatureWithObjCTypes:] #6",
	    OFInvalidFormatException,
	    [OFMethodSignature signatureWithObjCTypes: "{{}0"])

	TEST(@"OFSizeOfTypeEncoding() #1",
	    OFSizeOfTypeEncoding(@encode(struct Test1Struct)) ==
	    sizeof(struct Test1Struct))

	TEST(@"OFSizeOfTypeEncoding() #2",
	    OFSizeOfTypeEncoding(@encode(struct Test2Struct)) ==
	    sizeof(struct Test2Struct))

#if !defined(__STDC_NO_COMPLEX__) && defined(HAVE_COMPLEX_H) && \
    OF_GCC_VERSION >= 402
	TEST(@"OFSizeOfTypeEncoding() #3",
	    OFSizeOfTypeEncoding(@encode(struct Test3Struct)) ==
	    sizeof(struct Test3Struct))
#endif

	TEST(@"OFSizeOfTypeEncoding() #4",
	    OFSizeOfTypeEncoding(@encode(union Test3Union)) ==
	    sizeof(union Test3Union))

	TEST(@"OFSizeOfTypeEncoding() #5",
	    OFSizeOfTypeEncoding(@encode(union Test4Union)) ==
	    sizeof(union Test4Union))

	TEST(@"OFSizeOfTypeEncoding() #6",
	    OFSizeOfTypeEncoding(@encode(struct Test1Struct [5])) ==
	    sizeof(struct Test1Struct [5]))

	TEST(@"OFAlignmentOfTypeEncoding() #1",
	    OFAlignmentOfTypeEncoding(@encode(struct Test1Struct)) ==
	    OF_ALIGNOF(struct Test1Struct))

	TEST(@"OFAlignmentOfTypeEncoding() #2",
	    OFAlignmentOfTypeEncoding(@encode(struct Test2Struct)) ==
	    OF_ALIGNOF(struct Test2Struct))

#if !defined(__STDC_NO_COMPLEX__) && defined(HAVE_COMPLEX_H) && \
    OF_GCC_VERSION >= 402
	TEST(@"OFAlignmentOfTypeEncoding() #3",
	    OFAlignmentOfTypeEncoding(@encode(struct Test3Struct)) ==
	    OF_ALIGNOF(struct Test3Struct))
#endif

	TEST(@"OFAlignmentOfTypeEncoding() #4",
	    OFAlignmentOfTypeEncoding(@encode(union Test3Union)) ==
	    OF_ALIGNOF(union Test3Union))

	TEST(@"OFAlignmentOfTypeEncoding() #5",
	    OFAlignmentOfTypeEncoding(@encode(union Test4Union)) ==
	    OF_ALIGNOF(union Test4Union))

	TEST(@"OFAlignmentOfTypeEncoding() #6",
	    OFAlignmentOfTypeEncoding(@encode(struct Test1Struct [5])) ==
	    OF_ALIGNOF(struct Test1Struct [5]))

	objc_autoreleasePoolPop(pool);
}
@end

Modified tests/OFNumberTests.m from [92564f033d] to [c0de3f5f8b].

13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
 * file.
 */

#include "config.h"

#import "TestsAppDelegate.h"

static OFString *module = @"OFNumber";

@implementation TestsAppDelegate (OFNumberTests)
- (void)numberTests
{
	void *pool = objc_autoreleasePoolPush();
	OFNumber *num;

	TEST(@"+[numberWithLongLong:]",
	    (num = [OFNumber numberWithLongLong: 123456789]))

	TEST(@"-[isEqual:]",
	    [num isEqual: [OFNumber numberWithLong: 123456789]])

	TEST(@"-[hash]", num.hash == 0x82D8BC42)

	TEST(@"-[charValue]", num.charValue == 21)

	TEST(@"-[doubleValue]", num.doubleValue == 123456789.L)

	TEST(@"signed char minimum & maximum unmodified",
	    (num = [OFNumber numberWithChar: SCHAR_MIN]) &&
	    num.charValue == SCHAR_MIN &&
	    (num = [OFNumber numberWithChar: SCHAR_MAX]) &&
	    num.charValue == SCHAR_MAX)

	TEST(@"short minimum & maximum unmodified",
	    (num = [OFNumber numberWithShort: SHRT_MIN]) &&
	    num.shortValue == SHRT_MIN &&
	    (num = [OFNumber numberWithShort: SHRT_MAX]) &&
	    num.shortValue == SHRT_MAX)

	TEST(@"int minimum & maximum unmodified",
	    (num = [OFNumber numberWithInt: INT_MIN]) &&
	    num.intValue == INT_MIN &&
	    (num = [OFNumber numberWithInt: INT_MAX]) &&
	    num.intValue == INT_MAX)

	TEST(@"long minimum & maximum unmodified",
	    (num = [OFNumber numberWithLong: LONG_MIN]) &&
	    num.longValue == LONG_MIN &&
	    (num = [OFNumber numberWithLong: LONG_MAX]) &&
	    num.longValue == LONG_MAX)

	TEST(@"long long minimum & maximum unmodified",
	    (num = [OFNumber numberWithLongLong: LLONG_MIN]) &&
	    num.longLongValue == LLONG_MIN &&
	    (num = [OFNumber numberWithLongLong: LLONG_MAX]) &&
	    num.longLongValue == LLONG_MAX)

	TEST(@"unsigned char maximum unmodified",
	    (num = [OFNumber numberWithUnsignedChar: UCHAR_MAX]) &&
	    num.unsignedCharValue == UCHAR_MAX)

	TEST(@"unsigned short maximum unmodified",
	    (num = [OFNumber numberWithUnsignedShort: USHRT_MAX]) &&
	    num.unsignedShortValue == USHRT_MAX)

	TEST(@"unsigned int maximum unmodified",
	    (num = [OFNumber numberWithUnsignedInt: UINT_MAX]) &&
	    num.unsignedIntValue == UINT_MAX)

	TEST(@"unsigned long maximum unmodified",
	    (num = [OFNumber numberWithUnsignedLong: ULONG_MAX]) &&
	    num.unsignedLongValue == ULONG_MAX)

	TEST(@"unsigned long long maximum unmodified",
	    (num = [OFNumber numberWithUnsignedLongLong: ULLONG_MAX]) &&
	    num.unsignedLongLongValue == ULLONG_MAX)

	objc_autoreleasePoolPop(pool);
}
@end







|





|


|


|

|

|

|


|
|
|
|


|
|
|
|


|
|
|
|


|
|
|
|


|
|
|
|


|
|


|
|


|
|


|
|


|
|




13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
 * file.
 */

#include "config.h"

#import "TestsAppDelegate.h"

static OFString *const module = @"OFNumber";

@implementation TestsAppDelegate (OFNumberTests)
- (void)numberTests
{
	void *pool = objc_autoreleasePoolPush();
	OFNumber *number;

	TEST(@"+[numberWithLongLong:]",
	    (number = [OFNumber numberWithLongLong: 123456789]))

	TEST(@"-[isEqual:]",
	    [number isEqual: [OFNumber numberWithLong: 123456789]])

	TEST(@"-[hash]", number.hash == 0x82D8BC42)

	TEST(@"-[charValue]", number.charValue == 21)

	TEST(@"-[doubleValue]", number.doubleValue == 123456789.L)

	TEST(@"signed char minimum & maximum unmodified",
	    (number = [OFNumber numberWithChar: SCHAR_MIN]) &&
	    number.charValue == SCHAR_MIN &&
	    (number = [OFNumber numberWithChar: SCHAR_MAX]) &&
	    number.charValue == SCHAR_MAX)

	TEST(@"short minimum & maximum unmodified",
	    (number = [OFNumber numberWithShort: SHRT_MIN]) &&
	    number.shortValue == SHRT_MIN &&
	    (number = [OFNumber numberWithShort: SHRT_MAX]) &&
	    number.shortValue == SHRT_MAX)

	TEST(@"int minimum & maximum unmodified",
	    (number = [OFNumber numberWithInt: INT_MIN]) &&
	    number.intValue == INT_MIN &&
	    (number = [OFNumber numberWithInt: INT_MAX]) &&
	    number.intValue == INT_MAX)

	TEST(@"long minimum & maximum unmodified",
	    (number = [OFNumber numberWithLong: LONG_MIN]) &&
	    number.longValue == LONG_MIN &&
	    (number = [OFNumber numberWithLong: LONG_MAX]) &&
	    number.longValue == LONG_MAX)

	TEST(@"long long minimum & maximum unmodified",
	    (number = [OFNumber numberWithLongLong: LLONG_MIN]) &&
	    number.longLongValue == LLONG_MIN &&
	    (number = [OFNumber numberWithLongLong: LLONG_MAX]) &&
	    number.longLongValue == LLONG_MAX)

	TEST(@"unsigned char maximum unmodified",
	    (number = [OFNumber numberWithUnsignedChar: UCHAR_MAX]) &&
	    number.unsignedCharValue == UCHAR_MAX)

	TEST(@"unsigned short maximum unmodified",
	    (number = [OFNumber numberWithUnsignedShort: USHRT_MAX]) &&
	    number.unsignedShortValue == USHRT_MAX)

	TEST(@"unsigned int maximum unmodified",
	    (number = [OFNumber numberWithUnsignedInt: UINT_MAX]) &&
	    number.unsignedIntValue == UINT_MAX)

	TEST(@"unsigned long maximum unmodified",
	    (number = [OFNumber numberWithUnsignedLong: ULONG_MAX]) &&
	    number.unsignedLongValue == ULONG_MAX)

	TEST(@"unsigned long long maximum unmodified",
	    (number = [OFNumber numberWithUnsignedLongLong: ULLONG_MAX]) &&
	    number.unsignedLongLongValue == ULLONG_MAX)

	objc_autoreleasePoolPop(pool);
}
@end

Modified tests/OFObjectTests.m from [15af30b63f] to [84ff5d698c].

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
..
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
..
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118

119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190



191

192
193

194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216

#if (defined(OF_DRAGONFLYBSD) && defined(__LP64__)) || defined(OF_NINTENDO_3DS)
# define TOO_BIG (SIZE_MAX / 3)
#else
# define TOO_BIG (SIZE_MAX - 128)
#endif

static OFString *module = @"OFObject";

@interface MyObj: OFObject
{
	id _objectValue;
	Class _classValue;
	bool _boolValue;
	char _charValue;
	short _shortValue;
	int _intValue;
................................................................................
@property (nonatomic) unsigned int unsignedIntValue;
@property (nonatomic) unsigned long unsignedLongValue;
@property (nonatomic) unsigned long long unsignedLongLongValue;
@property (nonatomic) float floatValue;
@property (nonatomic) double doubleValue;
@end

@implementation MyObj
@synthesize objectValue = _objectValue, classValue = _classValue;
@synthesize boolValue = _boolValue, charValue = _charValue;
@synthesize shortValue = _shortValue, intValue = _intValue;
@synthesize longValue = _longValue, longLongValue = _longLongValue;
@synthesize unsignedCharValue = _unsignedCharValue;
@synthesize unsignedShortValue = _unsignedShortValue;
@synthesize unsignedIntValue = _unsignedIntValue;
................................................................................
}
@end

@implementation TestsAppDelegate (OFObjectTests)
- (void)objectTests
{
	void *pool = objc_autoreleasePoolPush();
	OFObject *o;
	MyObj *m;

	TEST(@"+[description]",
	    [[OFObject description] isEqual: @"OFObject"] &&
	    [[MyObj description] isEqual: @"MyObj"])

	o = [[[OFObject alloc] init] autorelease];
	m = [[[MyObj alloc] init] autorelease];

	TEST(@"-[description]",
	    [o.description isEqual: @"<OFObject>"] &&
	    [m.description isEqual: @"<MyObj>"])

	m.objectValue = @"Hello";
	m.classValue = [m class];
	TEST(@"-[valueForKey:]",
	    [[m valueForKey: @"objectValue"] isEqual: @"Hello"] &&
	    [[m valueForKey: @"classValue"] isEqual: m.class] &&
	    [[m valueForKey: @"class"] isEqual: m.class])

	EXPECT_EXCEPTION(@"-[valueForKey:] with undefined key",
	    OFUndefinedKeyException, [m valueForKey: @"undefined"])

	TEST(@"-[setValue:forKey:]",
	    R([m setValue: @"World" forKey: @"objectValue"]) &&
	    R([m setValue: [OFObject class] forKey: @"classValue"]) &&
	    [m.objectValue isEqual: @"World"] &&
	    [m.classValue isEqual: [OFObject class]])

	EXPECT_EXCEPTION(@"-[setValue:forKey:] with undefined key",

	    OFUndefinedKeyException, [m setValue: @"x" forKey: @"undefined"])

	m.boolValue = 1;
	m.charValue = 2;
	m.shortValue = 3;
	m.intValue = 4;
	m.longValue = 5;
	m.longLongValue = 6;
	m.unsignedCharValue = 7;
	m.unsignedShortValue = 8;
	m.unsignedIntValue = 9;
	m.unsignedLongValue = 10;
	m.unsignedLongLongValue = 11;
	m.floatValue = 12;
	m.doubleValue = 13;
	TEST(@"Auto-wrapping of -[valueForKey:]",
	    [[m valueForKey: @"boolValue"] isEqual:
	    [OFNumber numberWithBool: 1]] &&
	    [[m valueForKey: @"charValue"] isEqual:
	    [OFNumber numberWithChar: 2]] &&
	    [[m valueForKey: @"shortValue"] isEqual:
	    [OFNumber numberWithShort: 3]] &&
	    [[m valueForKey: @"intValue"] isEqual:
	    [OFNumber numberWithInt: 4]] &&
	    [[m valueForKey: @"longValue"] isEqual:
	    [OFNumber numberWithLong: 5]] &&
	    [[m valueForKey: @"longLongValue"] isEqual:
	    [OFNumber numberWithLongLong: 6]] &&
	    [[m valueForKey: @"unsignedCharValue"] isEqual:
	    [OFNumber numberWithUnsignedChar: 7]] &&
	    [[m valueForKey: @"unsignedShortValue"] isEqual:
	    [OFNumber numberWithUnsignedShort: 8]] &&
	    [[m valueForKey: @"unsignedIntValue"] isEqual:
	    [OFNumber numberWithUnsignedInt: 9]] &&
	    [[m valueForKey: @"unsignedLongValue"] isEqual:
	    [OFNumber numberWithUnsignedLong: 10]] &&
	    [[m valueForKey: @"unsignedLongLongValue"] isEqual:
	    [OFNumber numberWithUnsignedLongLong: 11]] &&
	    [[m valueForKey: @"floatValue"] isEqual:
	    [OFNumber numberWithFloat: 12]] &&
	    [[m valueForKey: @"doubleValue"] isEqual:
	    [OFNumber numberWithDouble: 13]])

	TEST(@"Auto-wrapping of -[setValue:forKey:]",
	    R([m setValue: [OFNumber numberWithBool: 0]
		   forKey: @"boolValue"]) &&
	    R([m setValue: [OFNumber numberWithChar: 10]
		   forKey: @"charValue"]) &&
	    R([m setValue: [OFNumber numberWithShort: 20]
		   forKey: @"shortValue"]) &&
	    R([m setValue: [OFNumber numberWithInt: 30]
		   forKey: @"intValue"]) &&
	    R([m setValue: [OFNumber numberWithLong: 40]
		   forKey: @"longValue"]) &&
	    R([m setValue: [OFNumber numberWithLongLong: 50]
		   forKey: @"longLongValue"]) &&
	    R([m setValue: [OFNumber numberWithUnsignedChar: 60]
		   forKey: @"unsignedCharValue"]) &&
	    R([m setValue: [OFNumber numberWithUnsignedShort: 70]
		   forKey: @"unsignedShortValue"]) &&
	    R([m setValue: [OFNumber numberWithUnsignedInt: 80]
		   forKey: @"unsignedIntValue"]) &&
	    R([m setValue: [OFNumber numberWithUnsignedLong: 90]
		   forKey: @"unsignedLongValue"]) &&
	    R([m setValue: [OFNumber numberWithUnsignedLongLong: 100]
		   forKey: @"unsignedLongLongValue"]) &&
	    R([m setValue: [OFNumber numberWithFloat: 110]
		   forKey: @"floatValue"]) &&
	    R([m setValue: [OFNumber numberWithDouble: 120]
		   forKey: @"doubleValue"]) &&
	    m.isBoolValue == 0 && m.charValue == 10 && m.shortValue == 20 &&
	    m.intValue == 30 && m.longValue == 40 && m.longLongValue == 50 &&



	    m.unsignedCharValue == 60 && m.unsignedShortValue == 70 &&

	    m.unsignedIntValue == 80 && m.unsignedLongValue == 90 &&
	    m.unsignedLongLongValue == 100 && m.floatValue == 110 &&

	    m.doubleValue == 120)

	EXPECT_EXCEPTION(@"Catch -[setValue:forKey:] with nil key for scalar",
	    OFInvalidArgumentException, [m setValue: (id _Nonnull)nil
					     forKey: @"intValue"])

	TEST(@"-[valueForKeyPath:]",
	    (m = [[[MyObj alloc] init] autorelease]) &&
	    (m.objectValue = [[[MyObj alloc] init] autorelease]) &&
	    R([m.objectValue
	    setObjectValue: [[[MyObj alloc] init] autorelease]]) &&
	    R([[m.objectValue objectValue] setDoubleValue: 0.5]) &&
	    [[m valueForKeyPath: @"objectValue.objectValue.doubleValue"]
	    doubleValue] == 0.5)

	TEST(@"[-setValue:forKeyPath:]",
	    R([m setValue: [OFNumber numberWithDouble: 0.75]
	       forKeyPath: @"objectValue.objectValue.doubleValue"]) &&
	    [[m.objectValue objectValue] doubleValue] == 0.75)

	objc_autoreleasePoolPop(pool);
}
@end







|

|







 







|







 







|
|



|

|
|


|
|

|
|

|
|
|


|


|
|
|
|


>
|

|
|
|
|
|
|
|
|
|
|
|
|
|

|

|

|

|

|

|

|

|

|

|

|

|

|



|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<
>
>
>
|
>
|
|
>
|


|
|


|
|
|
|
|
|



|
|
|




19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
..
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
..
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190

191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221

#if (defined(OF_DRAGONFLYBSD) && defined(__LP64__)) || defined(OF_NINTENDO_3DS)
# define TOO_BIG (SIZE_MAX / 3)
#else
# define TOO_BIG (SIZE_MAX - 128)
#endif

static OFString *const module = @"OFObject";

@interface MyObject: OFObject
{
	id _objectValue;
	Class _classValue;
	bool _boolValue;
	char _charValue;
	short _shortValue;
	int _intValue;
................................................................................
@property (nonatomic) unsigned int unsignedIntValue;
@property (nonatomic) unsigned long unsignedLongValue;
@property (nonatomic) unsigned long long unsignedLongLongValue;
@property (nonatomic) float floatValue;
@property (nonatomic) double doubleValue;
@end

@implementation MyObject
@synthesize objectValue = _objectValue, classValue = _classValue;
@synthesize boolValue = _boolValue, charValue = _charValue;
@synthesize shortValue = _shortValue, intValue = _intValue;
@synthesize longValue = _longValue, longLongValue = _longLongValue;
@synthesize unsignedCharValue = _unsignedCharValue;
@synthesize unsignedShortValue = _unsignedShortValue;
@synthesize unsignedIntValue = _unsignedIntValue;
................................................................................
}
@end

@implementation TestsAppDelegate (OFObjectTests)
- (void)objectTests
{
	void *pool = objc_autoreleasePoolPush();
	OFObject *object;
	MyObject *myObject;

	TEST(@"+[description]",
	    [[OFObject description] isEqual: @"OFObject"] &&
	    [[MyObject description] isEqual: @"MyObject"])

	object = [[[OFObject alloc] init] autorelease];
	myObject = [[[MyObject alloc] init] autorelease];

	TEST(@"-[description]",
	    [object.description isEqual: @"<OFObject>"] &&
	    [myObject.description isEqual: @"<MyObject>"])

	myObject.objectValue = @"Hello";
	myObject.classValue = myObject.class;
	TEST(@"-[valueForKey:]",
	    [[myObject valueForKey: @"objectValue"] isEqual: @"Hello"] &&
	    [[myObject valueForKey: @"classValue"] isEqual: myObject.class] &&
	    [[myObject valueForKey: @"class"] isEqual: myObject.class])

	EXPECT_EXCEPTION(@"-[valueForKey:] with undefined key",
	    OFUndefinedKeyException, [myObject valueForKey: @"undefined"])

	TEST(@"-[setValue:forKey:]",
	    R([myObject setValue: @"World" forKey: @"objectValue"]) &&
	    R([myObject setValue: [OFObject class] forKey: @"classValue"]) &&
	    [myObject.objectValue isEqual: @"World"] &&
	    [myObject.classValue isEqual: [OFObject class]])

	EXPECT_EXCEPTION(@"-[setValue:forKey:] with undefined key",
	    OFUndefinedKeyException,
	    [myObject setValue: @"x" forKey: @"undefined"])

	myObject.boolValue = 1;
	myObject.charValue = 2;
	myObject.shortValue = 3;
	myObject.intValue = 4;
	myObject.longValue = 5;
	myObject.longLongValue = 6;
	myObject.unsignedCharValue = 7;
	myObject.unsignedShortValue = 8;
	myObject.unsignedIntValue = 9;
	myObject.unsignedLongValue = 10;
	myObject.unsignedLongLongValue = 11;
	myObject.floatValue = 12;
	myObject.doubleValue = 13;
	TEST(@"Auto-wrapping of -[valueForKey:]",
	    [[myObject valueForKey: @"boolValue"] isEqual:
	    [OFNumber numberWithBool: 1]] &&
	    [[myObject valueForKey: @"charValue"] isEqual:
	    [OFNumber numberWithChar: 2]] &&
	    [[myObject valueForKey: @"shortValue"] isEqual:
	    [OFNumber numberWithShort: 3]] &&
	    [[myObject valueForKey: @"intValue"] isEqual:
	    [OFNumber numberWithInt: 4]] &&
	    [[myObject valueForKey: @"longValue"] isEqual:
	    [OFNumber numberWithLong: 5]] &&
	    [[myObject valueForKey: @"longLongValue"] isEqual:
	    [OFNumber numberWithLongLong: 6]] &&
	    [[myObject valueForKey: @"unsignedCharValue"] isEqual:
	    [OFNumber numberWithUnsignedChar: 7]] &&
	    [[myObject valueForKey: @"unsignedShortValue"] isEqual:
	    [OFNumber numberWithUnsignedShort: 8]] &&
	    [[myObject valueForKey: @"unsignedIntValue"] isEqual:
	    [OFNumber numberWithUnsignedInt: 9]] &&
	    [[myObject valueForKey: @"unsignedLongValue"] isEqual:
	    [OFNumber numberWithUnsignedLong: 10]] &&
	    [[myObject valueForKey: @"unsignedLongLongValue"] isEqual:
	    [OFNumber numberWithUnsignedLongLong: 11]] &&
	    [[myObject valueForKey: @"floatValue"] isEqual:
	    [OFNumber numberWithFloat: 12]] &&
	    [[myObject valueForKey: @"doubleValue"] isEqual:
	    [OFNumber numberWithDouble: 13]])

	TEST(@"Auto-wrapping of -[setValue:forKey:]",
	    R([myObject setValue: [OFNumber numberWithBool: 0]
			  forKey: @"boolValue"]) &&
	    R([myObject setValue: [OFNumber numberWithChar: 10]
			  forKey: @"charValue"]) &&
	    R([myObject setValue: [OFNumber numberWithShort: 20]
			  forKey: @"shortValue"]) &&
	    R([myObject setValue: [OFNumber numberWithInt: 30]
			  forKey: @"intValue"]) &&
	    R([myObject setValue: [OFNumber numberWithLong: 40]
			  forKey: @"longValue"]) &&
	    R([myObject setValue: [OFNumber numberWithLongLong: 50]
			  forKey: @"longLongValue"]) &&
	    R([myObject setValue: [OFNumber numberWithUnsignedChar: 60]
			  forKey: @"unsignedCharValue"]) &&
	    R([myObject setValue: [OFNumber numberWithUnsignedShort: 70]
			  forKey: @"unsignedShortValue"]) &&
	    R([myObject setValue: [OFNumber numberWithUnsignedInt: 80]
			  forKey: @"unsignedIntValue"]) &&
	    R([myObject setValue: [OFNumber numberWithUnsignedLong: 90]
			  forKey: @"unsignedLongValue"]) &&
	    R([myObject setValue: [OFNumber numberWithUnsignedLongLong: 100]
			  forKey: @"unsignedLongLongValue"]) &&
	    R([myObject setValue: [OFNumber numberWithFloat: 110]
			  forKey: @"floatValue"]) &&
	    R([myObject setValue: [OFNumber numberWithDouble: 120]
			  forKey: @"doubleValue"]) &&
	    myObject.isBoolValue == 0 && myObject.charValue == 10 &&

	    myObject.shortValue == 20 && myObject.intValue == 30 &&
	    myObject.longValue == 40 && myObject.longLongValue == 50 &&
	    myObject.unsignedCharValue == 60 &&
	    myObject.unsignedShortValue == 70 &&
	    myObject.unsignedIntValue == 80 &&
	    myObject.unsignedLongValue == 90 &&
	    myObject.unsignedLongLongValue == 100 &&
	    myObject.floatValue == 110 &&
	    myObject.doubleValue == 120)

	EXPECT_EXCEPTION(@"Catch -[setValue:forKey:] with nil key for scalar",
	    OFInvalidArgumentException,
	    [myObject setValue: (id _Nonnull)nil forKey: @"intValue"])

	TEST(@"-[valueForKeyPath:]",
	    (myObject = [[[MyObject alloc] init] autorelease]) &&
	    (myObject.objectValue = [[[MyObject alloc] init] autorelease]) &&
	    R([myObject.objectValue
	    setObjectValue: [[[MyObject alloc] init] autorelease]]) &&
	    R([[myObject.objectValue objectValue] setDoubleValue: 0.5]) &&
	    [[myObject valueForKeyPath: @"objectValue.objectValue.doubleValue"]
	    doubleValue] == 0.5)

	TEST(@"[-setValue:forKeyPath:]",
	    R([myObject setValue: [OFNumber numberWithDouble: 0.75]
		      forKeyPath: @"objectValue.objectValue.doubleValue"]) &&
	    [[myObject.objectValue objectValue] doubleValue] == 0.75)

	objc_autoreleasePoolPop(pool);
}
@end

Modified tests/OFPBKDF2Tests.m from [c97ca65028] to [650e1671f9].

15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

#include "config.h"

#include <string.h>

#import "TestsAppDelegate.h"

static OFString *module = @"PBKDF2";

@implementation TestsAppDelegate (PBKDF2Tests)
- (void)PBKDF2Tests
{
	void *pool = objc_autoreleasePoolPush();
	OFHMAC *HMAC = [OFHMAC HMACWithHashClass: [OFSHA1Hash class]
			   allowsSwappableMemory: true];
	unsigned char key[25];








|

|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

#include "config.h"

#include <string.h>

#import "TestsAppDelegate.h"

static OFString *const module = @"OFPBKDF2";

@implementation TestsAppDelegate (OFPBKDF2Tests)
- (void)PBKDF2Tests
{
	void *pool = objc_autoreleasePoolPush();
	OFHMAC *HMAC = [OFHMAC HMACWithHashClass: [OFSHA1Hash class]
			   allowsSwappableMemory: true];
	unsigned char key[25];

Modified tests/OFPluginTests.m from [79f8663f0b] to [4801b7fe9e].

16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include "config.h"

#import "TestsAppDelegate.h"

#import "plugin/TestPlugin.h"

#ifndef OF_IOS
# define PLUGIN_PATH @"plugin/TestPlugin"
#else
# define PLUGIN_PATH @"PlugIns/TestPlugin"
#endif

static OFString *module = @"OFPlugin";

@implementation TestsAppDelegate (OFPluginTests)
- (void)pluginTests
{
	void *pool = objc_autoreleasePoolPush();
	TestPlugin *plugin;

	TEST(@"+[pluginWithPath:]",
	    (plugin = [OFPlugin pluginWithPath: PLUGIN_PATH]))

	TEST(@"TestPlugin's -[test:]", [plugin test: 1234] == 2468)

	objc_autoreleasePoolPop(pool);
}
@end







|

|


|








|






16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include "config.h"

#import "TestsAppDelegate.h"

#import "plugin/TestPlugin.h"

#ifndef OF_IOS
static OFString *const pluginPath = @"plugin/TestPlugin";
#else
static OFString *const pluginPath = @"PlugIns/TestPlugin";
#endif

static OFString *const module = @"OFPlugin";

@implementation TestsAppDelegate (OFPluginTests)
- (void)pluginTests
{
	void *pool = objc_autoreleasePoolPush();
	TestPlugin *plugin;

	TEST(@"+[pluginWithPath:]",
	    (plugin = [OFPlugin pluginWithPath: pluginPath]))

	TEST(@"TestPlugin's -[test:]", [plugin test: 1234] == 2468)

	objc_autoreleasePoolPop(pool);
}
@end

Modified tests/OFPropertyListTests.m from [f46fac19eb] to [9ca2969379].

21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
	@"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"			\
	@"<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" "	\
	@"\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">"		\
	@"<plist version=\"1.0\">\n"					\
	x @"\n"								\
	@"</plist>"

static OFString *module = @"OFPropertyList";
static OFString *PLIST1 = PLIST(@"<string>Hello</string>");
static OFString *PLIST2 = PLIST(
    @"<array>"
    @" <string>Hello</string>"
    @" <data>V29ybGQh</data>"
    @" <date>2018-03-14T12:34:56Z</date>"
    @" <true/>"
    @" <false/>"
    @" <real>12.25</real>"
    @" <integer>-10</integer>"
    @"</array>");
static OFString *PLIST3 = PLIST(
    @"<dict>"
    @" <key>array</key>"
    @" <array>"
    @"  <string>Hello</string>"
    @"  <data>V29ybGQh</data>"
    @"  <date>2018-03-14T12:34:56Z</date>"
    @"  <true/>"







|
|
|









|







21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
	@"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"			\
	@"<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" "	\
	@"\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">"		\
	@"<plist version=\"1.0\">\n"					\
	x @"\n"								\
	@"</plist>"

static OFString *const module = @"OFPropertyList";
static OFString *const PLIST1 = PLIST(@"<string>Hello</string>");
static OFString *const PLIST2 = PLIST(
    @"<array>"
    @" <string>Hello</string>"
    @" <data>V29ybGQh</data>"
    @" <date>2018-03-14T12:34:56Z</date>"
    @" <true/>"
    @" <false/>"
    @" <real>12.25</real>"
    @" <integer>-10</integer>"
    @"</array>");
static OFString *const PLIST3 = PLIST(
    @"<dict>"
    @" <key>array</key>"
    @" <array>"
    @"  <string>Hello</string>"
    @"  <data>V29ybGQh</data>"
    @"  <date>2018-03-14T12:34:56Z</date>"
    @"  <true/>"

Modified tests/OFRIPEMD160HashTests.m from [4b2bd712b4] to [00f15b1edb].

15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57

#include "config.h"

#include <string.h>

#import "TestsAppDelegate.h"

static OFString *module = @"OFRIPEMD160Hash";

const uint8_t testfile_rmd160[20] =
	"\x46\x02\x97\xF5\x85\xDF\xB9\x21\x00\xC8\xF9\x87\xC6\xEC\x84\x0D\xCE"
	"\xE6\x08\x8B";

@implementation TestsAppDelegate (OFRIPEMD160HashTests)
- (void)RIPEMD160HashTests
{
	void *pool = objc_autoreleasePoolPush();
	OFRIPEMD160Hash *rmd160, *copy;
	OFFile *f = [OFFile fileWithPath: @"testfile.bin" mode: @"r"];

	TEST(@"+[hashWithAllowsSwappableMemory:]",
	    (rmd160 = [OFRIPEMD160Hash hashWithAllowsSwappableMemory: true]))

	while (!f.atEndOfStream) {
		char buf[64];
		size_t len = [f readIntoBuffer: buf length: 64];
		[rmd160 updateWithBuffer: buf length: len];
	}
	[f close];

	TEST(@"-[copy]", (copy = [[rmd160 copy] autorelease]))

	TEST(@"-[digest]",
	    memcmp(rmd160.digest, testfile_rmd160, 20) == 0 &&
	    memcmp(copy.digest, testfile_rmd160, 20) == 0)

	EXPECT_EXCEPTION(@"Detect invalid call of "
	    @"-[updateWithBuffer:length]", OFHashAlreadyCalculatedException,
	    [rmd160 updateWithBuffer: "" length: 1])

	objc_autoreleasePoolPop(pool);
}
@end







|

|







|
|


|

|
|
|
|

|

|


|
|



|




15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57

#include "config.h"

#include <string.h>

#import "TestsAppDelegate.h"

static OFString *const module = @"OFRIPEMD160Hash";

const uint8_t testFileRIPEMD160[20] =
	"\x46\x02\x97\xF5\x85\xDF\xB9\x21\x00\xC8\xF9\x87\xC6\xEC\x84\x0D\xCE"
	"\xE6\x08\x8B";

@implementation TestsAppDelegate (OFRIPEMD160HashTests)
- (void)RIPEMD160HashTests
{
	void *pool = objc_autoreleasePoolPush();
	OFRIPEMD160Hash *RIPEMD160, *RIPEMD160Copy;
	OFFile *file = [OFFile fileWithPath: @"testfile.bin" mode: @"r"];

	TEST(@"+[hashWithAllowsSwappableMemory:]",
	    (RIPEMD160 = [OFRIPEMD160Hash hashWithAllowsSwappableMemory: true]))

	while (!file.atEndOfStream) {
		char buffer[64];
		size_t length = [file readIntoBuffer: buffer length: 64];
		[RIPEMD160 updateWithBuffer: buffer length: length];
	}
	[file close];

	TEST(@"-[copy]", (RIPEMD160Copy = [[RIPEMD160 copy] autorelease]))

	TEST(@"-[digest]",
	    memcmp(RIPEMD160.digest, testFileRIPEMD160, 20) == 0 &&
	    memcmp(RIPEMD160Copy.digest, testFileRIPEMD160, 20) == 0)

	EXPECT_EXCEPTION(@"Detect invalid call of "
	    @"-[updateWithBuffer:length]", OFHashAlreadyCalculatedException,
	    [RIPEMD160 updateWithBuffer: "" length: 1])

	objc_autoreleasePoolPop(pool);
}
@end

Modified tests/OFSHA1HashTests.m from [3bceacae61] to [4f485b9d65].

15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57

#include "config.h"

#include <string.h>

#import "TestsAppDelegate.h"

static OFString *module = @"OFSHA1Hash";

const uint8_t testfile_sha1[20] =
	"\xC9\x9A\xB8\x7E\x1E\xC8\xEC\x65\xD5\xEB\xE4\x2E\x0D\xA6\x80\x96\xF5"
	"\x94\xE7\x17";

@implementation TestsAppDelegate (SHA1HashTests)
- (void)SHA1HashTests
{
	void *pool = objc_autoreleasePoolPush();
	OFSHA1Hash *sha1, *copy;
	OFFile *f = [OFFile fileWithPath: @"testfile.bin" mode: @"r"];

	TEST(@"+[hashWithAllowsSwappableMemory:]",
	    (sha1 = [OFSHA1Hash hashWithAllowsSwappableMemory: true]))

	while (!f.atEndOfStream) {
		char buf[64];
		size_t len = [f readIntoBuffer: buf length: 64];
		[sha1 updateWithBuffer: buf length: len];
	}
	[f close];

	TEST(@"-[copy]", (copy = [[sha1 copy] autorelease]))

	TEST(@"-[digest]",
	    memcmp(sha1.digest, testfile_sha1, 20) == 0 &&
	    memcmp(copy.digest, testfile_sha1, 20) == 0)

	EXPECT_EXCEPTION(@"Detect invalid call of "
	    @"-[updateWithBuffer:length:]", OFHashAlreadyCalculatedException,
	    [sha1 updateWithBuffer: "" length: 1])

	objc_autoreleasePoolPop(pool);
}
@end







|

|







|
|


|

|
|
|
|

|

|


|
|



|




15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57

#include "config.h"

#include <string.h>

#import "TestsAppDelegate.h"

static OFString *const module = @"OFSHA1Hash";

const uint8_t testFileSHA1[20] =
	"\xC9\x9A\xB8\x7E\x1E\xC8\xEC\x65\xD5\xEB\xE4\x2E\x0D\xA6\x80\x96\xF5"
	"\x94\xE7\x17";

@implementation TestsAppDelegate (SHA1HashTests)
- (void)SHA1HashTests
{
	void *pool = objc_autoreleasePoolPush();
	OFSHA1Hash *SHA1, *SHA1Copy;
	OFFile *file = [OFFile fileWithPath: @"testfile.bin" mode: @"r"];

	TEST(@"+[hashWithAllowsSwappableMemory:]",
	    (SHA1 = [OFSHA1Hash hashWithAllowsSwappableMemory: true]))

	while (!file.atEndOfStream) {
		char buffer[64];
		size_t length = [file readIntoBuffer: buffer length: 64];
		[SHA1 updateWithBuffer: buffer length: length];
	}
	[file close];

	TEST(@"-[copy]", (SHA1Copy = [[SHA1 copy] autorelease]))

	TEST(@"-[digest]",
	    memcmp(SHA1.digest, testFileSHA1, 20) == 0 &&
	    memcmp(SHA1Copy.digest, testFileSHA1, 20) == 0)

	EXPECT_EXCEPTION(@"Detect invalid call of "
	    @"-[updateWithBuffer:length:]", OFHashAlreadyCalculatedException,
	    [SHA1 updateWithBuffer: "" length: 1])

	objc_autoreleasePoolPop(pool);
}
@end

Modified tests/OFSHA224HashTests.m from [4309676a79] to [d949087e30].

15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57

#include "config.h"

#include <string.h>

#import "TestsAppDelegate.h"

static OFString *module = @"OFSHA224Hash";

const uint8_t testfile_sha224[28] =
	"\x27\x69\xD8\x04\x2D\x0F\xCA\x84\x6C\xF1\x62\x44\xBA\x0C\xBD\x46\x64"
	"\x5F\x4F\x20\x02\x4D\x15\xED\x1C\x61\x1F\xF7";

@implementation TestsAppDelegate (SHA224HashTests)
- (void)SHA224HashTests
{
	void *pool = objc_autoreleasePoolPush();
	OFSHA224Hash *sha224, *copy;
	OFFile *f = [OFFile fileWithPath: @"testfile.bin" mode: @"r"];

	TEST(@"+[hashWithAllowsSwappableMemory:]",
	    (sha224 = [OFSHA224Hash hashWithAllowsSwappableMemory: true]))

	while (!f.atEndOfStream) {
		char buf[64];
		size_t len = [f readIntoBuffer: buf length: 64];
		[sha224 updateWithBuffer: buf length: len];
	}
	[f close];

	TEST(@"-[copy]", (copy = [[sha224 copy] autorelease]))

	TEST(@"-[digest]",
	    memcmp(sha224.digest, testfile_sha224, 28) == 0 &&
	    memcmp(copy.digest, testfile_sha224, 28) == 0)

	EXPECT_EXCEPTION(@"Detect invalid call of "
	    @"-[updateWithBuffer:length:]", OFHashAlreadyCalculatedException,
	    [sha224 updateWithBuffer: "" length: 1])

	objc_autoreleasePoolPop(pool);
}
@end







|

|







|
|


|

|
|
|
|

|

|


|
|



|




15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57

#include "config.h"

#include <string.h>

#import "TestsAppDelegate.h"

static OFString *const module = @"OFSHA224Hash";

const uint8_t testFileSHA224[28] =
	"\x27\x69\xD8\x04\x2D\x0F\xCA\x84\x6C\xF1\x62\x44\xBA\x0C\xBD\x46\x64"
	"\x5F\x4F\x20\x02\x4D\x15\xED\x1C\x61\x1F\xF7";

@implementation TestsAppDelegate (SHA224HashTests)
- (void)SHA224HashTests
{
	void *pool = objc_autoreleasePoolPush();
	OFSHA224Hash *SHA224, *SHA224Copy;
	OFFile *file = [OFFile fileWithPath: @"testfile.bin" mode: @"r"];

	TEST(@"+[hashWithAllowsSwappableMemory:]",
	    (SHA224 = [OFSHA224Hash hashWithAllowsSwappableMemory: true]))

	while (!file.atEndOfStream) {
		char buffer[64];
		size_t length = [file readIntoBuffer: buffer length: 64];
		[SHA224 updateWithBuffer: buffer length: length];
	}
	[file close];

	TEST(@"-[copy]", (SHA224Copy = [[SHA224 copy] autorelease]))

	TEST(@"-[digest]",
	    memcmp(SHA224.digest, testFileSHA224, 28) == 0 &&
	    memcmp(SHA224Copy.digest, testFileSHA224, 28) == 0)

	EXPECT_EXCEPTION(@"Detect invalid call of "
	    @"-[updateWithBuffer:length:]", OFHashAlreadyCalculatedException,
	    [SHA224 updateWithBuffer: "" length: 1])

	objc_autoreleasePoolPop(pool);
}
@end

Modified tests/OFSHA256HashTests.m from [2f9948771c] to [f90460efa2].

15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57

#include "config.h"

#include <string.h>

#import "TestsAppDelegate.h"

static OFString *module = @"OFSHA256Hash";

const uint8_t testfile_sha256[32] =
	"\x1A\x02\xD6\x46\xF5\xA6\xBA\xAA\xFF\x7F\xD5\x87\xBA\xC3\xF6\xC6\xB5"
	"\x67\x93\x8F\x0F\x44\x90\xB8\xF5\x35\x89\xF0\x5A\x23\x7F\x69";

@implementation TestsAppDelegate (SHA256HashTests)
- (void)SHA256HashTests
{
	void *pool = objc_autoreleasePoolPush();
	OFSHA256Hash *sha256, *copy;
	OFFile *f = [OFFile fileWithPath: @"testfile.bin" mode: @"r"];

	TEST(@"+[hashWithAllowsSwappableMemory:]",
	    (sha256 = [OFSHA256Hash hashWithAllowsSwappableMemory: true]))

	while (!f.atEndOfStream) {
		char buf[64];
		size_t len = [f readIntoBuffer: buf length: 64];
		[sha256 updateWithBuffer: buf length: len];
	}
	[f close];

	TEST(@"-[copy]", (copy = [[sha256 copy] autorelease]))

	TEST(@"-[digest]",
	    memcmp(sha256.digest, testfile_sha256, 32) == 0 &&
	    memcmp(copy.digest, testfile_sha256, 32) == 0)

	EXPECT_EXCEPTION(@"Detect invalid call of "
	    @"-[updateWithBuffer:length:]", OFHashAlreadyCalculatedException,
	    [sha256 updateWithBuffer: "" length: 1])

	objc_autoreleasePoolPop(pool);
}
@end







|

|







|
|


|

|
|
|
|

|

|


|
|



|




15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57

#include "config.h"

#include <string.h>

#import "TestsAppDelegate.h"

static OFString *const module = @"OFSHA256Hash";

const uint8_t testFileSHA256[32] =
	"\x1A\x02\xD6\x46\xF5\xA6\xBA\xAA\xFF\x7F\xD5\x87\xBA\xC3\xF6\xC6\xB5"
	"\x67\x93\x8F\x0F\x44\x90\xB8\xF5\x35\x89\xF0\x5A\x23\x7F\x69";

@implementation TestsAppDelegate (SHA256HashTests)
- (void)SHA256HashTests
{
	void *pool = objc_autoreleasePoolPush();
	OFSHA256Hash *SHA256, *SHA256Copy;
	OFFile *file = [OFFile fileWithPath: @"testfile.bin" mode: @"r"];

	TEST(@"+[hashWithAllowsSwappableMemory:]",
	    (SHA256 = [OFSHA256Hash hashWithAllowsSwappableMemory: true]))

	while (!file.atEndOfStream) {
		char buffer[64];
		size_t length = [file readIntoBuffer: buffer length: 64];
		[SHA256 updateWithBuffer: buffer length: length];
	}
	[file close];

	TEST(@"-[copy]", (SHA256Copy = [[SHA256 copy] autorelease]))

	TEST(@"-[digest]",
	    memcmp(SHA256.digest, testFileSHA256, 32) == 0 &&
	    memcmp(SHA256Copy.digest, testFileSHA256, 32) == 0)

	EXPECT_EXCEPTION(@"Detect invalid call of "
	    @"-[updateWithBuffer:length:]", OFHashAlreadyCalculatedException,
	    [SHA256 updateWithBuffer: "" length: 1])

	objc_autoreleasePoolPop(pool);
}
@end

Modified tests/OFSHA384HashTests.m from [fdfc8fecb8] to [7fee81f984].

15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58

#include "config.h"

#include <string.h>

#import "TestsAppDelegate.h"

static OFString *module = @"OFSHA384Hash";

const uint8_t testfile_sha384[48] =
	"\x7E\xDE\x62\xE2\x10\xA5\x1E\x18\x8A\x11\x7F\x78\xD7\xC7\x55\xB6\x43"
	"\x94\x1B\xD2\x78\x5C\xCF\xF3\x8A\xB8\x98\x22\xC7\x0E\xFE\xF1\xEC\x53"
	"\xE9\x1A\xB3\x51\x70\x8C\x1F\x3F\x56\x12\x44\x01\x91\x54";

@implementation TestsAppDelegate (SHA384HashTests)
- (void)SHA384HashTests
{
	void *pool = objc_autoreleasePoolPush();
	OFSHA384Hash *sha384, *copy;
	OFFile *f = [OFFile fileWithPath: @"testfile.bin" mode: @"r"];

	TEST(@"+[hashWithAllowsSwappableMemory:]",
	    (sha384 = [OFSHA384Hash hashWithAllowsSwappableMemory: true]))

	while (!f.atEndOfStream) {
		char buf[128];
		size_t len = [f readIntoBuffer: buf length: 128];
		[sha384 updateWithBuffer: buf length: len];
	}
	[f close];

	TEST(@"-[copy]", (copy = [[sha384 copy] autorelease]))

	TEST(@"-[digest]",
	    memcmp(sha384.digest, testfile_sha384, 48) == 0 &&
	    memcmp(copy.digest, testfile_sha384, 48) == 0)

	EXPECT_EXCEPTION(@"Detect invalid call of "
	    @"-[updateWithBuffer:length:]", OFHashAlreadyCalculatedException,
	    [sha384 updateWithBuffer: "" length: 1])

	objc_autoreleasePoolPop(pool);
}
@end







|

|








|
|


|

|
|
|
|

|

|


|
|



|




15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58

#include "config.h"

#include <string.h>

#import "TestsAppDelegate.h"

static OFString *const module = @"OFSHA384Hash";

const uint8_t testFileSHA384[48] =
	"\x7E\xDE\x62\xE2\x10\xA5\x1E\x18\x8A\x11\x7F\x78\xD7\xC7\x55\xB6\x43"
	"\x94\x1B\xD2\x78\x5C\xCF\xF3\x8A\xB8\x98\x22\xC7\x0E\xFE\xF1\xEC\x53"
	"\xE9\x1A\xB3\x51\x70\x8C\x1F\x3F\x56\x12\x44\x01\x91\x54";

@implementation TestsAppDelegate (SHA384HashTests)
- (void)SHA384HashTests
{
	void *pool = objc_autoreleasePoolPush();
	OFSHA384Hash *SHA384, *SHA384Copy;
	OFFile *file = [OFFile fileWithPath: @"testfile.bin" mode: @"r"];

	TEST(@"+[hashWithAllowsSwappableMemory:]",
	    (SHA384 = [OFSHA384Hash hashWithAllowsSwappableMemory: true]))

	while (!file.atEndOfStream) {
		char buffer[128];
		size_t length = [file readIntoBuffer: buffer length: 128];
		[SHA384 updateWithBuffer: buffer length: length];
	}
	[file close];

	TEST(@"-[copy]", (SHA384Copy = [[SHA384 copy] autorelease]))

	TEST(@"-[digest]",
	    memcmp(SHA384.digest, testFileSHA384, 48) == 0 &&
	    memcmp(SHA384Copy.digest, testFileSHA384, 48) == 0)

	EXPECT_EXCEPTION(@"Detect invalid call of "
	    @"-[updateWithBuffer:length:]", OFHashAlreadyCalculatedException,
	    [SHA384 updateWithBuffer: "" length: 1])

	objc_autoreleasePoolPop(pool);
}
@end

Modified tests/OFSHA512HashTests.m from [ff0238e62b] to [b65f0f5008].

15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59

#include "config.h"

#include <string.h>

#import "TestsAppDelegate.h"

static OFString *module = @"OFSHA512Hash";

const uint8_t testfile_sha512[64] =
	"\x8F\x36\x6E\x3C\x19\x4B\xBB\xC7\x82\xAA\xCD\x7D\x55\xA2\xD3\x29\x29"
	"\x97\x6A\x3F\xEB\x9B\xB2\xCB\x75\xC9\xEC\xC8\x10\x07\xD6\x07\x31\x4A"
	"\xB1\x30\x97\x82\x58\xA5\x1F\x71\x42\xE6\x56\x07\x99\x57\xB2\xB8\x3B"
	"\xA1\x8A\x41\x64\x33\x69\x21\x8C\x2A\x44\x6D\xF2\xA0";

@implementation TestsAppDelegate (SHA512HashTests)
- (void)SHA512HashTests
{
	void *pool = objc_autoreleasePoolPush();
	OFSHA512Hash *sha512, *copy;
	OFFile *f = [OFFile fileWithPath: @"testfile.bin" mode: @"r"];

	TEST(@"+[hashWithAllowsSwappableMemory:]",
	    (sha512 = [OFSHA512Hash hashWithAllowsSwappableMemory: true]))

	while (!f.atEndOfStream) {
		char buf[128];
		size_t len = [f readIntoBuffer: buf length: 128];
		[sha512 updateWithBuffer: buf length: len];
	}
	[f close];

	TEST(@"-[copy]", (copy = [[sha512 copy] autorelease]))

	TEST(@"-[digest]",
	    memcmp(sha512.digest, testfile_sha512, 64) == 0 &&
	    memcmp(copy.digest, testfile_sha512, 64) == 0)

	EXPECT_EXCEPTION(@"Detect invalid call of "
	    @"-[updateWithBuffer:length:]", OFHashAlreadyCalculatedException,
	    [sha512 updateWithBuffer: "" length: 1])

	objc_autoreleasePoolPop(pool);
}
@end







|

|









|
|


|

|
|
|
|

|

|


|
|



|




15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59

#include "config.h"

#include <string.h>

#import "TestsAppDelegate.h"

static OFString *const module = @"OFSHA512Hash";

const uint8_t testFileSHA512[64] =
	"\x8F\x36\x6E\x3C\x19\x4B\xBB\xC7\x82\xAA\xCD\x7D\x55\xA2\xD3\x29\x29"
	"\x97\x6A\x3F\xEB\x9B\xB2\xCB\x75\xC9\xEC\xC8\x10\x07\xD6\x07\x31\x4A"
	"\xB1\x30\x97\x82\x58\xA5\x1F\x71\x42\xE6\x56\x07\x99\x57\xB2\xB8\x3B"
	"\xA1\x8A\x41\x64\x33\x69\x21\x8C\x2A\x44\x6D\xF2\xA0";

@implementation TestsAppDelegate (SHA512HashTests)
- (void)SHA512HashTests
{
	void *pool = objc_autoreleasePoolPush();
	OFSHA512Hash *SHA512, *SHA512Copy;
	OFFile *file = [OFFile fileWithPath: @"testfile.bin" mode: @"r"];

	TEST(@"+[hashWithAllowsSwappableMemory:]",
	    (SHA512 = [OFSHA512Hash hashWithAllowsSwappableMemory: true]))

	while (!file.atEndOfStream) {
		char buffer[128];
		size_t length = [file readIntoBuffer: buffer length: 128];
		[SHA512 updateWithBuffer: buffer length: length];
	}
	[file close];

	TEST(@"-[copy]", (SHA512Copy = [[SHA512 copy] autorelease]))

	TEST(@"-[digest]",
	    memcmp(SHA512.digest, testFileSHA512, 64) == 0 &&
	    memcmp(SHA512Copy.digest, testFileSHA512, 64) == 0)

	EXPECT_EXCEPTION(@"Detect invalid call of "
	    @"-[updateWithBuffer:length:]", OFHashAlreadyCalculatedException,
	    [SHA512 updateWithBuffer: "" length: 1])

	objc_autoreleasePoolPop(pool);
}
@end

Modified tests/OFSPXSocketTests.m from [8af68629fd] to [1c45b38ca1].

15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

#include "config.h"

#include <errno.h>

#import "TestsAppDelegate.h"

static OFString *module = @"OFSPXSocket";

@interface SPXSocketDelegate: OFObject <OFSPXSocketDelegate>
{
@public
	OFSequencedPacketSocket *_expectedServerSocket;
	OFSPXSocket *_expectedClientSocket;
	unsigned char _expectedNode[IPX_NODE_LEN];







|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

#include "config.h"

#include <errno.h>

#import "TestsAppDelegate.h"

static OFString *const module = @"OFSPXSocket";

@interface SPXSocketDelegate: OFObject <OFSPXSocketDelegate>
{
@public
	OFSequencedPacketSocket *_expectedServerSocket;
	OFSPXSocket *_expectedClientSocket;
	unsigned char _expectedNode[IPX_NODE_LEN];

Modified tests/OFSPXStreamSocketTests.m from [e27033149d] to [0326ef9bb8].

15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

#include "config.h"

#include <errno.h>

#import "TestsAppDelegate.h"

static OFString *module = @"OFSPXStreamSocket";

@interface SPXStreamSocketDelegate: OFObject <OFSPXStreamSocketDelegate>
{
@public
	OFStreamSocket *_expectedServerSocket;
	OFSPXStreamSocket *_expectedClientSocket;
	unsigned char _expectedNode[IPX_NODE_LEN];







|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

#include "config.h"

#include <errno.h>

#import "TestsAppDelegate.h"

static OFString *const module = @"OFSPXStreamSocket";

@interface SPXStreamSocketDelegate: OFObject <OFSPXStreamSocketDelegate>
{
@public
	OFStreamSocket *_expectedServerSocket;
	OFSPXStreamSocket *_expectedClientSocket;
	unsigned char _expectedNode[IPX_NODE_LEN];

Modified tests/OFScryptTests.m from [dc5f2613fe] to [2e44374c3f].

15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
...
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140

#include "config.h"

#include <string.h>

#import "TestsAppDelegate.h"

static OFString *module = @"scrypt";
/* Test vectors form RFC 7914 */
static const unsigned char salsa20Input[64] = {
	0x7E, 0x87, 0x9A, 0x21, 0x4F, 0x3E, 0xC9, 0x86, 0x7C, 0xA9, 0x40, 0xE6,
	0x41, 0x71, 0x8F, 0x26, 0xBA, 0xEE, 0x55, 0x5B, 0x8C, 0x61, 0xC1, 0xB5,
	0x0D, 0xF8, 0x46, 0x11, 0x6D, 0xCD, 0x3B, 0x1D, 0xEE, 0x24, 0xF3, 0x19,
	0xDF, 0x9B, 0x3D, 0x85, 0x14, 0x12, 0x1E, 0x4B, 0x5A, 0xC5, 0xAA, 0x32,
	0x76, 0x02, 0x1D, 0x29, 0x09, 0xC7, 0x48, 0x29, 0xED, 0xEB, 0xC6, 0x8D,
................................................................................
	0xAB, 0xE5, 0xEE, 0x98, 0x20, 0xAD, 0xAA, 0x47, 0x8E, 0x56, 0xFD, 0x8F,
	0x4B, 0xA5, 0xD0, 0x9F, 0xFA, 0x1C, 0x6D, 0x92, 0x7C, 0x40, 0xF4, 0xC3,
	0x37, 0x30, 0x40, 0x49, 0xE8, 0xA9, 0x52, 0xFB, 0xCB, 0xF4, 0x5C, 0x6F,
	0xA7, 0x7A, 0x41, 0xA4
};
#endif

@implementation TestsAppDelegate (ScryptTests)
- (void)scryptTests
{
	void *pool = objc_autoreleasePoolPush();
	uint32_t salsa20Buffer[16];
	uint32_t blockMixBuffer[32];
	uint32_t ROMixBuffer[32], ROMixTmp[17 * 32];
	unsigned char output[64];







|







 







|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
...
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140

#include "config.h"

#include <string.h>

#import "TestsAppDelegate.h"

static OFString *const module = @"OFScrypt";
/* Test vectors form RFC 7914 */
static const unsigned char salsa20Input[64] = {
	0x7E, 0x87, 0x9A, 0x21, 0x4F, 0x3E, 0xC9, 0x86, 0x7C, 0xA9, 0x40, 0xE6,
	0x41, 0x71, 0x8F, 0x26, 0xBA, 0xEE, 0x55, 0x5B, 0x8C, 0x61, 0xC1, 0xB5,
	0x0D, 0xF8, 0x46, 0x11, 0x6D, 0xCD, 0x3B, 0x1D, 0xEE, 0x24, 0xF3, 0x19,
	0xDF, 0x9B, 0x3D, 0x85, 0x14, 0x12, 0x1E, 0x4B, 0x5A, 0xC5, 0xAA, 0x32,
	0x76, 0x02, 0x1D, 0x29, 0x09, 0xC7, 0x48, 0x29, 0xED, 0xEB, 0xC6, 0x8D,
................................................................................
	0xAB, 0xE5, 0xEE, 0x98, 0x20, 0xAD, 0xAA, 0x47, 0x8E, 0x56, 0xFD, 0x8F,
	0x4B, 0xA5, 0xD0, 0x9F, 0xFA, 0x1C, 0x6D, 0x92, 0x7C, 0x40, 0xF4, 0xC3,
	0x37, 0x30, 0x40, 0x49, 0xE8, 0xA9, 0x52, 0xFB, 0xCB, 0xF4, 0x5C, 0x6F,
	0xA7, 0x7A, 0x41, 0xA4
};
#endif

@implementation TestsAppDelegate (OFScryptTests)
- (void)scryptTests
{
	void *pool = objc_autoreleasePoolPush();
	uint32_t salsa20Buffer[16];
	uint32_t blockMixBuffer[32];
	uint32_t ROMixBuffer[32], ROMixTmp[17 * 32];
	unsigned char output[64];

Modified tests/OFSerializationTests.m from [5f6e7408a0] to [c0ded8afa9].

13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45

46
47
48
49
50
51
52
53
54
55
56
57
58
59
60

61
62
63
64
 * file.
 */

#include "config.h"

#import "TestsAppDelegate.h"

static OFString *module = @"OFSerialization";

@implementation TestsAppDelegate (OFSerializationTests)
- (void)serializationTests
{
	void *pool = objc_autoreleasePoolPush();
	OFMutableDictionary *d = [OFMutableDictionary dictionary];
	OFMutableArray *a = [OFMutableArray array];
	OFList *l = [OFList list];
	OFData *data;
	OFString *s;

	[a addObject: @"Qu\"xbar\ntest"];
	[a addObject: [OFNumber numberWithInt: 1234]];
	[a addObject: [OFNumber numberWithDouble: 1234.5678]];
	[a addObject: [OFMutableString stringWithString: @"asd"]];
	[a addObject: [OFDate dateWithTimeIntervalSince1970: 1234.5678]];

	[d setObject: @"Hello" forKey: a];
	[d setObject: @"B\"la" forKey: @"Blub"];

	[l appendObject: @"Hello"];
	[l appendObject: @"Wo\rld!\nHow are you?"];
	[l appendObject: [OFURL URLWithString: @"https://objfw.nil.im/"]];
	[l appendObject:
	    [OFXMLElement elementWithXMLString: @"<x><y/><![CDATA[<]]></x>"]];

	[l appendObject: [OFSet setWithObjects: @"foo", @"foo", @"bar", nil]];
	[l appendObject:
	    [OFCountedSet setWithObjects: @"foo", @"foo", @"bar", nil]];

	[d setObject: @"list" forKey: l];

	data = [OFData dataWithItems: "0123456789:;<ABCDEFGHJIKLMNOPQRSTUVWXYZ"
			       count: 39];
	[d setObject: @"data" forKey: data];

	TEST(@"-[stringBySerializing]",
	    (s = d.stringBySerializing) && [s isEqual:
	    [OFString stringWithContentsOfFile: @"serialization.xml"]])

	TEST(@"-[objectByDeserializing]", [s.objectByDeserializing isEqual: d])


	objc_autoreleasePoolPop(pool);
}
@end







|





|
|
|

|

|
|
|
|
|

|
|

|
|
|
|

>
|
|


|



|


|


|
>




13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
 * file.
 */

#include "config.h"

#import "TestsAppDelegate.h"

static OFString *const module = @"OFSerialization";

@implementation TestsAppDelegate (OFSerializationTests)
- (void)serializationTests
{
	void *pool = objc_autoreleasePoolPush();
	OFMutableDictionary *dict = [OFMutableDictionary dictionary];
	OFMutableArray *array = [OFMutableArray array];
	OFList *list = [OFList list];
	OFData *data;
	OFString *string;

	[array addObject: @"Qu\"xbar\ntest"];
	[array addObject: [OFNumber numberWithInt: 1234]];
	[array addObject: [OFNumber numberWithDouble: 1234.5678]];
	[array addObject: [OFMutableString stringWithString: @"asd"]];
	[array addObject: [OFDate dateWithTimeIntervalSince1970: 1234.5678]];

	[dict setObject: @"Hello" forKey: array];
	[dict setObject: @"B\"la" forKey: @"Blub"];

	[list appendObject: @"Hello"];
	[list appendObject: @"Wo\rld!\nHow are you?"];
	[list appendObject: [OFURL URLWithString: @"https://objfw.nil.im/"]];
	[list appendObject:
	    [OFXMLElement elementWithXMLString: @"<x><y/><![CDATA[<]]></x>"]];
	[list appendObject:
	    [OFSet setWithObjects: @"foo", @"foo", @"bar", nil]];
	[list appendObject:
	    [OFCountedSet setWithObjects: @"foo", @"foo", @"bar", nil]];

	[dict setObject: @"list" forKey: list];

	data = [OFData dataWithItems: "0123456789:;<ABCDEFGHJIKLMNOPQRSTUVWXYZ"
			       count: 39];
	[dict setObject: @"data" forKey: data];

	TEST(@"-[stringBySerializing]",
	    (string = dict.stringBySerializing) && [string isEqual:
	    [OFString stringWithContentsOfFile: @"serialization.xml"]])

	TEST(@"-[objectByDeserializing]",
	    [string.objectByDeserializing isEqual: dict])

	objc_autoreleasePoolPop(pool);
}
@end

Modified tests/OFSocketTests.m from [da7b4aa12b] to [bd6253505c].

48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
	a.sockaddr.in6.sin6_addr.s6_addr[10] = a5 >> 8;		\
	a.sockaddr.in6.sin6_addr.s6_addr[11] = a5 & 0xFF;	\
	a.sockaddr.in6.sin6_addr.s6_addr[12] = a6 >> 8;		\
	a.sockaddr.in6.sin6_addr.s6_addr[13] = a6 & 0xFF;	\
	a.sockaddr.in6.sin6_addr.s6_addr[14] = a7 >> 8;		\
	a.sockaddr.in6.sin6_addr.s6_addr[15] = a7 & 0xFF;

static OFString *module = @"Socket";

@implementation TestsAppDelegate (SocketTests)
- (void)socketTests
{
	void *pool = objc_autoreleasePoolPush();
	OFSocketAddress addr;

	TEST(@"Parsing an IPv4",
	    R(addr = OFSocketAddressParseIP(@"127.0.0.1", 1234)) &&







|

|







48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
	a.sockaddr.in6.sin6_addr.s6_addr[10] = a5 >> 8;		\
	a.sockaddr.in6.sin6_addr.s6_addr[11] = a5 & 0xFF;	\
	a.sockaddr.in6.sin6_addr.s6_addr[12] = a6 >> 8;		\
	a.sockaddr.in6.sin6_addr.s6_addr[13] = a6 & 0xFF;	\
	a.sockaddr.in6.sin6_addr.s6_addr[14] = a7 >> 8;		\
	a.sockaddr.in6.sin6_addr.s6_addr[15] = a7 & 0xFF;

static OFString *const module = @"OFSocket";

@implementation TestsAppDelegate (OFSocketTests)
- (void)socketTests
{
	void *pool = objc_autoreleasePoolPush();
	OFSocketAddress addr;

	TEST(@"Parsing an IPv4",
	    R(addr = OFSocketAddressParseIP(@"127.0.0.1", 1234)) &&

Modified tests/OFStreamTests.m from [ad2f2ab750] to [7f38bebd95].

13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
..
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
 * file.
 */

#include "config.h"

#import "TestsAppDelegate.h"

static OFString *module = @"OFStream";

@interface StreamTester: OFStream
{
	int state;
}
@end

@implementation StreamTester
- (bool)lowlevelIsAtEndOfStream
{
	return (state > 1);
}

- (size_t)lowlevelReadIntoBuffer: (void *)buffer length: (size_t)size
{
................................................................................
@end

@implementation TestsAppDelegate (OFStreamTests)
- (void)streamTests
{
	void *pool = objc_autoreleasePoolPush();
	size_t pageSize = [OFSystemInfo pageSize];
	StreamTester *t = [[[StreamTester alloc] init] autorelease];
	OFString *str;
	char *cstr;

	cstr = OFAllocMemory(pageSize - 2, 1);
	memset(cstr, 'X', pageSize - 3);
	cstr[pageSize - 3] = '\0';

	TEST(@"-[readLine]", [[t readLine] isEqual: @"foo"] &&
	    [(str = [t readLine]) length] == pageSize - 3 &&
	    !strcmp(str.UTF8String, cstr))

	OFFreeMemory(cstr);

	objc_autoreleasePoolPop(pool);
}
@end







|

|





|







 







|
|
|

|
|
|

|
|
|

|




13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
..
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
 * file.
 */

#include "config.h"

#import "TestsAppDelegate.h"

static OFString *const module = @"OFStream";

@interface StreamTest: OFStream
{
	int state;
}
@end

@implementation StreamTest
- (bool)lowlevelIsAtEndOfStream
{
	return (state > 1);
}

- (size_t)lowlevelReadIntoBuffer: (void *)buffer length: (size_t)size
{
................................................................................
@end

@implementation TestsAppDelegate (OFStreamTests)
- (void)streamTests
{
	void *pool = objc_autoreleasePoolPush();
	size_t pageSize = [OFSystemInfo pageSize];
	StreamTest *test = [[[StreamTest alloc] init] autorelease];
	OFString *string;
	char *cString;

	cString = OFAllocMemory(pageSize - 2, 1);
	memset(cString, 'X', pageSize - 3);
	cString[pageSize - 3] = '\0';

	TEST(@"-[readLine]", [[test readLine] isEqual: @"foo"] &&
	    (string = [test readLine]).length == pageSize - 3 &&
	    !strcmp(string.UTF8String, cString))

	OFFreeMemory(cString);

	objc_autoreleasePoolPop(pool);
}
@end

Modified tests/OFStringTests.m from [40fec06275] to [ebff40f9d8].

26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
...
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238

239
240
241
242
243
244
245
246
...
261
262
263
264
265
266
267
268
269
270

271
272
273


274
275
276
277

278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293

294
295
296
297
298
299
300

301
302
303
304

305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322

323
324
325

326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363

364
365
366
367
368
369
370
371
...
471
472
473
474
475
476
477
478

479
480
481
482
483
484
485
486
487
488
489
490
491
...
498
499
500
501
502
503
504

505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
...
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584

585

586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618

619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
...
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
....
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196

1197
1198
1199

1200
1201
1202
1203
1204

1205
1206
1207

1208
1209
1210
1211
1212
1213
1214
1215
....
1231
1232
1233
1234
1235
1236
1237

1238
1239
1240
1241
1242
1243
1244
1245
1246
1247

1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259

1260
1261
1262
1263
1264
1265
1266
1267

1268
1269

1270
1271
1272
1273
1274
1275
1276

1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302

1303
1304
1305
1306
1307

1308
1309
1310
1311
1312

1313
1314
1315

1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327

1328
1329
1330

1331
1332

1333
1334

1335
1336
1337

1338
1339

1340
1341

1342
1343


1344
1345

1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
....
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
#import "OFUTF8String.h"

#ifndef INFINITY
# define INFINITY __builtin_inf()
#endif

static OFString *module = nil;
static OFString *whitespace[] = {
	@" \r \t\n\t \tasd  \t \t\t\r\n",
	@" \t\t  \t\t  \t \t"
};
static OFUnichar ucstr[] = {
	0xFEFF, 'f', 0xF6, 0xF6, 'b', 0xE4, 'r', 0x1F03A, 0
};
static OFUnichar sucstr[] = {
	0xFFFE0000, 0x66000000, 0xF6000000, 0xF6000000, 0x62000000, 0xE4000000,
	0x72000000, 0x3AF00100, 0
};
static uint16_t utf16str[] = {
	0xFEFF, 'f', 0xF6, 0xF6, 'b', 0xE4, 'r', 0xD83C, 0xDC3A, 0
};
static uint16_t sutf16str[] = {
	0xFFFE, 0x6600, 0xF600, 0xF600, 0x6200, 0xE400, 0x7200, 0x3CD8, 0x3ADC,
	0
};

@interface SimpleString: OFString
{
	OFMutableString *_string;
................................................................................
@end

@implementation TestsAppDelegate (OFStringTests)
- (void)stringTestsWithClass: (Class)stringClass
		mutableClass: (Class)mutableStringClass
{
	void *pool = objc_autoreleasePoolPush();
	OFMutableString *s[3];
	OFString *is;
	OFArray *a;
	size_t i;
	const OFUnichar *ua;
	const uint16_t *u16a;
	OFCharacterSet *cs;
	EntityHandler *h;
#ifdef OF_HAVE_BLOCKS
	__block int j;
	__block bool ok;
#endif

#define C(s) ((OFString *)[stringClass stringWithString: s])

	s[0] = [mutableStringClass stringWithString: @"täs€"];
	s[1] = [mutableStringClass string];
	s[2] = [[s[0] copy] autorelease];

	TEST(@"-[isEqual:]", [s[0] isEqual: s[2]] &&
	    ![s[0] isEqual: [[[OFObject alloc] init] autorelease]])

	TEST(@"-[compare:]", [s[0] compare: s[2]] == OFOrderedSame &&

	    [s[0] compare: @""] != OFOrderedSame &&
	    [C(@"") compare: @"a"] == OFOrderedAscending &&
	    [C(@"a") compare: @"b"] == OFOrderedAscending &&
	    [C(@"cd") compare: @"bc"] == OFOrderedDescending &&
	    [C(@"ä") compare: @"ö"] == OFOrderedAscending &&
	    [C(@"€") compare: @"ß"] == OFOrderedDescending &&
	    [C(@"aa") compare: @"z"] == OFOrderedAscending)

................................................................................
	    [C(@"AA") caseInsensitiveCompare: @"z"] == OFOrderedAscending &&
	    [[stringClass stringWithUTF8String: "ABC"] caseInsensitiveCompare:
	    [stringClass stringWithUTF8String: "AbD"]] ==
	    [C(@"abc") compare: @"abd"])
#endif

	TEST(@"-[hash] is the same if -[isEqual:] is true",
	    s[0].hash == s[2].hash)

	TEST(@"-[description]", [s[0].description isEqual: s[0]])


	TEST(@"-[appendString:] and -[appendUTF8String:]",
	    R([s[1] appendUTF8String: "1𝄞"]) && R([s[1] appendString: @"3"]) &&


	    R([s[0] appendString: s[1]]) && [s[0] isEqual: @"täs€1𝄞3"])

	TEST(@"-[appendCharacters:length:]",
	    R([s[1] appendCharacters: ucstr + 6 length: 2]) &&

	   [s[1] isEqual: @"1𝄞3r🀺"])

	TEST(@"-[length]", s[0].length == 7)
	TEST(@"-[UTF8StringLength]", s[0].UTF8StringLength == 13)
	TEST(@"-[hash]", s[0].hash == 0x705583C0)

	TEST(@"-[characterAtIndex:]",
	    [s[0] characterAtIndex: 0] == 't' &&
	    [s[0] characterAtIndex: 1] == 0xE4 &&
	    [s[0] characterAtIndex: 3] == 0x20AC &&
	    [s[0] characterAtIndex: 5] == 0x1D11E)

	EXPECT_EXCEPTION(@"Detect out of range in -[characterAtIndex:]",
	    OFOutOfRangeException, [s[0] characterAtIndex: 7])

	TEST(@"-[reverse]", R([s[0] reverse]) && [s[0] isEqual: @"3𝄞1€sät"])


	s[1] = [mutableStringClass stringWithString: @"abc"];

#ifdef OF_HAVE_UNICODE_TABLES
	TEST(@"-[uppercase]", R([s[0] uppercase]) &&
	    [s[0] isEqual: @"3𝄞1€SÄT"] &&
	    R([s[1] uppercase]) && [s[1] isEqual: @"ABC"])


	TEST(@"-[lowercase]", R([s[0] lowercase]) &&
	    [s[0] isEqual: @"3𝄞1€sät"] &&
	    R([s[1] lowercase]) && [s[1] isEqual: @"abc"])


	TEST(@"-[uppercaseString]",
	    [[s[0] uppercaseString] isEqual: @"3𝄞1€SÄT"])

	TEST(@"-[lowercaseString]", R([s[0] uppercase]) &&
	    [[s[0] lowercaseString] isEqual: @"3𝄞1€sät"])

	TEST(@"-[capitalizedString]", [C(@"džbla tdžst TDŽST").capitalizedString
	    isEqual: @"Džbla Tdžst Tdžst"])
#else
	TEST(@"-[uppercase]", R([s[0] uppercase]) &&
	    [s[0] isEqual: @"3𝄞1€SäT"] &&
	    R([s[1] uppercase]) && [s[1] isEqual: @"ABC"])

	TEST(@"-[lowercase]", R([s[0] lowercase]) &&
	    [s[0] isEqual: @"3𝄞1€sät"] &&
	    R([s[1] lowercase]) && [s[1] isEqual: @"abc"])


	TEST(@"-[uppercaseString]", [s[0].uppercaseString isEqual: @"3𝄞1€SäT"])

	TEST(@"-[lowercaseString]", R([s[0] uppercase]) &&

	    [s[0].lowercaseString isEqual: @"3𝄞1€sät"])

	TEST(@"-[capitalizedString]", [C(@"džbla tdžst TDŽST").capitalizedString
	    isEqual: @"džbla Tdžst TDŽst"])
#endif

	TEST(@"+[stringWithUTF8String:length:]",
	    (s[0] = [mutableStringClass stringWithUTF8String: "\xEF\xBB\xBF"
							      "foobar"
						      length: 6]) &&
	    [s[0] isEqual: @"foo"])

	TEST(@"+[stringWithUTF16String:]",
	    (is = [stringClass stringWithUTF16String: utf16str]) &&
	    [is isEqual: @"fööbär🀺"] &&
	    (is = [stringClass stringWithUTF16String: sutf16str]) &&
	    [is isEqual: @"fööbär🀺"])

	TEST(@"+[stringWithUTF32String:]",
	    (is = [stringClass stringWithUTF32String: ucstr]) &&
	    [is isEqual: @"fööbär🀺"] &&
	    (is = [stringClass stringWithUTF32String: sucstr]) &&
	    [is isEqual: @"fööbär🀺"])

#ifdef OF_HAVE_FILES
	TEST(@"+[stringWithContentsOfFile:encoding]", (is = [stringClass
	    stringWithContentsOfFile: @"testfile.txt"
			    encoding: OFStringEncodingISO8859_1]) &&
	    [is isEqual: @"testäöü"])

	TEST(@"+[stringWithContentsOfURL:encoding]", (is = [stringClass
	    stringWithContentsOfURL: [OFURL fileURLWithPath: @"testfile.txt"]
			   encoding: OFStringEncodingISO8859_1]) &&
	    [is isEqual: @"testäöü"])
#endif

	TEST(@"-[appendUTFString:length:]",
	    R([s[0] appendUTF8String: "\xEF\xBB\xBF" "barqux" length: 6]) &&

	    [s[0] isEqual: @"foobar"])

	EXPECT_EXCEPTION(@"Detection of invalid UTF-8 encoding #1",
	    OFInvalidEncodingException,
	    [stringClass stringWithUTF8String: "\xE0\x80"])
	EXPECT_EXCEPTION(@"Detection of invalid UTF-8 encoding #2",
	    OFInvalidEncodingException,
	    [stringClass stringWithUTF8String: "\xF0\x80\x80\xC0"])
................................................................................
#ifdef HAVE_CODEPAGE_437
	TEST(@"Lossy conversion of Unicode to Codepage 437",
	    !strcmp([C(@"T€st strîng ░▒▓") lossyCStringWithEncoding:
	    OFStringEncodingCodepage437], "T?st str\x8Cng \xB0\xB1\xB2"))
#endif

	TEST(@"+[stringWithFormat:]",
	    [(s[0] = [mutableStringClass stringWithFormat: @"%@:%d", @"test",

							   123])
	    isEqual: @"test:123"])

	TEST(@"-[appendFormat:]",
	    R(([s[0] appendFormat: @"%02X", 15])) &&
	    [s[0] isEqual: @"test:1230F"])

	TEST(@"-[rangeOfString:]",
	    [C(@"𝄞öö") rangeOfString: @"öö"].location == 1 &&
	    [C(@"𝄞öö") rangeOfString: @"ö"].location == 1 &&
	    [C(@"𝄞öö") rangeOfString: @"𝄞"].location == 0 &&
	    [C(@"𝄞öö") rangeOfString: @"x"].location == OFNotFound &&
	    [C(@"𝄞öö") rangeOfString: @"öö"
................................................................................
	    options: OFStringSearchBackwards].location == OFNotFound)

	EXPECT_EXCEPTION(
	    @"Detect out of range in -[rangeOfString:options:range:]",
	    OFOutOfRangeException,
	    [C(@"𝄞öö") rangeOfString: @"ö" options: 0 range: OFRangeMake(3, 1)])


	cs = [OFCharacterSet characterSetWithCharactersInString: @"cđ"];
	TEST(@"-[indexOfCharacterFromSet:]",
	     [C(@"abcđabcđe") indexOfCharacterFromSet: cs] == 2 &&
	     [C(@"abcđabcđë")
	     indexOfCharacterFromSet: cs
			     options: OFStringSearchBackwards] == 7 &&
	     [C(@"abcđabcđë")
	     indexOfCharacterFromSet: cs
			     options: 0
			       range: OFRangeMake(4, 4)] == 6 &&
	     [C(@"abcđabcđëf")
	     indexOfCharacterFromSet: cs
			     options: 0
			       range: OFRangeMake(8, 2)] == OFNotFound)

	EXPECT_EXCEPTION(
	    @"Detect out of range in -[indexOfCharacterFromSet:options:range:]",
	    OFOutOfRangeException,
	    [C(@"𝄞öö") indexOfCharacterFromSet: cs
				       options: 0
					 range: OFRangeMake(3, 1)])

	TEST(@"-[substringWithRange:]",
	    [[C(@"𝄞öö") substringWithRange: OFRangeMake(1, 1)] isEqual: @"ö"] &&
	    [[C(@"𝄞öö") substringWithRange: OFRangeMake(3, 0)] isEqual: @""])

................................................................................
	    !C(@"foo/bar").absolutePath && !C(@"foo").absolutePath)
# else
	TEST(@"-[isAbsolutePath]",
	    C(@"/foo").absolutePath && C(@"/foo/bar").absolutePath &&
	    !C(@"foo/bar").absolutePath && !C(@"foo").absolutePath)
# endif

	s[0] = [mutableStringClass stringWithString: @"foo"];
# if defined(OF_WINDOWS) || defined(OF_MSDOS)
	[s[0] appendString: @"\\"];
# else
	[s[0] appendString: @"/"];
# endif
	[s[0] appendString: @"bar"];
	s[1] = [mutableStringClass stringWithString: s[0]];
# if defined(OF_WINDOWS) || defined(OF_MSDOS)
	[s[1] appendString: @"\\"];
# else
	[s[1] appendString: @"/"];
# endif
	is = [stringClass stringWithString: s[1]];
	[s[1] appendString: @"baz"];
	TEST(@"-[stringByAppendingPathComponent:]",
	    [[s[0] stringByAppendingPathComponent: @"baz"] isEqual: s[1]] &&

	    [[is stringByAppendingPathComponent: @"baz"] isEqual: s[1]])

#endif

	TEST(@"-[hasPrefix:]", [C(@"foobar") hasPrefix: @"foo"] &&
	    ![C(@"foobar") hasPrefix: @"foobar0"])

	TEST(@"-[hasSuffix:]", [C(@"foobar") hasSuffix: @"bar"] &&
	    ![C(@"foobar") hasSuffix: @"foobar0"])

	i = 0;
	TEST(@"-[componentsSeparatedByString:]",
	    (a = [C(@"fooXXbarXXXXbazXXXX")
	    componentsSeparatedByString: @"XX"]) &&
	    [[a objectAtIndex: i++] isEqual: @"foo"] &&
	    [[a objectAtIndex: i++] isEqual: @"bar"] &&
	    [[a objectAtIndex: i++] isEqual: @""] &&
	    [[a objectAtIndex: i++] isEqual: @"baz"] &&
	    [[a objectAtIndex: i++] isEqual: @""] &&
	    [[a objectAtIndex: i++] isEqual: @""] &&
	    a.count == i &&
	    (a = [C(@"foo") componentsSeparatedByString: @""]) &&
	    [[a objectAtIndex: 0] isEqual: @"foo"] &&
	    a.count == 1)

	i = 0;
	TEST(@"-[componentsSeparatedByString:options:]",
	    (a = [C(@"fooXXbarXXXXbazXXXX")
	    componentsSeparatedByString: @"XX"
				options: OFStringSkipEmptyComponents]) &&
	    [[a objectAtIndex: i++] isEqual: @"foo"] &&
	    [[a objectAtIndex: i++] isEqual: @"bar"] &&
	    [[a objectAtIndex: i++] isEqual: @"baz"] &&
	    a.count == i)


	cs = [OFCharacterSet characterSetWithCharactersInString: @"XYZ"];

	i = 0;
	TEST(@"-[componentsSeparatedByCharactersInSet:]",
	    (a = [C(@"fooXYbarXYZXbazXYXZx")
	    componentsSeparatedByCharactersInSet: cs]) &&
	    [[a objectAtIndex: i++] isEqual: @"foo"] &&
	    [[a objectAtIndex: i++] isEqual: @""] &&
	    [[a objectAtIndex: i++] isEqual: @"bar"] &&
	    [[a objectAtIndex: i++] isEqual: @""] &&
	    [[a objectAtIndex: i++] isEqual: @""] &&
	    [[a objectAtIndex: i++] isEqual: @""] &&
	    [[a objectAtIndex: i++] isEqual: @"baz"] &&
	    [[a objectAtIndex: i++] isEqual: @""] &&
	    [[a objectAtIndex: i++] isEqual: @""] &&
	    [[a objectAtIndex: i++] isEqual: @""] &&
	    [[a objectAtIndex: i++] isEqual: @"x"] &&
	    a.count == i)

	i = 0;
	TEST(@"-[componentsSeparatedByCharactersInSet:options:]",
	    (a = [C(@"fooXYbarXYZXbazXYXZ")
	    componentsSeparatedByCharactersInSet: cs
	    options: OFStringSkipEmptyComponents]) &&
	    [[a objectAtIndex: i++] isEqual: @"foo"] &&
	    [[a objectAtIndex: i++] isEqual: @"bar"] &&
	    [[a objectAtIndex: i++] isEqual: @"baz"] &&
	    a.count == i)

#ifdef OF_HAVE_FILES
# if defined(OF_WINDOWS)
	TEST(@"+[pathWithComponents:]",
	    [[stringClass pathWithComponents: [OFArray arrayWithObjects:
	    @"foo", @"bar", @"baz", nil]] isEqual: @"foo\\bar\\baz"] &&
	    [[stringClass pathWithComponents: [OFArray arrayWithObjects:
................................................................................
	    [[stringClass pathWithComponents: [OFArray arrayWithObjects:
	    @"foo", nil]] isEqual: @"foo"])
# endif

# if defined(OF_WINDOWS)
	TEST(@"-[pathComponents]",
	    /* c:/tmp */
	    (a = C(@"c:/tmp").pathComponents) && a.count == 2 &&
	    [[a objectAtIndex: 0] isEqual: @"c:/"] &&
	    [[a objectAtIndex: 1] isEqual: @"tmp"] &&
	    /* c:\tmp\ */
	    (a = C(@"c:\\tmp\\").pathComponents) && a.count == 2 &&
	    [[a objectAtIndex: 0] isEqual: @"c:\\"] &&
	    [[a objectAtIndex: 1] isEqual: @"tmp"] &&
	    /* c:\ */
	    (a = C(@"c:\\").pathComponents) && a.count == 1 &&
	    [[a objectAtIndex: 0] isEqual: @"c:\\"] &&
	    /* c:/ */
	    (a = C(@"c:/").pathComponents) && a.count == 1 &&
	    [[a objectAtIndex: 0] isEqual: @"c:/"] &&
	    /* c: */
	    (a = C(@"c:").pathComponents) && a.count == 1 &&
	    [[a objectAtIndex: 0] isEqual: @"c:"] &&
	    /* foo\bar */
	    (a = C(@"foo\\bar").pathComponents) && a.count == 2 &&
	    [[a objectAtIndex: 0] isEqual: @"foo"] &&
	    [[a objectAtIndex: 1] isEqual: @"bar"] &&
	    /* foo\bar/baz/ */
	    (a = C(@"foo\\bar/baz/").pathComponents) && a.count == 3 &&
	    [[a objectAtIndex: 0] isEqual: @"foo"] &&
	    [[a objectAtIndex: 1] isEqual: @"bar"] &&
	    [[a objectAtIndex: 2] isEqual: @"baz"] &&
	    /* foo\/ */
	    (a = C(@"foo\\/").pathComponents) && a.count == 1 &&
	    [[a objectAtIndex: 0] isEqual: @"foo"] &&
	    /* \\foo\bar */
	    (a = C(@"\\\\foo\\bar").pathComponents) && a.count == 3 &&
	    [[a objectAtIndex: 0] isEqual: @"\\\\"] &&
	    [[a objectAtIndex: 1] isEqual: @"foo"] &&
	    [[a objectAtIndex: 2] isEqual: @"bar"] &&
	    C(@"").pathComponents.count == 0)
# elif defined(OF_MSDOS)
	TEST(@"-[pathComponents]",
	    /* c:/tmp */
	    (a = C(@"c:/tmp").pathComponents) && a.count == 2 &&
	    [[a objectAtIndex: 0] isEqual: @"c:/"] &&
	    [[a objectAtIndex: 1] isEqual: @"tmp"] &&
	    /* c:\tmp\ */
	    (a = C(@"c:\\tmp\\").pathComponents) && a.count == 2 &&
	    [[a objectAtIndex: 0] isEqual: @"c:\\"] &&
	    [[a objectAtIndex: 1] isEqual: @"tmp"] &&
	    /* c:\ */
	    (a = C(@"c:\\").pathComponents) && a.count == 1 &&
	    [[a objectAtIndex: 0] isEqual: @"c:\\"] &&
	    /* c:/ */
	    (a = C(@"c:/").pathComponents) && a.count == 1 &&
	    [[a objectAtIndex: 0] isEqual: @"c:/"] &&
	    /* c: */
	    (a = C(@"c:").pathComponents) && a.count == 1 &&
	    [[a objectAtIndex: 0] isEqual: @"c:"] &&
	    /* foo\bar */
	    (a = C(@"foo\\bar").pathComponents) && a.count == 2 &&
	    [[a objectAtIndex: 0] isEqual: @"foo"] &&
	    [[a objectAtIndex: 1] isEqual: @"bar"] &&
	    /* foo\bar/baz/ */
	    (a = C(@"foo\\bar/baz/").pathComponents) && a.count == 3 &&
	    [[a objectAtIndex: 0] isEqual: @"foo"] &&
	    [[a objectAtIndex: 1] isEqual: @"bar"] &&
	    [[a objectAtIndex: 2] isEqual: @"baz"] &&
	    /* foo\/ */
	    (a = C(@"foo\\/").pathComponents) && a.count == 1 &&
	    [[a objectAtIndex: 0] isEqual: @"foo"] &&
	    C(@"").pathComponents.count == 0)
# elif defined(OF_AMIGAOS)
	TEST(@"-[pathComponents]",
	    /* dh0:tmp */
	    (a = C(@"dh0:tmp").pathComponents) && a.count == 2 &&
	    [[a objectAtIndex: 0] isEqual: @"dh0:"] &&
	    [[a objectAtIndex: 1] isEqual: @"tmp"] &&
	    /* dh0:tmp/ */
	    (a = C(@"dh0:tmp/").pathComponents) && a.count == 2 &&
	    [[a objectAtIndex: 0] isEqual: @"dh0:"] &&
	    [[a objectAtIndex: 1] isEqual: @"tmp"] &&
	    /* dh0: */
	    (a = C(@"dh0:/").pathComponents) && a.count == 2 &&
	    [[a objectAtIndex: 0] isEqual: @"dh0:"] &&
	    [[a objectAtIndex: 1] isEqual: @"/"] &&
	    /* foo/bar */
	    (a = C(@"foo/bar").pathComponents) && a.count == 2 &&
	    [[a objectAtIndex: 0] isEqual: @"foo"] &&
	    [[a objectAtIndex: 1] isEqual: @"bar"] &&
	    /* foo/bar/baz/ */
	    (a = C(@"foo/bar/baz/").pathComponents) && a.count == 3 &&
	    [[a objectAtIndex: 0] isEqual: @"foo"] &&
	    [[a objectAtIndex: 1] isEqual: @"bar"] &&
	    [[a objectAtIndex: 2] isEqual: @"baz"] &&
	    /* foo// */
	    (a = C(@"foo//").pathComponents) && a.count == 2 &&
	    [[a objectAtIndex: 0] isEqual: @"foo"] &&
	    [[a objectAtIndex: 1] isEqual: @"/"] &&
	    C(@"").pathComponents.count == 0)
# elif defined(OF_NINTENDO_3DS) || defined(OF_WII)
	TEST(@"-[pathComponents]",
	    /* sdmc:/tmp */
	    (a = C(@"sdmc:/tmp").pathComponents) && a.count == 2 &&
	    [[a objectAtIndex: 0] isEqual: @"sdmc:"] &&
	    [[a objectAtIndex: 1] isEqual: @"tmp"] &&
	    /* sdmc:/ */
	    (a = C(@"sdmc:/").pathComponents) && a.count == 1 &&
	    [[a objectAtIndex: 0] isEqual: @"sdmc:"] &&
	    /* foo/bar */
	    (a = C(@"foo/bar").pathComponents) && a.count == 2 &&
	    [[a objectAtIndex: 0] isEqual: @"foo"] &&
	    [[a objectAtIndex: 1] isEqual: @"bar"] &&
	    /* foo/bar/baz/ */
	    (a = C(@"foo/bar/baz/").pathComponents) && a.count == 3 &&
	    [[a objectAtIndex: 0] isEqual: @"foo"] &&
	    [[a objectAtIndex: 1] isEqual: @"bar"] &&
	    [[a objectAtIndex: 2] isEqual: @"baz"] &&
	    /* foo// */
	    (a = C(@"foo//").pathComponents) && a.count == 1 &&
	    [[a objectAtIndex: 0] isEqual: @"foo"] &&
	    C(@"").pathComponents.count == 0)
# else
	TEST(@"-[pathComponents]",
	    /* /tmp */
	    (a = C(@"/tmp").pathComponents) && a.count == 2 &&
	    [[a objectAtIndex: 0] isEqual: @"/"] &&
	    [[a objectAtIndex: 1] isEqual: @"tmp"] &&
	    /* /tmp/ */
	    (a = C(@"/tmp/").pathComponents) && a.count == 2 &&
	    [[a objectAtIndex: 0] isEqual: @"/"] &&
	    [[a objectAtIndex: 1] isEqual: @"tmp"] &&
	    /* / */
	    (a = C(@"/").pathComponents) && a.count == 1 &&
	    [[a objectAtIndex: 0] isEqual: @"/"] &&
	    /* foo/bar */
	    (a = C(@"foo/bar").pathComponents) && a.count == 2 &&
	    [[a objectAtIndex: 0] isEqual: @"foo"] &&
	    [[a objectAtIndex: 1] isEqual: @"bar"] &&
	    /* foo/bar/baz/ */
	    (a = C(@"foo/bar/baz/").pathComponents) && a.count == 3 &&
	    [[a objectAtIndex: 0] isEqual: @"foo"] &&
	    [[a objectAtIndex: 1] isEqual: @"bar"] &&
	    [[a objectAtIndex: 2] isEqual: @"baz"] &&
	    /* foo// */
	    (a = C(@"foo//").pathComponents) && a.count == 1 &&
	    [[a objectAtIndex: 0] isEqual: @"foo"] &&
	    C(@"").pathComponents.count == 0)
# endif

# if defined(OF_WINDOWS)
	TEST(@"-[lastPathComponent]",
	    [C(@"c:/tmp").lastPathComponent isEqual: @"tmp"] &&
	    [C(@"c:\\tmp\\").lastPathComponent isEqual: @"tmp"] &&
................................................................................

	EXPECT_EXCEPTION(@"Detect out of range in -[unsignedLongLongValue]",
	    OFOutOfRangeException,
	    [C(@"0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF"
	       @"0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF")
	    unsignedLongLongValueWithBase: 16])

	TEST(@"-[characters]", (ua = C(@"fööbär🀺").characters) &&
	    !memcmp(ua, ucstr + 1, sizeof(ucstr) - 8))

#ifdef OF_BIG_ENDIAN
# define SWAPPED_BYTE_ORDER OFByteOrderLittleEndian
#else
# define SWAPPED_BYTE_ORDER OFByteOrderBigEndian
#endif
	TEST(@"-[UTF16String]", (u16a = C(@"fööbär🀺").UTF16String) &&

	    !memcmp(u16a, utf16str + 1, OFUTF16StringLength(utf16str) * 2) &&
	    (u16a = [C(@"fööbär🀺")
	    UTF16StringWithByteOrder: SWAPPED_BYTE_ORDER]) &&

	    !memcmp(u16a, sutf16str + 1, OFUTF16StringLength(sutf16str) * 2))

	TEST(@"-[UTF16StringLength]", C(@"fööbär🀺").UTF16StringLength == 8)

	TEST(@"-[UTF32String]", (ua = C(@"fööbär🀺").UTF32String) &&

	    !memcmp(ua, ucstr + 1, OFUTF32StringLength(ucstr) * 4) &&
	    (ua = [C(@"fööbär🀺") UTF32StringWithByteOrder:
	    SWAPPED_BYTE_ORDER]) &&

	    !memcmp(ua, sucstr + 1, OFUTF32StringLength(sucstr) * 4))
#undef SWAPPED_BYTE_ORDER

	TEST(@"-[stringByMD5Hashing]", [C(@"asdfoobar").stringByMD5Hashing
	    isEqual: @"184dce2ec49b5422c7cfd8728864db4c"])

	TEST(@"-[stringByRIPEMD160Hashing]",
	    [C(@"asdfoobar").stringByRIPEMD160Hashing
................................................................................
		     @"279e5addf8be854044bca0cece073fce28eec7d9"])

	TEST(@"-[stringBySHA512Hashing]", [C(@"asdfoobar").stringBySHA512Hashing
	    isEqual: @"0464c427da158b02161bb44a3090bbfc594611ef6a53603640454b56"
		     @"412a9247c3579a329e53a5dc74676b106755e3394f9454a2d4227324"
		     @"2615d32f80437d61"])


	cs = [OFCharacterSet characterSetWithCharactersInString: @"abfo'_~$🍏"];
	TEST(@"-[stringByURLEncodingWithAllowedCharacters:]",
	    [[C(@"foo\"ba'_~$]🍏🍌") stringByURLEncodingWithAllowedCharacters:
	    cs] isEqual: @"foo%22ba'_~$%5D🍏%F0%9F%8D%8C"])

	TEST(@"-[stringByURLDecoding]",
	    [C(@"foo%20bar%22+%24%F0%9F%8D%8C").stringByURLDecoding
	    isEqual: @"foo bar\"+$🍌"])

	TEST(@"-[insertString:atIndex:]",

	    (s[0] = [mutableStringClass stringWithString: @"𝄞öööbä€"]) &&
	    R([s[0] insertString: @"äöü" atIndex: 3]) &&
	    [s[0] isEqual: @"𝄞ööäöüöbä€"])

	EXPECT_EXCEPTION(@"Detect invalid format in -[stringByURLDecoding] "
	    @"#1", OFInvalidFormatException,
	    [C(@"foo%xbar") stringByURLDecoding])
	EXPECT_EXCEPTION(@"Detect invalid encoding in -[stringByURLDecoding] "
	    @"#2", OFInvalidEncodingException,
	    [C(@"foo%FFbar") stringByURLDecoding])

	TEST(@"-[setCharacter:atIndex:]",

	    (s[0] = [mutableStringClass stringWithString: @"abäde"]) &&
	    R([s[0] setCharacter: 0xF6 atIndex: 2]) &&
	    [s[0] isEqual: @"aböde"] &&
	    R([s[0] setCharacter: 'c' atIndex: 2]) &&
	    [s[0] isEqual: @"abcde"] &&
	    R([s[0] setCharacter: 0x20AC atIndex: 3]) &&
	    [s[0] isEqual: @"abc€e"] &&
	    R([s[0] setCharacter: 'x' atIndex: 1]) && [s[0] isEqual: @"axc€e"])


	TEST(@"-[deleteCharactersInRange:]",

	    (s[0] = [mutableStringClass stringWithString: @"𝄞öööbä€"]) &&
	    R([s[0] deleteCharactersInRange: OFRangeMake(1, 3)]) &&
	    [s[0] isEqual: @"𝄞bä€"] &&
	    R([s[0] deleteCharactersInRange: OFRangeMake(0, 4)]) &&
	    [s[0] isEqual: @""])

	TEST(@"-[replaceCharactersInRange:withString:]",

	    (s[0] = [mutableStringClass stringWithString: @"𝄞öööbä€"]) &&
	    R([s[0] replaceCharactersInRange: OFRangeMake(1, 3)
				  withString: @"äöüß"]) &&
	    [s[0] isEqual: @"𝄞äöüßbä€"] &&
	    R([s[0] replaceCharactersInRange: OFRangeMake(4, 2)
				  withString: @"b"]) &&
	    [s[0] isEqual: @"𝄞äöübä€"] &&
	    R([s[0] replaceCharactersInRange: OFRangeMake(0, 7)
				  withString: @""]) &&
	    [s[0] isEqual: @""])

	EXPECT_EXCEPTION(@"Detect OoR in -[deleteCharactersInRange:] #1",
	    OFOutOfRangeException,
	    {
		s[0] = [mutableStringClass stringWithString: @"𝄞öö"];
		[s[0] deleteCharactersInRange: OFRangeMake(2, 2)];
	    })

	EXPECT_EXCEPTION(@"Detect OoR in -[deleteCharactersInRange:] #2",
	    OFOutOfRangeException,
	    [s[0] deleteCharactersInRange: OFRangeMake(4, 0)])

	EXPECT_EXCEPTION(@"Detect OoR in "
	    @"-[replaceCharactersInRange:withString:] #1",
	    OFOutOfRangeException,
	    [s[0] replaceCharactersInRange: OFRangeMake(2, 2) withString: @""])


	EXPECT_EXCEPTION(@"Detect OoR in "
	    @"-[replaceCharactersInRange:withString:] #2",
	    OFOutOfRangeException,
	    [s[0] replaceCharactersInRange: OFRangeMake(4, 0) withString: @""])


	TEST(@"-[replaceOccurrencesOfString:withString:]",
	    (s[0] = [mutableStringClass stringWithString:
	    @"asd fo asd fofo asd"]) &&
	    R([s[0] replaceOccurrencesOfString: @"fo" withString: @"foo"]) &&

	    [s[0] isEqual: @"asd foo asd foofoo asd"] &&
	    (s[0] = [mutableStringClass stringWithString: @"XX"]) &&
	    R([s[0] replaceOccurrencesOfString: @"X" withString: @"XX"]) &&

	    [s[0] isEqual: @"XXXX"])

	TEST(@"-[replaceOccurrencesOfString:withString:options:range:]",
	    (s[0] = [mutableStringClass stringWithString:
	    @"foofoobarfoobarfoo"]) &&
	    R([s[0] replaceOccurrencesOfString: @"oo"
				    withString: @"óò"
				       options: 0
					 range: OFRangeMake(2, 15)]) &&
	    [s[0] isEqual: @"foofóòbarfóòbarfoo"])

	TEST(@"-[deleteLeadingWhitespaces]",

	    (s[0] = [mutableStringClass stringWithString: whitespace[0]]) &&
	    R([s[0] deleteLeadingWhitespaces]) &&
	    [s[0] isEqual: @"asd  \t \t\t\r\n"] &&

	    (s[0] = [mutableStringClass stringWithString: whitespace[1]]) &&
	    R([s[0] deleteLeadingWhitespaces]) && [s[0] isEqual: @""])


	TEST(@"-[deleteTrailingWhitespaces]",

	    (s[0] = [mutableStringClass stringWithString: whitespace[0]]) &&
	    R([s[0] deleteTrailingWhitespaces]) &&
	    [s[0] isEqual: @" \r \t\n\t \tasd"] &&

	    (s[0] = [mutableStringClass stringWithString: whitespace[1]]) &&
	    R([s[0] deleteTrailingWhitespaces]) && [s[0] isEqual: @""])


	TEST(@"-[deleteEnclosingWhitespaces]",

	    (s[0] = [mutableStringClass stringWithString: whitespace[0]]) &&
	    R([s[0] deleteEnclosingWhitespaces]) && [s[0] isEqual: @"asd"] &&


	    (s[0] = [mutableStringClass stringWithString: whitespace[1]]) &&
	    R([s[0] deleteEnclosingWhitespaces]) && [s[0] isEqual: @""])


#ifdef OF_HAVE_UNICODE_TABLES
	TEST(@"-[decomposedStringWithCanonicalMapping]",
	    [C(@"H\xC3\xA4llj\xC3\xB6").decomposedStringWithCanonicalMapping
	    isEqual: @"H\x61\xCC\x88llj\x6F\xCC\x88"]);

	TEST(@"-[decomposedStringWithCompatibilityMapping]",
	    [C(@"H\xC3\xA4llj\xC3\xB6").decomposedStringWithCompatibilityMapping
	    isEqual: @"H\x61\xCC\x88llj\x6F\xCC\x88"]);
#endif

	TEST(@"-[stringByXMLEscaping]",
	    (is = C(@"<hello> &world'\"!&").stringByXMLEscaping) &&
	    [is isEqual: @"&lt;hello&gt; &amp;world&apos;&quot;!&amp;"])

	TEST(@"-[stringByXMLUnescaping]",
	    [is.stringByXMLUnescaping isEqual: @"<hello> &world'\"!&"] &&
	    [C(@"&#x79;").stringByXMLUnescaping isEqual: @"y"] &&
	    [C(@"&#xe4;").stringByXMLUnescaping isEqual: @"ä"] &&
	    [C(@"&#8364;").stringByXMLUnescaping isEqual: @"€"] &&
	    [C(@"&#x1D11E;").stringByXMLUnescaping isEqual: @"𝄞"])

	EXPECT_EXCEPTION(@"Detect unknown entities in -[stringByXMLUnescaping]",
	    OFUnknownXMLEntityException, [C(@"&foo;") stringByXMLUnescaping])
................................................................................
	EXPECT_EXCEPTION(@"Detect invalid entities in -[stringByXMLUnescaping] "
	    @"#4", OFInvalidFormatException, [C(@"&#g;") stringByXMLUnescaping])
	EXPECT_EXCEPTION(@"Detect invalid entities in -[stringByXMLUnescaping] "
	    @"#5", OFInvalidFormatException,
	    [C(@"&#xg;") stringByXMLUnescaping])

	TEST(@"-[stringByXMLUnescapingWithDelegate:]",
	    (h = [[[EntityHandler alloc] init] autorelease]) &&
	    [[C(@"x&foo;y") stringByXMLUnescapingWithDelegate: h]
	    isEqual: @"xbary"])

#ifdef OF_HAVE_BLOCKS
	TEST(@"-[stringByXMLUnescapingWithBlock:]",
	    [[C(@"x&foo;y") stringByXMLUnescapingWithBlock:
	        ^ OFString *(OFString *str, OFString *entity) {
		    if ([entity isEqual: @"foo"])
			    return @"bar";

		    return nil;
	    }] isEqual: @"xbary"])

	j = 0;







|



|


|



|


|







 







|
|
|

|
|
|
|







|
|
|

|
|

|
>
|







 







|

|
>


|
>
>
|


<
>
|

|
|
|


|
|
|
|


|

|
>

|


|
|
<
>

|
|
<
>


|

|
|




|
|
|

|
|
|

>
|

|
>
|






|
|
|
|


|
|
|
|


|
|
|
|


|


|

|


|



|
>
|







 







|
>
|



|
|







 







>
|

|
|
|
|
<
|
|
|
|
|
|
|




|







 







|

|

|

|
|

|

|

|
|

|
>
|
>










|

|
|
|
|
|
|
|
|
|
|



|


|
|
|
|

>
|



|
|
|
|
|
|
|
|
|
|
|
|
|
|



|
|

|
|
|
|







 







|
|
|

|
|
|

|
|

|
|

|
|

|
|
|

|
|
|
|

|
|

|
|
|
|




|
|
|

|
|
|

|
|

|
|

|
|

|
|
|

|
|
|
|

|
|




|
|
|

|
|
|

|
|
|

|
|
|

|
|
|
|

|
|
|




|
|
|

|
|

|
|
|

|
|
|
|

|
|




|
|
|

|
|
|

|
|

|
|
|

|
|
|
|

|
|







 







|
|






|
>
|
|

>
|



|
>
|
|

>
|







 







>
|


|






>
|
|
|









>
|
|
|
|
|
|
|
|
>


>
|
|
|
|
|


>
|
|
|
|
|
|
|
|
|
|




|
|




|




|
>




|
>


|

|
>
|
|
|
>
|


|
|
|
|
|
|
|


>
|
|
|
>
|
|
>


>
|
|
|
>
|
|
>


>
|
|
>
>
|
|
>












|
|


|







 







|
|





|







26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
...
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
...
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280

281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304

305
306
307
308

309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
...
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
...
507
508
509
510
511
512
513
514
515
516
517
518
519
520

521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
...
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
...
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
....
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
....
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
....
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
#import "OFUTF8String.h"

#ifndef INFINITY
# define INFINITY __builtin_inf()
#endif

static OFString *module = nil;
static OFString *const whitespace[] = {
	@" \r \t\n\t \tasd  \t \t\t\r\n",
	@" \t\t  \t\t  \t \t"
};
static const OFUnichar unicharString[] = {
	0xFEFF, 'f', 0xF6, 0xF6, 'b', 0xE4, 'r', 0x1F03A, 0
};
static const OFUnichar swappedUnicharString[] = {
	0xFFFE0000, 0x66000000, 0xF6000000, 0xF6000000, 0x62000000, 0xE4000000,
	0x72000000, 0x3AF00100, 0
};
static const uint16_t UTF16String[] = {
	0xFEFF, 'f', 0xF6, 0xF6, 'b', 0xE4, 'r', 0xD83C, 0xDC3A, 0
};
static const uint16_t swappedUTF16String[] = {
	0xFFFE, 0x6600, 0xF600, 0xF600, 0x6200, 0xE400, 0x7200, 0x3CD8, 0x3ADC,
	0
};

@interface SimpleString: OFString
{
	OFMutableString *_string;
................................................................................
@end

@implementation TestsAppDelegate (OFStringTests)
- (void)stringTestsWithClass: (Class)stringClass
		mutableClass: (Class)mutableStringClass
{
	void *pool = objc_autoreleasePoolPush();
	OFMutableString *mutableString1, *mutableString2, *mutableString3;
	OFString *string;
	OFArray *array;
	size_t i;
	const OFUnichar *characters;
	const uint16_t *UTF16Characters;
	OFCharacterSet *characterSet;
	EntityHandler *entityHandler;
#ifdef OF_HAVE_BLOCKS
	__block int j;
	__block bool ok;
#endif

#define C(s) ((OFString *)[stringClass stringWithString: s])

	mutableString1 = [mutableStringClass stringWithString: @"täs€"];
	mutableString2 = [mutableStringClass string];
	mutableString3 = [[mutableString1 copy] autorelease];

	TEST(@"-[isEqual:]", [mutableString1 isEqual: mutableString3] &&
	    ![mutableString1 isEqual: [[[OFObject alloc] init] autorelease]])

	TEST(@"-[compare:]",
	    [mutableString1 compare: mutableString3] == OFOrderedSame &&
	    [mutableString1 compare: @""] != OFOrderedSame &&
	    [C(@"") compare: @"a"] == OFOrderedAscending &&
	    [C(@"a") compare: @"b"] == OFOrderedAscending &&
	    [C(@"cd") compare: @"bc"] == OFOrderedDescending &&
	    [C(@"ä") compare: @"ö"] == OFOrderedAscending &&
	    [C(@"€") compare: @"ß"] == OFOrderedDescending &&
	    [C(@"aa") compare: @"z"] == OFOrderedAscending)

................................................................................
	    [C(@"AA") caseInsensitiveCompare: @"z"] == OFOrderedAscending &&
	    [[stringClass stringWithUTF8String: "ABC"] caseInsensitiveCompare:
	    [stringClass stringWithUTF8String: "AbD"]] ==
	    [C(@"abc") compare: @"abd"])
#endif

	TEST(@"-[hash] is the same if -[isEqual:] is true",
	    mutableString1.hash == mutableString3.hash)

	TEST(@"-[description]",
	    [mutableString1.description isEqual: mutableString1])

	TEST(@"-[appendString:] and -[appendUTF8String:]",
	    R([mutableString2 appendUTF8String: "1𝄞"]) &&
	    R([mutableString2 appendString: @"3"]) &&
	    R([mutableString1 appendString: mutableString2]) &&
	    [mutableString1 isEqual: @"täs€1𝄞3"])

	TEST(@"-[appendCharacters:length:]",

	    R([mutableString2 appendCharacters: unicharString + 6 length: 2]) &&
	    [mutableString2 isEqual: @"1𝄞3r🀺"])

	TEST(@"-[length]", mutableString1.length == 7)
	TEST(@"-[UTF8StringLength]", mutableString1.UTF8StringLength == 13)
	TEST(@"-[hash]", mutableString1.hash == 0x705583C0)

	TEST(@"-[characterAtIndex:]",
	    [mutableString1 characterAtIndex: 0] == 't' &&
	    [mutableString1 characterAtIndex: 1] == 0xE4 &&
	    [mutableString1 characterAtIndex: 3] == 0x20AC &&
	    [mutableString1 characterAtIndex: 5] == 0x1D11E)

	EXPECT_EXCEPTION(@"Detect out of range in -[characterAtIndex:]",
	    OFOutOfRangeException, [mutableString1 characterAtIndex: 7])

	TEST(@"-[reverse]",
	    R([mutableString1 reverse]) && [mutableString1 isEqual: @"3𝄞1€sät"])

	mutableString2 = [mutableStringClass stringWithString: @"abc"];

#ifdef OF_HAVE_UNICODE_TABLES
	TEST(@"-[uppercase]", R([mutableString1 uppercase]) &&
	    [mutableString1 isEqual: @"3𝄞1€SÄT"] &&

	    R([mutableString2 uppercase]) && [mutableString2 isEqual: @"ABC"])

	TEST(@"-[lowercase]", R([mutableString1 lowercase]) &&
	    [mutableString1 isEqual: @"3𝄞1€sät"] &&

	    R([mutableString2 lowercase]) && [mutableString2 isEqual: @"abc"])

	TEST(@"-[uppercaseString]",
	    [[mutableString1 uppercaseString] isEqual: @"3𝄞1€SÄT"])

	TEST(@"-[lowercaseString]", R([mutableString1 uppercase]) &&
	    [[mutableString1 lowercaseString] isEqual: @"3𝄞1€sät"])

	TEST(@"-[capitalizedString]", [C(@"džbla tdžst TDŽST").capitalizedString
	    isEqual: @"Džbla Tdžst Tdžst"])
#else
	TEST(@"-[uppercase]", R([mutableString1 uppercase]) &&
	    [mutableString1 isEqual: @"3𝄞1€SäT"] &&
	    R([mutableString2 uppercase]) && [mutableString2 isEqual: @"ABC"])

	TEST(@"-[lowercase]", R([mutableString1 lowercase]) &&
	    [mutableString1 isEqual: @"3𝄞1€sät"] &&
	    R([mutableString2 lowercase]) && [mutableString2 isEqual: @"abc"])

	TEST(@"-[uppercaseString]",
	    [mutableString1.uppercaseString isEqual: @"3𝄞1€SäT"])

	TEST(@"-[lowercaseString]",
	    R([mutableString1 uppercase]) &&
	    [mutableString1.lowercaseString isEqual: @"3𝄞1€sät"])

	TEST(@"-[capitalizedString]", [C(@"džbla tdžst TDŽST").capitalizedString
	    isEqual: @"džbla Tdžst TDŽst"])
#endif

	TEST(@"+[stringWithUTF8String:length:]",
	    (mutableString1 = [mutableStringClass
	    stringWithUTF8String: "\xEF\xBB\xBF" "foobar"
			  length: 6]) &&
	    [mutableString1 isEqual: @"foo"])

	TEST(@"+[stringWithUTF16String:]",
	    (string = [stringClass stringWithUTF16String: UTF16String]) &&
	    [string isEqual: @"fööbär🀺"] &&
	    (string = [stringClass stringWithUTF16String:
	    swappedUTF16String]) && [string isEqual: @"fööbär🀺"])

	TEST(@"+[stringWithUTF32String:]",
	    (string = [stringClass stringWithUTF32String: unicharString]) &&
	    [string isEqual: @"fööbär🀺"] &&
	    (string = [stringClass stringWithUTF32String:
	    swappedUnicharString]) && [string isEqual: @"fööbär🀺"])

#ifdef OF_HAVE_FILES
	TEST(@"+[stringWithContentsOfFile:encoding]", (string = [stringClass
	    stringWithContentsOfFile: @"testfile.txt"
			    encoding: OFStringEncodingISO8859_1]) &&
	    [string isEqual: @"testäöü"])

	TEST(@"+[stringWithContentsOfURL:encoding]", (string = [stringClass
	    stringWithContentsOfURL: [OFURL fileURLWithPath: @"testfile.txt"]
			   encoding: OFStringEncodingISO8859_1]) &&
	    [string isEqual: @"testäöü"])
#endif

	TEST(@"-[appendUTFString:length:]",
	    R([mutableString1 appendUTF8String: "\xEF\xBB\xBF" "barqux"
					length: 6]) &&
	    [mutableString1 isEqual: @"foobar"])

	EXPECT_EXCEPTION(@"Detection of invalid UTF-8 encoding #1",
	    OFInvalidEncodingException,
	    [stringClass stringWithUTF8String: "\xE0\x80"])
	EXPECT_EXCEPTION(@"Detection of invalid UTF-8 encoding #2",
	    OFInvalidEncodingException,
	    [stringClass stringWithUTF8String: "\xF0\x80\x80\xC0"])
................................................................................
#ifdef HAVE_CODEPAGE_437
	TEST(@"Lossy conversion of Unicode to Codepage 437",
	    !strcmp([C(@"T€st strîng ░▒▓") lossyCStringWithEncoding:
	    OFStringEncodingCodepage437], "T?st str\x8Cng \xB0\xB1\xB2"))
#endif

	TEST(@"+[stringWithFormat:]",
	    [(mutableString1 = [mutableStringClass stringWithFormat: @"%@:%d",
								     @"test",
								     123])
	    isEqual: @"test:123"])

	TEST(@"-[appendFormat:]",
	    R(([mutableString1 appendFormat: @"%02X", 15])) &&
	    [mutableString1 isEqual: @"test:1230F"])

	TEST(@"-[rangeOfString:]",
	    [C(@"𝄞öö") rangeOfString: @"öö"].location == 1 &&
	    [C(@"𝄞öö") rangeOfString: @"ö"].location == 1 &&
	    [C(@"𝄞öö") rangeOfString: @"𝄞"].location == 0 &&
	    [C(@"𝄞öö") rangeOfString: @"x"].location == OFNotFound &&
	    [C(@"𝄞öö") rangeOfString: @"öö"
................................................................................
	    options: OFStringSearchBackwards].location == OFNotFound)

	EXPECT_EXCEPTION(
	    @"Detect out of range in -[rangeOfString:options:range:]",
	    OFOutOfRangeException,
	    [C(@"𝄞öö") rangeOfString: @"ö" options: 0 range: OFRangeMake(3, 1)])

	characterSet =
	    [OFCharacterSet characterSetWithCharactersInString: @"cđ"];
	TEST(@"-[indexOfCharacterFromSet:]",
	    [C(@"abcđabcđe") indexOfCharacterFromSet: characterSet] == 2 &&
	    [C(@"abcđabcđë")
	    indexOfCharacterFromSet: characterSet
			    options: OFStringSearchBackwards] == 7 &&

	    [C(@"abcđabcđë") indexOfCharacterFromSet: characterSet
					     options: 0
					       range: OFRangeMake(4, 4)] == 6 &&
	    [C(@"abcđabcđëf")
	    indexOfCharacterFromSet: characterSet
			    options: 0
			      range: OFRangeMake(8, 2)] == OFNotFound)

	EXPECT_EXCEPTION(
	    @"Detect out of range in -[indexOfCharacterFromSet:options:range:]",
	    OFOutOfRangeException,
	    [C(@"𝄞öö") indexOfCharacterFromSet: characterSet
				       options: 0
					 range: OFRangeMake(3, 1)])

	TEST(@"-[substringWithRange:]",
	    [[C(@"𝄞öö") substringWithRange: OFRangeMake(1, 1)] isEqual: @"ö"] &&
	    [[C(@"𝄞öö") substringWithRange: OFRangeMake(3, 0)] isEqual: @""])

................................................................................
	    !C(@"foo/bar").absolutePath && !C(@"foo").absolutePath)
# else
	TEST(@"-[isAbsolutePath]",
	    C(@"/foo").absolutePath && C(@"/foo/bar").absolutePath &&
	    !C(@"foo/bar").absolutePath && !C(@"foo").absolutePath)
# endif

	mutableString1 = [mutableStringClass stringWithString: @"foo"];
# if defined(OF_WINDOWS) || defined(OF_MSDOS)
	[mutableString1 appendString: @"\\"];
# else
	[mutableString1 appendString: @"/"];
# endif
	[mutableString1 appendString: @"bar"];
	mutableString2 = [mutableStringClass stringWithString: mutableString1];
# if defined(OF_WINDOWS) || defined(OF_MSDOS)
	[mutableString2 appendString: @"\\"];
# else
	[mutableString2 appendString: @"/"];
# endif
	string = [stringClass stringWithString: mutableString2];
	[mutableString2 appendString: @"baz"];
	TEST(@"-[stringByAppendingPathComponent:]",
	    [[mutableString1 stringByAppendingPathComponent: @"baz"]
	    isEqual: mutableString2] &&
	    [[string stringByAppendingPathComponent: @"baz"]
	    isEqual: mutableString2])
#endif

	TEST(@"-[hasPrefix:]", [C(@"foobar") hasPrefix: @"foo"] &&
	    ![C(@"foobar") hasPrefix: @"foobar0"])

	TEST(@"-[hasSuffix:]", [C(@"foobar") hasSuffix: @"bar"] &&
	    ![C(@"foobar") hasSuffix: @"foobar0"])

	i = 0;
	TEST(@"-[componentsSeparatedByString:]",
	    (array = [C(@"fooXXbarXXXXbazXXXX")
	    componentsSeparatedByString: @"XX"]) &&
	    [[array objectAtIndex: i++] isEqual: @"foo"] &&
	    [[array objectAtIndex: i++] isEqual: @"bar"] &&
	    [[array objectAtIndex: i++] isEqual: @""] &&
	    [[array objectAtIndex: i++] isEqual: @"baz"] &&
	    [[array objectAtIndex: i++] isEqual: @""] &&
	    [[array objectAtIndex: i++] isEqual: @""] &&
	    array.count == i &&
	    (array = [C(@"foo") componentsSeparatedByString: @""]) &&
	    [[array objectAtIndex: 0] isEqual: @"foo"] &&
	    array.count == 1)

	i = 0;
	TEST(@"-[componentsSeparatedByString:options:]",
	    (array = [C(@"fooXXbarXXXXbazXXXX")
	    componentsSeparatedByString: @"XX"
				options: OFStringSkipEmptyComponents]) &&
	    [[array objectAtIndex: i++] isEqual: @"foo"] &&
	    [[array objectAtIndex: i++] isEqual: @"bar"] &&
	    [[array objectAtIndex: i++] isEqual: @"baz"] &&
	    array.count == i)

	characterSet =
	    [OFCharacterSet characterSetWithCharactersInString: @"XYZ"];

	i = 0;
	TEST(@"-[componentsSeparatedByCharactersInSet:]",
	    (array = [C(@"fooXYbarXYZXbazXYXZx")
	    componentsSeparatedByCharactersInSet: characterSet]) &&
	    [[array objectAtIndex: i++] isEqual: @"foo"] &&
	    [[array objectAtIndex: i++] isEqual: @""] &&
	    [[array objectAtIndex: i++] isEqual: @"bar"] &&
	    [[array objectAtIndex: i++] isEqual: @""] &&
	    [[array objectAtIndex: i++] isEqual: @""] &&
	    [[array objectAtIndex: i++] isEqual: @""] &&
	    [[array objectAtIndex: i++] isEqual: @"baz"] &&
	    [[array objectAtIndex: i++] isEqual: @""] &&
	    [[array objectAtIndex: i++] isEqual: @""] &&
	    [[array objectAtIndex: i++] isEqual: @""] &&
	    [[array objectAtIndex: i++] isEqual: @"x"] &&
	    array.count == i)

	i = 0;
	TEST(@"-[componentsSeparatedByCharactersInSet:options:]",
	    (array = [C(@"fooXYbarXYZXbazXYXZ")
	    componentsSeparatedByCharactersInSet: characterSet
	    options: OFStringSkipEmptyComponents]) &&
	    [[array objectAtIndex: i++] isEqual: @"foo"] &&
	    [[array objectAtIndex: i++] isEqual: @"bar"] &&
	    [[array objectAtIndex: i++] isEqual: @"baz"] &&
	    array.count == i)

#ifdef OF_HAVE_FILES
# if defined(OF_WINDOWS)
	TEST(@"+[pathWithComponents:]",
	    [[stringClass pathWithComponents: [OFArray arrayWithObjects:
	    @"foo", @"bar", @"baz", nil]] isEqual: @"foo\\bar\\baz"] &&
	    [[stringClass pathWithComponents: [OFArray arrayWithObjects:
................................................................................
	    [[stringClass pathWithComponents: [OFArray arrayWithObjects:
	    @"foo", nil]] isEqual: @"foo"])
# endif

# if defined(OF_WINDOWS)
	TEST(@"-[pathComponents]",
	    /* c:/tmp */
	    (array = C(@"c:/tmp").pathComponents) && array.count == 2 &&
	    [[array objectAtIndex: 0] isEqual: @"c:/"] &&
	    [[array objectAtIndex: 1] isEqual: @"tmp"] &&
	    /* c:\tmp\ */
	    (array = C(@"c:\\tmp\\").pathComponents) && array.count == 2 &&
	    [[array objectAtIndex: 0] isEqual: @"c:\\"] &&
	    [[array objectAtIndex: 1] isEqual: @"tmp"] &&
	    /* c:\ */
	    (array = C(@"c:\\").pathComponents) && array.count == 1 &&
	    [[array objectAtIndex: 0] isEqual: @"c:\\"] &&
	    /* c:/ */
	    (array = C(@"c:/").pathComponents) && array.count == 1 &&
	    [[array objectAtIndex: 0] isEqual: @"c:/"] &&
	    /* c: */
	    (array = C(@"c:").pathComponents) && array.count == 1 &&
	    [[array objectAtIndex: 0] isEqual: @"c:"] &&
	    /* foo\bar */
	    (array = C(@"foo\\bar").pathComponents) && array.count == 2 &&
	    [[array objectAtIndex: 0] isEqual: @"foo"] &&
	    [[array objectAtIndex: 1] isEqual: @"bar"] &&
	    /* foo\bar/baz/ */
	    (array = C(@"foo\\bar/baz/").pathComponents) && array.count == 3 &&
	    [[array objectAtIndex: 0] isEqual: @"foo"] &&
	    [[array objectAtIndex: 1] isEqual: @"bar"] &&
	    [[array objectAtIndex: 2] isEqual: @"baz"] &&
	    /* foo\/ */
	    (array = C(@"foo\\/").pathComponents) && array.count == 1 &&
	    [[array objectAtIndex: 0] isEqual: @"foo"] &&
	    /* \\foo\bar */
	    (array = C(@"\\\\foo\\bar").pathComponents) && array.count == 3 &&
	    [[array objectAtIndex: 0] isEqual: @"\\\\"] &&
	    [[array objectAtIndex: 1] isEqual: @"foo"] &&
	    [[array objectAtIndex: 2] isEqual: @"bar"] &&
	    C(@"").pathComponents.count == 0)
# elif defined(OF_MSDOS)
	TEST(@"-[pathComponents]",
	    /* c:/tmp */
	    (array = C(@"c:/tmp").pathComponents) && array.count == 2 &&
	    [[array objectAtIndex: 0] isEqual: @"c:/"] &&
	    [[array objectAtIndex: 1] isEqual: @"tmp"] &&
	    /* c:\tmp\ */
	    (array = C(@"c:\\tmp\\").pathComponents) && array.count == 2 &&
	    [[array objectAtIndex: 0] isEqual: @"c:\\"] &&
	    [[array objectAtIndex: 1] isEqual: @"tmp"] &&
	    /* c:\ */
	    (array = C(@"c:\\").pathComponents) && array.count == 1 &&
	    [[array objectAtIndex: 0] isEqual: @"c:\\"] &&
	    /* c:/ */
	    (array = C(@"c:/").pathComponents) && array.count == 1 &&
	    [[array objectAtIndex: 0] isEqual: @"c:/"] &&
	    /* c: */
	    (array = C(@"c:").pathComponents) && array.count == 1 &&
	    [[array objectAtIndex: 0] isEqual: @"c:"] &&
	    /* foo\bar */
	    (array = C(@"foo\\bar").pathComponents) && array.count == 2 &&
	    [[array objectAtIndex: 0] isEqual: @"foo"] &&
	    [[array objectAtIndex: 1] isEqual: @"bar"] &&
	    /* foo\bar/baz/ */
	    (array = C(@"foo\\bar/baz/").pathComponents) && array.count == 3 &&
	    [[array objectAtIndex: 0] isEqual: @"foo"] &&
	    [[array objectAtIndex: 1] isEqual: @"bar"] &&
	    [[array objectAtIndex: 2] isEqual: @"baz"] &&
	    /* foo\/ */
	    (array = C(@"foo\\/").pathComponents) && array.count == 1 &&
	    [[array objectAtIndex: 0] isEqual: @"foo"] &&
	    C(@"").pathComponents.count == 0)
# elif defined(OF_AMIGAOS)
	TEST(@"-[pathComponents]",
	    /* dh0:tmp */
	    (array = C(@"dh0:tmp").pathComponents) && array.count == 2 &&
	    [[array objectAtIndex: 0] isEqual: @"dh0:"] &&
	    [[array objectAtIndex: 1] isEqual: @"tmp"] &&
	    /* dh0:tmp/ */
	    (array = C(@"dh0:tmp/").pathComponents) && array.count == 2 &&
	    [[array objectAtIndex: 0] isEqual: @"dh0:"] &&
	    [[array objectAtIndex: 1] isEqual: @"tmp"] &&
	    /* dh0: */
	    (array = C(@"dh0:/").pathComponents) && array.count == 2 &&
	    [[array objectAtIndex: 0] isEqual: @"dh0:"] &&
	    [[array objectAtIndex: 1] isEqual: @"/"] &&
	    /* foo/bar */
	    (array = C(@"foo/bar").pathComponents) && array.count == 2 &&
	    [[array objectAtIndex: 0] isEqual: @"foo"] &&
	    [[array objectAtIndex: 1] isEqual: @"bar"] &&
	    /* foo/bar/baz/ */
	    (array = C(@"foo/bar/baz/").pathComponents) && array.count == 3 &&
	    [[array objectAtIndex: 0] isEqual: @"foo"] &&
	    [[array objectAtIndex: 1] isEqual: @"bar"] &&
	    [[array objectAtIndex: 2] isEqual: @"baz"] &&
	    /* foo// */
	    (array = C(@"foo//").pathComponents) && array.count == 2 &&
	    [[array objectAtIndex: 0] isEqual: @"foo"] &&
	    [[array objectAtIndex: 1] isEqual: @"/"] &&
	    C(@"").pathComponents.count == 0)
# elif defined(OF_NINTENDO_3DS) || defined(OF_WII)
	TEST(@"-[pathComponents]",
	    /* sdmc:/tmp */
	    (array = C(@"sdmc:/tmp").pathComponents) && array.count == 2 &&
	    [[array objectAtIndex: 0] isEqual: @"sdmc:"] &&
	    [[array objectAtIndex: 1] isEqual: @"tmp"] &&
	    /* sdmc:/ */
	    (array = C(@"sdmc:/").pathComponents) && array.count == 1 &&
	    [[array objectAtIndex: 0] isEqual: @"sdmc:"] &&
	    /* foo/bar */
	    (array = C(@"foo/bar").pathComponents) && array.count == 2 &&
	    [[array objectAtIndex: 0] isEqual: @"foo"] &&
	    [[array objectAtIndex: 1] isEqual: @"bar"] &&
	    /* foo/bar/baz/ */
	    (array = C(@"foo/bar/baz/").pathComponents) && array.count == 3 &&
	    [[array objectAtIndex: 0] isEqual: @"foo"] &&
	    [[array objectAtIndex: 1] isEqual: @"bar"] &&
	    [[array objectAtIndex: 2] isEqual: @"baz"] &&
	    /* foo// */
	    (array = C(@"foo//").pathComponents) && array.count == 1 &&
	    [[array objectAtIndex: 0] isEqual: @"foo"] &&
	    C(@"").pathComponents.count == 0)
# else
	TEST(@"-[pathComponents]",
	    /* /tmp */
	    (array = C(@"/tmp").pathComponents) && array.count == 2 &&
	    [[array objectAtIndex: 0] isEqual: @"/"] &&
	    [[array objectAtIndex: 1] isEqual: @"tmp"] &&
	    /* /tmp/ */
	    (array = C(@"/tmp/").pathComponents) && array.count == 2 &&
	    [[array objectAtIndex: 0] isEqual: @"/"] &&
	    [[array objectAtIndex: 1] isEqual: @"tmp"] &&
	    /* / */
	    (array = C(@"/").pathComponents) && array.count == 1 &&
	    [[array objectAtIndex: 0] isEqual: @"/"] &&
	    /* foo/bar */
	    (array = C(@"foo/bar").pathComponents) && array.count == 2 &&
	    [[array objectAtIndex: 0] isEqual: @"foo"] &&
	    [[array objectAtIndex: 1] isEqual: @"bar"] &&
	    /* foo/bar/baz/ */
	    (array = C(@"foo/bar/baz/").pathComponents) && array.count == 3 &&
	    [[array objectAtIndex: 0] isEqual: @"foo"] &&
	    [[array objectAtIndex: 1] isEqual: @"bar"] &&
	    [[array objectAtIndex: 2] isEqual: @"baz"] &&
	    /* foo// */
	    (array = C(@"foo//").pathComponents) && array.count == 1 &&
	    [[array objectAtIndex: 0] isEqual: @"foo"] &&
	    C(@"").pathComponents.count == 0)
# endif

# if defined(OF_WINDOWS)
	TEST(@"-[lastPathComponent]",
	    [C(@"c:/tmp").lastPathComponent isEqual: @"tmp"] &&
	    [C(@"c:\\tmp\\").lastPathComponent isEqual: @"tmp"] &&
................................................................................

	EXPECT_EXCEPTION(@"Detect out of range in -[unsignedLongLongValue]",
	    OFOutOfRangeException,
	    [C(@"0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF"
	       @"0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF")
	    unsignedLongLongValueWithBase: 16])

	TEST(@"-[characters]", (characters = C(@"fööbär🀺").characters) &&
	    !memcmp(characters, unicharString + 1, sizeof(unicharString) - 8))

#ifdef OF_BIG_ENDIAN
# define SWAPPED_BYTE_ORDER OFByteOrderLittleEndian
#else
# define SWAPPED_BYTE_ORDER OFByteOrderBigEndian
#endif
	TEST(@"-[UTF16String]", (UTF16Characters = C(@"fööbär🀺").UTF16String) &&
	    !memcmp(UTF16Characters, UTF16String + 1,
	    OFUTF16StringLength(UTF16String) * 2) &&
	    (UTF16Characters = [C(@"fööbär🀺")
	    UTF16StringWithByteOrder: SWAPPED_BYTE_ORDER]) &&
	    !memcmp(UTF16Characters, swappedUTF16String + 1,
	    OFUTF16StringLength(swappedUTF16String) * 2))

	TEST(@"-[UTF16StringLength]", C(@"fööbär🀺").UTF16StringLength == 8)

	TEST(@"-[UTF32String]", (characters = C(@"fööbär🀺").UTF32String) &&
	    !memcmp(characters, unicharString + 1,
	    OFUTF32StringLength(unicharString) * 4) &&
	    (characters = [C(@"fööbär🀺") UTF32StringWithByteOrder:
	    SWAPPED_BYTE_ORDER]) &&
	    !memcmp(characters, swappedUnicharString + 1,
	    OFUTF32StringLength(swappedUnicharString) * 4))
#undef SWAPPED_BYTE_ORDER

	TEST(@"-[stringByMD5Hashing]", [C(@"asdfoobar").stringByMD5Hashing
	    isEqual: @"184dce2ec49b5422c7cfd8728864db4c"])

	TEST(@"-[stringByRIPEMD160Hashing]",
	    [C(@"asdfoobar").stringByRIPEMD160Hashing
................................................................................
		     @"279e5addf8be854044bca0cece073fce28eec7d9"])

	TEST(@"-[stringBySHA512Hashing]", [C(@"asdfoobar").stringBySHA512Hashing
	    isEqual: @"0464c427da158b02161bb44a3090bbfc594611ef6a53603640454b56"
		     @"412a9247c3579a329e53a5dc74676b106755e3394f9454a2d4227324"
		     @"2615d32f80437d61"])

	characterSet =
	    [OFCharacterSet characterSetWithCharactersInString: @"abfo'_~$🍏"];
	TEST(@"-[stringByURLEncodingWithAllowedCharacters:]",
	    [[C(@"foo\"ba'_~$]🍏🍌") stringByURLEncodingWithAllowedCharacters:
	    characterSet] isEqual: @"foo%22ba'_~$%5D🍏%F0%9F%8D%8C"])

	TEST(@"-[stringByURLDecoding]",
	    [C(@"foo%20bar%22+%24%F0%9F%8D%8C").stringByURLDecoding
	    isEqual: @"foo bar\"+$🍌"])

	TEST(@"-[insertString:atIndex:]",
	    (mutableString1 = [mutableStringClass
	    stringWithString: @"𝄞öööbä€"]) &&
	    R([mutableString1 insertString: @"äöü" atIndex: 3]) &&
	    [mutableString1 isEqual: @"𝄞ööäöüöbä€"])

	EXPECT_EXCEPTION(@"Detect invalid format in -[stringByURLDecoding] "
	    @"#1", OFInvalidFormatException,
	    [C(@"foo%xbar") stringByURLDecoding])
	EXPECT_EXCEPTION(@"Detect invalid encoding in -[stringByURLDecoding] "
	    @"#2", OFInvalidEncodingException,
	    [C(@"foo%FFbar") stringByURLDecoding])

	TEST(@"-[setCharacter:atIndex:]",
	    (mutableString1 = [mutableStringClass
	    stringWithString: @"abäde"]) &&
	    R([mutableString1 setCharacter: 0xF6 atIndex: 2]) &&
	    [mutableString1 isEqual: @"aböde"] &&
	    R([mutableString1 setCharacter: 'c' atIndex: 2]) &&
	    [mutableString1 isEqual: @"abcde"] &&
	    R([mutableString1 setCharacter: 0x20AC atIndex: 3]) &&
	    [mutableString1 isEqual: @"abc€e"] &&
	    R([mutableString1 setCharacter: 'x' atIndex: 1]) &&
	    [mutableString1 isEqual: @"axc€e"])

	TEST(@"-[deleteCharactersInRange:]",
	    (mutableString1 = [mutableStringClass
	    stringWithString: @"𝄞öööbä€"]) &&
	    R([mutableString1 deleteCharactersInRange: OFRangeMake(1, 3)]) &&
	    [mutableString1 isEqual: @"𝄞bä€"] &&
	    R([mutableString1 deleteCharactersInRange: OFRangeMake(0, 4)]) &&
	    [mutableString1 isEqual: @""])

	TEST(@"-[replaceCharactersInRange:withString:]",
	    (mutableString1 = [mutableStringClass
	    stringWithString: @"𝄞öööbä€"]) &&
	    R([mutableString1 replaceCharactersInRange: OFRangeMake(1, 3)
					    withString: @"äöüß"]) &&
	    [mutableString1 isEqual: @"𝄞äöüßbä€"] &&
	    R([mutableString1 replaceCharactersInRange: OFRangeMake(4, 2)
					    withString: @"b"]) &&
	    [mutableString1 isEqual: @"𝄞äöübä€"] &&
	    R([mutableString1 replaceCharactersInRange: OFRangeMake(0, 7)
					    withString: @""]) &&
	    [mutableString1 isEqual: @""])

	EXPECT_EXCEPTION(@"Detect OoR in -[deleteCharactersInRange:] #1",
	    OFOutOfRangeException,
	    {
		mutableString1 = [mutableStringClass stringWithString: @"𝄞öö"];
		[mutableString1 deleteCharactersInRange: OFRangeMake(2, 2)];
	    })

	EXPECT_EXCEPTION(@"Detect OoR in -[deleteCharactersInRange:] #2",
	    OFOutOfRangeException,
	    [mutableString1 deleteCharactersInRange: OFRangeMake(4, 0)])

	EXPECT_EXCEPTION(@"Detect OoR in "
	    @"-[replaceCharactersInRange:withString:] #1",
	    OFOutOfRangeException,
	    [mutableString1 replaceCharactersInRange: OFRangeMake(2, 2)
					  withString: @""])

	EXPECT_EXCEPTION(@"Detect OoR in "
	    @"-[replaceCharactersInRange:withString:] #2",
	    OFOutOfRangeException,
	    [mutableString1 replaceCharactersInRange: OFRangeMake(4, 0)
					  withString: @""])

	TEST(@"-[replaceOccurrencesOfString:withString:]",
	    (mutableString1 = [mutableStringClass stringWithString:
	    @"asd fo asd fofo asd"]) &&
	    R([mutableString1 replaceOccurrencesOfString: @"fo"
					      withString: @"foo"]) &&
	    [mutableString1 isEqual: @"asd foo asd foofoo asd"] &&
	    (mutableString1 = [mutableStringClass stringWithString: @"XX"]) &&
	    R([mutableString1 replaceOccurrencesOfString: @"X"
					      withString: @"XX"]) &&
	    [mutableString1 isEqual: @"XXXX"])

	TEST(@"-[replaceOccurrencesOfString:withString:options:range:]",
	    (mutableString1 = [mutableStringClass stringWithString:
	    @"foofoobarfoobarfoo"]) && R([mutableString1
	    replaceOccurrencesOfString: @"oo"
			    withString: @"óò"
			       options: 0
				 range: OFRangeMake(2, 15)]) &&
	    [mutableString1 isEqual: @"foofóòbarfóòbarfoo"])

	TEST(@"-[deleteLeadingWhitespaces]",
	    (mutableString1 = [mutableStringClass
	    stringWithString: whitespace[0]]) &&
	    R([mutableString1 deleteLeadingWhitespaces]) &&
	    [mutableString1 isEqual: @"asd  \t \t\t\r\n"] &&
	    (mutableString1 = [mutableStringClass
	    stringWithString: whitespace[1]]) &&
	    R([mutableString1 deleteLeadingWhitespaces]) &&
	    [mutableString1 isEqual: @""])

	TEST(@"-[deleteTrailingWhitespaces]",
	    (mutableString1 = [mutableStringClass
	    stringWithString: whitespace[0]]) &&
	    R([mutableString1 deleteTrailingWhitespaces]) &&
	    [mutableString1 isEqual: @" \r \t\n\t \tasd"] &&
	    (mutableString1 = [mutableStringClass
	    stringWithString: whitespace[1]]) &&
	    R([mutableString1 deleteTrailingWhitespaces]) &&
	    [mutableString1 isEqual: @""])

	TEST(@"-[deleteEnclosingWhitespaces]",
	    (mutableString1 = [mutableStringClass
	    stringWithString: whitespace[0]]) &&
	    R([mutableString1 deleteEnclosingWhitespaces]) &&
	    [mutableString1 isEqual: @"asd"] &&
	    (mutableString1 = [mutableStringClass
	    stringWithString: whitespace[1]]) &&
	    R([mutableString1 deleteEnclosingWhitespaces]) &&
	    [mutableString1 isEqual: @""])

#ifdef OF_HAVE_UNICODE_TABLES
	TEST(@"-[decomposedStringWithCanonicalMapping]",
	    [C(@"H\xC3\xA4llj\xC3\xB6").decomposedStringWithCanonicalMapping
	    isEqual: @"H\x61\xCC\x88llj\x6F\xCC\x88"]);

	TEST(@"-[decomposedStringWithCompatibilityMapping]",
	    [C(@"H\xC3\xA4llj\xC3\xB6").decomposedStringWithCompatibilityMapping
	    isEqual: @"H\x61\xCC\x88llj\x6F\xCC\x88"]);
#endif

	TEST(@"-[stringByXMLEscaping]",
	    (string = C(@"<hello> &world'\"!&").stringByXMLEscaping) &&
	    [string isEqual: @"&lt;hello&gt; &amp;world&apos;&quot;!&amp;"])

	TEST(@"-[stringByXMLUnescaping]",
	    [string.stringByXMLUnescaping isEqual: @"<hello> &world'\"!&"] &&
	    [C(@"&#x79;").stringByXMLUnescaping isEqual: @"y"] &&
	    [C(@"&#xe4;").stringByXMLUnescaping isEqual: @"ä"] &&
	    [C(@"&#8364;").stringByXMLUnescaping isEqual: @"€"] &&
	    [C(@"&#x1D11E;").stringByXMLUnescaping isEqual: @"𝄞"])

	EXPECT_EXCEPTION(@"Detect unknown entities in -[stringByXMLUnescaping]",
	    OFUnknownXMLEntityException, [C(@"&foo;") stringByXMLUnescaping])
................................................................................
	EXPECT_EXCEPTION(@"Detect invalid entities in -[stringByXMLUnescaping] "
	    @"#4", OFInvalidFormatException, [C(@"&#g;") stringByXMLUnescaping])
	EXPECT_EXCEPTION(@"Detect invalid entities in -[stringByXMLUnescaping] "
	    @"#5", OFInvalidFormatException,
	    [C(@"&#xg;") stringByXMLUnescaping])

	TEST(@"-[stringByXMLUnescapingWithDelegate:]",
	    (entityHandler = [[[EntityHandler alloc] init] autorelease]) &&
	    [[C(@"x&foo;y") stringByXMLUnescapingWithDelegate: entityHandler]
	    isEqual: @"xbary"])

#ifdef OF_HAVE_BLOCKS
	TEST(@"-[stringByXMLUnescapingWithBlock:]",
	    [[C(@"x&foo;y") stringByXMLUnescapingWithBlock:
		^ OFString *(OFString *str, OFString *entity) {
		    if ([entity isEqual: @"foo"])
			    return @"bar";

		    return nil;
	    }] isEqual: @"xbary"])

	j = 0;

Modified tests/OFTCPSocketTests.m from [dfc17ad706] to [a30a596e10].

23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
..
45
46
47
48
49
50
51
52
53
54
55
56
57

@implementation TestsAppDelegate (OFTCPSocketTests)
- (void)TCPSocketTests
{
	void *pool = objc_autoreleasePoolPush();
	OFTCPSocket *server, *client = nil, *accepted;
	uint16_t port;
	char buf[6];

	TEST(@"+[socket]", (server = [OFTCPSocket socket]) &&
	    (client = [OFTCPSocket socket]))

	TEST(@"-[bindToHost:port:]",
	    (port = [server bindToHost: @"127.0.0.1" port: 0]))

................................................................................
	TEST(@"-[remoteAddress]",
	    [OFSocketAddressString(accepted.remoteAddress)
	    isEqual: @"127.0.0.1"])

	TEST(@"-[writeString:]", [client writeString: @"Hello!"])

	TEST(@"-[readIntoBuffer:length:]",
	    [accepted readIntoBuffer: buf length: 6] &&
	    !memcmp(buf, "Hello!", 6))

	objc_autoreleasePoolPop(pool);
}
@end







|







 







|
|




23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
..
45
46
47
48
49
50
51
52
53
54
55
56
57

@implementation TestsAppDelegate (OFTCPSocketTests)
- (void)TCPSocketTests
{
	void *pool = objc_autoreleasePoolPush();
	OFTCPSocket *server, *client = nil, *accepted;
	uint16_t port;
	char buffer[6];

	TEST(@"+[socket]", (server = [OFTCPSocket socket]) &&
	    (client = [OFTCPSocket socket]))

	TEST(@"-[bindToHost:port:]",
	    (port = [server bindToHost: @"127.0.0.1" port: 0]))

................................................................................
	TEST(@"-[remoteAddress]",
	    [OFSocketAddressString(accepted.remoteAddress)
	    isEqual: @"127.0.0.1"])

	TEST(@"-[writeString:]", [client writeString: @"Hello!"])

	TEST(@"-[readIntoBuffer:length:]",
	    [accepted readIntoBuffer: buffer length: 6] &&
	    !memcmp(buffer, "Hello!", 6))

	objc_autoreleasePoolPop(pool);
}
@end

Modified tests/OFThreadTests.m from [61a0609ec2] to [6e125a20af].

13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28


29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
 * file.
 */

#include "config.h"

#import "TestsAppDelegate.h"

static OFString *module = @"OFThread";

@interface TestThread: OFThread
@end

@implementation TestThread
- (id)main
{
	[[OFThread threadDictionary] setObject: @"bar" forKey: @"foo"];



	return @"success";
}
@end

@implementation TestsAppDelegate (OFThreadTests)
- (void)threadTests
{
	void *pool = objc_autoreleasePoolPush();
	TestThread *t;
	OFMutableDictionary *d;

	TEST(@"+[thread]", (t = [TestThread thread]))

	TEST(@"-[start]", R([t start]))

	TEST(@"-[join]", [[t join] isEqual: @"success"])

	TEST(@"-[threadDictionary]", (d = [OFThread threadDictionary]) &&
	    [d objectForKey: @"foo"] == nil)

	objc_autoreleasePoolPop(pool);
}
@end







|








>
>









|
<

|

|

|

|
|




13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

41
42
43
44
45
46
47
48
49
50
51
52
53
 * file.
 */

#include "config.h"

#import "TestsAppDelegate.h"

static OFString *const module = @"OFThread";

@interface TestThread: OFThread
@end

@implementation TestThread
- (id)main
{
	[[OFThread threadDictionary] setObject: @"bar" forKey: @"foo"];
	OFEnsure([[[OFThread threadDictionary]
	    objectForKey: @"foo"] isEqual: @"bar"]);

	return @"success";
}
@end

@implementation TestsAppDelegate (OFThreadTests)
- (void)threadTests
{
	void *pool = objc_autoreleasePoolPush();
	TestThread *thread;


	TEST(@"+[thread]", (thread = [TestThread thread]))

	TEST(@"-[start]", R([thread start]))

	TEST(@"-[join]", [[thread join] isEqual: @"success"])

	TEST(@"-[threadDictionary]",
	    [[OFThread threadDictionary] objectForKey: @"foo"] == nil)

	objc_autoreleasePoolPop(pool);
}
@end

Modified tests/OFUDPSocketTests.m from [c440a7c2a6] to [6d7b4e4936].

15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

#include "config.h"

#include <string.h>

#import "TestsAppDelegate.h"

static OFString *module = @"OFUDPSocket";

@implementation TestsAppDelegate (OFUDPSocketTests)
- (void)UDPSocketTests
{
	void *pool = objc_autoreleasePoolPush();
	OFUDPSocket *sock;
	uint16_t port1;







|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

#include "config.h"

#include <string.h>

#import "TestsAppDelegate.h"

static OFString *const module = @"OFUDPSocket";

@implementation TestsAppDelegate (OFUDPSocketTests)
- (void)UDPSocketTests
{
	void *pool = objc_autoreleasePoolPush();
	OFUDPSocket *sock;
	uint16_t port1;

Modified tests/OFURLTests.m from [a23bc7aa5e] to [641ece2b4e].

13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
..
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
...
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154

155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194

195
196
197
198

199
200
201
202
203
204

205
206
207
208
209
210
211
212
213
214

215

216

217
218
219
220
221
222

223
224
225

226
227

228
229
230
231

232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248

249
250
251
252

253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269

270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
 * file.
 */

#include "config.h"

#import "TestsAppDelegate.h"

static OFString *module = @"OFURL";
static OFString *url_str = @"ht%3atp://us%3Aer:p%40w@ho%3Ast:1234/"
    @"pa%3Fth?que%23ry=1&f%26oo=b%3dar#frag%23ment";

@implementation TestsAppDelegate (OFURLTests)
- (void)URLTests
{
	void *pool = objc_autoreleasePoolPush();
	OFURL *u1, *u2, *u3, *u4, *u5, *u6, *u7;
	OFMutableURL *mu;

	TEST(@"+[URLWithString:]",
	    R(u1 = [OFURL URLWithString: url_str]) &&
	    R(u2 = [OFURL URLWithString: @"http://foo:80"]) &&
	    R(u3 = [OFURL URLWithString: @"http://bar/"]) &&
	    R(u4 = [OFURL URLWithString: @"file:///etc/passwd"]) &&
	    R(u5 = [OFURL URLWithString: @"http://foo/bar/qux/foo%2fbar"]) &&
	    R(u6 = [OFURL URLWithString: @"https://[12:34::56:abcd]/"]) &&
	    R(u7 = [OFURL URLWithString: @"https://[12:34::56:abcd]:234/"]))

	EXPECT_EXCEPTION(@"+[URLWithString:] fails with invalid characters #1",
	    OFInvalidFormatException,
	    [OFURL URLWithString: @"ht,tp://foo"])

	EXPECT_EXCEPTION(@"+[URLWithString:] fails with invalid characters #2",
	    OFInvalidFormatException,
................................................................................
	    [OFURL URLWithString: @"https://[f]:/"])

	EXPECT_EXCEPTION(@"+[URLWithString:] fails with invalid characters #8",
	    OFInvalidFormatException,
	    [OFURL URLWithString: @"https://[f]:f/"])

	TEST(@"+[URLWithString:relativeToURL:]",
	    [[[OFURL URLWithString: @"/foo" relativeToURL: u1] string] isEqual:
	    @"ht%3atp://us%3Aer:p%40w@ho%3Ast:1234/foo"] &&
	    [[[OFURL URLWithString: @"foo/bar?q"
		     relativeToURL: [OFURL URLWithString: @"http://h/qux/quux"]]
	    string] isEqual: @"http://h/qux/foo/bar?q"] &&
	    [[[OFURL URLWithString: @"foo/bar"
		     relativeToURL: [OFURL URLWithString: @"http://h/qux/?x"]]
	    string] isEqual: @"http://h/qux/foo/bar"] &&
	    [[[OFURL URLWithString: @"http://foo/?q"
		     relativeToURL: u1] string] isEqual: @"http://foo/?q"] &&
	    [[[OFURL URLWithString: @"foo"
		     relativeToURL: [OFURL URLWithString: @"http://foo/bar"]]
	    string] isEqual: @"http://foo/foo"] &&
	    [[[OFURL URLWithString: @"foo"
		     relativeToURL: [OFURL URLWithString: @"http://foo"]]
	    string] isEqual: @"http://foo/foo"])

	EXPECT_EXCEPTION(
	    @"+[URLWithString:relativeToURL:] fails with invalid characters #1",
	    OFInvalidFormatException,
	    [OFURL URLWithString: @"`" relativeToURL: u1])

	EXPECT_EXCEPTION(
	    @"+[URLWithString:relativeToURL:] fails with invalid characters #2",
	    OFInvalidFormatException,
	    [OFURL URLWithString: @"/`" relativeToURL: u1])

	EXPECT_EXCEPTION(
	    @"+[URLWithString:relativeToURL:] fails with invalid characters #3",
	    OFInvalidFormatException,
	    [OFURL URLWithString: @"?`" relativeToURL: u1])

	EXPECT_EXCEPTION(
	    @"+[URLWithString:relativeToURL:] fails with invalid characters #4",
	    OFInvalidFormatException,
	    [OFURL URLWithString: @"#`" relativeToURL: u1])

#ifdef OF_HAVE_FILES
	TEST(@"+[fileURLWithPath:]",
	    [[[OFURL fileURLWithPath: @"testfile.txt"] fileSystemRepresentation]
	    isEqual: [[OFFileManager defaultManager].currentDirectoryPath
	    stringByAppendingPathComponent: @"testfile.txt"]])

................................................................................
	    [tmp.host isEqual: @"test"] && [tmp.path isEqual: @"/"] &&
	    [tmp.string isEqual: @"file://test/"] &&
	    [tmp.fileSystemRepresentation isEqual: @"\\\\test"])
# endif
#endif

	TEST(@"-[string]",
	    [u1.string isEqual: url_str] &&
	    [u2.string isEqual: @"http://foo:80"] &&
	    [u3.string isEqual: @"http://bar/"] &&
	    [u4.string isEqual: @"file:///etc/passwd"])

	TEST(@"-[scheme]",
	    [u1.scheme isEqual: @"ht:tp"] && [u4.scheme isEqual: @"file"])

	TEST(@"-[user]", [u1.user isEqual: @"us:er"] && u4.user == nil)
	TEST(@"-[password]",
	    [u1.password isEqual: @"p@w"] && u4.password == nil)
	TEST(@"-[host]", [u1.host isEqual: @"ho:st"] &&
	    [u6.host isEqual: @"12:34::56:abcd"] &&
	    [u7.host isEqual: @"12:34::56:abcd"])
	TEST(@"-[port]", u1.port.unsignedShortValue == 1234 &&
	    [u4 port] == nil && u7.port.unsignedShortValue == 234)
	TEST(@"-[path]",

	    [u1.path isEqual: @"/pa?th"] && [u4.path isEqual: @"/etc/passwd"])
	TEST(@"-[pathComponents]",
	    [u1.pathComponents isEqual:
	    [OFArray arrayWithObjects: @"/", @"pa?th", nil]] &&
	    [u4.pathComponents isEqual:
	    [OFArray arrayWithObjects: @"/", @"etc", @"passwd", nil]] &&
	    [u5.pathComponents isEqual:
	    [OFArray arrayWithObjects: @"/", @"bar", @"qux", @"foo/bar", nil]])
	TEST(@"-[lastPathComponent]",
	    [[[OFURL URLWithString: @"http://host/foo//bar/baz"]
	    lastPathComponent] isEqual: @"baz"] &&
	    [[[OFURL URLWithString: @"http://host/foo//bar/baz/"]
	    lastPathComponent] isEqual: @"baz"] &&
	    [[[OFURL URLWithString: @"http://host/foo/"]
	    lastPathComponent] isEqual: @"foo"] &&
	    [[[OFURL URLWithString: @"http://host/"]
	    lastPathComponent] isEqual: @"/"] &&
	    [u5.lastPathComponent isEqual: @"foo/bar"])
	TEST(@"-[query]",
	    [u1.query isEqual: @"que#ry=1&f&oo=b=ar"] && u4.query == nil)
	TEST(@"-[queryDictionary]",
	    [u1.queryDictionary isEqual:
	    [OFDictionary dictionaryWithKeysAndObjects:
	    @"que#ry", @"1", @"f&oo", @"b=ar", nil]]);
	TEST(@"-[fragment]",
	    [u1.fragment isEqual: @"frag#ment"] && u4.fragment == nil)

	TEST(@"-[copy]", R(u4 = [[u1 copy] autorelease]))

	TEST(@"-[isEqual:]", [u1 isEqual: u4] && ![u2 isEqual: u3] &&
	    [[OFURL URLWithString: @"HTTP://bar/"] isEqual: u3])

	TEST(@"-[hash:]", u1.hash == u4.hash && u2.hash != u3.hash)

	EXPECT_EXCEPTION(@"Detection of invalid format",
	    OFInvalidFormatException, [OFURL URLWithString: @"http"])

	mu = [OFMutableURL URL];

	TEST(@"-[setScheme:]",

	    (mu.scheme = @"ht:tp") && [mu.URLEncodedScheme isEqual: @"ht%3Atp"])

	TEST(@"-[setURLEncodedScheme:]",
	    (mu.URLEncodedScheme = @"ht%3Atp") && [mu.scheme isEqual: @"ht:tp"])


	EXPECT_EXCEPTION(
	    @"-[setURLEncodedScheme:] with invalid characters fails",
	    OFInvalidFormatException, mu.URLEncodedScheme = @"~")

	TEST(@"-[setHost:]",

	    (mu.host = @"ho:st") && [mu.URLEncodedHost isEqual: @"ho%3Ast"] &&
	    (mu.host = @"12:34:ab") &&
	    [mu.URLEncodedHost isEqual: @"[12:34:ab]"] &&
	    (mu.host = @"12:34:aB") &&
	    [mu.URLEncodedHost isEqual: @"[12:34:aB]"] &&
	    (mu.host = @"12:34:g") &&
	    [mu.URLEncodedHost isEqual: @"12%3A34%3Ag"])

	TEST(@"-[setURLEncodedHost:]",
	    (mu.URLEncodedHost = @"ho%3Ast") && [mu.host isEqual: @"ho:st"] &&

	    (mu.URLEncodedHost = @"[12:34]") && [mu.host isEqual: @"12:34"] &&

	    (mu.URLEncodedHost = @"[12::ab]") && [mu.host isEqual: @"12::ab"])


	EXPECT_EXCEPTION(@"-[setURLEncodedHost:] with invalid characters fails"
	    " #1", OFInvalidFormatException, mu.URLEncodedHost = @"/")

	EXPECT_EXCEPTION(@"-[setURLEncodedHost:] with invalid characters fails"
	    " #2", OFInvalidFormatException, mu.URLEncodedHost = @"[12:34")


	EXPECT_EXCEPTION(@"-[setURLEncodedHost:] with invalid characters fails"
	    " #3", OFInvalidFormatException, mu.URLEncodedHost = @"[a::g]")


	TEST(@"-[setUser:]",

	    (mu.user = @"us:er") && [mu.URLEncodedUser isEqual: @"us%3Aer"])

	TEST(@"-[setURLEncodedUser:]",
	    (mu.URLEncodedUser = @"us%3Aer") && [mu.user isEqual: @"us:er"])


	EXPECT_EXCEPTION(@"-[setURLEncodedUser:] with invalid characters fails",
	    OFInvalidFormatException, mu.URLEncodedHost = @"/")

	TEST(@"-[setPassword:]",
	    (mu.password = @"pass:word") &&
	    [mu.URLEncodedPassword isEqual: @"pass%3Aword"])

	TEST(@"-[setURLEncodedPassword:]",
	    (mu.URLEncodedPassword = @"pass%3Aword") &&
	    [mu.password isEqual: @"pass:word"])

	EXPECT_EXCEPTION(
	    @"-[setURLEncodedPassword:] with invalid characters fails",
	    OFInvalidFormatException, mu.URLEncodedPassword = @"/")

	TEST(@"-[setPath:]",

	    (mu.path = @"pa/th@?") && [mu.URLEncodedPath isEqual: @"pa/th@%3F"])

	TEST(@"-[setURLEncodedPath:]",
	    (mu.URLEncodedPath = @"pa/th@%3F") && [mu.path isEqual: @"pa/th@?"])


	EXPECT_EXCEPTION(@"-[setURLEncodedPath:] with invalid characters fails",
	    OFInvalidFormatException, mu.URLEncodedPath = @"?")

	TEST(@"-[setQuery:]",
	    (mu.query = @"que/ry?#") &&
	    [mu.URLEncodedQuery isEqual: @"que/ry?%23"])

	TEST(@"-[setURLEncodedQuery:]",
	    (mu.URLEncodedQuery = @"que/ry?%23") &&
	    [mu.query isEqual: @"que/ry?#"])

	EXPECT_EXCEPTION(
	    @"-[setURLEncodedQuery:] with invalid characters fails",
	    OFInvalidFormatException, mu.URLEncodedQuery = @"`")

	TEST(@"-[setQueryDictionary:]",

	    (mu.queryDictionary = [OFDictionary dictionaryWithKeysAndObjects:
	    @"foo&bar", @"baz=qux", @"f=oobar", @"b&azqux", nil]) &&
	    [mu.URLEncodedQuery isEqual:
	    @"foo%26bar=baz%3Dqux&f%3Doobar=b%26azqux"])

	TEST(@"-[setFragment:]",
	    (mu.fragment = @"frag/ment?#") &&
	    [mu.URLEncodedFragment isEqual: @"frag/ment?%23"])

	TEST(@"-[setURLEncodedFragment:]",
	    (mu.URLEncodedFragment = @"frag/ment?%23") &&
	    [mu.fragment isEqual: @"frag/ment?#"])

	EXPECT_EXCEPTION(
	    @"-[setURLEncodedFragment:] with invalid characters fails",
	    OFInvalidFormatException, mu.URLEncodedFragment = @"`")

	TEST(@"-[URLByAppendingPathComponent:isDirectory:]",
	    [[[OFURL URLWithString: @"file:///foo/bar"]
	    URLByAppendingPathComponent: @"qux" isDirectory: false] isEqual:
	    [OFURL URLWithString: @"file:///foo/bar/qux"]] &&
	    [[[OFURL URLWithString: @"file:///foo/bar/"]
	    URLByAppendingPathComponent: @"qux" isDirectory: false] isEqual:







|
|






|
|


|
|
|
|
|
|
|







 







|
|







|










|




|




|




|







 







|
|
|
|


|

|

|
|
|
|
|
|

>
|

|

|

|










|

|

|



|

|

|
|

|




|


>
|


|
>



|


>
|
|
|
|
|
|
|


|
>
|
>
|
>


|


|
>


|
>


>
|


|
>


|


|
|


|
|



|


>
|


|
>


|


|
|


|
|



|


>
|

|



|
|


|
|



|







13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
..
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
...
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
 * file.
 */

#include "config.h"

#import "TestsAppDelegate.h"

static OFString *const module = @"OFURL";
static OFString *URLString = @"ht%3atp://us%3Aer:p%40w@ho%3Ast:1234/"
    @"pa%3Fth?que%23ry=1&f%26oo=b%3dar#frag%23ment";

@implementation TestsAppDelegate (OFURLTests)
- (void)URLTests
{
	void *pool = objc_autoreleasePoolPush();
	OFURL *URL1, *URL2, *URL3, *URL4, *URL5, *URL6, *URL7;
	OFMutableURL *mutableURL;

	TEST(@"+[URLWithString:]",
	    R(URL1 = [OFURL URLWithString: URLString]) &&
	    R(URL2 = [OFURL URLWithString: @"http://foo:80"]) &&
	    R(URL3 = [OFURL URLWithString: @"http://bar/"]) &&
	    R(URL4 = [OFURL URLWithString: @"file:///etc/passwd"]) &&
	    R(URL5 = [OFURL URLWithString: @"http://foo/bar/qux/foo%2fbar"]) &&
	    R(URL6 = [OFURL URLWithString: @"https://[12:34::56:abcd]/"]) &&
	    R(URL7 = [OFURL URLWithString: @"https://[12:34::56:abcd]:234/"]))

	EXPECT_EXCEPTION(@"+[URLWithString:] fails with invalid characters #1",
	    OFInvalidFormatException,
	    [OFURL URLWithString: @"ht,tp://foo"])

	EXPECT_EXCEPTION(@"+[URLWithString:] fails with invalid characters #2",
	    OFInvalidFormatException,
................................................................................
	    [OFURL URLWithString: @"https://[f]:/"])

	EXPECT_EXCEPTION(@"+[URLWithString:] fails with invalid characters #8",
	    OFInvalidFormatException,
	    [OFURL URLWithString: @"https://[f]:f/"])

	TEST(@"+[URLWithString:relativeToURL:]",
	    [[[OFURL URLWithString: @"/foo" relativeToURL: URL1] string]
	    isEqual: @"ht%3atp://us%3Aer:p%40w@ho%3Ast:1234/foo"] &&
	    [[[OFURL URLWithString: @"foo/bar?q"
		     relativeToURL: [OFURL URLWithString: @"http://h/qux/quux"]]
	    string] isEqual: @"http://h/qux/foo/bar?q"] &&
	    [[[OFURL URLWithString: @"foo/bar"
		     relativeToURL: [OFURL URLWithString: @"http://h/qux/?x"]]
	    string] isEqual: @"http://h/qux/foo/bar"] &&
	    [[[OFURL URLWithString: @"http://foo/?q"
		     relativeToURL: URL1] string] isEqual: @"http://foo/?q"] &&
	    [[[OFURL URLWithString: @"foo"
		     relativeToURL: [OFURL URLWithString: @"http://foo/bar"]]
	    string] isEqual: @"http://foo/foo"] &&
	    [[[OFURL URLWithString: @"foo"
		     relativeToURL: [OFURL URLWithString: @"http://foo"]]
	    string] isEqual: @"http://foo/foo"])

	EXPECT_EXCEPTION(
	    @"+[URLWithString:relativeToURL:] fails with invalid characters #1",
	    OFInvalidFormatException,
	    [OFURL URLWithString: @"`" relativeToURL: URL1])

	EXPECT_EXCEPTION(
	    @"+[URLWithString:relativeToURL:] fails with invalid characters #2",
	    OFInvalidFormatException,
	    [OFURL URLWithString: @"/`" relativeToURL: URL1])

	EXPECT_EXCEPTION(
	    @"+[URLWithString:relativeToURL:] fails with invalid characters #3",
	    OFInvalidFormatException,
	    [OFURL URLWithString: @"?`" relativeToURL: URL1])

	EXPECT_EXCEPTION(
	    @"+[URLWithString:relativeToURL:] fails with invalid characters #4",
	    OFInvalidFormatException,
	    [OFURL URLWithString: @"#`" relativeToURL: URL1])

#ifdef OF_HAVE_FILES
	TEST(@"+[fileURLWithPath:]",
	    [[[OFURL fileURLWithPath: @"testfile.txt"] fileSystemRepresentation]
	    isEqual: [[OFFileManager defaultManager].currentDirectoryPath
	    stringByAppendingPathComponent: @"testfile.txt"]])

................................................................................
	    [tmp.host isEqual: @"test"] && [tmp.path isEqual: @"/"] &&
	    [tmp.string isEqual: @"file://test/"] &&
	    [tmp.fileSystemRepresentation isEqual: @"\\\\test"])
# endif
#endif

	TEST(@"-[string]",
	    [URL1.string isEqual: URLString] &&
	    [URL2.string isEqual: @"http://foo:80"] &&
	    [URL3.string isEqual: @"http://bar/"] &&
	    [URL4.string isEqual: @"file:///etc/passwd"])

	TEST(@"-[scheme]",
	    [URL1.scheme isEqual: @"ht:tp"] && [URL4.scheme isEqual: @"file"])

	TEST(@"-[user]", [URL1.user isEqual: @"us:er"] && URL4.user == nil)
	TEST(@"-[password]",
	    [URL1.password isEqual: @"p@w"] && URL4.password == nil)
	TEST(@"-[host]", [URL1.host isEqual: @"ho:st"] &&
	    [URL6.host isEqual: @"12:34::56:abcd"] &&
	    [URL7.host isEqual: @"12:34::56:abcd"])
	TEST(@"-[port]", URL1.port.unsignedShortValue == 1234 &&
	    [URL4 port] == nil && URL7.port.unsignedShortValue == 234)
	TEST(@"-[path]",
	    [URL1.path isEqual: @"/pa?th"] &&
	    [URL4.path isEqual: @"/etc/passwd"])
	TEST(@"-[pathComponents]",
	    [URL1.pathComponents isEqual:
	    [OFArray arrayWithObjects: @"/", @"pa?th", nil]] &&
	    [URL4.pathComponents isEqual:
	    [OFArray arrayWithObjects: @"/", @"etc", @"passwd", nil]] &&
	    [URL5.pathComponents isEqual:
	    [OFArray arrayWithObjects: @"/", @"bar", @"qux", @"foo/bar", nil]])
	TEST(@"-[lastPathComponent]",
	    [[[OFURL URLWithString: @"http://host/foo//bar/baz"]
	    lastPathComponent] isEqual: @"baz"] &&
	    [[[OFURL URLWithString: @"http://host/foo//bar/baz/"]
	    lastPathComponent] isEqual: @"baz"] &&
	    [[[OFURL URLWithString: @"http://host/foo/"]
	    lastPathComponent] isEqual: @"foo"] &&
	    [[[OFURL URLWithString: @"http://host/"]
	    lastPathComponent] isEqual: @"/"] &&
	    [URL5.lastPathComponent isEqual: @"foo/bar"])
	TEST(@"-[query]",
	    [URL1.query isEqual: @"que#ry=1&f&oo=b=ar"] && URL4.query == nil)
	TEST(@"-[queryDictionary]",
	    [URL1.queryDictionary isEqual:
	    [OFDictionary dictionaryWithKeysAndObjects:
	    @"que#ry", @"1", @"f&oo", @"b=ar", nil]]);
	TEST(@"-[fragment]",
	    [URL1.fragment isEqual: @"frag#ment"] && URL4.fragment == nil)

	TEST(@"-[copy]", R(URL4 = [[URL1 copy] autorelease]))

	TEST(@"-[isEqual:]", [URL1 isEqual: URL4] && ![URL2 isEqual: URL3] &&
	    [[OFURL URLWithString: @"HTTP://bar/"] isEqual: URL3])

	TEST(@"-[hash:]", URL1.hash == URL4.hash && URL2.hash != URL3.hash)

	EXPECT_EXCEPTION(@"Detection of invalid format",
	    OFInvalidFormatException, [OFURL URLWithString: @"http"])

	mutableURL = [OFMutableURL URL];

	TEST(@"-[setScheme:]",
	    (mutableURL.scheme = @"ht:tp") &&
	    [mutableURL.URLEncodedScheme isEqual: @"ht%3Atp"])

	TEST(@"-[setURLEncodedScheme:]",
	    (mutableURL.URLEncodedScheme = @"ht%3Atp") &&
	    [mutableURL.scheme isEqual: @"ht:tp"])

	EXPECT_EXCEPTION(
	    @"-[setURLEncodedScheme:] with invalid characters fails",
	    OFInvalidFormatException, mutableURL.URLEncodedScheme = @"~")

	TEST(@"-[setHost:]",
	    (mutableURL.host = @"ho:st") &&
	    [mutableURL.URLEncodedHost isEqual: @"ho%3Ast"] &&
	    (mutableURL.host = @"12:34:ab") &&
	    [mutableURL.URLEncodedHost isEqual: @"[12:34:ab]"] &&
	    (mutableURL.host = @"12:34:aB") &&
	    [mutableURL.URLEncodedHost isEqual: @"[12:34:aB]"] &&
	    (mutableURL.host = @"12:34:g") &&
	    [mutableURL.URLEncodedHost isEqual: @"12%3A34%3Ag"])

	TEST(@"-[setURLEncodedHost:]",
	    (mutableURL.URLEncodedHost = @"ho%3Ast") &&
	    [mutableURL.host isEqual: @"ho:st"] &&
	    (mutableURL.URLEncodedHost = @"[12:34]") &&
	    [mutableURL.host isEqual: @"12:34"] &&
	    (mutableURL.URLEncodedHost = @"[12::ab]") &&
	    [mutableURL.host isEqual: @"12::ab"])

	EXPECT_EXCEPTION(@"-[setURLEncodedHost:] with invalid characters fails"
	    " #1", OFInvalidFormatException, mutableURL.URLEncodedHost = @"/")

	EXPECT_EXCEPTION(@"-[setURLEncodedHost:] with invalid characters fails"
	    " #2", OFInvalidFormatException,
	    mutableURL.URLEncodedHost = @"[12:34")

	EXPECT_EXCEPTION(@"-[setURLEncodedHost:] with invalid characters fails"
	    " #3", OFInvalidFormatException,
	    mutableURL.URLEncodedHost = @"[a::g]")

	TEST(@"-[setUser:]",
	    (mutableURL.user = @"us:er") &&
	    [mutableURL.URLEncodedUser isEqual: @"us%3Aer"])

	TEST(@"-[setURLEncodedUser:]",
	    (mutableURL.URLEncodedUser = @"us%3Aer") &&
	    [mutableURL.user isEqual: @"us:er"])

	EXPECT_EXCEPTION(@"-[setURLEncodedUser:] with invalid characters fails",
	    OFInvalidFormatException, mutableURL.URLEncodedHost = @"/")

	TEST(@"-[setPassword:]",
	    (mutableURL.password = @"pass:word") &&
	    [mutableURL.URLEncodedPassword isEqual: @"pass%3Aword"])

	TEST(@"-[setURLEncodedPassword:]",
	    (mutableURL.URLEncodedPassword = @"pass%3Aword") &&
	    [mutableURL.password isEqual: @"pass:word"])

	EXPECT_EXCEPTION(
	    @"-[setURLEncodedPassword:] with invalid characters fails",
	    OFInvalidFormatException, mutableURL.URLEncodedPassword = @"/")

	TEST(@"-[setPath:]",
	    (mutableURL.path = @"pa/th@?") &&
	    [mutableURL.URLEncodedPath isEqual: @"pa/th@%3F"])

	TEST(@"-[setURLEncodedPath:]",
	    (mutableURL.URLEncodedPath = @"pa/th@%3F") &&
	    [mutableURL.path isEqual: @"pa/th@?"])

	EXPECT_EXCEPTION(@"-[setURLEncodedPath:] with invalid characters fails",
	    OFInvalidFormatException, mutableURL.URLEncodedPath = @"?")

	TEST(@"-[setQuery:]",
	    (mutableURL.query = @"que/ry?#") &&
	    [mutableURL.URLEncodedQuery isEqual: @"que/ry?%23"])

	TEST(@"-[setURLEncodedQuery:]",
	    (mutableURL.URLEncodedQuery = @"que/ry?%23") &&
	    [mutableURL.query isEqual: @"que/ry?#"])

	EXPECT_EXCEPTION(
	    @"-[setURLEncodedQuery:] with invalid characters fails",
	    OFInvalidFormatException, mutableURL.URLEncodedQuery = @"`")

	TEST(@"-[setQueryDictionary:]",
	    (mutableURL.queryDictionary =
	    [OFDictionary dictionaryWithKeysAndObjects:
	    @"foo&bar", @"baz=qux", @"f=oobar", @"b&azqux", nil]) &&
	    [mutableURL.URLEncodedQuery isEqual:
	    @"foo%26bar=baz%3Dqux&f%3Doobar=b%26azqux"])

	TEST(@"-[setFragment:]",
	    (mutableURL.fragment = @"frag/ment?#") &&
	    [mutableURL.URLEncodedFragment isEqual: @"frag/ment?%23"])

	TEST(@"-[setURLEncodedFragment:]",
	    (mutableURL.URLEncodedFragment = @"frag/ment?%23") &&
	    [mutableURL.fragment isEqual: @"frag/ment?#"])

	EXPECT_EXCEPTION(
	    @"-[setURLEncodedFragment:] with invalid characters fails",
	    OFInvalidFormatException, mutableURL.URLEncodedFragment = @"`")

	TEST(@"-[URLByAppendingPathComponent:isDirectory:]",
	    [[[OFURL URLWithString: @"file:///foo/bar"]
	    URLByAppendingPathComponent: @"qux" isDirectory: false] isEqual:
	    [OFURL URLWithString: @"file:///foo/bar/qux"]] &&
	    [[[OFURL URLWithString: @"file:///foo/bar/"]
	    URLByAppendingPathComponent: @"qux" isDirectory: false] isEqual:

Modified tests/OFValueTests.m from [f7da5ac296] to [f0ec7ac363].

15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

#include "config.h"

#include <string.h>

#import "TestsAppDelegate.h"

static OFString *module = @"OFValue";

@implementation TestsAppDelegate (OFValueTests)
- (void)valueTests
{
	void *pool = objc_autoreleasePoolPush();
	OFRange range = OFRangeMake(1, 64), range2;
	OFPoint point = OFPointMake(1.5f, 3.0f), point2;







|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

#include "config.h"

#include <string.h>

#import "TestsAppDelegate.h"

static OFString *const module = @"OFValue";

@implementation TestsAppDelegate (OFValueTests)
- (void)valueTests
{
	void *pool = objc_autoreleasePoolPush();
	OFRange range = OFRangeMake(1, 64), range2;
	OFPoint point = OFPointMake(1.5f, 3.0f), point2;

Modified tests/OFWindowsRegistryKeyTests.m from [5df411ba49] to [b3eba3a2d6].

13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
..
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
 * file.
 */

#include "config.h"

#import "TestsAppDelegate.h"

static OFString *module = @"OFWindowsRegistryKey";

@implementation TestsAppDelegate (OFWindowsRegistryKeyTests)
- (void)windowsRegistryKeyTests
{
	void *pool = objc_autoreleasePoolPush();
	OFData *data = [OFData dataWithItems: "abcdef" count: 6];
	OFWindowsRegistryKey *softwareKey, *ObjFWKey;
	DWORD type;

	TEST(@"+[OFWindowsRegistryKey classesRootKey]",
	    [OFWindowsRegistryKey classesRootKey])

	TEST(@"+[OFWindowsRegistryKey currentConfigKey]",
	    [OFWindowsRegistryKey currentConfigKey])
................................................................................
		   openSubkeyAtPath: @"Software"
	    securityAndAccessRights: KEY_ALL_ACCESS]) &&
	    [[OFWindowsRegistryKey currentUserKey]
		   openSubkeyAtPath: @"nonexistent"
	    securityAndAccessRights: KEY_ALL_ACCESS] == nil)

	TEST(@"-[createSubkeyAtPath:securityAndAccessRights:]",
	    (ObjFWKey = [softwareKey createSubkeyAtPath: @"ObjFW"
				securityAndAccessRights: KEY_ALL_ACCESS]))

	TEST(@"-[setData:forValueNamed:type:]",
	    R([ObjFWKey setData: data forValueNamed: @"data" type: REG_BINARY]))

	TEST(@"-[dataForValueNamed:subkeyPath:flags:type:]",
	    [[ObjFWKey dataForValueNamed: @"data" type: &type] isEqual: data] &&
	    type == REG_BINARY)

	TEST(@"-[setString:forValueNamed:type:]",
	    R([ObjFWKey setString: @"foobar" forValueNamed: @"string"]) &&
	    R([ObjFWKey setString: @"%PATH%;foo"
		    forValueNamed: @"expand"
			     type: REG_EXPAND_SZ]))

	TEST(@"-[stringForValue:subkeyPath:]",
	    [[ObjFWKey stringForValueNamed: @"string"] isEqual: @"foobar"] &&
	    [[ObjFWKey stringForValueNamed: @"expand" type: &type]
	    isEqual: @"%PATH%;foo"] &&
	    type == REG_EXPAND_SZ)

	TEST(@"-[deleteValueNamed:]", R([ObjFWKey deleteValueNamed: @"data"]))

	TEST(@"-[deleteSubkeyAtPath:]",
	    R([softwareKey deleteSubkeyAtPath: @"ObjFW"]))

	objc_autoreleasePoolPop(pool);
}
@end







|






|







 







|



|


|



|
|




|
|



|







13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
..
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
 * file.
 */

#include "config.h"

#import "TestsAppDelegate.h"

static OFString *const module = @"OFWindowsRegistryKey";

@implementation TestsAppDelegate (OFWindowsRegistryKeyTests)
- (void)windowsRegistryKeyTests
{
	void *pool = objc_autoreleasePoolPush();
	OFData *data = [OFData dataWithItems: "abcdef" count: 6];
	OFWindowsRegistryKey *softwareKey, *objFWKey;
	DWORD type;

	TEST(@"+[OFWindowsRegistryKey classesRootKey]",
	    [OFWindowsRegistryKey classesRootKey])

	TEST(@"+[OFWindowsRegistryKey currentConfigKey]",
	    [OFWindowsRegistryKey currentConfigKey])
................................................................................
		   openSubkeyAtPath: @"Software"
	    securityAndAccessRights: KEY_ALL_ACCESS]) &&
	    [[OFWindowsRegistryKey currentUserKey]
		   openSubkeyAtPath: @"nonexistent"
	    securityAndAccessRights: KEY_ALL_ACCESS] == nil)

	TEST(@"-[createSubkeyAtPath:securityAndAccessRights:]",
	    (objFWKey = [softwareKey createSubkeyAtPath: @"ObjFW"
				securityAndAccessRights: KEY_ALL_ACCESS]))

	TEST(@"-[setData:forValueNamed:type:]",
	    R([objFWKey setData: data forValueNamed: @"data" type: REG_BINARY]))

	TEST(@"-[dataForValueNamed:subkeyPath:flags:type:]",
	    [[objFWKey dataForValueNamed: @"data" type: &type] isEqual: data] &&
	    type == REG_BINARY)

	TEST(@"-[setString:forValueNamed:type:]",
	    R([objFWKey setString: @"foobar" forValueNamed: @"string"]) &&
	    R([objFWKey setString: @"%PATH%;foo"
		    forValueNamed: @"expand"
			     type: REG_EXPAND_SZ]))

	TEST(@"-[stringForValue:subkeyPath:]",
	    [[objFWKey stringForValueNamed: @"string"] isEqual: @"foobar"] &&
	    [[objFWKey stringForValueNamed: @"expand" type: &type]
	    isEqual: @"%PATH%;foo"] &&
	    type == REG_EXPAND_SZ)

	TEST(@"-[deleteValueNamed:]", R([objFWKey deleteValueNamed: @"data"]))

	TEST(@"-[deleteSubkeyAtPath:]",
	    R([softwareKey deleteSubkeyAtPath: @"ObjFW"]))

	objc_autoreleasePoolPop(pool);
}
@end

Modified tests/OFXMLElementBuilderTests.m from [47b293e0e2] to [1ae510b9c5].

13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
..
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
 * file.
 */

#include "config.h"

#import "TestsAppDelegate.h"

static OFString *module = @"OFXMLElementBuilder";
static OFXMLNode *nodes[2];
static size_t i = 0;

@implementation TestsAppDelegate (OFXMLElementBuilderTests)
- (void)elementBuilder: (OFXMLElementBuilder *)builder
       didBuildElement: (OFXMLElement *)element
{
................................................................................
	OFEnsure(i == 1);
	nodes[i++] = [node retain];
}

- (void)XMLElementBuilderTests
{
	void *pool = objc_autoreleasePoolPush();
	OFXMLParser *p = [OFXMLParser parser];
	OFXMLElementBuilder *builder = [OFXMLElementBuilder builder];
	OFString *str = @"<foo>bar<![CDATA[f<oo]]>baz<qux/>"
	    " <qux xmlns:qux='urn:qux'><?asd?><qux:bar/><x qux:y='z'/></qux>"
	    "</foo>";

	p.delegate = builder;
	builder.delegate = self;

	TEST(@"Building elements from parsed XML",
	    R([p parseString: str]) &&
	    nodes[0] != nil && [nodes[0].XMLString isEqual: str] &&
	    R([p parseString: @"<!--foo-->"]) &&
	    nodes[1] != nil && [nodes[1].XMLString isEqual: @"<!--foo-->"] &&
	    i == 2)

	[nodes[0] release];
	[nodes[1] release];
	objc_autoreleasePoolPop(pool);
}
@end







|







 







|

|



|



|
|
|








13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
..
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
 * file.
 */

#include "config.h"

#import "TestsAppDelegate.h"

static OFString *const module = @"OFXMLElementBuilder";
static OFXMLNode *nodes[2];
static size_t i = 0;

@implementation TestsAppDelegate (OFXMLElementBuilderTests)
- (void)elementBuilder: (OFXMLElementBuilder *)builder
       didBuildElement: (OFXMLElement *)element
{
................................................................................
	OFEnsure(i == 1);
	nodes[i++] = [node retain];
}

- (void)XMLElementBuilderTests
{
	void *pool = objc_autoreleasePoolPush();
	OFXMLParser *parser = [OFXMLParser parser];
	OFXMLElementBuilder *builder = [OFXMLElementBuilder builder];
	OFString *string = @"<foo>bar<![CDATA[f<oo]]>baz<qux/>"
	    " <qux xmlns:qux='urn:qux'><?asd?><qux:bar/><x qux:y='z'/></qux>"
	    "</foo>";

	parser.delegate = builder;
	builder.delegate = self;

	TEST(@"Building elements from parsed XML",
	    R([parser parseString: string]) &&
	    nodes[0] != nil && [nodes[0].XMLString isEqual: string] &&
	    R([parser parseString: @"<!--foo-->"]) &&
	    nodes[1] != nil && [nodes[1].XMLString isEqual: @"<!--foo-->"] &&
	    i == 2)

	[nodes[0] release];
	[nodes[1] release];
	objc_autoreleasePoolPop(pool);
}
@end

Modified tests/OFXMLNodeTests.m from [c231b8bd5e] to [3a041e8eb3].

13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28


29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
 * file.
 */

#include "config.h"

#import "TestsAppDelegate.h"

static OFString *module = @"OFXMLNode";

@implementation TestsAppDelegate (OFXMLNodeTests)
- (void)XMLNodeTests
{
	void *pool = objc_autoreleasePoolPush();
	id nodes[4];
	OFArray *a;



	TEST(@"+[elementWithName:]",
	    (nodes[0] = [OFXMLElement elementWithName: @"foo"]) &&
	    [[nodes[0] XMLString] isEqual: @"<foo/>"])

	TEST(@"+[elementWithName:stringValue:]",
	    (nodes[1] = [OFXMLElement elementWithName: @"foo"
					  stringValue: @"b&ar"]) &&
	    [[nodes[1] XMLString] isEqual: @"<foo>b&amp;ar</foo>"])

	TEST(@"+[elementWithName:namespace:]",
	    (nodes[2] = [OFXMLElement elementWithName: @"foo"
					    namespace: @"urn:objfw:test"]) &&
	    R([nodes[2] addAttributeWithName: @"test" stringValue: @"test"]) &&
	    R([nodes[2] setPrefix: @"objfw-test"
		     forNamespace: @"urn:objfw:test"]) &&
	    [[nodes[2] XMLString] isEqual: @"<objfw-test:foo test='test'/>"] &&
	    (nodes[3] = [OFXMLElement elementWithName: @"foo"
					    namespace: @"urn:objfw:test"]) &&
	    R([nodes[3] addAttributeWithName: @"test" stringValue: @"test"]) &&
	    [[nodes[3] XMLString] isEqual:
	    @"<foo xmlns='urn:objfw:test' test='test'/>"])

	TEST(@"+[elementWithName:namespace:stringValue:]",
	    (nodes[3] = [OFXMLElement elementWithName: @"foo"
					    namespace: @"urn:objfw:test"
					  stringValue: @"x"]) &&
	    R([nodes[3] setPrefix: @"objfw-test"
		     forNamespace: @"urn:objfw:test"]) &&
	    [[nodes[3] XMLString] isEqual:
	    @"<objfw-test:foo>x</objfw-test:foo>"])

	TEST(@"+[charactersWithString:]",
	    (nodes[3] = [OFXMLCharacters charactersWithString: @"<foo>"]) &&
	    [[nodes[3] XMLString] isEqual: @"&lt;foo&gt;"])

	TEST(@"+[CDATAWithString:]",
	    (nodes[3] = [OFXMLCDATA CDATAWithString: @"<foo>"]) &&
	    [[nodes[3] XMLString] isEqual: @"<![CDATA[<foo>]]>"]);

	TEST(@"+[commentWithText:]",
	    (nodes[3] = [OFXMLComment commentWithText: @" comment "]) &&
	    [[nodes[3] XMLString] isEqual: @"<!-- comment -->"])

	module = @"OFXMLElement";

	TEST(@"-[addAttributeWithName:stringValue:]",
	    R([nodes[0] addAttributeWithName: @"foo" stringValue: @"b&ar"]) &&
	    [[nodes[0] XMLString] isEqual: @"<foo foo='b&amp;ar'/>"] &&
	    R([nodes[1] addAttributeWithName: @"foo" stringValue: @"b&ar"]) &&
	    [[nodes[1] XMLString] isEqual:
	    @"<foo foo='b&amp;ar'>b&amp;ar</foo>"])

	TEST(@"-[setPrefix:forNamespace:]",
	    R([nodes[1] setPrefix: @"objfw-test"
		     forNamespace: @"urn:objfw:test"]))

	TEST(@"-[addAttributeWithName:namespace:stringValue:]",
	    R([nodes[1] addAttributeWithName: @"foo"
				   namespace: @"urn:objfw:test"
				 stringValue: @"bar"]) &&
	    R([nodes[1] addAttributeWithName: @"foo"
				   namespace: @"urn:objfw:test"
				 stringValue: @"ignored"]) &&
	    [[nodes[1] XMLString] isEqual:
	    @"<foo foo='b&amp;ar' objfw-test:foo='bar'>b&amp;ar</foo>"])

	TEST(@"-[removeAttributeForName:namespace:]",
	    R([nodes[1] removeAttributeForName: @"foo"]) &&
	    [[nodes[1] XMLString] isEqual:
	    @"<foo objfw-test:foo='bar'>b&amp;ar</foo>"] &&
	    R([nodes[1] removeAttributeForName: @"foo"
				     namespace: @"urn:objfw:test"]) &&
	    [[nodes[1] XMLString] isEqual: @"<foo>b&amp;ar</foo>"])

	TEST(@"-[addChild:]",
	    R([nodes[0] addChild: [OFXMLElement elementWithName: @"bar"]]) &&
	    [[nodes[0] XMLString] isEqual:
	    @"<foo foo='b&amp;ar'><bar/></foo>"] &&
	    R([nodes[2] addChild: [OFXMLElement elementWithName: @"bar"
		       namespace: @"urn:objfw:test"]]) &&
	    [[nodes[2] XMLString] isEqual:
	    @"<objfw-test:foo test='test'><objfw-test:bar/></objfw-test:foo>"])

	TEST(@"+[elementWithXMLString:] and -[stringValue]",
	    [[[OFXMLElement elementWithXMLString:
	    @"<?xml version='1.0' encoding='UTF-8'?>\r\n<x>foo<![CDATA[bar]]>"
	    @"<y>b<!-- fooo -->az</y>qux</x>"] stringValue]
	    isEqual: @"foobarbazqux"])

	TEST(@"-[elementsForName:namespace:]",
	    (a = [nodes[2] elementsForName: @"bar"
				 namespace: @"urn:objfw:test"]) &&
	    a.count == 1 && [[[a firstObject] XMLString] isEqual:
	    @"<bar xmlns='urn:objfw:test'/>"])

	TEST(@"-[isEqual:]",
	    [[OFXMLElement elementWithXMLString: @"<foo bar='asd'/>"] isEqual:
	    [OFXMLElement elementWithXMLString: @"<foo bar='asd'></foo>"]] &&
	    [[OFXMLElement elementWithXMLString: @"<x><y/></x>"] isEqual:
	    [OFXMLElement elementWithXMLString: @"<x><y></y></x>"]])







|





|
|

>
>

|
|


|
|
|


|
|
|
|
|
|
|
|
|
|



|
|
|
|
|
<
|


|
|


|
|


|
|




|
|
|
<
|


|
|


|
|
|
|
|
|
|



|
|

|
|
|


|
|

|
|
|









|
|
|







13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58

59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78

79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
 * file.
 */

#include "config.h"

#import "TestsAppDelegate.h"

static OFString *module;

@implementation TestsAppDelegate (OFXMLNodeTests)
- (void)XMLNodeTests
{
	void *pool = objc_autoreleasePoolPush();
	id node1, node2, node3, node4;
	OFArray *array;

	module = @"OFXMLNode";

	TEST(@"+[elementWithName:]",
	    (node1 = [OFXMLElement elementWithName: @"foo"]) &&
	    [[node1 XMLString] isEqual: @"<foo/>"])

	TEST(@"+[elementWithName:stringValue:]",
	    (node2 = [OFXMLElement elementWithName: @"foo"
				       stringValue: @"b&ar"]) &&
	    [[node2 XMLString] isEqual: @"<foo>b&amp;ar</foo>"])

	TEST(@"+[elementWithName:namespace:]",
	    (node3 = [OFXMLElement elementWithName: @"foo"
					 namespace: @"urn:objfw:test"]) &&
	    R([node3 addAttributeWithName: @"test" stringValue: @"test"]) &&
	    R([node3 setPrefix: @"objfw-test"
		  forNamespace: @"urn:objfw:test"]) &&
	    [[node3 XMLString] isEqual: @"<objfw-test:foo test='test'/>"] &&
	    (node4 = [OFXMLElement elementWithName: @"foo"
					 namespace: @"urn:objfw:test"]) &&
	    R([node4 addAttributeWithName: @"test" stringValue: @"test"]) &&
	    [[node4 XMLString] isEqual:
	    @"<foo xmlns='urn:objfw:test' test='test'/>"])

	TEST(@"+[elementWithName:namespace:stringValue:]",
	    (node4 = [OFXMLElement elementWithName: @"foo"
					 namespace: @"urn:objfw:test"
				       stringValue: @"x"]) &&
	    R([node4 setPrefix: @"objfw-test"
		  forNamespace: @"urn:objfw:test"]) &&

	    [[node4 XMLString] isEqual: @"<objfw-test:foo>x</objfw-test:foo>"])

	TEST(@"+[charactersWithString:]",
	    (node4 = [OFXMLCharacters charactersWithString: @"<foo>"]) &&
	    [[node4 XMLString] isEqual: @"&lt;foo&gt;"])

	TEST(@"+[CDATAWithString:]",
	    (node4 = [OFXMLCDATA CDATAWithString: @"<foo>"]) &&
	    [[node4 XMLString] isEqual: @"<![CDATA[<foo>]]>"]);

	TEST(@"+[commentWithText:]",
	    (node4 = [OFXMLComment commentWithText: @" comment "]) &&
	    [[node4 XMLString] isEqual: @"<!-- comment -->"])

	module = @"OFXMLElement";

	TEST(@"-[addAttributeWithName:stringValue:]",
	    R([node1 addAttributeWithName: @"foo" stringValue: @"b&ar"]) &&
	    [[node1 XMLString] isEqual: @"<foo foo='b&amp;ar'/>"] &&
	    R([node2 addAttributeWithName: @"foo" stringValue: @"b&ar"]) &&

	    [[node2 XMLString] isEqual: @"<foo foo='b&amp;ar'>b&amp;ar</foo>"])

	TEST(@"-[setPrefix:forNamespace:]",
	    R([node2 setPrefix: @"objfw-test"
		  forNamespace: @"urn:objfw:test"]))

	TEST(@"-[addAttributeWithName:namespace:stringValue:]",
	    R([node2 addAttributeWithName: @"foo"
				namespace: @"urn:objfw:test"
			      stringValue: @"bar"]) &&
	    R([node2 addAttributeWithName: @"foo"
				namespace: @"urn:objfw:test"
			      stringValue: @"ignored"]) &&
	    [[node2 XMLString] isEqual:
	    @"<foo foo='b&amp;ar' objfw-test:foo='bar'>b&amp;ar</foo>"])

	TEST(@"-[removeAttributeForName:namespace:]",
	    R([node2 removeAttributeForName: @"foo"]) &&
	    [[node2 XMLString] isEqual:
	    @"<foo objfw-test:foo='bar'>b&amp;ar</foo>"] &&
	    R([node2 removeAttributeForName: @"foo"
				  namespace: @"urn:objfw:test"]) &&
	    [[node2 XMLString] isEqual: @"<foo>b&amp;ar</foo>"])

	TEST(@"-[addChild:]",
	    R([node1 addChild: [OFXMLElement elementWithName: @"bar"]]) &&
	    [[node1 XMLString] isEqual:
	    @"<foo foo='b&amp;ar'><bar/></foo>"] &&
	    R([node3 addChild: [OFXMLElement elementWithName: @"bar"
		    namespace: @"urn:objfw:test"]]) &&
	    [[node3 XMLString] isEqual:
	    @"<objfw-test:foo test='test'><objfw-test:bar/></objfw-test:foo>"])

	TEST(@"+[elementWithXMLString:] and -[stringValue]",
	    [[[OFXMLElement elementWithXMLString:
	    @"<?xml version='1.0' encoding='UTF-8'?>\r\n<x>foo<![CDATA[bar]]>"
	    @"<y>b<!-- fooo -->az</y>qux</x>"] stringValue]
	    isEqual: @"foobarbazqux"])

	TEST(@"-[elementsForName:namespace:]",
	    (array = [node3 elementsForName: @"bar"
				  namespace: @"urn:objfw:test"]) &&
	    array.count == 1 && [[array.firstObject XMLString] isEqual:
	    @"<bar xmlns='urn:objfw:test'/>"])

	TEST(@"-[isEqual:]",
	    [[OFXMLElement elementWithXMLString: @"<foo bar='asd'/>"] isEqual:
	    [OFXMLElement elementWithXMLString: @"<foo bar='asd'></foo>"]] &&
	    [[OFXMLElement elementWithXMLString: @"<x><y/></x>"] isEqual:
	    [OFXMLElement elementWithXMLString: @"<x><y></y></x>"]])

Modified tests/OFXMLParserTests.m from [20f4783b1c] to [3eb25f939e].

16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51

52
53
54
55
56

57
58
59

60
61

62
63

64
65
66

67
68
69
70

71
72
73
74

75
76
77
78

79
80
81

82

83
84
85
86
87
88
89
90
91

92
93
94

95

96
97
98
99
100
101
102
103
104
105

106
107
108

109
110
111
112
113
114
115
116
117
118
119
120
121
122
123

124
125
126

127

128
129
130
131
132
133
134
135
136
137
138
139
140

141

142
143
144

145
146
147

148
149
150

151
152
153
154
155
156
157
...
161
162
163
164
165
166
167

168
169
170
171
172

173
174
175

176

177
178
179
180
181
182
183
184
...
188
189
190
191
192
193
194

195
196
197
198

199
200
201

202
203
204
205
206

207
208
209

210
211
212

213
214
215

216

217
218
219

220
221
222

223

224
225
226

227
228
229

230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
...
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
...
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
#include "config.h"

#include <stdlib.h>
#include <string.h>

#import "TestsAppDelegate.h"

static OFString *module = @"OFXMLParser";
static int i = 0;

enum event_type {
	PROCESSING_INSTRUCTION,
	TAG_OPEN,
	TAG_CLOSE,
	STRING,
	CDATA,
	COMMENT
};

@implementation TestsAppDelegate (OFXMLParser)
-   (void)parser: (OFXMLParser *)parser
  didCreateEvent: (enum event_type)type
	    name: (OFString *)name
	  prefix: (OFString *)prefix
       namespace: (OFString *)ns
      attributes: (OFArray *)attrs
	  string: (OFString *)string
{
	OFString *msg;

	i++;
	msg = [OFString stringWithFormat: @"Parsing part #%d", i];

	switch (i) {
	case 1:
		TEST(msg, type == PROCESSING_INSTRUCTION &&

		    [name isEqual: @"xml"] &&
		    [string isEqual: @"version='1.0'"])
		break;
	case 2:
		TEST(msg, type == PROCESSING_INSTRUCTION &&

		    [name isEqual: @"p?i"] && string == nil)
		break;
	case 3:

		TEST(msg, type == TAG_OPEN && [name isEqual: @"root"] &&
		    prefix == nil && ns == nil && attrs.count == 0)

		break;
	case 4:

		TEST(msg, type == STRING && [string isEqual: @"\n\n "])
		break;
	case 5:

		TEST(msg, type == CDATA && [string isEqual: @"f<]]]oo]"] &&
		    parser.lineNumber == 3)
		break;
	case 6:

		TEST(msg, type == TAG_OPEN && [name isEqual: @"bar"] &&
		    prefix == nil && ns == nil && attrs == nil)
		break;
	case 7:

		TEST(msg, type == TAG_CLOSE && [name isEqual: @"bar"] &&
		    prefix == nil && ns == nil && attrs == nil)
		break;
	case 8:

		TEST(msg, type == STRING && [string isEqual: @"\n "])
		break;
	case 9:

		TEST(msg, type == TAG_OPEN && [name isEqual: @"foobar"] &&

		    prefix == nil && [ns isEqual: @"urn:objfw:test:foobar"] &&
		    attrs.count == 1 &&
		    /* xmlns attr */
		    [[[attrs objectAtIndex: 0] name] isEqual: @"xmlns"] &&
		    [[attrs objectAtIndex: 0] namespace] == nil &&
		    [[[attrs objectAtIndex: 0] stringValue] isEqual:
		    @"urn:objfw:test:foobar"])
		break;
	case 10:

		TEST(msg, type == STRING && [string isEqual: @"\n  "])
		break;
	case 11:

		TEST(msg, type == TAG_OPEN && [name isEqual: @"qux"] &&

		    prefix == nil && [ns isEqual: @"urn:objfw:test:foobar"] &&
		    attrs.count == 1 &&
		    /* xmlns:foo attr */
		    [[[attrs objectAtIndex: 0] name] isEqual: @"foo"] &&
		    [[[attrs objectAtIndex: 0] namespace] isEqual:
		    @"http://www.w3.org/2000/xmlns/"] &&
		    [[[attrs objectAtIndex: 0] stringValue] isEqual:
		    @"urn:objfw:test:foo"])
		break;
	case 12:

		TEST(msg, type == STRING && [string isEqual: @"\n   "])
		break;
	case 13:

		TEST(msg, type == TAG_OPEN && [name isEqual: @"bla"] &&
		    [prefix isEqual: @"foo"] &&
		    [ns isEqual: @"urn:objfw:test:foo"] &&
		    attrs.count == 2 &&
		    /* foo:bla attr */
		    [[[attrs objectAtIndex: 0] name] isEqual: @"bla"] &&
		    [[[attrs objectAtIndex: 0] namespace] isEqual:
		    @"urn:objfw:test:foo"] &&
		    [[[attrs objectAtIndex: 0] stringValue] isEqual: @"bla"] &&
		    /* blafoo attr */
		    [[[attrs objectAtIndex: 1] name] isEqual: @"blafoo"] &&
		    [[attrs objectAtIndex: 1] namespace] == nil &&
		    [[[attrs objectAtIndex: 1] stringValue] isEqual: @"foo"])
		break;
	case 14:

		TEST(msg, type == STRING && [string isEqual: @"\n    "])
		break;
	case 15:

		TEST(msg, type == TAG_OPEN && [name isEqual: @"blup"] &&

		    prefix == nil && [ns isEqual: @"urn:objfw:test:foobar"] &&
		    attrs.count == 2 &&
		    /* foo:qux attr */
		    [[[attrs objectAtIndex: 0] name] isEqual: @"qux"] &&
		    [[[attrs objectAtIndex: 0] namespace] isEqual:
		    @"urn:objfw:test:foo"] &&
		    [[[attrs objectAtIndex: 0] stringValue] isEqual: @"asd"] &&
		    /* quxqux attr */
		    [[[attrs objectAtIndex: 1] name] isEqual: @"quxqux"] &&
		    [[attrs objectAtIndex: 1] namespace] == nil &&
		    [[[attrs objectAtIndex: 1] stringValue] isEqual: @"test"])
		break;
	case 16:

		TEST(msg, type == TAG_CLOSE && [name isEqual: @"blup"] &&

		    prefix == nil && [ns isEqual: @"urn:objfw:test:foobar"])
		break;
	case 17:

		TEST(msg, type == STRING && [string isEqual: @"\n    "])
		break;
	case 18:

		TEST(msg, type == TAG_OPEN && [name isEqual: @"bla"] &&
		    [prefix isEqual: @"bla"] &&
		    [ns isEqual: @"urn:objfw:test:bla"] && attrs.count == 3 &&

		    /* xmlns:bla attr */
		    [[[attrs objectAtIndex: 0] name] isEqual: @"bla"] &&
		    [[[attrs objectAtIndex: 0] namespace] isEqual:
		    @"http://www.w3.org/2000/xmlns/"] &&
		    [[[attrs objectAtIndex: 0] stringValue] isEqual:
		    @"urn:objfw:test:bla"] &&
		    /* qux attr */
................................................................................
		    /* bla:foo attr */
		    [[[attrs objectAtIndex: 2] name] isEqual: @"foo"] &&
		    [[[attrs objectAtIndex: 2] namespace] isEqual:
		    @"urn:objfw:test:bla"] &&
		    [[[attrs objectAtIndex: 2] stringValue] isEqual: @"blafoo"])
		break;
	case 19:

		TEST(msg, type == TAG_CLOSE && [name isEqual: @"bla"] &&
		    [prefix isEqual: @"bla"] &&
		    [ns isEqual: @"urn:objfw:test:bla"])
		break;
	case 20:

		TEST(msg, type == STRING && [string isEqual: @"\n    "])
		break;
	case 21:

		TEST(msg, type == TAG_OPEN && [name isEqual: @"abc"] &&

		    prefix == nil && [ns isEqual: @"urn:objfw:test:abc"] &&
		    attrs.count == 3 &&
		    /* xmlns attr */
		    [[[attrs objectAtIndex: 0] name] isEqual: @"xmlns"] &&
		    [[attrs objectAtIndex: 0] namespace] == nil &&
		    [[[attrs objectAtIndex: 0] stringValue] isEqual:
		    @"urn:objfw:test:abc"] &&
		    /* abc attr */
................................................................................
		    /* foo:abc attr */
		    [[[attrs objectAtIndex: 2] name] isEqual: @"abc"] &&
		    [[[attrs objectAtIndex: 2] namespace] isEqual:
		    @"urn:objfw:test:foo"] &&
		    [[[attrs objectAtIndex: 2] stringValue] isEqual: @"abc"])
		break;
	case 22:

		TEST(msg, type == TAG_CLOSE && [name isEqual: @"abc"] &&
		    prefix == nil && [ns isEqual: @"urn:objfw:test:abc"])
		break;
	case 23:

		TEST(msg, type == STRING && [string isEqual: @"\n   "])
		break;
	case 24:

		TEST(msg, type == TAG_CLOSE && [name isEqual: @"bla"] &&
		    [prefix isEqual: @"foo"] &&
		    [ns isEqual: @"urn:objfw:test:foo"])
		break;
	case 25:

		TEST(msg, type == STRING && [string isEqual: @"\n   "])
		break;
	case 26:

		TEST(msg, type == COMMENT && [string isEqual: @" commänt "])
		break;
	case 27:

		TEST(msg, type == STRING && [string isEqual: @"\n  "])
		break;
	case 28:

		TEST(msg, type == TAG_CLOSE && [name isEqual: @"qux"] &&

		    prefix == nil && [ns isEqual: @"urn:objfw:test:foobar"])
		break;
	case 29:

		TEST(msg, type == STRING && [string isEqual: @"\n "])
		break;
	case 30:

		TEST(msg, type == TAG_CLOSE && [name isEqual: @"foobar"] &&

		    prefix == nil && [ns isEqual: @"urn:objfw:test:foobar"])
		break;
	case 31:

		TEST(msg, type == STRING && [string isEqual: @"\n"])
		break;
	case 32:

		TEST(msg, type == TAG_CLOSE && [name isEqual: @"root"] &&
		    prefix == nil && ns == nil);
		break;
	}
}

-			  (void)parser: (OFXMLParser *)parser
  foundProcessingInstructionWithTarget: (OFString *)target
				  data: (OFString *)data
{
	[self	    parser: parser
	    didCreateEvent: PROCESSING_INSTRUCTION
		      name: target
		    prefix: nil
		 namespace: nil
		attributes: nil
		    string: data];
}

-    (void)parser: (OFXMLParser *)parser
  didStartElement: (OFString *)name
	   prefix: (OFString *)prefix
	namespace: (OFString *)ns
       attributes: (OFArray *)attrs
{
	[self	    parser: parser
	    didCreateEvent: TAG_OPEN
		      name: name
		    prefix: prefix
		 namespace: ns
		attributes: attrs
		    string: nil];
}

-  (void)parser: (OFXMLParser *)parser
  didEndElement: (OFString *)name
	 prefix: (OFString *)prefix
      namespace: (OFString *)ns
{
	[self	    parser: parser
	    didCreateEvent: TAG_CLOSE
		      name: name
		    prefix: prefix
		 namespace: ns
		attributes: nil
		    string: nil];
}

- (void)parser: (OFXMLParser *)parser foundCharacters: (OFString *)string
{
	[self	    parser: parser
	    didCreateEvent: STRING
		      name: nil
		    prefix: nil
		 namespace: nil
		attributes: nil
		    string: string];
}

- (void)parser: (OFXMLParser *)parser foundCDATA: (OFString *)cdata
{
	[self	    parser: parser
	    didCreateEvent: CDATA
		      name: nil
		    prefix: nil
		 namespace: nil
		attributes: nil
		    string: cdata];
}

- (void)parser: (OFXMLParser *)parser foundComment: (OFString *)comment
{
	[self	    parser: parser
	    didCreateEvent: COMMENT
		      name: nil
		    prefix: nil
		 namespace: nil
		attributes: nil
		    string: comment];
}

................................................................................

	return nil;
}

- (void)XMLParserTests
{
	void *pool = objc_autoreleasePoolPush();
	const char *str = "\xEF\xBB\xBF<?xml version='1.0'?><?p?i?>"
	    "<!DOCTYPE foo><root>\r\r"
	    " <![CDATA[f<]]]oo]]]><bar/>\n"
	    " <foobar xmlns='urn:objfw:test:foobar'>\r\n"
	    "  <qux xmlns:foo='urn:objfw:test:foo'>\n"
	    "   <foo:bla foo:bla = '&#x62;&#x6c;&#x61;' blafoo='foo'>\n"
	    "    <blup foo:qux='asd' quxqux='test'/>\n"
	    "    <bla:bla\r\rxmlns:bla\r=\t\"urn:objfw:test:bla\" qux='qux'\r\n"
................................................................................
	    "    <abc xmlns='urn:objfw:test:abc' abc='abc' foo:abc='abc'/>\n"
	    "   </foo:bla>\n"
	    "   <!-- commänt -->\n"
	    "  </qux>\n"
	    " </foobar>\n"
	    "</root>";
	OFXMLParser *parser;
	size_t j, len;

	TEST(@"+[parser]", (parser = [OFXMLParser parser]))

	TEST(@"-[setDelegate:]", (parser.delegate = self))

	/* Simulate a stream where we only get chunks */
	len = strlen(str);

	for (j = 0; j < len; j+= 2) {
		if (parser.hasFinishedParsing)
			abort();

		if (j + 2 > len)
			[parser parseBuffer: str + j length: 1];
		else
			[parser parseBuffer: str + j length: 2];
	}

	TEST(@"Checking if everything was parsed",
	    i == 32 && parser.lineNumber == 18)

	TEST(@"-[hasFinishedParsing]", parser.hasFinishedParsing)








|


|
|
|
|
|
|
|




|


|



|


|



|
>




|
>



>
|
<
>


>
|


>
|



>
|
|


>
|
|


>
|


>
|
>
|








>
|


>
|
>
|









>
|


>
|

|












>
|


>
|
>
|












>
|
>
|


>
|


>
|

|
>







 







>
|

|


>
|


>
|
>
|







 







>
|
|


>
|


>
|

|


>
|


>
|


>
|


>
|
>
|


>
|


>
|
>
|


>
|


>
|
|









|










|



|


|







|


|


|







|







|


|




|





|







 







|







 







|






|

|



|
|

|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63

64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
...
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
...
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
...
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
...
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
#include "config.h"

#include <stdlib.h>
#include <string.h>

#import "TestsAppDelegate.h"

static OFString *const module = @"OFXMLParser";
static int i = 0;

enum EventType {
	eventTypeProcessingInstruction,
	eventTypeTagOpen,
	eventTypeTagClose,
	eventTypeString,
	eventTypeCDATA,
	eventTypeComment
};

@implementation TestsAppDelegate (OFXMLParser)
-   (void)parser: (OFXMLParser *)parser
  didCreateEvent: (enum EventType)type
	    name: (OFString *)name
	  prefix: (OFString *)prefix
       namespace: (OFString *)namespace
      attributes: (OFArray *)attrs
	  string: (OFString *)string
{
	OFString *message;

	i++;
	message = [OFString stringWithFormat: @"Parsing part #%d", i];

	switch (i) {
	case 1:
		TEST(message,
		    type == eventTypeProcessingInstruction &&
		    [name isEqual: @"xml"] &&
		    [string isEqual: @"version='1.0'"])
		break;
	case 2:
		TEST(message,
		    type == eventTypeProcessingInstruction &&
		    [name isEqual: @"p?i"] && string == nil)
		break;
	case 3:
		TEST(message,
		    type == eventTypeTagOpen && [name isEqual: @"root"] &&

		    prefix == nil && namespace == nil && attrs.count == 0)
		break;
	case 4:
		TEST(message,
		    type == eventTypeString && [string isEqual: @"\n\n "])
		break;
	case 5:
		TEST(message,
		    type == eventTypeCDATA && [string isEqual: @"f<]]]oo]"] &&
		    parser.lineNumber == 3)
		break;
	case 6:
		TEST(message,
		    type == eventTypeTagOpen && [name isEqual: @"bar"] &&
		    prefix == nil && namespace == nil && attrs == nil)
		break;
	case 7:
		TEST(message,
		    type == eventTypeTagClose && [name isEqual: @"bar"] &&
		    prefix == nil && namespace == nil && attrs == nil)
		break;
	case 8:
		TEST(message,
		    type == eventTypeString && [string isEqual: @"\n "])
		break;
	case 9:
		TEST(message,
		    type == eventTypeTagOpen && [name isEqual: @"foobar"] &&
		    prefix == nil &&
		    [namespace isEqual: @"urn:objfw:test:foobar"] &&
		    attrs.count == 1 &&
		    /* xmlns attr */
		    [[[attrs objectAtIndex: 0] name] isEqual: @"xmlns"] &&
		    [[attrs objectAtIndex: 0] namespace] == nil &&
		    [[[attrs objectAtIndex: 0] stringValue] isEqual:
		    @"urn:objfw:test:foobar"])
		break;
	case 10:
		TEST(message,
		    type == eventTypeString && [string isEqual: @"\n  "])
		break;
	case 11:
		TEST(message,
		    type == eventTypeTagOpen && [name isEqual: @"qux"] &&
		    prefix == nil &&
		    [namespace isEqual: @"urn:objfw:test:foobar"] &&
		    attrs.count == 1 &&
		    /* xmlns:foo attr */
		    [[[attrs objectAtIndex: 0] name] isEqual: @"foo"] &&
		    [[[attrs objectAtIndex: 0] namespace] isEqual:
		    @"http://www.w3.org/2000/xmlns/"] &&
		    [[[attrs objectAtIndex: 0] stringValue] isEqual:
		    @"urn:objfw:test:foo"])
		break;
	case 12:
		TEST(message,
		    type == eventTypeString && [string isEqual: @"\n   "])
		break;
	case 13:
		TEST(message,
		    type == eventTypeTagOpen && [name isEqual: @"bla"] &&
		    [prefix isEqual: @"foo"] &&
		    [namespace isEqual: @"urn:objfw:test:foo"] &&
		    attrs.count == 2 &&
		    /* foo:bla attr */
		    [[[attrs objectAtIndex: 0] name] isEqual: @"bla"] &&
		    [[[attrs objectAtIndex: 0] namespace] isEqual:
		    @"urn:objfw:test:foo"] &&
		    [[[attrs objectAtIndex: 0] stringValue] isEqual: @"bla"] &&
		    /* blafoo attr */
		    [[[attrs objectAtIndex: 1] name] isEqual: @"blafoo"] &&
		    [[attrs objectAtIndex: 1] namespace] == nil &&
		    [[[attrs objectAtIndex: 1] stringValue] isEqual: @"foo"])
		break;
	case 14:
		TEST(message,
		    type == eventTypeString && [string isEqual: @"\n    "])
		break;
	case 15:
		TEST(message,
		    type == eventTypeTagOpen && [name isEqual: @"blup"] &&
		    prefix == nil &&
		    [namespace isEqual: @"urn:objfw:test:foobar"] &&
		    attrs.count == 2 &&
		    /* foo:qux attr */
		    [[[attrs objectAtIndex: 0] name] isEqual: @"qux"] &&
		    [[[attrs objectAtIndex: 0] namespace] isEqual:
		    @"urn:objfw:test:foo"] &&
		    [[[attrs objectAtIndex: 0] stringValue] isEqual: @"asd"] &&
		    /* quxqux attr */
		    [[[attrs objectAtIndex: 1] name] isEqual: @"quxqux"] &&
		    [[attrs objectAtIndex: 1] namespace] == nil &&
		    [[[attrs objectAtIndex: 1] stringValue] isEqual: @"test"])
		break;
	case 16:
		TEST(message,
		    type == eventTypeTagClose && [name isEqual: @"blup"] &&
		    prefix == nil &&
		    [namespace isEqual: @"urn:objfw:test:foobar"])
		break;
	case 17:
		TEST(message,
		    type == eventTypeString && [string isEqual: @"\n    "])
		break;
	case 18:
		TEST(message,
		    type == eventTypeTagOpen && [name isEqual: @"bla"] &&
		    [prefix isEqual: @"bla"] &&
		    [namespace isEqual: @"urn:objfw:test:bla"] &&
		    attrs.count == 3 &&
		    /* xmlns:bla attr */
		    [[[attrs objectAtIndex: 0] name] isEqual: @"bla"] &&
		    [[[attrs objectAtIndex: 0] namespace] isEqual:
		    @"http://www.w3.org/2000/xmlns/"] &&
		    [[[attrs objectAtIndex: 0] stringValue] isEqual:
		    @"urn:objfw:test:bla"] &&
		    /* qux attr */
................................................................................
		    /* bla:foo attr */
		    [[[attrs objectAtIndex: 2] name] isEqual: @"foo"] &&
		    [[[attrs objectAtIndex: 2] namespace] isEqual:
		    @"urn:objfw:test:bla"] &&
		    [[[attrs objectAtIndex: 2] stringValue] isEqual: @"blafoo"])
		break;
	case 19:
		TEST(message,
		    type == eventTypeTagClose && [name isEqual: @"bla"] &&
		    [prefix isEqual: @"bla"] &&
		    [namespace isEqual: @"urn:objfw:test:bla"])
		break;
	case 20:
		TEST(message,
		    type == eventTypeString && [string isEqual: @"\n    "])
		break;
	case 21:
		TEST(message,
		    type == eventTypeTagOpen && [name isEqual: @"abc"] &&
		    prefix == nil &&
		    [namespace isEqual: @"urn:objfw:test:abc"] &&
		    attrs.count == 3 &&
		    /* xmlns attr */
		    [[[attrs objectAtIndex: 0] name] isEqual: @"xmlns"] &&
		    [[attrs objectAtIndex: 0] namespace] == nil &&
		    [[[attrs objectAtIndex: 0] stringValue] isEqual:
		    @"urn:objfw:test:abc"] &&
		    /* abc attr */
................................................................................
		    /* foo:abc attr */
		    [[[attrs objectAtIndex: 2] name] isEqual: @"abc"] &&
		    [[[attrs objectAtIndex: 2] namespace] isEqual:
		    @"urn:objfw:test:foo"] &&
		    [[[attrs objectAtIndex: 2] stringValue] isEqual: @"abc"])
		break;
	case 22:
		TEST(message,
		    type == eventTypeTagClose && [name isEqual: @"abc"] &&
		    prefix == nil && [namespace isEqual: @"urn:objfw:test:abc"])
		break;
	case 23:
		TEST(message,
		    type == eventTypeString && [string isEqual: @"\n   "])
		break;
	case 24:
		TEST(message,
		    type == eventTypeTagClose && [name isEqual: @"bla"] &&
		    [prefix isEqual: @"foo"] &&
		    [namespace isEqual: @"urn:objfw:test:foo"])
		break;
	case 25:
		TEST(message,
		    type == eventTypeString && [string isEqual: @"\n   "])
		break;
	case 26:
		TEST(message,
		    type == eventTypeComment && [string isEqual: @" commänt "])
		break;
	case 27:
		TEST(message,
		    type == eventTypeString && [string isEqual: @"\n  "])
		break;
	case 28:
		TEST(message,
		    type == eventTypeTagClose && [name isEqual: @"qux"] &&
		    prefix == nil &&
		    [namespace isEqual: @"urn:objfw:test:foobar"])
		break;
	case 29:
		TEST(message,
		    type == eventTypeString && [string isEqual: @"\n "])
		break;
	case 30:
		TEST(message,
		    type == eventTypeTagClose && [name isEqual: @"foobar"] &&
		    prefix == nil &&
		    [namespace isEqual: @"urn:objfw:test:foobar"])
		break;
	case 31:
		TEST(message,
		    type == eventTypeString && [string isEqual: @"\n"])
		break;
	case 32:
		TEST(message,
		    type == eventTypeTagClose && [name isEqual: @"root"] &&
		    prefix == nil && namespace == nil);
		break;
	}
}

-			  (void)parser: (OFXMLParser *)parser
  foundProcessingInstructionWithTarget: (OFString *)target
				  data: (OFString *)data
{
	[self	    parser: parser
	    didCreateEvent: eventTypeProcessingInstruction
		      name: target
		    prefix: nil
		 namespace: nil
		attributes: nil
		    string: data];
}

-    (void)parser: (OFXMLParser *)parser
  didStartElement: (OFString *)name
	   prefix: (OFString *)prefix
	namespace: (OFString *)namespace
       attributes: (OFArray *)attrs
{
	[self	    parser: parser
	    didCreateEvent: eventTypeTagOpen
		      name: name
		    prefix: prefix
		 namespace: namespace
		attributes: attrs
		    string: nil];
}

-  (void)parser: (OFXMLParser *)parser
  didEndElement: (OFString *)name
	 prefix: (OFString *)prefix
      namespace: (OFString *)namespace
{
	[self	    parser: parser
	    didCreateEvent: eventTypeTagClose
		      name: name
		    prefix: prefix
		 namespace: namespace
		attributes: nil
		    string: nil];
}

- (void)parser: (OFXMLParser *)parser foundCharacters: (OFString *)string
{
	[self	    parser: parser
	    didCreateEvent: eventTypeString
		      name: nil
		    prefix: nil
		 namespace: nil
		attributes: nil
		    string: string];
}

- (void)parser: (OFXMLParser *)parser foundCDATA: (OFString *)CDATA
{
	[self	    parser: parser
	    didCreateEvent: eventTypeCDATA
		      name: nil
		    prefix: nil
		 namespace: nil
		attributes: nil
		    string: CDATA];
}

- (void)parser: (OFXMLParser *)parser foundComment: (OFString *)comment
{
	[self	    parser: parser
	    didCreateEvent: eventTypeComment
		      name: nil
		    prefix: nil
		 namespace: nil
		attributes: nil
		    string: comment];
}

................................................................................

	return nil;
}

- (void)XMLParserTests
{
	void *pool = objc_autoreleasePoolPush();
	const char *string = "\xEF\xBB\xBF<?xml version='1.0'?><?p?i?>"
	    "<!DOCTYPE foo><root>\r\r"
	    " <![CDATA[f<]]]oo]]]><bar/>\n"
	    " <foobar xmlns='urn:objfw:test:foobar'>\r\n"
	    "  <qux xmlns:foo='urn:objfw:test:foo'>\n"
	    "   <foo:bla foo:bla = '&#x62;&#x6c;&#x61;' blafoo='foo'>\n"
	    "    <blup foo:qux='asd' quxqux='test'/>\n"
	    "    <bla:bla\r\rxmlns:bla\r=\t\"urn:objfw:test:bla\" qux='qux'\r\n"
................................................................................
	    "    <abc xmlns='urn:objfw:test:abc' abc='abc' foo:abc='abc'/>\n"
	    "   </foo:bla>\n"
	    "   <!-- commänt -->\n"
	    "  </qux>\n"
	    " </foobar>\n"
	    "</root>";
	OFXMLParser *parser;
	size_t j, length;

	TEST(@"+[parser]", (parser = [OFXMLParser parser]))

	TEST(@"-[setDelegate:]", (parser.delegate = self))

	/* Simulate a stream where we only get chunks */
	length = strlen(string);

	for (j = 0; j < length; j+= 2) {
		if (parser.hasFinishedParsing)
			abort();

		if (j + 2 > length)
			[parser parseBuffer: string + j length: 1];
		else
			[parser parseBuffer: string + j length: 2];
	}

	TEST(@"Checking if everything was parsed",
	    i == 32 && parser.lineNumber == 18)

	TEST(@"-[hasFinishedParsing]", parser.hasFinishedParsing)

Modified tests/RuntimeARCTests.m from [17d2d82f60] to [b48c97e0ac].

13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
 * file.
 */

#include "config.h"

#import "TestsAppDelegate.h"

static OFString *module = @"Runtime (ARC)";

@interface RuntimeARCTest: OFObject
@end

@implementation RuntimeARCTest
- (instancetype)init
{







|







13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
 * file.
 */

#include "config.h"

#import "TestsAppDelegate.h"

static OFString *const module = @"Runtime (ARC)";

@interface RuntimeARCTest: OFObject
@end

@implementation RuntimeARCTest
- (instancetype)init
{

Modified tests/RuntimeTests.m from [60799e33cc] to [20a13fa2e0].

13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
..
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88

89
90
91
92
93
94
95
96
97
98
99
100

101
102
103
104
105
106
107
108
109
110
111
 * file.
 */

#include "config.h"

#import "TestsAppDelegate.h"

static OFString *module = @"Runtime";

@interface OFObject (SuperTest)
- (id)superTest;
@end

@interface RuntimeTest: OFObject
{
................................................................................
}
@end

@implementation TestsAppDelegate (RuntimeTests)
- (void)runtimeTests
{
	void *pool = objc_autoreleasePoolPush();
	RuntimeTest *rt = [[[RuntimeTest alloc] init] autorelease];
	OFString *t, *foo;
#ifdef OF_OBJFW_RUNTIME
	int cid1, cid2;
	uintmax_t value;
	id object;
#endif

	EXPECT_EXCEPTION(@"Calling a non-existent method via super",
	    OFNotImplementedException, [rt superTest])

	TEST(@"Calling a method via a super with self == nil",
	    [rt nilSuperTest] == nil)

	t = [OFMutableString stringWithString: @"foo"];
	foo = @"foo";

	[rt setFoo: t];
	TEST(@"copy, nonatomic properties", [rt.foo isEqual: foo] &&
	    rt.foo != foo && rt.foo.retainCount == 1)

	rt.bar = t;
	TEST(@"retain, atomic properties", rt.bar == t && t.retainCount == 3)


#ifdef OF_OBJFW_RUNTIME
	if (sizeof(uintptr_t) == 8)
		value = 0xDEADBEEFDEADBEF;
	else if (sizeof(uintptr_t) == 4)
		value = 0xDEADBEF;
	else
		abort();

	TEST(@"Tagged pointers",
	    (cid1 = objc_registerTaggedPointerClass([OFString class])) != -1 &&
	    (cid2 = objc_registerTaggedPointerClass([OFNumber class])) != -1 &&

	    (object = objc_createTaggedPointer(cid2, (uintptr_t)value)) &&
	    object_getClass(object) == [OFNumber class] &&
	    [object class] == [OFNumber class] &&
	    object_getTaggedPointerValue(object) == value &&
	    objc_createTaggedPointer(cid2, UINTPTR_MAX >> 4) != nil &&
	    objc_createTaggedPointer(cid2, (UINTPTR_MAX >> 4) + 1) == nil)
#endif

	objc_autoreleasePoolPop(pool);
}
@end







|







 







|
|

|





|


|

|


|
|
|

|
|
>










|
|
>
|



|
|





13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
..
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
 * file.
 */

#include "config.h"

#import "TestsAppDelegate.h"

static OFString *const module = @"Runtime";

@interface OFObject (SuperTest)
- (id)superTest;
@end

@interface RuntimeTest: OFObject
{
................................................................................
}
@end

@implementation TestsAppDelegate (RuntimeTests)
- (void)runtimeTests
{
	void *pool = objc_autoreleasePoolPush();
	RuntimeTest *test = [[[RuntimeTest alloc] init] autorelease];
	OFString *string, *foo;
#ifdef OF_OBJFW_RUNTIME
	int classID;
	uintmax_t value;
	id object;
#endif

	EXPECT_EXCEPTION(@"Calling a non-existent method via super",
	    OFNotImplementedException, [test superTest])

	TEST(@"Calling a method via a super with self == nil",
	    [test nilSuperTest] == nil)

	string = [OFMutableString stringWithString: @"foo"];
	foo = @"foo";

	test.foo = string;
	TEST(@"copy, nonatomic properties", [test.foo isEqual: foo] &&
	    test.foo != foo && test.foo.retainCount == 1)

	test.bar = string;
	TEST(@"retain, atomic properties",
	    test.bar == string && string.retainCount == 3)

#ifdef OF_OBJFW_RUNTIME
	if (sizeof(uintptr_t) == 8)
		value = 0xDEADBEEFDEADBEF;
	else if (sizeof(uintptr_t) == 4)
		value = 0xDEADBEF;
	else
		abort();

	TEST(@"Tagged pointers",
	    objc_registerTaggedPointerClass([OFString class]) != -1 &&
	    (classID = objc_registerTaggedPointerClass([OFNumber class])) !=
	    -1 &&
	    (object = objc_createTaggedPointer(classID, (uintptr_t)value)) &&
	    object_getClass(object) == [OFNumber class] &&
	    [object class] == [OFNumber class] &&
	    object_getTaggedPointerValue(object) == value &&
	    objc_createTaggedPointer(classID, UINTPTR_MAX >> 4) != nil &&
	    objc_createTaggedPointer(classID, (UINTPTR_MAX >> 4) + 1) == nil)
#endif

	objc_autoreleasePoolPop(pool);
}
@end

Modified tests/TestsAppDelegate.h from [2fa9306569] to [36680e2682].

142
143
144
145
146
147
148




149
150
151
152
153
154
155
...
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
...
210
211
212
213
214
215
216




217
218
219
220
221
222
223
...
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
@interface TestsAppDelegate (OFNumberTests)
- (void)numberTests;
@end

@interface TestsAppDelegate (OFObjectTests)
- (void)objectTests;
@end





@interface TestsAppDelegate (OFPropertyListTests)
- (void)propertyListTests;
@end

@interface TestsAppDelegate (OFPluginTests)
- (void)pluginTests;
................................................................................
- (void)runtimeARCTests;
@end

@interface TestsAppDelegate (OFRIPEMD160HashTests)
- (void)RIPEMD160HashTests;
@end

@interface TestsAppDelegate (ScryptTests)
- (void)scryptTests;
@end

@interface TestsAppDelegate (OFSHA1HashTests)
- (void)SHA1HashTests;
@end

................................................................................
@interface TestsAppDelegate (OFSystemInfoTests)
- (void)systemInfoTests;
@end

@interface TestsAppDelegate (OFHMACTests)
- (void)HMACTests;
@end





@interface TestsAppDelegate (OFStreamTests)
- (void)streamTests;
@end

@interface TestsAppDelegate (OFStringTests)
- (void)stringTests;
................................................................................
- (void)XMLNodeTests;
@end

@interface TestsAppDelegate (OFXMLParserTests)
    <OFXMLParserDelegate, OFXMLElementBuilderDelegate>
- (void)XMLParserTests;
@end

@interface TestsAppDelegate (PBKDF2Tests)
- (void)PBKDF2Tests;
@end

@interface TestsAppDelegate (SocketTests)
- (void)socketTests;
@end







>
>
>
>







 







|







 







>
>
>
>







 







<
<
<
<
<
<
<
<
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
...
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
...
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
...
263
264
265
266
267
268
269








@interface TestsAppDelegate (OFNumberTests)
- (void)numberTests;
@end

@interface TestsAppDelegate (OFObjectTests)
- (void)objectTests;
@end

@interface TestsAppDelegate (OFPBKDF2Tests)
- (void)PBKDF2Tests;
@end

@interface TestsAppDelegate (OFPropertyListTests)
- (void)propertyListTests;
@end

@interface TestsAppDelegate (OFPluginTests)
- (void)pluginTests;
................................................................................
- (void)runtimeARCTests;
@end

@interface TestsAppDelegate (OFRIPEMD160HashTests)
- (void)RIPEMD160HashTests;
@end

@interface TestsAppDelegate (OFScryptTests)
- (void)scryptTests;
@end

@interface TestsAppDelegate (OFSHA1HashTests)
- (void)SHA1HashTests;
@end

................................................................................
@interface TestsAppDelegate (OFSystemInfoTests)
- (void)systemInfoTests;
@end

@interface TestsAppDelegate (OFHMACTests)
- (void)HMACTests;
@end

@interface TestsAppDelegate (OFSocketTests)
- (void)socketTests;
@end

@interface TestsAppDelegate (OFStreamTests)
- (void)streamTests;
@end

@interface TestsAppDelegate (OFStringTests)
- (void)stringTests;
................................................................................
- (void)XMLNodeTests;
@end

@interface TestsAppDelegate (OFXMLParserTests)
    <OFXMLParserDelegate, OFXMLElementBuilderDelegate>
- (void)XMLParserTests;
@end








Modified tests/TestsAppDelegate.m from [6f59a3820f] to [1130ab2e6c].

51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
...
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
...
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
# undef id
#endif

extern unsigned long OFHashSeed;

#ifdef OF_PSP
static int
exit_cb(int arg1, int arg2, void *arg)
{
	sceKernelExitGame();

	return 0;
}

static int
callback_thread(SceSize args, void *argp)
{
	sceKernelRegisterExitCallback(
	    sceKernelCreateCallback("Exit Callback", exit_cb, NULL));
	sceKernelSleepThreadCB();

	return 0;
}
#endif

int
................................................................................

#ifdef OF_PSP
	pspDebugScreenInit();

	sceCtrlSetSamplingCycle(0);
	sceCtrlSetSamplingMode(PSP_CTRL_MODE_DIGITAL);

	if ((tid = sceKernelCreateThread("update_thread", callback_thread,
	    0x11, 0xFA0, 0, 0)) >= 0)
		sceKernelStartThread(tid, 0, 0);
#endif

#ifdef OF_NINTENDO_DS
	consoleDemoInit();
#endif
................................................................................
	}
#else
	return OFApplicationMain(&argc, &argv, [[TestsAppDelegate alloc] init]);
#endif
}

@implementation TestsAppDelegate
- (void)outputTesting: (OFString *)test
	     inModule: (OFString *)module
{
	if (OFStdOut.hasTerminal) {
		[OFStdOut setForegroundColor: [OFColor yellow]];
		[OFStdOut writeFormat: @"[%@] %@: testing...", module, test];
	} else
		[OFStdOut writeFormat: @"[%@] %@: ", module, test];
}

- (void)outputSuccess: (OFString *)test
	     inModule: (OFString *)module
{
	if (OFStdOut.hasTerminal) {
		[OFStdOut setForegroundColor: [OFColor lime]];
		[OFStdOut eraseLine];
		[OFStdOut writeFormat: @"\r[%@] %@: ok\n", module, test];
	} else
		[OFStdOut writeLine: @"ok"];
}

- (void)outputFailure: (OFString *)test
	     inModule: (OFString *)module
{
	if (OFStdOut.hasTerminal) {
		[OFStdOut setForegroundColor: [OFColor red]];
		[OFStdOut eraseLine];
		[OFStdOut writeFormat: @"\r[%@] %@: failed\n", module, test];

#ifdef OF_WII







|







|


|







 







|







 







|
<








|
<









|
<







51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
...
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
...
196
197
198
199
200
201
202
203

204
205
206
207
208
209
210
211
212

213
214
215
216
217
218
219
220
221
222

223
224
225
226
227
228
229
# undef id
#endif

extern unsigned long OFHashSeed;

#ifdef OF_PSP
static int
exitCallback(int arg1, int arg2, void *arg)
{
	sceKernelExitGame();

	return 0;
}

static int
threadCallback(SceSize args, void *argp)
{
	sceKernelRegisterExitCallback(
	    sceKernelCreateCallback("Exit Callback", exitCallback, NULL));
	sceKernelSleepThreadCB();

	return 0;
}
#endif

int
................................................................................

#ifdef OF_PSP
	pspDebugScreenInit();

	sceCtrlSetSamplingCycle(0);
	sceCtrlSetSamplingMode(PSP_CTRL_MODE_DIGITAL);

	if ((tid = sceKernelCreateThread("update_thread", threadCallback,
	    0x11, 0xFA0, 0, 0)) >= 0)
		sceKernelStartThread(tid, 0, 0);
#endif

#ifdef OF_NINTENDO_DS
	consoleDemoInit();
#endif
................................................................................
	}
#else
	return OFApplicationMain(&argc, &argv, [[TestsAppDelegate alloc] init]);
#endif
}

@implementation TestsAppDelegate
- (void)outputTesting: (OFString *)test inModule: (OFString *)module

{
	if (OFStdOut.hasTerminal) {
		[OFStdOut setForegroundColor: [OFColor yellow]];
		[OFStdOut writeFormat: @"[%@] %@: testing...", module, test];
	} else
		[OFStdOut writeFormat: @"[%@] %@: ", module, test];
}

- (void)outputSuccess: (OFString *)test inModule: (OFString *)module

{
	if (OFStdOut.hasTerminal) {
		[OFStdOut setForegroundColor: [OFColor lime]];
		[OFStdOut eraseLine];
		[OFStdOut writeFormat: @"\r[%@] %@: ok\n", module, test];
	} else
		[OFStdOut writeLine: @"ok"];
}

- (void)outputFailure: (OFString *)test inModule: (OFString *)module

{
	if (OFStdOut.hasTerminal) {
		[OFStdOut setForegroundColor: [OFColor red]];
		[OFStdOut eraseLine];
		[OFStdOut writeFormat: @"\r[%@] %@: failed\n", module, test];

#ifdef OF_WII