Commit c81d400e authored by Steffen Michels's avatar Steffen Michels

Merge branch 'properties-on-instances' into 'master'

Support @property and friends on instances

Closes #3

See merge request !2
parents f2ead2e9 6c3fe26e
Pipeline #28986 passed with stage
in 1 minute and 44 seconds
......@@ -18,7 +18,7 @@ Minimal test suites use only \nameref{sec:property}, though \nameref{sec:propert
\subsubsection{\clean{@property}}
\label{sec:property}
\availableon{functions}
\availableon{functions; instances}
In properties, the full Clean syntax can be used to specify Gast properties.
Since Gast is automatically imported (see \cref{sec:property-bootstrap}), you can use its combinators.
The first line of a property indicates its name and arguments.
......@@ -86,7 +86,7 @@ Then we can use this invariant in the definition of the correctness property of
\subsubsection{\clean{@precondition}}
\label{sec:precondition}
\availableon{functions}
\availableon{functions; instances}
This is a convenience field for functions that already have a(t least one) \nameref{sec:property} field.
Its content should be an arbitrary Clean expression with type \clean{Bool} or \clean{Property}.
......@@ -157,7 +157,7 @@ For example:
\subsubsection{\clean{@property-test-with}}
\label{sec:property-test-with}
\availableon{modules; functions}
\availableon{modules; functions; instances}
With this field it is possible to abstract from concrete types in property signatures and still allow Gast to generate test values.
We can specify the correctness property of \module{Data.Set}'s \clean{member} function (\cref{sec:property}) more abstractly using \clean{a} instead of \clean{Int}:
......
......@@ -44,8 +44,10 @@ from syntax import
:: Ident{id_name},
:: Module{mod_defs,mod_ident},
:: Optional,
:: ParsedDefinition(PD_Function,PD_Type,PD_TypeSpec),
:: ParsedDefinition(PD_Function,PD_Instance,PD_Instances,PD_Type,PD_TypeSpec),
:: ParsedExpr,
:: ParsedInstance{pi_ident},
:: ParsedInstanceAndMembers{pim_pi},
:: ParsedTypeDef,
:: Position,
:: Priority,
......@@ -241,12 +243,21 @@ handleModule opts fp w
opts.print_options
opts.test_options
moddoc
// Functions:
[(id.id_name,doc) \\
(pd,id) <-
[(pd,id) \\ pd=:(PD_Function pos id _ _ _ _) <- dcldefs] ++
[(pd,id) \\ pd=:(PD_TypeSpec pos id _ _ _) <- dcldefs],
Just docstring <- [getComment pd documentation],
doc <- parseDocWithWarnings docstring]
// Instances:
[(id.id_name,doc) \\
(pd,id) <-
[(pd,id) \\ pd=:(PD_Instance {pim_pi=pim_pi=:{pi_ident=id}}) <- dcldefs] ++
[(pd,id) \\ pd=:(PD_Instances piams) <- dcldefs, {pim_pi=pim_pi=:{pi_ident=id}} <- piams],
Just docstring <- [getComment pd documentation],
doc <- parseDocWithWarnings docstring]
// Type definitions:
[(id.id_name,doc) \\
pd=:(PD_Type {td_ident=id}) <- dcldefs,
Just docstring <- [getComment pd documentation],
......@@ -300,13 +311,15 @@ where
Right (r,ws) -> traceParseWarnings ws [r]
generatePropertyModule :: !String !String ![String] ![String] !(Maybe ModuleDoc)
![(!String, !FunctionDoc)] ![(!String, !TypeDoc)]
![(String, FunctionDoc)]
![(String, InstanceDoc)]
![(String, TypeDoc)]
-> (!Int, !Real, !String)
generatePropertyModule testmodname modname print_options test_options mod_doc fes tes
generatePropertyModule testmodname modname print_options test_options mod_doc fes ies tes
= (n_props, coverage, tests)
where
n_props = length props
coverage = toReal (length (filter (not o isEmpty) propsets)) / toReal (length fes)
coverage = toReal (length (filter (not o isEmpty) propsets)) / toReal (length fes + length ies)
tests = join "\n\n"
[ "module " +++ testmodname
, join "\n"
......@@ -323,8 +336,11 @@ where
: [gp.gp_implementation \\ gp <- props]
]
propsets = map (uncurry $ generateProperties modname pvis generators) fes
where pvis = fromMaybe [] $ docPropertyTestWith <$> mod_doc
propsets = handle fes ++ handle ies
where
handle :: ([(String,doc)] -> [[GeneratedProperty]]) | docPreconditions, docProperties, docPropertyTestWith doc
handle = map (uncurry $ generateProperties modname pvis generators)
pvis = fromMaybe [] $ docPropertyTestWith <$> mod_doc
props = flatten propsets
bootstrap = fromMaybe "" (docPropertyBootstrap =<< mod_doc)
......@@ -378,10 +394,11 @@ where
, ga_ptg :: !Maybe NamedTestGenerator // the generator used
}
generateProperties :: !String ![PropertyVarInstantiation] ![NamedTestGenerator] !String !FunctionDoc -> [GeneratedProperty]
generateProperties :: !String ![PropertyVarInstantiation] ![NamedTestGenerator] !String
!doc -> [GeneratedProperty] | docPreconditions, docProperties, docPropertyTestWith doc
generateProperties modname pvis generators fname doc =
[gen i fname doc.preconditions p config
\\ p <- doc.properties
[gen i fname (docPreconditions doc) p config
\\ p <- docProperties doc
, config <- configurationsForProperty p (pvis ++ docPropertyTestWith doc)
& i <- [1..]]
where
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment