prelude-compat
This commit is contained in:
parent
b48b1e8bc1
commit
eb51069cb5
1
.gitignore
vendored
1
.gitignore
vendored
@ -1 +1,2 @@
|
|||||||
doc/_build/
|
doc/_build/
|
||||||
|
scripts/
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
name: servant-quickcheck
|
name: servant-quickcheck
|
||||||
version: 0.1.0.0
|
version: 0.0.0.0
|
||||||
synopsis: QuickCheck entire APIs
|
synopsis: QuickCheck entire APIs
|
||||||
description:
|
description:
|
||||||
This packages provides QuickCheck properties that are tested across an entire
|
This packages provides QuickCheck properties that are tested across an entire
|
||||||
@ -20,12 +20,12 @@ flag long-tests
|
|||||||
library
|
library
|
||||||
exposed-modules: Servant.QuickCheck
|
exposed-modules: Servant.QuickCheck
|
||||||
, Servant.QuickCheck.Internal
|
, Servant.QuickCheck.Internal
|
||||||
-- , Servant.QuickCheck.Internal.Benchmarking
|
|
||||||
, Servant.QuickCheck.Internal.Predicates
|
, Servant.QuickCheck.Internal.Predicates
|
||||||
, Servant.QuickCheck.Internal.HasGenRequest
|
, Servant.QuickCheck.Internal.HasGenRequest
|
||||||
, Servant.QuickCheck.Internal.QuickCheck
|
, Servant.QuickCheck.Internal.QuickCheck
|
||||||
, Servant.QuickCheck.Internal.Equality
|
, Servant.QuickCheck.Internal.Equality
|
||||||
build-depends: base >=4.7 && <4.9
|
build-depends: base >=4.7 && <4.9
|
||||||
|
, base-compat == 0.9.*
|
||||||
, QuickCheck == 2.8.*
|
, QuickCheck == 2.8.*
|
||||||
, bytestring == 0.10.*
|
, bytestring == 0.10.*
|
||||||
, aeson > 0.10 && < 0.12
|
, aeson > 0.10 && < 0.12
|
||||||
@ -63,6 +63,7 @@ library
|
|||||||
, ScopedTypeVariables
|
, ScopedTypeVariables
|
||||||
, OverloadedStrings
|
, OverloadedStrings
|
||||||
, FunctionalDependencies
|
, FunctionalDependencies
|
||||||
|
, NoImplicitPrelude
|
||||||
default-language: Haskell2010
|
default-language: Haskell2010
|
||||||
|
|
||||||
test-suite spec
|
test-suite spec
|
||||||
@ -89,16 +90,3 @@ test-suite spec
|
|||||||
, DataKinds
|
, DataKinds
|
||||||
if flag(long-tests)
|
if flag(long-tests)
|
||||||
cpp-options: -DLONG_TESTS
|
cpp-options: -DLONG_TESTS
|
||||||
|
|
||||||
-- test-suite doctests
|
|
||||||
-- default-language: Haskell2010
|
|
||||||
-- type: exitcode-stdio-1.0
|
|
||||||
-- ghc-options: -threaded
|
|
||||||
-- main-is: Doctest.hs
|
|
||||||
-- hs-source-dirs: test
|
|
||||||
-- build-depends: base >4 && <5
|
|
||||||
-- , doctest
|
|
||||||
-- , filemanip
|
|
||||||
-- , directory
|
|
||||||
-- , filepath
|
|
||||||
-- HS-Source-Dirs: test
|
|
||||||
|
|||||||
@ -4,4 +4,3 @@ import Servant.QuickCheck.Internal.HasGenRequest as X
|
|||||||
import Servant.QuickCheck.Internal.Predicates as X
|
import Servant.QuickCheck.Internal.Predicates as X
|
||||||
import Servant.QuickCheck.Internal.QuickCheck as X
|
import Servant.QuickCheck.Internal.QuickCheck as X
|
||||||
import Servant.QuickCheck.Internal.Equality as X
|
import Servant.QuickCheck.Internal.Equality as X
|
||||||
import Servant.QuickCheck.Internal.Benchmarking as X
|
|
||||||
|
|||||||
@ -1,83 +0,0 @@
|
|||||||
-- This is a WIP module that shouldn't be used.
|
|
||||||
module Servant.QuickCheck.Internal.Benchmarking where
|
|
||||||
|
|
||||||
import Data.ByteString (ByteString)
|
|
||||||
import Data.ByteString.Lazy (toStrict)
|
|
||||||
import Network.HTTP.Client
|
|
||||||
import Network.HTTP.Types
|
|
||||||
import Servant.Client
|
|
||||||
|
|
||||||
data BenchOptions = BenchOptions
|
|
||||||
{ duration :: Int
|
|
||||||
, threads :: Int
|
|
||||||
, connections :: Int
|
|
||||||
, noOfTests :: Int
|
|
||||||
} deriving (Eq, Show, Read)
|
|
||||||
|
|
||||||
defaultBenchOptions :: BenchOptions
|
|
||||||
defaultBenchOptions = BenchOptions
|
|
||||||
{ duration = 10
|
|
||||||
, threads = 1
|
|
||||||
, connections = 10
|
|
||||||
, noOfTests = 10
|
|
||||||
}
|
|
||||||
|
|
||||||
data WrkScript = WrkScript
|
|
||||||
{ wrkScheme :: Scheme
|
|
||||||
, wrkHost :: ByteString
|
|
||||||
, wrkPort :: Int
|
|
||||||
, wrkMethod :: Method
|
|
||||||
, wrkPath :: ByteString
|
|
||||||
, wrkHeaders :: [Header]
|
|
||||||
, wrkBody :: ByteString
|
|
||||||
} deriving (Eq, Show)
|
|
||||||
|
|
||||||
mkScript :: WrkScript -> String
|
|
||||||
mkScript w
|
|
||||||
= "wrk.scheme = \"" ++ sscheme (wrkScheme w) ++ "\""
|
|
||||||
++ "\nwrk.host = " ++ show (wrkHost w)
|
|
||||||
++ "\nwrk.port = " ++ show (wrkPort w)
|
|
||||||
++ "\nwrk.method = " ++ show (wrkMethod w)
|
|
||||||
++ "\nwrk.path = " ++ show (wrkPath w)
|
|
||||||
++ foldr (\(h,v) old -> old ++ "\nwrk.headers[" ++ show h ++ "] = " ++ show v)
|
|
||||||
""
|
|
||||||
(wrkHeaders w)
|
|
||||||
++ "\nwrk.body = " ++ show (wrkBody w)
|
|
||||||
++ "\n" ++ reportFmt
|
|
||||||
where
|
|
||||||
sscheme Http = "http"
|
|
||||||
sscheme Https = "https"
|
|
||||||
|
|
||||||
reqToWrk :: Request -> WrkScript
|
|
||||||
reqToWrk r = WrkScript
|
|
||||||
{ wrkScheme = Http
|
|
||||||
, wrkHost = host r
|
|
||||||
, wrkPort = port r
|
|
||||||
, wrkMethod = method r
|
|
||||||
, wrkPath = path r
|
|
||||||
, wrkHeaders = requestHeaders r
|
|
||||||
, wrkBody = case requestBody r of
|
|
||||||
RequestBodyLBS r' -> toStrict r'
|
|
||||||
_ -> error "expecting RequestBodyLBS"
|
|
||||||
}
|
|
||||||
|
|
||||||
reportFmt :: String
|
|
||||||
reportFmt
|
|
||||||
= "done = function(summary, latency, requests)\n"
|
|
||||||
++ " for _, p in pairs({ 50, 75, 99, 99.999 }) do\n"
|
|
||||||
++ " n = latency:percentile(p)\n"
|
|
||||||
++ " io.write(string.format(\"%g%%, %d\\n\", p, n))\n"
|
|
||||||
++ " end\n"
|
|
||||||
++ "end\n"
|
|
||||||
|
|
||||||
{-data BenchResult = BenchResult-}
|
|
||||||
{-{ benchReq :: Request-}
|
|
||||||
{-, benchLatencyDist :: [(Percentile, Microsecs)]-}
|
|
||||||
{-, benchLatencyAvg :: Microsecs-}
|
|
||||||
{-} deriving (Eq, Show, Read, Generic)-}
|
|
||||||
|
|
||||||
{-newtype Microsecs = Microsecs { unMicroSecs :: Int }-}
|
|
||||||
{-deriving (Eq, Show, Read, Generic)-}
|
|
||||||
|
|
||||||
{-newtype Percentile = Percentile { unPercentile :: Int }-}
|
|
||||||
{-deriving (Eq, Show, Read, Generic)-}
|
|
||||||
@ -1,7 +1,8 @@
|
|||||||
module Servant.QuickCheck.Internal.Equality where
|
module Servant.QuickCheck.Internal.Equality where
|
||||||
|
|
||||||
import Network.HTTP.Client
|
import Data.Function (on)
|
||||||
import Data.Function (on)
|
import Network.HTTP.Client (Response, responseBody)
|
||||||
|
import Prelude.Compat
|
||||||
|
|
||||||
newtype ResponseEquality b
|
newtype ResponseEquality b
|
||||||
= ResponseEquality { getResponseEquality :: Response b -> Response b -> Bool }
|
= ResponseEquality { getResponseEquality :: Response b -> Response b -> Bool }
|
||||||
@ -12,9 +13,13 @@ instance Monoid (ResponseEquality b) where
|
|||||||
a x y && b x y
|
a x y && b x y
|
||||||
|
|
||||||
-- | Use `Eq` instance for `Response`
|
-- | Use `Eq` instance for `Response`
|
||||||
|
--
|
||||||
|
-- #SINCE#
|
||||||
allEquality :: Eq b => ResponseEquality b
|
allEquality :: Eq b => ResponseEquality b
|
||||||
allEquality = ResponseEquality (==)
|
allEquality = ResponseEquality (==)
|
||||||
|
|
||||||
-- | ByteString `Eq` instance over the response body.
|
-- | ByteString `Eq` instance over the response body.
|
||||||
|
--
|
||||||
|
-- #SINCE#
|
||||||
bodyEquality :: Eq b => ResponseEquality b
|
bodyEquality :: Eq b => ResponseEquality b
|
||||||
bodyEquality = ResponseEquality ((==) `on` responseBody)
|
bodyEquality = ResponseEquality ((==) `on` responseBody)
|
||||||
|
|||||||
@ -5,15 +5,16 @@ import Data.Default.Class (def)
|
|||||||
import Data.Monoid ((<>))
|
import Data.Monoid ((<>))
|
||||||
import Data.String (fromString)
|
import Data.String (fromString)
|
||||||
import Data.String.Conversions (cs)
|
import Data.String.Conversions (cs)
|
||||||
import GHC.TypeLits
|
import GHC.TypeLits (KnownSymbol, Nat, symbolVal)
|
||||||
import Network.HTTP.Client (Request, RequestBody (..), host,
|
import Network.HTTP.Client (Request, RequestBody (..), host,
|
||||||
method, path, port, requestBody,
|
method, path, port, queryString,
|
||||||
requestHeaders, secure, queryString)
|
requestBody, requestHeaders, secure)
|
||||||
import Network.HTTP.Media (renderHeader)
|
import Network.HTTP.Media (renderHeader)
|
||||||
|
import Prelude.Compat
|
||||||
import Servant
|
import Servant
|
||||||
import Servant.API.ContentTypes
|
import Servant.API.ContentTypes (AllMimeRender (..))
|
||||||
import Servant.Client (BaseUrl (..), Scheme (..))
|
import Servant.Client (BaseUrl (..), Scheme (..))
|
||||||
import Test.QuickCheck
|
import Test.QuickCheck (Arbitrary (..), Gen, elements, oneof)
|
||||||
|
|
||||||
|
|
||||||
class HasGenRequest a where
|
class HasGenRequest a where
|
||||||
|
|||||||
@ -3,6 +3,7 @@ module Servant.QuickCheck.Internal.Predicates where
|
|||||||
import Control.Monad (liftM2)
|
import Control.Monad (liftM2)
|
||||||
import Data.Aeson (Object, decode)
|
import Data.Aeson (Object, decode)
|
||||||
import Data.Bifunctor (Bifunctor (..))
|
import Data.Bifunctor (Bifunctor (..))
|
||||||
|
import Prelude.Compat
|
||||||
import qualified Data.ByteString as SBS
|
import qualified Data.ByteString as SBS
|
||||||
import qualified Data.ByteString.Char8 as SBSC
|
import qualified Data.ByteString.Char8 as SBSC
|
||||||
import qualified Data.ByteString.Lazy as LBS
|
import qualified Data.ByteString.Lazy as LBS
|
||||||
@ -169,6 +170,8 @@ honoursAcceptHeader
|
|||||||
-- __References__:
|
-- __References__:
|
||||||
--
|
--
|
||||||
-- * @Cache-Control@ header: <https://tools.ietf.org/html/rfc7234#section-5.2 RFC 7234 Section 5.2>
|
-- * @Cache-Control@ header: <https://tools.ietf.org/html/rfc7234#section-5.2 RFC 7234 Section 5.2>
|
||||||
|
--
|
||||||
|
-- #SINCE#
|
||||||
getsHaveCacheControlHeader :: RequestPredicate Text Bool
|
getsHaveCacheControlHeader :: RequestPredicate Text Bool
|
||||||
getsHaveCacheControlHeader
|
getsHaveCacheControlHeader
|
||||||
= RequestPredicate
|
= RequestPredicate
|
||||||
@ -184,6 +187,8 @@ getsHaveCacheControlHeader
|
|||||||
-- | [__Best Practice__]
|
-- | [__Best Practice__]
|
||||||
--
|
--
|
||||||
-- Like 'getsHaveCacheControlHeader', but for @HEAD@ requests.
|
-- Like 'getsHaveCacheControlHeader', but for @HEAD@ requests.
|
||||||
|
--
|
||||||
|
-- #SINCE#
|
||||||
headsHaveCacheControlHeader :: RequestPredicate Text Bool
|
headsHaveCacheControlHeader :: RequestPredicate Text Bool
|
||||||
headsHaveCacheControlHeader
|
headsHaveCacheControlHeader
|
||||||
= RequestPredicate
|
= RequestPredicate
|
||||||
@ -254,6 +259,8 @@ linkHeadersAreValid
|
|||||||
-- __References__:
|
-- __References__:
|
||||||
--
|
--
|
||||||
-- * @WWW-Authenticate@ header: <https://tools.ietf.org/html/rfc7235#section-4.1 RFC 7235 Section 4.1>
|
-- * @WWW-Authenticate@ header: <https://tools.ietf.org/html/rfc7235#section-4.1 RFC 7235 Section 4.1>
|
||||||
|
--
|
||||||
|
-- #SINCE#
|
||||||
unauthorizedContainsWWWAuthenticate :: ResponsePredicate Text Bool
|
unauthorizedContainsWWWAuthenticate :: ResponsePredicate Text Bool
|
||||||
unauthorizedContainsWWWAuthenticate
|
unauthorizedContainsWWWAuthenticate
|
||||||
= ResponsePredicate "unauthorizedContainsWWWAuthenticate" (\resp ->
|
= ResponsePredicate "unauthorizedContainsWWWAuthenticate" (\resp ->
|
||||||
@ -331,6 +338,8 @@ instance JoinPreds (ResponsePredicate Text Bool) where
|
|||||||
-- the existing predicates.
|
-- the existing predicates.
|
||||||
--
|
--
|
||||||
-- > not500 <%> onlyJsonObjects <%> empty
|
-- > not500 <%> onlyJsonObjects <%> empty
|
||||||
|
--
|
||||||
|
-- #SINCE#
|
||||||
(<%>) :: JoinPreds a => a -> Predicates [Text] [Text] -> Predicates [Text] [Text]
|
(<%>) :: JoinPreds a => a -> Predicates [Text] [Text] -> Predicates [Text] [Text]
|
||||||
(<%>) = joinPreds
|
(<%>) = joinPreds
|
||||||
infixr 6 <%>
|
infixr 6 <%>
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import Network.HTTP.Client (Manager, Request, checkStatus,
|
|||||||
defaultManagerSettings, httpLbs,
|
defaultManagerSettings, httpLbs,
|
||||||
newManager)
|
newManager)
|
||||||
import Network.Wai.Handler.Warp (withApplication)
|
import Network.Wai.Handler.Warp (withApplication)
|
||||||
|
import Prelude.Compat
|
||||||
import Servant (Context (EmptyContext), HasServer,
|
import Servant (Context (EmptyContext), HasServer,
|
||||||
Server, serveWithContext)
|
Server, serveWithContext)
|
||||||
import Servant.Client (BaseUrl (..), Scheme (..))
|
import Servant.Client (BaseUrl (..), Scheme (..))
|
||||||
@ -23,12 +24,16 @@ import Servant.QuickCheck.Internal.Equality
|
|||||||
|
|
||||||
-- | Start a servant application on an open port, run the provided function,
|
-- | Start a servant application on an open port, run the provided function,
|
||||||
-- then stop the application.
|
-- then stop the application.
|
||||||
|
--
|
||||||
|
-- #SINCE#
|
||||||
withServantServer :: HasServer a '[] => Proxy a -> IO (Server a)
|
withServantServer :: HasServer a '[] => Proxy a -> IO (Server a)
|
||||||
-> (BaseUrl -> IO r) -> IO r
|
-> (BaseUrl -> IO r) -> IO r
|
||||||
withServantServer api = withServantServerAndContext api EmptyContext
|
withServantServer api = withServantServerAndContext api EmptyContext
|
||||||
|
|
||||||
-- | Like 'withServantServer', but allows passing in a 'Context' to the
|
-- | Like 'withServantServer', but allows passing in a 'Context' to the
|
||||||
-- application.
|
-- application.
|
||||||
|
--
|
||||||
|
-- #SINCE#
|
||||||
withServantServerAndContext :: HasServer a ctx
|
withServantServerAndContext :: HasServer a ctx
|
||||||
=> Proxy a -> Context ctx -> IO (Server a) -> (BaseUrl -> IO r) -> IO r
|
=> Proxy a -> Context ctx -> IO (Server a) -> (BaseUrl -> IO r) -> IO r
|
||||||
withServantServerAndContext api ctx server t
|
withServantServerAndContext api ctx server t
|
||||||
@ -46,6 +51,8 @@ withServantServerAndContext api ctx server t
|
|||||||
--
|
--
|
||||||
-- Evidently, if the behaviour of the server is expected to be
|
-- Evidently, if the behaviour of the server is expected to be
|
||||||
-- non-deterministic, this function may produce spurious failures
|
-- non-deterministic, this function may produce spurious failures
|
||||||
|
--
|
||||||
|
-- #SINCE#
|
||||||
serversEqual :: HasGenRequest a =>
|
serversEqual :: HasGenRequest a =>
|
||||||
Proxy a -> BaseUrl -> BaseUrl -> Args -> ResponseEquality LBS.ByteString -> Expectation
|
Proxy a -> BaseUrl -> BaseUrl -> Args -> ResponseEquality LBS.ByteString -> Expectation
|
||||||
serversEqual api burl1 burl2 args req = do
|
serversEqual api burl1 burl2 args req = do
|
||||||
@ -78,6 +85,8 @@ serversEqual api burl1 burl2 args req = do
|
|||||||
-- > <%> onlyJsonObjects
|
-- > <%> onlyJsonObjects
|
||||||
-- > <%> notAllowedContainsAllowHeader
|
-- > <%> notAllowedContainsAllowHeader
|
||||||
-- > <%> mempty)
|
-- > <%> mempty)
|
||||||
|
--
|
||||||
|
-- #SINCE#
|
||||||
serverSatisfies :: (HasGenRequest a) =>
|
serverSatisfies :: (HasGenRequest a) =>
|
||||||
Proxy a -> BaseUrl -> Args -> Predicates [Text] [Text] -> Expectation
|
Proxy a -> BaseUrl -> Args -> Predicates [Text] [Text] -> Expectation
|
||||||
serverSatisfies api burl args preds = do
|
serverSatisfies api burl args preds = do
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user