cachix-1.7: test/Daemon/PushManagerSpec.hs
module Daemon.PushManagerSpec where
import qualified Cachix.Client.Daemon.Log as Log
import qualified Cachix.Client.Daemon.Protocol as Protocol
import Cachix.Client.Daemon.PushManager
import qualified Cachix.Client.Daemon.PushManager.PushJob as PushJob
import Cachix.Client.Daemon.Types.PushManager
import Cachix.Client.OptionsParser (defaultPushOptions)
import Control.Retry (defaultRetryStatus)
import qualified Data.Set as Set
import Data.Time (getCurrentTime)
import Protolude
import Test.Hspec
spec :: Spec
spec = do
describe "push job" $ do
it "starts in the queued state" $ do
let request = Protocol.PushRequest {Protocol.storePaths = ["foo", "bar"]}
pushJob <- PushJob.new request
PushJob.status pushJob `shouldBe` Queued
it "can be resolved" $ do
let request = Protocol.PushRequest {Protocol.storePaths = ["foo", "bar"]}
pathSet = Set.fromList ["foo", "bar"]
closure = PushJob.ResolvedClosure pathSet pathSet
initPushJob <- PushJob.new request
timestamp <- getCurrentTime
let pushJob = PushJob.populateQueue closure timestamp initPushJob
PushJob.status pushJob `shouldBe` Running
PushJob.queue pushJob `shouldBe` pathSet
PushJob.result pushJob `shouldBe` mempty
it "marks paths as pushed" $
do
let request = Protocol.PushRequest {Protocol.storePaths = ["foo", "bar"]}
pathSet = Set.fromList ["foo", "bar"]
closure = PushJob.ResolvedClosure pathSet pathSet
timestamp <- getCurrentTime
initPushJob <- PushJob.new request
let pushJob =
initPushJob
& PushJob.populateQueue closure timestamp
& PushJob.markStorePathPushed "foo"
PushJob.status pushJob `shouldBe` Running
PushJob.queue pushJob `shouldBe` Set.fromList ["bar"]
PushJob.result pushJob
`shouldBe` PushJob.PushResult
{ PushJob.prFailedPaths = mempty,
PushJob.prPushedPaths = Set.fromList ["foo"],
PushJob.prSkippedPaths = mempty
}
it "marks paths as failed" $
do
let request = Protocol.PushRequest {Protocol.storePaths = ["foo", "bar"]}
pathSet = Set.fromList ["foo", "bar"]
closure = PushJob.ResolvedClosure pathSet pathSet
timestamp <- getCurrentTime
initPushJob <- PushJob.new request
let pushJob =
initPushJob
& PushJob.populateQueue closure timestamp
& PushJob.markStorePathFailed "foo"
PushJob.status pushJob `shouldBe` Running
PushJob.queue pushJob `shouldBe` Set.fromList ["bar"]
PushJob.result pushJob
`shouldBe` PushJob.PushResult
{ PushJob.prFailedPaths = Set.fromList ["foo"],
PushJob.prPushedPaths = mempty,
PushJob.prSkippedPaths = mempty
}
describe "push manager" $ do
it "queues push jobs " $ inPushManager $ do
let request = Protocol.PushRequest {Protocol.storePaths = ["foo", "bar"]}
pushId <- addPushJob request
mpushJob <- lookupPushJob pushId
liftIO $ do
mpushJob `shouldSatisfy` isJust
for_ mpushJob $ \pushJob -> do
PushJob.pushId pushJob `shouldBe` pushId
PushJob.pushRequest pushJob `shouldBe` request
it "manages the lifecycle of a push job" $ inPushManager $ do
let paths = ["bar", "foo"]
let pushRequest = Protocol.PushRequest {Protocol.storePaths = paths}
pushId <- addPushJob pushRequest
let pathSet = Set.fromList paths
closure = PushJob.ResolvedClosure pathSet pathSet
resolvePushJob pushId closure
withPushJob pushId $ \pushJob -> liftIO $ do
PushJob.status pushJob `shouldBe` Running
PushJob.startedAt pushJob `shouldSatisfy` isJust
forM_ paths $ \path -> do
pushStorePathAttempt path 1 defaultRetryStatus
pushStorePathDone path
withPushJob pushId $ \pushJob -> liftIO $ do
PushJob.status pushJob `shouldBe` Completed
PushJob.completedAt pushJob `shouldSatisfy` isJust
PushJob.result pushJob
`shouldBe` PushResult
{ prFailedPaths = mempty,
prPushedPaths = Set.fromList paths,
prSkippedPaths = mempty
}
withPushManager :: (PushManagerEnv -> IO a) -> IO a
withPushManager f = do
logger <- liftIO $ Log.new "daemon" Nothing Log.Debug
newPushManagerEnv defaultPushOptions logger mempty >>= f
inPushManager :: PushManager a -> IO a
inPushManager f = withPushManager (`runPushManager` f)