packages feed

http2-1.3.1: test/HTTP2/PrioritySpec.hs

{-# 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]

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)