/* * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in * the packaging of this file. * * Alternatively, it may be distributed under the terms of the GNU General * Public License, either version 2 or 3, which can be found in the file * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this * file. */ #include "config.h" #import "TestsAppDelegate.h" static OFString *const module = @"OFURI"; static OFString *URIString = @"ht%3atp://us%3Aer:p%40w@ho%3Ast:1234/" @"pa%3Fth?que%23ry=1&f%26oo=b%3dar#frag%23ment"; @implementation TestsAppDelegate (OFURITests) - (void)URITests { void *pool = objc_autoreleasePoolPush(); OFURI *URI1, *URI2, *URI3, *URI4, *URI5, *URI6, *URI7; OFMutableURI *mutableURI; TEST(@"+[URIWithString:]", R(URI1 = [OFURI URIWithString: URIString]) && R(URI2 = [OFURI URIWithString: @"http://foo:80"]) && R(URI3 = [OFURI URIWithString: @"http://bar/"]) && R(URI4 = [OFURI URIWithString: @"file:///etc/passwd"]) && R(URI5 = [OFURI URIWithString: @"http://foo/bar/qux/foo%2fbar"]) && R(URI6 = [OFURI URIWithString: @"https://[12:34::56:abcd]/"]) && R(URI7 = [OFURI URIWithString: @"https://[12:34::56:abcd]:234/"])) EXPECT_EXCEPTION(@"+[URIWithString:] fails with invalid characters #1", OFInvalidFormatException, [OFURI URIWithString: @"ht,tp://foo"]) EXPECT_EXCEPTION(@"+[URIWithString:] fails with invalid characters #2", OFInvalidFormatException, [OFURI URIWithString: @"http://f`oo"]) EXPECT_EXCEPTION(@"+[URIWithString:] fails with invalid characters #3", OFInvalidFormatException, [OFURI URIWithString: @"http://foo/`"]) EXPECT_EXCEPTION(@"+[URIWithString:] fails with invalid characters #4", OFInvalidFormatException, [OFURI URIWithString: @"http://foo/foo?`"]) EXPECT_EXCEPTION(@"+[URIWithString:] fails with invalid characters #5", OFInvalidFormatException, [OFURI URIWithString: @"http://foo/foo?foo#`"]) EXPECT_EXCEPTION(@"+[URIWithString:] fails with invalid characters #6", OFInvalidFormatException, [OFURI URIWithString: @"https://[g]/"]) EXPECT_EXCEPTION(@"+[URIWithString:] fails with invalid characters #7", OFInvalidFormatException, [OFURI URIWithString: @"https://[f]:/"]) EXPECT_EXCEPTION(@"+[URIWithString:] fails with invalid characters #8", OFInvalidFormatException, [OFURI URIWithString: @"https://[f]:f/"]) TEST(@"+[URIWithString:relativeToURI:]", [[[OFURI URIWithString: @"/foo" relativeToURI: URI1] string] isEqual: @"ht%3atp://us%3Aer:p%40w@ho%3Ast:1234/foo"] && [[[OFURI URIWithString: @"foo/bar?q" relativeToURI: [OFURI URIWithString: @"http://h/qux/quux"]] string] isEqual: @"http://h/qux/foo/bar?q"] && [[[OFURI URIWithString: @"foo/bar" relativeToURI: [OFURI URIWithString: @"http://h/qux/?x"]] string] isEqual: @"http://h/qux/foo/bar"] && [[[OFURI URIWithString: @"http://foo/?q" relativeToURI: URI1] string] isEqual: @"http://foo/?q"] && [[[OFURI URIWithString: @"foo" relativeToURI: [OFURI URIWithString: @"http://foo/bar"]] string] isEqual: @"http://foo/foo"] && [[[OFURI URIWithString: @"foo" relativeToURI: [OFURI URIWithString: @"http://foo"]] string] isEqual: @"http://foo/foo"]) EXPECT_EXCEPTION( @"+[URIWithString:relativeToURI:] fails with invalid characters #1", OFInvalidFormatException, [OFURI URIWithString: @"`" relativeToURI: URI1]) EXPECT_EXCEPTION( @"+[URIWithString:relativeToURI:] fails with invalid characters #2", OFInvalidFormatException, [OFURI URIWithString: @"/`" relativeToURI: URI1]) EXPECT_EXCEPTION( @"+[URIWithString:relativeToURI:] fails with invalid characters #3", OFInvalidFormatException, [OFURI URIWithString: @"?`" relativeToURI: URI1]) EXPECT_EXCEPTION( @"+[URIWithString:relativeToURI:] fails with invalid characters #4", OFInvalidFormatException, [OFURI URIWithString: @"#`" relativeToURI: URI1]) #ifdef OF_HAVE_FILES TEST(@"+[fileURIWithPath:]", [[[OFURI fileURIWithPath: @"testfile.txt"] fileSystemRepresentation] isEqual: [[OFFileManager defaultManager].currentDirectoryPath stringByAppendingPathComponent: @"testfile.txt"]]) # if defined(OF_WINDOWS) || defined(OF_MSDOS) OFURI *tmp; TEST(@"+[fileURIWithPath:] for c:\\", (tmp = [OFURI fileURIWithPath: @"c:\\"]) && [tmp.string isEqual: @"file:///c:/"] && [tmp.fileSystemRepresentation isEqual: @"c:\\"]) # endif # ifdef OF_WINDOWS TEST(@"+[fileURIWithPath:] with UNC", (tmp = [OFURI fileURIWithPath: @"\\\\foo\\bar"]) && [tmp.host isEqual: @"foo"] && [tmp.path isEqual: @"/bar"] && [tmp.string isEqual: @"file://foo/bar"] && [tmp.fileSystemRepresentation isEqual: @"\\\\foo\\bar"] && (tmp = [OFURI fileURIWithPath: @"\\\\test"]) && [tmp.host isEqual: @"test"] && [tmp.path isEqual: @"/"] && [tmp.string isEqual: @"file://test/"] && [tmp.fileSystemRepresentation isEqual: @"\\\\test"]) # endif #endif TEST(@"-[string]", [URI1.string isEqual: URIString] && [URI2.string isEqual: @"http://foo:80"] && [URI3.string isEqual: @"http://bar/"] && [URI4.string isEqual: @"file:///etc/passwd"]) TEST(@"-[scheme]", [URI1.scheme isEqual: @"ht:tp"] && [URI4.scheme isEqual: @"file"]) TEST(@"-[user]", [URI1.user isEqual: @"us:er"] && URI4.user == nil) TEST(@"-[password]", [URI1.password isEqual: @"p@w"] && URI4.password == nil) TEST(@"-[host]", [URI1.host isEqual: @"ho:st"] && [URI6.host isEqual: @"12:34::56:abcd"] && [URI7.host isEqual: @"12:34::56:abcd"]) TEST(@"-[port]", URI1.port.unsignedShortValue == 1234 && [URI4 port] == nil && URI7.port.unsignedShortValue == 234) TEST(@"-[path]", [URI1.path isEqual: @"/pa?th"] && [URI4.path isEqual: @"/etc/passwd"]) TEST(@"-[pathComponents]", [URI1.pathComponents isEqual: [OFArray arrayWithObjects: @"/", @"pa?th", nil]] && [URI4.pathComponents isEqual: [OFArray arrayWithObjects: @"/", @"etc", @"passwd", nil]] && [URI5.pathComponents isEqual: [OFArray arrayWithObjects: @"/", @"bar", @"qux", @"foo/bar", nil]]) TEST(@"-[lastPathComponent]", [[[OFURI URIWithString: @"http://host/foo//bar/baz"] lastPathComponent] isEqual: @"baz"] && [[[OFURI URIWithString: @"http://host/foo//bar/baz/"] lastPathComponent] isEqual: @"baz"] && [[[OFURI URIWithString: @"http://host/foo/"] lastPathComponent] isEqual: @"foo"] && [[[OFURI URIWithString: @"http://host/"] lastPathComponent] isEqual: @"/"] && [URI5.lastPathComponent isEqual: @"foo/bar"]) TEST(@"-[query]", [URI1.query isEqual: @"que#ry=1&f&oo=b=ar"] && URI4.query == nil) TEST(@"-[queryItems]", [URI1.queryItems isEqual: [OFArray arrayWithObjects: [OFPair pairWithFirstObject: @"que#ry" secondObject: @"1"], [OFPair pairWithFirstObject: @"f&oo" secondObject: @"b=ar"], nil]]); TEST(@"-[fragment]", [URI1.fragment isEqual: @"frag#ment"] && URI4.fragment == nil) TEST(@"-[copy]", R(URI4 = [[URI1 copy] autorelease])) TEST(@"-[isEqual:]", [URI1 isEqual: URI4] && ![URI2 isEqual: URI3] && [[OFURI URIWithString: @"HTTP://bar/"] isEqual: URI3]) TEST(@"-[hash:]", URI1.hash == URI4.hash && URI2.hash != URI3.hash) EXPECT_EXCEPTION(@"Detection of invalid format", OFInvalidFormatException, [OFURI URIWithString: @"http"]) mutableURI = [OFMutableURI URI]; TEST(@"-[setScheme:]", (mutableURI.scheme = @"ht:tp") && [mutableURI.percentEncodedScheme isEqual: @"ht%3Atp"]) TEST(@"-[setPercentEncodedScheme:]", (mutableURI.percentEncodedScheme = @"ht%3Atp") && [mutableURI.scheme isEqual: @"ht:tp"]) EXPECT_EXCEPTION( @"-[setPercentEncodedScheme:] with invalid characters fails", OFInvalidFormatException, mutableURI.percentEncodedScheme = @"~") TEST(@"-[setHost:]", (mutableURI.host = @"ho:st") && [mutableURI.percentEncodedHost isEqual: @"ho%3Ast"] && (mutableURI.host = @"12:34:ab") && [mutableURI.percentEncodedHost isEqual: @"[12:34:ab]"] && (mutableURI.host = @"12:34:aB") && [mutableURI.percentEncodedHost isEqual: @"[12:34:aB]"] && (mutableURI.host = @"12:34:g") && [mutableURI.percentEncodedHost isEqual: @"12%3A34%3Ag"]) TEST(@"-[setPercentEncodedHost:]", (mutableURI.percentEncodedHost = @"ho%3Ast") && [mutableURI.host isEqual: @"ho:st"] && (mutableURI.percentEncodedHost = @"[12:34]") && [mutableURI.host isEqual: @"12:34"] && (mutableURI.percentEncodedHost = @"[12::ab]") && [mutableURI.host isEqual: @"12::ab"]) EXPECT_EXCEPTION( @"-[setPercentEncodedHost:] with invalid characters fails #1", OFInvalidFormatException, mutableURI.percentEncodedHost = @"/") EXPECT_EXCEPTION( @"-[setPercentEncodedHost:] with invalid characters fails #2", OFInvalidFormatException, mutableURI.percentEncodedHost = @"[12:34") EXPECT_EXCEPTION( @"-[setPercentEncodedHost:] with invalid characters fails #3", OFInvalidFormatException, mutableURI.percentEncodedHost = @"[a::g]") TEST(@"-[setUser:]", (mutableURI.user = @"us:er") && [mutableURI.percentEncodedUser isEqual: @"us%3Aer"]) TEST(@"-[setPercentEncodedUser:]", (mutableURI.percentEncodedUser = @"us%3Aer") && [mutableURI.user isEqual: @"us:er"]) EXPECT_EXCEPTION( @"-[setPercentEncodedUser:] with invalid characters fails", OFInvalidFormatException, mutableURI.percentEncodedHost = @"/") TEST(@"-[setPassword:]", (mutableURI.password = @"pass:word") && [mutableURI.percentEncodedPassword isEqual: @"pass%3Aword"]) TEST(@"-[setPercentEncodedPassword:]", (mutableURI.percentEncodedPassword = @"pass%3Aword") && [mutableURI.password isEqual: @"pass:word"]) EXPECT_EXCEPTION( @"-[setPercentEncodedPassword:] with invalid characters fails", OFInvalidFormatException, mutableURI.percentEncodedPassword = @"/") TEST(@"-[setPath:]", (mutableURI.path = @"pa/th@?") && [mutableURI.percentEncodedPath isEqual: @"pa/th@%3F"]) TEST(@"-[setPercentEncodedPath:]", (mutableURI.percentEncodedPath = @"pa/th@%3F") && [mutableURI.path isEqual: @"pa/th@?"]) EXPECT_EXCEPTION( @"-[setPercentEncodedPath:] with invalid characters fails", OFInvalidFormatException, mutableURI.percentEncodedPath = @"?") TEST(@"-[setQuery:]", (mutableURI.query = @"que/ry?#") && [mutableURI.percentEncodedQuery isEqual: @"que/ry?%23"]) TEST(@"-[setPercentEncodedQuery:]", (mutableURI.percentEncodedQuery = @"que/ry?%23") && [mutableURI.query isEqual: @"que/ry?#"]) EXPECT_EXCEPTION( @"-[setPercentEncodedQuery:] with invalid characters fails", OFInvalidFormatException, mutableURI.percentEncodedQuery = @"`") TEST(@"-[setQueryItems:]", (mutableURI.queryItems = [OFArray arrayWithObjects: [OFPair pairWithFirstObject: @"foo&bar" secondObject: @"baz=qux"], [OFPair pairWithFirstObject: @"f=oobar" secondObject: @"b&azqux"], nil]) && [mutableURI.percentEncodedQuery isEqual: @"foo%26bar=baz%3Dqux&f%3Doobar=b%26azqux"]) TEST(@"-[setFragment:]", (mutableURI.fragment = @"frag/ment?#") && [mutableURI.percentEncodedFragment isEqual: @"frag/ment?%23"]) TEST(@"-[setPercentEncodedFragment:]", (mutableURI.percentEncodedFragment = @"frag/ment?%23") && [mutableURI.fragment isEqual: @"frag/ment?#"]) EXPECT_EXCEPTION( @"-[setPercentEncodedFragment:] with invalid characters fails", OFInvalidFormatException, mutableURI.percentEncodedFragment = @"`") TEST(@"-[URIByAppendingPathComponent:isDirectory:]", [[[OFURI URIWithString: @"file:///foo/bar"] URIByAppendingPathComponent: @"qux" isDirectory: false] isEqual: [OFURI URIWithString: @"file:///foo/bar/qux"]] && [[[OFURI URIWithString: @"file:///foo/bar/"] URIByAppendingPathComponent: @"qux" isDirectory: false] isEqual: [OFURI URIWithString: @"file:///foo/bar/qux"]] && [[[OFURI URIWithString: @"file:///foo/bar/"] URIByAppendingPathComponent: @"qu?x" isDirectory: false] isEqual: [OFURI URIWithString: @"file:///foo/bar/qu%3Fx"]] && [[[OFURI URIWithString: @"file:///foo/bar/"] URIByAppendingPathComponent: @"qu?x" isDirectory: true] isEqual: [OFURI URIWithString: @"file:///foo/bar/qu%3Fx/"]]) TEST(@"-[URIByStandardizingPath]", [[[OFURI URIWithString: @"http://foo/bar/.."] URIByStandardizingPath] isEqual: [OFURI URIWithString: @"http://foo/"]] && [[[OFURI URIWithString: @"http://foo/bar/%2E%2E/../qux/"] URIByStandardizingPath] isEqual: [OFURI URIWithString: @"http://foo/bar/qux/"]] && [[[OFURI URIWithString: @"http://foo/bar/./././qux/./"] URIByStandardizingPath] isEqual: [OFURI URIWithString: @"http://foo/bar/qux/"]] && [[[OFURI URIWithString: @"http://foo/bar/../../qux"] URIByStandardizingPath] isEqual: [OFURI URIWithString: @"http://foo/../qux"]]) objc_autoreleasePoolPop(pool); } @end