diff options
Diffstat (limited to 'bittorrent/tests/Network/BitTorrent/Tracker/RPC')
-rw-r--r-- | bittorrent/tests/Network/BitTorrent/Tracker/RPC/HTTPSpec.hs | 95 | ||||
-rw-r--r-- | bittorrent/tests/Network/BitTorrent/Tracker/RPC/UDPSpec.hs | 144 |
2 files changed, 239 insertions, 0 deletions
diff --git a/bittorrent/tests/Network/BitTorrent/Tracker/RPC/HTTPSpec.hs b/bittorrent/tests/Network/BitTorrent/Tracker/RPC/HTTPSpec.hs new file mode 100644 index 00000000..e928f917 --- /dev/null +++ b/bittorrent/tests/Network/BitTorrent/Tracker/RPC/HTTPSpec.hs | |||
@@ -0,0 +1,95 @@ | |||
1 | {-# LANGUAGE RecordWildCards #-} | ||
2 | module Network.BitTorrent.Tracker.RPC.HTTPSpec (spec) where | ||
3 | import Control.Monad | ||
4 | import Data.Default | ||
5 | import Data.List as L | ||
6 | import Test.Hspec | ||
7 | |||
8 | import Network.BitTorrent.Internal.Progress | ||
9 | import Network.BitTorrent.Tracker.Message as Message | ||
10 | import Network.BitTorrent.Tracker.RPC.HTTP | ||
11 | |||
12 | import Network.BitTorrent.Tracker.TestData | ||
13 | import Network.BitTorrent.Tracker.MessageSpec hiding (spec) | ||
14 | |||
15 | |||
16 | validateInfo :: AnnounceQuery -> AnnounceInfo -> Expectation | ||
17 | validateInfo _ (Message.Failure reason) = do | ||
18 | error $ "validateInfo: " ++ show reason | ||
19 | validateInfo AnnounceQuery {..} AnnounceInfo {..} = do | ||
20 | return () | ||
21 | -- case respComplete <|> respIncomplete of | ||
22 | -- Nothing -> return () | ||
23 | -- Just n -> n `shouldBe` L.length (getPeerList respPeers) | ||
24 | |||
25 | isUnrecognizedScheme :: RpcException -> Bool | ||
26 | isUnrecognizedScheme (RequestFailed _) = True | ||
27 | isUnrecognizedScheme _ = False | ||
28 | |||
29 | isNotResponding :: RpcException -> Bool | ||
30 | isNotResponding (RequestFailed _) = True | ||
31 | isNotResponding _ = False | ||
32 | |||
33 | spec :: Spec | ||
34 | spec = parallel $ do | ||
35 | describe "Manager" $ do | ||
36 | describe "newManager" $ do | ||
37 | it "" $ pending | ||
38 | |||
39 | describe "closeManager" $ do | ||
40 | it "" $ pending | ||
41 | |||
42 | describe "withManager" $ do | ||
43 | it "" $ pending | ||
44 | |||
45 | describe "RPC" $ do | ||
46 | describe "announce" $ do | ||
47 | it "must fail on bad uri scheme" $ do | ||
48 | withManager def $ \ mgr -> do | ||
49 | q <- arbitrarySample | ||
50 | announce mgr "magnet://foo.bar" q | ||
51 | `shouldThrow` isUnrecognizedScheme | ||
52 | |||
53 | describe "scrape" $ do | ||
54 | it "must fail on bad uri scheme" $ do | ||
55 | withManager def $ \ mgr -> do | ||
56 | scrape mgr "magnet://foo.bar" [] | ||
57 | `shouldThrow` isUnrecognizedScheme | ||
58 | |||
59 | forM_ (L.filter isHttpTracker trackers) $ \ TrackerEntry {..} -> | ||
60 | context trackerName $ do | ||
61 | |||
62 | describe "announce" $ do | ||
63 | if tryAnnounce | ||
64 | then do | ||
65 | it "have valid response" $ do | ||
66 | withManager def $ \ mgr -> do | ||
67 | -- q <- arbitrarySample | ||
68 | let ih = maybe def L.head hashList | ||
69 | let q = AnnounceQuery ih "-HS0003-203534.37420" 6000 | ||
70 | (Progress 0 0 0) Nothing Nothing (Just Started) | ||
71 | info <- announce mgr trackerURI q | ||
72 | validateInfo q info | ||
73 | else do | ||
74 | it "should fail with RequestFailed" $ do | ||
75 | withManager def $ \ mgr -> do | ||
76 | q <- arbitrarySample | ||
77 | announce mgr trackerURI q | ||
78 | `shouldThrow` isNotResponding | ||
79 | |||
80 | describe "scrape" $ do | ||
81 | if tryScraping | ||
82 | then do | ||
83 | it "have valid response" $ do | ||
84 | withManager def $ \ mgr -> do | ||
85 | xs <- scrape mgr trackerURI [def] | ||
86 | L.length xs `shouldSatisfy` (>= 1) | ||
87 | else do | ||
88 | it "should fail with ScrapelessTracker" $ do | ||
89 | pending | ||
90 | |||
91 | when (not tryAnnounce) $ do | ||
92 | it "should fail with RequestFailed" $ do | ||
93 | withManager def $ \ mgr -> do | ||
94 | scrape mgr trackerURI [def] | ||
95 | `shouldThrow` isNotResponding | ||
diff --git a/bittorrent/tests/Network/BitTorrent/Tracker/RPC/UDPSpec.hs b/bittorrent/tests/Network/BitTorrent/Tracker/RPC/UDPSpec.hs new file mode 100644 index 00000000..73acb3fa --- /dev/null +++ b/bittorrent/tests/Network/BitTorrent/Tracker/RPC/UDPSpec.hs | |||
@@ -0,0 +1,144 @@ | |||
1 | {-# LANGUAGE RecordWildCards #-} | ||
2 | module Network.BitTorrent.Tracker.RPC.UDPSpec (spec, rpcOpts) where | ||
3 | import Control.Concurrent | ||
4 | import Control.Concurrent.Async | ||
5 | import Control.Exception | ||
6 | import Control.Monad | ||
7 | import Data.Default | ||
8 | import Data.List as L | ||
9 | import Data.Maybe | ||
10 | import Test.Hspec | ||
11 | |||
12 | import Network.BitTorrent.Address | ||
13 | import Network.BitTorrent.Tracker.Message as Message | ||
14 | |||
15 | import Network.BitTorrent.Tracker.TestData | ||
16 | import Network.BitTorrent.Tracker.MessageSpec hiding (spec) | ||
17 | import Network.BitTorrent.Tracker.RPC.UDP | ||
18 | |||
19 | |||
20 | validateInfo :: AnnounceQuery -> AnnounceInfo -> Expectation | ||
21 | validateInfo _ Message.Failure {} = error "validateInfo: failure" | ||
22 | validateInfo AnnounceQuery {..} AnnounceInfo {..} = do | ||
23 | respComplete `shouldSatisfy` isJust | ||
24 | respIncomplete `shouldSatisfy` isJust | ||
25 | respMinInterval `shouldSatisfy` isNothing | ||
26 | respWarning `shouldSatisfy` isNothing | ||
27 | peerList `shouldSatisfy` L.all (isNothing . peerId) | ||
28 | where | ||
29 | peerList = getPeerList respPeers | ||
30 | |||
31 | -- | Number of concurrent calls. | ||
32 | rpcCount :: Int | ||
33 | rpcCount = 100 | ||
34 | |||
35 | rpcOpts :: Options | ||
36 | rpcOpts = def | ||
37 | { optMinTimeout = 1 | ||
38 | , optMaxTimeout = 10 | ||
39 | } | ||
40 | |||
41 | isTimeoutExpired :: RpcException -> Bool | ||
42 | isTimeoutExpired (TimeoutExpired _) = True | ||
43 | isTimeoutExpired _ = False | ||
44 | |||
45 | isSomeException :: SomeException -> Bool | ||
46 | isSomeException _ = True | ||
47 | |||
48 | isIOException :: IOException -> Bool | ||
49 | isIOException _ = True | ||
50 | |||
51 | spec :: Spec | ||
52 | spec = parallel $ do | ||
53 | describe "newManager" $ do | ||
54 | it "should throw exception on zero optMaxPacketSize" $ do | ||
55 | let opts = def { optMaxPacketSize = 0 } | ||
56 | newManager opts `shouldThrow` isSomeException | ||
57 | |||
58 | it "should throw exception on zero optMinTimout" $ do | ||
59 | let opts = def { optMinTimeout = 0 } | ||
60 | newManager opts `shouldThrow` isSomeException | ||
61 | |||
62 | it "should throw exception on zero optMaxTimeout" $ do | ||
63 | let opts = def { optMaxTimeout = 0 } | ||
64 | newManager opts `shouldThrow` isSomeException | ||
65 | |||
66 | it "should throw exception on maxTimeout < minTimeout" $ do | ||
67 | let opts = def { optMinTimeout = 2, optMaxTimeout = 1 } | ||
68 | newManager opts `shouldThrow` isSomeException | ||
69 | |||
70 | it "should throw exception on zero optMultiplier" $ do | ||
71 | let opts = def { optMultiplier = 0 } | ||
72 | newManager opts `shouldThrow` isSomeException | ||
73 | |||
74 | describe "closeManager" $ do | ||
75 | it "unblock rpc calls" $ do | ||
76 | mgr <- newManager rpcOpts | ||
77 | _ <- forkIO $ do | ||
78 | threadDelay 10000000 | ||
79 | closeManager mgr | ||
80 | q <- arbitrarySample | ||
81 | announce mgr (trackerURI badTracker) q `shouldThrow` (== ManagerClosed) | ||
82 | |||
83 | it "announce throw exception after manager closed" $ do | ||
84 | mgr <- newManager rpcOpts | ||
85 | closeManager mgr | ||
86 | q <- arbitrarySample | ||
87 | announce mgr (trackerURI badTracker) q `shouldThrow` isIOException | ||
88 | |||
89 | it "scrape throw exception after manager closed" $ do | ||
90 | mgr <- newManager rpcOpts | ||
91 | closeManager mgr | ||
92 | scrape mgr (trackerURI badTracker) [def] `shouldThrow` isIOException | ||
93 | |||
94 | describe "withManager" $ do | ||
95 | it "closesManager at exit" $ do | ||
96 | mgr <- withManager rpcOpts return | ||
97 | scrape mgr (trackerURI badTracker) [def] `shouldThrow` isSomeException | ||
98 | |||
99 | describe "RPC" $ do | ||
100 | describe "announce" $ do | ||
101 | it "must fail on bad scheme" $ do | ||
102 | withManager rpcOpts $ \ mgr -> do | ||
103 | q <- arbitrarySample | ||
104 | announce mgr "magnet://a.com" q | ||
105 | `shouldThrow` (== UnrecognizedScheme "magnet:") | ||
106 | |||
107 | describe "scrape" $ do | ||
108 | it "must fail on bad scheme" $ do | ||
109 | withManager rpcOpts $ \ mgr -> do | ||
110 | scrape mgr "magnet://a.com" [] | ||
111 | `shouldThrow` (== UnrecognizedScheme "magnet:") | ||
112 | |||
113 | forM_ (L.filter isUdpTracker trackers) $ \ TrackerEntry {..} -> | ||
114 | context trackerName $ do | ||
115 | |||
116 | describe "announce" $ do | ||
117 | if tryAnnounce then do | ||
118 | it "have valid response" $ do | ||
119 | withManager rpcOpts $ \ mgr -> do | ||
120 | q <- arbitrarySample | ||
121 | announce mgr trackerURI q >>= validateInfo q | ||
122 | else do | ||
123 | it "should throw TimeoutExpired" $ do | ||
124 | withManager rpcOpts $ \ mgr -> do | ||
125 | q <- arbitrarySample | ||
126 | announce mgr trackerURI q `shouldThrow` isTimeoutExpired | ||
127 | |||
128 | describe "scrape" $ do | ||
129 | if tryScraping then do | ||
130 | it "have valid response" $ do | ||
131 | withManager rpcOpts $ \ mgr -> do | ||
132 | xs <- scrape mgr trackerURI [def] | ||
133 | L.length xs `shouldSatisfy` (>= 1) | ||
134 | else do | ||
135 | it "should throw TimeoutExpired" $ do | ||
136 | withManager rpcOpts $ \ mgr -> do | ||
137 | scrape mgr trackerURI [def] `shouldThrow` isTimeoutExpired | ||
138 | |||
139 | describe "Manager" $ do | ||
140 | when tryScraping $ do | ||
141 | it "should handle arbitrary intermixed concurrent queries" $ do | ||
142 | withManager rpcOpts $ \ mgr -> do | ||
143 | _ <- mapConcurrently (\ _ -> scrape mgr trackerURI [def]) [1..rpcCount] | ||
144 | return () | ||