pcapng-0.1.0.0: test/Spec.hs
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE ScopedTypeVariables #-}
import Control.Lens ((^.))
import Control.Monad (forM, forM_)
import Control.Monad.IO.Class
import Control.Monad.Trans.Resource
import Data.Conduit
import Data.Conduit.Cereal (sinkGet)
import qualified Data.Conduit.Combinators as C (head, sourceFile)
import Data.Conduit.List (consume)
import Data.List (isPrefixOf)
import Data.Serialize (get)
import System.Directory
import System.FilePath.Posix (takeExtension, takeFileName,
(</>))
import System.IO (hPutStrLn, stderr)
import Test.Hspec
import Test.Hspec.Core.Runner
import Test.QuickCheck
import qualified Data.WordString32.Conduit as WSC
import Network.Pcap.NG.Block
import Network.Pcap.NG.BlockType
import qualified Test.Data.WordString32 (spec)
import qualified Test.Network.Pcap.NG.BlockType (spec)
import qualified Test.Network.Pcap.NG.Endianness (spec)
import qualified Test.Network.Pcap.NG.Options (spec)
main :: IO ()
main = hspecWith config spec
where
config = defaultConfig {
configColorMode = ColorAlways
, configFailureReport = Just "failure.log"
, configDiff = True
}
filesWithExts :: FilePath -- ^ Directory to search
-> [String ]-- ^ Extensions list
-> IO [FilePath]
filesWithExts dirName exts =
map (dirName </>) . filter matchExt <$> getDirectoryContents dirName
where
matchExt = (`elem` exts)
. takeExtension
consumeBlock :: MonadIO m => ConduitT Block Void m ()
consumeBlock = awaitForever
$ liftIO . hPutStrLn stderr . show . (^. blockType)
testPcapFile :: FilePath -> Spec
testPcapFile filename =
it filename $ do
parse filename >>= (`shouldMatchList` [])
testPcapFileSections :: FilePath -> [BlockType] -> Spec
testPcapFileSections filename bts =
it filename $
parse filename >>= (`shouldMatchList` bts)
testPcapFilePrefixAndCount :: FilePath -> [BlockType] -> Int -> Spec
testPcapFilePrefixAndCount filename prefix count = do
describe filename $ do
it (filename <> " has correct prefix") $ do
actualBts <- parse filename
actualBts `shouldSatisfy` (isPrefixOf prefix)
it (filename <> "has correct number of packets") $ do
actualBts <- parse filename
length actualBts `shouldBe` count
blockTypes = awaitForever $ \block -> do
liftIO $ print $ block ^. blockType
yield (block ^. blockType)
parse filename = runConduitRes
$ WSC.sourceFile filename .| blockConduit .| blockTypes .| consume
{-
parse :: FilePath -> IO ()
parse filename = runConduitRes
$ WSC.sourceFile filename .| pcapNgConduit2 .| consumeBlock
-}
testPcapFileHeader :: FilePath -> Spec
testPcapFileHeader filename =
it filename $
parseHeader filename `shouldReturn` SectionHeader
parseHeader filename = do
header :: Maybe Block <- runConduitRes
$ WSC.sourceFile filename .| blockConduit .| C.head
case header of
Just h -> do
print $ h ^. blockType
return $ h ^. blockType
Nothing -> error "No blocktype here!"
spec = do
describe "Network.Pcap.NG.BlockType" $
Test.Network.Pcap.NG.BlockType.spec
describe "Network.Pcap.NG.Options" $
Test.Network.Pcap.NG.Options.spec
describe "Data.WordString32" $
Test.Data.WordString32.spec
describe "Block recognition" $ do
return ()
describe "Undifferentiated blocks" $ do
describe "Pcap.org examples" $ do
files <- runIO $ filesWithExts "test/pcapng.org" [".ntar", ".pcapng"]
runIO $ putStrLn $ "Test files found: " <> show files
describe "parse first block" $
forM_ files testPcapFileHeader
describe "parse all blocks" $ do
testPcapFileSections "test/pcapng.org/dhcp.pcapng" $
[SectionHeader, IfDesc, EnhancedPacket, EnhancedPacket, EnhancedPacket, EnhancedPacket]
testPcapFilePrefixAndCount "test/pcapng.org/pcap-ng_Wi-Fi_Bluetooth_USB_Cooked_timestamps_issue_1.ntar"
[SectionHeader,IfDesc,EnhancedPacket] 224
testPcapFileSections "test/pcapng.org/dhcp_big_endian.pcapng" $
[SectionHeader, IfDesc, NameResolution] <> replicate 4 EnhancedPacket
testPcapFileSections "test/pcapng.org/dhcp_little_endian.pcapng" $
[SectionHeader, IfDesc, NameResolution] <> replicate 4 EnhancedPacket
testPcapFileSections "test/pcapng.org/many_interfaces.pcapng" $
[SectionHeader] <> replicate 11 IfDesc
<> replicate 64 EnhancedPacket
<> [NameResolution]
<> replicate 11 IfStats
xdescribe "Failing tests" $ do
testPcapFileSections "test/pcapng.org/http.bigendian.ntar" $
[]
testPcapFileSections "test/pcapng.org/icmp2.ntar" $
[]
describe "Wireshark examples" $ do
testPcapFileSections "test/wireshark/dhcp-nanosecond.pcapng" $
[SectionHeader, IfDesc] <> replicate 4 EnhancedPacket
testPcapFileSections "test/wireshark/dmgr.pcapng" $
[SectionHeader, IfDesc] <> replicate 42 EnhancedPacket
testPcapFileSections "test/wireshark/http2-brotli.pcapng" $
[SectionHeader, IfDesc, DecryptionSecrets] <> replicate 25 EnhancedPacket
testPcapFileSections "test/wireshark/ikev2-decrypt-aes256cbc.pcapng" $
[SectionHeader, IfDesc, IfDesc] <> replicate 4 EnhancedPacket <> [IfStats, IfStats]
testPcapFileSections "test/wireshark/packet-h2-14_headers.pcapng" $
[SectionHeader, IfDesc] <> replicate 15 EnhancedPacket <> [IfStats]
testPcapFileSections "test/wireshark/tls12-dsb.pcapng" $
[SectionHeader, IfDesc, DecryptionSecrets] <> replicate 9 EnhancedPacket
<> [DecryptionSecrets] <> replicate 8 EnhancedPacket
testPcapFileSections "test/wireshark/dhcp.pcapng" $ [SectionHeader, IfDesc] <> replicate 4 EnhancedPacket
testPcapFileSections "test/wireshark/dtls12-aes128ccm8-dsb.pcapng" $
[SectionHeader, IfDesc, DecryptionSecrets] <> replicate 13 EnhancedPacket
testPcapFileSections "test/wireshark/http-brotli.pcapng" $
[SectionHeader, IfDesc] <> replicate 10 EnhancedPacket <> [IfStats]
testPcapFileSections "test/wireshark/ikev2-decrypt-aes256ccm16.pcapng" $
[SectionHeader,IfDesc,IfDesc] <> replicate 4 EnhancedPacket <> replicate 2 IfStats
testPcapFileSections "test/wireshark/sip.pcapng" $ [SectionHeader,IfDesc] <> replicate 6 EnhancedPacket
testPcapFileSections "test/wireshark/wireguard-ping-tcp-dsb.pcapng" $
[SectionHeader, IfDesc, DecryptionSecrets] <> replicate 22 EnhancedPacket