Skip to content

Commit

Permalink
Added DNS Recoverability test
Browse files Browse the repository at this point in the history
  • Loading branch information
bolt12 committed Apr 14, 2022
1 parent a81e8b8 commit ddf4317
Showing 1 changed file with 90 additions and 4 deletions.
94 changes: 90 additions & 4 deletions ouroboros-network/test/Test/Ouroboros/Network/Testnet.hs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE BangPatterns #-}

module Test.Ouroboros.Network.Testnet (tests) where

Expand All @@ -26,6 +27,8 @@ import Data.Time (secondsToDiffTime)
import System.Random (mkStdGen)
import GHC.Exception.Type (SomeException)

import qualified Network.DNS.Types as DNS

import Ouroboros.Network.Testing.Data.AbsBearerInfo
(AbsBearerInfo (..), attenuation, delay, toSduSize)
import Ouroboros.Network.PeerSelection.Governor
Expand All @@ -34,7 +37,7 @@ import Ouroboros.Network.Testing.Data.Signal
(Events, Signal, eventsToList,
signalProperty)
import Ouroboros.Network.PeerSelection.RootPeersDNS
(TraceLocalRootPeers, TracePublicRootPeers)
(TraceLocalRootPeers (..), TracePublicRootPeers (..), dapDomain)
import Ouroboros.Network.PeerSelection.Types (PeerStatus(..))
import Ouroboros.Network.Driver.Limits (ProtocolTimeLimits(..))
import Ouroboros.Network.Diffusion.P2P
Expand All @@ -45,6 +48,8 @@ import qualified Ouroboros.Network.Testing.Data.Signal as Signal
import qualified Ouroboros.Network.PeerSelection.Governor as Governor
import qualified Ouroboros.Network.PeerSelection.LocalRootPeers as LocalRootPeers
import qualified Ouroboros.Network.PeerSelection.EstablishedPeers as EstablishedPeers
import Ouroboros.Network.PeerSelection.RootPeersDNS.DNSActions
(DNSorIOError(DNSError))
import Ouroboros.Network.Protocol.Handshake.Type
(ClientHasAgency(..), ServerHasAgency (..))
import qualified Ouroboros.Network.Diffusion.P2P as Diff.P2P
Expand Down Expand Up @@ -90,6 +95,8 @@ tests =
prop_diffusionScript_commandScript_valid
, testProperty "diffusion no livelock"
prop_diffusion_nolivelock
, testProperty "diffusion dns can recover from fails"
prop_diffusion_dns_can_recover
, testProperty "diffusion target established local"
prop_diffusion_target_established_local
, testProperty "diffusion target active below"
Expand Down Expand Up @@ -268,9 +275,88 @@ prop_diffusion_nolivelock defaultBearerInfo diffScript@(DiffusionScript l) =
| countdown threshold h = go t
| otherwise = Just h

countdown 0 (_ : _) = False
countdown _ [] = True
countdown n (_ : es) = countdown (n-1) es
countdown :: Int -> [(Time, e)] -> Bool
countdown 0 (_ : _) = False
countdown _ [] = True
countdown !n (_ : es) = countdown (n-1) es

-- | Test that verifies that that we can recover from DNS lookup failures.
--
-- This checks that if a node is configured with a local root peer through DNS,
-- and then the peer gets disconnected, the DNS lookup fails (so you can’t
-- reconnect). After a bit DNS lookup succeeds and you manage to connect again.
--
prop_diffusion_dns_can_recover :: AbsBearerInfo
-> DiffusionScript
-> Property
prop_diffusion_dns_can_recover defaultBearerInfo diffScript =
let sim :: forall s . IOSim s Void
sim = diffusionSimulation (toBearerInfo defaultBearerInfo)
diffScript
tracersExtraWithTimeName
tracerDiffusionSimWithTimeName

events :: [Events DiffusionTestTrace]
events = fmap ( Signal.eventsFromList
. fmap (\(WithName _ (WithTime t b)) -> (t, b))
)
. Trace.toList
. splitWithNameTrace
. Trace.fromList ()
. fmap snd
. Signal.eventsToList
. Signal.eventsFromListUpToTime (Time (10 * 60 * 60))
. Trace.toList
. fmap (\(WithTime t (WithName name b)) -> (t, WithName name (WithTime t b)))
. withTimeNameTraceEvents
@DiffusionTestTrace
@NtNAddr
$ runSimTrace sim

in conjoin
$ verify_dns_can_recover
<$> events

where
verify :: Set DNS.Domain
-> Int
-> [Either (Set DNS.Domain) (Set DNS.Domain)]
-> Property
verify toRecover recovered [] =
counterexample (show toRecover ++ " none of these DNS names recovered")
(Set.null toRecover || recovered > 0)
verify toRecover recovered (Left dns:t) =
verify (toRecover <> dns) recovered t
verify toRecover recovered (Right dns:t) =
if all (`Set.member` toRecover) dns
then verify (Set.foldl' (flip Set.delete) toRecover dns)
(recovered + 1)
t
else verify toRecover recovered t

verify_dns_can_recover :: Events DiffusionTestTrace -> Property
verify_dns_can_recover events =
-- The left case is for DNS lookup failures
-- The right case is for DNS lookup successes
let psDNSLookups :: Events (Either (Set DNS.Domain) (Set DNS.Domain))
psDNSLookups =
Signal.selectEvents
(\case
DiffusionLocalRootPeerTrace (TraceLocalRootFailure dap (DNSError _)) ->
Just (Left (Set.singleton (dapDomain dap)))
DiffusionPublicRootPeerTrace (TracePublicRootFailure bs _) ->
Just (Left (Set.singleton bs))
DiffusionLocalRootPeerTrace (TraceLocalRootResult dap _) ->
Just (Right (Set.singleton (dapDomain dap)))
DiffusionPublicRootPeerTrace (TracePublicRootResult bs _) ->
Just (Right (Set.singleton bs))
_ ->
Nothing
)
$ events

in counterexample (show psDNSLookups)
$ verify Set.empty 0 (map snd $ Signal.eventsToList psDNSLookups)

-- | A variant of
-- 'Test.Ouroboros.Network.PeerSelection.prop_governor_target_established_local'
Expand Down

0 comments on commit ddf4317

Please sign in to comment.