Index: tests/Makefile ================================================================== --- tests/Makefile +++ tests/Makefile @@ -1,18 +1,16 @@ include ../extra.mk -SUBDIRS = OFObject \ - OFAutoreleasePool \ +SUBDIRS = OFAutoreleasePool \ OFDataArray \ OFArray \ OFDictionary \ OFHashes \ ${OFPLUGIN} \ - OFString \ OFTCPSocket \ OFThread \ OFList \ OFXMLElement \ OFXMLParser \ ${OBJC_SYNC} include ../buildsys.mk DELETED tests/OFString/Makefile Index: tests/OFString/Makefile ================================================================== --- tests/OFString/Makefile +++ tests/OFString/Makefile @@ -1,25 +0,0 @@ -PROG_NOINST = ofstring${PROG_SUFFIX} -SRCS = OFString.m - -include ../../buildsys.mk -include ../../extra.mk - -CPPFLAGS += -I../../src -I../.. -LIBS := -L../../src -lobjfw ${LIBS} - -.PHONY: run - -all: run -run: ${PROG_NOINST} - rm -f libobjfw.so.0 libobjfw.so.0.1 libobjfw.dll libobjfw.dylib - ln -s ../../src/libobjfw.so libobjfw.so.0 - ln -s ../../src/libobjfw.so libobjfw.so.0.1 - if test -f ../../src/libobjfw.dll; then \ - ln ../../src/libobjfw.dll libobjfw.dll; \ - fi - ln -s ../../src/libobjfw.dylib libobjfw.dylib - LD_LIBRARY_PATH=.$${LD_LIBRARY_PATH+:}$$LD_LIBRARY_PATH \ - DYLD_LIBRARY_PATH=.$${DYLD_LIBRARY_PATH+:}$$DYLD_LIBRARY_PATH \ - ${TEST_LAUNCHER} ./${PROG_NOINST}; EXIT=$$?; \ - rm -f libobjfw.so.0 libobjfw.so.0.1 libobjfw.dll libobjfw.dylib; \ - exit $$EXIT DELETED tests/OFString/OFString.m Index: tests/OFString/OFString.m ================================================================== --- tests/OFString/OFString.m +++ tests/OFString/OFString.m @@ -1,260 +0,0 @@ -/* - * Copyright (c) 2008 - 2009 - * Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of libobjfw. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE included in - * the packaging of this file. - */ - -#include "config.h" - -#include - -#import "OFString.h" -#import "OFArray.h" -#import "OFAutoreleasePool.h" -#import "OFExceptions.h" - -#ifndef _WIN32 -#define ZD "%zd" -#else -#define ZD "%u" -#endif - -#define NUM_TESTS 73 -#define SUCCESS \ - printf("\r\033[1;%dmTests successful: " ZD "/%d\033[0m", \ - (i == NUM_TESTS - 1 ? 32 : 33), i + 1, NUM_TESTS); \ - fflush(stdout); -#define FAIL \ - printf("\r\033[K\033[1;31mTest " ZD "/%d failed!\033[m\n", \ - i + 1, NUM_TESTS); \ - return 1; -#define CHECK(cond) \ - if (cond) { \ - SUCCESS \ - } else { \ - FAIL \ - } \ - i++; -#define CHECK_EXCEPT(code, exception) \ - @try { \ - code; \ - FAIL \ - } @catch (exception *e) { \ - SUCCESS \ - } \ - i++; - -@interface EntityHandler: OFObject -@end - -@implementation EntityHandler -- (OFString*)foundUnknownEntityNamed: (OFString*)entity -{ - if ([entity isEqual: @"foo"]) - return @"bar"; - - return nil; -} -@end - -int -main() -{ - size_t i = 0; - size_t j = 0; - - OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init]; - OFString *s1 = [OFMutableString stringWithCString: "test"]; - OFString *s2 = [OFMutableString stringWithCString: ""]; - OFString *s3; - OFString *s4 = [OFMutableString string]; - OFArray *a; - EntityHandler *h; - - s3 = [s1 copy]; - - CHECK([s1 isEqual: s3]) - CHECK(![s1 isEqual: [[OFObject alloc] init]]) - CHECK([s1 hash] == [s3 hash]) - - [s2 appendCString: "12"]; - [s2 appendString: @"3"]; - [s4 setToCString: [s2 cString]]; - - CHECK(![s2 compare: s4]) - CHECK([[s1 appendString: s2] isEqual: @"test123"]) - CHECK([s1 cStringLength] == 7) - CHECK([s1 hash] == 0xC44F49A4) - CHECK([[s1 reverse] isEqual: @"321tset"]) - CHECK([[s1 upper] isEqual: @"321TSET"]) - CHECK([[s1 lower] isEqual: @"321tset"]) - - /* Also clears all the memory of the returned C strings */ - [pool release]; - - s1 = [OFMutableString stringWithCString: "foobar" - length: 3]; - CHECK([s1 isEqual: @"foo"]) - - [s1 appendCString: "foobarqux" + 3 - withLength: 3]; - CHECK([s1 isEqual: @"foobar"]) - - /* UTF-8 tests */ - CHECK_EXCEPT(s1 = [OFString stringWithCString: "\xE0\x80"], - OFInvalidEncodingException) - CHECK_EXCEPT(s1 = [OFString stringWithCString: "\xF0\x80\x80\xC0"], - OFInvalidEncodingException) - - s1 = [OFMutableString stringWithCString: "äöü€𝄞"]; - CHECK([[s1 reverse] isEqual: @"𝄞€üöä"]) - [s1 dealloc]; - - /* Encoding tests */ - CHECK([[OFString stringWithCString: "\xE4\xF6\xFC" - encoding: OF_STRING_ENCODING_ISO_8859_1] - isEqual: @"äöü"]) - - CHECK([[OFString stringWithCString: "\xA4\xA6\xA8\xB4\xB8\xBC\xBD\xBE" - encoding: OF_STRING_ENCODING_ISO_8859_15] - isEqual: @"€ŠšŽžŒœŸ"]) - CHECK([[OFString stringWithCString: "\x80\x82\x83\x84\x85\x86\x87\x88" - "\x89\x8A\x8B\x8C\x8E\x91\x92\x93" - "\x94\x95\x96\x97\x98\x99\x9A\x9B" - "\x9C\x9E\x9F" - encoding: OF_STRING_ENCODING_WINDOWS_1252] - isEqual: @"€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ"]) - - /* Format tests */ - s1 = [OFMutableString stringWithFormat: @"%s: %d", "test", 123]; - CHECK([s1 isEqual: @"test: 123"]) - - [s1 appendWithFormat: @"%02X", 15]; - CHECK([s1 isEqual: @"test: 1230F"]) - - /* Find index tests */ - CHECK([@"foo" indexOfFirstOccurrenceOfString: @"oo"] == 1) - CHECK([@"foo" indexOfLastOccurrenceOfString: @"oo"] == 1) - CHECK([@"foo" indexOfFirstOccurrenceOfString: @"o"] == 1) - CHECK([@"foo" indexOfLastOccurrenceOfString: @"o"] == 2) - CHECK([@"foo" indexOfFirstOccurrenceOfString: @"f"] == 0) - CHECK([@"foo" indexOfLastOccurrenceOfString: @"f"] == 0) - CHECK([@"foo" indexOfFirstOccurrenceOfString: @"x"] == SIZE_MAX) - CHECK([@"foo" indexOfLastOccurrenceOfString: @"x"] == SIZE_MAX) - - /* Substring tests */ - CHECK([[@"foo" substringFromIndex: 1 - toIndex: 2] isEqual: @"o"]); - CHECK([[@"foo" substringFromIndex: 3 - toIndex: 3] isEqual: @""]); - CHECK_EXCEPT([@"foo" substringFromIndex: 2 - toIndex: 4], OFOutOfRangeException) - CHECK_EXCEPT([@"foo" substringFromIndex: 4 - toIndex: 4], OFOutOfRangeException) - CHECK_EXCEPT([@"foo" substringFromIndex: 2 - toIndex: 0], OFInvalidArgumentException) - - /* Misc tests */ - CHECK([[@"foo" stringByAppendingString: @"bar"] isEqual: @"foobar"]) - CHECK([@"foobar" hasPrefix: @"foo"]) - CHECK([@"foobar" hasSuffix: @"bar"]) - CHECK(![@"foobar" hasPrefix: @"foobar0"]) - CHECK(![@"foobar" hasSuffix: @"foobar0"]) - - /* Split tests */ - a = [@"fooXXbarXXXXbazXXXX" splitWithDelimiter: @"XX"]; - CHECK([[a objectAtIndex: j++] isEqual: @"foo"]) - CHECK([[a objectAtIndex: j++] isEqual: @"bar"]) - CHECK([[a objectAtIndex: j++] isEqual: @""]) - CHECK([[a objectAtIndex: j++] isEqual: @"baz"]) - CHECK([[a objectAtIndex: j++] isEqual: @""]) - CHECK([[a objectAtIndex: j++] isEqual: @""]) - - /* Hash tests */ - CHECK([[@"asdfoobar" md5Hash] - isEqual: @"184dce2ec49b5422c7cfd8728864db4c"]); - CHECK([[@"asdfoobar" sha1Hash] - isEqual: @"f5f81ac0a8b5cbfdc4585ec1ad32e7b3a12b9b49"]); - - /* URL encoding tests */ - CHECK([[@"foo\"ba'_~$" stringByURLEncoding] - isEqual: @"foo%22ba%27_~%24"]) - CHECK([[@"foo%20bar%22+%24" stringByURLDecoding] - isEqual: @"foo bar\" $"]) - CHECK_EXCEPT([@"foo%bar" stringByURLDecoding], - OFInvalidEncodingException) - CHECK_EXCEPT([@"foo%FFbar" stringByURLDecoding], - OFInvalidEncodingException) - - /* Remove tests */ - s1 = [@"fooobar" mutableCopy]; - [s1 removeCharactersFromIndex: 1 - toIndex: 4]; - CHECK([s1 isEqual: @"fbar"]) - [s1 removeCharactersFromIndex: 0 - toIndex: 4]; - CHECK([s1 isEqual: @""]) - - /* Replace tests */ - s1 = [@"asd fo asd fofo asd" mutableCopy]; - [s1 replaceOccurrencesOfString: @"fo" - withString: @"foo"]; - CHECK([s1 isEqual: @"asd foo asd foofoo asd"]) - s1 = [@"XX" mutableCopy]; - [s1 replaceOccurrencesOfString: @"X" - withString: @"XX"]; - CHECK([s1 isEqual: @"XXXX"]) - - /* Whitespace removing tests */ - s1 = [@" \r \t\n\t \tasd \t \t\t\r\n" mutableCopy]; - s2 = [s1 mutableCopy]; - s3 = [s1 mutableCopy]; - CHECK([[s1 removeLeadingWhitespaces] isEqual: @"asd \t \t\t\r\n"]) - CHECK([[s2 removeTrailingWhitespaces] isEqual: @" \r \t\n\t \tasd"]) - CHECK([[s3 removeLeadingAndTrailingWhitespaces] isEqual: @"asd"]) - - s1 = [@" \t\t \t\t \t \t" mutableCopy]; - s2 = [s1 mutableCopy]; - s3 = [s1 mutableCopy]; - CHECK([[s1 removeLeadingWhitespaces] isEqual: @""]) - CHECK([[s2 removeTrailingWhitespaces] isEqual: @""]) - CHECK([[s3 removeLeadingAndTrailingWhitespaces] isEqual: @""]) - - /* XML escaping tests */ - s1 = [@" &world'\"!&" stringByXMLEscaping]; - CHECK([s1 isEqual: @"<hello> &world'"!&"]) - - /* XML unescaping tests */ - CHECK([[s1 stringByXMLUnescaping] isEqual: @" &world'\"!&"]); - CHECK_EXCEPT([@"&foo;" stringByXMLUnescaping], - OFInvalidEncodingException) - - h = [[EntityHandler alloc] init]; - s1 = [@"x&foo;y" stringByXMLUnescapingWithHandler: h]; - CHECK([s1 isEqual: @"xbary"]); - - CHECK_EXCEPT([@"x&" stringByXMLUnescaping], - OFInvalidEncodingException) - - CHECK([[@"y" stringByXMLUnescaping] isEqual: @"y"]); - CHECK([[@"ä" stringByXMLUnescaping] isEqual: @"ä"]); - CHECK([[@"€" stringByXMLUnescaping] isEqual: @"€"]); - CHECK([[@"𝄞" stringByXMLUnescaping] isEqual: @"𝄞"]); - - CHECK_EXCEPT([@"&#;" stringByXMLUnescaping], OFInvalidEncodingException) - CHECK_EXCEPT([@"&#x;" stringByXMLUnescaping], - OFInvalidEncodingException) - CHECK_EXCEPT([@"&#g;" stringByXMLUnescaping], - OFInvalidEncodingException) - CHECK_EXCEPT([@"&#xg;" stringByXMLUnescaping], - OFInvalidEncodingException) - - puts(""); - - return 0; -} Index: tests_new/Makefile ================================================================== --- tests_new/Makefile +++ tests_new/Makefile @@ -1,8 +1,9 @@ PROG_NOINST = tests${PROG_SUFFIX} SRCS = main.m \ - object.m + object.m \ + string.m include ../buildsys.mk include ../extra.mk CPPFLAGS += -I../src -I.. -DSTDOUT Index: tests_new/main.h ================================================================== --- tests_new/main.h +++ tests_new/main.h @@ -16,23 +16,29 @@ extern void failed(OFString*, OFString*); #define TEST(test, cond) \ { \ testing(module, test); \ + \ if (cond) \ success(module, test); \ else \ failed(module, test); \ } #define EXPECT_EXCEPTION(test, exception, code) \ { \ BOOL caught = NO; \ \ + testing(module, test); \ + \ @try { \ code; \ } @catch (exception *e) { \ caught = YES; \ [e dealloc]; \ } \ \ - TEST(test, caught) \ + if (caught) \ + success(module, test); \ + else \ + failed(module, test); \ } Index: tests_new/main.m ================================================================== --- tests_new/main.m +++ tests_new/main.m @@ -18,10 +18,13 @@ #import #import extern void object_tests(); +extern void string_tests(); + +static int fails = 0; static void output(OFString *str, int color) { #ifdef STDOUT @@ -36,12 +39,12 @@ fputs("\r\033[K\033[1;31m", stdout); break; } fputs([str cString], stdout); - fputs("\033[m", stdout); + fflush(stdout); #else #error No output method! #endif } @@ -73,16 +76,17 @@ OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init]; OFString *str = [OFString stringWithFormat: @"[%s] %s: failed\n", [module cString], [test cString]]; output(str, 2); + fails++; [pool release]; - exit(1); } int main() { object_tests(); + string_tests(); - return 0; + return fails; } ADDED tests_new/string.m Index: tests_new/string.m ================================================================== --- tests_new/string.m +++ tests_new/string.m @@ -0,0 +1,253 @@ +/* + * Copyright (c) 2008 - 2009 + * Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of libobjfw. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE included in + * the packaging of this file. + */ + +#include "config.h" + +#import "OFString.h" +#import "OFArray.h" +#import "OFAutoreleasePool.h" +#import "OFExceptions.h" + +#import "main.h" + +static OFString *module = @"OFString"; +static OFString* whitespace[] = { + @" \r \t\n\t \tasd \t \t\t\r\n", + @" \t\t \t\t \t \t" +}; + +@interface EntityHandler: OFObject +@end + +@implementation EntityHandler +- (OFString*)foundUnknownEntityNamed: (OFString*)entity +{ + if ([entity isEqual: @"foo"]) + return @"bar"; + + return nil; +} +@end + +void +string_tests() +{ + OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init]; + OFString *s[3]; + OFArray *a; + int i; + EntityHandler *h; + + s[0] = [OFMutableString stringWithString: @"test"]; + s[1] = [OFMutableString 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]] == 0 && + [s[0] compare: @""] != 0) + + TEST(@"-[hash] is the same if -[isEqual:] is YES", + [s[0] hash] == [s[2] hash]) + + TEST(@"-[appendString:] and -[appendCString:]", + [s[1] appendCString: "12"] && [s[1] appendString: @"3"] && + [[s[0] appendString: s[1]] isEqual: @"test123"]) + + TEST(@"-[cStringLength]", [s[0] cStringLength] == 7) + TEST(@"-[hash]", [s[0] hash] == 0xC44F49A4) + TEST(@"-[reverse]", [[s[0] reverse] isEqual: @"321tset"]) + TEST(@"-[upper]", [[s[0] upper] isEqual: @"321TSET"]) + TEST(@"-[lower]", [[s[0] lower] isEqual: @"321tset"]) + + TEST(@"+[stringWithCString:length:]", + (s[0] = [OFMutableString stringWithCString: "foobar" + length: 3]) && + [s[0] isEqual: @"foo"]) + + TEST(@"-[appendCStringWithLength:]", + [[s[0] appendCString: "foobarqux" + 3 + withLength: 3] isEqual: @"foobar"]) + + EXPECT_EXCEPTION(@"Detection of invalid UTF-8 encoding #1", + OFInvalidEncodingException, + [OFString stringWithCString: "\xE0\x80"]) + EXPECT_EXCEPTION(@"Detection of invalid UTF-8 encoding #2", + OFInvalidEncodingException, + [OFString stringWithCString: "\xF0\x80\x80\xC0"]) + + TEST(@"-[reverse] on UTF-8 strings", + (s[0] = [[OFMutableString stringWithCString: "äöü€𝄞"] reverse]) && + [s[0] isEqual: @"𝄞€üöä"]) + + TEST(@"Conversion of ISO 8859-1 to UTF-8", + [[OFString stringWithCString: "\xE4\xF6\xFC" + encoding: OF_STRING_ENCODING_ISO_8859_1] + isEqual: @"äöü"]) + + TEST(@"Conversion of ISO 8859-15 to UTF-8", + [[OFString stringWithCString: "\xA4\xA6\xA8\xB4\xB8\xBC\xBD\xBE" + encoding: OF_STRING_ENCODING_ISO_8859_15] + isEqual: @"€ŠšŽžŒœŸ"]) + + TEST(@"Conversion of Windows 1252 to UTF-8", + [[OFString stringWithCString: "\x80\x82\x83\x84\x85\x86\x87\x88" + "\x89\x8A\x8B\x8C\x8E\x91\x92\x93" + "\x94\x95\x96\x97\x98\x99\x9A\x9B" + "\x9C\x9E\x9F" + encoding: OF_STRING_ENCODING_WINDOWS_1252] + isEqual: @"€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ"]) + + TEST(@"+[stringWithFormat:]", + [(s[0] = [OFMutableString stringWithFormat: @"%s: %d", "test", 123]) + isEqual: @"test: 123"]) + + TEST(@"-[appendWithFormat:]", + [([s[0] appendWithFormat: @"%02X", 15]) isEqual: @"test: 1230F"]) + + TEST(@"-[indexOfFirstOccurrenceOfString:]", + [@"foo" indexOfFirstOccurrenceOfString: @"oo"] == 1 && + [@"foo" indexOfFirstOccurrenceOfString: @"o"] == 1 && + [@"foo" indexOfFirstOccurrenceOfString: @"f"] == 0 && + [@"foo" indexOfFirstOccurrenceOfString: @"x"] == SIZE_MAX) + + TEST(@"-[indexOfLastOccurrenceOfString:]", + [@"foo" indexOfLastOccurrenceOfString: @"oo"] == 1 && + [@"foo" indexOfLastOccurrenceOfString: @"o"] == 2 && + [@"foo" indexOfLastOccurrenceOfString: @"f"] == 0 && + [@"foo" indexOfLastOccurrenceOfString: @"x"] == SIZE_MAX) + + TEST(@"-[substringFromIndexToIndex:]", + [[@"foo" substringFromIndex: 1 + toIndex: 2] isEqual: @"o"] && + [[@"foo" substringFromIndex: 3 + toIndex: 3] isEqual: @""]) + + EXPECT_EXCEPTION(@"Detect out of range in " + @"-[substringFromIndex:toIndex:] #1", OFOutOfRangeException, + [@"foo" substringFromIndex: 2 + toIndex: 4]) + EXPECT_EXCEPTION(@"Detect out of range in " + @"-[substringFromIndex:toIndex:] #2", OFOutOfRangeException, + [@"foo" substringFromIndex: 4 + toIndex: 4]) + + EXPECT_EXCEPTION(@"Detect start > end in " + @"-[substringFromIndex:toIndex:]", OFInvalidArgumentException, + [@"foo" substringFromIndex: 2 + toIndex: 0]) + + TEST(@"-[stringByAppendingString:]", + [[@"foo" stringByAppendingString: @"bar"] isEqual: @"foobar"]) + + TEST(@"-[hasPrefix:]", [@"foobar" hasPrefix: @"foo"] && + ![@"foobar" hasPrefix: @"foobar0"]) + + TEST(@"-[hasSuffix:]", [@"foobar" hasSuffix: @"bar"] && + ![@"foobar" hasSuffix: @"foobar0"]) + + i = 0; + TEST(@"-[splitWithDelimiter:]", + (a = [@"fooXXbarXXXXbazXXXX" splitWithDelimiter: @"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: @""]) + + TEST(@"-[md5Hash]", [[@"asdfoobar" md5Hash] + isEqual: @"184dce2ec49b5422c7cfd8728864db4c"]) + + TEST(@"-[sha1Hash]", [[@"asdfoobar" sha1Hash] + isEqual: @"f5f81ac0a8b5cbfdc4585ec1ad32e7b3a12b9b49"]) + + TEST(@"-[stringByURLEncoding]", + [[@"foo\"ba'_~$" stringByURLEncoding] isEqual: @"foo%22ba%27_~%24"]) + + TEST(@"-[stringByURLDecoding]", + [[@"foo%20bar%22+%24" stringByURLDecoding] isEqual: @"foo bar\" $"]) + + EXPECT_EXCEPTION(@"Detect invalid encoding in -[stringByURLDecoding] " + @"#1", OFInvalidEncodingException, [@"foo%bar" stringByURLDecoding]) + EXPECT_EXCEPTION(@"Detect invalid encoding in -[stringByURLDecoding] " + @"#2", OFInvalidEncodingException, + [@"foo%FFbar" stringByURLDecoding]) + + TEST(@"-[removeCharactersFromIndex:toIndex:]", + (s[0] = [OFMutableString stringWithString: @"fooobar"]) && + [s[0] removeCharactersFromIndex: 1 + toIndex: 4] && + [s[0] isEqual: @"fbar"] && + [s[0] removeCharactersFromIndex: 0 + toIndex: 4] && + [s[0] isEqual: @""]) + + TEST(@"-[replaceOccurrencesOfString:withString:]", + [[[OFMutableString stringWithString: @"asd fo asd fofo asd"] + replaceOccurrencesOfString: @"fo" + withString: @"foo"] + isEqual: @"asd foo asd foofoo asd"] && + [[[OFMutableString stringWithString: @"XX"] + replaceOccurrencesOfString: @"X" + withString: @"XX"] + isEqual: @"XXXX"]) + + TEST(@"-[removeLeadingWhitespaces]", + (s[0] = [OFMutableString stringWithString: whitespace[0]]) && + [[s[0] removeLeadingWhitespaces] isEqual: @"asd \t \t\t\r\n"] && + (s[0] = [OFMutableString stringWithString: whitespace[1]]) && + [[s[0] removeLeadingWhitespaces] isEqual: @""]) + + TEST(@"-[removeTrailingWhitespaces]", + (s[0] = [OFMutableString stringWithString: whitespace[0]]) && + [[s[0] removeTrailingWhitespaces] isEqual: @" \r \t\n\t \tasd"] && + (s[0] = [OFMutableString stringWithString: whitespace[1]]) && + [[s[0] removeTrailingWhitespaces] isEqual: @""]) + + TEST(@"-[removeLeadingAndTrailingWhitespaces]", + (s[0] = [OFMutableString stringWithString: whitespace[0]]) && + [[s[0] removeLeadingAndTrailingWhitespaces] isEqual: @"asd"] && + (s[0] = [OFMutableString stringWithString: whitespace[1]]) && + [[s[0] removeLeadingAndTrailingWhitespaces] isEqual: @""]) + + TEST(@"-[stringByXMLEscaping]", + (s[0] = [@" &world'\"!&" stringByXMLEscaping]) && + [s[0] isEqual: @"<hello> &world'"!&"]) + + TEST(@"-[stringByXMLUnescaping]", + [[s[0] stringByXMLUnescaping] isEqual: @" &world'\"!&"] && + [[@"y" stringByXMLUnescaping] isEqual: @"y"] && + [[@"ä" stringByXMLUnescaping] isEqual: @"ä"] && + [[@"€" stringByXMLUnescaping] isEqual: @"€"] && + [[@"𝄞" stringByXMLUnescaping] isEqual: @"𝄞"]) + + EXPECT_EXCEPTION(@"Detect invalid entities in -[stringByXMLUnescaping] " + @"#1", OFInvalidEncodingException, [@"&foo;" stringByXMLUnescaping]) + EXPECT_EXCEPTION(@"Detect invalid entities in -[stringByXMLUnescaping] " + @"#2", OFInvalidEncodingException, [@"x&" stringByXMLUnescaping]) + EXPECT_EXCEPTION(@"Detect invalid entities in -[stringByXMLUnescaping] " + @"#3", OFInvalidEncodingException, [@"&#;" stringByXMLUnescaping]) + EXPECT_EXCEPTION(@"Detect invalid entities in -[stringByXMLUnescaping] " + @"#4", OFInvalidEncodingException, [@"&#x;" stringByXMLUnescaping]) + EXPECT_EXCEPTION(@"Detect invalid entities in -[stringByXMLUnescaping] " + @"#5", OFInvalidEncodingException, [@"&#g;" stringByXMLUnescaping]) + EXPECT_EXCEPTION(@"Detect invalid entities in -[stringByXMLUnescaping] " + @"#6", OFInvalidEncodingException, [@"&#xg;" stringByXMLUnescaping]) + + TEST(@"-[stringByXMLUnescapingWithHandler:]", + (h = [[[EntityHandler alloc] init] autorelease]) && + (s[0] = [@"x&foo;y" stringByXMLUnescapingWithHandler: h]) && + [s[0] isEqual: @"xbary"]) + + [pool release]; +}