From 8d6c11c4ba06720435a9ef9f412fa1f60ade8a88 Mon Sep 17 00:00:00 2001 From: Chuck Grindel Date: Thu, 21 Dec 2023 09:55:41 -0700 Subject: [PATCH 01/37] chore: shutdown Bazel servers launched by RunTests.hs --- rules_haskell_tests/tests/RunTests.hs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/rules_haskell_tests/tests/RunTests.hs b/rules_haskell_tests/tests/RunTests.hs index 78bdab253..a0b0373cd 100644 --- a/rules_haskell_tests/tests/RunTests.hs +++ b/rules_haskell_tests/tests/RunTests.hs @@ -149,10 +149,12 @@ main = hspec $ do it "bazel test examples" $ do assertSuccess $ (bazel ["build", "//..."]) { Process.cwd = Just "../examples" } assertSuccess $ (bazel ["test", "//..."]) { Process.cwd = Just "../examples" } + assertSuccess $ (bazel ["shutdown"]) { Process.cwd = Just "../examples" } it "bazel test tutorial" $ do assertSuccess $ (bazel ["build", "//..."]) { Process.cwd = Just "../tutorial" } assertSuccess (bazel ["test", "//..."]) { Process.cwd = Just "../tutorial" } + assertSuccess (bazel ["shutdown"]) { Process.cwd = Just "../tutorial" } -- * Bazel commands From 9cc18733b3f79a4e353f7655f0874a09113da07f Mon Sep 17 00:00:00 2001 From: Chuck Grindel Date: Fri, 22 Dec 2023 11:54:13 -0700 Subject: [PATCH 02/37] Try running shutdown after all of the bazel commands. --- rules_haskell_tests/tests/RunTests.hs | 252 +++++++++++++------------- 1 file changed, 129 insertions(+), 123 deletions(-) diff --git a/rules_haskell_tests/tests/RunTests.hs b/rules_haskell_tests/tests/RunTests.hs index a0b0373cd..4bbcaafc5 100644 --- a/rules_haskell_tests/tests/RunTests.hs +++ b/rules_haskell_tests/tests/RunTests.hs @@ -14,7 +14,7 @@ import System.Environment (lookupEnv) import qualified System.Process as Process import Test.Hspec.Core.Spec (SpecM) -import Test.Hspec (context, hspec, it, describe, runIO) +import Test.Hspec (context, hspec, it, describe, runIO, afterAll_) import BinModule (b) import GenModule (a) @@ -23,128 +23,130 @@ import IntegrationTesting main :: IO () main = hspec $ do - it "bazel test" $ do - assertSuccess (bazel ["test", "//..."]) - - it "bazel test prof" $ do - ghcVersion <- lookupEnv "GHC_VERSION" - - -- In .github/workflows/workflow.yaml we specify --test_tag_filters - -- -dont_test_on_darwin. However, specifiying --test_tag_filters - -- -requires_dynamic here alone would override that filter. So, - -- we have to duplicate that filter here. - let tagFilter | os == "darwin" = "-dont_test_on_darwin,-requires_dynamic,-skip_profiling" ++ ( - -- skip tests for specific GHC version, see https://github.com/tweag/rules_haskell/issues/2073 - maybe "" (",-dont_build_on_macos_with_ghc_" ++) ghcVersion) - | otherwise = "-requires_dynamic,-skip_profiling" - assertSuccess (bazel ["test", "-c", "dbg", "//...", "--build_tag_filters", tagFilter, "--test_tag_filters", tagFilter]) - - it "bazel build worker" $ do - assertSuccess (bazel ["build", "@rules_haskell//tools/worker:bin"]) - - describe "stack_snapshot pinning" $ - it "handles packages in subdirectories correctly" $ do - -- NOTE Keep in sync with - -- .github/workflows/workflow.yaml - let withBackup filename k = - withSystemTempDirectory "bazel_backup" $ \tmp_dir -> do - bracket_ - (copyFile filename (tmp_dir "backup")) - (copyFile (tmp_dir "backup") filename) - k - -- Test that pinning works and produces buildable targets. - -- Backup the lock file to avoid unintended changes when run locally. - withBackup "stackage-pinning-test_snapshot.json" $ do - assertSuccess (bazel ["run", "@stackage-pinning-test-unpinned//:pin"]) - assertSuccess (bazel ["build", "@stackage-pinning-test//:hspec"]) - - describe "repl" $ do - it "for libraries" $ do - assertSuccess (bazel ["run", "//tests/repl-targets:hs-lib-bad@repl", "--", "-ignore-dot-ghci", "-e", "1 + 2"]) - - it "for binaries" $ do - assertSuccess (bazel ["run", "//tests/binary-indirect-cbits:binary-indirect-cbits@repl", "--", "-ignore-dot-ghci", "-e", ":main"]) - - assertSuccess (bazel ["run", "//tests/repl-targets:hs-test-bad@repl", "--", "-ignore-dot-ghci", "-e", "1 + 2"]) - - it "with rebindable syntax" $ do - let p' (stdout, _stderr) = lines stdout == ["True"] - outputSatisfy p' (bazel ["run", "//tests/repl-targets:rebindable-syntax@repl", "--", "-ignore-dot-ghci", "-e", "check"]) - - it "sets classpath" $ do - assertSuccess (bazel ["run", "//tests/java_classpath:java_classpath@repl", "--", "-ignore-dot-ghci", "-e", ":main"]) - - -- Test `compiler_flags` from toolchain and rule for REPL - it "compiler flags" $ do - assertSuccess (bazel ["run", "//tests/repl-flags:compiler_flags@repl", "--", "-ignore-dot-ghci", "-e", ":main"]) - - -- Test make variable expansion in `compiler_flags` and `repl_ghci_args`. - describe "make variables" $ do - it "compiler flags" $ do - assertSuccess (bazel ["run", "//tests/repl-make-variables:test-compiler-flags@repl", "--", "-ignore-dot-ghci", "-e", ":main"]) - it "indirect repl flags" $ do - assertSuccess (bazel ["run", "//tests/repl-make-variables:repl-indirect-flags", "--", "-ignore-dot-ghci", "-e", ":main"]) - it "direct repl flags" $ do - assertSuccess (bazel ["run", "//tests/repl-make-variables:repl-direct-flags", "--", "-ignore-dot-ghci", "-e", ":main"]) - - -- Test `repl_ghci_args` from toolchain and rule for REPL - it "repl flags" $ do - assertSuccess (bazel ["run", "//tests/repl-flags:repl_flags@repl", "--", "-ignore-dot-ghci", "-e", "foo"]) - - it "fails on multiple definitions" $ do - assertSuccess (bazel ["run", "//tests/repl-multiple-definition:repl", "--", "-ignore-dot-ghci", "-e", "final"]) - - describe "multi_repl" $ do - it "loads transitive library dependencies" $ do - let p' (stdout, _stderr) = lines stdout == ["tests/multi_repl/bc/src/BC/C.hs"] - outputSatisfy p' (bazel ["run", "//tests/multi_repl:c_only_repl", "--", "-ignore-dot-ghci", "-e", ":show targets"]) - it "loads transitive source dependencies" $ do - let p' (stdout, _stderr) = sort (lines stdout) == ["tests/multi_repl/a/src/A/A.hs","tests/multi_repl/bc/src/BC/B.hs","tests/multi_repl/bc/src/BC/C.hs"] - outputSatisfy p' (bazel ["run", "//tests/multi_repl:c_multi_repl", "--", "-ignore-dot-ghci", "-e", ":show targets"]) - it "loads core library dependencies" $ do - let p' (stdout, _stderr) = sort (lines stdout) == ["tests/multi_repl/core_package_dep/Lib.hs"] - outputSatisfy p' (bazel ["run", "//tests/multi_repl:core_package_dep", "--", "-ignore-dot-ghci", "-e", ":show targets"]) - it "doesn't allow to manually load modules" $ do - assertFailure (bazel ["run", "//tests/multi_repl:c_multi_repl", "--", "-ignore-dot-ghci", "-e", ":load BC.C", "-e", "c"]) - - describe "ghcide" $ do - it "loads RunTests.hs" $ - assertSuccess (Process.proc "./.ghcide" ["tests/RunTests.hs"]) - it "loads module with module dependency" $ - assertSuccess (Process.proc "./.ghcide" ["tests/binary-with-lib/Main.hs"]) - - describe "failures" $ do - -- Make sure not to include haskell_repl (@repl) or alias (-repl) targets - -- in the query. Those would not fail under bazel test. - all_failure_tests <- bazelQuery "kind('haskell_library|haskell_binary|haskell_test', //tests/failures/...) intersect attr('tags', 'manual', //tests/failures/...)" - - for_ all_failure_tests $ \test -> do - it test $ do - assertFailure (bazel ["build", test]) - - context "known issues" $ do - it "haskell_doc fails with plugins #1549" $ - -- https://github.com/tweag/rules_haskell/issues/1549 - assertFailure (bazel ["build", "//tests/haddock-with-plugin"]) - it "transitive re-exports do not work #1145" $ - -- https://github.com/tweag/rules_haskell/issues/1145 - assertFailure (bazel ["build", "//tests/package-reexport-transitive"]) - it "doctest failure with foreign import #1559" $ - -- https://github.com/tweag/rules_haskell/issues/1559 - assertFailure (bazel ["build", "//tests/haskell_doctest_ffi_1559:doctest-a"]) - - -- Test that the repl still works if we shadow some Prelude functions - it "repl name shadowing" $ do - let p (stdout, stderr) = not $ any ("error" `isInfixOf`) [stdout, stderr] - outputSatisfy p (bazel ["run", "//tests/repl-name-conflicts:lib@repl", "--", "-ignore-dot-ghci", "-e", "stdin"]) - - it "Repl works with remote_download_toplevel" $ do - let p (stdout, stderr) = not $ any ("error" `isInfixOf`) [stdout, stderr] - withSystemTempDirectory "bazel_disk_cache" $ \tmp_disk_cache -> do - assertSuccess $ bazel ["run", "//tests/multi_repl:c_only_repl", "--disk_cache=" <> tmp_disk_cache] - assertSuccess $ bazel ["clean"] - outputSatisfy p - (bazel ["run", "//tests/multi_repl:c_only_repl", "--disk_cache=" <> tmp_disk_cache, "--remote_download_toplevel"]) + afterAll_ shutdownBazel $ + describe "root workspace" $ do + it "bazel test" $ do + assertSuccess (bazel ["test", "//..."]) + + it "bazel test prof" $ do + ghcVersion <- lookupEnv "GHC_VERSION" + + -- In .github/workflows/workflow.yaml we specify --test_tag_filters + -- -dont_test_on_darwin. However, specifiying --test_tag_filters + -- -requires_dynamic here alone would override that filter. So, + -- we have to duplicate that filter here. + let tagFilter | os == "darwin" = "-dont_test_on_darwin,-requires_dynamic,-skip_profiling" ++ ( + -- skip tests for specific GHC version, see https://github.com/tweag/rules_haskell/issues/2073 + maybe "" (",-dont_build_on_macos_with_ghc_" ++) ghcVersion) + | otherwise = "-requires_dynamic,-skip_profiling" + assertSuccess (bazel ["test", "-c", "dbg", "//...", "--build_tag_filters", tagFilter, "--test_tag_filters", tagFilter]) + + it "bazel build worker" $ do + assertSuccess (bazel ["build", "@rules_haskell//tools/worker:bin"]) + + describe "stack_snapshot pinning" $ + it "handles packages in subdirectories correctly" $ do + -- NOTE Keep in sync with + -- .github/workflows/workflow.yaml + let withBackup filename k = + withSystemTempDirectory "bazel_backup" $ \tmp_dir -> do + bracket_ + (copyFile filename (tmp_dir "backup")) + (copyFile (tmp_dir "backup") filename) + k + -- Test that pinning works and produces buildable targets. + -- Backup the lock file to avoid unintended changes when run locally. + withBackup "stackage-pinning-test_snapshot.json" $ do + assertSuccess (bazel ["run", "@stackage-pinning-test-unpinned//:pin"]) + assertSuccess (bazel ["build", "@stackage-pinning-test//:hspec"]) + + describe "repl" $ do + it "for libraries" $ do + assertSuccess (bazel ["run", "//tests/repl-targets:hs-lib-bad@repl", "--", "-ignore-dot-ghci", "-e", "1 + 2"]) + + it "for binaries" $ do + assertSuccess (bazel ["run", "//tests/binary-indirect-cbits:binary-indirect-cbits@repl", "--", "-ignore-dot-ghci", "-e", ":main"]) + + assertSuccess (bazel ["run", "//tests/repl-targets:hs-test-bad@repl", "--", "-ignore-dot-ghci", "-e", "1 + 2"]) + + it "with rebindable syntax" $ do + let p' (stdout, _stderr) = lines stdout == ["True"] + outputSatisfy p' (bazel ["run", "//tests/repl-targets:rebindable-syntax@repl", "--", "-ignore-dot-ghci", "-e", "check"]) + + it "sets classpath" $ do + assertSuccess (bazel ["run", "//tests/java_classpath:java_classpath@repl", "--", "-ignore-dot-ghci", "-e", ":main"]) + + -- Test `compiler_flags` from toolchain and rule for REPL + it "compiler flags" $ do + assertSuccess (bazel ["run", "//tests/repl-flags:compiler_flags@repl", "--", "-ignore-dot-ghci", "-e", ":main"]) + + -- Test make variable expansion in `compiler_flags` and `repl_ghci_args`. + describe "make variables" $ do + it "compiler flags" $ do + assertSuccess (bazel ["run", "//tests/repl-make-variables:test-compiler-flags@repl", "--", "-ignore-dot-ghci", "-e", ":main"]) + it "indirect repl flags" $ do + assertSuccess (bazel ["run", "//tests/repl-make-variables:repl-indirect-flags", "--", "-ignore-dot-ghci", "-e", ":main"]) + it "direct repl flags" $ do + assertSuccess (bazel ["run", "//tests/repl-make-variables:repl-direct-flags", "--", "-ignore-dot-ghci", "-e", ":main"]) + + -- Test `repl_ghci_args` from toolchain and rule for REPL + it "repl flags" $ do + assertSuccess (bazel ["run", "//tests/repl-flags:repl_flags@repl", "--", "-ignore-dot-ghci", "-e", "foo"]) + + it "fails on multiple definitions" $ do + assertSuccess (bazel ["run", "//tests/repl-multiple-definition:repl", "--", "-ignore-dot-ghci", "-e", "final"]) + + describe "multi_repl" $ do + it "loads transitive library dependencies" $ do + let p' (stdout, _stderr) = lines stdout == ["tests/multi_repl/bc/src/BC/C.hs"] + outputSatisfy p' (bazel ["run", "//tests/multi_repl:c_only_repl", "--", "-ignore-dot-ghci", "-e", ":show targets"]) + it "loads transitive source dependencies" $ do + let p' (stdout, _stderr) = sort (lines stdout) == ["tests/multi_repl/a/src/A/A.hs","tests/multi_repl/bc/src/BC/B.hs","tests/multi_repl/bc/src/BC/C.hs"] + outputSatisfy p' (bazel ["run", "//tests/multi_repl:c_multi_repl", "--", "-ignore-dot-ghci", "-e", ":show targets"]) + it "loads core library dependencies" $ do + let p' (stdout, _stderr) = sort (lines stdout) == ["tests/multi_repl/core_package_dep/Lib.hs"] + outputSatisfy p' (bazel ["run", "//tests/multi_repl:core_package_dep", "--", "-ignore-dot-ghci", "-e", ":show targets"]) + it "doesn't allow to manually load modules" $ do + assertFailure (bazel ["run", "//tests/multi_repl:c_multi_repl", "--", "-ignore-dot-ghci", "-e", ":load BC.C", "-e", "c"]) + + describe "ghcide" $ do + it "loads RunTests.hs" $ + assertSuccess (Process.proc "./.ghcide" ["tests/RunTests.hs"]) + it "loads module with module dependency" $ + assertSuccess (Process.proc "./.ghcide" ["tests/binary-with-lib/Main.hs"]) + + describe "failures" $ do + -- Make sure not to include haskell_repl (@repl) or alias (-repl) targets + -- in the query. Those would not fail under bazel test. + all_failure_tests <- bazelQuery "kind('haskell_library|haskell_binary|haskell_test', //tests/failures/...) intersect attr('tags', 'manual', //tests/failures/...)" + + for_ all_failure_tests $ \test -> do + it test $ do + assertFailure (bazel ["build", test]) + + context "known issues" $ do + it "haskell_doc fails with plugins #1549" $ + -- https://github.com/tweag/rules_haskell/issues/1549 + assertFailure (bazel ["build", "//tests/haddock-with-plugin"]) + it "transitive re-exports do not work #1145" $ + -- https://github.com/tweag/rules_haskell/issues/1145 + assertFailure (bazel ["build", "//tests/package-reexport-transitive"]) + it "doctest failure with foreign import #1559" $ + -- https://github.com/tweag/rules_haskell/issues/1559 + assertFailure (bazel ["build", "//tests/haskell_doctest_ffi_1559:doctest-a"]) + + -- Test that the repl still works if we shadow some Prelude functions + it "repl name shadowing" $ do + let p (stdout, stderr) = not $ any ("error" `isInfixOf`) [stdout, stderr] + outputSatisfy p (bazel ["run", "//tests/repl-name-conflicts:lib@repl", "--", "-ignore-dot-ghci", "-e", "stdin"]) + + it "Repl works with remote_download_toplevel" $ do + let p (stdout, stderr) = not $ any ("error" `isInfixOf`) [stdout, stderr] + withSystemTempDirectory "bazel_disk_cache" $ \tmp_disk_cache -> do + assertSuccess $ bazel ["run", "//tests/multi_repl:c_only_repl", "--disk_cache=" <> tmp_disk_cache] + assertSuccess $ bazel ["clean"] + outputSatisfy p + (bazel ["run", "//tests/multi_repl:c_only_repl", "--disk_cache=" <> tmp_disk_cache, "--remote_download_toplevel"]) it "bazel test examples" $ do assertSuccess $ (bazel ["build", "//..."]) { Process.cwd = Just "../examples" } @@ -167,6 +169,10 @@ bazel args = Process.proc "bazel" args bazelQuery :: String -> SpecM a [String] bazelQuery q = lines <$> runIO (Process.readProcess "bazel" ["query", q] "") +shutdownBazel :: IO () +shutdownBazel = do + assertSuccess (bazel ["shutdown"]) + pure () -- Generated dependencies for testing the ghcide support _ghciIDE :: Int From 5799ca55942ea3761b2a2c87b392a249b0f1af5d Mon Sep 17 00:00:00 2001 From: Chuck Grindel Date: Fri, 22 Dec 2023 13:17:27 -0700 Subject: [PATCH 03/37] Remove extra describe. --- rules_haskell_tests/tests/RunTests.hs | 246 +++++++++++++------------- 1 file changed, 123 insertions(+), 123 deletions(-) diff --git a/rules_haskell_tests/tests/RunTests.hs b/rules_haskell_tests/tests/RunTests.hs index 4bbcaafc5..1f1360922 100644 --- a/rules_haskell_tests/tests/RunTests.hs +++ b/rules_haskell_tests/tests/RunTests.hs @@ -23,130 +23,129 @@ import IntegrationTesting main :: IO () main = hspec $ do - afterAll_ shutdownBazel $ - describe "root workspace" $ do - it "bazel test" $ do - assertSuccess (bazel ["test", "//..."]) - - it "bazel test prof" $ do - ghcVersion <- lookupEnv "GHC_VERSION" - - -- In .github/workflows/workflow.yaml we specify --test_tag_filters - -- -dont_test_on_darwin. However, specifiying --test_tag_filters - -- -requires_dynamic here alone would override that filter. So, - -- we have to duplicate that filter here. - let tagFilter | os == "darwin" = "-dont_test_on_darwin,-requires_dynamic,-skip_profiling" ++ ( - -- skip tests for specific GHC version, see https://github.com/tweag/rules_haskell/issues/2073 - maybe "" (",-dont_build_on_macos_with_ghc_" ++) ghcVersion) - | otherwise = "-requires_dynamic,-skip_profiling" - assertSuccess (bazel ["test", "-c", "dbg", "//...", "--build_tag_filters", tagFilter, "--test_tag_filters", tagFilter]) - - it "bazel build worker" $ do - assertSuccess (bazel ["build", "@rules_haskell//tools/worker:bin"]) - - describe "stack_snapshot pinning" $ - it "handles packages in subdirectories correctly" $ do - -- NOTE Keep in sync with - -- .github/workflows/workflow.yaml - let withBackup filename k = - withSystemTempDirectory "bazel_backup" $ \tmp_dir -> do - bracket_ - (copyFile filename (tmp_dir "backup")) - (copyFile (tmp_dir "backup") filename) - k - -- Test that pinning works and produces buildable targets. - -- Backup the lock file to avoid unintended changes when run locally. - withBackup "stackage-pinning-test_snapshot.json" $ do - assertSuccess (bazel ["run", "@stackage-pinning-test-unpinned//:pin"]) - assertSuccess (bazel ["build", "@stackage-pinning-test//:hspec"]) - - describe "repl" $ do - it "for libraries" $ do - assertSuccess (bazel ["run", "//tests/repl-targets:hs-lib-bad@repl", "--", "-ignore-dot-ghci", "-e", "1 + 2"]) - - it "for binaries" $ do - assertSuccess (bazel ["run", "//tests/binary-indirect-cbits:binary-indirect-cbits@repl", "--", "-ignore-dot-ghci", "-e", ":main"]) - - assertSuccess (bazel ["run", "//tests/repl-targets:hs-test-bad@repl", "--", "-ignore-dot-ghci", "-e", "1 + 2"]) - - it "with rebindable syntax" $ do - let p' (stdout, _stderr) = lines stdout == ["True"] - outputSatisfy p' (bazel ["run", "//tests/repl-targets:rebindable-syntax@repl", "--", "-ignore-dot-ghci", "-e", "check"]) - - it "sets classpath" $ do - assertSuccess (bazel ["run", "//tests/java_classpath:java_classpath@repl", "--", "-ignore-dot-ghci", "-e", ":main"]) - - -- Test `compiler_flags` from toolchain and rule for REPL + afterAll_ shutdownBazel $ do + it "bazel test" $ do + assertSuccess (bazel ["test", "//..."]) + + it "bazel test prof" $ do + ghcVersion <- lookupEnv "GHC_VERSION" + + -- In .github/workflows/workflow.yaml we specify --test_tag_filters + -- -dont_test_on_darwin. However, specifiying --test_tag_filters + -- -requires_dynamic here alone would override that filter. So, + -- we have to duplicate that filter here. + let tagFilter | os == "darwin" = "-dont_test_on_darwin,-requires_dynamic,-skip_profiling" ++ ( + -- skip tests for specific GHC version, see https://github.com/tweag/rules_haskell/issues/2073 + maybe "" (",-dont_build_on_macos_with_ghc_" ++) ghcVersion) + | otherwise = "-requires_dynamic,-skip_profiling" + assertSuccess (bazel ["test", "-c", "dbg", "//...", "--build_tag_filters", tagFilter, "--test_tag_filters", tagFilter]) + + it "bazel build worker" $ do + assertSuccess (bazel ["build", "@rules_haskell//tools/worker:bin"]) + + describe "stack_snapshot pinning" $ + it "handles packages in subdirectories correctly" $ do + -- NOTE Keep in sync with + -- .github/workflows/workflow.yaml + let withBackup filename k = + withSystemTempDirectory "bazel_backup" $ \tmp_dir -> do + bracket_ + (copyFile filename (tmp_dir "backup")) + (copyFile (tmp_dir "backup") filename) + k + -- Test that pinning works and produces buildable targets. + -- Backup the lock file to avoid unintended changes when run locally. + withBackup "stackage-pinning-test_snapshot.json" $ do + assertSuccess (bazel ["run", "@stackage-pinning-test-unpinned//:pin"]) + assertSuccess (bazel ["build", "@stackage-pinning-test//:hspec"]) + + describe "repl" $ do + it "for libraries" $ do + assertSuccess (bazel ["run", "//tests/repl-targets:hs-lib-bad@repl", "--", "-ignore-dot-ghci", "-e", "1 + 2"]) + + it "for binaries" $ do + assertSuccess (bazel ["run", "//tests/binary-indirect-cbits:binary-indirect-cbits@repl", "--", "-ignore-dot-ghci", "-e", ":main"]) + + assertSuccess (bazel ["run", "//tests/repl-targets:hs-test-bad@repl", "--", "-ignore-dot-ghci", "-e", "1 + 2"]) + + it "with rebindable syntax" $ do + let p' (stdout, _stderr) = lines stdout == ["True"] + outputSatisfy p' (bazel ["run", "//tests/repl-targets:rebindable-syntax@repl", "--", "-ignore-dot-ghci", "-e", "check"]) + + it "sets classpath" $ do + assertSuccess (bazel ["run", "//tests/java_classpath:java_classpath@repl", "--", "-ignore-dot-ghci", "-e", ":main"]) + + -- Test `compiler_flags` from toolchain and rule for REPL + it "compiler flags" $ do + assertSuccess (bazel ["run", "//tests/repl-flags:compiler_flags@repl", "--", "-ignore-dot-ghci", "-e", ":main"]) + + -- Test make variable expansion in `compiler_flags` and `repl_ghci_args`. + describe "make variables" $ do it "compiler flags" $ do - assertSuccess (bazel ["run", "//tests/repl-flags:compiler_flags@repl", "--", "-ignore-dot-ghci", "-e", ":main"]) - - -- Test make variable expansion in `compiler_flags` and `repl_ghci_args`. - describe "make variables" $ do - it "compiler flags" $ do - assertSuccess (bazel ["run", "//tests/repl-make-variables:test-compiler-flags@repl", "--", "-ignore-dot-ghci", "-e", ":main"]) - it "indirect repl flags" $ do - assertSuccess (bazel ["run", "//tests/repl-make-variables:repl-indirect-flags", "--", "-ignore-dot-ghci", "-e", ":main"]) - it "direct repl flags" $ do - assertSuccess (bazel ["run", "//tests/repl-make-variables:repl-direct-flags", "--", "-ignore-dot-ghci", "-e", ":main"]) - - -- Test `repl_ghci_args` from toolchain and rule for REPL - it "repl flags" $ do - assertSuccess (bazel ["run", "//tests/repl-flags:repl_flags@repl", "--", "-ignore-dot-ghci", "-e", "foo"]) - - it "fails on multiple definitions" $ do - assertSuccess (bazel ["run", "//tests/repl-multiple-definition:repl", "--", "-ignore-dot-ghci", "-e", "final"]) - - describe "multi_repl" $ do - it "loads transitive library dependencies" $ do - let p' (stdout, _stderr) = lines stdout == ["tests/multi_repl/bc/src/BC/C.hs"] - outputSatisfy p' (bazel ["run", "//tests/multi_repl:c_only_repl", "--", "-ignore-dot-ghci", "-e", ":show targets"]) - it "loads transitive source dependencies" $ do - let p' (stdout, _stderr) = sort (lines stdout) == ["tests/multi_repl/a/src/A/A.hs","tests/multi_repl/bc/src/BC/B.hs","tests/multi_repl/bc/src/BC/C.hs"] - outputSatisfy p' (bazel ["run", "//tests/multi_repl:c_multi_repl", "--", "-ignore-dot-ghci", "-e", ":show targets"]) - it "loads core library dependencies" $ do - let p' (stdout, _stderr) = sort (lines stdout) == ["tests/multi_repl/core_package_dep/Lib.hs"] - outputSatisfy p' (bazel ["run", "//tests/multi_repl:core_package_dep", "--", "-ignore-dot-ghci", "-e", ":show targets"]) - it "doesn't allow to manually load modules" $ do - assertFailure (bazel ["run", "//tests/multi_repl:c_multi_repl", "--", "-ignore-dot-ghci", "-e", ":load BC.C", "-e", "c"]) - - describe "ghcide" $ do - it "loads RunTests.hs" $ - assertSuccess (Process.proc "./.ghcide" ["tests/RunTests.hs"]) - it "loads module with module dependency" $ - assertSuccess (Process.proc "./.ghcide" ["tests/binary-with-lib/Main.hs"]) - - describe "failures" $ do - -- Make sure not to include haskell_repl (@repl) or alias (-repl) targets - -- in the query. Those would not fail under bazel test. - all_failure_tests <- bazelQuery "kind('haskell_library|haskell_binary|haskell_test', //tests/failures/...) intersect attr('tags', 'manual', //tests/failures/...)" - - for_ all_failure_tests $ \test -> do - it test $ do - assertFailure (bazel ["build", test]) - - context "known issues" $ do - it "haskell_doc fails with plugins #1549" $ - -- https://github.com/tweag/rules_haskell/issues/1549 - assertFailure (bazel ["build", "//tests/haddock-with-plugin"]) - it "transitive re-exports do not work #1145" $ - -- https://github.com/tweag/rules_haskell/issues/1145 - assertFailure (bazel ["build", "//tests/package-reexport-transitive"]) - it "doctest failure with foreign import #1559" $ - -- https://github.com/tweag/rules_haskell/issues/1559 - assertFailure (bazel ["build", "//tests/haskell_doctest_ffi_1559:doctest-a"]) - - -- Test that the repl still works if we shadow some Prelude functions - it "repl name shadowing" $ do - let p (stdout, stderr) = not $ any ("error" `isInfixOf`) [stdout, stderr] - outputSatisfy p (bazel ["run", "//tests/repl-name-conflicts:lib@repl", "--", "-ignore-dot-ghci", "-e", "stdin"]) - - it "Repl works with remote_download_toplevel" $ do - let p (stdout, stderr) = not $ any ("error" `isInfixOf`) [stdout, stderr] - withSystemTempDirectory "bazel_disk_cache" $ \tmp_disk_cache -> do - assertSuccess $ bazel ["run", "//tests/multi_repl:c_only_repl", "--disk_cache=" <> tmp_disk_cache] - assertSuccess $ bazel ["clean"] - outputSatisfy p - (bazel ["run", "//tests/multi_repl:c_only_repl", "--disk_cache=" <> tmp_disk_cache, "--remote_download_toplevel"]) + assertSuccess (bazel ["run", "//tests/repl-make-variables:test-compiler-flags@repl", "--", "-ignore-dot-ghci", "-e", ":main"]) + it "indirect repl flags" $ do + assertSuccess (bazel ["run", "//tests/repl-make-variables:repl-indirect-flags", "--", "-ignore-dot-ghci", "-e", ":main"]) + it "direct repl flags" $ do + assertSuccess (bazel ["run", "//tests/repl-make-variables:repl-direct-flags", "--", "-ignore-dot-ghci", "-e", ":main"]) + + -- Test `repl_ghci_args` from toolchain and rule for REPL + it "repl flags" $ do + assertSuccess (bazel ["run", "//tests/repl-flags:repl_flags@repl", "--", "-ignore-dot-ghci", "-e", "foo"]) + + it "fails on multiple definitions" $ do + assertSuccess (bazel ["run", "//tests/repl-multiple-definition:repl", "--", "-ignore-dot-ghci", "-e", "final"]) + + describe "multi_repl" $ do + it "loads transitive library dependencies" $ do + let p' (stdout, _stderr) = lines stdout == ["tests/multi_repl/bc/src/BC/C.hs"] + outputSatisfy p' (bazel ["run", "//tests/multi_repl:c_only_repl", "--", "-ignore-dot-ghci", "-e", ":show targets"]) + it "loads transitive source dependencies" $ do + let p' (stdout, _stderr) = sort (lines stdout) == ["tests/multi_repl/a/src/A/A.hs","tests/multi_repl/bc/src/BC/B.hs","tests/multi_repl/bc/src/BC/C.hs"] + outputSatisfy p' (bazel ["run", "//tests/multi_repl:c_multi_repl", "--", "-ignore-dot-ghci", "-e", ":show targets"]) + it "loads core library dependencies" $ do + let p' (stdout, _stderr) = sort (lines stdout) == ["tests/multi_repl/core_package_dep/Lib.hs"] + outputSatisfy p' (bazel ["run", "//tests/multi_repl:core_package_dep", "--", "-ignore-dot-ghci", "-e", ":show targets"]) + it "doesn't allow to manually load modules" $ do + assertFailure (bazel ["run", "//tests/multi_repl:c_multi_repl", "--", "-ignore-dot-ghci", "-e", ":load BC.C", "-e", "c"]) + + describe "ghcide" $ do + it "loads RunTests.hs" $ + assertSuccess (Process.proc "./.ghcide" ["tests/RunTests.hs"]) + it "loads module with module dependency" $ + assertSuccess (Process.proc "./.ghcide" ["tests/binary-with-lib/Main.hs"]) + + describe "failures" $ do + -- Make sure not to include haskell_repl (@repl) or alias (-repl) targets + -- in the query. Those would not fail under bazel test. + all_failure_tests <- bazelQuery "kind('haskell_library|haskell_binary|haskell_test', //tests/failures/...) intersect attr('tags', 'manual', //tests/failures/...)" + + for_ all_failure_tests $ \test -> do + it test $ do + assertFailure (bazel ["build", test]) + + context "known issues" $ do + it "haskell_doc fails with plugins #1549" $ + -- https://github.com/tweag/rules_haskell/issues/1549 + assertFailure (bazel ["build", "//tests/haddock-with-plugin"]) + it "transitive re-exports do not work #1145" $ + -- https://github.com/tweag/rules_haskell/issues/1145 + assertFailure (bazel ["build", "//tests/package-reexport-transitive"]) + it "doctest failure with foreign import #1559" $ + -- https://github.com/tweag/rules_haskell/issues/1559 + assertFailure (bazel ["build", "//tests/haskell_doctest_ffi_1559:doctest-a"]) + + -- Test that the repl still works if we shadow some Prelude functions + it "repl name shadowing" $ do + let p (stdout, stderr) = not $ any ("error" `isInfixOf`) [stdout, stderr] + outputSatisfy p (bazel ["run", "//tests/repl-name-conflicts:lib@repl", "--", "-ignore-dot-ghci", "-e", "stdin"]) + + it "Repl works with remote_download_toplevel" $ do + let p (stdout, stderr) = not $ any ("error" `isInfixOf`) [stdout, stderr] + withSystemTempDirectory "bazel_disk_cache" $ \tmp_disk_cache -> do + assertSuccess $ bazel ["run", "//tests/multi_repl:c_only_repl", "--disk_cache=" <> tmp_disk_cache] + assertSuccess $ bazel ["clean"] + outputSatisfy p + (bazel ["run", "//tests/multi_repl:c_only_repl", "--disk_cache=" <> tmp_disk_cache, "--remote_download_toplevel"]) it "bazel test examples" $ do assertSuccess $ (bazel ["build", "//..."]) { Process.cwd = Just "../examples" } @@ -171,6 +170,7 @@ bazelQuery q = lines <$> runIO (Process.readProcess "bazel" ["query", q] "") shutdownBazel :: IO () shutdownBazel = do + putStrLn "MADE IT!" assertSuccess (bazel ["shutdown"]) pure () From d902ea61664e0af8222f201b8d47ada7e6c0cee9 Mon Sep 17 00:00:00 2001 From: Chuck Grindel Date: Fri, 22 Dec 2023 13:19:54 -0700 Subject: [PATCH 04/37] Change the debug. --- rules_haskell_tests/tests/RunTests.hs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/rules_haskell_tests/tests/RunTests.hs b/rules_haskell_tests/tests/RunTests.hs index 1f1360922..90315518b 100644 --- a/rules_haskell_tests/tests/RunTests.hs +++ b/rules_haskell_tests/tests/RunTests.hs @@ -170,7 +170,9 @@ bazelQuery q = lines <$> runIO (Process.readProcess "bazel" ["query", q] "") shutdownBazel :: IO () shutdownBazel = do - putStrLn "MADE IT!" + -- DEBUG BEGIN + putStrLn "Shutting down Bazel." + -- DEBUG END assertSuccess (bazel ["shutdown"]) pure () From d894e35175fc33d105d63e92e7adce3a407431ba Mon Sep 17 00:00:00 2001 From: Chuck Grindel Date: Fri, 22 Dec 2023 14:42:46 -0700 Subject: [PATCH 05/37] Print memory_pressure before and after shutdown. --- rules_haskell_tests/tests/RunTests.hs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/rules_haskell_tests/tests/RunTests.hs b/rules_haskell_tests/tests/RunTests.hs index 90315518b..23f80df6c 100644 --- a/rules_haskell_tests/tests/RunTests.hs +++ b/rules_haskell_tests/tests/RunTests.hs @@ -171,11 +171,20 @@ bazelQuery q = lines <$> runIO (Process.readProcess "bazel" ["query", q] "") shutdownBazel :: IO () shutdownBazel = do -- DEBUG BEGIN - putStrLn "Shutting down Bazel." + printMem "BEFORE" -- DEBUG END assertSuccess (bazel ["shutdown"]) + -- DEBUG BEGIN + printMem "AFTER" + -- DEBUG END pure () +printMem :: String -> IO () +printMem msg = do + putStrLn msg + (_, stdOut, _) <- Process.readProcessWithExitCode "/usr/bin/memory_pressure" [] "" + putStrLn stdOut + -- Generated dependencies for testing the ghcide support _ghciIDE :: Int _ghciIDE = a + b From 8918cb64e378f28864b33166ee86936f5c527f9d Mon Sep 17 00:00:00 2001 From: Chuck Grindel Date: Fri, 22 Dec 2023 16:28:19 -0700 Subject: [PATCH 06/37] Dump processes using memory. --- rules_haskell_tests/tests/RunTests.hs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/rules_haskell_tests/tests/RunTests.hs b/rules_haskell_tests/tests/RunTests.hs index 23f80df6c..751a68433 100644 --- a/rules_haskell_tests/tests/RunTests.hs +++ b/rules_haskell_tests/tests/RunTests.hs @@ -182,7 +182,8 @@ shutdownBazel = do printMem :: String -> IO () printMem msg = do putStrLn msg - (_, stdOut, _) <- Process.readProcessWithExitCode "/usr/bin/memory_pressure" [] "" + -- (_, stdOut, _) <- Process.readProcessWithExitCode "/usr/bin/memory_pressure" [] "" + (_, stdOut, _) <- Process.readProcessWithExitCode "/usr/bin/top" ["-l", "1", "-s", "0", "-o", "mem", "-n", "15"] "" putStrLn stdOut -- Generated dependencies for testing the ghcide support From 3c3de7c107d6ba8c3549b76eee59f85a61a02108 Mon Sep 17 00:00:00 2001 From: Chuck Grindel Date: Tue, 2 Jan 2024 13:31:13 -0700 Subject: [PATCH 07/37] Restrict number of tests. Dump memory info. --- .github/workflows/workflow.yaml | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/.github/workflows/workflow.yaml b/.github/workflows/workflow.yaml index b1f2534f9..08bba71d4 100644 --- a/.github/workflows/workflow.yaml +++ b/.github/workflows/workflow.yaml @@ -43,8 +43,11 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-latest, macos-latest] - module: [rules_haskell, rules_haskell_nix, rules_haskell_tests] + # TODO(chuck): FIX ME! + # os: [ubuntu-latest, macos-latest] + # module: [rules_haskell, rules_haskell_nix, rules_haskell_tests] + os: [macos-latest] + module: [rules_haskell_tests] bzlmod: [true, false] ghc: - 9.2.8 @@ -130,7 +133,15 @@ jobs: # Shutdown Bazel to free up memory # https://github.com/tweag/rules_haskell/issues/2089. bazel shutdown + # DEBUG BEGIN + echo >&2 "CHUCK BEFORE" + top -l 1 -s 0 -o mem | head -n 25 >&2 + # DEBUG END ./bazel-ci-bin/tests/run-tests + # DEBUG BEGIN + echo >&2 "CHUCK AFTER" + top -l 1 -s 0 -o mem | head -n 25 >&2 + # DEBUG END bazel coverage //... test-bindist: From 374b4ba8726d2e2f604a542346867a057e946a2b Mon Sep 17 00:00:00 2001 From: Chuck Grindel Date: Tue, 2 Jan 2024 15:09:14 -0700 Subject: [PATCH 08/37] Install darwin.top. --- rules_haskell_tests/shell.nix | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/rules_haskell_tests/shell.nix b/rules_haskell_tests/shell.nix index d040173ab..955f1b0d0 100644 --- a/rules_haskell_tests/shell.nix +++ b/rules_haskell_tests/shell.nix @@ -38,7 +38,10 @@ mkShell { file ] ++ lib.optionals docTools [ graphviz python39Packages.sphinx zip unzip ]; - packages = [ bazel_6 ]; + # packages = [ bazel_6 ]; + # DEBUG BEGIN + packages = [ bazel_6 darwin.top ]; + # DEBUG END shellHook = '' # Add nix config flags to .bazelrc.local. From 4670cbb459735352a7860a4121f77aa0a48adbe3 Mon Sep 17 00:00:00 2001 From: Chuck Grindel Date: Tue, 2 Jan 2024 15:26:06 -0700 Subject: [PATCH 09/37] Remove changes to shell.nix. Run not pure. --- .github/workflows/workflow.yaml | 3 +++ rules_haskell_tests/shell.nix | 5 +---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/workflow.yaml b/.github/workflows/workflow.yaml index 08bba71d4..c770e9956 100644 --- a/.github/workflows/workflow.yaml +++ b/.github/workflows/workflow.yaml @@ -124,6 +124,9 @@ jobs: with: options: ${{ env.NIX_SHELL_ARGS }} working-directory: rules_haskell_tests + # DEBUG BEGIN + pure: false + # DEBUG END run: | # XXX run start script `--with-bzlmod=true` when supported if ! ${{ matrix.bzlmod }}; then diff --git a/rules_haskell_tests/shell.nix b/rules_haskell_tests/shell.nix index 955f1b0d0..d040173ab 100644 --- a/rules_haskell_tests/shell.nix +++ b/rules_haskell_tests/shell.nix @@ -38,10 +38,7 @@ mkShell { file ] ++ lib.optionals docTools [ graphviz python39Packages.sphinx zip unzip ]; - # packages = [ bazel_6 ]; - # DEBUG BEGIN - packages = [ bazel_6 darwin.top ]; - # DEBUG END + packages = [ bazel_6 ]; shellHook = '' # Add nix config flags to .bazelrc.local. From 25e0a02de68f78ddbd04b6213eb15c94d56c6036 Mon Sep 17 00:00:00 2001 From: Chuck Grindel Date: Tue, 2 Jan 2024 15:36:29 -0700 Subject: [PATCH 10/37] More debug --- .github/workflows/workflow.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/workflow.yaml b/.github/workflows/workflow.yaml index c770e9956..16c607247 100644 --- a/.github/workflows/workflow.yaml +++ b/.github/workflows/workflow.yaml @@ -139,6 +139,7 @@ jobs: # DEBUG BEGIN echo >&2 "CHUCK BEFORE" top -l 1 -s 0 -o mem | head -n 25 >&2 + echo >&2 "run-tests" # DEBUG END ./bazel-ci-bin/tests/run-tests # DEBUG BEGIN From 31b6b839d4baa662fdb218cc0e952d5593785515 Mon Sep 17 00:00:00 2001 From: Chuck Grindel Date: Tue, 2 Jan 2024 16:19:01 -0700 Subject: [PATCH 11/37] More debug --- .github/workflows/workflow.yaml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/.github/workflows/workflow.yaml b/.github/workflows/workflow.yaml index 16c607247..dcb103b42 100644 --- a/.github/workflows/workflow.yaml +++ b/.github/workflows/workflow.yaml @@ -138,13 +138,16 @@ jobs: bazel shutdown # DEBUG BEGIN echo >&2 "CHUCK BEFORE" - top -l 1 -s 0 -o mem | head -n 25 >&2 + # top -l 1 -s 0 -o mem | head -n 25 >&2 + top -l 1 -s 0 -o mem >&2 echo >&2 "run-tests" # DEBUG END - ./bazel-ci-bin/tests/run-tests + # ./bazel-ci-bin/tests/run-tests + ./bazel-ci-bin/tests/run-tests || true # DEBUG BEGIN echo >&2 "CHUCK AFTER" - top -l 1 -s 0 -o mem | head -n 25 >&2 + # top -l 1 -s 0 -o mem | head -n 25 >&2 + top -l 1 -s 0 -o mem >&2 # DEBUG END bazel coverage //... From 65f70513b911df40cd0a8786870b50718df05dc0 Mon Sep 17 00:00:00 2001 From: Chuck Grindel Date: Wed, 3 Jan 2024 06:46:53 -0700 Subject: [PATCH 12/37] Remove debug code as the exit failure value is now 1. --- .github/workflows/workflow.yaml | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/workflow.yaml b/.github/workflows/workflow.yaml index dcb103b42..03cdbaf60 100644 --- a/.github/workflows/workflow.yaml +++ b/.github/workflows/workflow.yaml @@ -125,7 +125,7 @@ jobs: options: ${{ env.NIX_SHELL_ARGS }} working-directory: rules_haskell_tests # DEBUG BEGIN - pure: false + # pure: false # DEBUG END run: | # XXX run start script `--with-bzlmod=true` when supported @@ -136,19 +136,19 @@ jobs: # Shutdown Bazel to free up memory # https://github.com/tweag/rules_haskell/issues/2089. bazel shutdown - # DEBUG BEGIN - echo >&2 "CHUCK BEFORE" - # top -l 1 -s 0 -o mem | head -n 25 >&2 - top -l 1 -s 0 -o mem >&2 - echo >&2 "run-tests" - # DEBUG END + # # DEBUG BEGIN + # echo >&2 "CHUCK BEFORE" + # # top -l 1 -s 0 -o mem | head -n 25 >&2 + # top -l 1 -s 0 -o mem >&2 + # echo >&2 "run-tests" + # # DEBUG END # ./bazel-ci-bin/tests/run-tests ./bazel-ci-bin/tests/run-tests || true - # DEBUG BEGIN - echo >&2 "CHUCK AFTER" - # top -l 1 -s 0 -o mem | head -n 25 >&2 - top -l 1 -s 0 -o mem >&2 - # DEBUG END + # # DEBUG BEGIN + # echo >&2 "CHUCK AFTER" + # # top -l 1 -s 0 -o mem | head -n 25 >&2 + # top -l 1 -s 0 -o mem >&2 + # # DEBUG END bazel coverage //... test-bindist: From 4b0dbddd45ebdea5c339f59f3a09f15511ee72ad Mon Sep 17 00:00:00 2001 From: Chuck Grindel Date: Wed, 3 Jan 2024 06:47:55 -0700 Subject: [PATCH 13/37] Add debug comment --- .github/workflows/workflow.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/workflow.yaml b/.github/workflows/workflow.yaml index 03cdbaf60..d741e53a7 100644 --- a/.github/workflows/workflow.yaml +++ b/.github/workflows/workflow.yaml @@ -46,7 +46,9 @@ jobs: # TODO(chuck): FIX ME! # os: [ubuntu-latest, macos-latest] # module: [rules_haskell, rules_haskell_nix, rules_haskell_tests] + # DEBUG BEGIN os: [macos-latest] + # DEBUG END module: [rules_haskell_tests] bzlmod: [true, false] ghc: From 95c8a3dfed498763edcb27ada37d6d02b451921d Mon Sep 17 00:00:00 2001 From: Chuck Grindel Date: Wed, 3 Jan 2024 07:20:12 -0700 Subject: [PATCH 14/37] Add action-tmate --- .github/workflows/workflow.yaml | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/.github/workflows/workflow.yaml b/.github/workflows/workflow.yaml index d741e53a7..cd0a7f5e5 100644 --- a/.github/workflows/workflow.yaml +++ b/.github/workflows/workflow.yaml @@ -48,13 +48,19 @@ jobs: # module: [rules_haskell, rules_haskell_nix, rules_haskell_tests] # DEBUG BEGIN os: [macos-latest] - # DEBUG END module: [rules_haskell_tests] - bzlmod: [true, false] + # DEBUG END + # TODO(chuck): FIX ME! + # bzlmod: [true, false] + # ghc: + # - 9.2.8 + # - 9.4.6 + # - 9.6.2 + # DEBUG BEGIN + bzlmod: [true] ghc: - 9.2.8 - - 9.4.6 - - 9.6.2 + # DEBUG END exclude: - module: rules_haskell_nix @@ -104,6 +110,10 @@ jobs: EOF cp .bazelrc.local rules_haskell_nix cp .bazelrc.local rules_haskell_tests + # DEBUG BEGIN + - name: Setup tmate session + uses: mxschmitt/action-tmate@v3 + # DEBUG END - name: Build & test - rules_haskell if: matrix.module == 'rules_haskell' uses: tweag/run-nix-shell@v0 @@ -144,8 +154,8 @@ jobs: # top -l 1 -s 0 -o mem >&2 # echo >&2 "run-tests" # # DEBUG END - # ./bazel-ci-bin/tests/run-tests - ./bazel-ci-bin/tests/run-tests || true + ./bazel-ci-bin/tests/run-tests + # ./bazel-ci-bin/tests/run-tests || true # # DEBUG BEGIN # echo >&2 "CHUCK AFTER" # # top -l 1 -s 0 -o mem | head -n 25 >&2 From d9164b167d81339c2031b28f2d060d9672f5d5fa Mon Sep 17 00:00:00 2001 From: Chuck Grindel Date: Wed, 3 Jan 2024 08:09:27 -0700 Subject: [PATCH 15/37] Revert changes to workflow.yaml. --- .github/workflows/workflow.yaml | 40 +++++---------------------------- 1 file changed, 5 insertions(+), 35 deletions(-) diff --git a/.github/workflows/workflow.yaml b/.github/workflows/workflow.yaml index cd0a7f5e5..b1f2534f9 100644 --- a/.github/workflows/workflow.yaml +++ b/.github/workflows/workflow.yaml @@ -43,24 +43,13 @@ jobs: strategy: fail-fast: false matrix: - # TODO(chuck): FIX ME! - # os: [ubuntu-latest, macos-latest] - # module: [rules_haskell, rules_haskell_nix, rules_haskell_tests] - # DEBUG BEGIN - os: [macos-latest] - module: [rules_haskell_tests] - # DEBUG END - # TODO(chuck): FIX ME! - # bzlmod: [true, false] - # ghc: - # - 9.2.8 - # - 9.4.6 - # - 9.6.2 - # DEBUG BEGIN - bzlmod: [true] + os: [ubuntu-latest, macos-latest] + module: [rules_haskell, rules_haskell_nix, rules_haskell_tests] + bzlmod: [true, false] ghc: - 9.2.8 - # DEBUG END + - 9.4.6 + - 9.6.2 exclude: - module: rules_haskell_nix @@ -110,10 +99,6 @@ jobs: EOF cp .bazelrc.local rules_haskell_nix cp .bazelrc.local rules_haskell_tests - # DEBUG BEGIN - - name: Setup tmate session - uses: mxschmitt/action-tmate@v3 - # DEBUG END - name: Build & test - rules_haskell if: matrix.module == 'rules_haskell' uses: tweag/run-nix-shell@v0 @@ -136,9 +121,6 @@ jobs: with: options: ${{ env.NIX_SHELL_ARGS }} working-directory: rules_haskell_tests - # DEBUG BEGIN - # pure: false - # DEBUG END run: | # XXX run start script `--with-bzlmod=true` when supported if ! ${{ matrix.bzlmod }}; then @@ -148,19 +130,7 @@ jobs: # Shutdown Bazel to free up memory # https://github.com/tweag/rules_haskell/issues/2089. bazel shutdown - # # DEBUG BEGIN - # echo >&2 "CHUCK BEFORE" - # # top -l 1 -s 0 -o mem | head -n 25 >&2 - # top -l 1 -s 0 -o mem >&2 - # echo >&2 "run-tests" - # # DEBUG END ./bazel-ci-bin/tests/run-tests - # ./bazel-ci-bin/tests/run-tests || true - # # DEBUG BEGIN - # echo >&2 "CHUCK AFTER" - # # top -l 1 -s 0 -o mem | head -n 25 >&2 - # top -l 1 -s 0 -o mem >&2 - # # DEBUG END bazel coverage //... test-bindist: From 812c47d27e3e90dea0cab7fc624b2d39a5e5912d Mon Sep 17 00:00:00 2001 From: Chuck Grindel Date: Wed, 3 Jan 2024 08:15:36 -0700 Subject: [PATCH 16/37] Update comments. --- rules_haskell_tests/tests/RunTests.hs | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/rules_haskell_tests/tests/RunTests.hs b/rules_haskell_tests/tests/RunTests.hs index 751a68433..b1bf4a4da 100644 --- a/rules_haskell_tests/tests/RunTests.hs +++ b/rules_haskell_tests/tests/RunTests.hs @@ -168,21 +168,22 @@ bazel args = Process.proc "bazel" args bazelQuery :: String -> SpecM a [String] bazelQuery q = lines <$> runIO (Process.readProcess "bazel" ["query", q] "") +-- | Shutdown Bazel shutdownBazel :: IO () shutdownBazel = do - -- DEBUG BEGIN - printMem "BEFORE" - -- DEBUG END + -- Related to https://github.com/tweag/rules_haskell/issues/2089 + -- We experience intermittent "Exit Code: ExitFailure (-9)" errors. Added the + -- printMemory calls to help us debug when the error happens again. + printMemory "BEFORE" assertSuccess (bazel ["shutdown"]) - -- DEBUG BEGIN - printMem "AFTER" - -- DEBUG END + printMemory "AFTER" pure () -printMem :: String -> IO () -printMem msg = do +-- | Print information about the current memory state to debug intermittent failures +-- Related to https://github.com/tweag/rules_haskell/issues/2089 +printMemory :: String -> IO () +printMemory msg = do putStrLn msg - -- (_, stdOut, _) <- Process.readProcessWithExitCode "/usr/bin/memory_pressure" [] "" (_, stdOut, _) <- Process.readProcessWithExitCode "/usr/bin/top" ["-l", "1", "-s", "0", "-o", "mem", "-n", "15"] "" putStrLn stdOut From a66b72b1ac2c739468c3f8254b68196fcd4a12fd Mon Sep 17 00:00:00 2001 From: Chuck Grindel Date: Wed, 3 Jan 2024 08:49:16 -0700 Subject: [PATCH 17/37] Add hook to print memory info before/after tests. --- rules_haskell_tests/tests/RunTests.hs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/rules_haskell_tests/tests/RunTests.hs b/rules_haskell_tests/tests/RunTests.hs index b1bf4a4da..85bd17e9e 100644 --- a/rules_haskell_tests/tests/RunTests.hs +++ b/rules_haskell_tests/tests/RunTests.hs @@ -23,7 +23,7 @@ import IntegrationTesting main :: IO () main = hspec $ do - afterAll_ shutdownBazel $ do + afterAll_ shutdownBazel $ after_ printMemoryHook $ do it "bazel test" $ do assertSuccess (bazel ["test", "//..."]) @@ -179,6 +179,14 @@ shutdownBazel = do printMemory "AFTER" pure () +-- | Print memory information before and after each test +printMemoryHook :: IO () -> IO () +printMemoryHook action = bracket + (printMemory "BEFORE") + (printMemory "AFTER") + (const action) + + -- | Print information about the current memory state to debug intermittent failures -- Related to https://github.com/tweag/rules_haskell/issues/2089 printMemory :: String -> IO () From f5db8d1cdae7201a4b62aff73529d2a7b93c8d83 Mon Sep 17 00:00:00 2001 From: Chuck Grindel Date: Wed, 3 Jan 2024 08:54:57 -0700 Subject: [PATCH 18/37] Add after_ to import list. --- rules_haskell_tests/tests/RunTests.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rules_haskell_tests/tests/RunTests.hs b/rules_haskell_tests/tests/RunTests.hs index 85bd17e9e..5de4b228e 100644 --- a/rules_haskell_tests/tests/RunTests.hs +++ b/rules_haskell_tests/tests/RunTests.hs @@ -14,7 +14,7 @@ import System.Environment (lookupEnv) import qualified System.Process as Process import Test.Hspec.Core.Spec (SpecM) -import Test.Hspec (context, hspec, it, describe, runIO, afterAll_) +import Test.Hspec (context, hspec, it, describe, runIO, after_, afterAll_) import BinModule (b) import GenModule (a) From 0bd50210963dd85f81a327108e773b473b89e4e3 Mon Sep 17 00:00:00 2001 From: Chuck Grindel Date: Wed, 3 Jan 2024 10:49:25 -0700 Subject: [PATCH 19/37] Use bracket_ --- rules_haskell_tests/tests/RunTests.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rules_haskell_tests/tests/RunTests.hs b/rules_haskell_tests/tests/RunTests.hs index 5de4b228e..82b0bf8f6 100644 --- a/rules_haskell_tests/tests/RunTests.hs +++ b/rules_haskell_tests/tests/RunTests.hs @@ -181,7 +181,7 @@ shutdownBazel = do -- | Print memory information before and after each test printMemoryHook :: IO () -> IO () -printMemoryHook action = bracket +printMemoryHook action = bracket_ (printMemory "BEFORE") (printMemory "AFTER") (const action) From 4dece53f9412ce352908f74ca260c1f32b2bcb44 Mon Sep 17 00:00:00 2001 From: Chuck Grindel Date: Wed, 3 Jan 2024 10:53:06 -0700 Subject: [PATCH 20/37] Undo indent. --- rules_haskell_tests/tests/RunTests.hs | 247 +++++++++++++------------- 1 file changed, 122 insertions(+), 125 deletions(-) diff --git a/rules_haskell_tests/tests/RunTests.hs b/rules_haskell_tests/tests/RunTests.hs index 82b0bf8f6..fdfad43b2 100644 --- a/rules_haskell_tests/tests/RunTests.hs +++ b/rules_haskell_tests/tests/RunTests.hs @@ -22,130 +22,129 @@ import GenModule (a) import IntegrationTesting main :: IO () -main = hspec $ do - afterAll_ shutdownBazel $ after_ printMemoryHook $ do - it "bazel test" $ do - assertSuccess (bazel ["test", "//..."]) - - it "bazel test prof" $ do - ghcVersion <- lookupEnv "GHC_VERSION" - - -- In .github/workflows/workflow.yaml we specify --test_tag_filters - -- -dont_test_on_darwin. However, specifiying --test_tag_filters - -- -requires_dynamic here alone would override that filter. So, - -- we have to duplicate that filter here. - let tagFilter | os == "darwin" = "-dont_test_on_darwin,-requires_dynamic,-skip_profiling" ++ ( - -- skip tests for specific GHC version, see https://github.com/tweag/rules_haskell/issues/2073 - maybe "" (",-dont_build_on_macos_with_ghc_" ++) ghcVersion) - | otherwise = "-requires_dynamic,-skip_profiling" - assertSuccess (bazel ["test", "-c", "dbg", "//...", "--build_tag_filters", tagFilter, "--test_tag_filters", tagFilter]) - - it "bazel build worker" $ do - assertSuccess (bazel ["build", "@rules_haskell//tools/worker:bin"]) - - describe "stack_snapshot pinning" $ - it "handles packages in subdirectories correctly" $ do - -- NOTE Keep in sync with - -- .github/workflows/workflow.yaml - let withBackup filename k = - withSystemTempDirectory "bazel_backup" $ \tmp_dir -> do - bracket_ - (copyFile filename (tmp_dir "backup")) - (copyFile (tmp_dir "backup") filename) - k - -- Test that pinning works and produces buildable targets. - -- Backup the lock file to avoid unintended changes when run locally. - withBackup "stackage-pinning-test_snapshot.json" $ do - assertSuccess (bazel ["run", "@stackage-pinning-test-unpinned//:pin"]) - assertSuccess (bazel ["build", "@stackage-pinning-test//:hspec"]) - - describe "repl" $ do - it "for libraries" $ do - assertSuccess (bazel ["run", "//tests/repl-targets:hs-lib-bad@repl", "--", "-ignore-dot-ghci", "-e", "1 + 2"]) - - it "for binaries" $ do - assertSuccess (bazel ["run", "//tests/binary-indirect-cbits:binary-indirect-cbits@repl", "--", "-ignore-dot-ghci", "-e", ":main"]) - - assertSuccess (bazel ["run", "//tests/repl-targets:hs-test-bad@repl", "--", "-ignore-dot-ghci", "-e", "1 + 2"]) - - it "with rebindable syntax" $ do - let p' (stdout, _stderr) = lines stdout == ["True"] - outputSatisfy p' (bazel ["run", "//tests/repl-targets:rebindable-syntax@repl", "--", "-ignore-dot-ghci", "-e", "check"]) - - it "sets classpath" $ do - assertSuccess (bazel ["run", "//tests/java_classpath:java_classpath@repl", "--", "-ignore-dot-ghci", "-e", ":main"]) - - -- Test `compiler_flags` from toolchain and rule for REPL +main = hspec $ afterAll_ shutdownBazel $ after_ printMemoryHook $ do + it "bazel test" $ do + assertSuccess (bazel ["test", "//..."]) + + it "bazel test prof" $ do + ghcVersion <- lookupEnv "GHC_VERSION" + + -- In .github/workflows/workflow.yaml we specify --test_tag_filters + -- -dont_test_on_darwin. However, specifiying --test_tag_filters + -- -requires_dynamic here alone would override that filter. So, + -- we have to duplicate that filter here. + let tagFilter | os == "darwin" = "-dont_test_on_darwin,-requires_dynamic,-skip_profiling" ++ ( + -- skip tests for specific GHC version, see https://github.com/tweag/rules_haskell/issues/2073 + maybe "" (",-dont_build_on_macos_with_ghc_" ++) ghcVersion) + | otherwise = "-requires_dynamic,-skip_profiling" + assertSuccess (bazel ["test", "-c", "dbg", "//...", "--build_tag_filters", tagFilter, "--test_tag_filters", tagFilter]) + + it "bazel build worker" $ do + assertSuccess (bazel ["build", "@rules_haskell//tools/worker:bin"]) + + describe "stack_snapshot pinning" $ + it "handles packages in subdirectories correctly" $ do + -- NOTE Keep in sync with + -- .github/workflows/workflow.yaml + let withBackup filename k = + withSystemTempDirectory "bazel_backup" $ \tmp_dir -> do + bracket_ + (copyFile filename (tmp_dir "backup")) + (copyFile (tmp_dir "backup") filename) + k + -- Test that pinning works and produces buildable targets. + -- Backup the lock file to avoid unintended changes when run locally. + withBackup "stackage-pinning-test_snapshot.json" $ do + assertSuccess (bazel ["run", "@stackage-pinning-test-unpinned//:pin"]) + assertSuccess (bazel ["build", "@stackage-pinning-test//:hspec"]) + + describe "repl" $ do + it "for libraries" $ do + assertSuccess (bazel ["run", "//tests/repl-targets:hs-lib-bad@repl", "--", "-ignore-dot-ghci", "-e", "1 + 2"]) + + it "for binaries" $ do + assertSuccess (bazel ["run", "//tests/binary-indirect-cbits:binary-indirect-cbits@repl", "--", "-ignore-dot-ghci", "-e", ":main"]) + + assertSuccess (bazel ["run", "//tests/repl-targets:hs-test-bad@repl", "--", "-ignore-dot-ghci", "-e", "1 + 2"]) + + it "with rebindable syntax" $ do + let p' (stdout, _stderr) = lines stdout == ["True"] + outputSatisfy p' (bazel ["run", "//tests/repl-targets:rebindable-syntax@repl", "--", "-ignore-dot-ghci", "-e", "check"]) + + it "sets classpath" $ do + assertSuccess (bazel ["run", "//tests/java_classpath:java_classpath@repl", "--", "-ignore-dot-ghci", "-e", ":main"]) + + -- Test `compiler_flags` from toolchain and rule for REPL + it "compiler flags" $ do + assertSuccess (bazel ["run", "//tests/repl-flags:compiler_flags@repl", "--", "-ignore-dot-ghci", "-e", ":main"]) + + -- Test make variable expansion in `compiler_flags` and `repl_ghci_args`. + describe "make variables" $ do it "compiler flags" $ do - assertSuccess (bazel ["run", "//tests/repl-flags:compiler_flags@repl", "--", "-ignore-dot-ghci", "-e", ":main"]) - - -- Test make variable expansion in `compiler_flags` and `repl_ghci_args`. - describe "make variables" $ do - it "compiler flags" $ do - assertSuccess (bazel ["run", "//tests/repl-make-variables:test-compiler-flags@repl", "--", "-ignore-dot-ghci", "-e", ":main"]) - it "indirect repl flags" $ do - assertSuccess (bazel ["run", "//tests/repl-make-variables:repl-indirect-flags", "--", "-ignore-dot-ghci", "-e", ":main"]) - it "direct repl flags" $ do - assertSuccess (bazel ["run", "//tests/repl-make-variables:repl-direct-flags", "--", "-ignore-dot-ghci", "-e", ":main"]) - - -- Test `repl_ghci_args` from toolchain and rule for REPL - it "repl flags" $ do - assertSuccess (bazel ["run", "//tests/repl-flags:repl_flags@repl", "--", "-ignore-dot-ghci", "-e", "foo"]) - - it "fails on multiple definitions" $ do - assertSuccess (bazel ["run", "//tests/repl-multiple-definition:repl", "--", "-ignore-dot-ghci", "-e", "final"]) - - describe "multi_repl" $ do - it "loads transitive library dependencies" $ do - let p' (stdout, _stderr) = lines stdout == ["tests/multi_repl/bc/src/BC/C.hs"] - outputSatisfy p' (bazel ["run", "//tests/multi_repl:c_only_repl", "--", "-ignore-dot-ghci", "-e", ":show targets"]) - it "loads transitive source dependencies" $ do - let p' (stdout, _stderr) = sort (lines stdout) == ["tests/multi_repl/a/src/A/A.hs","tests/multi_repl/bc/src/BC/B.hs","tests/multi_repl/bc/src/BC/C.hs"] - outputSatisfy p' (bazel ["run", "//tests/multi_repl:c_multi_repl", "--", "-ignore-dot-ghci", "-e", ":show targets"]) - it "loads core library dependencies" $ do - let p' (stdout, _stderr) = sort (lines stdout) == ["tests/multi_repl/core_package_dep/Lib.hs"] - outputSatisfy p' (bazel ["run", "//tests/multi_repl:core_package_dep", "--", "-ignore-dot-ghci", "-e", ":show targets"]) - it "doesn't allow to manually load modules" $ do - assertFailure (bazel ["run", "//tests/multi_repl:c_multi_repl", "--", "-ignore-dot-ghci", "-e", ":load BC.C", "-e", "c"]) - - describe "ghcide" $ do - it "loads RunTests.hs" $ - assertSuccess (Process.proc "./.ghcide" ["tests/RunTests.hs"]) - it "loads module with module dependency" $ - assertSuccess (Process.proc "./.ghcide" ["tests/binary-with-lib/Main.hs"]) - - describe "failures" $ do - -- Make sure not to include haskell_repl (@repl) or alias (-repl) targets - -- in the query. Those would not fail under bazel test. - all_failure_tests <- bazelQuery "kind('haskell_library|haskell_binary|haskell_test', //tests/failures/...) intersect attr('tags', 'manual', //tests/failures/...)" - - for_ all_failure_tests $ \test -> do - it test $ do - assertFailure (bazel ["build", test]) - - context "known issues" $ do - it "haskell_doc fails with plugins #1549" $ - -- https://github.com/tweag/rules_haskell/issues/1549 - assertFailure (bazel ["build", "//tests/haddock-with-plugin"]) - it "transitive re-exports do not work #1145" $ - -- https://github.com/tweag/rules_haskell/issues/1145 - assertFailure (bazel ["build", "//tests/package-reexport-transitive"]) - it "doctest failure with foreign import #1559" $ - -- https://github.com/tweag/rules_haskell/issues/1559 - assertFailure (bazel ["build", "//tests/haskell_doctest_ffi_1559:doctest-a"]) - - -- Test that the repl still works if we shadow some Prelude functions - it "repl name shadowing" $ do - let p (stdout, stderr) = not $ any ("error" `isInfixOf`) [stdout, stderr] - outputSatisfy p (bazel ["run", "//tests/repl-name-conflicts:lib@repl", "--", "-ignore-dot-ghci", "-e", "stdin"]) - - it "Repl works with remote_download_toplevel" $ do - let p (stdout, stderr) = not $ any ("error" `isInfixOf`) [stdout, stderr] - withSystemTempDirectory "bazel_disk_cache" $ \tmp_disk_cache -> do - assertSuccess $ bazel ["run", "//tests/multi_repl:c_only_repl", "--disk_cache=" <> tmp_disk_cache] - assertSuccess $ bazel ["clean"] - outputSatisfy p - (bazel ["run", "//tests/multi_repl:c_only_repl", "--disk_cache=" <> tmp_disk_cache, "--remote_download_toplevel"]) + assertSuccess (bazel ["run", "//tests/repl-make-variables:test-compiler-flags@repl", "--", "-ignore-dot-ghci", "-e", ":main"]) + it "indirect repl flags" $ do + assertSuccess (bazel ["run", "//tests/repl-make-variables:repl-indirect-flags", "--", "-ignore-dot-ghci", "-e", ":main"]) + it "direct repl flags" $ do + assertSuccess (bazel ["run", "//tests/repl-make-variables:repl-direct-flags", "--", "-ignore-dot-ghci", "-e", ":main"]) + + -- Test `repl_ghci_args` from toolchain and rule for REPL + it "repl flags" $ do + assertSuccess (bazel ["run", "//tests/repl-flags:repl_flags@repl", "--", "-ignore-dot-ghci", "-e", "foo"]) + + it "fails on multiple definitions" $ do + assertSuccess (bazel ["run", "//tests/repl-multiple-definition:repl", "--", "-ignore-dot-ghci", "-e", "final"]) + + describe "multi_repl" $ do + it "loads transitive library dependencies" $ do + let p' (stdout, _stderr) = lines stdout == ["tests/multi_repl/bc/src/BC/C.hs"] + outputSatisfy p' (bazel ["run", "//tests/multi_repl:c_only_repl", "--", "-ignore-dot-ghci", "-e", ":show targets"]) + it "loads transitive source dependencies" $ do + let p' (stdout, _stderr) = sort (lines stdout) == ["tests/multi_repl/a/src/A/A.hs","tests/multi_repl/bc/src/BC/B.hs","tests/multi_repl/bc/src/BC/C.hs"] + outputSatisfy p' (bazel ["run", "//tests/multi_repl:c_multi_repl", "--", "-ignore-dot-ghci", "-e", ":show targets"]) + it "loads core library dependencies" $ do + let p' (stdout, _stderr) = sort (lines stdout) == ["tests/multi_repl/core_package_dep/Lib.hs"] + outputSatisfy p' (bazel ["run", "//tests/multi_repl:core_package_dep", "--", "-ignore-dot-ghci", "-e", ":show targets"]) + it "doesn't allow to manually load modules" $ do + assertFailure (bazel ["run", "//tests/multi_repl:c_multi_repl", "--", "-ignore-dot-ghci", "-e", ":load BC.C", "-e", "c"]) + + describe "ghcide" $ do + it "loads RunTests.hs" $ + assertSuccess (Process.proc "./.ghcide" ["tests/RunTests.hs"]) + it "loads module with module dependency" $ + assertSuccess (Process.proc "./.ghcide" ["tests/binary-with-lib/Main.hs"]) + + describe "failures" $ do + -- Make sure not to include haskell_repl (@repl) or alias (-repl) targets + -- in the query. Those would not fail under bazel test. + all_failure_tests <- bazelQuery "kind('haskell_library|haskell_binary|haskell_test', //tests/failures/...) intersect attr('tags', 'manual', //tests/failures/...)" + + for_ all_failure_tests $ \test -> do + it test $ do + assertFailure (bazel ["build", test]) + + context "known issues" $ do + it "haskell_doc fails with plugins #1549" $ + -- https://github.com/tweag/rules_haskell/issues/1549 + assertFailure (bazel ["build", "//tests/haddock-with-plugin"]) + it "transitive re-exports do not work #1145" $ + -- https://github.com/tweag/rules_haskell/issues/1145 + assertFailure (bazel ["build", "//tests/package-reexport-transitive"]) + it "doctest failure with foreign import #1559" $ + -- https://github.com/tweag/rules_haskell/issues/1559 + assertFailure (bazel ["build", "//tests/haskell_doctest_ffi_1559:doctest-a"]) + + -- Test that the repl still works if we shadow some Prelude functions + it "repl name shadowing" $ do + let p (stdout, stderr) = not $ any ("error" `isInfixOf`) [stdout, stderr] + outputSatisfy p (bazel ["run", "//tests/repl-name-conflicts:lib@repl", "--", "-ignore-dot-ghci", "-e", "stdin"]) + + it "Repl works with remote_download_toplevel" $ do + let p (stdout, stderr) = not $ any ("error" `isInfixOf`) [stdout, stderr] + withSystemTempDirectory "bazel_disk_cache" $ \tmp_disk_cache -> do + assertSuccess $ bazel ["run", "//tests/multi_repl:c_only_repl", "--disk_cache=" <> tmp_disk_cache] + assertSuccess $ bazel ["clean"] + outputSatisfy p + (bazel ["run", "//tests/multi_repl:c_only_repl", "--disk_cache=" <> tmp_disk_cache, "--remote_download_toplevel"]) it "bazel test examples" $ do assertSuccess $ (bazel ["build", "//..."]) { Process.cwd = Just "../examples" } @@ -174,9 +173,7 @@ shutdownBazel = do -- Related to https://github.com/tweag/rules_haskell/issues/2089 -- We experience intermittent "Exit Code: ExitFailure (-9)" errors. Added the -- printMemory calls to help us debug when the error happens again. - printMemory "BEFORE" assertSuccess (bazel ["shutdown"]) - printMemory "AFTER" pure () -- | Print memory information before and after each test From 8f585b6c62a11c74e9ed50213d3f7df05b88416a Mon Sep 17 00:00:00 2001 From: Chuck Grindel Date: Wed, 3 Jan 2024 10:54:07 -0700 Subject: [PATCH 21/37] Remove extra line --- rules_haskell_tests/tests/RunTests.hs | 1 - 1 file changed, 1 deletion(-) diff --git a/rules_haskell_tests/tests/RunTests.hs b/rules_haskell_tests/tests/RunTests.hs index fdfad43b2..51f6c33b4 100644 --- a/rules_haskell_tests/tests/RunTests.hs +++ b/rules_haskell_tests/tests/RunTests.hs @@ -183,7 +183,6 @@ printMemoryHook action = bracket_ (printMemory "AFTER") (const action) - -- | Print information about the current memory state to debug intermittent failures -- Related to https://github.com/tweag/rules_haskell/issues/2089 printMemory :: String -> IO () From e9614cef1997f0ad364985256d00c3c86b90baec Mon Sep 17 00:00:00 2001 From: Chuck Grindel Date: Wed, 3 Jan 2024 11:14:25 -0700 Subject: [PATCH 22/37] Remove const --- rules_haskell_tests/tests/RunTests.hs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/rules_haskell_tests/tests/RunTests.hs b/rules_haskell_tests/tests/RunTests.hs index 51f6c33b4..7ddcc2f33 100644 --- a/rules_haskell_tests/tests/RunTests.hs +++ b/rules_haskell_tests/tests/RunTests.hs @@ -171,8 +171,8 @@ bazelQuery q = lines <$> runIO (Process.readProcess "bazel" ["query", q] "") shutdownBazel :: IO () shutdownBazel = do -- Related to https://github.com/tweag/rules_haskell/issues/2089 - -- We experience intermittent "Exit Code: ExitFailure (-9)" errors. Added the - -- printMemory calls to help us debug when the error happens again. + -- We experience intermittent "Exit Code: ExitFailure (-9)" errors. Shutdown + -- Bazel when done executing tests for the workspace. assertSuccess (bazel ["shutdown"]) pure () @@ -181,7 +181,7 @@ printMemoryHook :: IO () -> IO () printMemoryHook action = bracket_ (printMemory "BEFORE") (printMemory "AFTER") - (const action) + action -- | Print information about the current memory state to debug intermittent failures -- Related to https://github.com/tweag/rules_haskell/issues/2089 From 92fc02151e4d6949caa239019125faa801d6370b Mon Sep 17 00:00:00 2001 From: Chuck Grindel Date: Wed, 3 Jan 2024 11:23:30 -0700 Subject: [PATCH 23/37] Fixed typo. --- rules_haskell_tests/tests/RunTests.hs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rules_haskell_tests/tests/RunTests.hs b/rules_haskell_tests/tests/RunTests.hs index 7ddcc2f33..32ecab15b 100644 --- a/rules_haskell_tests/tests/RunTests.hs +++ b/rules_haskell_tests/tests/RunTests.hs @@ -14,7 +14,7 @@ import System.Environment (lookupEnv) import qualified System.Process as Process import Test.Hspec.Core.Spec (SpecM) -import Test.Hspec (context, hspec, it, describe, runIO, after_, afterAll_) +import Test.Hspec (context, hspec, it, describe, runIO, around_, afterAll_) import BinModule (b) import GenModule (a) @@ -22,7 +22,7 @@ import GenModule (a) import IntegrationTesting main :: IO () -main = hspec $ afterAll_ shutdownBazel $ after_ printMemoryHook $ do +main = hspec $ afterAll_ shutdownBazel $ around_ printMemoryHook $ do it "bazel test" $ do assertSuccess (bazel ["test", "//..."]) From 88a3e7b888f06c16dd1d4a1846f6f0aaf41d3464 Mon Sep 17 00:00:00 2001 From: Chuck Grindel Date: Wed, 3 Jan 2024 12:19:55 -0700 Subject: [PATCH 24/37] printMemory to output info about top failure. --- rules_haskell_tests/tests/RunTests.hs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/rules_haskell_tests/tests/RunTests.hs b/rules_haskell_tests/tests/RunTests.hs index 32ecab15b..cbdceae25 100644 --- a/rules_haskell_tests/tests/RunTests.hs +++ b/rules_haskell_tests/tests/RunTests.hs @@ -11,6 +11,7 @@ import System.FilePath (()) import System.Info (os) import System.IO.Temp (withSystemTempDirectory) import System.Environment (lookupEnv) +import System.Exit (ExitCode(..)) import qualified System.Process as Process import Test.Hspec.Core.Spec (SpecM) @@ -179,8 +180,8 @@ shutdownBazel = do -- | Print memory information before and after each test printMemoryHook :: IO () -> IO () printMemoryHook action = bracket_ - (printMemory "BEFORE") - (printMemory "AFTER") + (printMemory "=== BEFORE ===") + (printMemory "=== AFTER ===") action -- | Print information about the current memory state to debug intermittent failures @@ -188,8 +189,13 @@ printMemoryHook action = bracket_ printMemory :: String -> IO () printMemory msg = do putStrLn msg - (_, stdOut, _) <- Process.readProcessWithExitCode "/usr/bin/top" ["-l", "1", "-s", "0", "-o", "mem", "-n", "15"] "" - putStrLn stdOut + (exitCode, stdOut, stdErr) <- Process.readProcessWithExitCode "top" ["-l", "1", "-s", "0", "-o", "mem", "-n", "15"] "" + -- (exitCode, stdOut, stdErr) <- Process.readProcessWithExitCode "/usr/bin/top" ["-l", "1", "-s", "0", "-o", "mem", "-n", "15"] "" + -- (exitCode, stdOut, stdErr) <- Process.readProcessWithExitCode "foo" ["-l", "1", "-s", "0", "-o", "mem", "-n", "15"] "" + -- putStrLn stdOut + case exitCode of + ExitSuccess -> putStrLn stdOut + ExitFailure _ -> putStrLn ("=== printMemory failed ===\n" ++ stdErr) -- Generated dependencies for testing the ghcide support _ghciIDE :: Int From 71b4c84fbb3909cc1e9d91036ae752db5f38d049 Mon Sep 17 00:00:00 2001 From: Chuck Grindel Date: Wed, 3 Jan 2024 14:11:54 -0700 Subject: [PATCH 25/37] Install procps --- rules_haskell_tests/shell.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rules_haskell_tests/shell.nix b/rules_haskell_tests/shell.nix index d040173ab..47a2bf145 100644 --- a/rules_haskell_tests/shell.nix +++ b/rules_haskell_tests/shell.nix @@ -38,7 +38,7 @@ mkShell { file ] ++ lib.optionals docTools [ graphviz python39Packages.sphinx zip unzip ]; - packages = [ bazel_6 ]; + packages = [ bazel_6 procps ]; shellHook = '' # Add nix config flags to .bazelrc.local. From a803c0610d5ae175397d30a101167ef9e479cb06 Mon Sep 17 00:00:00 2001 From: Chuck Grindel Date: Wed, 3 Jan 2024 16:29:06 -0700 Subject: [PATCH 26/37] Remove added packages --- rules_haskell_tests/shell.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rules_haskell_tests/shell.nix b/rules_haskell_tests/shell.nix index 47a2bf145..d040173ab 100644 --- a/rules_haskell_tests/shell.nix +++ b/rules_haskell_tests/shell.nix @@ -38,7 +38,7 @@ mkShell { file ] ++ lib.optionals docTools [ graphviz python39Packages.sphinx zip unzip ]; - packages = [ bazel_6 procps ]; + packages = [ bazel_6 ]; shellHook = '' # Add nix config flags to .bazelrc.local. From 3fbddb4a66299f16e3c98d870521afb68a9942b3 Mon Sep 17 00:00:00 2001 From: Chuck Grindel Date: Wed, 3 Jan 2024 16:29:56 -0700 Subject: [PATCH 27/37] Try just using system-installed top. --- rules_haskell_tests/tests/RunTests.hs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/rules_haskell_tests/tests/RunTests.hs b/rules_haskell_tests/tests/RunTests.hs index cbdceae25..b08c8db61 100644 --- a/rules_haskell_tests/tests/RunTests.hs +++ b/rules_haskell_tests/tests/RunTests.hs @@ -189,10 +189,7 @@ printMemoryHook action = bracket_ printMemory :: String -> IO () printMemory msg = do putStrLn msg - (exitCode, stdOut, stdErr) <- Process.readProcessWithExitCode "top" ["-l", "1", "-s", "0", "-o", "mem", "-n", "15"] "" - -- (exitCode, stdOut, stdErr) <- Process.readProcessWithExitCode "/usr/bin/top" ["-l", "1", "-s", "0", "-o", "mem", "-n", "15"] "" - -- (exitCode, stdOut, stdErr) <- Process.readProcessWithExitCode "foo" ["-l", "1", "-s", "0", "-o", "mem", "-n", "15"] "" - -- putStrLn stdOut + (exitCode, stdOut, stdErr) <- Process.readProcessWithExitCode "/usr/bin/top" ["-l", "1", "-s", "0", "-o", "mem", "-n", "15"] "" case exitCode of ExitSuccess -> putStrLn stdOut ExitFailure _ -> putStrLn ("=== printMemory failed ===\n" ++ stdErr) From eb5a227d61420301edbe35a93d3d61fa8aa84b2d Mon Sep 17 00:00:00 2001 From: Chuck Grindel Date: Thu, 4 Jan 2024 08:47:09 -0700 Subject: [PATCH 28/37] Refactor common steps into buildAndTest hook. --- rules_haskell_tests/tests/RunTests.hs | 277 +++++++++++++------------- 1 file changed, 141 insertions(+), 136 deletions(-) diff --git a/rules_haskell_tests/tests/RunTests.hs b/rules_haskell_tests/tests/RunTests.hs index b08c8db61..b272af096 100644 --- a/rules_haskell_tests/tests/RunTests.hs +++ b/rules_haskell_tests/tests/RunTests.hs @@ -6,6 +6,7 @@ import Control.Exception.Safe (bracket_) import Data.Foldable (for_) import Data.List (isInfixOf, sort) +import GHC.Stack (HasCallStack) import System.Directory (copyFile) import System.FilePath (()) import System.Info (os) @@ -14,7 +15,7 @@ import System.Environment (lookupEnv) import System.Exit (ExitCode(..)) import qualified System.Process as Process -import Test.Hspec.Core.Spec (SpecM) +import Test.Hspec.Core.Spec (SpecM, SpecWith) import Test.Hspec (context, hspec, it, describe, runIO, around_, afterAll_) import BinModule (b) @@ -23,139 +24,134 @@ import GenModule (a) import IntegrationTesting main :: IO () -main = hspec $ afterAll_ shutdownBazel $ around_ printMemoryHook $ do - it "bazel test" $ do - assertSuccess (bazel ["test", "//..."]) - - it "bazel test prof" $ do - ghcVersion <- lookupEnv "GHC_VERSION" - - -- In .github/workflows/workflow.yaml we specify --test_tag_filters - -- -dont_test_on_darwin. However, specifiying --test_tag_filters - -- -requires_dynamic here alone would override that filter. So, - -- we have to duplicate that filter here. - let tagFilter | os == "darwin" = "-dont_test_on_darwin,-requires_dynamic,-skip_profiling" ++ ( - -- skip tests for specific GHC version, see https://github.com/tweag/rules_haskell/issues/2073 - maybe "" (",-dont_build_on_macos_with_ghc_" ++) ghcVersion) - | otherwise = "-requires_dynamic,-skip_profiling" - assertSuccess (bazel ["test", "-c", "dbg", "//...", "--build_tag_filters", tagFilter, "--test_tag_filters", tagFilter]) - - it "bazel build worker" $ do - assertSuccess (bazel ["build", "@rules_haskell//tools/worker:bin"]) - - describe "stack_snapshot pinning" $ - it "handles packages in subdirectories correctly" $ do - -- NOTE Keep in sync with - -- .github/workflows/workflow.yaml - let withBackup filename k = - withSystemTempDirectory "bazel_backup" $ \tmp_dir -> do - bracket_ - (copyFile filename (tmp_dir "backup")) - (copyFile (tmp_dir "backup") filename) - k - -- Test that pinning works and produces buildable targets. - -- Backup the lock file to avoid unintended changes when run locally. - withBackup "stackage-pinning-test_snapshot.json" $ do - assertSuccess (bazel ["run", "@stackage-pinning-test-unpinned//:pin"]) - assertSuccess (bazel ["build", "@stackage-pinning-test//:hspec"]) - - describe "repl" $ do - it "for libraries" $ do - assertSuccess (bazel ["run", "//tests/repl-targets:hs-lib-bad@repl", "--", "-ignore-dot-ghci", "-e", "1 + 2"]) - - it "for binaries" $ do - assertSuccess (bazel ["run", "//tests/binary-indirect-cbits:binary-indirect-cbits@repl", "--", "-ignore-dot-ghci", "-e", ":main"]) - - assertSuccess (bazel ["run", "//tests/repl-targets:hs-test-bad@repl", "--", "-ignore-dot-ghci", "-e", "1 + 2"]) - - it "with rebindable syntax" $ do - let p' (stdout, _stderr) = lines stdout == ["True"] - outputSatisfy p' (bazel ["run", "//tests/repl-targets:rebindable-syntax@repl", "--", "-ignore-dot-ghci", "-e", "check"]) - - it "sets classpath" $ do - assertSuccess (bazel ["run", "//tests/java_classpath:java_classpath@repl", "--", "-ignore-dot-ghci", "-e", ":main"]) - - -- Test `compiler_flags` from toolchain and rule for REPL - it "compiler flags" $ do - assertSuccess (bazel ["run", "//tests/repl-flags:compiler_flags@repl", "--", "-ignore-dot-ghci", "-e", ":main"]) - - -- Test make variable expansion in `compiler_flags` and `repl_ghci_args`. - describe "make variables" $ do +main = hspec $ around_ printMemoryHook $ do + + describe "rules_haskell_tests" $ afterAll_ (shutdownBazel ".") $ do + it "bazel test" $ do + assertSuccess (bazel ["test", "//..."]) + + it "bazel test prof" $ do + ghcVersion <- lookupEnv "GHC_VERSION" + + -- In .github/workflows/workflow.yaml we specify --test_tag_filters + -- -dont_test_on_darwin. However, specifiying --test_tag_filters + -- -requires_dynamic here alone would override that filter. So, + -- we have to duplicate that filter here. + let tagFilter | os == "darwin" = "-dont_test_on_darwin,-requires_dynamic,-skip_profiling" ++ ( + -- skip tests for specific GHC version, see https://github.com/tweag/rules_haskell/issues/2073 + maybe "" (",-dont_build_on_macos_with_ghc_" ++) ghcVersion) + | otherwise = "-requires_dynamic,-skip_profiling" + assertSuccess (bazel ["test", "-c", "dbg", "//...", "--build_tag_filters", tagFilter, "--test_tag_filters", tagFilter]) + + it "bazel build worker" $ do + assertSuccess (bazel ["build", "@rules_haskell//tools/worker:bin"]) + + describe "stack_snapshot pinning" $ + it "handles packages in subdirectories correctly" $ do + -- NOTE Keep in sync with + -- .github/workflows/workflow.yaml + let withBackup filename k = + withSystemTempDirectory "bazel_backup" $ \tmp_dir -> do + bracket_ + (copyFile filename (tmp_dir "backup")) + (copyFile (tmp_dir "backup") filename) + k + -- Test that pinning works and produces buildable targets. + -- Backup the lock file to avoid unintended changes when run locally. + withBackup "stackage-pinning-test_snapshot.json" $ do + assertSuccess (bazel ["run", "@stackage-pinning-test-unpinned//:pin"]) + assertSuccess (bazel ["build", "@stackage-pinning-test//:hspec"]) + + describe "repl" $ do + it "for libraries" $ do + assertSuccess (bazel ["run", "//tests/repl-targets:hs-lib-bad@repl", "--", "-ignore-dot-ghci", "-e", "1 + 2"]) + + it "for binaries" $ do + assertSuccess (bazel ["run", "//tests/binary-indirect-cbits:binary-indirect-cbits@repl", "--", "-ignore-dot-ghci", "-e", ":main"]) + + assertSuccess (bazel ["run", "//tests/repl-targets:hs-test-bad@repl", "--", "-ignore-dot-ghci", "-e", "1 + 2"]) + + it "with rebindable syntax" $ do + let p' (stdout, _stderr) = lines stdout == ["True"] + outputSatisfy p' (bazel ["run", "//tests/repl-targets:rebindable-syntax@repl", "--", "-ignore-dot-ghci", "-e", "check"]) + + it "sets classpath" $ do + assertSuccess (bazel ["run", "//tests/java_classpath:java_classpath@repl", "--", "-ignore-dot-ghci", "-e", ":main"]) + + -- Test `compiler_flags` from toolchain and rule for REPL it "compiler flags" $ do - assertSuccess (bazel ["run", "//tests/repl-make-variables:test-compiler-flags@repl", "--", "-ignore-dot-ghci", "-e", ":main"]) - it "indirect repl flags" $ do - assertSuccess (bazel ["run", "//tests/repl-make-variables:repl-indirect-flags", "--", "-ignore-dot-ghci", "-e", ":main"]) - it "direct repl flags" $ do - assertSuccess (bazel ["run", "//tests/repl-make-variables:repl-direct-flags", "--", "-ignore-dot-ghci", "-e", ":main"]) - - -- Test `repl_ghci_args` from toolchain and rule for REPL - it "repl flags" $ do - assertSuccess (bazel ["run", "//tests/repl-flags:repl_flags@repl", "--", "-ignore-dot-ghci", "-e", "foo"]) - - it "fails on multiple definitions" $ do - assertSuccess (bazel ["run", "//tests/repl-multiple-definition:repl", "--", "-ignore-dot-ghci", "-e", "final"]) - - describe "multi_repl" $ do - it "loads transitive library dependencies" $ do - let p' (stdout, _stderr) = lines stdout == ["tests/multi_repl/bc/src/BC/C.hs"] - outputSatisfy p' (bazel ["run", "//tests/multi_repl:c_only_repl", "--", "-ignore-dot-ghci", "-e", ":show targets"]) - it "loads transitive source dependencies" $ do - let p' (stdout, _stderr) = sort (lines stdout) == ["tests/multi_repl/a/src/A/A.hs","tests/multi_repl/bc/src/BC/B.hs","tests/multi_repl/bc/src/BC/C.hs"] - outputSatisfy p' (bazel ["run", "//tests/multi_repl:c_multi_repl", "--", "-ignore-dot-ghci", "-e", ":show targets"]) - it "loads core library dependencies" $ do - let p' (stdout, _stderr) = sort (lines stdout) == ["tests/multi_repl/core_package_dep/Lib.hs"] - outputSatisfy p' (bazel ["run", "//tests/multi_repl:core_package_dep", "--", "-ignore-dot-ghci", "-e", ":show targets"]) - it "doesn't allow to manually load modules" $ do - assertFailure (bazel ["run", "//tests/multi_repl:c_multi_repl", "--", "-ignore-dot-ghci", "-e", ":load BC.C", "-e", "c"]) - - describe "ghcide" $ do - it "loads RunTests.hs" $ - assertSuccess (Process.proc "./.ghcide" ["tests/RunTests.hs"]) - it "loads module with module dependency" $ - assertSuccess (Process.proc "./.ghcide" ["tests/binary-with-lib/Main.hs"]) - - describe "failures" $ do - -- Make sure not to include haskell_repl (@repl) or alias (-repl) targets - -- in the query. Those would not fail under bazel test. - all_failure_tests <- bazelQuery "kind('haskell_library|haskell_binary|haskell_test', //tests/failures/...) intersect attr('tags', 'manual', //tests/failures/...)" - - for_ all_failure_tests $ \test -> do - it test $ do - assertFailure (bazel ["build", test]) - - context "known issues" $ do - it "haskell_doc fails with plugins #1549" $ - -- https://github.com/tweag/rules_haskell/issues/1549 - assertFailure (bazel ["build", "//tests/haddock-with-plugin"]) - it "transitive re-exports do not work #1145" $ - -- https://github.com/tweag/rules_haskell/issues/1145 - assertFailure (bazel ["build", "//tests/package-reexport-transitive"]) - it "doctest failure with foreign import #1559" $ - -- https://github.com/tweag/rules_haskell/issues/1559 - assertFailure (bazel ["build", "//tests/haskell_doctest_ffi_1559:doctest-a"]) - - -- Test that the repl still works if we shadow some Prelude functions - it "repl name shadowing" $ do - let p (stdout, stderr) = not $ any ("error" `isInfixOf`) [stdout, stderr] - outputSatisfy p (bazel ["run", "//tests/repl-name-conflicts:lib@repl", "--", "-ignore-dot-ghci", "-e", "stdin"]) - - it "Repl works with remote_download_toplevel" $ do - let p (stdout, stderr) = not $ any ("error" `isInfixOf`) [stdout, stderr] - withSystemTempDirectory "bazel_disk_cache" $ \tmp_disk_cache -> do - assertSuccess $ bazel ["run", "//tests/multi_repl:c_only_repl", "--disk_cache=" <> tmp_disk_cache] - assertSuccess $ bazel ["clean"] - outputSatisfy p - (bazel ["run", "//tests/multi_repl:c_only_repl", "--disk_cache=" <> tmp_disk_cache, "--remote_download_toplevel"]) - - it "bazel test examples" $ do - assertSuccess $ (bazel ["build", "//..."]) { Process.cwd = Just "../examples" } - assertSuccess $ (bazel ["test", "//..."]) { Process.cwd = Just "../examples" } - assertSuccess $ (bazel ["shutdown"]) { Process.cwd = Just "../examples" } - - it "bazel test tutorial" $ do - assertSuccess $ (bazel ["build", "//..."]) { Process.cwd = Just "../tutorial" } - assertSuccess (bazel ["test", "//..."]) { Process.cwd = Just "../tutorial" } - assertSuccess (bazel ["shutdown"]) { Process.cwd = Just "../tutorial" } + assertSuccess (bazel ["run", "//tests/repl-flags:compiler_flags@repl", "--", "-ignore-dot-ghci", "-e", ":main"]) + + -- Test make variable expansion in `compiler_flags` and `repl_ghci_args`. + describe "make variables" $ do + it "compiler flags" $ do + assertSuccess (bazel ["run", "//tests/repl-make-variables:test-compiler-flags@repl", "--", "-ignore-dot-ghci", "-e", ":main"]) + it "indirect repl flags" $ do + assertSuccess (bazel ["run", "//tests/repl-make-variables:repl-indirect-flags", "--", "-ignore-dot-ghci", "-e", ":main"]) + it "direct repl flags" $ do + assertSuccess (bazel ["run", "//tests/repl-make-variables:repl-direct-flags", "--", "-ignore-dot-ghci", "-e", ":main"]) + + -- Test `repl_ghci_args` from toolchain and rule for REPL + it "repl flags" $ do + assertSuccess (bazel ["run", "//tests/repl-flags:repl_flags@repl", "--", "-ignore-dot-ghci", "-e", "foo"]) + + it "fails on multiple definitions" $ do + assertSuccess (bazel ["run", "//tests/repl-multiple-definition:repl", "--", "-ignore-dot-ghci", "-e", "final"]) + + describe "multi_repl" $ do + it "loads transitive library dependencies" $ do + let p' (stdout, _stderr) = lines stdout == ["tests/multi_repl/bc/src/BC/C.hs"] + outputSatisfy p' (bazel ["run", "//tests/multi_repl:c_only_repl", "--", "-ignore-dot-ghci", "-e", ":show targets"]) + it "loads transitive source dependencies" $ do + let p' (stdout, _stderr) = sort (lines stdout) == ["tests/multi_repl/a/src/A/A.hs","tests/multi_repl/bc/src/BC/B.hs","tests/multi_repl/bc/src/BC/C.hs"] + outputSatisfy p' (bazel ["run", "//tests/multi_repl:c_multi_repl", "--", "-ignore-dot-ghci", "-e", ":show targets"]) + it "loads core library dependencies" $ do + let p' (stdout, _stderr) = sort (lines stdout) == ["tests/multi_repl/core_package_dep/Lib.hs"] + outputSatisfy p' (bazel ["run", "//tests/multi_repl:core_package_dep", "--", "-ignore-dot-ghci", "-e", ":show targets"]) + it "doesn't allow to manually load modules" $ do + assertFailure (bazel ["run", "//tests/multi_repl:c_multi_repl", "--", "-ignore-dot-ghci", "-e", ":load BC.C", "-e", "c"]) + + describe "ghcide" $ do + it "loads RunTests.hs" $ + assertSuccess (Process.proc "./.ghcide" ["tests/RunTests.hs"]) + it "loads module with module dependency" $ + assertSuccess (Process.proc "./.ghcide" ["tests/binary-with-lib/Main.hs"]) + + describe "failures" $ do + -- Make sure not to include haskell_repl (@repl) or alias (-repl) targets + -- in the query. Those would not fail under bazel test. + all_failure_tests <- bazelQuery "kind('haskell_library|haskell_binary|haskell_test', //tests/failures/...) intersect attr('tags', 'manual', //tests/failures/...)" + + for_ all_failure_tests $ \test -> do + it test $ do + assertFailure (bazel ["build", test]) + + context "known issues" $ do + it "haskell_doc fails with plugins #1549" $ + -- https://github.com/tweag/rules_haskell/issues/1549 + assertFailure (bazel ["build", "//tests/haddock-with-plugin"]) + it "transitive re-exports do not work #1145" $ + -- https://github.com/tweag/rules_haskell/issues/1145 + assertFailure (bazel ["build", "//tests/package-reexport-transitive"]) + it "doctest failure with foreign import #1559" $ + -- https://github.com/tweag/rules_haskell/issues/1559 + assertFailure (bazel ["build", "//tests/haskell_doctest_ffi_1559:doctest-a"]) + + -- Test that the repl still works if we shadow some Prelude functions + it "repl name shadowing" $ do + let p (stdout, stderr) = not $ any ("error" `isInfixOf`) [stdout, stderr] + outputSatisfy p (bazel ["run", "//tests/repl-name-conflicts:lib@repl", "--", "-ignore-dot-ghci", "-e", "stdin"]) + + it "Repl works with remote_download_toplevel" $ do + let p (stdout, stderr) = not $ any ("error" `isInfixOf`) [stdout, stderr] + withSystemTempDirectory "bazel_disk_cache" $ \tmp_disk_cache -> do + assertSuccess $ bazel ["run", "//tests/multi_repl:c_only_repl", "--disk_cache=" <> tmp_disk_cache] + assertSuccess $ bazel ["clean"] + outputSatisfy p + (bazel ["run", "//tests/multi_repl:c_only_repl", "--disk_cache=" <> tmp_disk_cache, "--remote_download_toplevel"]) + + buildAndTest "../examples" + buildAndTest "../tutorial" -- * Bazel commands @@ -169,14 +165,23 @@ bazelQuery :: String -> SpecM a [String] bazelQuery q = lines <$> runIO (Process.readProcess "bazel" ["query", q] "") -- | Shutdown Bazel -shutdownBazel :: IO () -shutdownBazel = do +shutdownBazel :: String -> IO () +shutdownBazel path = do -- Related to https://github.com/tweag/rules_haskell/issues/2089 -- We experience intermittent "Exit Code: ExitFailure (-9)" errors. Shutdown -- Bazel when done executing tests for the workspace. - assertSuccess (bazel ["shutdown"]) + assertSuccess (bazel ["shutdown"]) { Process.cwd = Just path } pure () +buildAndTest :: HasCallStack => String -> SpecWith () +buildAndTest path = describe path $ afterAll_ (shutdownBazel path) $ do + it "bazel build" $ do + assertSuccess $ (bazel ["build", "//..."]) { Process.cwd = Just path } + it "bazel test" $ do + assertSuccess $ (bazel ["test", "//..."]) { Process.cwd = Just path } + +-- * Print Memory Hooks + -- | Print memory information before and after each test printMemoryHook :: IO () -> IO () printMemoryHook action = bracket_ From a4f0744e9bcb97efd13fecd7b5d73bc1803a3dab Mon Sep 17 00:00:00 2001 From: Chuck Grindel Date: Thu, 4 Jan 2024 09:22:05 -0700 Subject: [PATCH 29/37] Check RHT_PRINT_MEMORY env variable on whether to run hook. --- rules_haskell_tests/tests/RunTests.hs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/rules_haskell_tests/tests/RunTests.hs b/rules_haskell_tests/tests/RunTests.hs index b272af096..f7fda4474 100644 --- a/rules_haskell_tests/tests/RunTests.hs +++ b/rules_haskell_tests/tests/RunTests.hs @@ -183,11 +183,16 @@ buildAndTest path = describe path $ afterAll_ (shutdownBazel path) $ do -- * Print Memory Hooks -- | Print memory information before and after each test +-- Only perform the hook if RHT_PRINT_MEMORY is "true". printMemoryHook :: IO () -> IO () -printMemoryHook action = bracket_ - (printMemory "=== BEFORE ===") - (printMemory "=== AFTER ===") - action +printMemoryHook action = do + rhtPrintMem <- lookupEnv "RHT_PRINT_MEMORY" + case rhtPrintMem of + Just "true" -> bracket_ + (printMemory "=== BEFORE ===") + (printMemory "=== AFTER ===") + action + _ -> action -- | Print information about the current memory state to debug intermittent failures -- Related to https://github.com/tweag/rules_haskell/issues/2089 From 88f0931abef707c4f40945e2816555bd3bbce3f8 Mon Sep 17 00:00:00 2001 From: Chuck Grindel Date: Thu, 4 Jan 2024 09:30:29 -0700 Subject: [PATCH 30/37] Check for top existence. --- rules_haskell_tests/tests/RunTests.hs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/rules_haskell_tests/tests/RunTests.hs b/rules_haskell_tests/tests/RunTests.hs index f7fda4474..3fbe262b6 100644 --- a/rules_haskell_tests/tests/RunTests.hs +++ b/rules_haskell_tests/tests/RunTests.hs @@ -194,12 +194,25 @@ printMemoryHook action = do action _ -> action +topPath :: String +topPath = "/usr/bin/top" + -- | Print information about the current memory state to debug intermittent failures -- Related to https://github.com/tweag/rules_haskell/issues/2089 printMemory :: String -> IO () printMemory msg = do + -- Do not attempt to run top, if it does not exist. + (exitCode, _, _) <- Process.readProcessWithExitCode "test" [topPath] "" + case exitCode of + ExitSuccess -> _doPrintMemory msg + ExitFailure _ -> pure () + +-- | Print information about the current memory state to debug intermittent failures +-- Related to https://github.com/tweag/rules_haskell/issues/2089 +_doPrintMemory :: String -> IO () +_doPrintMemory msg = do putStrLn msg - (exitCode, stdOut, stdErr) <- Process.readProcessWithExitCode "/usr/bin/top" ["-l", "1", "-s", "0", "-o", "mem", "-n", "15"] "" + (exitCode, stdOut, stdErr) <- Process.readProcessWithExitCode topPath ["-l", "1", "-s", "0", "-o", "mem", "-n", "15"] "" case exitCode of ExitSuccess -> putStrLn stdOut ExitFailure _ -> putStrLn ("=== printMemory failed ===\n" ++ stdErr) From 9a645e548018ba7ae2a69325e9a39bb38f5b2cea Mon Sep 17 00:00:00 2001 From: Chuck Grindel Date: Thu, 4 Jan 2024 09:37:36 -0700 Subject: [PATCH 31/37] Execute CI with RHT_PRINT_MEMORY. --- .github/workflows/workflow.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/workflow.yaml b/.github/workflows/workflow.yaml index b1f2534f9..ed495aaaf 100644 --- a/.github/workflows/workflow.yaml +++ b/.github/workflows/workflow.yaml @@ -130,7 +130,8 @@ jobs: # Shutdown Bazel to free up memory # https://github.com/tweag/rules_haskell/issues/2089. bazel shutdown - ./bazel-ci-bin/tests/run-tests + # Execute the tests dumping out memory/process information before and after each test. + RHT_PRINT_MEMORY=true ./bazel-ci-bin/tests/run-tests bazel coverage //... test-bindist: From e0e93674e92d8a230510ec144ba6d3690e6e909b Mon Sep 17 00:00:00 2001 From: Chuck Grindel Date: Fri, 5 Jan 2024 06:25:41 -0700 Subject: [PATCH 32/37] Replace broken file existence test with doesFileExist. --- rules_haskell_tests/tests/RunTests.hs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/rules_haskell_tests/tests/RunTests.hs b/rules_haskell_tests/tests/RunTests.hs index 3fbe262b6..d357a9d2a 100644 --- a/rules_haskell_tests/tests/RunTests.hs +++ b/rules_haskell_tests/tests/RunTests.hs @@ -7,7 +7,7 @@ import Control.Exception.Safe (bracket_) import Data.Foldable (for_) import Data.List (isInfixOf, sort) import GHC.Stack (HasCallStack) -import System.Directory (copyFile) +import System.Directory (copyFile, doesFileExist) import System.FilePath (()) import System.Info (os) import System.IO.Temp (withSystemTempDirectory) @@ -202,10 +202,10 @@ topPath = "/usr/bin/top" printMemory :: String -> IO () printMemory msg = do -- Do not attempt to run top, if it does not exist. - (exitCode, _, _) <- Process.readProcessWithExitCode "test" [topPath] "" - case exitCode of - ExitSuccess -> _doPrintMemory msg - ExitFailure _ -> pure () + topExists <- doesFileExist topPath + if topExists + then _doPrintMemory msg + else pure() -- | Print information about the current memory state to debug intermittent failures -- Related to https://github.com/tweag/rules_haskell/issues/2089 From 4651a771421c8c211d104ac58664871e8bf890d8 Mon Sep 17 00:00:00 2001 From: Chuck Grindel Date: Fri, 5 Jan 2024 08:14:21 -0700 Subject: [PATCH 33/37] Add disk space stats. --- rules_haskell_tests/tests/RunTests.hs | 42 ++++++++++++++++++--------- 1 file changed, 29 insertions(+), 13 deletions(-) diff --git a/rules_haskell_tests/tests/RunTests.hs b/rules_haskell_tests/tests/RunTests.hs index d357a9d2a..b2e9079ea 100644 --- a/rules_haskell_tests/tests/RunTests.hs +++ b/rules_haskell_tests/tests/RunTests.hs @@ -24,7 +24,7 @@ import GenModule (a) import IntegrationTesting main :: IO () -main = hspec $ around_ printMemoryHook $ do +main = hspec $ around_ printStatsHook $ do describe "rules_haskell_tests" $ afterAll_ (shutdownBazel ".") $ do it "bazel test" $ do @@ -184,38 +184,54 @@ buildAndTest path = describe path $ afterAll_ (shutdownBazel path) $ do -- | Print memory information before and after each test -- Only perform the hook if RHT_PRINT_MEMORY is "true". -printMemoryHook :: IO () -> IO () -printMemoryHook action = do +printStatsHook :: IO () -> IO () +printStatsHook action = do rhtPrintMem <- lookupEnv "RHT_PRINT_MEMORY" case rhtPrintMem of Just "true" -> bracket_ - (printMemory "=== BEFORE ===") - (printMemory "=== AFTER ===") + (printStats "=== BEFORE ===") + (printStats "=== AFTER ===") action _ -> action topPath :: String topPath = "/usr/bin/top" --- | Print information about the current memory state to debug intermittent failures +dfPath :: String +dfPath = "/bin/df" + +-- | Print information about the computer state to debug intermittent failures -- Related to https://github.com/tweag/rules_haskell/issues/2089 -printMemory :: String -> IO () -printMemory msg = do +printStats :: String -> IO () +printStats msg = do -- Do not attempt to run top, if it does not exist. topExists <- doesFileExist topPath + dfExists <- doesFileExist dfPath + if topExists || dfExists then putStrLn msg else pure() if topExists - then _doPrintMemory msg + then _printMemory + else pure() + if dfExists + then _printDiskInfo else pure() -- | Print information about the current memory state to debug intermittent failures -- Related to https://github.com/tweag/rules_haskell/issues/2089 -_doPrintMemory :: String -> IO () -_doPrintMemory msg = do - putStrLn msg +_printMemory :: IO () +_printMemory = do (exitCode, stdOut, stdErr) <- Process.readProcessWithExitCode topPath ["-l", "1", "-s", "0", "-o", "mem", "-n", "15"] "" case exitCode of ExitSuccess -> putStrLn stdOut - ExitFailure _ -> putStrLn ("=== printMemory failed ===\n" ++ stdErr) + ExitFailure _ -> putStrLn ("=== _printMemory failed ===\n" ++ stdErr) + +-- | Print information about the disk drives to debug intermittent failures +-- Related to https://github.com/tweag/rules_haskell/issues/2089 +_printDiskInfo :: IO () +_printDiskInfo = do + (exitCode, stdOut, stdErr) <- Process.readProcessWithExitCode dfPath ["-H"] "" + case exitCode of + ExitSuccess -> putStrLn stdOut + ExitFailure _ -> putStrLn ("=== _printDiskInfo failed ===\n" ++ stdErr) -- Generated dependencies for testing the ghcide support _ghciIDE :: Int From f52da8079424d18a889694f4de26ade20937cd66 Mon Sep 17 00:00:00 2001 From: Chuck Grindel Date: Fri, 5 Jan 2024 08:58:24 -0700 Subject: [PATCH 34/37] Shutdown Bazel before running repl test. --- rules_haskell_tests/tests/RunTests.hs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rules_haskell_tests/tests/RunTests.hs b/rules_haskell_tests/tests/RunTests.hs index b2e9079ea..266143ab3 100644 --- a/rules_haskell_tests/tests/RunTests.hs +++ b/rules_haskell_tests/tests/RunTests.hs @@ -16,7 +16,7 @@ import System.Exit (ExitCode(..)) import qualified System.Process as Process import Test.Hspec.Core.Spec (SpecM, SpecWith) -import Test.Hspec (context, hspec, it, describe, runIO, around_, afterAll_) +import Test.Hspec (context, hspec, it, describe, runIO, around_, after_, afterAll_) import BinModule (b) import GenModule (a) @@ -142,7 +142,7 @@ main = hspec $ around_ printStatsHook $ do let p (stdout, stderr) = not $ any ("error" `isInfixOf`) [stdout, stderr] outputSatisfy p (bazel ["run", "//tests/repl-name-conflicts:lib@repl", "--", "-ignore-dot-ghci", "-e", "stdin"]) - it "Repl works with remote_download_toplevel" $ do + it "Repl works with remote_download_toplevel" $ after_ (shutdownBazel ".") $ do let p (stdout, stderr) = not $ any ("error" `isInfixOf`) [stdout, stderr] withSystemTempDirectory "bazel_disk_cache" $ \tmp_disk_cache -> do assertSuccess $ bazel ["run", "//tests/multi_repl:c_only_repl", "--disk_cache=" <> tmp_disk_cache] From 242a8a1f42898f017aa554a005291fb49414dab4 Mon Sep 17 00:00:00 2001 From: Chuck Grindel Date: Fri, 5 Jan 2024 09:29:17 -0700 Subject: [PATCH 35/37] Fix compilation error. --- rules_haskell_tests/tests/RunTests.hs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/rules_haskell_tests/tests/RunTests.hs b/rules_haskell_tests/tests/RunTests.hs index 266143ab3..af51a3d02 100644 --- a/rules_haskell_tests/tests/RunTests.hs +++ b/rules_haskell_tests/tests/RunTests.hs @@ -16,7 +16,7 @@ import System.Exit (ExitCode(..)) import qualified System.Process as Process import Test.Hspec.Core.Spec (SpecM, SpecWith) -import Test.Hspec (context, hspec, it, describe, runIO, around_, after_, afterAll_) +import Test.Hspec (context, hspec, it, describe, runIO, around_, afterAll_) import BinModule (b) import GenModule (a) @@ -142,7 +142,8 @@ main = hspec $ around_ printStatsHook $ do let p (stdout, stderr) = not $ any ("error" `isInfixOf`) [stdout, stderr] outputSatisfy p (bazel ["run", "//tests/repl-name-conflicts:lib@repl", "--", "-ignore-dot-ghci", "-e", "stdin"]) - it "Repl works with remote_download_toplevel" $ after_ (shutdownBazel ".") $ do + it "Repl works with remote_download_toplevel" $ do + shutdownBazel "." let p (stdout, stderr) = not $ any ("error" `isInfixOf`) [stdout, stderr] withSystemTempDirectory "bazel_disk_cache" $ \tmp_disk_cache -> do assertSuccess $ bazel ["run", "//tests/multi_repl:c_only_repl", "--disk_cache=" <> tmp_disk_cache] From 2a774a73fb2497ef0021870d7da68b5809fb415a Mon Sep 17 00:00:00 2001 From: Chuck Grindel Date: Fri, 5 Jan 2024 10:16:33 -0700 Subject: [PATCH 36/37] Add comment and fix formatting. --- rules_haskell_tests/tests/RunTests.hs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/rules_haskell_tests/tests/RunTests.hs b/rules_haskell_tests/tests/RunTests.hs index af51a3d02..349fde5ee 100644 --- a/rules_haskell_tests/tests/RunTests.hs +++ b/rules_haskell_tests/tests/RunTests.hs @@ -143,6 +143,9 @@ main = hspec $ around_ printStatsHook $ do outputSatisfy p (bazel ["run", "//tests/repl-name-conflicts:lib@repl", "--", "-ignore-dot-ghci", "-e", "stdin"]) it "Repl works with remote_download_toplevel" $ do + -- This test has a tendency to fail with Exit Code: ExitFailure (-9) on the GitHub macos + -- runners. To give it every chance to succeed, we shutdown Bazel to provide as much + -- memory as possible. shutdownBazel "." let p (stdout, stderr) = not $ any ("error" `isInfixOf`) [stdout, stderr] withSystemTempDirectory "bazel_disk_cache" $ \tmp_disk_cache -> do @@ -209,12 +212,8 @@ printStats msg = do topExists <- doesFileExist topPath dfExists <- doesFileExist dfPath if topExists || dfExists then putStrLn msg else pure() - if topExists - then _printMemory - else pure() - if dfExists - then _printDiskInfo - else pure() + if topExists then _printMemory else pure() + if dfExists then _printDiskInfo else pure() -- | Print information about the current memory state to debug intermittent failures -- Related to https://github.com/tweag/rules_haskell/issues/2089 From cc87cfa250ab8d8425c6a8128c9d81c5d7a3c0ec Mon Sep 17 00:00:00 2001 From: Chuck Grindel Date: Fri, 5 Jan 2024 15:20:57 -0700 Subject: [PATCH 37/37] Disable the test that is causing the OOM error. --- rules_haskell_tests/tests/RunTests.hs | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/rules_haskell_tests/tests/RunTests.hs b/rules_haskell_tests/tests/RunTests.hs index 349fde5ee..870da9b94 100644 --- a/rules_haskell_tests/tests/RunTests.hs +++ b/rules_haskell_tests/tests/RunTests.hs @@ -142,17 +142,15 @@ main = hspec $ around_ printStatsHook $ do let p (stdout, stderr) = not $ any ("error" `isInfixOf`) [stdout, stderr] outputSatisfy p (bazel ["run", "//tests/repl-name-conflicts:lib@repl", "--", "-ignore-dot-ghci", "-e", "stdin"]) - it "Repl works with remote_download_toplevel" $ do - -- This test has a tendency to fail with Exit Code: ExitFailure (-9) on the GitHub macos - -- runners. To give it every chance to succeed, we shutdown Bazel to provide as much - -- memory as possible. - shutdownBazel "." - let p (stdout, stderr) = not $ any ("error" `isInfixOf`) [stdout, stderr] - withSystemTempDirectory "bazel_disk_cache" $ \tmp_disk_cache -> do - assertSuccess $ bazel ["run", "//tests/multi_repl:c_only_repl", "--disk_cache=" <> tmp_disk_cache] - assertSuccess $ bazel ["clean"] - outputSatisfy p - (bazel ["run", "//tests/multi_repl:c_only_repl", "--disk_cache=" <> tmp_disk_cache, "--remote_download_toplevel"]) + -- GH2096: This test is flaky in CI using the MacOS GitHub runners. The flakiness is slowing + -- development on other features. Disable this test until a satisfying solution is found. + -- it "Repl works with remote_download_toplevel" $ do + -- let p (stdout, stderr) = not $ any ("error" `isInfixOf`) [stdout, stderr] + -- withSystemTempDirectory "bazel_disk_cache" $ \tmp_disk_cache -> do + -- assertSuccess $ bazel ["run", "//tests/multi_repl:c_only_repl", "--disk_cache=" <> tmp_disk_cache] + -- assertSuccess $ bazel ["clean"] + -- outputSatisfy p + -- (bazel ["run", "//tests/multi_repl:c_only_repl", "--disk_cache=" <> tmp_disk_cache, "--remote_download_toplevel"]) buildAndTest "../examples" buildAndTest "../tutorial"