diff options
-rw-r--r-- | bittorrent.cabal | 4 | ||||
-rw-r--r-- | tests/Network/BitTorrent/Core/FingerprintSpec.hs | 33 | ||||
-rw-r--r-- | tests/Network/BitTorrent/Core/NodeInfoSpec.hs | 52 | ||||
-rw-r--r-- | tests/Network/BitTorrent/Core/PeerAddrSpec.hs | 221 | ||||
-rw-r--r-- | tests/Network/BitTorrent/Core/PeerIdSpec.hs | 25 | ||||
-rw-r--r-- | tests/Network/BitTorrent/CoreSpec.hs | 308 |
6 files changed, 301 insertions, 342 deletions
diff --git a/bittorrent.cabal b/bittorrent.cabal index 761ed1c4..6df074bb 100644 --- a/bittorrent.cabal +++ b/bittorrent.cabal | |||
@@ -177,10 +177,6 @@ test-suite spec | |||
177 | Data.Torrent.ProgressSpec | 177 | Data.Torrent.ProgressSpec |
178 | Network.BitTorrent.Client.HandleSpec | 178 | Network.BitTorrent.Client.HandleSpec |
179 | Network.BitTorrent.CoreSpec | 179 | Network.BitTorrent.CoreSpec |
180 | Network.BitTorrent.Core.FingerprintSpec | ||
181 | Network.BitTorrent.Core.NodeInfoSpec | ||
182 | Network.BitTorrent.Core.PeerAddrSpec | ||
183 | Network.BitTorrent.Core.PeerIdSpec | ||
184 | Network.BitTorrent.DHTSpec | 180 | Network.BitTorrent.DHTSpec |
185 | Network.BitTorrent.DHT.TestData | 181 | Network.BitTorrent.DHT.TestData |
186 | Network.BitTorrent.DHT.MessageSpec | 182 | Network.BitTorrent.DHT.MessageSpec |
diff --git a/tests/Network/BitTorrent/Core/FingerprintSpec.hs b/tests/Network/BitTorrent/Core/FingerprintSpec.hs deleted file mode 100644 index f8ed6950..00000000 --- a/tests/Network/BitTorrent/Core/FingerprintSpec.hs +++ /dev/null | |||
@@ -1,33 +0,0 @@ | |||
1 | -- | see <http://bittorrent.org/beps/bep_0020.html> | ||
2 | module Network.BitTorrent.Core.FingerprintSpec (spec) where | ||
3 | import Test.Hspec | ||
4 | import Network.BitTorrent.Address | ||
5 | |||
6 | spec :: Spec | ||
7 | spec = do | ||
8 | describe "client info" $ do | ||
9 | it "decode mainline encoded peer id" $ do | ||
10 | fingerprint "M4-3-6--xxxxxxxxxxxx" `shouldBe` "Mainline-4.3.6" | ||
11 | fingerprint "M4-20-8-xxxxxxxxxxxx" `shouldBe` "Mainline-4.20.8" | ||
12 | |||
13 | it "decode azureus encoded peer id" $ do | ||
14 | fingerprint "-AZ2060-xxxxxxxxxxxx" `shouldBe` "Azureus-2060" | ||
15 | fingerprint "-BS0000-xxxxxxxxxxxx" `shouldBe` "BTSlave-0" | ||
16 | |||
17 | it "decode Shad0w style peer id" $ do | ||
18 | fingerprint "S58B-----xxxxxxxxxxx" `shouldBe` "Shadow-5.8.11" | ||
19 | fingerprint "T58B-----xxxxxxxxxxx" `shouldBe` "BitTornado-5.8.11" | ||
20 | |||
21 | it "decode bitcomet style peer id" $ do | ||
22 | fingerprint "exbc01xxxxxxxxxxxxxx" `shouldBe` "BitComet-48.49" | ||
23 | fingerprint "FUTB01xxxxxxxxxxxxxx" `shouldBe` "BitComet-48.49" | ||
24 | fingerprint "exbc01LORDxxxxxxxxxx" `shouldBe` "BitLord-48.49" | ||
25 | |||
26 | it "decode opera style peer id" $ do | ||
27 | fingerprint "OP0123xxxxxxxxxxxxxx" `shouldBe` "Opera-123" | ||
28 | |||
29 | it "decode ML donkey style peer id" $ do | ||
30 | fingerprint "-ML2.7.2-xxxxxxxxxxx" `shouldBe` "MLdonkey-0" | ||
31 | |||
32 | -- TODO XBT, Bits on Wheels, Queen Bee, BitTyrant, TorrenTopia, | ||
33 | -- BitSpirit, Rufus, G3 Torrent, FlashGet \ No newline at end of file | ||
diff --git a/tests/Network/BitTorrent/Core/NodeInfoSpec.hs b/tests/Network/BitTorrent/Core/NodeInfoSpec.hs deleted file mode 100644 index 0d30b9a6..00000000 --- a/tests/Network/BitTorrent/Core/NodeInfoSpec.hs +++ /dev/null | |||
@@ -1,52 +0,0 @@ | |||
1 | {-# OPTIONS -fno-warn-orphans #-} | ||
2 | module Network.BitTorrent.Core.NodeInfoSpec (spec) where | ||
3 | import Control.Applicative | ||
4 | import Data.Serialize as S | ||
5 | import Data.String | ||
6 | import Test.Hspec | ||
7 | import Test.QuickCheck | ||
8 | |||
9 | import Network.BitTorrent.Address | ||
10 | import Network.BitTorrent.Core.PeerAddrSpec () | ||
11 | |||
12 | instance Arbitrary NodeId where | ||
13 | arbitrary = fromString <$> vector 20 | ||
14 | |||
15 | instance Arbitrary a => Arbitrary (NodeAddr a) where | ||
16 | arbitrary = NodeAddr <$> arbitrary <*> arbitrary | ||
17 | |||
18 | instance Arbitrary a => Arbitrary (NodeInfo a) where | ||
19 | arbitrary = NodeInfo <$> arbitrary <*> arbitrary | ||
20 | |||
21 | spec :: Spec | ||
22 | spec = do | ||
23 | describe "NodeId" $ do | ||
24 | it "properly serialized" $ do | ||
25 | S.decode "mnopqrstuvwxyz123456" | ||
26 | `shouldBe` Right ("mnopqrstuvwxyz123456" :: NodeId) | ||
27 | |||
28 | S.encode ("mnopqrstuvwxyz123456" :: NodeId) | ||
29 | `shouldBe` "mnopqrstuvwxyz123456" | ||
30 | |||
31 | it "properly serialized (iso)" $ property $ \ nid -> | ||
32 | S.decode (S.encode nid) `shouldBe` | ||
33 | Right (nid :: NodeId) | ||
34 | |||
35 | describe "NodeAddr" $ do | ||
36 | it "properly serialized" $ do | ||
37 | S.decode "\127\0\0\1\1\2" `shouldBe` | ||
38 | Right ("127.0.0.1:258" :: NodeAddr IPv4) | ||
39 | |||
40 | it "properly serialized (iso)" $ property $ \ nid -> | ||
41 | S.decode (S.encode nid) `shouldBe` | ||
42 | Right (nid :: NodeAddr IPv4) | ||
43 | |||
44 | describe "NodeInfo" $ do | ||
45 | it "properly serialized" $ do | ||
46 | S.decode "mnopqrstuvwxyz123456\ | ||
47 | \\127\0\0\1\1\2" `shouldBe` Right | ||
48 | (NodeInfo "mnopqrstuvwxyz123456" "127.0.0.1:258" :: NodeInfo IPv4) | ||
49 | |||
50 | it "properly serialized (iso)" $ property $ \ nid -> | ||
51 | S.decode (S.encode nid) `shouldBe` | ||
52 | Right (nid :: NodeInfo IPv4) | ||
diff --git a/tests/Network/BitTorrent/Core/PeerAddrSpec.hs b/tests/Network/BitTorrent/Core/PeerAddrSpec.hs deleted file mode 100644 index 387126db..00000000 --- a/tests/Network/BitTorrent/Core/PeerAddrSpec.hs +++ /dev/null | |||
@@ -1,221 +0,0 @@ | |||
1 | {-# LANGUAGE FlexibleInstances #-} | ||
2 | {-# OPTIONS_GHC -fno-warn-orphans #-} | ||
3 | module Network.BitTorrent.Core.PeerAddrSpec (spec) where | ||
4 | import Control.Applicative | ||
5 | import Data.BEncode as BE | ||
6 | import Data.ByteString.Lazy as BL | ||
7 | import Data.IP | ||
8 | import Data.Serialize as S | ||
9 | import Data.Word | ||
10 | import Network | ||
11 | import Test.Hspec | ||
12 | import Test.QuickCheck | ||
13 | |||
14 | import Network.BitTorrent.Core.PeerIdSpec () | ||
15 | import Network.BitTorrent.Address | ||
16 | |||
17 | instance Arbitrary IPv4 where | ||
18 | arbitrary = do | ||
19 | a <- choose (0, 255) | ||
20 | b <- choose (0, 255) | ||
21 | c <- choose (0, 255) | ||
22 | d <- choose (0, 255) | ||
23 | return $ toIPv4 [a, b, c, d] | ||
24 | |||
25 | instance Arbitrary IPv6 where | ||
26 | arbitrary = do | ||
27 | a <- choose (0, fromIntegral (maxBound :: Word16)) | ||
28 | b <- choose (0, fromIntegral (maxBound :: Word16)) | ||
29 | c <- choose (0, fromIntegral (maxBound :: Word16)) | ||
30 | d <- choose (0, fromIntegral (maxBound :: Word16)) | ||
31 | e <- choose (0, fromIntegral (maxBound :: Word16)) | ||
32 | f <- choose (0, fromIntegral (maxBound :: Word16)) | ||
33 | g <- choose (0, fromIntegral (maxBound :: Word16)) | ||
34 | h <- choose (0, fromIntegral (maxBound :: Word16)) | ||
35 | return $ toIPv6 [a, b, c, d, e, f, g, h] | ||
36 | |||
37 | instance Arbitrary IP where | ||
38 | arbitrary = frequency | ||
39 | [ (1, IPv4 <$> arbitrary) | ||
40 | , (1, IPv6 <$> arbitrary) | ||
41 | ] | ||
42 | |||
43 | instance Arbitrary PortNumber where | ||
44 | arbitrary = fromIntegral <$> (arbitrary :: Gen Word16) | ||
45 | |||
46 | instance Arbitrary a => Arbitrary (PeerAddr a) where | ||
47 | arbitrary = PeerAddr <$> arbitrary <*> arbitrary <*> arbitrary | ||
48 | |||
49 | spec :: Spec | ||
50 | spec = do | ||
51 | describe "PortNumber" $ do | ||
52 | it "properly serialized" $ do | ||
53 | S.decode "\x1\x2" `shouldBe` Right (258 :: PortNumber) | ||
54 | S.encode (258 :: PortNumber) `shouldBe` "\x1\x2" | ||
55 | |||
56 | it "properly bencoded" $ do | ||
57 | BE.decode "i80e" `shouldBe` Right (80 :: PortNumber) | ||
58 | |||
59 | it "fail if port number is invalid" $ do | ||
60 | (BE.decode "i-10e" :: BE.Result PortNumber) | ||
61 | `shouldBe` | ||
62 | Left "fromBEncode: unable to decode PortNumber: -10" | ||
63 | |||
64 | (BE.decode "i70000e" :: BE.Result PortNumber) | ||
65 | `shouldBe` | ||
66 | Left "fromBEncode: unable to decode PortNumber: 70000" | ||
67 | |||
68 | describe "Peer IPv4" $ do | ||
69 | it "properly serialized" $ do | ||
70 | S.decode "\x1\x2\x3\x4" `shouldBe` Right (toIPv4 [1, 2, 3, 4]) | ||
71 | S.encode (toIPv4 [1, 2, 3, 4]) `shouldBe` "\x1\x2\x3\x4" | ||
72 | |||
73 | it "properly serialized (iso)" $ property $ \ ip -> do | ||
74 | S.decode (S.encode ip) `shouldBe` Right (ip :: IPv4) | ||
75 | |||
76 | it "properly bencoded" $ do | ||
77 | BE.decode "11:168.192.0.1" `shouldBe` Right (toIPv4 [168, 192, 0, 1]) | ||
78 | BE.encode (toIPv4 [168, 192, 0, 1]) `shouldBe` "11:168.192.0.1" | ||
79 | |||
80 | it "properly bencoded (iso)" $ property $ \ ip -> | ||
81 | BE.decode (BL.toStrict (BE.encode ip)) `shouldBe` Right (ip :: IPv4) | ||
82 | |||
83 | it "fail gracefully on invalid strings" $ do | ||
84 | BE.decode "3:1.1" `shouldBe` | ||
85 | (Left "fromBEncode: unable to decode IP: 1.1" :: BE.Result IPv4) | ||
86 | |||
87 | it "fail gracefully on invalid bencode" $ do | ||
88 | BE.decode "i10e" `shouldBe` | ||
89 | (Left "fromBEncode: unable to decode IP: addr should be a bstring" | ||
90 | :: BE.Result IPv4) | ||
91 | |||
92 | describe "Peer IPv6" $ do | ||
93 | it "properly serialized" $ do | ||
94 | S.decode "\x1\x2\x3\x4\x5\x6\x7\x8\x9\xa\xb\xc\xd\xe\xf\x10" | ||
95 | `shouldBe` | ||
96 | Right ("102:304:506:708:90a:b0c:d0e:f10" :: IPv6) | ||
97 | |||
98 | S.encode ("102:304:506:708:90a:b0c:d0e:f10" :: IPv6) | ||
99 | `shouldBe` | ||
100 | "\x1\x2\x3\x4\x5\x6\x7\x8\x9\xa\xb\xc\xd\xe\xf\x10" | ||
101 | |||
102 | it "properly serialized (iso)" $ property $ \ ip -> | ||
103 | S.decode (S.encode ip) `shouldBe` Right (ip :: IPv6) | ||
104 | |||
105 | it "properly bencoded" $ do | ||
106 | BE.decode "3:::1" `shouldBe` Right (toIPv6 [0, 0, 0, 0, 0, 0, 0, 1]) | ||
107 | BE.encode (toIPv6 [0, 0, 0, 0, 0, 0, 0, 1]) `shouldBe` | ||
108 | "23:00:00:00:00:00:00:00:01" | ||
109 | |||
110 | BE.decode "23:00:00:00:00:00:00:00:01" | ||
111 | `shouldBe` | ||
112 | Right (toIPv6 [0, 0, 0, 0, 0, 0, 0, 1]) | ||
113 | |||
114 | it "properly bencoded iso" $ property $ \ ip -> | ||
115 | BE.decode (BL.toStrict (BE.encode ip)) `shouldBe` Right (ip :: IPv4) | ||
116 | |||
117 | it "fail gracefully on invalid strings" $ do | ||
118 | BE.decode "4:g::1" `shouldBe` | ||
119 | (Left "fromBEncode: unable to decode IP: g::1" :: BE.Result IPv6) | ||
120 | |||
121 | it "fail gracefully on invalid bencode" $ do | ||
122 | BE.decode "i10e" `shouldBe` | ||
123 | (Left "fromBEncode: unable to decode IP: addr should be a bstring" | ||
124 | :: BE.Result IPv6) | ||
125 | |||
126 | |||
127 | describe "Peer IP" $ do | ||
128 | it "properly serialized IPv6" $ do | ||
129 | S.decode "\x1\x2\x3\x4\x5\x6\x7\x8\x9\xa\xb\xc\xd\xe\xf\x10" | ||
130 | `shouldBe` | ||
131 | Right ("102:304:506:708:90a:b0c:d0e:f10" :: IP) | ||
132 | |||
133 | S.encode ("102:304:506:708:90a:b0c:d0e:f10" :: IP) | ||
134 | `shouldBe` | ||
135 | "\x1\x2\x3\x4\x5\x6\x7\x8\x9\xa\xb\xc\xd\xe\xf\x10" | ||
136 | |||
137 | it "properly serialized (iso) IPv6" $ property $ \ ip -> | ||
138 | S.decode (S.encode ip) `shouldBe` Right (ip :: IP) | ||
139 | |||
140 | it "properly serialized IPv4" $ do | ||
141 | S.decode "\x1\x2\x3\x4" `shouldBe` Right (IPv4 $ toIPv4 [1, 2, 3, 4]) | ||
142 | S.encode (toIPv4 [1, 2, 3, 4]) `shouldBe` "\x1\x2\x3\x4" | ||
143 | |||
144 | it "properly serialized (iso) IPv4" $ property $ \ ip -> do | ||
145 | S.decode (S.encode ip) `shouldBe` Right (ip :: IP) | ||
146 | |||
147 | it "properly bencoded" $ do | ||
148 | BE.decode "11:168.192.0.1" `shouldBe` | ||
149 | Right (IPv4 (toIPv4 [168, 192, 0, 1])) | ||
150 | |||
151 | BE.decode "3:::1" `shouldBe` Right | ||
152 | (IPv6 (toIPv6 [0, 0, 0, 0, 0, 0, 0, 1])) | ||
153 | |||
154 | BE.encode (IPv6 (toIPv6 [0, 0, 0, 0, 0, 0, 0, 1])) `shouldBe` | ||
155 | "23:00:00:00:00:00:00:00:01" | ||
156 | |||
157 | BE.decode "23:00:00:00:00:00:00:00:01" | ||
158 | `shouldBe` | ||
159 | Right (IPv6 (toIPv6 [0, 0, 0, 0, 0, 0, 0, 1])) | ||
160 | |||
161 | it "properly bencoded iso" $ property $ \ ip -> | ||
162 | BE.decode (BL.toStrict (BE.encode ip)) `shouldBe` Right (ip :: IP) | ||
163 | |||
164 | it "fail gracefully on invalid strings" $ do | ||
165 | BE.decode "4:g::1" `shouldBe` | ||
166 | (Left "fromBEncode: unable to decode IP: g::1" :: BE.Result IP) | ||
167 | |||
168 | it "fail gracefully on invalid bencode" $ do | ||
169 | BE.decode "i10e" `shouldBe` | ||
170 | (Left "fromBEncode: unable to decode IP: addr should be a bstring" | ||
171 | :: BE.Result IP) | ||
172 | |||
173 | describe "PeerAddr" $ do | ||
174 | it "IsString" $ do | ||
175 | ("127.0.0.1:80" :: PeerAddr IP) | ||
176 | `shouldBe` PeerAddr Nothing "127.0.0.1" 80 | ||
177 | |||
178 | ("127.0.0.1:80" :: PeerAddr IPv4) | ||
179 | `shouldBe` PeerAddr Nothing "127.0.0.1" 80 | ||
180 | |||
181 | ("[::1]:80" :: PeerAddr IP) | ||
182 | `shouldBe` PeerAddr Nothing "::1" 80 | ||
183 | |||
184 | ("[::1]:80" :: PeerAddr IPv6) | ||
185 | `shouldBe` PeerAddr Nothing "::1" 80 | ||
186 | |||
187 | it "properly bencoded (iso)" $ property $ \ addr -> | ||
188 | BE.decode (BL.toStrict (BE.encode addr)) | ||
189 | `shouldBe` Right (addr :: PeerAddr IP) | ||
190 | |||
191 | |||
192 | it "properly bencoded (ipv4)" $ do | ||
193 | BE.decode "d2:ip11:168.192.0.1\ | ||
194 | \7:peer id20:01234567890123456789\ | ||
195 | \4:porti6881e\ | ||
196 | \e" | ||
197 | `shouldBe` | ||
198 | Right (PeerAddr (Just "01234567890123456789") | ||
199 | (IPv4 (toIPv4 [168, 192, 0, 1])) | ||
200 | 6881) | ||
201 | |||
202 | it "properly bencoded (ipv6)" $ do | ||
203 | BE.decode "d2:ip3:::1\ | ||
204 | \7:peer id20:01234567890123456789\ | ||
205 | \4:porti6881e\ | ||
206 | \e" | ||
207 | `shouldBe` | ||
208 | Right (PeerAddr (Just "01234567890123456789") | ||
209 | (IPv6 (toIPv6 [0, 0, 0, 0, 0, 0, 0, 1])) | ||
210 | 6881) | ||
211 | |||
212 | it "peer id is optional" $ do | ||
213 | BE.decode "d2:ip11:168.192.0.1\ | ||
214 | \4:porti6881e\ | ||
215 | \e" | ||
216 | `shouldBe` | ||
217 | Right (PeerAddr Nothing (IPv4 (toIPv4 [168, 192, 0, 1])) 6881) | ||
218 | |||
219 | it "has sock addr for both ipv4 and ipv6" $ do | ||
220 | show (peerSockAddr "128.0.0.1:80") `shouldBe` "128.0.0.1:80" | ||
221 | show (peerSockAddr "[::1]:8080" ) `shouldBe` "[::1]:8080" | ||
diff --git a/tests/Network/BitTorrent/Core/PeerIdSpec.hs b/tests/Network/BitTorrent/Core/PeerIdSpec.hs deleted file mode 100644 index 29b98bbc..00000000 --- a/tests/Network/BitTorrent/Core/PeerIdSpec.hs +++ /dev/null | |||
@@ -1,25 +0,0 @@ | |||
1 | {-# OPTIONS -fno-warn-orphans #-} | ||
2 | module Network.BitTorrent.Core.PeerIdSpec (spec) where | ||
3 | import Control.Applicative | ||
4 | import Data.BEncode as BE | ||
5 | import Data.Text.Encoding as T | ||
6 | import Test.Hspec | ||
7 | import Test.QuickCheck | ||
8 | import Test.QuickCheck.Instances () | ||
9 | import Network.BitTorrent.Address | ||
10 | |||
11 | |||
12 | instance Arbitrary PeerId where | ||
13 | arbitrary = oneof | ||
14 | [ azureusStyle defaultClientId defaultVersionNumber | ||
15 | <$> (T.encodeUtf8 <$> arbitrary) | ||
16 | , shadowStyle 'X' defaultVersionNumber | ||
17 | <$> (T.encodeUtf8 <$> arbitrary) | ||
18 | ] | ||
19 | |||
20 | spec :: Spec | ||
21 | spec = do | ||
22 | describe "PeerId" $ do | ||
23 | it "properly bencoded" $ do | ||
24 | BE.decode "20:01234567890123456789" | ||
25 | `shouldBe` Right ("01234567890123456789" :: PeerId) \ No newline at end of file | ||
diff --git a/tests/Network/BitTorrent/CoreSpec.hs b/tests/Network/BitTorrent/CoreSpec.hs index 1e1a21a1..5bf900b2 100644 --- a/tests/Network/BitTorrent/CoreSpec.hs +++ b/tests/Network/BitTorrent/CoreSpec.hs | |||
@@ -1,11 +1,305 @@ | |||
1 | -- | Re-export modules. | 1 | {-# LANGUAGE FlexibleInstances #-} |
2 | {-# OPTIONS_GHC -fno-warn-orphans #-} | ||
2 | module Network.BitTorrent.CoreSpec (spec) where | 3 | module Network.BitTorrent.CoreSpec (spec) where |
3 | import Network.BitTorrent.Core.FingerprintSpec as CoreSpec () | 4 | import Control.Applicative |
4 | import Network.BitTorrent.Core.PeerAddrSpec as CoreSpec () | 5 | import Data.BEncode as BE |
5 | import Network.BitTorrent.Core.NodeInfoSpec as CoreSpec () | 6 | import Data.ByteString.Lazy as BL |
6 | import Network.BitTorrent.Core.PeerIdSpec as CoreSpec () | 7 | import Data.IP |
8 | import Data.Serialize as S | ||
9 | import Data.String | ||
10 | import Data.Text.Encoding as T | ||
11 | import Data.Word | ||
12 | import Network | ||
13 | import Test.Hspec | ||
14 | import Test.QuickCheck | ||
15 | import Test.QuickCheck.Instances () | ||
7 | 16 | ||
8 | import Test.Hspec (Spec) | 17 | import Network.BitTorrent.Address |
18 | |||
19 | |||
20 | instance Arbitrary IPv4 where | ||
21 | arbitrary = do | ||
22 | a <- choose (0, 255) | ||
23 | b <- choose (0, 255) | ||
24 | c <- choose (0, 255) | ||
25 | d <- choose (0, 255) | ||
26 | return $ toIPv4 [a, b, c, d] | ||
27 | |||
28 | instance Arbitrary IPv6 where | ||
29 | arbitrary = do | ||
30 | a <- choose (0, fromIntegral (maxBound :: Word16)) | ||
31 | b <- choose (0, fromIntegral (maxBound :: Word16)) | ||
32 | c <- choose (0, fromIntegral (maxBound :: Word16)) | ||
33 | d <- choose (0, fromIntegral (maxBound :: Word16)) | ||
34 | e <- choose (0, fromIntegral (maxBound :: Word16)) | ||
35 | f <- choose (0, fromIntegral (maxBound :: Word16)) | ||
36 | g <- choose (0, fromIntegral (maxBound :: Word16)) | ||
37 | h <- choose (0, fromIntegral (maxBound :: Word16)) | ||
38 | return $ toIPv6 [a, b, c, d, e, f, g, h] | ||
39 | |||
40 | instance Arbitrary IP where | ||
41 | arbitrary = frequency | ||
42 | [ (1, IPv4 <$> arbitrary) | ||
43 | , (1, IPv6 <$> arbitrary) | ||
44 | ] | ||
45 | |||
46 | instance Arbitrary PortNumber where | ||
47 | arbitrary = fromIntegral <$> (arbitrary :: Gen Word16) | ||
48 | |||
49 | instance Arbitrary PeerId where | ||
50 | arbitrary = oneof | ||
51 | [ azureusStyle defaultClientId defaultVersionNumber | ||
52 | <$> (T.encodeUtf8 <$> arbitrary) | ||
53 | , shadowStyle 'X' defaultVersionNumber | ||
54 | <$> (T.encodeUtf8 <$> arbitrary) | ||
55 | ] | ||
56 | |||
57 | instance Arbitrary a => Arbitrary (PeerAddr a) where | ||
58 | arbitrary = PeerAddr <$> arbitrary <*> arbitrary <*> arbitrary | ||
59 | |||
60 | instance Arbitrary NodeId where | ||
61 | arbitrary = fromString <$> vector 20 | ||
62 | |||
63 | instance Arbitrary a => Arbitrary (NodeAddr a) where | ||
64 | arbitrary = NodeAddr <$> arbitrary <*> arbitrary | ||
65 | |||
66 | instance Arbitrary a => Arbitrary (NodeInfo a) where | ||
67 | arbitrary = NodeInfo <$> arbitrary <*> arbitrary | ||
9 | 68 | ||
10 | spec :: Spec | 69 | spec :: Spec |
11 | spec = return () \ No newline at end of file | 70 | spec = do |
71 | describe "PeerId" $ do | ||
72 | it "properly bencoded" $ do | ||
73 | BE.decode "20:01234567890123456789" | ||
74 | `shouldBe` Right ("01234567890123456789" :: PeerId) | ||
75 | |||
76 | describe "PortNumber" $ do | ||
77 | it "properly serialized" $ do | ||
78 | S.decode "\x1\x2" `shouldBe` Right (258 :: PortNumber) | ||
79 | S.encode (258 :: PortNumber) `shouldBe` "\x1\x2" | ||
80 | |||
81 | it "properly bencoded" $ do | ||
82 | BE.decode "i80e" `shouldBe` Right (80 :: PortNumber) | ||
83 | |||
84 | it "fail if port number is invalid" $ do | ||
85 | (BE.decode "i-10e" :: BE.Result PortNumber) | ||
86 | `shouldBe` | ||
87 | Left "fromBEncode: unable to decode PortNumber: -10" | ||
88 | |||
89 | (BE.decode "i70000e" :: BE.Result PortNumber) | ||
90 | `shouldBe` | ||
91 | Left "fromBEncode: unable to decode PortNumber: 70000" | ||
92 | |||
93 | describe "Peer IPv4" $ do | ||
94 | it "properly serialized" $ do | ||
95 | S.decode "\x1\x2\x3\x4" `shouldBe` Right (toIPv4 [1, 2, 3, 4]) | ||
96 | S.encode (toIPv4 [1, 2, 3, 4]) `shouldBe` "\x1\x2\x3\x4" | ||
97 | |||
98 | it "properly serialized (iso)" $ property $ \ ip -> do | ||
99 | S.decode (S.encode ip) `shouldBe` Right (ip :: IPv4) | ||
100 | |||
101 | it "properly bencoded" $ do | ||
102 | BE.decode "11:168.192.0.1" `shouldBe` Right (toIPv4 [168, 192, 0, 1]) | ||
103 | BE.encode (toIPv4 [168, 192, 0, 1]) `shouldBe` "11:168.192.0.1" | ||
104 | |||
105 | it "properly bencoded (iso)" $ property $ \ ip -> | ||
106 | BE.decode (BL.toStrict (BE.encode ip)) `shouldBe` Right (ip :: IPv4) | ||
107 | |||
108 | it "fail gracefully on invalid strings" $ do | ||
109 | BE.decode "3:1.1" `shouldBe` | ||
110 | (Left "fromBEncode: unable to decode IP: 1.1" :: BE.Result IPv4) | ||
111 | |||
112 | it "fail gracefully on invalid bencode" $ do | ||
113 | BE.decode "i10e" `shouldBe` | ||
114 | (Left "fromBEncode: unable to decode IP: addr should be a bstring" | ||
115 | :: BE.Result IPv4) | ||
116 | |||
117 | describe "Peer IPv6" $ do | ||
118 | it "properly serialized" $ do | ||
119 | S.decode "\x1\x2\x3\x4\x5\x6\x7\x8\x9\xa\xb\xc\xd\xe\xf\x10" | ||
120 | `shouldBe` | ||
121 | Right ("102:304:506:708:90a:b0c:d0e:f10" :: IPv6) | ||
122 | |||
123 | S.encode ("102:304:506:708:90a:b0c:d0e:f10" :: IPv6) | ||
124 | `shouldBe` | ||
125 | "\x1\x2\x3\x4\x5\x6\x7\x8\x9\xa\xb\xc\xd\xe\xf\x10" | ||
126 | |||
127 | it "properly serialized (iso)" $ property $ \ ip -> | ||
128 | S.decode (S.encode ip) `shouldBe` Right (ip :: IPv6) | ||
129 | |||
130 | it "properly bencoded" $ do | ||
131 | BE.decode "3:::1" `shouldBe` Right (toIPv6 [0, 0, 0, 0, 0, 0, 0, 1]) | ||
132 | BE.encode (toIPv6 [0, 0, 0, 0, 0, 0, 0, 1]) `shouldBe` | ||
133 | "23:00:00:00:00:00:00:00:01" | ||
134 | |||
135 | BE.decode "23:00:00:00:00:00:00:00:01" | ||
136 | `shouldBe` | ||
137 | Right (toIPv6 [0, 0, 0, 0, 0, 0, 0, 1]) | ||
138 | |||
139 | it "properly bencoded iso" $ property $ \ ip -> | ||
140 | BE.decode (BL.toStrict (BE.encode ip)) `shouldBe` Right (ip :: IPv4) | ||
141 | |||
142 | it "fail gracefully on invalid strings" $ do | ||
143 | BE.decode "4:g::1" `shouldBe` | ||
144 | (Left "fromBEncode: unable to decode IP: g::1" :: BE.Result IPv6) | ||
145 | |||
146 | it "fail gracefully on invalid bencode" $ do | ||
147 | BE.decode "i10e" `shouldBe` | ||
148 | (Left "fromBEncode: unable to decode IP: addr should be a bstring" | ||
149 | :: BE.Result IPv6) | ||
150 | |||
151 | |||
152 | describe "Peer IP" $ do | ||
153 | it "properly serialized IPv6" $ do | ||
154 | S.decode "\x1\x2\x3\x4\x5\x6\x7\x8\x9\xa\xb\xc\xd\xe\xf\x10" | ||
155 | `shouldBe` | ||
156 | Right ("102:304:506:708:90a:b0c:d0e:f10" :: IP) | ||
157 | |||
158 | S.encode ("102:304:506:708:90a:b0c:d0e:f10" :: IP) | ||
159 | `shouldBe` | ||
160 | "\x1\x2\x3\x4\x5\x6\x7\x8\x9\xa\xb\xc\xd\xe\xf\x10" | ||
161 | |||
162 | it "properly serialized (iso) IPv6" $ property $ \ ip -> | ||
163 | S.decode (S.encode ip) `shouldBe` Right (ip :: IP) | ||
164 | |||
165 | it "properly serialized IPv4" $ do | ||
166 | S.decode "\x1\x2\x3\x4" `shouldBe` Right (IPv4 $ toIPv4 [1, 2, 3, 4]) | ||
167 | S.encode (toIPv4 [1, 2, 3, 4]) `shouldBe` "\x1\x2\x3\x4" | ||
168 | |||
169 | it "properly serialized (iso) IPv4" $ property $ \ ip -> do | ||
170 | S.decode (S.encode ip) `shouldBe` Right (ip :: IP) | ||
171 | |||
172 | it "properly bencoded" $ do | ||
173 | BE.decode "11:168.192.0.1" `shouldBe` | ||
174 | Right (IPv4 (toIPv4 [168, 192, 0, 1])) | ||
175 | |||
176 | BE.decode "3:::1" `shouldBe` Right | ||
177 | (IPv6 (toIPv6 [0, 0, 0, 0, 0, 0, 0, 1])) | ||
178 | |||
179 | BE.encode (IPv6 (toIPv6 [0, 0, 0, 0, 0, 0, 0, 1])) `shouldBe` | ||
180 | "23:00:00:00:00:00:00:00:01" | ||
181 | |||
182 | BE.decode "23:00:00:00:00:00:00:00:01" | ||
183 | `shouldBe` | ||
184 | Right (IPv6 (toIPv6 [0, 0, 0, 0, 0, 0, 0, 1])) | ||
185 | |||
186 | it "properly bencoded iso" $ property $ \ ip -> | ||
187 | BE.decode (BL.toStrict (BE.encode ip)) `shouldBe` Right (ip :: IP) | ||
188 | |||
189 | it "fail gracefully on invalid strings" $ do | ||
190 | BE.decode "4:g::1" `shouldBe` | ||
191 | (Left "fromBEncode: unable to decode IP: g::1" :: BE.Result IP) | ||
192 | |||
193 | it "fail gracefully on invalid bencode" $ do | ||
194 | BE.decode "i10e" `shouldBe` | ||
195 | (Left "fromBEncode: unable to decode IP: addr should be a bstring" | ||
196 | :: BE.Result IP) | ||
197 | |||
198 | describe "PeerAddr" $ do | ||
199 | it "IsString" $ do | ||
200 | ("127.0.0.1:80" :: PeerAddr IP) | ||
201 | `shouldBe` PeerAddr Nothing "127.0.0.1" 80 | ||
202 | |||
203 | ("127.0.0.1:80" :: PeerAddr IPv4) | ||
204 | `shouldBe` PeerAddr Nothing "127.0.0.1" 80 | ||
205 | |||
206 | ("[::1]:80" :: PeerAddr IP) | ||
207 | `shouldBe` PeerAddr Nothing "::1" 80 | ||
208 | |||
209 | ("[::1]:80" :: PeerAddr IPv6) | ||
210 | `shouldBe` PeerAddr Nothing "::1" 80 | ||
211 | |||
212 | it "properly bencoded (iso)" $ property $ \ addr -> | ||
213 | BE.decode (BL.toStrict (BE.encode addr)) | ||
214 | `shouldBe` Right (addr :: PeerAddr IP) | ||
215 | |||
216 | |||
217 | it "properly bencoded (ipv4)" $ do | ||
218 | BE.decode "d2:ip11:168.192.0.1\ | ||
219 | \7:peer id20:01234567890123456789\ | ||
220 | \4:porti6881e\ | ||
221 | \e" | ||
222 | `shouldBe` | ||
223 | Right (PeerAddr (Just "01234567890123456789") | ||
224 | (IPv4 (toIPv4 [168, 192, 0, 1])) | ||
225 | 6881) | ||
226 | |||
227 | it "properly bencoded (ipv6)" $ do | ||
228 | BE.decode "d2:ip3:::1\ | ||
229 | \7:peer id20:01234567890123456789\ | ||
230 | \4:porti6881e\ | ||
231 | \e" | ||
232 | `shouldBe` | ||
233 | Right (PeerAddr (Just "01234567890123456789") | ||
234 | (IPv6 (toIPv6 [0, 0, 0, 0, 0, 0, 0, 1])) | ||
235 | 6881) | ||
236 | |||
237 | it "peer id is optional" $ do | ||
238 | BE.decode "d2:ip11:168.192.0.1\ | ||
239 | \4:porti6881e\ | ||
240 | \e" | ||
241 | `shouldBe` | ||
242 | Right (PeerAddr Nothing (IPv4 (toIPv4 [168, 192, 0, 1])) 6881) | ||
243 | |||
244 | it "has sock addr for both ipv4 and ipv6" $ do | ||
245 | show (peerSockAddr "128.0.0.1:80") `shouldBe` "128.0.0.1:80" | ||
246 | show (peerSockAddr "[::1]:8080" ) `shouldBe` "[::1]:8080" | ||
247 | |||
248 | describe "NodeId" $ do | ||
249 | it "properly serialized" $ do | ||
250 | S.decode "mnopqrstuvwxyz123456" | ||
251 | `shouldBe` Right ("mnopqrstuvwxyz123456" :: NodeId) | ||
252 | |||
253 | S.encode ("mnopqrstuvwxyz123456" :: NodeId) | ||
254 | `shouldBe` "mnopqrstuvwxyz123456" | ||
255 | |||
256 | it "properly serialized (iso)" $ property $ \ nid -> | ||
257 | S.decode (S.encode nid) `shouldBe` | ||
258 | Right (nid :: NodeId) | ||
259 | |||
260 | describe "NodeAddr" $ do | ||
261 | it "properly serialized" $ do | ||
262 | S.decode "\127\0\0\1\1\2" `shouldBe` | ||
263 | Right ("127.0.0.1:258" :: NodeAddr IPv4) | ||
264 | |||
265 | it "properly serialized (iso)" $ property $ \ nid -> | ||
266 | S.decode (S.encode nid) `shouldBe` | ||
267 | Right (nid :: NodeAddr IPv4) | ||
268 | |||
269 | describe "NodeInfo" $ do | ||
270 | it "properly serialized" $ do | ||
271 | S.decode "mnopqrstuvwxyz123456\ | ||
272 | \\127\0\0\1\1\2" `shouldBe` Right | ||
273 | (NodeInfo "mnopqrstuvwxyz123456" "127.0.0.1:258" :: NodeInfo IPv4) | ||
274 | |||
275 | it "properly serialized (iso)" $ property $ \ nid -> | ||
276 | S.decode (S.encode nid) `shouldBe` | ||
277 | Right (nid :: NodeInfo IPv4) | ||
278 | |||
279 | -- see <http://bittorrent.org/beps/bep_0020.html> | ||
280 | describe "Fingerprint" $ do | ||
281 | it "decode mainline encoded peer id" $ do | ||
282 | fingerprint "M4-3-6--xxxxxxxxxxxx" `shouldBe` "Mainline-4.3.6" | ||
283 | fingerprint "M4-20-8-xxxxxxxxxxxx" `shouldBe` "Mainline-4.20.8" | ||
284 | |||
285 | it "decode azureus encoded peer id" $ do | ||
286 | fingerprint "-AZ2060-xxxxxxxxxxxx" `shouldBe` "Azureus-2060" | ||
287 | fingerprint "-BS0000-xxxxxxxxxxxx" `shouldBe` "BTSlave-0" | ||
288 | |||
289 | it "decode Shad0w style peer id" $ do | ||
290 | fingerprint "S58B-----xxxxxxxxxxx" `shouldBe` "Shadow-5.8.11" | ||
291 | fingerprint "T58B-----xxxxxxxxxxx" `shouldBe` "BitTornado-5.8.11" | ||
292 | |||
293 | it "decode bitcomet style peer id" $ do | ||
294 | fingerprint "exbc01xxxxxxxxxxxxxx" `shouldBe` "BitComet-48.49" | ||
295 | fingerprint "FUTB01xxxxxxxxxxxxxx" `shouldBe` "BitComet-48.49" | ||
296 | fingerprint "exbc01LORDxxxxxxxxxx" `shouldBe` "BitLord-48.49" | ||
297 | |||
298 | it "decode opera style peer id" $ do | ||
299 | fingerprint "OP0123xxxxxxxxxxxxxx" `shouldBe` "Opera-123" | ||
300 | |||
301 | it "decode ML donkey style peer id" $ do | ||
302 | fingerprint "-ML2.7.2-xxxxxxxxxxx" `shouldBe` "MLdonkey-0" | ||
303 | |||
304 | -- TODO XBT, Bits on Wheels, Queen Bee, BitTyrant, TorrenTopia, | ||
305 | -- BitSpirit, Rufus, G3 Torrent, FlashGet \ No newline at end of file | ||