roboservant 0.1.0.0 → 0.1.0.1
raw patch · 4 files changed
+18/−18 lines, 4 filesPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
API changes (from Hackage documentation)
- Roboservant.StateMachine: ApiOffset :: Int -> ApiOffset
- Roboservant.StateMachine: Op :: ApiOffset -> [(TypeRep, Var (Opaque (IORef Dynamic)) v)] -> Op
- Roboservant.StateMachine: State :: Map TypeRep (NonEmpty (Var (Opaque (IORef Dynamic)) v)) -> State v
- Roboservant.StateMachine: [AnEndpoint] :: Server endpoint -> Bundled endpoints -> Bundled (endpoint : endpoints)
- Roboservant.StateMachine: [NoEndpoints] :: Bundled '[]
- Roboservant.StateMachine: [stateRefs] :: State v -> Map TypeRep (NonEmpty (Var (Opaque (IORef Dynamic)) v))
- Roboservant.StateMachine: callEndpoint :: (MonadGen n, MonadIO m) => ReifiedApi -> Command n m State
- Roboservant.StateMachine: class FlattenServer api
- Roboservant.StateMachine: class NormalizeFunction m where {
- Roboservant.StateMachine: class ToReifiedApi (endpoints :: [*])
- Roboservant.StateMachine: class ToReifiedEndpoint (endpoint :: *)
- Roboservant.StateMachine: data Bundled endpoints
- Roboservant.StateMachine: data Op (v :: * -> *)
- Roboservant.StateMachine: data State v
- Roboservant.StateMachine: flattenServer :: FlattenServer api => Server api -> Bundled (Endpoints api)
- Roboservant.StateMachine: newtype ApiOffset
- Roboservant.StateMachine: normalize :: NormalizeFunction m => m -> Normal m
- Roboservant.StateMachine: toReifiedApi :: ToReifiedApi endpoints => Bundled endpoints -> Proxy endpoints -> ReifiedApi
- Roboservant.StateMachine: toReifiedEndpoint :: ToReifiedEndpoint endpoint => Dynamic -> Proxy endpoint -> ReifiedEndpoint
- Roboservant.StateMachine: type ReifiedApi = [(ApiOffset, [TypeRep], TypeRep, Dynamic)]
- Roboservant.StateMachine: type ReifiedEndpoint = ([TypeRep], TypeRep, Dynamic)
- Roboservant.StateMachine: type family Normal m;
- Roboservant.StateMachine: }
- Roboservant.StateMachine: prop_concurrent :: ReifiedApi -> Property
+ Roboservant.StateMachine: prop_concurrent :: forall api. (FlattenServer api, ToReifiedApi (Endpoints api)) => Server api -> Property
- Roboservant.StateMachine: prop_sequential :: ReifiedApi -> Property
+ Roboservant.StateMachine: prop_sequential :: forall api. (FlattenServer api, ToReifiedApi (Endpoints api)) => Server api -> Property
Files
- README.md +1/−2
- roboservant.cabal +3/−3
- src/Roboservant/StateMachine.hs +10/−5
- test/Spec.hs +4/−8
README.md view
@@ -29,9 +29,8 @@ From the tests: ```- let reifiedApi = RS.toReifiedApi (RS.flattenServer @Foo.FooApi Foo.fooServer) (Proxy @(Endpoints Foo.FooApi)) assert "should find an error in Foo" . not- =<< checkSequential (Group "Foo" [("Foo", RS.prop_sequential reifiedApi)])+ =<< checkSequential (Group "Foo" [("Foo", RS.prop_sequential @Foo.FooApi Foo.fooServer)]) ``` We have a server that blows up if the value of the int in a `Foo` ever gets above 10. Note:
roboservant.cabal view
@@ -4,12 +4,12 @@ -- -- see: https://github.com/sol/hpack ----- hash: 51154f1c866aea92673a52985de6810cebda3b2662fddd7b7f88a56725e30041+-- hash: 24c3d87b15d4d45c7a72d5972edaef1acc1bef842dc9b7b5bbf625bc14f04199 name: roboservant-version: 0.1.0.0+version: 0.1.0.1 synopsis: Automatic session-aware servant testing-description: Please see the README on GitHub at <https://github.com/githubuser/roboservant#readme>+description: Please see the README on GitHub at <https://github.com/mwotton/roboservant#readme> category: Web homepage: https://github.com/mwotton/roboservant#readme bug-reports: https://github.com/mwotton/roboservant/issues
src/Roboservant/StateMachine.hs view
@@ -16,7 +16,10 @@ {-# LANGUAGE TypeOperators #-} {-# LANGUAGE UndecidableInstances #-} -module Roboservant.StateMachine where+module Roboservant.StateMachine+( prop_sequential+, prop_concurrent+) where import Control.Monad.Except (runExceptT) import Control.Monad.IO.Class (MonadIO, liftIO)@@ -223,8 +226,9 @@ -- , Ensure (no-500 here) ] -prop_sequential :: ReifiedApi -> Property-prop_sequential reifiedApi = do+prop_sequential :: forall api. (FlattenServer api, ToReifiedApi (Endpoints api)) => Server api -> Property+prop_sequential server = do+ let reifiedApi = toReifiedApi (flattenServer @api server) (Proxy @(Endpoints api)) property $ do let initialState = State mempty actions <-@@ -235,8 +239,9 @@ [callEndpoint reifiedApi] executeSequential initialState actions -prop_concurrent :: ReifiedApi -> Property-prop_concurrent reifiedApi =+prop_concurrent :: forall api. (FlattenServer api, ToReifiedApi (Endpoints api)) => Server api -> Property+prop_concurrent server =+ let reifiedApi = toReifiedApi (flattenServer @api server) (Proxy @(Endpoints api)) in let initialState = State mempty in withTests 1000 . withRetries 10 . property $ do actions <-
test/Spec.hs view
@@ -1,11 +1,9 @@ {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE TypeApplications #-} -import Data.Proxy (Proxy (..)) import qualified Foo-import Hedgehog (Group (..), checkSequential)+import Hedgehog (Group (..), checkSequential, withTests) import qualified Roboservant as RS-import Servant (Endpoints) import qualified UnsafeIO -- | this is pretty bad. hopefully Jacob knows a better way of doing this.@@ -17,15 +15,13 @@ -- | This is horribly laid out, sorry. Will fix at some point. main :: IO () main = do- let reifiedApi = RS.toReifiedApi (RS.flattenServer @Foo.FooApi Foo.fooServer) (Proxy @(Endpoints Foo.FooApi)) assert "should find an error in Foo" . not- =<< checkSequential (Group "Foo" [("Foo", RS.prop_sequential reifiedApi)])+ =<< checkSequential (Group "Foo" [("Foo", withTests 1000 $ RS.prop_sequential @Foo.FooApi Foo.fooServer)]) -- The UnsafeIO checker does not actually really use the contextually aware stuff, though it -- could: it's mostly here to show how to test for concurrency problems. unsafeServer <- UnsafeIO.makeServer- let unsafeApi = RS.toReifiedApi (RS.flattenServer @UnsafeIO.UnsafeApi unsafeServer) (Proxy @(Endpoints UnsafeIO.UnsafeApi)) -- this will not detect the error, as it requires concurrency.- assert "should find nothing" =<< checkSequential (Group "Unsafe" [("Sequential", RS.prop_sequential unsafeApi)])+ assert "should find nothing" =<< checkSequential (Group "Unsafe" [("Sequential", RS.prop_sequential @UnsafeIO.UnsafeApi unsafeServer)]) -- this will! assert "should find with parallel check" . not- =<< checkSequential (Group "Unsafe" [("Parallel", RS.prop_concurrent unsafeApi)])+ =<< checkSequential (Group "Unsafe" [("Parallel", withTests 100000 $ RS.prop_concurrent @UnsafeIO.UnsafeApi unsafeServer)])