bloodhound-1.0.0.0: tests/Test/FleetSpec.hs
{-# LANGUAGE OverloadedStrings #-}
module Test.FleetSpec (spec) where
import Data.Aeson
import Data.Aeson.KeyMap qualified as KM
import Data.ByteString.Lazy.Char8 qualified as LBS
import TestsUtils.Import
import Prelude
-- | Canonical @GET /{index}/_fleet/global_checkpoints@ response.
sampleGlobalCheckpointsBytes :: LBS.ByteString
sampleGlobalCheckpointsBytes =
"{\
\ \"global_checkpoints\": [0, 42, 100],\
\ \"timed_out\": false\
\}"
-- | A polling response that @timed_out@ before advancing, plus an unknown
-- sibling field (@future_field@) the @fgcrExtras@ catch-all must keep.
sampleGlobalCheckpointsWithExtrasBytes :: LBS.ByteString
sampleGlobalCheckpointsWithExtrasBytes =
"{\
\ \"global_checkpoints\": [42],\
\ \"timed_out\": true,\
\ \"future_field\": \"experimental\"\
\}"
spec :: Spec
spec = describe "Fleet API" $ do
describe "GlobalCheckpoint JSON" $ do
it "round-trips as a JSON number" $ do
let Just decoded = decode "42" :: Maybe GlobalCheckpoint
unGlobalCheckpoint decoded `shouldBe` 42
encode (42 :: GlobalCheckpoint) `shouldBe` "42"
it "decodes the documented -1 'no checkpoint' sentinel" $ do
let Just decoded = decode "-1" :: Maybe GlobalCheckpoint
unGlobalCheckpoint decoded `shouldBe` (-1)
it "rejects a non-number value" $ do
let decoded = decode "\"x\"" :: Maybe GlobalCheckpoint
decoded `shouldBe` Nothing
describe "FleetGlobalCheckpointsResponse JSON" $ do
it "decodes the canonical shape" $ do
let Just decoded =
decode sampleGlobalCheckpointsBytes ::
Maybe FleetGlobalCheckpointsResponse
fgcrCheckpoints decoded `shouldBe` [0, 42, 100]
fgcrTimedOut decoded `shouldBe` False
fgcrExtras decoded `shouldBe` KM.empty
it "preserves unknown sibling fields in extras" $ do
let Just decoded =
decode sampleGlobalCheckpointsWithExtrasBytes ::
Maybe FleetGlobalCheckpointsResponse
fgcrTimedOut decoded `shouldBe` True
KM.lookup "future_field" (fgcrExtras decoded) `shouldSatisfy` isJust
it "round-trips through encode . decode" $ do
let Just decoded =
decode sampleGlobalCheckpointsWithExtrasBytes ::
Maybe FleetGlobalCheckpointsResponse
Just roundTripped =
decode (encode decoded) :: Maybe FleetGlobalCheckpointsResponse
fgcrCheckpoints roundTripped `shouldBe` [42]
fgcrTimedOut roundTripped `shouldBe` True
-- The @future_field@ extra survives the round-trip.
KM.lookup "future_field" (fgcrExtras roundTripped) `shouldSatisfy` isJust
-- The known keys are not duplicated into extras.
KM.lookup "global_checkpoints" (fgcrExtras roundTripped) `shouldBe` Nothing
it "rejects a response missing 'global_checkpoints'" $ do
let decoded =
decode "{\"timed_out\":false}" ::
Maybe FleetGlobalCheckpointsResponse
decoded `shouldBe` Nothing
it "decodes an empty global_checkpoints array" $ do
let Just decoded =
decode "{\"global_checkpoints\":[],\"timed_out\":false}" ::
Maybe FleetGlobalCheckpointsResponse
fgcrCheckpoints decoded `shouldBe` []
fgcrTimedOut decoded `shouldBe` False
describe "FleetGlobalCheckpointsOptions params" $ do
it "default options render no query string" $ do
fleetGlobalCheckpointsOptionsParams defaultFleetGlobalCheckpointsOptions
`shouldBe` []
it "renders boolean wait_for_advance / wait_for_index" $ do
let opts =
defaultFleetGlobalCheckpointsOptions
{ fgcoWaitForAdvance = Just True,
fgcoWaitForIndex = Just False
}
fleetGlobalCheckpointsOptionsParams opts
`shouldContain` [("wait_for_advance", Just "true")]
fleetGlobalCheckpointsOptionsParams opts
`shouldContain` [("wait_for_index", Just "false")]
it "renders checkpoints as a comma-separated list" $ do
let opts =
defaultFleetGlobalCheckpointsOptions
{ fgcoCheckpoints = [1, 2, 3]
}
fleetGlobalCheckpointsOptionsParams opts
`shouldContain` [("checkpoints", Just "1,2,3")]
it "omits an empty checkpoints list" $ do
let opts =
defaultFleetGlobalCheckpointsOptions
{ fgcoCheckpoints = []
}
fleetGlobalCheckpointsOptionsParams opts
`shouldBe` []
it "renders timeout as magnitude plus time-unit suffix" $ do
let opts =
defaultFleetGlobalCheckpointsOptions
{ fgcoTimeout = Just (TimeUnitSeconds, 30)
}
fleetGlobalCheckpointsOptionsParams opts
`shouldContain` [("timeout", Just "30s")]
describe "FleetSearchOptions params" $ do
it "default options render no query string" $ do
fleetSearchOptionsParams defaultFleetSearchOptions
`shouldBe` []
it "renders wait_for_checkpoints as a comma-separated list" $ do
let opts =
defaultFleetSearchOptions
{ fsoWaitForCheckpoints = [7, 14]
}
fleetSearchOptionsParams opts
`shouldContain` [("wait_for_checkpoints", Just "7,14")]
it "renders allow_partial_search_results as a bool string" $ do
let opts =
defaultFleetSearchOptions
{ fsoAllowPartialSearchResults = Just False
}
fleetSearchOptionsParams opts
`shouldContain` [("allow_partial_search_results", Just "false")]
it "omits an empty wait_for_checkpoints list" $ do
let opts =
defaultFleetSearchOptions
{ fsoWaitForCheckpoints = []
}
fleetSearchOptionsParams opts
`shouldNotContain` [("wait_for_checkpoints", Just "")]