diff options
Diffstat (limited to 'bittorrent/tests/Network/BitTorrent/DHT/RoutingSpec.hs')
-rw-r--r-- | bittorrent/tests/Network/BitTorrent/DHT/RoutingSpec.hs | 77 |
1 files changed, 77 insertions, 0 deletions
diff --git a/bittorrent/tests/Network/BitTorrent/DHT/RoutingSpec.hs b/bittorrent/tests/Network/BitTorrent/DHT/RoutingSpec.hs new file mode 100644 index 00000000..07a906ba --- /dev/null +++ b/bittorrent/tests/Network/BitTorrent/DHT/RoutingSpec.hs | |||
@@ -0,0 +1,77 @@ | |||
1 | {-# LANGUAGE ScopedTypeVariables #-} | ||
2 | {-# LANGUAGE FlexibleContexts #-} | ||
3 | module Network.BitTorrent.DHT.RoutingSpec (spec) where | ||
4 | import Control.Applicative | ||
5 | import Control.Monad.State | ||
6 | import Data.Default | ||
7 | import Data.List as L | ||
8 | import Data.Maybe | ||
9 | import Test.Hspec | ||
10 | import Test.QuickCheck | ||
11 | |||
12 | import Network.BitTorrent.Address | ||
13 | import Network.BitTorrent.DHT.Routing as T | ||
14 | |||
15 | import Network.BitTorrent.CoreSpec hiding (spec) | ||
16 | |||
17 | |||
18 | type Network ip = [NodeAddr ip] | ||
19 | |||
20 | data Env ip = Env | ||
21 | { currentTime :: Timestamp | ||
22 | , network :: Network ip | ||
23 | } deriving Show | ||
24 | |||
25 | type Simulation ip = State (Env ip) | ||
26 | |||
27 | runSimulation :: Eq ip => Env ip -> Routing ip a -> Maybe a | ||
28 | runSimulation e m = evalState (runRouting ping closest timestamp m) e | ||
29 | where | ||
30 | ping addr = gets (L.elem addr . network) | ||
31 | closest nid = error "runSimulation" | ||
32 | timestamp = gets currentTime | ||
33 | |||
34 | instance Arbitrary ip => Arbitrary (Env ip) where | ||
35 | arbitrary = Env <$> arbitrary <*> (vector nodeCount) | ||
36 | where | ||
37 | nodeCount = 1000 | ||
38 | |||
39 | instance (Arbitrary ip, Eq ip) => Arbitrary (Table ip) where | ||
40 | arbitrary = do | ||
41 | thisId <- arbitrary | ||
42 | bucketN <- choose (1, 20) | ||
43 | let table = nullTable thisId bucketN | ||
44 | |||
45 | -- nodeN <- (`mod` bucketN) <$> arbitrary | ||
46 | -- nodes <- vector nodeN | ||
47 | |||
48 | node <- arbitrary | ||
49 | mt <- do | ||
50 | env <- arbitrary | ||
51 | return $ runSimulation env $ do | ||
52 | (_,t') <- T.insert (currentTime env) (TryInsert node) table | ||
53 | return t' :: Routing ip (Table ip) | ||
54 | --(foldM (flip fillTable) table nodes) | ||
55 | return (fromJust mt) | ||
56 | -- where | ||
57 | -- fillTable x t = do | ||
58 | -- t' <- T.insert x t | ||
59 | -- return $ if T.full t' then t else t' | ||
60 | |||
61 | spec :: Spec | ||
62 | spec = do | ||
63 | describe "size" $ do | ||
64 | it "null table is empty" $ do | ||
65 | T.size (nullTable def 2 :: Table IPv4) `shouldBe` 0 | ||
66 | |||
67 | it "the same node never appear in different buckets" $ property $ \ t -> do | ||
68 | let xss = T.toList (t :: Table Int) | ||
69 | let justOnce x = L.length (L.filter (L.elem x) xss) == 1 | ||
70 | L.all justOnce (L.concat xss) | ||
71 | |||
72 | it "insert is idemponent" $ property $ \ (e :: Env Int) n t -> do | ||
73 | let ins :: NodeInfo Int -> Table Int -> Routing Int (Table Int) | ||
74 | ins n t = snd <$> T.insert (currentTime e) (TryInsert n) t | ||
75 | let t1 = runSimulation e (ins n t) | ||
76 | let t2 = runSimulation e (ins n t >>= ins n) | ||
77 | t1 `shouldBe` t2 | ||