curl-runnings 0.9.2 → 0.10.0
raw patch · 5 files changed
+71/−27 lines, 5 filesdep +connectiondep +http-client-tlsdep ~base
Dependencies added: connection, http-client-tls
Dependency ranges changed: base
Files
- README.md +18/−0
- app/Main.hs +11/−8
- curl-runnings.cabal +10/−7
- src/Testing/CurlRunnings.hs +26/−9
- src/Testing/CurlRunnings/Types.hs +6/−3
README.md view
@@ -102,6 +102,24 @@ ```curl-runnings --help ``` ++### Running With Docker+A dockerfile is included in the root of the project. The Dockerfile will expect the linux based curl-runnings executable in the same directory as the Dockerfile and a `tests.yml` file. You can download the latest executable from the release page : https://github.com/aviaviavi/curl-runnings/releases .++``` docker build . -t curl-runnings-tests```++``` docker run curl-runnings-tests```++If you use docker-compose, you can add this to docker-compose.yml:++```+tests:+ build:+ context: .+ dockerfile: ./Dockerfile+```++ ### Contributing Contributions in any form are welcome and encouraged. Don't be shy! :D
app/Main.hs view
@@ -30,9 +30,10 @@ -- | Command line flags data CurlRunnings = CurlRunnings- { file :: FilePath- , grep :: Maybe T.Text- , upgrade :: Bool+ { file :: FilePath+ , grep :: Maybe T.Text+ , upgrade :: Bool+ , skip_tls_check :: Bool } deriving (Show, Data, Typeable, Eq) -- | cmdargs object@@ -42,6 +43,7 @@ { file = def &= typFile &= help "File to run" , grep = def &= help "Regex to filter test cases by name" , upgrade = def &= help "Pull the latest version of curl runnings"+ , skip_tls_check = def &= help "Don't perform a TLS check (USE WITH CAUTION. Only use this if you signed your own certs)" } &= summary ("curl-runnings " ++ showVersion version) &= program "curl-runnings" &=@@ -72,17 +74,17 @@ setGithubReqHeaders :: Request -> Request setGithubReqHeaders = setRequestHeaders [("User-Agent", "aviaviavi")] -runFile :: FilePath -> Verbosity -> Maybe T.Text -> IO ()-runFile "" _ _ =+runFile :: FilePath -> Verbosity -> Maybe T.Text -> TLSCheckType -> IO ()+runFile "" _ _ _ = putStrLn "Please specify an input file with the --file (-f) flag or use --help for more information"-runFile path verbosityLevel regexp = do+runFile path verbosityLevel regexp tlsType = do home <- getEnv "HOME" suite <- decodeFile . T.unpack $ T.replace "~" (T.pack home) (T.pack path) case suite of Right s -> do results <-- runSuite (s {suiteCaseFilter = regexp}) $ toLogLevel verbosityLevel+ runSuite (s {suiteCaseFilter = regexp}) (toLogLevel verbosityLevel) $ tlsType if any isFailing results then putStrLn (T.unpack $ makeRed "Some tests failed") >> exitWith (ExitFailure 1)@@ -188,6 +190,7 @@ main = do userArgs <- cmdArgs argParser verbosityLevel <- getVerbosity+ let tlsCheckType = if skip_tls_check userArgs then SkipTLSCheck else DoTLSCheck if upgrade userArgs then upgradeCurlRunnings- else runFile (file userArgs) verbosityLevel (grep userArgs)+ else runFile (file userArgs) verbosityLevel (grep userArgs) tlsCheckType
curl-runnings.cabal view
@@ -1,11 +1,13 @@--- This file has been generated from package.yaml by hpack version 0.28.2.+cabal-version: 1.12++-- This file has been generated from package.yaml by hpack version 0.31.1. -- -- see: https://github.com/sol/hpack ----- hash: 0e66b58842dd3cfc4bba11992201740113a8539e45270702205df083d4feb579+-- hash: e7cff7f0f8e0a24c815714efc642a28f90928aa4c4dc7cc5743c8bfb9ece772c name: curl-runnings-version: 0.9.2+version: 0.10.0 synopsis: A framework for declaratively writing curl based API tests description: Please see the README on Github at <https://github.com/aviaviavi/curl-runnings#readme> category: Testing@@ -17,13 +19,12 @@ license: MIT license-file: LICENSE build-type: Simple-cabal-version: >= 1.10 extra-source-files:+ README.md examples/example-spec.json examples/example-spec.yaml examples/importable.yaml examples/interpolation-spec.yaml- README.md source-repository head type: git@@ -34,12 +35,14 @@ src build-depends: aeson >=1.2.4.0- , base >=4.7 && <5+ , base >=4.0 && <5 , bytestring >=0.10.8.2 , case-insensitive >=0.2.1+ , connection >=0.2.8 , directory >=1.3.0.2 , hspec >=2.4.4 , hspec-expectations >=0.8.2+ , http-client-tls >=0.3.5.3 , http-conduit >=2.2.4 , http-types >=0.9.1 , megaparsec >=6.3.0@@ -85,7 +88,7 @@ test ghc-options: -threaded -rtsopts -with-rtsopts=-N build-depends:- base >=4.7 && <5+ base >=4.0 && <5 , curl-runnings , directory >=1.3.0.2 , hspec >=2.4.4
src/Testing/CurlRunnings.hs view
@@ -24,6 +24,8 @@ import qualified Data.Text as T import qualified Data.Vector as V import qualified Data.Yaml.Include as YI+import Network.Connection (TLSSettings (..))+import Network.HTTP.Client.TLS (mkManagerSettings) import Network.HTTP.Conduit import Network.HTTP.Simple import qualified Network.HTTP.Types.Header as HTTP@@ -35,6 +37,7 @@ import Text.Printf import Text.Regex.Posix + -- | decode a json or yaml file into a suite object decodeFile :: FilePath -> IO (Either String CurlSuite) decodeFile specPath =@@ -48,10 +51,22 @@ _ -> return . Left $ printf "Invalid spec path %s" specPath else return . Left $ printf "%s not found" specPath ++noVerifyTlsManagerSettings :: ManagerSettings+noVerifyTlsManagerSettings = mkManagerSettings noVerifyTlsSettings Nothing++noVerifyTlsSettings :: TLSSettings+noVerifyTlsSettings =+ TLSSettingsSimple+ { settingDisableCertificateValidation = True+ , settingDisableSession = True+ , settingUseServerName = False+ }+ -- | Run a single test case, and returns the result. IO is needed here since this method is responsible -- for actually curling the test case endpoint and parsing the result. runCase :: CurlRunningsState -> CurlCase -> IO CaseResult-runCase state curlCase = do+runCase state@(CurlRunningsState _ _ _ tlsCheckType) curlCase = do let eInterpolatedUrl = interpolateQueryString state $ url curlCase eInterpolatedHeaders = interpolateHeaders state $ fromMaybe (HeaderSet []) (headers curlCase)@@ -66,9 +81,11 @@ return $ CaseFail curlCase Nothing Nothing [QueryFailure curlCase l] Right replacedJSON -> do initReq <- parseRequest $ T.unpack interpolatedUrl+ manager <- newManager noVerifyTlsManagerSettings let request = setRequestBodyJSON (fromMaybe emptyObject replacedJSON) .- setRequestHeaders (toHTTPHeaders interpolatedHeaders) $+ setRequestHeaders (toHTTPHeaders interpolatedHeaders) .+ (if tlsCheckType == DoTLSCheck then id else (setRequestManager manager)) $ initReq {method = B8S.pack . show $ requestMethod curlCase} logger state DEBUG (pShow request) logger@@ -183,8 +200,8 @@ printR x = print x >> return x -- | Runs the test cases in order and stop when an error is hit. Returns all the results-runSuite :: CurlSuite -> LogLevel -> IO [CaseResult]-runSuite (CurlSuite cases filterRegex) logLevel = do+runSuite :: CurlSuite -> LogLevel -> TLSCheckType -> IO [CaseResult]+runSuite (CurlSuite cases filterRegex) logLevel tlsType = do fullEnv <- getEnvironment let envMap = H.fromList $ map (\(x, y) -> (T.pack x, T.pack y)) fullEnv filterNameByRegexp curlCase =@@ -198,12 +215,12 @@ Just CaseFail {} -> return prevResults Just CasePass {} -> do result <-- runCase (CurlRunningsState envMap prevResults logLevel) curlCase >>=+ runCase (CurlRunningsState envMap prevResults logLevel tlsType) curlCase >>= printR return $ prevResults ++ [result] Nothing -> do result <-- runCase (CurlRunningsState envMap [] logLevel) curlCase >>= printR+ runCase (CurlRunningsState envMap [] logLevel tlsType) curlCase >>= printR return [result]) [] (filter filterNameByRegexp cases)@@ -367,14 +384,14 @@ Left l -> Left l Right (String s) -> Right $ rawText <> s (Right o) -> Left $ QueryTypeMismatch "Expected a string" o-getStringValueForQuery (CurlRunningsState env _ _) (InterpolatedQuery rawText (EnvironmentVariable v)) =+getStringValueForQuery (CurlRunningsState env _ _ _) (InterpolatedQuery rawText (EnvironmentVariable v)) = Right $ rawText <> H.lookupDefault "" v env -- | Lookup the value for the specified query getValueForQuery :: CurlRunningsState -> InterpolatedQuery -> Either QueryError Value getValueForQuery _ (LiteralText rawText) = Right $ String rawText-getValueForQuery (CurlRunningsState _ previousResults _) full@(NonInterpolatedQuery (Query indexes)) =+getValueForQuery (CurlRunningsState _ previousResults _ _) full@(NonInterpolatedQuery (Query indexes)) = case head indexes of (CaseResultIndex i) -> let maybeCase = arrayGet previousResults $ fromInteger i@@ -417,7 +434,7 @@ T.pack $ "'$< ... >' queries must start with a RESPONSES[index] query: " ++ show full-getValueForQuery (CurlRunningsState env _ _) (NonInterpolatedQuery (EnvironmentVariable var)) =+getValueForQuery (CurlRunningsState env _ _ _) (NonInterpolatedQuery (EnvironmentVariable var)) = Right . String $ H.lookupDefault "" var env getValueForQuery state (InterpolatedQuery _ q) = case getValueForQuery state (NonInterpolatedQuery q) of
src/Testing/CurlRunnings/Types.hs view
@@ -23,6 +23,7 @@ , FullQueryText , SingleQueryText , CurlRunningsState(..)+ , TLSCheckType(..) , isFailing , isPassing@@ -391,14 +392,16 @@ -- | A map of the system environment type Environment = H.HashMap T.Text T.Text +data TLSCheckType = SkipTLSCheck | DoTLSCheck deriving (Show, Eq)+ -- | The state of a suite. Tracks environment variables, and all the test results so far-data CurlRunningsState = CurlRunningsState Environment [CaseResult] LogLevel+data CurlRunningsState = CurlRunningsState Environment [CaseResult] LogLevel TLSCheckType logger :: CurlRunningsState -> CurlRunningsLogger-logger (CurlRunningsState _ _ l) = makeLogger l+logger (CurlRunningsState _ _ l _) = makeLogger l unsafeLogger :: Show a => CurlRunningsState -> CurlRunningsUnsafeLogger a-unsafeLogger (CurlRunningsState _ _ l) = makeUnsafeLogger l+unsafeLogger (CurlRunningsState _ _ l _) = makeUnsafeLogger l -- | A single lookup operation in a json query data Index