{-# LANGUAGE BangPatterns, CPP #-} module HTTP2.PrioritySpec where #if __GLASGOW_HASKELL__ < 709 import Control.Applicative #endif import Data.List (group, sort) import Test.Hspec import Network.HTTP2.Priority import qualified Network.HTTP2.Priority.PSQ as P import Network.HTTP2.Types spec :: Spec spec = do describe "priority tree" $ do it "enqueue and dequeue frames from Firefox properly" $ firefox describe "base priority queue" $ do it "queues entries based on weight" $ do let q = P.enqueue 5 (P.newPrecedence 1) 5 $ P.enqueue 3 (P.newPrecedence 101) 3 $ P.enqueue 1 (P.newPrecedence 201) 1 P.empty xs = enqdeq q 1000 map length (group (sort xs)) `shouldBe` [664,333,3] it "deletes properly" $ do let q = P.enqueue 7 (P.newPrecedence 1) 7 $ P.enqueue 5 (P.newPrecedence 5) 5 $ P.enqueue 3 (P.newPrecedence 50) 3 $ P.enqueue 1 (P.newPrecedence 201) (1 :: Int) P.empty let Just (k1,_,_,q1) = P.dequeue q k1 `shouldBe` 1 let (mk, q2) = P.delete 5 q1 mk `shouldBe` Just 5 let Just (k3,_,_,q3) = P.dequeue q2 k3 `shouldBe` 3 let Just (k4,_,_,_) = P.dequeue q3 k4 `shouldBe` 7 it "deletes entries properly" $ do let q = P.enqueue 5 (P.newPrecedence 1) 5 $ P.enqueue 3 (P.newPrecedence 101) 3 $ P.enqueue 1 (P.newPrecedence 201) 1 P.empty (mv1,q1) = P.delete 1 q (mv2,q2) = P.delete 3 q P.baseDeficit q `shouldBe` 0 mv1 `shouldBe` Just (1 :: Int) P.baseDeficit q1 `shouldBe` 326 mv2 `shouldBe` Just 3 P.baseDeficit q2 `shouldBe` 0 firefox :: IO () firefox = do pt <- newPriorityTree :: IO (PriorityTree Int) prepare pt 3 (pri 0 201) prepare pt 5 (pri 0 101) prepare pt 7 (pri 0 1) prepare pt 9 (pri 7 1) prepare pt 11 (pri 3 1) enQ pt 13 (pre 11 32) deQ pt `shouldReturn` 13 enQ pt 15 (pre 3 32) enQ pt 17 (pre 3 32) enQ pt 19 (pre 3 32) enQ pt 21 (pre 3 32) enQ pt 23 (pre 3 32) enQ pt 25 (pre 3 32) enQ pt 27 (pre 11 22) enQ pt 29 (pre 11 22) enQ pt 31 (pre 11 22) enQ pt 33 (pre 5 32) enQ pt 35 (pre 5 32) enQ pt 37 (pre 5 32) deQ pt `shouldReturn` 15 deQ pt `shouldReturn` 33 deQ pt `shouldReturn` 17 delete pt 17 (pre 3 32) `shouldReturn` Nothing delete pt 31 (pre 11 22) `shouldReturn` Just 31 deQ pt `shouldReturn` 19 deQ pt `shouldReturn` 35 deQ pt `shouldReturn` 21 deQ pt `shouldReturn` 23 deQ pt `shouldReturn` 37 deQ pt `shouldReturn` 25 deQ pt `shouldReturn` 27 deQ pt `shouldReturn` 29 enQ pt 39 (pre 3 32) deQ pt `shouldReturn` 39 enQ :: PriorityTree Int -> StreamId -> Precedence -> IO () enQ pt sid p = enqueue pt sid p sid deQ :: PriorityTree Int -> IO StreamId deQ pt = (\(x,_,_) -> x) <$> dequeue pt pri :: StreamId -> Weight -> Priority pri dep w = Priority False dep w pre :: StreamId -> Weight -> Precedence pre dep w = toPrecedence $ pri dep w enqdeq :: P.PriorityQueue Int -> Int -> [Int] enqdeq pq num = loop pq num [] where loop _ 0 ks = ks loop !q !n ks = case P.dequeue q of Nothing -> error "enqdeq" Just (k,p,v,q') -> loop (P.enqueue k p v q') (n - 1) (k:ks)