packages feed

capataz-0.2.0.0: test/testsuite/Control/Concurrent/Capataz/SupervisorTest.hs

{-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE NoImplicitPrelude     #-}
{-# LANGUAGE OverloadedStrings     #-}
module Control.Concurrent.Capataz.SupervisorTest where

import RIO

import           Control.Concurrent.Capataz (set)
import qualified Control.Concurrent.Capataz as SUT
import           Test.Util

import Test.Tasty       (TestTree, testGroup)
import Test.Tasty.HUnit (testCase)

tests :: TestTree
tests = testGroup
  "supervision trees"
  [ testCase "initialize and teardown of supervision tree works as expected"
    $ testCapatazStreamWithOptions
        (& set
          SUT.supervisorProcessSpecListL
          [ SUT.supervisorSpec
            "tree-1"
            (set
              SUT.supervisorProcessSpecListL
              [ SUT.workerSpecWithDefaults "1-A"
                                           (forever $ threadDelay 10001000)
              , SUT.workerSpecWithDefaults "1-B"
                                           (forever $ threadDelay 10001000)
              ]
            )
          , SUT.supervisorSpec
            "tree-2"
            (set
              SUT.supervisorProcessSpecListL
              [ SUT.workerSpecWithDefaults "2-A"
                                           (forever $ threadDelay 10001000)
              , SUT.workerSpecWithDefaults "2-B"
                                           (forever $ threadDelay 10001000)
              ]
            )
          ]
        )
        [ andP [assertSupervisorName "tree-1", assertWorkerStarted "1-A"]
        , andP [assertSupervisorName "tree-1", assertWorkerStarted "1-B"]
        , andP
          [ assertSupervisorName "tree-1"
          , assertEventType SupervisorStatusChanged
          , assertSupervisorStatusChanged SUT.Initializing SUT.Running
          ]
        , andP [assertSupervisorName "tree-2", assertWorkerStarted "2-A"]
        , andP [assertSupervisorName "tree-2", assertWorkerStarted "2-B"]
        , andP
          [ assertSupervisorName "tree-2"
          , assertEventType SupervisorStatusChanged
          , assertSupervisorStatusChanged SUT.Initializing SUT.Running
          ]
        , andP
          [ assertRootSupervisor
          , assertEventType SupervisorStatusChanged
          , assertSupervisorStatusChanged SUT.Initializing SUT.Running
          ]
        ]
        (const $ return ())
        []
        [ andP
          [ assertRootSupervisor
          , assertEventType SupervisorStatusChanged
          , assertSupervisorStatusChanged SUT.Running SUT.Halting
          ]
        , andP [assertRootSupervisor, assertEventType ProcessTerminationStarted]
        , andP [assertSupervisorName "tree-1", assertWorkerTerminated "1-A"]
        , andP [assertSupervisorName "tree-1", assertWorkerTerminated "1-B"]
        , andP [assertSupervisorName "tree-2", assertWorkerTerminated "2-A"]
        , andP [assertSupervisorName "tree-2", assertWorkerTerminated "2-B"]
        , andP
          [assertRootSupervisor, assertEventType ProcessTerminationFinished]
        , andP
          [ assertRootSupervisor
          , assertEventType SupervisorStatusChanged
          , assertSupervisorStatusChanged SUT.Halting SUT.Halted
          ]
        ]
        Nothing
  , testCase "supervision sub-tree gets restarted on failure" $ do
    failingAction <- mkFailingSubRoutine 2
    testCapatazStreamWithOptions
      (set SUT.supervisorIntensityL 3 . set
        SUT.supervisorProcessSpecListL
        [ SUT.supervisorSpec
            "tree-1"
            ( set SUT.supervisorIntensityL     1
            . set SUT.supervisorPeriodSecondsL 10
            . set
                SUT.supervisorProcessSpecListL
                [SUT.workerSpecWithDefaults "failing-worker" failingAction]
            )
        ]
      )
      []
      (const $ threadDelay 1000)
      [ assertWorkerFailed "failing-worker"
      , assertSupervisorFailed "tree-1"
      , assertWorkerStarted "failing-worker"
      , assertSupervisorRestarted "tree-1"
      ]
      []
      Nothing
  , testCase "AllForOne strategy restarts sibling supervision tree" $ do
    failingAction <- mkFailingSubRoutine 2
    testCapatazStreamWithOptions
      ( set SUT.supervisorIntensityL       3
      . set SUT.supervisorRestartStrategyL SUT.AllForOne
      . set
          SUT.supervisorProcessSpecListL
          [ SUT.supervisorSpec
            "tree-1"
            ( set SUT.supervisorIntensityL     1
            . set SUT.supervisorPeriodSecondsL 10
            . set
                SUT.supervisorProcessSpecListL
                [SUT.workerSpecWithDefaults "failing-worker" failingAction]
            )
          , SUT.supervisorSpec
            "tree-2"
            (set
              SUT.supervisorProcessSpecListL
              [ SUT.workerSpec "stable-worker"
                               (forever $ threadDelay 1000100)
                               id
              ]
            )
          ]
      )
      []
      (const $ threadDelay 9000)
      [ assertWorkerFailed "failing-worker"
      , assertWorkerStarted "stable-worker"
      , assertSupervisorFailed "tree-1"
      , assertSupervisorRestarted "tree-1"
      , assertSupervisorTerminated "tree-2"
      , assertWorkerStarted "stable-worker"
      , assertSupervisorRestarted "tree-2"
      ]
      []
      Nothing
  ]