@@ -9,96 +9,192 @@ import XCTest
99
1010class SwifterTestsHttpParser : XCTestCase {
1111
12- class TestSocket : Socket {
13- var content = [ UInt8] ( )
14- var offset = 0
15-
16- init ( _ content: String ) {
17- super. init ( socketFileDescriptor: - 1 )
18- self . content. append ( contentsOf: [ UInt8] ( content. utf8) )
19- }
20-
21- override func read( ) throws -> UInt8 {
22- if offset < content. count {
23- let value = self . content [ offset]
24- offset = offset + 1
25- return value
26- }
27- throw SocketError . recvFailed ( " " )
12+ func testRandomStuff( ) {
13+ do {
14+ let data = [ UInt8] ( " 1231245 " . utf8)
15+ try HttpIncomingDataPorcessor ( 0 , { item in
16+ XCTAssert ( false , " Http processor should not return a request object for invalid data . " )
17+ } ) . process ( data [ 0 ..< data. count] )
18+ } catch {
19+ XCTAssert ( false , " No exception " )
2820 }
2921 }
3022
31- func testParser( ) {
32- let parser = HttpParser ( )
33-
23+ func testInvalidStatusLineChunk( ) {
3424 do {
35- let _ = try parser. readHttpRequest ( TestSocket ( " " ) )
36- XCTAssert ( false , " Parser should throw an error if socket is empty. " )
37- } catch { }
38-
25+ let data = [ UInt8] ( " GET HTTP/1.0 " . utf8)
26+ try HttpIncomingDataPorcessor ( 0 , { item in
27+ XCTAssert ( false , " Http processor should not return a request object for invalid status line. " )
28+ } ) . process ( data [ 0 ..< data. count] )
29+ } catch {
30+ XCTAssert ( false , " No exception " )
31+ }
32+ }
33+
34+ func testValidStatusLineChunk( ) {
3935 do {
40- let _ = try parser. readHttpRequest ( TestSocket ( " 12345678 " ) )
41- XCTAssert ( false , " Parser should throw an error if status line has single token. " )
42- } catch { }
43-
36+ let data = [ UInt8] ( " GET / HTTP/1.0 " . utf8)
37+ try HttpIncomingDataPorcessor ( 0 , { item in
38+ XCTAssert ( false , " Http processor should not return a request object for valid status line only. " )
39+ } ) . process ( data [ 0 ..< data. count] )
40+ } catch {
41+ XCTAssert ( false , " No exception " )
42+ }
43+ }
44+
45+ func testStatusLineWithSingleNextLine( ) {
4446 do {
45- let _ = try parser. readHttpRequest ( TestSocket ( " GET HTTP/1.0 " ) )
46- XCTAssert ( false , " Parser should throw an error if status line has not enough tokens. " )
47- } catch { }
48-
47+ let data = [ UInt8] ( " GET / HTTP/1.0 \r \n " . utf8)
48+ try HttpIncomingDataPorcessor ( 0 , { item in
49+ XCTAssert ( false , " Http processor should not return if there is no double next line symbol. " )
50+ } ) . process ( data [ 0 ..< data. count] )
51+ } catch {
52+ XCTAssert ( false , " No exception " )
53+ }
54+ }
55+
56+ func testStatusLineWithDoubleNextLine( ) {
4957 do {
50- let _ = try parser. readHttpRequest ( TestSocket ( " GET / HTTP/1.0 " ) )
51- XCTAssert ( false , " Parser should throw an error if there is no next line symbol. " )
52- } catch { }
53-
58+ var request : Request ? = nil
59+ let data = [ UInt8] ( " GET / HTTP/1.0 \r \n \r \n " . utf8)
60+ try HttpIncomingDataPorcessor ( 0 , { item in
61+ request = item
62+ } ) . process ( data [ 0 ..< data. count] )
63+ XCTAssertEqual ( request? . path, " / " )
64+ XCTAssertEqual ( request? . method, " GET " )
65+ XCTAssertEqual ( request? . httpVersion, . http10)
66+ } catch {
67+ XCTAssert ( false , " There should be no crash for valid http request. " )
68+ }
69+ }
70+
71+ func testContentLengthZero( ) {
5472 do {
55- let _ = try parser. readHttpRequest ( TestSocket ( " GET / HTTP/1.0 " ) )
56- XCTAssert ( false , " Parser should throw an error if there is no next line symbol. " )
57- } catch { }
58-
73+ var request : Request ? = nil
74+ let data = [ UInt8] ( " GET / HTTP/1.0 \r \n Content-Length: 0 \r \n \r \n " . utf8)
75+ try HttpIncomingDataPorcessor ( 0 , { item in
76+ request = item
77+ } ) . process ( data [ 0 ..< data. count] )
78+ XCTAssertEqual ( request? . path, " / " )
79+ XCTAssertEqual ( request? . method, " GET " )
80+ XCTAssertEqual ( request? . body. count, 0 )
81+ XCTAssertEqual ( request? . httpVersion, . http10)
82+ } catch {
83+ XCTAssert ( false , " No exception " )
84+ }
85+ }
86+
87+ func testContentLengthNonZero( ) {
5988 do {
60- let _ = try parser. readHttpRequest ( TestSocket ( " GET / HTTP/1.0 \r " ) )
61- XCTAssert ( false , " Parser should throw an error if there is no next line symbol. " )
62- } catch { }
63-
89+ var request : Request ? = nil
90+ let data = [ UInt8] ( " GET / HTTP/1.0 \r \n Content-Length: 5 \r \n \r \n 12345 " . utf8)
91+ try HttpIncomingDataPorcessor ( 0 , { item in
92+ request = item
93+ } ) . process ( data [ 0 ..< data. count] )
94+ XCTAssertEqual ( request? . path, " / " )
95+ XCTAssertEqual ( request? . method, " GET " )
96+ XCTAssertEqual ( request? . body. count, 5 )
97+ XCTAssertEqual ( ( request? . body) !, [ 49 , 50 , 51 , 52 , 53 ] )
98+ XCTAssertEqual ( request? . httpVersion, . http10)
99+ } catch {
100+ XCTAssert ( false , " No exception " )
101+ }
102+ }
103+
104+ func testContentLengthWithBodyChunk( ) {
64105 do {
65- let _ = try parser. readHttpRequest ( TestSocket ( " GET / HTTP/1.0 \n " ) )
66- XCTAssert ( false , " Parser should throw an error if there is no 'Content-Length' header. " )
67- } catch { }
68-
106+ var request : Request ? = nil
107+ let data = [ UInt8] ( " GET / HTTP/1.0 \r \n Content-Length: 10 \r \n \r \n 123 " . utf8)
108+ try HttpIncomingDataPorcessor ( 0 , { item in
109+ request = item
110+ } ) . process ( data [ 0 ..< data. count] )
111+ XCTAssertNil ( request)
112+ } catch {
113+ XCTAssert ( false , " No exception " )
114+ }
115+ }
116+
117+ func testContentProcessedInChunks( ) {
69118 do {
70- let _ = try parser. readHttpRequest ( TestSocket ( " GET / HTTP/1.0 \r \n Content-Length: 0 \r \n \r \n " ) )
119+ var request : Request ? = nil
120+
121+ let processor = HttpIncomingDataPorcessor ( 0 , { item in
122+ request = item
123+ } )
124+
125+ let chunk1 = [ UInt8] ( " GET /chunk HTTP/1.0 \r \n Content-Length: 20 \r \n \r \n 123 " . utf8)
126+ try processor. process ( chunk1 [ 0 ..< chunk1. count] )
127+
128+ XCTAssertNil ( request)
129+
130+ let chunk2 = [ UInt8] ( " 1234567890 " . utf8)
131+ try processor. process ( chunk2 [ 0 ..< chunk2. count] )
132+
133+ XCTAssertNil ( request)
134+
135+ let chunk3 = [ UInt8] ( " 1234567 " . utf8)
136+ try processor. process ( chunk3 [ 0 ..< chunk3. count] )
137+
138+ XCTAssertEqual ( request? . path, " /chunk " )
139+ XCTAssertEqual ( request? . method, " GET " )
140+ XCTAssertEqual ( request? . body. count, 20 )
141+ XCTAssertEqual ( request? . httpVersion, . http10)
142+
71143 } catch {
72- XCTAssert ( false , " Parser should not throw any errors if there is a valid 'Content-Length' header. " )
144+ XCTAssert ( false , " No exception " )
73145 }
74-
146+ }
147+
148+ func testHeaders( ) {
75149 do {
76- let _ = try parser. readHttpRequest ( TestSocket ( " GET / HTTP/1.0 \n Content-Length: 0 \r \n \n " ) )
150+ var request : Request ? = nil
151+ let data = [ UInt8] ( " GET / HTTP/1.0 \r \n a: b \r \n c: d \r \n Content-Length: 0 \r \n \r \n " . utf8)
152+ try HttpIncomingDataPorcessor ( 0 , { item in
153+ request = item
154+ } ) . process ( data [ 0 ..< data. count] )
155+ XCTAssertNotNil ( request)
156+ XCTAssertEqual ( request? . headers. first? . 0 , " a " )
157+ XCTAssertEqual ( request? . headers. first? . 1 , " b " )
158+ XCTAssertEqual ( request? . headers [ 1 ] . 0 , " c " )
159+ XCTAssertEqual ( request? . headers [ 1 ] . 1 , " d " )
77160 } catch {
78- XCTAssert ( false , " Parser should not throw any errors if there is a valid 'Content-Length' header. " )
161+ XCTAssert ( false , " No exception " )
79162 }
80-
163+ }
164+
165+ func testPath( ) {
81166 do {
82- let _ = try parser. readHttpRequest ( TestSocket ( " GET / HTTP/1.0 \n Content-Length: 5 \n \n 12345 " ) )
167+ var request : Request ? = nil
168+ let data = [ UInt8] ( " GET /a/b/c/d?1345678=1231 HTTP/1.0 \r \n Content-Length: 0 \r \n \r \n " . utf8)
169+ try HttpIncomingDataPorcessor ( 0 , { item in
170+ request = item
171+ } ) . process ( data [ 0 ..< data. count] )
172+ XCTAssertEqual ( request? . path, " /a/b/c/d " )
173+ XCTAssertEqual ( request? . method, " GET " )
174+ XCTAssertEqual ( request? . body. count, 0 )
175+ XCTAssertEqual ( request? . httpVersion, . http10)
83176 } catch {
84- XCTAssert ( false , " Parser should not throw any errors if there is a valid 'Content-Length' header. " )
177+ XCTAssert ( false , " No exception " )
85178 }
86-
179+ }
180+
181+ func testPathWithComplexQuery( ) {
87182 do {
88- let _ = try parser. readHttpRequest ( TestSocket ( " GET / HTTP/1.0 \n Content-Length: 10 \r \n \n " ) )
89- XCTAssert ( false , " Parser should throw an error if request' body is too short. " )
90- } catch { }
91-
92- var r = try ? parser. readHttpRequest ( TestSocket ( " GET / HTTP/1.0 \n Content-Length: 10 \n \n 1234567890 " ) )
93- XCTAssertEqual ( r? . method, " GET " , " Parser should extract HTTP method name from the status line. " )
94- XCTAssertEqual ( r? . path, " / " , " Parser should extract HTTP path value from the status line. " )
95- XCTAssertEqual ( r? . headers [ " content-length " ] , " 10 " , " Parser should extract Content-Length header value. " )
96-
97- r = try ? parser. readHttpRequest ( TestSocket ( " POST / HTTP/1.0 \n Content-Length: 10 \n \n 1234567890 " ) )
98- XCTAssertEqual ( r? . method, " POST " , " Parser should extract HTTP method name from the status line. " )
99-
100- r = try ? parser. readHttpRequest ( TestSocket ( " GET / HTTP/1.0 \n Header1: 1 \n Header2: 2 \n Content-Length: 0 \n \n " ) )
101- XCTAssertEqual ( r? . headers [ " header1 " ] , " 1 " , " Parser should extract multiple headers from the request. " )
102- XCTAssertEqual ( r? . headers [ " header2 " ] , " 2 " , " Parser should extract multiple headers from the request. " )
183+ var request : Request ? = nil
184+ let data = [ UInt8] ( " GET /a/b/c/d?key=value1?&key=???s HTTP/1.0 \r \n Content-Length: 0 \r \n \r \n " . utf8)
185+ try HttpIncomingDataPorcessor ( 0 , { item in
186+ request = item
187+ } ) . process ( data [ 0 ..< data. count] )
188+ XCTAssertEqual ( request? . path, " /a/b/c/d " )
189+ XCTAssertEqual ( request? . method, " GET " )
190+ XCTAssertEqual ( request? . query [ 0 ] . 0 , " key " )
191+ XCTAssertEqual ( request? . query [ 0 ] . 1 , " value1? " )
192+ XCTAssertEqual ( request? . query [ 1 ] . 0 , " key " )
193+ XCTAssertEqual ( request? . query [ 1 ] . 1 , " ???s " )
194+ XCTAssertEqual ( request? . body. count, 0 )
195+ XCTAssertEqual ( request? . httpVersion, . http10)
196+ } catch {
197+ XCTAssert ( false , " No exception " )
198+ }
103199 }
104200}
0 commit comments