Skip to content
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

Make ErrorsSpec use generated types and constructors names #9

Merged
merged 1 commit into from
May 24, 2023

Conversation

carbolymer
Copy link
Contributor

@carbolymer carbolymer commented May 22, 2023

Description

All important changes are in ErrorSpec modules. Other modified haskell source files contain Data instances required for using derived types', modules' and constructors' names.

Changelog

- description: |
    Add `Eq` and `Data` instances to various error types
  compatibility: compatible
  type: feature

Checklist

  • Commit sequence broadly makes sense and commits have useful messages
  • New tests are added if needed and existing tests are updated. These may include:
    • golden tests
    • property tests
    • roundtrip tests
    • integration tests
      See Runnings tests for more details
  • Any changes are noted in the CHANGELOG.md for affected package
  • The version bounds in .cabal files are updated
  • CI passes. See note on CI. The following CI checks are required:
    • Code is linted with hlint. See .github/workflows/check-hlint.yml to get the hlint version
    • Code is formatted with stylish-haskell. See .github/workflows/stylish-haskell.yml to get the stylish-haskell version
    • Code builds on Linux, MacOS and Windows for ghc-8.10.7 and ghc-9.2.7
  • Self-reviewed the diff

Note on CI

If your PR is from a fork, the necessary CI jobs won't trigger automatically for security reasons.
You will need to get someone with write privileges. Please contact IOG node developers to do this
for you.

@carbolymer carbolymer force-pushed the mgalazyn/feat/refactor-errorsspec branch 2 times, most recently from 326f5af to e2b8dcc Compare May 23, 2023 10:20
$ displayError $ ScriptDataRangeError (Aeson.String "<JSON>") (ScriptDataConstructorOutOfRange 1)

it "ScriptDataJsonSchemaError" $ H.requireTest $ do
flip H.diffVsGoldenFile "test/golden/errors/ScriptDataJsonSchemaError/ScriptDataJsonSchemaError.txt"
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There was a typo with file name which went unnoticed. The golden file name didn't match the constructor name. Hopefully it will be harder to make new ones.

displayError err `H.diffVsGoldenFile` ("test/golden/errors" </> typeName </> constructorName <> ".txt")
testErrorMessage_ moduleName typeName constructorName err

testErrorMessage_ :: (HasCallStack, Error a) => String -> String -> String -> a -> Spec
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An escape hatch when adding of Data instance gets impossible (like when we embed TypeRep in our error data types) or requires significant multi-package changes and outweights the benefits here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add your comment to the code 👍

@carbolymer carbolymer marked this pull request as ready for review May 23, 2023 10:32
, Bech32WrongPrefix text text
]

testAllErrorMessages
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be useful to use type applications here and elsewhere so the type name is in the test code. For example:

testAllErrorMessages @InputDecodeError

@carbolymer carbolymer force-pushed the mgalazyn/feat/refactor-errorsspec branch from e2b8dcc to 751c8b0 Compare May 23, 2023 11:11
Copy link
Contributor

@Jimbo4350 Jimbo4350 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

displayError err `H.diffVsGoldenFile` ("test/golden/errors" </> typeName </> constructorName <> ".txt")
testErrorMessage_ moduleName typeName constructorName err

testErrorMessage_ :: (HasCallStack, Error a) => String -> String -> String -> a -> Spec
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add your comment to the code 👍


testErrorMessage :: (HasCallStack, MonadIO m, MonadTest m, Data p , Error p) => p -> m ()
-- , ("TransactionValidityIntervalError", TransactionValidityIntervalError $
-- Qry.PastHorizon
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left over comment?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a leftover from original change, that we want to eventually test this case as well, but we can't because we don't have access to data constructors of PastHorizon or its fields' types' constructors and we need to expose a dummy value for such purposes.

, TxMetadataBytesTooLong 0
, TxMetadataNumberOutOfRange 0
]

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ideally we want to check that we have covered all of the constructors. I suggest the following (can be a follow up PR):

diff --git a/cardano-api/golden/Test/Golden/ErrorsSpec.hs b/cardano-api/golden/Test/Golden/ErrorsSpec.hs
index 036fe5db0..d6c1d4149 100644
--- a/cardano-api/golden/Test/Golden/ErrorsSpec.hs
+++ b/cardano-api/golden/Test/Golden/ErrorsSpec.hs
@@ -237,11 +237,16 @@ spec = describe "Test.Golden.Errors" $ do
   testAllErrorMessages @TxMetadataRangeError
     [ TxMetadataTextTooLong 0
     , TxMetadataBytesTooLong 0
-    , TxMetadataNumberOutOfRange 0
+   -- , TxMetadataNumberOutOfRange 0
     ]
 
+countDataConstructors :: Data a => a -> Int
+countDataConstructors = length . dataTypeConstrs . dataTypeOf
+
 testAllErrorMessages :: forall a. (HasCallStack, Data a, Error a) => [a] -> Spec
 testAllErrorMessages errs = withFrozenCallStack $ do
+  it "All data constructors covered"  $ do
+    length errs `shouldBe`countDataConstructors (head errs)
   let typeName = show $ typeRep (Proxy @a)
   describe typeName $
     mapM_ testErrorMessage errs

When you run the golden test suite:

...
  ✓ <interactive> passed 1 test.
      TxMetadataRangeError [✔]
    All data constructors covered [✘]
    TxMetadataRangeError
  ✓ <interactive> passed 1 test.
      TxMetadataTextTooLong [✔]
  ✓ <interactive> passed 1 test.
      TxMetadataBytesTooLong [✔]

Failures:

  1) Test.Golden.Errors.Test.Golden.Errors All data constructors covered
       expected: 3
        but got: 2

  To rerun use: --match "/Test.Golden.Errors/Test.Golden.Errors/All data constructors covered/"

You should probably pattern match on the empty list and fail in that case so we can "safely" use head or something similar.

@carbolymer carbolymer force-pushed the mgalazyn/feat/refactor-errorsspec branch from 751c8b0 to 9ad6061 Compare May 24, 2023 14:33
@carbolymer carbolymer force-pushed the mgalazyn/feat/refactor-errorsspec branch from 9ad6061 to b01534b Compare May 24, 2023 14:36
@carbolymer carbolymer enabled auto-merge May 24, 2023 14:44
@carbolymer carbolymer added this pull request to the merge queue May 24, 2023
Merged via the queue into main with commit c1344f4 May 24, 2023
13 of 14 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants