1import Test.Framework (defaultMain, testGroup, Test)
2import Test.Framework.Providers.HUnit
3import Test.HUnit hiding (Test)
6import Network.Wai.Parse
7import qualified Data.ByteString.Char8 as S8
8import qualified Data.ByteString.Lazy.Char8 as L8
12main = defaultMain [testSuite]
15testSuite = testGroup "Network.Wai.Parse"
16 [ testCase "parseQueryString" caseParseQueryString
17 , testCase "parseQueryString with question mark" caseParseQueryStringQM
18 , testCase "parseCookies" caseParseCookies
19 , testCase "parseHttpAccept" caseParseHttpAccept
20 , testCase "parseRequestBody" caseParseRequestBody
21 , testCase "findBound" caseFindBound
22 , testCase "sinkTillBound" caseSinkTillBound
25caseParseQueryString :: Assertion
26caseParseQueryString = do
28 map (S8.pack *** S8.pack) l @=? parseQueryString (S8.pack r)
31 go [("foo", "")] "foo"
32 go [("foo", "bar")] "foo=bar"
33 go [("foo", "bar"), ("baz", "bin")] "foo=bar&baz=bin"
35 go [("%1Q", "")] "%1Q"
39 go [("foo bar", "")] "foo+bar"
41caseParseQueryStringQM :: Assertion
42caseParseQueryStringQM = do
44 map (S8.pack *** S8.pack) l
45 @=? parseQueryString (S8.pack $ '?' : r)
48 go [("foo", "")] "foo"
49 go [("foo", "bar")] "foo=bar"
50 go [("foo", "bar"), ("baz", "bin")] "foo=bar&baz=bin"
52 go [("%1Q", "")] "%1Q"
56 go [("foo bar", "")] "foo+bar"
58caseParseCookies :: Assertion
60 let input = S8.pack "a=a1;b=b2; c=c3"
61 expected = [("a", "a1"), ("b", "b2"), ("c", "c3")]
62 map (S8.pack *** S8.pack) expected @=? parseCookies input
64caseParseHttpAccept :: Assertion
65caseParseHttpAccept = do
67 S8.pack "text/plain; q=0.5, text/html, text/x-dvi; q=0.8, text/x-c"
68 expected = ["text/html", "text/x-c", "text/x-dvi", "text/plain"]
69 map S8.pack expected @=? parseHttpAccept input
71caseParseRequestBody :: Assertion
72caseParseRequestBody = t where
75 "Content-Disposition: form-data; name=\"document\"; filename=\"b.txt\"\n" ++
76 "Content-Type: text/plain; charset=iso-8859-1\n\n" ++
77 "This is a file.\n" ++
78 "It has two lines.\n" ++
80 "Content-Disposition: form-data; name=\"title\"\n" ++
81 "Content-Type: text/plain; charset=iso-8859-1\n\n" ++
84 "Content-Disposition: form-data; name=\"summary\"\n" ++
85 "Content-Type: text/plain; charset=iso-8859-1\n\n" ++
86 "This is my file\n" ++
89 content3 = S8.pack "------WebKitFormBoundaryB1pWXPZ6lNr8RiLh\r\nContent-Disposition: form-data; name=\"yaml\"; filename=\"README\"\r\nContent-Type: application/octet-stream\r\n\r\nPhoto blog using Hack.\n\r\n------WebKitFormBoundaryB1pWXPZ6lNr8RiLh--\r\n"
91 let content1 = S8.pack "foo=bar&baz=bin"
92 let ctype1 = S8.pack "application/x-www-form-urlencoded"
93 result1 <- parseRequestBody lbsSink $ toRequest ctype1 content1
94 assertEqual "parsing post x-www-form-urlencoded"
95 (map (S8.pack *** S8.pack) [("foo", "bar"), ("baz", "bin")], [])
98 let ctype2 = S8.pack "multipart/form-data; boundary=AaB03x"
99 result2 <- parseRequestBody lbsSink $ toRequest ctype2 content2
101 [ ("title", "A File")
102 , ("summary", "This is my file\nfile test")
104 let textPlain = S8.pack $ "text/plain; charset=iso-8859-1"
106 [(S8.pack "document", FileInfo (S8.pack "b.txt") textPlain $ L8.pack
107 "This is a file.\nIt has two lines.")]
108 let expected2 = (map (S8.pack *** S8.pack) expectedsmap2, expectedfile2)
109 assertEqual "parsing post multipart/form-data"
113 let ctype3 = S8.pack "multipart/form-data; boundary=----WebKitFormBoundaryB1pWXPZ6lNr8RiLh"
114 result3 <- parseRequestBody lbsSink $ toRequest ctype3 content3
115 let expectedsmap3 = []
116 let expectedfile3 = [(S8.pack "yaml", FileInfo (S8.pack "README") (S8.pack "application/octet-stream") $
117 L8.pack "Photo blog using Hack.\n")]
118 let expected3 = (expectedsmap3, expectedfile3)
119 assertEqual "parsing actual post multipart/form-data"
123 result2' <- parseRequestBody lbsSink $ toRequest' ctype2 content2
124 assertEqual "parsing post multipart/form-data 2"
128 result3' <- parseRequestBody lbsSink $ toRequest' ctype3 content3
129 assertEqual "parsing actual post multipart/form-data 2"
133toRequest :: S8.ByteString -> S8.ByteString -> Request
134toRequest ctype content = Request
135 { requestHeaders = [(ReqContentType, ctype)]
136 , requestBody = toSource content
137 , requestMethod = undefined
138 , httpVersion = undefined
139 , pathInfo = undefined
140 , queryString = undefined
141 , serverName = undefined
142 , serverPort = undefined
143 , urlScheme = undefined
144 , errorHandler = undefined
145 , remoteHost = undefined
148toRequest' :: S8.ByteString -> S8.ByteString -> Request
149toRequest' ctype content = Request
150 { requestHeaders = [(ReqContentType, ctype)]
151 , requestBody = toSource' content
152 , requestMethod = undefined
153 , httpVersion = undefined
154 , pathInfo = undefined
155 , queryString = undefined
156 , serverName = undefined
157 , serverPort = undefined
158 , urlScheme = undefined
159 , errorHandler = undefined
160 , remoteHost = undefined
163toSource :: S8.ByteString -> Source
164toSource bs = Source $
166 Nothing -> return Nothing
167 Just (x, xs) -> return $ Just (S8.singleton x, toSource xs)
169toSource' :: S8.ByteString -> Source
170toSource' bs = Source $ return $ Just (bs, Source $ return Nothing)
172caseFindBound :: Assertion
174 findBound (S8.pack "def") (S8.pack "abcdefghi") @?=
175 FoundBound (S8.pack "abc") (S8.pack "ghi")
176 findBound (S8.pack "def") (S8.pack "ABC") @?= NoBound
177 findBound (S8.pack "def") (S8.pack "abcd") @?= PartialBound
178 findBound (S8.pack "def") (S8.pack "abcdE") @?= NoBound
179 findBound (S8.pack "def") (S8.pack "abcdEdef") @?=
180 FoundBound (S8.pack "abcdE") (S8.pack "")
182caseSinkTillBound :: Assertion
183caseSinkTillBound = do
184 caseSinkTillBoundHelper $ Just . toSource
185 caseSinkTillBoundHelper $ Just . toSource'
187caseSinkTillBoundHelper :: (S8.ByteString -> Maybe Source) -> Assertion
188caseSinkTillBoundHelper tosrc = do
189 let iter () _ = return ()
190 let src = S8.pack "this is some text"
191 bound1 = S8.pack "some"
192 bound2 = S8.pack "some!"
193 (_, res1, _) <- sinkTillBound bound1 (S8.empty, tosrc src) iter ()
195 (_, res2, _) <- sinkTillBound bound2 (S8.empty, tosrc src) iter ()
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list