module Tests.IP4.Fragmentation where import Tests.IP4.Packet import Tests.Network import Hans.Config import Hans.IP4.Fragments import Hans.IP4.Packet import Hans.Monad (runHansOnce) import qualified Data.ByteString.Lazy as L import Data.Maybe (catMaybes) import Test.Tasty import Test.Tasty.QuickCheck (testProperty) import Test.QuickCheck import Test.QuickCheck.Monadic fragTests :: TestTree fragTests = testGroup "Fragmentation" [ testProperty "Reassembly" propReassemble ] propReassemble :: Property propReassemble = monadicIO $ do src <- pick arbitraryIP4 dst <- pick arbitraryIP4 prot <- pick arbitraryProtocol ident <- pick arbitraryIdent len <- pick (choose (100,1500)) -- path mtu must be at least 68 (28 for header, and 40 for options) mtu <- pick (choose (68,len)) bytes <- pick (arbitraryPayload len) let hdr = emptyIP4Header { ip4DestAddr = dst , ip4SourceAddr = src , ip4Protocol = prot , ip4Ident = ident } chunks = [(h,L.toStrict body) | (h,body) <- splitPacket mtu hdr bytes] incoming <- pick (shuffle chunks) table <- run (newFragTable defaultConfig) results <- run $ sequence [ runHansOnce (processFragment table fhdr body) | (fhdr,body) <- incoming ] run (cleanupFragTable table) -- we should only get a single successful result here, otherwise something -- is wrong with the way that fragments are being collected case catMaybes results of [(_,result)] -> return (L.fromStrict result == bytes) _ -> return False