packages feed

quic-0.3.12: test/ResetSpec.hs

{-# LANGUAGE OverloadedStrings #-}

module ResetSpec where

import Data.Bits ((.&.))
import qualified Data.ByteString as BS
import Data.List (nub)
import Test.Hspec

import Network.QUIC.Internal

spec :: Spec
spec = describe "a stateless reset" $ do
    it "has the two bits RFC 9000 fixes at 01" $ do
        flags <- mapM (const firstByte) [1 .. 200 :: Int]
        -- Header form 0 and the QUIC Bit set.  A peer that has not asked for
        -- that bit to be greased discards anything else before it looks for a
        -- token, and we are answering a packet we have no connection for, so
        -- whether it asked is what we cannot know.
        all (\w -> w .&. 0xc0 == 0x40) flags `shouldBe` True
    it "does not always send the same bits" $ do
        flags <- mapM (const firstByte) [1 .. 200 :: Int]
        length (nub flags) `shouldSatisfy` (> 1)
    it "is read as a short header packet by a peer that greases nothing" $ do
        -- Fifty of them: with one random bit wrong, one reset gets through
        -- half the time.  True here is the peer refusing a cleared QUIC Bit,
        -- which is what a peer that has not asked for greasing does.
        bss <- mapM (const $ makeStatelessReset token) [1 .. 50 :: Int]
        pkts <- concat <$> mapM (`decodePackets` True) bss
        filter broken pkts `shouldBe` []
    it "is 1280 octets, under three times the 428 it answers" $ do
        bs <- makeStatelessReset token
        BS.length bs `shouldBe` 1280
        BS.length bs `shouldSatisfy` (< 3 * 428)
    it "ends with the token" $ do
        bs <- makeStatelessReset token
        BS.drop (BS.length bs - 16) bs `shouldBe` fromStatelessResetToken token
  where
    firstByte = BS.head <$> makeStatelessReset token
    token = StatelessResetToken "0123456789abcdef"
    broken (PacketIB BrokenPacket _) = True
    broken _ = False