module Testlib.Options (getOptions, TestOptions (..)) where

import Data.List.Split (splitOn)
import Options.Applicative
import System.Environment (lookupEnv)
import Prelude

data TestOptions = TestOptions
  { TestOptions -> [String]
includeTests :: [String],
    TestOptions -> [String]
excludeTests :: [String],
    TestOptions -> Bool
listTests :: Bool,
    TestOptions -> Maybe String
xmlReport :: Maybe FilePath,
    TestOptions -> String
configFile :: String
  }

parser :: Parser TestOptions
parser :: Parser TestOptions
parser =
  [String]
-> [String] -> Bool -> Maybe String -> String -> TestOptions
TestOptions
    ([String]
 -> [String] -> Bool -> Maybe String -> String -> TestOptions)
-> Parser [String]
-> Parser
     ([String] -> Bool -> Maybe String -> String -> TestOptions)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser String -> Parser [String]
forall a. Parser a -> Parser [a]
forall (f :: * -> *) a. Alternative f => f a -> f [a]
many
      ( Mod OptionFields String -> Parser String
forall s. IsString s => Mod OptionFields s -> Parser s
strOption
          ( String -> Mod OptionFields String
forall (f :: * -> *) a. HasName f => String -> Mod f a
long String
"include"
              Mod OptionFields String
-> Mod OptionFields String -> Mod OptionFields String
forall a. Semigroup a => a -> a -> a
<> Char -> Mod OptionFields String
forall (f :: * -> *) a. HasName f => Char -> Mod f a
short Char
'i'
              Mod OptionFields String
-> Mod OptionFields String -> Mod OptionFields String
forall a. Semigroup a => a -> a -> a
<> String -> Mod OptionFields String
forall (f :: * -> *) a. HasMetavar f => String -> Mod f a
metavar String
"PATTERN"
              Mod OptionFields String
-> Mod OptionFields String -> Mod OptionFields String
forall a. Semigroup a => a -> a -> a
<> String -> Mod OptionFields String
forall (f :: * -> *) a. String -> Mod f a
help String
"Include tests matching PATTERN (simple substring match). This flag can be provided multiple times. This flag can also be provided via the TEST_INCLUDE environment variable."
          )
      )
    Parser ([String] -> Bool -> Maybe String -> String -> TestOptions)
-> Parser [String]
-> Parser (Bool -> Maybe String -> String -> TestOptions)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser String -> Parser [String]
forall a. Parser a -> Parser [a]
forall (f :: * -> *) a. Alternative f => f a -> f [a]
many
      ( Mod OptionFields String -> Parser String
forall s. IsString s => Mod OptionFields s -> Parser s
strOption
          ( String -> Mod OptionFields String
forall (f :: * -> *) a. HasName f => String -> Mod f a
long String
"exclude"
              Mod OptionFields String
-> Mod OptionFields String -> Mod OptionFields String
forall a. Semigroup a => a -> a -> a
<> Char -> Mod OptionFields String
forall (f :: * -> *) a. HasName f => Char -> Mod f a
short Char
'x'
              Mod OptionFields String
-> Mod OptionFields String -> Mod OptionFields String
forall a. Semigroup a => a -> a -> a
<> String -> Mod OptionFields String
forall (f :: * -> *) a. HasMetavar f => String -> Mod f a
metavar String
"PATTERN"
              Mod OptionFields String
-> Mod OptionFields String -> Mod OptionFields String
forall a. Semigroup a => a -> a -> a
<> String -> Mod OptionFields String
forall (f :: * -> *) a. String -> Mod f a
help String
"Exclude tests matching PATTERN (simple substring match). This flag can be provided multiple times. This flag can also be provided via the TEST_EXCLUDE environment variable."
          )
      )
    Parser (Bool -> Maybe String -> String -> TestOptions)
-> Parser Bool -> Parser (Maybe String -> String -> TestOptions)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Mod FlagFields Bool -> Parser Bool
switch (String -> Mod FlagFields Bool
forall (f :: * -> *) a. HasName f => String -> Mod f a
long String
"list" Mod FlagFields Bool -> Mod FlagFields Bool -> Mod FlagFields Bool
forall a. Semigroup a => a -> a -> a
<> Char -> Mod FlagFields Bool
forall (f :: * -> *) a. HasName f => Char -> Mod f a
short Char
'l' Mod FlagFields Bool -> Mod FlagFields Bool -> Mod FlagFields Bool
forall a. Semigroup a => a -> a -> a
<> String -> Mod FlagFields Bool
forall (f :: * -> *) a. String -> Mod f a
help String
"Only list tests.")
    Parser (Maybe String -> String -> TestOptions)
-> Parser (Maybe String) -> Parser (String -> TestOptions)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser String -> Parser (Maybe String)
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional
      ( Mod OptionFields String -> Parser String
forall s. IsString s => Mod OptionFields s -> Parser s
strOption
          ( String -> Mod OptionFields String
forall (f :: * -> *) a. HasName f => String -> Mod f a
long String
"xml"
              Mod OptionFields String
-> Mod OptionFields String -> Mod OptionFields String
forall a. Semigroup a => a -> a -> a
<> String -> Mod OptionFields String
forall (f :: * -> *) a. HasMetavar f => String -> Mod f a
metavar String
"FILE"
              Mod OptionFields String
-> Mod OptionFields String -> Mod OptionFields String
forall a. Semigroup a => a -> a -> a
<> String -> Mod OptionFields String
forall (f :: * -> *) a. String -> Mod f a
help String
"Generate XML report for the tests"
          )
      )
    Parser (String -> TestOptions)
-> Parser String -> Parser TestOptions
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Mod OptionFields String -> Parser String
forall s. IsString s => Mod OptionFields s -> Parser s
strOption
      ( String -> Mod OptionFields String
forall (f :: * -> *) a. HasName f => String -> Mod f a
long String
"config"
          Mod OptionFields String
-> Mod OptionFields String -> Mod OptionFields String
forall a. Semigroup a => a -> a -> a
<> Char -> Mod OptionFields String
forall (f :: * -> *) a. HasName f => Char -> Mod f a
short Char
'c'
          Mod OptionFields String
-> Mod OptionFields String -> Mod OptionFields String
forall a. Semigroup a => a -> a -> a
<> String -> Mod OptionFields String
forall (f :: * -> *) a. HasMetavar f => String -> Mod f a
metavar String
"FILE"
          Mod OptionFields String
-> Mod OptionFields String -> Mod OptionFields String
forall a. Semigroup a => a -> a -> a
<> String -> Mod OptionFields String
forall (f :: * -> *) a. String -> Mod f a
help String
"Use configuration FILE"
          Mod OptionFields String
-> Mod OptionFields String -> Mod OptionFields String
forall a. Semigroup a => a -> a -> a
<> String -> Mod OptionFields String
forall (f :: * -> *) a. HasValue f => a -> Mod f a
value String
"services/integration.yaml"
      )

optInfo :: ParserInfo TestOptions
optInfo :: ParserInfo TestOptions
optInfo =
  Parser TestOptions -> InfoMod TestOptions -> ParserInfo TestOptions
forall a. Parser a -> InfoMod a -> ParserInfo a
info
    (Parser TestOptions
parser Parser TestOptions
-> Parser (TestOptions -> TestOptions) -> Parser TestOptions
forall (f :: * -> *) a b. Applicative f => f a -> f (a -> b) -> f b
<**> Parser (TestOptions -> TestOptions)
forall a. Parser (a -> a)
helper)
    ( InfoMod TestOptions
forall a. InfoMod a
fullDesc
        InfoMod TestOptions -> InfoMod TestOptions -> InfoMod TestOptions
forall a. Semigroup a => a -> a -> a
<> String -> InfoMod TestOptions
forall a. String -> InfoMod a
progDesc String
"Run integration tests"
        InfoMod TestOptions -> InfoMod TestOptions -> InfoMod TestOptions
forall a. Semigroup a => a -> a -> a
<> String -> InfoMod TestOptions
forall a. String -> InfoMod a
header String
"integration - wire-server integration test suite"
    )

getOptions :: IO TestOptions
getOptions :: IO TestOptions
getOptions = do
  [String]
defaultsInclude <- [String] -> (String -> [String]) -> Maybe String -> [String]
forall b a. b -> (a -> b) -> Maybe a -> b
maybe [] (String -> String -> [String]
forall a. Eq a => [a] -> [a] -> [[a]]
splitOn String
",") (Maybe String -> [String]) -> IO (Maybe String) -> IO [String]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> IO (Maybe String)
lookupEnv String
"TEST_INCLUDE"
  [String]
defaultsExclude <- [String] -> (String -> [String]) -> Maybe String -> [String]
forall b a. b -> (a -> b) -> Maybe a -> b
maybe [] (String -> String -> [String]
forall a. Eq a => [a] -> [a] -> [[a]]
splitOn String
",") (Maybe String -> [String]) -> IO (Maybe String) -> IO [String]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> IO (Maybe String)
lookupEnv String
"TEST_EXCLUDE"
  Maybe String
defaultsXMLReport <- String -> IO (Maybe String)
lookupEnv String
"TEST_XML"
  TestOptions
opts <- ParserInfo TestOptions -> IO TestOptions
forall a. ParserInfo a -> IO a
execParser ParserInfo TestOptions
optInfo
  TestOptions -> IO TestOptions
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure
    TestOptions
opts
      { includeTests = includeTests opts `orFromEnv` defaultsInclude,
        excludeTests = excludeTests opts `orFromEnv` defaultsExclude,
        xmlReport = xmlReport opts `orFromEnv` defaultsXMLReport
      }
  where
    orFromEnv :: t a -> t a -> t a
orFromEnv t a
fromArgs t a
fromEnv =
      if t a -> Bool
forall a. t a -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null t a
fromArgs
        then t a
fromEnv
        else t a
fromArgs