network-anonymous-i2p-0.9.0: test/Network/Anonymous/I2P/Protocol/ParserSpec.hs
{-# LANGUAGE OverloadedStrings #-}
module Network.Anonymous.I2P.Protocol.ParserSpec where
import qualified Data.ByteString as BS
import Network.Anonymous.I2P.Protocol.Parser
import Network.Anonymous.I2P.Protocol.Parser.Ast (Token (..))
import Test.Hspec
import Test.Hspec.Attoparsec
testDestination :: BS.ByteString
testDestination = "TedPIHKiYHLLavX~2XgghB-jYBFkwkeztWM5rwyJCO2yR2gT92FcuEahEcTrykTxafzv~4jSQOL5w0EqElqlM~PEFy5~L1pOyGB56-yVd4I-g2fsM9MGKlXNOeQinghKOcfbQx1LVY35-0X5lQSNX-8I~U7Lefukj7gSC5hieWkDS6WiUW6nYw~t061Ra0GXf2qzqFTB4nkQvnCFKaZGtNwOUUpmIbF0OtLyr6TxC7BQKgcg4jyZPS1LaBO6Wev0ZFYiQHLk4S-1LQFBfT13BxN34g-eCInwHlYeMD6NEdiy0BYHhnbBTq02HbgD3FjxW~GBBB-6a~eFABaIiJJ08XR8Mm6KKpNh~gQXut2OLxs55UhEkqk8YmTODrf6yzWzldCdaaAEVMfryO9oniWWCVl1FgLmzUHPGQ3yzvb8OlXiED2hunEfaEg0fg77FRDnYJnDHMF7i5zcUzRGb67rUa1To~H65hR9cFNWTAwX4svC-gRbbvxfi-bthyj-QqeBBQAEAAcAAOEyRS5bFHDrXnWpsjcRvpQj436gS4iCjCzdOohWgeBKC~gfLVY658op9GF6oRJ78ezPN9FBE0JqNrAM75-uL9CIeJd8JUwdldm83RNSVI1ZPZBK-5F3DgIjTsqHDMzQ9xPETiBO2UZZogXSThx9I9uYuAtg296ZhziKjYnl7wi2i3IgQlNbuPW16ajOcNeKnL1OqFipAL9e3k~LEhgBNM3J2hK1M4jO~BQ19TxIXXUfBsHFU4YjwkAOKqOxR1iP8YD~xUSfdtF9mBe6fT8-WW3-n2WgHXiTLW3PJjJuPYM4hNKNmsxsEz5vi~DE6H1pUsPVs2oXFYKZF3EcsKUVaAVWJBarBPuVNYdJgIbgl1~TJeNor8hGQw6rUTJFaZ~jjQ=="
spec :: Spec
spec = do
describe "parsing quoted values" $ do
it "it should succeed when providing a doublequoted value" $
let msg :: BS.ByteString
msg = "\"foo\""
in msg ~> quotedValue `shouldParse` "foo"
it "it should succeed when providing a doublequoted value with spaces" $
let msg :: BS.ByteString
msg = "\"foo bar\""
in msg ~> quotedValue `shouldParse` "foo bar"
it "it should succeed when providing a doublequoted value with an escaped quote" $
let msg :: BS.ByteString
msg = "\"foo \\\" bar\""
in msg ~> quotedValue `shouldParse` "foo \\\" bar"
it "it should stop after a doublequoted value has been reached" $
let msg :: BS.ByteString
msg = "\"foo bar\" \"baz\""
in msg ~> quotedValue `shouldParse` "foo bar"
it "it should succeed when providing a singlequoted value" $
let msg :: BS.ByteString
msg = "'foo'"
in msg ~> quotedValue `shouldParse` "foo"
it "it should succeed when providing a singlequoted value with spaces" $
let msg :: BS.ByteString
msg = "'foo bar'"
in msg ~> quotedValue `shouldParse` "foo bar"
it "it should succeed when providing a singlequoted value with an escaped quote" $
let msg :: BS.ByteString
msg = "'foo \\' bar'"
in msg ~> quotedValue `shouldParse` "foo \\' bar"
it "it should stop after a singlequoted value has been reached" $
let msg :: BS.ByteString
msg = "'foo bar' 'baz'"
in msg ~> quotedValue `shouldParse` "foo bar"
describe "parsing unquoted values" $ do
it "it should succeed when providing a simple value" $
let msg :: BS.ByteString
msg = "foo"
in msg ~> unquotedValue `shouldParse` "foo"
it "it should stop after whitespace" $
let msg :: BS.ByteString
msg = "foo bar"
in msg ~> unquotedValue `shouldParse` "foo"
it "it should stop after a newline" $
let msg :: BS.ByteString
msg = "foo\r\nbar"
in msg ~> unquotedValue `shouldParse` "foo"
it "it should eat a destination" $
testDestination ~> unquotedValue `shouldParse` testDestination
it "it should eat a destination and not continue with more" $
BS.concat [testDestination, " foo=bar"] ~> unquotedValue `shouldParse` testDestination
it "should fail on empty input" $
unquotedValue `shouldFailOn` BS.empty
describe "parsing keys" $ do
it "it should succeed when providing a simple key" $
let msg :: BS.ByteString
msg = "foo"
in msg ~> key `shouldParse` (Token "foo" Nothing)
it "it should succeed when providing a space separated key" $
let msg :: BS.ByteString
msg = "foo bar"
in msg ~> key `shouldParse` (Token "foo" Nothing)
it "it should succeed when providing an equals separated key" $
let msg :: BS.ByteString
msg = "foo=bar"
in msg ~> key `shouldParse` (Token "foo" Nothing)
it "should fail on empty input" $
key `shouldFailOn` BS.empty
describe "parsing key/values" $ do
it "it should succeed when providing a simple key/value" $
let msg :: BS.ByteString
msg = "foo=bar"
in msg ~> keyValue `shouldParse` (Token "foo" (Just "bar"))
it "it should succeed when providing a key/value where the value contains an equals sign" $
let msg :: BS.ByteString
msg = "foo=bar=wombat"
in msg ~> keyValue `shouldParse` (Token "foo" (Just "bar=wombat"))
it "it should succeed when providing a destination as value" $
let msg :: BS.ByteString
msg = BS.concat ["destination=", testDestination]
in msg ~> keyValue `shouldParse` (Token "destination" (Just testDestination))
it "it should succeed when providing a quoted value" $
let msg :: BS.ByteString
msg = "foo=\"bar wombat\""
in msg ~> keyValue `shouldParse` (Token "foo" (Just "bar wombat"))
it "should fail on empty value" $
keyValue `shouldFailOn` ("foo=" :: BS.ByteString)
it "should fail on empty key" $
keyValue `shouldFailOn` ("=bar" :: BS.ByteString)
describe "parsing a token" $ do
it "should parse a key when only providing a key" $
let msg :: BS.ByteString
msg = "foo"
in msg ~> token `shouldParse` (Token "foo" Nothing)
it "should parse a key/value when providing a key/value" $
let msg :: BS.ByteString
msg = "foo=bar"
in msg ~> token `shouldParse` (Token "foo" (Just "bar"))
it "should skip any preceding horizontal whitespace" $
let msg :: BS.ByteString
msg = " foo"
in msg ~> token `shouldParse` (Token "foo" Nothing)
it "should not skip any preceding newlines" $
let msg :: BS.ByteString
msg = "\nfoo"
in token `shouldFailOn` msg
describe "parsing many tokens" $ do
it "should parse multiple keys correctly" $
let msg :: BS.ByteString
msg = "foo bar"
in msg ~> tokens `shouldParse` [(Token "foo" Nothing), (Token "bar" Nothing)]
it "should parse multiple key/valuess correctly" $
let msg :: BS.ByteString
msg = "foo=bar wom=bat"
in msg ~> tokens `shouldParse` [(Token "foo" (Just "bar")), (Token "wom" (Just "bat"))]
it "should be able to mix and match key/values and keys" $
let msg :: BS.ByteString
msg = "foo=bar wombat foz=baz"
in msg ~> tokens `shouldParse` [(Token "foo" (Just "bar")), (Token "wombat" Nothing), Token "foz" (Just "baz")]
describe "parsing a line" $ do
it "should parse multiple keys correctly" $
let msg :: BS.ByteString
msg = "foo bar\n"
in msg ~> line `shouldParse` [(Token "foo" Nothing), (Token "bar" Nothing)]
it "should fail when no newline is provided" $
line `shouldFailOn` ("foo bar" :: BS.ByteString)