From 6c80daaf562c2672fd002b89c1f7de22a7c8c823 Mon Sep 17 00:00:00 2001 From: Maximilian Algehed Date: Tue, 7 Oct 2025 14:37:56 +0200 Subject: [PATCH 1/5] Implement coveralls support --- .github/workflows/haskell-ci.yml | 50 ++++++++++++++++++++++++++++++-- constrained-generators.cabal | 9 ++++-- stack.yaml | 4 +++ stack.yaml.lock | 12 ++++++++ test/Constrained/Tests.hs | 9 ++++-- 5 files changed, 75 insertions(+), 9 deletions(-) create mode 100644 stack.yaml create mode 100644 stack.yaml.lock diff --git a/.github/workflows/haskell-ci.yml b/.github/workflows/haskell-ci.yml index 2e71619..b49097f 100644 --- a/.github/workflows/haskell-ci.yml +++ b/.github/workflows/haskell-ci.yml @@ -1,4 +1,6 @@ name: Haskell-CI +permissions: + contents: read on: push: @@ -15,13 +17,13 @@ concurrency: cancel-in-progress: true jobs: - linux: - name: Haskell-CI - Linux - ${{ matrix.ghc-version }} + test-with-cabal: + name: Haskell-CI - Linux - cabal - ${{ matrix.ghc-version }} strategy: matrix: ghc-version: [latest, 9.12, "9.10", 9.8, 9.6] - os: [ubuntu-24.04] + os: [ubuntu-latest] fail-fast: false runs-on: ${{ matrix.os }} @@ -43,3 +45,45 @@ jobs: with: key: ${{ matrix.os }}-${{ matrix.ghc-version }}-${{ github.sha }} path: ~/.cabal/store + + test-with-stack: + name: Stack + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: haskell-actions/setup@v2 + id: setup-haskell-stack + name: Setup Haskell + with: + enable-stack: true + stack-version: latest + ghc-version: 9.6.7 + + - name: Cache + id: cache + uses: actions/cache@v4 + with: + path: | + ${{ steps.setup-haskell-stack.outputs.stack-root }} + .stack-work + key: ${{ runner.os }}-stack-${{ github.sha }} + restore-keys: ${{ runner.os }}-stack + + - name: Test + run: stack test --coverage --flag constrained-generators:devel + + - uses: actions/cache/save@v4 + with: + path: | + ${{ steps.setup-haskell-stack.outputs.stack-root }} + .stack-work + key: ${{ runner.os }}-stack-${{ github.sha }} + + - name: Upload coverage report + env: + COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_REPO_TOKEN }} + run: | + [ -n "${COVERALLS_REPO_TOKEN}" ] + curl -L https://github.com/rubik/stack-hpc-coveralls/releases/download/v0.0.7.0/shc-Linux-X64.tar.bz2 | tar xj shc + ./shc --repo-token="$COVERALLS_REPO_TOKEN" --partial-coverage --fetch-coverage combined all diff --git a/constrained-generators.cabal b/constrained-generators.cabal index 1b487af..0991f97 100644 --- a/constrained-generators.cabal +++ b/constrained-generators.cabal @@ -121,7 +121,7 @@ library examples prettyprinter, random, -test-suite constrained +test-suite constrained-tests type: exitcode-stdio-1.0 main-is: Tests.hs hs-source-dirs: test @@ -141,9 +141,12 @@ test-suite constrained QuickCheck, base, constrained-generators, - constrained-generators:examples, containers, - hspec, + hspec + + if !flag(devel) + build-depends: + constrained-generators:examples benchmark bench type: exitcode-stdio-1.0 diff --git a/stack.yaml b/stack.yaml new file mode 100644 index 0000000..01c0455 --- /dev/null +++ b/stack.yaml @@ -0,0 +1,4 @@ +snapshot: lts-22.44 +packages: +- . +system-ghc: true diff --git a/stack.yaml.lock b/stack.yaml.lock new file mode 100644 index 0000000..8d134eb --- /dev/null +++ b/stack.yaml.lock @@ -0,0 +1,12 @@ +# This file was autogenerated by Stack. +# You should not edit this file by hand. +# For more information, please see the documentation at: +# https://docs.haskellstack.org/en/stable/topics/lock_files + +packages: [] +snapshots: +- completed: + sha256: 238fa745b64f91184f9aa518fe04bdde6552533d169b0da5256670df83a0f1a9 + size: 721141 + url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/22/44.yaml + original: lts-22.44 diff --git a/test/Constrained/Tests.hs b/test/Constrained/Tests.hs index 9edbc96..fae502b 100644 --- a/test/Constrained/Tests.hs +++ b/test/Constrained/Tests.hs @@ -1,4 +1,5 @@ {-# LANGUAGE AllowAmbiguousTypes #-} +{-# LANGUAGE CPP #-} {-# LANGUAGE ConstraintKinds #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE FlexibleContexts #-} @@ -59,6 +60,9 @@ testAll = hspec $ tests False tests :: Bool -> Spec tests nightly = describe "constrained" . modifyMaxSuccess (\ms -> if nightly then ms * 10 else ms) $ do + testSpec "setOfPairLetSpec" setOfPairLetSpec + testSpec "setPair" setPair + testSpec "mapElemSpec" mapElemSpec testSpec "complicatedEither" complicatedEither testSpec "pairCant" pairCant -- TODO: figure out why this doesn't shrink @@ -70,7 +74,6 @@ tests nightly = testSpec "assertRealMultiple" assertRealMultiple testSpec "setSpec" setSpec testSpec "leqPair" leqPair - testSpec "setPair" setPair testSpecNoShrink "listEmpty" listEmpty testSpec "compositionalSpec" compositionalSpec testSpec "simplePairSpec" simplePairSpec @@ -80,7 +83,6 @@ tests nightly = testSpec "maybeSpec" maybeSpec testSpecNoShrink "eitherSetSpec" eitherSetSpec testSpec "fooSpec" fooSpec - testSpec "mapElemSpec" mapElemSpec testSpec "mapElemKeySpec" mapElemKeySpec -- TODO: figure out why this doesn't shrink testSpecNoShrink "mapIsJust" mapIsJust @@ -95,7 +97,6 @@ tests nightly = -- more detailed shrinking of `SuspendedSpec`s testSpecNoShrink "setPairSpec" setPairSpec testSpec "fixedSetSpec" fixedSetSpec - testSpec "setOfPairLetSpec" setOfPairLetSpec testSpecNoShrink "emptyEitherSpec" emptyEitherSpec testSpecNoShrink "emptyEitherMemberSpec" emptyEitherMemberSpec testSpec "setSingletonSpec" setSingletonSpec @@ -315,11 +316,13 @@ testSpec' withShrink n s = do checkCoverage' $ prop_constrained_explained s +#if MIN_VERSION_QuickCheck(2, 16, 0) when withShrink $ prop "prop_shrink_sound" $ discardAfter 100_000 $ checkCoverage' $ prop_shrink_sound s +#endif ------------------------------------------------------------------------ -- Test properties of the instance Num (NumSpec Integer) From 4f0c40301a72d87eb977281725fa7f18067f6c67 Mon Sep 17 00:00:00 2001 From: Maximilian Algehed Date: Mon, 13 Oct 2025 10:55:20 +0200 Subject: [PATCH 2/5] old name to avoid annoying ci issues --- .github/workflows/haskell-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/haskell-ci.yml b/.github/workflows/haskell-ci.yml index b49097f..d75c4d3 100644 --- a/.github/workflows/haskell-ci.yml +++ b/.github/workflows/haskell-ci.yml @@ -18,7 +18,7 @@ concurrency: jobs: test-with-cabal: - name: Haskell-CI - Linux - cabal - ${{ matrix.ghc-version }} + name: Haskell-CI - Linux - ${{ matrix.ghc-version }} strategy: matrix: From d30af162b1b9a286eecbe2a8b1385530e2d379c1 Mon Sep 17 00:00:00 2001 From: Maximilian Algehed Date: Mon, 13 Oct 2025 11:18:38 +0200 Subject: [PATCH 3/5] test coverage improvement reporting --- examples/Constrained/Examples/Basic.hs | 3 +++ src/Constrained/NumOrd.hs | 27 ++++++++++++++++++++++++++ test/Constrained/Tests.hs | 1 + 3 files changed, 31 insertions(+) diff --git a/examples/Constrained/Examples/Basic.hs b/examples/Constrained/Examples/Basic.hs index bbda1ae..fda7fbe 100644 --- a/examples/Constrained/Examples/Basic.hs +++ b/examples/Constrained/Examples/Basic.hs @@ -363,3 +363,6 @@ pairCant = constrained' $ \ [var| i |] [var| p |] -> , not_ $ k `elem_` lit [1..9] ] ] + +signumPositive :: Specification Rational +signumPositive = constrained $ \ x -> signum (x * 30) >=. 1 diff --git a/src/Constrained/NumOrd.hs b/src/Constrained/NumOrd.hs index df4027a..021f809 100644 --- a/src/Constrained/NumOrd.hs +++ b/src/Constrained/NumOrd.hs @@ -774,6 +774,33 @@ instance {-# OVERLAPPABLE #-} (HasSpec a, MaybeBounded a, Integral a, TypeSpec a then r - signum a else r +instance HasDivision (Ratio Integer) where + doDivide = (/) + + divideSpec 0 _ = TrueSpec + divideSpec a (NumSpecInterval ml mu) = typeSpec ts + where + ts | a > 0 = NumSpecInterval ml' mu' + | otherwise = NumSpecInterval mu' ml' + ml' = adjustLowerBound <$> ml + mu' = adjustUpperBound <$> mu + adjustLowerBound l = + let r = l / a + l' = r * a + in + if l' < l + then r + (l - l') * 2 / a + else r + + adjustUpperBound u = + let r = u / a + u' = r * a + in + if u < u' + then r - (u' - u) * 2 / a + else r + + instance HasDivision Float where doDivide = (/) diff --git a/test/Constrained/Tests.hs b/test/Constrained/Tests.hs index fae502b..f415226 100644 --- a/test/Constrained/Tests.hs +++ b/test/Constrained/Tests.hs @@ -60,6 +60,7 @@ testAll = hspec $ tests False tests :: Bool -> Spec tests nightly = describe "constrained" . modifyMaxSuccess (\ms -> if nightly then ms * 10 else ms) $ do + testSpec "signumPositive" signumPositive testSpec "setOfPairLetSpec" setOfPairLetSpec testSpec "setPair" setPair testSpec "mapElemSpec" mapElemSpec From 714117f13eb6d8a1914ce5fb9270a34ed29cf329 Mon Sep 17 00:00:00 2001 From: Maximilian Algehed Date: Mon, 13 Oct 2025 14:26:58 +0200 Subject: [PATCH 4/5] Fix QuickCheck version issue --- test/Constrained/Tests.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Constrained/Tests.hs b/test/Constrained/Tests.hs index f415226..6205f52 100644 --- a/test/Constrained/Tests.hs +++ b/test/Constrained/Tests.hs @@ -317,7 +317,7 @@ testSpec' withShrink n s = do checkCoverage' $ prop_constrained_explained s -#if MIN_VERSION_QuickCheck(2, 16, 0) +#if MIN_VERSION_QuickCheck(2, 15, 0) when withShrink $ prop "prop_shrink_sound" $ discardAfter 100_000 $ From cbdfde628530f485669f5f3ea996ecdffa4d61d1 Mon Sep 17 00:00:00 2001 From: Maximilian Algehed Date: Fri, 17 Oct 2025 07:55:51 +0200 Subject: [PATCH 5/5] dev, not devel --- .github/workflows/haskell-ci.yml | 2 +- constrained-generators.cabal | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/haskell-ci.yml b/.github/workflows/haskell-ci.yml index d75c4d3..738d201 100644 --- a/.github/workflows/haskell-ci.yml +++ b/.github/workflows/haskell-ci.yml @@ -71,7 +71,7 @@ jobs: restore-keys: ${{ runner.os }}-stack - name: Test - run: stack test --coverage --flag constrained-generators:devel + run: stack test --coverage --flag constrained-generators:dev - uses: actions/cache/save@v4 with: diff --git a/constrained-generators.cabal b/constrained-generators.cabal index d1978c3..d3d1f7d 100644 --- a/constrained-generators.cabal +++ b/constrained-generators.cabal @@ -144,7 +144,7 @@ test-suite constrained-tests containers, hspec - if !flag(devel) + if !flag(dev) build-depends: constrained-generators:examples