keter-rate-limiting-plugin-0.1.0.0: test/Keter/RateLimiter/LeakyBucketStateTests.hs
{-# LANGUAGE OverloadedStrings #-}
{-|
Module : Keter.RateLimiter.LeakyBucketStateTests
Description : Tests for the LeakyBucketState data type and its JSON handling
Copyright : (c) 2025 Oleksandr Zhabenko
License : MIT
Maintainer : oleksandr.zhabenko@yahoo.com
Stability : experimental
Portability : POSIX
This module contains unit tests for the 'LeakyBucketState' data type, including
its construction, equality, JSON serialization/deserialization, and validation logic.
-}
module Keter.RateLimiter.LeakyBucketStateTests (tests) where
import Test.Tasty
import Test.Tasty.HUnit
import Data.Aeson (encode, decode)
import qualified Data.ByteString.Lazy.Char8 as LBS
import Keter.RateLimiter.Types (LeakyBucketState(..))
-- | Test suite for 'LeakyBucketState' including JSON behavior and validation.
--
-- > defaultMain Keter.RateLimiter.LeakyBucketStateTests.tests
tests :: TestTree
tests = testGroup "Keter.RateLimiter.LeakyBucketState Tests"
[ testCase "Construct and compare LeakyBucketState" $ do
let state = LeakyBucketState { level = 2.5, lastTime = 1625073600 }
state @?= LeakyBucketState { level = 2.5, lastTime = 1625073600 }
level state @?= 2.5
lastTime state @?= 1625073600
, testCase "JSON serialization and deserialization" $ do
let state = LeakyBucketState { level = 2.5, lastTime = 1625073600 }
let json = encode state
case decode json :: Maybe LeakyBucketState of
Nothing -> assertFailure "JSON deserialization failed"
Just decoded -> decoded @?= state
, testCase "Invalid JSON: negative level" $ do
let invalidJson = LBS.pack "{\"level\":-1.0,\"lastTime\":1625073600}"
case decode invalidJson :: Maybe LeakyBucketState of
Just _ -> assertFailure "Should fail to deserialize negative level"
Nothing -> return () -- Expected failure
, testCase "Invalid JSON: level exceeds maximum" $ do
let invalidJson = LBS.pack "{\"level\":1000001.0,\"lastTime\":1625073600}"
case decode invalidJson :: Maybe LeakyBucketState of
Just _ -> assertFailure "Should fail to deserialize level exceeding 1000000"
Nothing -> return () -- Expected failure
, testCase "Invalid JSON: malformed input" $ do
let invalidJson = LBS.pack "{\"level\":2.5}" -- Missing lastTime
case decode invalidJson :: Maybe LeakyBucketState of
Just _ -> assertFailure "Should fail to deserialize malformed JSON"
Nothing -> return () -- Expected failure
, testCase "Edge case: zero level" $ do
let state = LeakyBucketState { level = 0.0, lastTime = 1625073600 }
let json = encode state
case decode json :: Maybe LeakyBucketState of
Nothing -> assertFailure "JSON deserialization failed for zero level"
Just decoded -> decoded @?= state
, testCase "Edge case: large valid lastTime" $ do
let state = LeakyBucketState { level = 500.0, lastTime = 1755734400 } -- ≈ 2025-08-01
let json = encode state
case decode json :: Maybe LeakyBucketState of
Nothing -> assertFailure "JSON deserialization failed for large lastTime"
Just decoded -> decoded @?= state
]