bloodhound-1.0.0.0: tests/Test/ReindexOptionsSpec.hs
{-# LANGUAGE OverloadedStrings #-}
module Test.ReindexOptionsSpec (spec) where
import Data.List (sort)
import Data.Scientific (Scientific)
import Data.Text qualified as T
import Database.Bloodhound.Common.Types
import Test.Hspec (Spec, describe, it, shouldBe)
-- | Stable ordering for equality. The renderer preserves field-declaration
-- order but tests compare the set of params, not the order.
normalize :: [(T.Text, Maybe T.Text)] -> [(T.Text, Maybe T.Text)]
normalize = sort
-- | Boolean helpers rendered as @true@/@false@ strings.
boolTrue :: Maybe T.Text
boolTrue = Just "true"
boolFalse :: Maybe T.Text
boolFalse = Just "false"
spec :: Spec
spec =
describe "ReindexOptions URI param rendering" $ do
it "defaultReindexOptions emits no params" $
reindexOptionsParams defaultReindexOptions
`shouldBe` []
describe "conflicts" $ do
it "ConflictsProceed renders as conflicts=proceed" $ do
let opts = defaultReindexOptions {rioConflicts = Just ConflictsProceed}
reindexOptionsParams opts `shouldBe` [("conflicts", Just "proceed")]
it "ConflictsAbort renders as conflicts=abort" $ do
let opts = defaultReindexOptions {rioConflicts = Just ConflictsAbort}
reindexOptionsParams opts `shouldBe` [("conflicts", Just "abort")]
it "refresh renders via RefreshPolicy" $ do
let opts = defaultReindexOptions {rioRefresh = Just RefreshTrue}
reindexOptionsParams opts `shouldBe` [("refresh", Just "true")]
it "timeout renders verbatim" $ do
let opts = defaultReindexOptions {rioTimeout = Just "5s"}
reindexOptionsParams opts `shouldBe` [("timeout", Just "5s")]
it "scroll renders verbatim" $ do
let opts = defaultReindexOptions {rioScroll = Just "1m"}
reindexOptionsParams opts `shouldBe` [("scroll", Just "1m")]
describe "wait_for_active_shards" $ do
it "AllActiveShards renders as wait_for_active_shards=all" $ do
let opts = defaultReindexOptions {rioWaitForActiveShards = Just AllActiveShards}
reindexOptionsParams opts `shouldBe` [("wait_for_active_shards", Just "all")]
it "ActiveShards n renders as wait_for_active_shards=<n>" $ do
let opts = defaultReindexOptions {rioWaitForActiveShards = Just (ActiveShards 2)}
reindexOptionsParams opts `shouldBe` [("wait_for_active_shards", Just "2")]
it "requests_per_second renders as decimal" $ do
let opts = defaultReindexOptions {rioRequestsPerSecond = Just 500}
reindexOptionsParams opts `shouldBe` [("requests_per_second", Just "500")]
it "requests_per_second renders 0 (no throttling)" $ do
let opts = defaultReindexOptions {rioRequestsPerSecond = Just 0}
reindexOptionsParams opts `shouldBe` [("requests_per_second", Just "0")]
describe "slices" $ do
it "SlicesAuto renders as slices=auto" $ do
let opts = defaultReindexOptions {rioSlices = Just SlicesAuto}
reindexOptionsParams opts `shouldBe` [("slices", Just "auto")]
it "SlicesCount n renders as slices=<n>" $ do
let opts = defaultReindexOptions {rioSlices = Just (SlicesCount 4)}
reindexOptionsParams opts `shouldBe` [("slices", Just "4")]
it "pipeline renders verbatim" $ do
let opts = defaultReindexOptions {rioPipeline = Just "my-pipe"}
reindexOptionsParams opts `shouldBe` [("pipeline", Just "my-pipe")]
describe "require_alias" $ do
it "Just True renders as require_alias=true" $ do
let opts = defaultReindexOptions {rioRequireAlias = Just True}
reindexOptionsParams opts `shouldBe` [("require_alias", boolTrue)]
it "Just False renders as require_alias=false" $ do
let opts = defaultReindexOptions {rioRequireAlias = Just False}
reindexOptionsParams opts `shouldBe` [("require_alias", boolFalse)]
it "max_docs renders as decimal" $ do
let opts = defaultReindexOptions {rioMaxDocs = Just 100}
reindexOptionsParams opts `shouldBe` [("max_docs", Just "100")]
it "renders every field together when all are populated" $ do
let opts =
defaultReindexOptions
{ rioConflicts = Just ConflictsProceed,
rioRefresh = Just RefreshWaitFor,
rioTimeout = Just "5s",
rioScroll = Just "1m",
rioWaitForActiveShards = Just (ActiveShards 1),
rioRequestsPerSecond = Just 100,
rioSlices = Just (SlicesCount 4),
rioPipeline = Just "my-pipe",
rioRequireAlias = Just True,
rioMaxDocs = Just 500
}
normalize (reindexOptionsParams opts)
`shouldBe` normalize
[ ("conflicts", Just "proceed"),
("refresh", Just "wait_for"),
("timeout", Just "5s"),
("scroll", Just "1m"),
("wait_for_active_shards", Just "1"),
("requests_per_second", Just "100"),
("slices", Just "4"),
("pipeline", Just "my-pipe"),
("require_alias", boolTrue),
("max_docs", Just "500")
]
-- RethrottleRate renders the value of the requests_per_second URI
-- parameter carried by 'rethrottleReindex'. Mirrors the examples in
-- the ES docs: -1 for unlimited, plain integers for whole rates
-- (no trailing .0), fractional form for decimals.
describe "RethrottleRate rendering" $ do
it "RethrottleUnlimited renders as -1" $
renderRethrottleRate RethrottleUnlimited `shouldBe` "-1"
it "integer-valued rate renders without trailing .0" $
renderRethrottleRate (RethrottlePerSecond 12) `shouldBe` "12"
it "fractional rate renders as a decimal" $
renderRethrottleRate (RethrottlePerSecond (1.7 :: Scientific))
`shouldBe` "1.7"
it "zero rate renders as 0" $
renderRethrottleRate (RethrottlePerSecond 0) `shouldBe` "0"
-- A negative 'RethrottlePerSecond' is not validated (see the
-- Haddock on 'RethrottleRate') — it renders verbatim and collides
-- with 'RethrottleUnlimited' on the wire. ES treats any negative
-- value as unlimited, so the wire-level effect is the same; this
-- test pins down the chosen behaviour so future refactors notice
-- if they change it.
it "negative rate renders verbatim (collides with Unlimited)" $
renderRethrottleRate (RethrottlePerSecond (-1)) `shouldBe` "-1"