packages feed

toxiproxy-haskell-0.2.0.0: test/Spec.hs

{-# LANGUAGE OverloadedStrings #-}
module Main where

import Test.Hspec

import Servant.Client
import Servant.API
import qualified Data.Map.Strict as Map
import Control.Concurrent (threadDelay)
import System.Process (withCreateProcess, proc, CreateProcess)
import System.IO.Silently (silence)
import Network.HTTP.Client (newManager, defaultManagerSettings)
import Data.Either (isLeft)
import Data.Time.Clock.POSIX (getPOSIXTime)

import Toxiproxy

main :: IO ()
main = hspec $ do
  describe "Toxiproxy API" $ do
    it "get version" $
      withToxiproxyServer $
        run getVersion `shouldReturn` Right version
    it "post reset" $
      withToxiproxyServer $
        run postReset `shouldReturn` Right NoContent
    it "create, update, get and delete a proxy" $
      withToxiproxyServer $ do
        let name = "myProxy"
        let proxy = Proxy
              { proxyName     = name
              , proxyListen   = "127.0.0.1:4444"
              , proxyUpstream = "127.0.0.1:4445"
              , proxyEnabled  = False
              , proxyToxics   = []
              }
        run (createProxy proxy) `shouldReturn` Right proxy
        run getProxies `shouldReturn` Right (Map.fromList [(name, proxy)])
        run (getProxy name) `shouldReturn` Right proxy
        let enabled = proxy { proxyEnabled  = True }
        run (updateProxy name enabled) `shouldReturn` Right enabled
        run (deleteProxy name) `shouldReturn` Right NoContent
        run getProxies `shouldReturn` Right Map.empty
    it "populate proxies" $
      withToxiproxyServer $ do
        let proxy1 = Proxy
              { proxyName     = "myProxy"
              , proxyListen   = "127.0.0.1:4444"
              , proxyUpstream = "127.0.0.1:4445"
              , proxyEnabled  = False
              , proxyToxics   = []
              }
        let proxy2 = Proxy
              { proxyName     = "myOtherProxy"
              , proxyListen   = "127.0.0.1:4446"
              , proxyUpstream = "127.0.0.1:4447"
              , proxyEnabled  = False
              , proxyToxics   = []
              }
        run (postPopulate [proxy1, proxy2]) `shouldReturn` Right (Populate [proxy1, proxy2])
    it "create get, update and delete toxic" $
      withToxiproxyServer $ do
        let name = "myProxy"
        let toxicName = "latency"
        let toxic = Toxic
              { toxicName       = toxicName
              , toxicType       = Latency
              , toxicStream     = Upstream
              , toxicToxicity   = 1
              , toxicAttributes = Map.fromList [("latency", 1000), ("jitter", 0)]
              }
        let proxy = Proxy
              { proxyName     = name
              , proxyListen   = "127.0.0.1:4444"
              , proxyUpstream = "127.0.0.1:4445"
              , proxyEnabled  = False
              , proxyToxics   = []
              }
        let proxyWithToxic = proxy { proxyToxics = [toxic] }
        let updatedToxic =
              toxic { toxicAttributes = Map.fromList [("latency", 1000), ("jitter", 0)] }
        run (createProxy proxy) `shouldReturn` Right proxy
        run (createToxic name toxic) `shouldReturn` Right toxic
        run (getToxics name) `shouldReturn` Right [toxic]
        run (getProxy name) `shouldReturn` Right proxyWithToxic
        run (updateToxic name toxicName updatedToxic) `shouldReturn` Right updatedToxic
        run (deleteToxic name toxicName) `shouldReturn` Right NoContent
        run (getToxics name) `shouldReturn` Right []
  describe "Toxiproxy Helpers" $ do
    it "disabled temporarily using withDisabled" $
      withToxiproxyServer $ do
        let proxy = Proxy
              { proxyName     = "myProxy"
              , proxyListen   = "127.0.0.1:4444"
              , proxyUpstream = "127.0.0.1:8474"
              , proxyEnabled  = True
              , proxyToxics   = []
              }
        withProxy proxy $ \proxy -> do
          runThroughProxy getVersion `shouldReturn` Right version
          withDisabled proxy $ do
            resp <- runThroughProxy getVersion
            isLeft resp `shouldBe` True
          runThroughProxy getVersion `shouldReturn` Right version
    it "has temporary toxic using withToxic" $
      withToxiproxyServer $ do
        let proxy = Proxy
              { proxyName     = "myProxy"
              , proxyListen   = "127.0.0.1:4444"
              , proxyUpstream = "127.0.0.1:8474"
              , proxyEnabled  = True
              , proxyToxics   = []
              }
        let toxic = Toxic
              { toxicName       = "latency"
              , toxicType       = Latency
              , toxicStream     = Upstream
              , toxicToxicity   = 1
              , toxicAttributes = Map.fromList [("latency", 1000), ("jitter", 0)]
              }
        withProxy proxy $ \proxy -> do
          runThroughProxy getVersion `shouldReturn` Right version
          withToxic proxy toxic $ do
            before <- getPOSIXTime
            runThroughProxy getVersion `shouldReturn` Right version
            after <- getPOSIXTime
            after - before > 1 `shouldBe` True
          runThroughProxy getVersion `shouldReturn` Right version

withToxiproxyServer :: IO a -> IO a
withToxiproxyServer f =
  silence $
    withCreateProcess server $ \_ _ _ _ -> threadDelay 100000 >> f
  where
    server :: CreateProcess
    server = proc "toxiproxy-server" []

version :: Version
version = Version "git-fe6bf4f"

proxyUrl :: BaseUrl
proxyUrl = BaseUrl Http "127.0.0.1" 4444 ""

runThroughProxy :: ClientM a -> IO (Either ServantError a)
runThroughProxy f = do
  manager <- newManager defaultManagerSettings
  runClientM f (ClientEnv manager proxyUrl)