Skip to content

Make type field optional for tests and benchmarks #8115

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
May 1, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions Cabal-syntax/src/Distribution/PackageDescription/FieldGrammar.hs
Original file line number Diff line number Diff line change
Expand Up @@ -325,7 +325,7 @@ testSuiteFieldGrammar = TestSuiteStanza
^^^ availableSince CabalSpecV3_6 [] -- TODO 3_8

validateTestSuite :: Position -> TestSuiteStanza -> ParseResult TestSuite
validateTestSuite pos stanza = case _testStanzaTestType stanza of
validateTestSuite pos stanza = case testSuiteType of
Nothing -> pure basicTestSuite

Just tt@(TestTypeUnknown _ _) ->
Expand Down Expand Up @@ -357,6 +357,11 @@ validateTestSuite pos stanza = case _testStanzaTestType stanza of
{ testInterface = TestSuiteLibV09 ver module_ }

where
testSuiteType =
_testStanzaTestType stanza
<|> testTypeExe <$ _testStanzaMainIs stanza
<|> testTypeLib <$ _testStanzaTestModule stanza

missingField name tt = "The '" ++ name ++ "' field is required for the "
++ prettyShow tt ++ " test suite type."

Expand Down Expand Up @@ -442,7 +447,7 @@ benchmarkFieldGrammar = BenchmarkStanza
<*> blurFieldGrammar benchmarkStanzaBuildInfo buildInfoFieldGrammar

validateBenchmark :: Position -> BenchmarkStanza -> ParseResult Benchmark
validateBenchmark pos stanza = case _benchmarkStanzaBenchmarkType stanza of
validateBenchmark pos stanza = case benchmarkStanzaType of
Nothing -> pure emptyBenchmark
{ benchmarkBuildInfo = _benchmarkStanzaBuildInfo stanza }

Expand All @@ -469,6 +474,10 @@ validateBenchmark pos stanza = case _benchmarkStanzaBenchmarkType stanza of
}

where
benchmarkStanzaType =
_benchmarkStanzaBenchmarkType stanza
<|> benchmarkTypeExe <$ _benchmarkStanzaMainIs stanza

missingField name tt = "The '" ++ name ++ "' field is required for the "
++ prettyShow tt ++ " benchmark type."

Expand Down
12 changes: 4 additions & 8 deletions Cabal-syntax/src/Distribution/PackageDescription/Parsec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -319,10 +319,8 @@ goSections specVer = traverse_ process
let hasType ts = testInterface ts /= testInterface mempty
unless (onAllBranches hasType testSuite) $ lift $ parseFailure pos $ concat
[ "Test suite " ++ show (prettyShow name')
, " is missing required field \"type\" or the field "
, "is not present in all conditional branches. The "
, "available test types are: "
, intercalate ", " (map prettyShow knownTestTypes)
, " is missing required field \"main-is\" or the field "
, "is not present in all conditional branches."
]

-- TODO check duplicate name here?
Expand All @@ -337,10 +335,8 @@ goSections specVer = traverse_ process
let hasType ts = benchmarkInterface ts /= benchmarkInterface mempty
unless (onAllBranches hasType bench) $ lift $ parseFailure pos $ concat
[ "Benchmark " ++ show (prettyShow name')
, " is missing required field \"type\" or the field "
, "is not present in all conditional branches. The "
, "available benchmark types are: "
, intercalate ", " (map prettyShow knownBenchmarkTypes)
, " is missing required field \"main-is\" or the field "
, "is not present in all conditional branches."
]

-- TODO check duplicate name here?
Expand Down
3 changes: 1 addition & 2 deletions Cabal-syntax/src/Distribution/Types/BenchmarkInterface.hs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@ import Distribution.Compat.Prelude
import Distribution.Types.BenchmarkType
import Distribution.Version

-- | The benchmark interfaces that are currently defined. Each
-- benchmark must specify which interface it supports.
-- | The benchmark interfaces that are currently defined.
--
-- More interfaces may be defined in future, either new revisions or
-- totally new interfaces.
Expand Down
6 changes: 5 additions & 1 deletion Cabal-syntax/src/Distribution/Types/BenchmarkType.hs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
module Distribution.Types.BenchmarkType (
BenchmarkType(..),
knownBenchmarkTypes,
benchmarkTypeExe,
) where

import Distribution.Compat.Prelude
Expand All @@ -28,7 +29,10 @@ instance Structured BenchmarkType
instance NFData BenchmarkType where rnf = genericRnf

knownBenchmarkTypes :: [BenchmarkType]
knownBenchmarkTypes = [ BenchmarkTypeExe (mkVersion [1,0]) ]
knownBenchmarkTypes = [ benchmarkTypeExe ]

benchmarkTypeExe :: BenchmarkType
benchmarkTypeExe = BenchmarkTypeExe (mkVersion [1,0])

instance Pretty BenchmarkType where
pretty (BenchmarkTypeExe ver) = text "exitcode-stdio-" <<>> pretty ver
Expand Down
3 changes: 1 addition & 2 deletions Cabal-syntax/src/Distribution/Types/TestSuiteInterface.hs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@ import Distribution.Types.TestType
import Distribution.ModuleName
import Distribution.Version

-- | The test suite interfaces that are currently defined. Each test suite must
-- specify which interface it supports.
-- | The test suite interfaces that are currently defined.
--
-- More interfaces may be defined in future, either new revisions or totally
-- new interfaces.
Expand Down
13 changes: 11 additions & 2 deletions Cabal-syntax/src/Distribution/Types/TestType.hs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
module Distribution.Types.TestType (
TestType(..),
knownTestTypes,
testTypeExe,
testTypeLib,
) where

import Distribution.Compat.Prelude
Expand All @@ -28,8 +30,15 @@ instance Structured TestType
instance NFData TestType where rnf = genericRnf

knownTestTypes :: [TestType]
knownTestTypes = [ TestTypeExe (mkVersion [1,0])
, TestTypeLib (mkVersion [0,9]) ]
knownTestTypes = [ testTypeExe
, testTypeLib
]

testTypeExe :: TestType
testTypeExe = TestTypeExe (mkVersion [1,0])

testTypeLib :: TestType
testTypeLib = TestTypeLib (mkVersion [0,9])

instance Pretty TestType where
pretty (TestTypeExe ver) = text "exitcode-stdio-" <<>> pretty ver
Expand Down
2 changes: 1 addition & 1 deletion Cabal-tests/tests/ParserTests/errors/issue-5055-2.errors
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
VERSION: Just (mkVersion [2,0])
issue-5055-2.cabal:15:1: Test suite "flag-cabal-test" is missing required field "type" or the field is not present in all conditional branches. The available test types are: exitcode-stdio-1.0, detailed-0.9
issue-5055-2.cabal:15:1: Test suite "flag-cabal-test" is missing required field "main-is" or the field is not present in all conditional branches.
2 changes: 1 addition & 1 deletion Cabal-tests/tests/ParserTests/errors/issue-5055.errors
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
VERSION: Just (mkVersion [2,0])
issue-5055.cabal:15:1: Test suite "flag-cabal-test" is missing required field "type" or the field is not present in all conditional branches. The available test types are: exitcode-stdio-1.0, detailed-0.9
issue-5055.cabal:15:1: Test suite "flag-cabal-test" is missing required field "main-is" or the field is not present in all conditional branches.
8 changes: 3 additions & 5 deletions Cabal-tests/tests/ParserTests/regressions/issue-5055.expr
Original file line number Diff line number Diff line change
Expand Up @@ -213,11 +213,9 @@ GenericPackageDescription {
condTreeData = TestSuite {
testName = UnqualComponentName
"",
testInterface =
TestSuiteUnsupported
(TestTypeUnknown
""
(mkVersion [])),
testInterface = TestSuiteExeV10
(mkVersion [1, 0])
"FirstMain.hs",
testBuildInfo = BuildInfo {
buildable = True,
buildTools = [],
Expand Down
2 changes: 2 additions & 0 deletions Cabal-tests/tests/ParserTests/regressions/issue-5055.format
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,5 @@ test-suite flag-cabal-test
build-depends: base >=4.8 && <5

if os(windows)
type: exitcode-stdio-1.0
main-is: FirstMain.hs
4 changes: 4 additions & 0 deletions Cabal/src/Distribution/PackageDescription/Check.hs
Original file line number Diff line number Diff line change
Expand Up @@ -322,12 +322,14 @@ checkTestSuite pkg test =
TestSuiteUnsupported tt@(TestTypeUnknown _ _) -> Just $
PackageBuildWarning $
quote (prettyShow tt) ++ " is not a known type of test suite. "
++ "Either remove the 'type' field or use a known type. "
++ "The known test suite types are: "
++ commaSep (map prettyShow knownTestTypes)

TestSuiteUnsupported tt -> Just $
PackageBuildWarning $
quote (prettyShow tt) ++ " is not a supported test suite version. "
++ "Either remove the 'type' field or use a known type. "
++ "The known test suite types are: "
++ commaSep (map prettyShow knownTestTypes)
_ -> Nothing
Expand Down Expand Up @@ -372,12 +374,14 @@ checkBenchmark _pkg bm =
BenchmarkUnsupported tt@(BenchmarkTypeUnknown _ _) -> Just $
PackageBuildWarning $
quote (prettyShow tt) ++ " is not a known type of benchmark. "
++ "Either remove the 'type' field or use a known type. "
++ "The known benchmark types are: "
++ commaSep (map prettyShow knownBenchmarkTypes)

BenchmarkUnsupported tt -> Just $
PackageBuildWarning $
quote (prettyShow tt) ++ " is not a supported benchmark version. "
++ "Either remove the 'type' field or use a known type. "
++ "The known benchmark types are: "
++ commaSep (map prettyShow knownBenchmarkTypes)
_ -> Nothing
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ benchmark solver-disabled
build-depends: a-package-that-does-not-exist

benchmark user-disabled
type: exitcode-stdio-1.0
main-is: Test.hs
build-depends: base

Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ build-type: Simple
cabal-version: >= 1.10

test-suite p1
type: exitcode-stdio-1.0
main-is: P1.hs
build-depends: base

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ executable an-exe
other-modules: AModule

test-suite a-testsuite
type: exitcode-stdio-1.0
main-is: Test.hs
other-modules: AModule

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ library
default-language: Haskell2010

test-suite foo
type: detailed-0.9
test-module: Foo
hs-source-dirs: tests
build-depends: base, Cabal, DuplicateModuleName
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ build-type: Simple
cabal-version: >= 1.10

benchmark foo
type: exitcode-stdio-1.0
main-is: Foo.hs
build-depends: base
default-language: Haskell2010
Expand Down
10 changes: 10 additions & 0 deletions changelog.d/pr-8115
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
synopsis: Make type field optional for tests and benchmarks
packages: Cabal, Cabal-syntax
prs: #8115
issues: #7459
description: {

Allow the ommission of the `type` field in `test-suite` and `benchmark` stanzas
when the type can be inferred by the presence of `main-is` or `test-module`.

}
30 changes: 4 additions & 26 deletions doc/cabal-package.rst
Original file line number Diff line number Diff line change
Expand Up @@ -926,7 +926,6 @@ look something like this:
default-language: Haskell2010

test-suite test-foo
type: exitcode-stdio-1.0
main-is: test-foo.hs
-- NOTE: no constraints on 'foo-internal' as same-package
-- dependencies implicitly refer to the same package instance
Expand Down Expand Up @@ -1188,14 +1187,14 @@ Test suites
The test suite may be described using the following fields, as well as
build information fields (see the section on `build information`_).

.. pkg-field:: type: interface (required)
.. pkg-field:: type: interface

The interface type and version of the test suite. Cabal supports two
test suite interfaces, called ``exitcode-stdio-1.0`` and
test suite interfaces, called ``exitcode-stdio-1.0`` (default) and
``detailed-0.9``. Each of these types may require or disallow other
fields as described below.

Test suites using the ``exitcode-stdio-1.0`` interface are executables
Test suites using the ``exitcode-stdio-1.0`` (default) interface are executables
that indicate test failure with a non-zero exit code when run; they may
provide human-readable log information through the standard output and
error channels. The ``exitcode-stdio-1.0`` type requires the ``main-is``
Expand All @@ -1204,7 +1203,6 @@ field.
.. pkg-field:: main-is: filename
:synopsis: Module containing tests main function.

:required: ``exitcode-stdio-1.0``
:disallowed: ``detailed-0.9``

The name of the ``.hs`` or ``.lhs`` file containing the ``Main``
Expand All @@ -1226,7 +1224,6 @@ the :pkg-field:`test-module` field.

.. pkg-field:: test-module: identifier

:required: ``detailed-0.9``
:disallowed: ``exitcode-stdio-1.0``

The module exporting the ``tests`` symbol.
Expand All @@ -1247,7 +1244,6 @@ demonstrate the use of the ``exitcode-stdio-1.0`` interface.
Build-Type: Simple

Test-Suite test-foo
type: exitcode-stdio-1.0
main-is: test-foo.hs
build-depends: base >= 4 && < 5
default-language: Haskell2010
Expand Down Expand Up @@ -1282,7 +1278,6 @@ be provided by the library that provides the testing facility.
Build-Type: Simple

Test-Suite test-bar
type: detailed-0.9
test-module: Bar
build-depends: base >= 4 && < 5, Cabal >= 1.9.2 && < 2
default-language: Haskell2010
Expand Down Expand Up @@ -1345,20 +1340,8 @@ Benchmarks
The benchmark may be described using the following fields, as well as
build information fields (see the section on `build information`_).

.. pkg-field:: type: interface (required)

The interface type and version of the benchmark. At the moment Cabal
only support one benchmark interface, called ``exitcode-stdio-1.0``.

Benchmarks using the ``exitcode-stdio-1.0`` interface are executables
that indicate failure to run the benchmark with a non-zero exit code
when run; they may provide human-readable information through the
standard output and error channels.

.. pkg-field:: main-is: filename

:required: ``exitcode-stdio-1.0``

The name of the ``.hs`` or ``.lhs`` file containing the ``Main``
module. Note that it is the ``.hs`` filename that must be listed,
even if that file is generated using a preprocessor. The source file
Expand All @@ -1367,12 +1350,9 @@ standard output and error channels.
field of an executable section. Further, while the name of the file may
vary, the module itself must be named ``Main``.

Example: Package using ``exitcode-stdio-1.0`` interface
Example:
"""""""""""""""""""""""""""""""""""""""""""""""""""""""

The example package description and executable source file below
demonstrate the use of the ``exitcode-stdio-1.0`` interface.

.. code-block:: cabal
:caption: foo.cabal
:name: foo-bench.cabal
Expand All @@ -1384,7 +1364,6 @@ demonstrate the use of the ``exitcode-stdio-1.0`` interface.
Build-Type: Simple

Benchmark bench-foo
type: exitcode-stdio-1.0
main-is: bench-foo.hs
build-depends: base >= 4 && < 5, time >= 1.1 && < 1.7
default-language: Haskell2010
Expand Down Expand Up @@ -2719,7 +2698,6 @@ Starting with Cabal-2.2 it's possible to use common build info stanzas.

test-suite tests
import: deps, test-deps
type: exitcode-stdio-1.0
main-is: Tests.hs
build-depends: foo
default-language: Haskell2010
Expand Down