diff options
author | Vincent Ambo <tazjin@google.com> | 2019-07-04T10·18+0100 |
---|---|---|
committer | Vincent Ambo <tazjin@google.com> | 2019-07-04T10·18+0100 |
commit | f723b8b878a3c4a4687b9e337a875500bebb39b1 (patch) | |
tree | e85204cf042c355e90cff61c111e7d8cd15df311 /third_party/bazel/rules_haskell/tests | |
parent | 2eb1dc26e42ffbdc168f05ef744bd4b4f3e4c36f (diff) |
feat(third_party/bazel): Check in rules_haskell from Tweag r/17
Diffstat (limited to 'third_party/bazel/rules_haskell/tests')
236 files changed, 4522 insertions, 0 deletions
diff --git a/third_party/bazel/rules_haskell/tests/BUILD.bazel b/third_party/bazel/rules_haskell/tests/BUILD.bazel new file mode 100644 index 000000000000..276db5546332 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/BUILD.bazel @@ -0,0 +1,322 @@ +load(":inline_tests.bzl", "sh_inline_test") +load("@bazel_tools//tools/build_rules:test_rules.bzl", "rule_test") +load("//tests:rule_test_exe.bzl", "rule_test_exe") +load( + "@io_tweag_rules_haskell//haskell:c2hs.bzl", + "c2hs_toolchain", +) +load( + "@io_tweag_rules_haskell//haskell:haskell.bzl", + "haskell_binary", + "haskell_doctest_toolchain", + "haskell_proto_toolchain", + "haskell_test", + "haskell_toolchain", +) +load( + "//:constants.bzl", + "test_ghc_version", +) + +package(default_testonly = 1) + +haskell_doctest_toolchain( + name = "doctest-toolchain", + doctest = "@hackage-doctest//:bin", + tags = ["requires_doctest"], +) + +# This toolchain is morally testonly. However, that would break our +# tests of haskell_library_rules: aspects of non-testonly +# proto_library rules (from com_google_protobuf) can't themselves be +# testonly. + +haskell_proto_toolchain( + name = "protobuf-toolchain", + testonly = 0, + plugin = "@hackage-proto-lens-protoc//:bin/proto-lens-protoc", + protoc = "@com_google_protobuf//:protoc", + tags = ["requires_hackage"], + deps = [ + "//tests/hackage:base", + "//tests/hackage:bytestring", + "//tests/hackage:containers", + "//tests/hackage:deepseq", + "//tests/hackage:mtl", + "//tests/hackage:text", + "@hackage//:data-default-class", + "@hackage//:lens-family", + "@hackage//:lens-family-core", + "@hackage//:lens-labels", + "@hackage//:proto-lens", + ], +) + +c2hs_toolchain( + name = "c2hs-toolchain", + c2hs = "@hackage-c2hs//:bin", + tags = ["requires_c2hs"], +) + +rule_test_exe( + name = "test-binary-simple", + size = "small", + generates = ["binary-simple"], + rule = "//tests/binary-simple", +) + +rule_test_exe( + name = "test-binary-custom-main", + size = "small", + generates = ["binary-custom-main"], + rule = "//tests/binary-custom-main", +) + +rule_test( + name = "test-binary-with-lib", + size = "small", + generates = ["binary-with-lib"], + rule = "//tests/binary-with-lib", +) + +rule_test( + name = "test-binary-with-prebuilt", + size = "small", + generates = ["binary-with-prebuilt"], + rule = "//tests/binary-with-prebuilt", + tags = ["requires_hackage"], +) + +rule_test( + name = "test-binary-with-main", + size = "small", + generates = ["binary-with-main"], + rule = "//tests/binary-with-main", +) + +rule_test( + name = "test-binary-with-sysdeps", + size = "small", + generates = ["binary-with-sysdeps"], + rule = "//tests/binary-with-sysdeps", + tags = ["requires_zlib"], +) + +sh_test( + name = "test-binary-with-data", + size = "small", + srcs = ["//tests/binary-with-data"], + args = ["$(location //tests/binary-with-data:bin1)"], + data = ["//tests/binary-with-data:bin1"], + tags = ["requires_hackage"], +) + +rule_test( + name = "test-library-deps", + size = "small", + generates = select({ + "@bazel_tools//src/conditions:darwin": [ + "libHStestsZSlibrary-depsZSlibrary-deps-ghc{}.dylib".format(test_ghc_version), + "libHStestsZSlibrary-depsZSlibrary-deps.a", + ], + "@bazel_tools//src/conditions:windows": [ + "libHStestsZSlibrary-depsZSlibrary-deps-ghc{}.dll".format(test_ghc_version), + "libHStestsZSlibrary-depsZSlibrary-deps.a", + ], + "//conditions:default": [ + "libHStestsZSlibrary-depsZSlibrary-deps-ghc{}.so".format(test_ghc_version), + "libHStestsZSlibrary-depsZSlibrary-deps.a", + ], + }), + rule = "//tests/library-deps", +) + +rule_test( + name = "test-hsc", + size = "small", + generates = ["hsc"], + rule = "//tests/hsc", +) + +rule_test( + name = "test-haddock", + size = "small", + generates = [ + "haddock/index", + "haddock/testsZShaddockZShaddock-lib-a", + "haddock/testsZShaddockZShaddock-lib-b", + "haddock/testsZShaddockZShaddock-lib-deep", + ], + rule = "//tests/haddock", + tags = ["requires_hackage"], +) + +rule_test( + name = "test-haskell_lint-library", + size = "small", + generates = [ + "lint-log-lib-b", + ], + rule = "//tests/haskell_lint:lint-lib-b", +) + +rule_test( + name = "test-haskell_lint-binary", + size = "small", + generates = [ + "lint-log-bin", + ], + rule = "//tests/haskell_lint:lint-bin", +) + +rule_test( + name = "test-haskell_doctest", + size = "small", + generates = [ + "doctest-log-doctest-lib-lib-b", + ], + rule = "//tests/haskell_doctest:doctest-lib", + tags = ["requires_doctest"], +) + +rule_test( + name = "test-haskell_test", + size = "small", + generates = ["haskell_test"], + rule = "//tests/haskell_test:haskell_test", +) + +rule_test( + name = "test-java_classpath", + size = "small", + generates = ["java_classpath"], + rule = "//tests/java_classpath", +) + +rule_test( + name = "test-cc_haskell_import-cc-link", + size = "small", + generates = ["cc-bin"], + rule = "//tests/cc_haskell_import:cc-bin", + tags = ["requires_threaded_rts"], +) + +sh_test( + name = "test-cc_haskell_import_python", + size = "small", + srcs = ["scripts/exec.sh"], + args = ["tests/cc_haskell_import/python_add_one"], + data = [ + "//tests/cc_haskell_import:python_add_one", + "@bazel_tools//tools/bash/runfiles", + ], + tags = ["requires_threaded_rts"], +) + +sh_inline_test( + name = "test-haskell_binary-with-link-flags", + size = "small", + args = ["$(location //tests/binary-with-link-flags:binary-with-link-flags)"], + data = ["//tests/binary-with-link-flags"], + script = """\ +set -e + +# Fails if executable was linked without -threaded flag. +$1 +RTS -N +""", +) + +rule_test( + name = "test-lhs", + size = "small", + generates = ["lhs-bin"], + rule = "//tests/lhs:lhs-bin", +) + +rule_test( + name = "test-hs-boot", + size = "small", + generates = ["hs-boot"], + rule = "//tests/hs-boot:hs-boot", +) + +rule_test( + name = "test-textual-hdrs", + size = "small", + generates = ["textual-hdrs"], + rule = "//tests/textual-hdrs:textual-hdrs", +) + +rule_test( + name = "test-two-libs", + size = "small", + generates = ["two-libs"], + rule = "//tests/two-libs:two-libs", +) + +genrule( + name = "run-bin-with-lib", + outs = ["dummy"], + cmd = """sh -c ' + set -e + $(location //tests/binary-with-lib:binary-with-lib) + touch $(location dummy) +'""", + tools = ["//tests/binary-with-lib"], +) + +rule_test( + name = "test-run-bin-with-lib", + size = "small", + generates = ["dummy"], + rule = "//tests:run-bin-with-lib", +) + +genrule( + name = "run-bin-with-lib-dynamic", + outs = ["dyn-dummy"], + cmd = """sh -c ' + set -e + $(location //tests/binary-with-lib-dynamic:binary-with-lib-dynamic) + touch $(location dyn-dummy) +'""", + tools = ["//tests/binary-with-lib-dynamic"], +) + +rule_test( + name = "test-run-bin-with-lib-dynamic", + size = "small", + generates = ["dyn-dummy"], + rule = "//tests:run-bin-with-lib-dynamic", +) + +genrule( + name = "run-bin-with-c-lib", + outs = ["c-dummy"], + cmd = """sh -c ' + set -e + $(location //tests/c-compiles) + touch $(location c-dummy) +'""", + tools = ["//tests/c-compiles"], +) + +rule_test( + name = "test-run-bin-with-c-lib", + size = "small", + generates = ["c-dummy"], + rule = "//tests:run-bin-with-c-lib", +) + +# This is the test runner +haskell_binary( + name = "run-tests", + srcs = ["RunTests.hs"], + tags = ["requires_hackage"], + deps = [ + "//tests/hackage:base", + "//tests/hackage:process", + "@hackage//:hspec", + "@hackage//:hspec-core", + ], +) diff --git a/third_party/bazel/rules_haskell/tests/RunTests.hs b/third_party/bazel/rules_haskell/tests/RunTests.hs new file mode 100644 index 000000000000..b6218bbcefc2 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/RunTests.hs @@ -0,0 +1,155 @@ +{-# OPTIONS -Wall #-} + +{-# LANGUAGE FlexibleContexts #-} +{-# LANGUAGE QuasiQuotes #-} + +import Data.Foldable (for_) +import Data.List (isInfixOf, sort) +import System.Exit (ExitCode(..)) + +import qualified System.Process as Process +import Test.Hspec.Core.Spec (SpecM) +import Test.Hspec (hspec, it, describe, runIO, shouldSatisfy, expectationFailure) + +main :: IO () +main = hspec $ do + it "bazel lint" $ do + assertSuccess (bazel ["run", "//:buildifier"]) + + it "bazel test" $ do + assertSuccess (bazel ["test", "//...", "--build_tests_only"]) + + it "haddock links" $ do + -- Test haddock links + -- All haddock tests are stored inside //tests/haddock + -- Temporaries files appears inside /doc-.... outputs and are ignored + + -- the copy / chmod is here to workaround the fact that + -- linkchecker is dropping privileges to "nobody" user if called + -- from root, which is the case on CI. + assertSuccess (safeShell + [ "bazel build --config=ci //tests/haddock/..." + , "pwd=$(pwd)" + , "cd $(mktemp -d)" + , "cp -r $pwd/bazel-ci-bin/tests/haddock ." + , "chmod -R o+r ." + , "linkchecker . --ignore-url=/doc-" + ]) + + it "bazel test prof" $ do + assertSuccess (bazel ["test", "-c", "dbg", "//...", "--build_tests_only"]) + + describe "repl" $ do + it "for libraries" $ do + assertSuccess (bazel ["run", "//tests/repl-targets:hs-lib@repl", "--", "-ignore-dot-ghci", "-e", "show (foo 10) ++ bar ++ baz ++ gen"]) + assertSuccess (bazel ["run", "//tests/repl-targets:hs-lib-bad@repl", "--", "-ignore-dot-ghci", "-e", "1 + 2"]) + + it "for binaries" $ do + assertSuccess (bazel ["run", "//tests/repl-targets:hs-bin@repl", "--", "-ignore-dot-ghci", "-e", ":main"]) + + assertSuccess (bazel ["run", "//tests/binary-indirect-cbits:binary-indirect-cbits@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 `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"]) + + 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 "startup script" $ do + assertSuccess (safeShell ["./tests/run-start-script.sh"]) + + describe "failures" $ do + all_failure_tests <- bazelQuery "kind(rule, //tests/failures/...) intersect attr('tags', 'manual', //tests/failures/...)" + + for_ all_failure_tests $ \test -> do + it test $ do + assertFailure (bazel ["build", "test"]) + + -- 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 "bazel test examples" $ do + assertSuccess (bazel ["test", "@io_tweag_rules_haskell_examples//..."]) + + it "bazel test tutorial" $ do + assertSuccess (bazel ["test", "@io_tweag_rules_haskell_tutorial//..."]) + +-- * Bazel commands + +-- | Returns a bazel command line suitable for CI +-- This should be called with the action as first item of the list. e.g 'bazel ["build", "//..."]'. +bazel :: [String] -> Process.CreateProcess +-- Note: --config=ci is intercalated between the action and the list +-- of arguments. It should appears after the action, but before any +-- @--@ following argument. +bazel (command:args) = Process.proc "bazel" (command:"--config=ci":args) +bazel [] = Process.proc "bazel" [] + +-- | Runs a bazel query and return the list of matching targets +bazelQuery :: String -> SpecM a [String] +bazelQuery q = lines <$> runIO (Process.readProcess "bazel" ["query", q] "") + +-- * Action helpers + +-- | Ensure that @(stdout, stderr)@ of the command satisfies a predicate +outputSatisfy + :: ((String, String) -> Bool) + -> Process.CreateProcess + -> IO () +outputSatisfy predicate cmd = do + (exitCode, stdout, stderr) <- Process.readCreateProcessWithExitCode cmd "" + + case exitCode of + ExitSuccess -> (stdout, stderr) `shouldSatisfy` predicate + ExitFailure _ -> expectationFailure (formatOutput exitCode stdout stderr) + +-- | The command must success +assertSuccess :: Process.CreateProcess -> IO () +assertSuccess = outputSatisfy (const True) + +-- | The command must fail +assertFailure :: Process.CreateProcess -> IO () +assertFailure cmd = do + (exitCode, stdout, stderr) <- Process.readCreateProcessWithExitCode cmd "" + + case exitCode of + ExitFailure _ -> pure () + ExitSuccess -> expectationFailure ("Unexpected success of a failure test with output:\n" ++ formatOutput exitCode stdout stderr) + +-- | Execute in a sub shell the list of command +-- This will fail if any of the command in the list fail +safeShell :: [String] -> Process.CreateProcess +safeShell l = Process.shell (unlines ("set -e":l)) + +-- * Formatting helpers + +formatOutput :: ExitCode -> String -> String -> String +formatOutput exitcode stdout stderr = + let + header = replicate 20 '-' + headerLarge = replicate 20 '=' + + in unlines [ + headerLarge + , "Exit Code: " <> show exitcode + , headerLarge + , "Standard Output" + , header + , stdout + , headerLarge + , "Error Output" + , header + , stderr + , header] diff --git a/third_party/bazel/rules_haskell/tests/binary-custom-main/BUILD.bazel b/third_party/bazel/rules_haskell/tests/binary-custom-main/BUILD.bazel new file mode 100644 index 000000000000..c749b85eaac4 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/binary-custom-main/BUILD.bazel @@ -0,0 +1,17 @@ +load( + "@io_tweag_rules_haskell//haskell:haskell.bzl", + "haskell_test", +) + +package(default_testonly = 1) + +haskell_test( + name = "binary-custom-main", + srcs = ["Main.hs"], + expected_covered_expressions_percentage = 50, + tags = [ + "coverage-compatible", + ], + visibility = ["//visibility:public"], + deps = ["//tests/hackage:base"], +) diff --git a/third_party/bazel/rules_haskell/tests/binary-custom-main/Main.hs b/third_party/bazel/rules_haskell/tests/binary-custom-main/Main.hs new file mode 100644 index 000000000000..c8dbf9fbdb9e --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/binary-custom-main/Main.hs @@ -0,0 +1,4 @@ +module Main (main) where + +main :: IO () +main = return () diff --git a/third_party/bazel/rules_haskell/tests/binary-dynamic/BUILD.bazel b/third_party/bazel/rules_haskell/tests/binary-dynamic/BUILD.bazel new file mode 100644 index 000000000000..765963f19fe0 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/binary-dynamic/BUILD.bazel @@ -0,0 +1,14 @@ +load( + "@io_tweag_rules_haskell//haskell:haskell.bzl", + "haskell_test", +) + +package(default_testonly = 1) + +haskell_test( + name = "binary-dynamic", + srcs = ["Main.hs"], + linkstatic = False, + visibility = ["//visibility:public"], + deps = ["//tests/hackage:base"], +) diff --git a/third_party/bazel/rules_haskell/tests/binary-dynamic/Main.hs b/third_party/bazel/rules_haskell/tests/binary-dynamic/Main.hs new file mode 100644 index 000000000000..2048dbdecd9a --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/binary-dynamic/Main.hs @@ -0,0 +1,3 @@ +module Main where + +main = putStrLn "hello world" diff --git a/third_party/bazel/rules_haskell/tests/binary-exe-path/BUILD.bazel b/third_party/bazel/rules_haskell/tests/binary-exe-path/BUILD.bazel new file mode 100644 index 000000000000..0cb617a50877 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/binary-exe-path/BUILD.bazel @@ -0,0 +1,13 @@ +load( + "@io_tweag_rules_haskell//haskell:haskell.bzl", + "haskell_test", +) + +package(default_testonly = 1) + +haskell_test( + name = "binary-exe-path", + srcs = ["Main.hs"], + visibility = ["//visibility:public"], + deps = ["//tests/hackage:base"], +) diff --git a/third_party/bazel/rules_haskell/tests/binary-exe-path/Main.hs b/third_party/bazel/rules_haskell/tests/binary-exe-path/Main.hs new file mode 100644 index 000000000000..6a02bb9fc8ec --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/binary-exe-path/Main.hs @@ -0,0 +1,5 @@ +module Main where + +import System.Environment + +main = getExecutablePath >>= putStrLn diff --git a/third_party/bazel/rules_haskell/tests/binary-indirect-cbits/BUILD.bazel b/third_party/bazel/rules_haskell/tests/binary-indirect-cbits/BUILD.bazel new file mode 100644 index 000000000000..6668f230e508 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/binary-indirect-cbits/BUILD.bazel @@ -0,0 +1,36 @@ +load( + "@io_tweag_rules_haskell//haskell:haskell.bzl", + "haskell_binary", + "haskell_library", +) + +haskell_binary( + name = "binary-indirect-cbits", + srcs = ["Main.hs"], + linkstatic = False, + visibility = ["//visibility:public"], + deps = [ + "//tests/hackage:base", + "//tests/library-with-cbits", + ], +) + +haskell_binary( + name = "binary-indirect-cbits-partially-static", + srcs = ["Main.hs"], + linkstatic = False, + deps = [ + "//tests/hackage:base", + "//tests/library-with-cbits:library-with-cbits-static", + ], +) + +haskell_binary( + name = "binary-indirect-cbits-fully-static", + srcs = ["Main.hs"], + linkstatic = True, + deps = [ + "//tests/hackage:base", + "//tests/library-with-cbits:library-with-cbits-static", + ], +) diff --git a/third_party/bazel/rules_haskell/tests/binary-indirect-cbits/Main.hs b/third_party/bazel/rules_haskell/tests/binary-indirect-cbits/Main.hs new file mode 100644 index 000000000000..c9d7037e23c2 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/binary-indirect-cbits/Main.hs @@ -0,0 +1,5 @@ +import AddOne + +main :: IO () +main = do + putStrLn $ show $ addOne 2 diff --git a/third_party/bazel/rules_haskell/tests/binary-indirect-cbits/Wrapper.hs b/third_party/bazel/rules_haskell/tests/binary-indirect-cbits/Wrapper.hs new file mode 100644 index 000000000000..00b6be28f405 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/binary-indirect-cbits/Wrapper.hs @@ -0,0 +1,5 @@ +module Wrapper + ( module AddOne + ) where + +import AddOne diff --git a/third_party/bazel/rules_haskell/tests/binary-indirect-cbits/Wrapper2.hs b/third_party/bazel/rules_haskell/tests/binary-indirect-cbits/Wrapper2.hs new file mode 100644 index 000000000000..a39233a84271 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/binary-indirect-cbits/Wrapper2.hs @@ -0,0 +1,9 @@ +module Wrapper2 + ( module AddOne + , addOne2 + ) where + +import AddOne +import qualified Wrapper + +addOne2 = Wrapper.addOne diff --git a/third_party/bazel/rules_haskell/tests/binary-linkstatic-flag/BUILD.bazel b/third_party/bazel/rules_haskell/tests/binary-linkstatic-flag/BUILD.bazel new file mode 100644 index 000000000000..4e8e7cfa6684 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/binary-linkstatic-flag/BUILD.bazel @@ -0,0 +1,118 @@ +load( + "@io_tweag_rules_haskell//haskell:haskell.bzl", + "haskell_library", + "haskell_test", +) +load("//tests:inline_tests.bzl", "sh_inline_test") + +# test whether `linkstatic` works as expected +package(default_testonly = 1) + +cc_library( + name = "c-lib", + srcs = ["c-lib.c"], +) + +haskell_library( + name = "HsLib", + srcs = ["HsLib.hs"], + deps = [ + "//tests/hackage:base", + ], +) + +haskell_test( + name = "binary-static", + srcs = ["Main.hs"], + linkstatic = True, + deps = [ + ":HsLib", + ":c-lib", + "//tests/hackage:base", + ], +) + +haskell_test( + name = "binary-dynamic", + srcs = ["Main.hs"], + linkstatic = False, + deps = [ + ":HsLib", + ":c-lib", + "//tests/hackage:base", + ], +) + +config_setting( + name = "debug_build", + values = { + "compilation_mode": "dbg", + }, +) + +# Ensure that linkstatic=True only links to static library targets. +sh_inline_test( + name = "test-binary-static-symbols", + size = "small", + args = [ + "$(rootpath :binary-static)", + ], + data = [ + ":binary-static", + ], + script = """ + set -eo pipefail + binary="$1" + # Symbols are prefixed with underscore on MacOS but not on Linux. + if nm -u "$binary" | grep -q "\<_\?value"; then + echo "C library dependency not linked statically: ${binary}" + exit 1 + fi + if nm -u "$binary" | grep -q HsLib_value_closure; then + echo "Haskell library dependency not linked statically ${binary}" + exit 1 + fi + """, +) + +# Ensure that linkstatic=False only links to dynamic library targets. +sh_inline_test( + name = "test-binary-dynamic-symbols", + size = "small", + args = [ + "$(rootpath :binary-dynamic)", + ] + select({ + ":debug_build": ["dbg"], + "//conditions:default": ["rls"], + }), + data = [ + ":binary-dynamic", + ], + script = """ + set -eo pipefail + binary="$1" + mode="$2" + if [[ $mode = dbg ]]; then + # Skip test in debug builds. Debug mode forces static linking. + exit 0 + fi + # Symbols are prefixed with underscore on MacOS but not on Linux. + if ! nm -u "$binary" | grep -q "\<_\?value"; then + echo "C library dependency not linked dynamically" + exit 1 + fi + if ! nm -u "$binary" | grep -q HsLib_value_closure; then + echo "Haskell library dependency not linked dynamically" + exit 1 + fi + """, +) + +test_suite( + name = "binary-linkstatic-flag", + tests = [ + ":test-binary-dynamic-symbols", + ":test-binary-static-symbols", + ], + visibility = ["//visibility:public"], +) diff --git a/third_party/bazel/rules_haskell/tests/binary-linkstatic-flag/HsLib.hs b/third_party/bazel/rules_haskell/tests/binary-linkstatic-flag/HsLib.hs new file mode 100644 index 000000000000..68271826d7ee --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/binary-linkstatic-flag/HsLib.hs @@ -0,0 +1,4 @@ +module HsLib (value) where + +value :: Int +value = 13 diff --git a/third_party/bazel/rules_haskell/tests/binary-linkstatic-flag/Main.hs b/third_party/bazel/rules_haskell/tests/binary-linkstatic-flag/Main.hs new file mode 100644 index 000000000000..7836c2220277 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/binary-linkstatic-flag/Main.hs @@ -0,0 +1,9 @@ +{-# LANGUAGE ForeignFunctionInterface #-} + +module Main (main) where + +import qualified HsLib + +foreign import ccall "value" value :: Int + +main = print $ HsLib.value + value diff --git a/third_party/bazel/rules_haskell/tests/binary-linkstatic-flag/c-lib.c b/third_party/bazel/rules_haskell/tests/binary-linkstatic-flag/c-lib.c new file mode 100644 index 000000000000..9a1e526017ec --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/binary-linkstatic-flag/c-lib.c @@ -0,0 +1 @@ +int value() { return 29; } diff --git a/third_party/bazel/rules_haskell/tests/binary-simple/BUILD.bazel b/third_party/bazel/rules_haskell/tests/binary-simple/BUILD.bazel new file mode 100644 index 000000000000..d44d395fb8c7 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/binary-simple/BUILD.bazel @@ -0,0 +1,15 @@ +load( + "@io_tweag_rules_haskell//haskell:haskell.bzl", + "haskell_test", +) + +package(default_testonly = 1) + +haskell_test( + name = "binary-simple", + srcs = ["Main.hs"], + expected_covered_expressions_percentage = 100, + tags = ["coverage-compatible"], + visibility = ["//visibility:public"], + deps = ["//tests/hackage:base"], +) diff --git a/third_party/bazel/rules_haskell/tests/binary-simple/Main.hs b/third_party/bazel/rules_haskell/tests/binary-simple/Main.hs new file mode 100644 index 000000000000..2048dbdecd9a --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/binary-simple/Main.hs @@ -0,0 +1,3 @@ +module Main where + +main = putStrLn "hello world" diff --git a/third_party/bazel/rules_haskell/tests/binary-with-compiler-flags/BUILD.bazel b/third_party/bazel/rules_haskell/tests/binary-with-compiler-flags/BUILD.bazel new file mode 100644 index 000000000000..727d8447ab4b --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/binary-with-compiler-flags/BUILD.bazel @@ -0,0 +1,18 @@ +load( + "@io_tweag_rules_haskell//haskell:haskell.bzl", + "haskell_test", +) + +package(default_testonly = 1) + +haskell_test( + name = "binary-with-compiler-flags", + srcs = ["Main.hs"], + # Flags that require -threaded, which we should get from the toolchain's + # compiler_flags. Include spaces to validate proper quoting: + compiler_flags = [ + "-with-rtsopts=-N2 -qg -I0 -n2m -A128m", + "-XLambdaCase", + ], + deps = ["//tests/hackage:base"], +) diff --git a/third_party/bazel/rules_haskell/tests/binary-with-compiler-flags/Main.hs b/third_party/bazel/rules_haskell/tests/binary-with-compiler-flags/Main.hs new file mode 100644 index 000000000000..b95db17f76da --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/binary-with-compiler-flags/Main.hs @@ -0,0 +1,13 @@ +-- Expects to pull -XStandaloneDeriving from the default compiler flags. +module Main (main) where + +data Foo = Foo +deriving instance Show Foo + +-- Expects -XLambdaCase to be passed via the 'compiler_flags' rule attribute. +dummyId :: Foo -> Foo +dummyId = \case + Foo -> Foo + +main :: IO () +main = print $ dummyId Foo diff --git a/third_party/bazel/rules_haskell/tests/binary-with-data/BUILD.bazel b/third_party/bazel/rules_haskell/tests/binary-with-data/BUILD.bazel new file mode 100644 index 000000000000..200498f64018 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/binary-with-data/BUILD.bazel @@ -0,0 +1,31 @@ +load( + "@io_tweag_rules_haskell//haskell:haskell.bzl", + "haskell_test", +) + +package(default_testonly = 1) + +# XXX: on Windows those tests need `--experimental_enable_runfiles` to succeed +# XXX: see: https://github.com/tweag/rules_haskell/issues/647#issuecomment-459001362 + +haskell_test( + name = "bin1", + srcs = ["bin1.hs"], + # Regular file input: + data = ["bin1-input"], + visibility = ["//visibility:public"], + deps = ["//tests/hackage:base"], +) + +haskell_test( + name = "binary-with-data", + srcs = ["bin2.hs"], + args = ["$(location :bin1)"], + data = [":bin1"], + tags = ["requires_hackage"], + visibility = ["//visibility:public"], + deps = [ + "//tests/hackage:base", + "//tests/hackage:process", + ], +) diff --git a/third_party/bazel/rules_haskell/tests/binary-with-data/bin1-input b/third_party/bazel/rules_haskell/tests/binary-with-data/bin1-input new file mode 100644 index 000000000000..12f00e90b6ef --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/binary-with-data/bin1-input @@ -0,0 +1 @@ +contents diff --git a/third_party/bazel/rules_haskell/tests/binary-with-data/bin1.hs b/third_party/bazel/rules_haskell/tests/binary-with-data/bin1.hs new file mode 100644 index 000000000000..309f6ecd5641 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/binary-with-data/bin1.hs @@ -0,0 +1,9 @@ +module Main where + +import Control.Monad (unless) + +main :: IO () +main = do + contents <- readFile "tests/binary-with-data/bin1-input" + unless (contents == "contents\n") + $ error $ "Incorrect input; got " ++ show contents diff --git a/third_party/bazel/rules_haskell/tests/binary-with-data/bin2.hs b/third_party/bazel/rules_haskell/tests/binary-with-data/bin2.hs new file mode 100644 index 000000000000..31d2404a6a9d --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/binary-with-data/bin2.hs @@ -0,0 +1,8 @@ +module Main where + +import System.Process (callProcess) +import System.Environment (getArgs) + +main = do + [arg] <- getArgs + callProcess arg [] diff --git a/third_party/bazel/rules_haskell/tests/binary-with-import/BUILD.bazel b/third_party/bazel/rules_haskell/tests/binary-with-import/BUILD.bazel new file mode 100644 index 000000000000..3b920d37c41a --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/binary-with-import/BUILD.bazel @@ -0,0 +1,26 @@ +load( + "@io_tweag_rules_haskell//haskell:haskell.bzl", + "haskell_library", + "haskell_test", +) + +package(default_testonly = 1) + +haskell_library( + name = "lib", + srcs = ["src/Lib.hs"], + deps = [ + "//tests/hackage:base", + "//tests/hackage:transformers", + ], +) + +haskell_test( + name = "binary-with-import", + srcs = ["Main.hs"], + visibility = ["//visibility:public"], + deps = [ + ":lib", + "//tests/hackage:base", + ], +) diff --git a/third_party/bazel/rules_haskell/tests/binary-with-import/Main.hs b/third_party/bazel/rules_haskell/tests/binary-with-import/Main.hs new file mode 100644 index 000000000000..1bded5e8e55b --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/binary-with-import/Main.hs @@ -0,0 +1,6 @@ +module Main where + +import Lib (printValue) + +main :: IO () +main = printValue diff --git a/third_party/bazel/rules_haskell/tests/binary-with-import/src/Lib.hs b/third_party/bazel/rules_haskell/tests/binary-with-import/src/Lib.hs new file mode 100644 index 000000000000..d384e73e6337 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/binary-with-import/src/Lib.hs @@ -0,0 +1,13 @@ +module Lib (printValue) where + +import Control.Monad (void) +import Control.Monad.Trans.Class (lift) +import Control.Monad.Trans.Except (ExceptT, runExceptT) + +getValue :: Monad m => ExceptT e m Int +getValue = pure 42 + +printValue :: IO () +printValue = void $ runExceptT $ do + value <- getValue + lift $ print value diff --git a/third_party/bazel/rules_haskell/tests/binary-with-indirect-sysdeps/BUILD.bazel b/third_party/bazel/rules_haskell/tests/binary-with-indirect-sysdeps/BUILD.bazel new file mode 100644 index 000000000000..195288882b1a --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/binary-with-indirect-sysdeps/BUILD.bazel @@ -0,0 +1,27 @@ +load( + "@io_tweag_rules_haskell//haskell:haskell.bzl", + "haskell_library", + "haskell_test", +) + +package(default_testonly = 1) + +haskell_library( + name = "hs-lib", + srcs = ["HsLib.hs"], + tags = ["requires_zlib"], + deps = [ + "//tests/hackage:base", + "@zlib.dev//:zlib", + ], +) + +haskell_test( + name = "binary-with-indirect-sysdeps", + srcs = ["Main.hs"], + tags = ["requires_zlib"], + deps = [ + ":hs-lib", + "//tests/hackage:base", + ], +) diff --git a/third_party/bazel/rules_haskell/tests/binary-with-indirect-sysdeps/HsLib.hs b/third_party/bazel/rules_haskell/tests/binary-with-indirect-sysdeps/HsLib.hs new file mode 100644 index 000000000000..1077606e31e2 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/binary-with-indirect-sysdeps/HsLib.hs @@ -0,0 +1,8 @@ +module HsLib where + +import Foreign.Ptr +import Foreign.C.Types + +foreign import ccall crc32 :: CLong -> Ptr () -> CInt -> IO () + +test = crc32 0 nullPtr 0 diff --git a/third_party/bazel/rules_haskell/tests/binary-with-indirect-sysdeps/Main.hs b/third_party/bazel/rules_haskell/tests/binary-with-indirect-sysdeps/Main.hs new file mode 100644 index 000000000000..9c92b34c8a38 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/binary-with-indirect-sysdeps/Main.hs @@ -0,0 +1,5 @@ +module Main where + +import HsLib (test) + +main = test diff --git a/third_party/bazel/rules_haskell/tests/binary-with-lib-dynamic/BUILD.bazel b/third_party/bazel/rules_haskell/tests/binary-with-lib-dynamic/BUILD.bazel new file mode 100644 index 000000000000..6be2db88b732 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/binary-with-lib-dynamic/BUILD.bazel @@ -0,0 +1,25 @@ +load( + "@io_tweag_rules_haskell//haskell:haskell.bzl", + "haskell_library", + "haskell_test", +) + +package(default_testonly = 1) + +haskell_library( + name = "lib", + srcs = glob(["src/*.hs"]), + linkstatic = False, + src_strip_prefix = "src", +) + +haskell_test( + name = "binary-with-lib-dynamic", + srcs = ["Main.hs"], + linkstatic = False, + visibility = ["//visibility:public"], + deps = [ + ":lib", + "//tests/hackage:base", + ], +) diff --git a/third_party/bazel/rules_haskell/tests/binary-with-lib-dynamic/Main.hs b/third_party/bazel/rules_haskell/tests/binary-with-lib-dynamic/Main.hs new file mode 100644 index 000000000000..d88f7c93d66a --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/binary-with-lib-dynamic/Main.hs @@ -0,0 +1,7 @@ +module Main where + +import Control.Monad (unless) +import Lib (value) + +main = unless (value == 42) + $ error $ "Incorrect lib value. Got " <> show value diff --git a/third_party/bazel/rules_haskell/tests/binary-with-lib-dynamic/src/Lib.hs b/third_party/bazel/rules_haskell/tests/binary-with-lib-dynamic/src/Lib.hs new file mode 100644 index 000000000000..0521761f3572 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/binary-with-lib-dynamic/src/Lib.hs @@ -0,0 +1,5 @@ +{-# LANGUAGE NoImplicitPrelude #-} + +module Lib (value) where + +value = 42 diff --git a/third_party/bazel/rules_haskell/tests/binary-with-lib/BUILD.bazel b/third_party/bazel/rules_haskell/tests/binary-with-lib/BUILD.bazel new file mode 100644 index 000000000000..196d551305a9 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/binary-with-lib/BUILD.bazel @@ -0,0 +1,27 @@ +load( + "@io_tweag_rules_haskell//haskell:haskell.bzl", + "haskell_library", + "haskell_test", +) + +package(default_testonly = 1) + +haskell_library( + name = "lib", + srcs = glob(["src/*.hs"]), + src_strip_prefix = "src", + deps = [ + "//tests/hackage:template-haskell", + ], +) + +haskell_test( + name = "binary-with-lib", + srcs = ["Main.hs"], + visibility = ["//visibility:public"], + deps = [ + ":lib", + "//tests/hackage:base", + "//tests/hackage:template-haskell", + ], +) diff --git a/third_party/bazel/rules_haskell/tests/binary-with-lib/Main.hs b/third_party/bazel/rules_haskell/tests/binary-with-lib/Main.hs new file mode 100644 index 000000000000..19ad3dd58ea0 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/binary-with-lib/Main.hs @@ -0,0 +1,11 @@ +{-# LANGUAGE TemplateHaskell #-} +module Main where + +import Control.Monad (unless) +import Lib (value) +import Language.Haskell.TH + +val = $(value) + +main = unless (val == 42) + $ error $ "Incorrect lib value. Got " <> show val diff --git a/third_party/bazel/rules_haskell/tests/binary-with-lib/src/Lib.hs b/third_party/bazel/rules_haskell/tests/binary-with-lib/src/Lib.hs new file mode 100644 index 000000000000..e78d2ef77f1b --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/binary-with-lib/src/Lib.hs @@ -0,0 +1,8 @@ +{-# LANGUAGE NoImplicitPrelude #-} +{-# LANGUAGE TemplateHaskell #-} + +module Lib (value) where + +import Language.Haskell.TH + +value = [|42|] diff --git a/third_party/bazel/rules_haskell/tests/binary-with-link-flags/BUILD.bazel b/third_party/bazel/rules_haskell/tests/binary-with-link-flags/BUILD.bazel new file mode 100644 index 000000000000..cf2aba515b69 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/binary-with-link-flags/BUILD.bazel @@ -0,0 +1,17 @@ +load( + "@io_tweag_rules_haskell//haskell:haskell.bzl", + "haskell_test", +) + +package( + default_testonly = 1, + default_visibility = ["//visibility:public"], +) + +haskell_test( + name = "binary-with-link-flags", + srcs = ["Main.hs"], + compiler_flags = ["-threaded"], + visibility = ["//visibility:public"], + deps = ["//tests/hackage:base"], +) diff --git a/third_party/bazel/rules_haskell/tests/binary-with-link-flags/Main.hs b/third_party/bazel/rules_haskell/tests/binary-with-link-flags/Main.hs new file mode 100644 index 000000000000..de106fe48f9a --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/binary-with-link-flags/Main.hs @@ -0,0 +1,3 @@ +module Main where + +main = return () diff --git a/third_party/bazel/rules_haskell/tests/binary-with-main/BUILD.bazel b/third_party/bazel/rules_haskell/tests/binary-with-main/BUILD.bazel new file mode 100644 index 000000000000..e1243260c2ab --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/binary-with-main/BUILD.bazel @@ -0,0 +1,14 @@ +load( + "@io_tweag_rules_haskell//haskell:haskell.bzl", + "haskell_test", +) + +package(default_testonly = 1) + +haskell_test( + name = "binary-with-main", + srcs = ["MainIsHere.hs"], + main_function = "MainIsHere.this", + visibility = ["//visibility:public"], + deps = ["//tests/hackage:base"], +) diff --git a/third_party/bazel/rules_haskell/tests/binary-with-main/MainIsHere.hs b/third_party/bazel/rules_haskell/tests/binary-with-main/MainIsHere.hs new file mode 100644 index 000000000000..5e8d38ba70df --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/binary-with-main/MainIsHere.hs @@ -0,0 +1,4 @@ +module MainIsHere (this) where + +this :: IO () +this = return () diff --git a/third_party/bazel/rules_haskell/tests/binary-with-plugin/BUILD.bazel b/third_party/bazel/rules_haskell/tests/binary-with-plugin/BUILD.bazel new file mode 100644 index 000000000000..f3a8e3f4d689 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/binary-with-plugin/BUILD.bazel @@ -0,0 +1,53 @@ +load( + "@io_tweag_rules_haskell//haskell:haskell.bzl", + "ghc_plugin", + "haskell_library", + "haskell_test", + "haskell_toolchain_library", +) + +package(default_testonly = 1) + +config_setting( + name = "debug_build", + values = { + "compilation_mode": "dbg", + }, +) + +haskell_toolchain_library(name = "base") + +haskell_toolchain_library(name = "ghc") + +haskell_toolchain_library(name = "process") + +haskell_library( + name = "plugin-lib", + srcs = ["Plugin.hs"], + deps = [ + ":base", + ":ghc", + ":process", + ], +) + +ghc_plugin( + name = "plugin", + args = ["$(location //tests/binary-simple)"], + module = "Plugin", + tools = ["//tests/binary-simple"], + deps = [":plugin-lib"], +) + +haskell_test( + name = "binary-with-plugin", + srcs = ["Main.hs"], + plugins = select({ + # XXX If profiling is enabled, ignore the plugin because of + # https://gitlab.haskell.org/ghc/ghc/issues/14335. + ":debug_build": [], + "//conditions:default": [":plugin"], + }), + visibility = ["//visibility:public"], + deps = [":base"], +) diff --git a/third_party/bazel/rules_haskell/tests/binary-with-plugin/Main.hs b/third_party/bazel/rules_haskell/tests/binary-with-plugin/Main.hs new file mode 100644 index 000000000000..2048dbdecd9a --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/binary-with-plugin/Main.hs @@ -0,0 +1,3 @@ +module Main where + +main = putStrLn "hello world" diff --git a/third_party/bazel/rules_haskell/tests/binary-with-plugin/Plugin.hs b/third_party/bazel/rules_haskell/tests/binary-with-plugin/Plugin.hs new file mode 100644 index 000000000000..3827bb799215 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/binary-with-plugin/Plugin.hs @@ -0,0 +1,15 @@ +module Plugin (plugin) where + +import Control.Monad (when) +import GhcPlugins +import System.Process (readProcess) + +plugin :: Plugin +plugin = defaultPlugin { installCoreToDos = install } + +install :: [CommandLineOption] -> [CoreToDo] -> CoreM [CoreToDo] +install [arg] todo = do + when ('$' `elem` arg) $ + fail "Make variable not expanded." + _ <- liftIO $ readProcess arg [] "" + return todo diff --git a/third_party/bazel/rules_haskell/tests/binary-with-prebuilt/BUILD.bazel b/third_party/bazel/rules_haskell/tests/binary-with-prebuilt/BUILD.bazel new file mode 100644 index 000000000000..99a22ae9991f --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/binary-with-prebuilt/BUILD.bazel @@ -0,0 +1,19 @@ +load( + "@io_tweag_rules_haskell//haskell:haskell.bzl", + "haskell_test", +) + +package(default_testonly = 1) + +haskell_test( + name = "binary-with-prebuilt", + srcs = ["Main.hs"], + tags = ["requires_hackage"], + visibility = ["//visibility:public"], + deps = [ + "//tests/hackage:base", + "//tests/hackage:template-haskell", + "@hackage//:streaming", + "@hackage//:void", + ], +) diff --git a/third_party/bazel/rules_haskell/tests/binary-with-prebuilt/Main.hs b/third_party/bazel/rules_haskell/tests/binary-with-prebuilt/Main.hs new file mode 100644 index 000000000000..aa3b1b40ee8a --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/binary-with-prebuilt/Main.hs @@ -0,0 +1,6 @@ +module Main where + +import Data.List () +import Language.Haskell.TH () + +main = return () diff --git a/third_party/bazel/rules_haskell/tests/binary-with-sysdeps/BUILD.bazel b/third_party/bazel/rules_haskell/tests/binary-with-sysdeps/BUILD.bazel new file mode 100644 index 000000000000..769ecf31a38c --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/binary-with-sysdeps/BUILD.bazel @@ -0,0 +1,17 @@ +load( + "@io_tweag_rules_haskell//haskell:haskell.bzl", + "haskell_test", +) + +package(default_testonly = 1) + +haskell_test( + name = "binary-with-sysdeps", + srcs = ["Main.hs"], + tags = ["requires_zlib"], + visibility = ["//visibility:public"], + deps = [ + "//tests/hackage:base", + "@zlib", + ], +) diff --git a/third_party/bazel/rules_haskell/tests/binary-with-sysdeps/Main.hs b/third_party/bazel/rules_haskell/tests/binary-with-sysdeps/Main.hs new file mode 100644 index 000000000000..bf8da504168a --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/binary-with-sysdeps/Main.hs @@ -0,0 +1,8 @@ +module Main where + +import Foreign.Ptr +import Foreign.C.Types + +foreign import ccall crc32 :: CLong -> Ptr () -> CInt -> IO () + +main = crc32 0 nullPtr 0 diff --git a/third_party/bazel/rules_haskell/tests/c-compiles-still/BUILD.bazel b/third_party/bazel/rules_haskell/tests/c-compiles-still/BUILD.bazel new file mode 100644 index 000000000000..314b895b6be4 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/c-compiles-still/BUILD.bazel @@ -0,0 +1,15 @@ +load( + "@io_tweag_rules_haskell//haskell:haskell.bzl", + "haskell_library", +) + +package(default_testonly = 1) + +haskell_library( + name = "foo", + srcs = ["Foo.hs"], + deps = [ + "//tests/data:ourclibrary", + "//tests/hackage:base", + ], +) diff --git a/third_party/bazel/rules_haskell/tests/c-compiles-still/Foo.hs b/third_party/bazel/rules_haskell/tests/c-compiles-still/Foo.hs new file mode 100644 index 000000000000..f325b2efcfbb --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/c-compiles-still/Foo.hs @@ -0,0 +1,4 @@ +module Foo (foo) where + +foo :: Int +foo = 5 diff --git a/third_party/bazel/rules_haskell/tests/c-compiles/BUILD.bazel b/third_party/bazel/rules_haskell/tests/c-compiles/BUILD.bazel new file mode 100644 index 000000000000..b5256bfb18d0 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/c-compiles/BUILD.bazel @@ -0,0 +1,26 @@ +load( + "@io_tweag_rules_haskell//haskell:haskell.bzl", + "haskell_library", + "haskell_test", +) + +package(default_testonly = 1) + +haskell_library( + name = "hs-lib", + srcs = ["Lib.hs"], + deps = [ + "//tests/data:ourclibrary", + "//tests/hackage:base", + ], +) + +haskell_test( + name = "c-compiles", + srcs = ["Main.hs"], + visibility = ["//visibility:public"], + deps = [ + ":hs-lib", + "//tests/hackage:base", + ], +) diff --git a/third_party/bazel/rules_haskell/tests/c-compiles/Lib.hs b/third_party/bazel/rules_haskell/tests/c-compiles/Lib.hs new file mode 100644 index 000000000000..6ebec6b460ce --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/c-compiles/Lib.hs @@ -0,0 +1,10 @@ +{-# LANGUAGE ForeignFunctionInterface #-} +module Lib (ten) where + +import Foreign.C.Types (CInt(..)) + +foreign import ccall "c_add_one" + c_add_one :: CInt -> CInt + +ten :: Int +ten = fromIntegral (c_add_one 9) diff --git a/third_party/bazel/rules_haskell/tests/c-compiles/Main.hs b/third_party/bazel/rules_haskell/tests/c-compiles/Main.hs new file mode 100644 index 000000000000..5fc7b957c84b --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/c-compiles/Main.hs @@ -0,0 +1,8 @@ +module Main (main) where + +import Control.Monad (unless) +import Lib (ten) + +main :: IO () +main = unless (ten == 10) + $ error $ "Incorrect lib value. Got " <> show ten diff --git a/third_party/bazel/rules_haskell/tests/c-compiles/c-compiles.c b/third_party/bazel/rules_haskell/tests/c-compiles/c-compiles.c new file mode 100644 index 000000000000..2d3a4d742c30 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/c-compiles/c-compiles.c @@ -0,0 +1 @@ +int add_five(int x) { return x + 5; } diff --git a/third_party/bazel/rules_haskell/tests/c2hs/BUILD.bazel b/third_party/bazel/rules_haskell/tests/c2hs/BUILD.bazel new file mode 100644 index 000000000000..a343c55f57fc --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/c2hs/BUILD.bazel @@ -0,0 +1,36 @@ +load("@io_tweag_rules_haskell//haskell:c2hs.bzl", "c2hs_library") +load( + "@io_tweag_rules_haskell//haskell:haskell.bzl", + "haskell_library", +) + +package(default_testonly = 1) + +c2hs_library( + name = "foo", + srcs = ["src/Foo/Foo.chs"], + src_strip_prefix = "src", + tags = [ + "requires_c2hs", + "requires_zlib", + ], + deps = ["@zlib.dev//:zlib"], +) + +c2hs_library( + name = "bar", + srcs = ["Bar.chs"], + tags = ["requires_c2hs"], + deps = [":foo"], +) + +haskell_library( + name = "c2hs", + srcs = [ + ":bar", + ":foo", + "@c2hs_repo//:baz", + ], + tags = ["requires_c2hs"], + deps = ["//tests/hackage:base"], +) diff --git a/third_party/bazel/rules_haskell/tests/c2hs/Bar.chs b/third_party/bazel/rules_haskell/tests/c2hs/Bar.chs new file mode 100644 index 000000000000..1de32c1ccb3b --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/c2hs/Bar.chs @@ -0,0 +1,6 @@ +module Bar (bar) where + +{#import Foo.Foo#} + +bar :: Int +bar = 6 diff --git a/third_party/bazel/rules_haskell/tests/c2hs/repo/BUILD.bazel b/third_party/bazel/rules_haskell/tests/c2hs/repo/BUILD.bazel new file mode 100644 index 000000000000..4f1d15c09a6f --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/c2hs/repo/BUILD.bazel @@ -0,0 +1,10 @@ +load("@io_tweag_rules_haskell//haskell:c2hs.bzl", "c2hs_library") + +package(default_testonly = 1) + +c2hs_library( + name = "baz", + srcs = ["Baz.chs"], + visibility = ["//visibility:public"], + deps = ["@zlib.dev//:zlib"], +) diff --git a/third_party/bazel/rules_haskell/tests/c2hs/repo/Baz.chs b/third_party/bazel/rules_haskell/tests/c2hs/repo/Baz.chs new file mode 100644 index 000000000000..b6d74dfc4ea8 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/c2hs/repo/Baz.chs @@ -0,0 +1,6 @@ +module Baz (baz) where + +#include <zlib.h> + +baz :: Int +baz = {# sizeof gz_header_s #} diff --git a/third_party/bazel/rules_haskell/tests/c2hs/repo/WORKSPACE b/third_party/bazel/rules_haskell/tests/c2hs/repo/WORKSPACE new file mode 100644 index 000000000000..e53539f0b46c --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/c2hs/repo/WORKSPACE @@ -0,0 +1 @@ +workspace(name = "c2hs_repo") diff --git a/third_party/bazel/rules_haskell/tests/c2hs/src/Foo/Foo.chs b/third_party/bazel/rules_haskell/tests/c2hs/src/Foo/Foo.chs new file mode 100644 index 000000000000..244f3b2b29ff --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/c2hs/src/Foo/Foo.chs @@ -0,0 +1,6 @@ +module Foo.Foo (foo) where + +#include <zlib.h> + +foo :: Int +foo = {# sizeof gz_header_s #} diff --git a/third_party/bazel/rules_haskell/tests/cc_haskell_import/BUILD.bazel b/third_party/bazel/rules_haskell/tests/cc_haskell_import/BUILD.bazel new file mode 100644 index 000000000000..c89631450059 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/cc_haskell_import/BUILD.bazel @@ -0,0 +1,70 @@ +load( + "@io_tweag_rules_haskell//haskell:haskell.bzl", + "haskell_library", +) + +package(default_testonly = 1) + +haskell_library( + name = "hs-lib-a", + srcs = ["LibA.hs"], + deps = [ + "//tests/data:ourclibrary", + "//tests/hackage:base", + ], +) + +haskell_library( + name = "hs-lib-b", + srcs = ["LibB.hs"], + deps = [ + ":hs-lib-a", + "//tests/hackage:base", + ], +) + +cc_binary( + name = "cc-bin", + srcs = [ + "main.c", + ], + # TODO support linking with static haskell libraries. + linkstatic = False, + tags = ["requires_threaded_rts"], + visibility = ["//tests:__subpackages__"], + deps = [ + ":hs-lib-b", + "@ghc//:threaded-rts", + ], +) + +# We go one step further and use the Haskell library from above +# to build a static .so which is then loaded with a Python script +# and calls the Haskell function constructed from GHC C FFI. + +# shared library which python will dlopen +cc_binary( + name = "hs-lib-b-wrapped.so", + linkshared = 1, + linkstatic = 0, + tags = ["requires_threaded_rts"], + visibility = ["//tests:__subpackages__"], + deps = [ + ":hs-lib-b", + "@ghc//:threaded-rts", + ], +) + +# just dlopens hb-lib-b-wrapped.so and prints it +py_binary( + name = "python_add_one", + srcs = ["python_add_one.py"], + data = [ + ":hs-lib-b-wrapped.so", + ], + default_python_version = "PY3", + srcs_version = "PY3ONLY", + tags = ["requires_threaded_rts"], + visibility = ["//tests:__subpackages__"], + deps = ["@bazel_tools//tools/python/runfiles"], +) diff --git a/third_party/bazel/rules_haskell/tests/cc_haskell_import/LibA.hs b/third_party/bazel/rules_haskell/tests/cc_haskell_import/LibA.hs new file mode 100644 index 000000000000..db8e442e5a5f --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/cc_haskell_import/LibA.hs @@ -0,0 +1,8 @@ +module LibA (add_one) where + +import Data.Int (Int32) + +foreign import ccall "c_add_one" c_add_one' :: Int32 -> Int32 + +add_one :: Int32 -> Int32 +add_one x = c_add_one' x diff --git a/third_party/bazel/rules_haskell/tests/cc_haskell_import/LibB.hs b/third_party/bazel/rules_haskell/tests/cc_haskell_import/LibB.hs new file mode 100644 index 000000000000..5904463b51fc --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/cc_haskell_import/LibB.hs @@ -0,0 +1,9 @@ +module LibB (add_one_hs) where + +import LibA (add_one) +import Data.Int (Int32) + +foreign export ccall add_one_hs :: Int32 -> IO Int32 + +add_one_hs :: Int32 -> IO Int32 +add_one_hs x = pure $! add_one x + 0 diff --git a/third_party/bazel/rules_haskell/tests/cc_haskell_import/cbits.c b/third_party/bazel/rules_haskell/tests/cc_haskell_import/cbits.c new file mode 100644 index 000000000000..587d26ba28aa --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/cc_haskell_import/cbits.c @@ -0,0 +1,5 @@ +#include <stdint.h> + +int32_t c_add_one(int32_t x) { + return 1 + x; +} diff --git a/third_party/bazel/rules_haskell/tests/cc_haskell_import/main.c b/third_party/bazel/rules_haskell/tests/cc_haskell_import/main.c new file mode 100644 index 000000000000..661174e5df49 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/cc_haskell_import/main.c @@ -0,0 +1,11 @@ +#include <stdio.h> +#include "HsFFI.h" + +extern HsInt32 add_one_hs(HsInt32 a0); + +int main(int argc, char *argv[]) { + hs_init(&argc, &argv); + printf("Adding one to 5 through Haskell is %d\n", add_one_hs(5)); + hs_exit(); + return 0; +} diff --git a/third_party/bazel/rules_haskell/tests/cc_haskell_import/python_add_one.py b/third_party/bazel/rules_haskell/tests/cc_haskell_import/python_add_one.py new file mode 100644 index 000000000000..b400102d1cc6 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/cc_haskell_import/python_add_one.py @@ -0,0 +1,18 @@ +import os +import ctypes +from bazel_tools.tools.python.runfiles import runfiles +import subprocess + +r = runfiles.Create() + +path = r.Rlocation('io_tweag_rules_haskell/tests/cc_haskell_import/hs-lib-b-wrapped.so') + +foreignlib = ctypes.cdll.LoadLibrary(path) + +# ATTN: If you remove this print *statement* hs_init will segfault! +# If you use the python3 print *function*, it will segfault as well! +# TODO: wtf? +print foreignlib + +foreignlib.hs_init() +assert(str(foreignlib.add_one_hs(1)) == "2") diff --git a/third_party/bazel/rules_haskell/tests/cpp_macro_conflict/BUILD.bazel b/third_party/bazel/rules_haskell/tests/cpp_macro_conflict/BUILD.bazel new file mode 100644 index 000000000000..af8848a6eea7 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/cpp_macro_conflict/BUILD.bazel @@ -0,0 +1,36 @@ +load( + "@io_tweag_rules_haskell//haskell:haskell.bzl", + "haskell_library", + "haskell_test", +) + +package(default_testonly = 1) + +# empty library with package name "bytestring" +haskell_library( + name = "bytestring", + srcs = ["src/BS.hs"], + deps = ["//tests/hackage:base"], +) + +# This depends on two packages "bytestring" +# There should be no CPP macro conflict +haskell_test( + name = "macro_conflict", + srcs = ["Main.hs"], + compiler_flags = [ + "-XCPP", + "-Werror", + ] + select({ + # clang on darwin fails because of unused command line argument, it fails because of -Werror + "@bazel_tools//src/conditions:darwin": [ + "-optP-Wno-unused-command-line-argument", + ], + "//conditions:default": [], + }), + deps = [ + ":bytestring", + "//tests/hackage:base", + "//tests/hackage:bytestring", + ], +) diff --git a/third_party/bazel/rules_haskell/tests/cpp_macro_conflict/Main.hs b/third_party/bazel/rules_haskell/tests/cpp_macro_conflict/Main.hs new file mode 100644 index 000000000000..f5a27e6a7efb --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/cpp_macro_conflict/Main.hs @@ -0,0 +1,4 @@ +import qualified Data.ByteString +import BS + +main = putStrLn "hello" diff --git a/third_party/bazel/rules_haskell/tests/cpp_macro_conflict/src/BS.hs b/third_party/bazel/rules_haskell/tests/cpp_macro_conflict/src/BS.hs new file mode 100644 index 000000000000..437b7e5f72cd --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/cpp_macro_conflict/src/BS.hs @@ -0,0 +1 @@ +module BS where diff --git a/third_party/bazel/rules_haskell/tests/data/BUILD.bazel b/third_party/bazel/rules_haskell/tests/data/BUILD.bazel new file mode 100644 index 000000000000..7083de23af40 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/data/BUILD.bazel @@ -0,0 +1,15 @@ +# Generic data files and targets that are used by multiple tests + +cc_library( + name = "ourclibrary", + srcs = [":ourclibrary.c"], + linkstatic = False, + visibility = ["//visibility:public"], +) + +cc_library( + name = "ourclibrary-static", + srcs = [":ourclibrary.c"], + linkstatic = True, + visibility = ["//visibility:public"], +) diff --git a/third_party/bazel/rules_haskell/tests/data/ourclibrary.c b/third_party/bazel/rules_haskell/tests/data/ourclibrary.c new file mode 100644 index 000000000000..587d26ba28aa --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/data/ourclibrary.c @@ -0,0 +1,5 @@ +#include <stdint.h> + +int32_t c_add_one(int32_t x) { + return 1 + x; +} diff --git a/third_party/bazel/rules_haskell/tests/encoding/BUILD.bazel b/third_party/bazel/rules_haskell/tests/encoding/BUILD.bazel new file mode 100644 index 000000000000..588d13f6d0b7 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/encoding/BUILD.bazel @@ -0,0 +1,21 @@ +load( + "@io_tweag_rules_haskell//haskell:haskell.bzl", + "haskell_test", +) + +package(default_testonly = 1) + +haskell_test( + name = "encoding", + srcs = [ + "Main.hs", + "TH.hs", + ], + extra_srcs = [ + "unicode.txt", + ], + deps = [ + "//tests/hackage:base", + "//tests/hackage:template-haskell", + ], +) diff --git a/third_party/bazel/rules_haskell/tests/encoding/Main.hs b/third_party/bazel/rules_haskell/tests/encoding/Main.hs new file mode 100644 index 000000000000..beb5f2a29497 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/encoding/Main.hs @@ -0,0 +1,8 @@ +{-# LANGUAGE TemplateHaskell #-} + +module Main (main) where + +import TH + +main :: IO () +main = putStrLn $foo diff --git a/third_party/bazel/rules_haskell/tests/encoding/TH.hs b/third_party/bazel/rules_haskell/tests/encoding/TH.hs new file mode 100644 index 000000000000..8cb52b3f1139 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/encoding/TH.hs @@ -0,0 +1,7 @@ +module TH (foo) where + +import Language.Haskell.TH +import Language.Haskell.TH.Syntax (lift) + +foo :: Q Exp +foo = runIO (readFile "tests/encoding/unicode.txt") >>= lift diff --git a/third_party/bazel/rules_haskell/tests/encoding/unicode.txt b/third_party/bazel/rules_haskell/tests/encoding/unicode.txt new file mode 100644 index 000000000000..74e5f2638d08 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/encoding/unicode.txt @@ -0,0 +1 @@ +Некоторый текст на русском. diff --git a/third_party/bazel/rules_haskell/tests/external-haskell-repository/BUILD.bazel b/third_party/bazel/rules_haskell/tests/external-haskell-repository/BUILD.bazel new file mode 100644 index 000000000000..30ff35704050 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/external-haskell-repository/BUILD.bazel @@ -0,0 +1,17 @@ +# Tests correct linking of haskell packages that were created +# in a different bazel repository, e.g. with hazel. + +load( + "@io_tweag_rules_haskell//haskell:haskell.bzl", + "haskell_test", +) + +haskell_test( + name = "external-haskell-repository", + srcs = ["Main.hs"], + visibility = ["//visibility:public"], + deps = [ + "//tests/hackage:base", + "@haskell_package_repository_dummy//:library-with-cbits", + ], +) diff --git a/third_party/bazel/rules_haskell/tests/external-haskell-repository/Main.hs b/third_party/bazel/rules_haskell/tests/external-haskell-repository/Main.hs new file mode 100644 index 000000000000..97fcc158880a --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/external-haskell-repository/Main.hs @@ -0,0 +1,6 @@ +module Main where + +import AddOne +import Control.Exception (assert) + +main = assert (addOne 41 == 42) $ return () diff --git a/third_party/bazel/rules_haskell/tests/external-haskell-repository/workspace_dummy.bzl b/third_party/bazel/rules_haskell/tests/external-haskell-repository/workspace_dummy.bzl new file mode 100644 index 000000000000..1ccc0aadf1de --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/external-haskell-repository/workspace_dummy.bzl @@ -0,0 +1,64 @@ +# This file constructs a dummy workspace to test +# haskell binaries that are included from outside repositories +# (because linking external repositories works differently). + +# Repo-ception, in the sense that we build a WORKSPACE +# that references the workspaces already set up in the +# `rules_haskell` WORKSPACE. +def _haskell_package_repository_dummy_impl(rep_ctx): + rep_ctx.file( + "WORKSPACE", + executable = False, + content = """ +repository(name={name}) + +register_toolchains( + "@io_tweag_rules_haskell//tests/:ghc" +) +""".format(name = rep_ctx.name), + ) + + # this mirrors tests/library-with-cbits + + rep_ctx.file( + "BUILD", + executable = False, + content = """ +load( + "@io_tweag_rules_haskell//haskell:haskell.bzl", + "haskell_toolchain", + "haskell_library", +) +load( + "@io_tweag_rules_haskell//:constants.bzl", + "test_ghc_version", +) + +haskell_library( + name = "library-with-cbits", + srcs = ["AddOne.hs"], + deps = [ + "@io_tweag_rules_haskell//tests/data:ourclibrary", + "@io_tweag_rules_haskell//tests/hackage:base", + ], + + linkstatic = False, + visibility = ["//visibility:public"], +) +""", + ) + + rep_ctx.file( + "AddOne.hs", + executable = False, + content = """ +module AddOne where + +foreign import ccall "c_add_one" addOne :: Int -> Int +""", + ) + +haskell_package_repository_dummy = repository_rule( + _haskell_package_repository_dummy_impl, + local = True, +) diff --git a/third_party/bazel/rules_haskell/tests/extra-source-files/BUILD.bazel b/third_party/bazel/rules_haskell/tests/extra-source-files/BUILD.bazel new file mode 100644 index 000000000000..9552d7c9e974 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/extra-source-files/BUILD.bazel @@ -0,0 +1,44 @@ +load( + "@io_tweag_rules_haskell//haskell:haskell.bzl", + "haskell_library", + "haskell_test", +) + +package(default_testonly = 1) + +haskell_library( + name = "extra-source-files", + srcs = [ + "Foo.hs", + "FooTH.hs", + ], + # Test that the linker can also see the extra_srcs. + compiler_flags = ["-optl-Wl,@tests/extra-source-files/ld-options.txt"], + extra_srcs = [ + "file.txt", + "ld-options.txt", + ], + deps = [ + "//tests/hackage:base", + "//tests/hackage:template-haskell", + ], +) + +haskell_test( + name = "extra-source-files-bin", + srcs = [ + "Foo.hs", + "FooTH.hs", + "Main.hs", + ], + # Test that the linker can also see the extra_srcs. + compiler_flags = ["-optl-Wl,@tests/extra-source-files/ld-options.txt"], + extra_srcs = [ + "file.txt", + "ld-options.txt", + ], + deps = [ + "//tests/hackage:base", + "//tests/hackage:template-haskell", + ], +) diff --git a/third_party/bazel/rules_haskell/tests/extra-source-files/Foo.hs b/third_party/bazel/rules_haskell/tests/extra-source-files/Foo.hs new file mode 100644 index 000000000000..b3f0c04492db --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/extra-source-files/Foo.hs @@ -0,0 +1,8 @@ +{-# LANGUAGE TemplateHaskell #-} + +module Foo (foo) where + +import FooTH (embedFile) + +foo :: String +foo = $(embedFile "tests/extra-source-files/file.txt") ++ "!" diff --git a/third_party/bazel/rules_haskell/tests/extra-source-files/FooTH.hs b/third_party/bazel/rules_haskell/tests/extra-source-files/FooTH.hs new file mode 100644 index 000000000000..24d663108355 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/extra-source-files/FooTH.hs @@ -0,0 +1,12 @@ +{-# LANGUAGE TemplateHaskell #-} + +module FooTH (embedFile) where + +import Language.Haskell.TH +import Language.Haskell.TH.Syntax + +embedFile :: FilePath -> Q Exp +embedFile path = do + str <- runIO (readFile path) + addDependentFile path + [| str |] diff --git a/third_party/bazel/rules_haskell/tests/extra-source-files/Main.hs b/third_party/bazel/rules_haskell/tests/extra-source-files/Main.hs new file mode 100644 index 000000000000..13e4bd765b6a --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/extra-source-files/Main.hs @@ -0,0 +1,4 @@ +import Foo (foo) + +main :: IO () +main = putStrLn foo diff --git a/third_party/bazel/rules_haskell/tests/extra-source-files/file.txt b/third_party/bazel/rules_haskell/tests/extra-source-files/file.txt new file mode 100644 index 000000000000..5bc133a4d007 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/extra-source-files/file.txt @@ -0,0 +1 @@ +And here we go diff --git a/third_party/bazel/rules_haskell/tests/extra-source-files/ld-options.txt b/third_party/bazel/rules_haskell/tests/extra-source-files/ld-options.txt new file mode 100644 index 000000000000..e69de29bb2d1 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/extra-source-files/ld-options.txt diff --git a/third_party/bazel/rules_haskell/tests/failures/transitive-deps/BUILD.bazel b/third_party/bazel/rules_haskell/tests/failures/transitive-deps/BUILD.bazel new file mode 100644 index 000000000000..c2efbd924a32 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/failures/transitive-deps/BUILD.bazel @@ -0,0 +1,66 @@ +load( + "@io_tweag_rules_haskell//haskell:haskell.bzl", + "haskell_library", +) + +package(default_testonly = 1) + +haskell_library( + name = "lib-a", + srcs = ["LibA.hs"], + deps = ["//tests/hackage:base"], +) + +haskell_library( + name = "lib-b", + srcs = ["LibB.hs"], + visibility = ["//visibility:private"], + deps = [ + ":lib-a", + "//tests/hackage:base", + ], +) + +# Targets that must FAIL. These are tagged as manual so that +# +# $ bazel build //... +# +# does not fail. + +haskell_library( + # Should fail because it doesn't specify "base" explicitly. + name = "lib-cFailure", + srcs = ["LibC.hs"], + tags = ["manual"], + deps = [":lib-b"], +) + +haskell_library( + name = "lib-c", + srcs = ["LibC.hs"], + deps = [ + ":lib-b", + "//tests/hackage:base", + ], +) + +haskell_library( + # Should fail because it doesn't specify "lib-a" explicitly. + name = "lib-dFailure", + srcs = ["LibD.hs"], + tags = ["manual"], + deps = [ + ":lib-b", + "//tests/hackage:base", + ], +) + +haskell_library( + name = "lib-d", + srcs = ["LibD.hs"], + deps = [ + ":lib-a", + ":lib-b", + "//tests/hackage:base", + ], +) diff --git a/third_party/bazel/rules_haskell/tests/failures/transitive-deps/LibA.hs b/third_party/bazel/rules_haskell/tests/failures/transitive-deps/LibA.hs new file mode 100644 index 000000000000..23e9486489fe --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/failures/transitive-deps/LibA.hs @@ -0,0 +1,4 @@ +module LibA (thingA) where + +thingA :: Int +thingA = 5 diff --git a/third_party/bazel/rules_haskell/tests/failures/transitive-deps/LibB.hs b/third_party/bazel/rules_haskell/tests/failures/transitive-deps/LibB.hs new file mode 100644 index 000000000000..9ab883093bd8 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/failures/transitive-deps/LibB.hs @@ -0,0 +1,6 @@ +module LibB (thingB) where + +import LibA (thingA) + +thingB :: Int +thingB = thingA + 1 diff --git a/third_party/bazel/rules_haskell/tests/failures/transitive-deps/LibC.hs b/third_party/bazel/rules_haskell/tests/failures/transitive-deps/LibC.hs new file mode 100644 index 000000000000..70514f13168b --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/failures/transitive-deps/LibC.hs @@ -0,0 +1,6 @@ +module LibC (thingC) where + +import LibB (thingB) + +thingC :: Int +thingC = thingB * 2 diff --git a/third_party/bazel/rules_haskell/tests/failures/transitive-deps/LibD.hs b/third_party/bazel/rules_haskell/tests/failures/transitive-deps/LibD.hs new file mode 100644 index 000000000000..326d224a2a15 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/failures/transitive-deps/LibD.hs @@ -0,0 +1,7 @@ +module LibD (thingD) where + +import LibA (thingA) +import LibB (thingB) + +thingD :: Int +thingD = thingA + thingB diff --git a/third_party/bazel/rules_haskell/tests/generated-modules/BUILD.bazel b/third_party/bazel/rules_haskell/tests/generated-modules/BUILD.bazel new file mode 100644 index 000000000000..098c7148a960 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/generated-modules/BUILD.bazel @@ -0,0 +1,56 @@ +load( + "@io_tweag_rules_haskell//haskell:haskell.bzl", + "haskell_library", + "haskell_test", +) + +package( + default_testonly = 1, + default_visibility = ["//visibility:public"], +) + +genrule( + name = "generate-genmodule", + outs = ["src/GenModule.hs"], + cmd = "printf 'module GenModule where\na = 1 :: Int' > $@", +) + +haskell_library( + name = "GenModule", + srcs = [":generate-genmodule"], + src_strip_prefix = "src", + deps = ["//tests/hackage:base"], +) + +genrule( + name = "generate-binmodule", + outs = ["src/BinModule.hs"], + cmd = "printf 'module BinModule where\nb = 2 :: Int' > $@", + output_to_bindir = 1, +) + +haskell_library( + name = "BinModule", + srcs = [":generate-binmodule"], + src_strip_prefix = "src", + deps = ["//tests/hackage:base"], +) + +genrule( + name = "generate-main", + outs = ["src/Main.hs"], + cmd = "printf 'module Main where\nimport GenModule\nimport BinModule\n" + + "main = print (a+b) :: IO ()' > $@", +) + +haskell_test( + name = "generated-modules", + size = "small", + srcs = [":generate-main"], + src_strip_prefix = "src", + deps = [ + ":BinModule", + ":GenModule", + "//tests/hackage:base", + ], +) diff --git a/third_party/bazel/rules_haskell/tests/ghc.nix b/third_party/bazel/rules_haskell/tests/ghc.nix new file mode 100644 index 000000000000..cde1699918f2 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/ghc.nix @@ -0,0 +1,41 @@ +{ pkgs ? import ../nixpkgs {} +# Whether we want to wrap the packages using <bazel_haskell_wrapper>. +# When this is called from inside bazel, we need to wrap the haskell package +# set using <bazel_haskell_wrapper>. Otherwise we don't need (and don't want) +# to. +, wrapPackages ? (builtins.tryEval <bazel_haskell_wrapper>).success +}: + +with pkgs; + +let haskellPackages = pkgs.haskell.packages.ghc864.override { + overrides = with pkgs.haskell.lib; self: super: rec { + libc = import ./haddock/libC.nix self pkgs; + }; + }; + genBazelBuild = + if wrapPackages + then callPackage <bazel_haskell_wrapper> {} + else (x: x); + +in + { + ghc = haskellPackages.ghcWithPackages (p: with p; [ + + # haskell_proto_library inputs + bytestring + containers + data-default-class + lens-family + lens-labels + proto-lens + text + + # test inputs + libc + + # for test runner + hspec + ]); + haskellPackages = genBazelBuild haskellPackages; +} diff --git a/third_party/bazel/rules_haskell/tests/ghc/BUILD.bazel b/third_party/bazel/rules_haskell/tests/ghc/BUILD.bazel new file mode 100644 index 000000000000..345ce4badf91 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/ghc/BUILD.bazel @@ -0,0 +1,3 @@ +load("//tests/ghc:ghc.bzl", "ghc_help") + +ghc_help(name = "ghc_help") diff --git a/third_party/bazel/rules_haskell/tests/ghc/ghc.bzl b/third_party/bazel/rules_haskell/tests/ghc/ghc.bzl new file mode 100644 index 000000000000..443f04e7be63 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/ghc/ghc.bzl @@ -0,0 +1,19 @@ +"""Runs ghc --help""" + +hs_toolchain = "@io_tweag_rules_haskell//haskell:toolchain" + +def _impl(ctx): + output = ctx.outputs.out + ghc = ctx.toolchains[hs_toolchain].tools.ghc + ctx.actions.run_shell( + inputs = [ghc], + outputs = [output], + progress_message = "Printing ghc help message", + command = "%s --help > %s" % (ghc.path, output.path), + ) + +ghc_help = rule( + implementation = _impl, + outputs = {"out": "out_file"}, + toolchains = [hs_toolchain], +) diff --git a/third_party/bazel/rules_haskell/tests/hackage/BUILD.bazel b/third_party/bazel/rules_haskell/tests/hackage/BUILD.bazel new file mode 100644 index 000000000000..63fb6f941b4b --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/hackage/BUILD.bazel @@ -0,0 +1,34 @@ +""" + Fetches GHC boot packages from GHC directly rather than from Nixpkgs + for better bindist support. +""" + +package(default_visibility = [ + "//tests:__subpackages__", + "@haskell_package_repository_dummy//:__subpackages__", +]) + +load( + "@io_tweag_rules_haskell//haskell:haskell.bzl", + "haskell_toolchain_library", +) + +[ + haskell_toolchain_library(name = name) + for name in [ + "array", + "base", + "binary", + "bytestring", + "containers", + "deepseq", + "directory", + "filepath", + "mtl", + "template-haskell", + "transformers", + "ghc-prim", + "process", + "text", + ] +] diff --git a/third_party/bazel/rules_haskell/tests/haddock/BUILD.bazel b/third_party/bazel/rules_haskell/tests/haddock/BUILD.bazel new file mode 100644 index 000000000000..6955285c87d2 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/haddock/BUILD.bazel @@ -0,0 +1,73 @@ +load( + "@io_tweag_rules_haskell//haskell:haskell.bzl", + "haskell_doc", + "haskell_library", + "haskell_toolchain_library", +) + +package( + default_testonly = 1, + default_visibility = ["//visibility:public"], +) + +haskell_library( + name = "haddock-lib-deep", + srcs = ["Deep.hsc"], + deps = ["//tests/hackage:base"], +) + +haskell_library( + name = "haddock-lib-a", + srcs = [ + "LibA.hs", + "LibA/A.hs", + "header.h", + ], + compiler_flags = ["-I."], + deps = [ + ":haddock-lib-deep", + "//tests/hackage:base", + "//tests/hackage:template-haskell", + ], +) + +haskell_toolchain_library( + name = "haddock-lib-c", + package = "libc", +) + +haskell_library( + name = "haddock-lib-b", + srcs = [ + "LibB.hs", + "TH.hs", + ], + extra_srcs = [ + "unicode.txt", + ], + tags = [ + "requires_hackage", + "requires_zlib", + ], + deps = [ + ":haddock-lib-a", + "//tests/hackage:base", + "//tests/hackage:template-haskell", + "@hackage//:libc", + "@zlib", + ], +) + +haskell_doc( + name = "haddock", + index_transitive_deps = False, + tags = ["requires_hackage"], + deps = [":haddock-lib-b"], +) + +haskell_doc( + name = "haddock-transitive", + index_transitive_deps = True, + tags = ["requires_hackage"], + deps = [":haddock-lib-b"], +) diff --git a/third_party/bazel/rules_haskell/tests/haddock/Deep.hsc b/third_party/bazel/rules_haskell/tests/haddock/Deep.hsc new file mode 100644 index 000000000000..6fb0482a1572 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/haddock/Deep.hsc @@ -0,0 +1,11 @@ +-- | "Deep" doc. +module Deep (deep_lib) where + +-- | 'deep_lib' doc. + +#if __GLASGOW_HASKELL__ >= 700 +#ifndef _INTERNAL_HSC_DO_NOT_DEFINE_ME +deep_lib :: Int +deep_lib = 100 +#endif +#endif diff --git a/third_party/bazel/rules_haskell/tests/haddock/LibA.hs b/third_party/bazel/rules_haskell/tests/haddock/LibA.hs new file mode 100644 index 000000000000..252c90ccc6d9 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/haddock/LibA.hs @@ -0,0 +1,19 @@ +-- | "LibA" header +{-# LANGUAGE CPP #-} +{-# LANGUAGE TemplateHaskell #-} + +#include "header.h" + +module LibA where + +import LibA.A (a) +import Deep (deep_lib) + +-- | 'A' declaration. +data A = + -- | 'A' constructor. + A + +-- | Doc for 'f' using 'a' and 'deep_lib'. +f :: Int +f = const $a deep_lib + MAGIC_NUMBER diff --git a/third_party/bazel/rules_haskell/tests/haddock/LibA/A.hs b/third_party/bazel/rules_haskell/tests/haddock/LibA/A.hs new file mode 100644 index 000000000000..3be8dd5aadd3 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/haddock/LibA/A.hs @@ -0,0 +1,10 @@ +-- | "LibA.A" header +{-# LANGUAGE TemplateHaskell #-} + +module LibA.A where + +import Language.Haskell.TH + +-- | 'a' doc +a :: Q Exp +a = [| 5 |] diff --git a/third_party/bazel/rules_haskell/tests/haddock/LibB.hs b/third_party/bazel/rules_haskell/tests/haddock/LibB.hs new file mode 100644 index 000000000000..b4df1ffcb9a2 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/haddock/LibB.hs @@ -0,0 +1,21 @@ +{-# LANGUAGE TemplateHaskell #-} +-- | "LibB" doc. + +module LibB where + +import LibA.A (a) +import LibA (f) +import LibC (mytype, LibCType) +import TH (foo) + +-- | Doc for 'x' using 'f' and 'a' and 'Int'. +x :: Int +x = const f a + +-- | This uses a type from an undocumented package +y :: LibCType +y = mytype + +-- | A thing generated with TH. +z :: String +z = $foo diff --git a/third_party/bazel/rules_haskell/tests/haddock/TH.hs b/third_party/bazel/rules_haskell/tests/haddock/TH.hs new file mode 100644 index 000000000000..6e791b09154e --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/haddock/TH.hs @@ -0,0 +1,7 @@ +module TH (foo) where + +import Language.Haskell.TH +import Language.Haskell.TH.Syntax (lift) + +foo :: Q Exp +foo = runIO (readFile "tests/haddock/unicode.txt") >>= lift diff --git a/third_party/bazel/rules_haskell/tests/haddock/header.h b/third_party/bazel/rules_haskell/tests/haddock/header.h new file mode 100644 index 000000000000..ec5eddd2766e --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/haddock/header.h @@ -0,0 +1 @@ +#define MAGIC_NUMBER 100 diff --git a/third_party/bazel/rules_haskell/tests/haddock/libC.nix b/third_party/bazel/rules_haskell/tests/haddock/libC.nix new file mode 100644 index 000000000000..d345178838f1 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/haddock/libC.nix @@ -0,0 +1,47 @@ +# A trivial `haskellPackages` library that has haddock generation disabled +self: pkgs: +let + # pkgs = import ../../nixpkgs.nix {}; + + libC = pkgs.writeText "LibC.hs" '' + {-# language NoImplicitPrelude #-} + module LibC where + + data LibCType = LibCType + + -- | myfunction + mytype :: LibCType + mytype = LibCType + ''; + + cabal = pkgs.writeText "libc.cabal" '' + name: libc + version: 0.1.0.0 + build-type: Simple + cabal-version: >=1.10 + + library + default-language: Haskell2010 + exposed-modules: LibC + ''; + + src = pkgs.runCommand "libc-src" {} '' + mkdir $out + cp ${libC} $out/LibC.hs + cp ${cabal} $out/libc.cabal + ''; + +in + # This call means the `.haddock` file is not generated, + # even though the ghc package still references the location + # where it would ordinarily be. + pkgs.haskell.lib.dontHaddock + + (self.callPackage + ({ mkDerivation }: mkDerivation { + pname = "libc"; + version = "0.1.0.0"; + src = src; + license = pkgs.lib.licenses.mit; + isExecutable = false; + }) {}) diff --git a/third_party/bazel/rules_haskell/tests/haddock/unicode.txt b/third_party/bazel/rules_haskell/tests/haddock/unicode.txt new file mode 100644 index 000000000000..74e5f2638d08 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/haddock/unicode.txt @@ -0,0 +1 @@ +Некоторый текст на русском. diff --git a/third_party/bazel/rules_haskell/tests/haskell_doctest/BUILD.bazel b/third_party/bazel/rules_haskell/tests/haskell_doctest/BUILD.bazel new file mode 100644 index 000000000000..c1d4e527aefc --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/haskell_doctest/BUILD.bazel @@ -0,0 +1,73 @@ +load( + "@io_tweag_rules_haskell//haskell:haskell.bzl", + "haskell_doctest", + "haskell_library", + "haskell_test", +) + +package(default_testonly = 1) + +haskell_library( + name = "lib-a", + srcs = ["Foo.hs"], + tags = ["requires_zlib"], + deps = [ + "//tests/data:ourclibrary", + "//tests/hackage:base", + "@zlib.dev//:zlib", + ], +) + +haskell_library( + name = "lib-b", + srcs = [ + "Bar.hs", + "Baz.hs", + "Quux.hsc", + ], + tags = ["requires_zlib"], + deps = [ + ":lib-a", + "//tests/hackage:base", + ], +) + +haskell_doctest( + name = "doctest-lib-all-fail", + tags = ["manual"], # must FAIL + visibility = ["//visibility:public"], + deps = [":lib-b"], +) + +haskell_doctest( + name = "doctest-lib-all-success", + doctest_flags = ["-DMAGIC_DOCTEST_THING"], + tags = ["requires_doctest"], + visibility = ["//visibility:public"], + deps = [":lib-b"], +) + +haskell_doctest( + name = "doctest-lib", + modules = ["Bar"], # exclude Baz and succeed + tags = ["requires_doctest"], + visibility = ["//visibility:public"], + deps = [":lib-b"], +) + +haskell_test( + name = "bin", + srcs = ["Main.hs"], + tags = ["requires_zlib"], + deps = [ + ":lib-a", + "//tests/hackage:base", + ], +) + +haskell_doctest( + name = "doctest-bin", + tags = ["requires_doctest"], + visibility = ["//visibility:public"], + deps = [":bin"], +) diff --git a/third_party/bazel/rules_haskell/tests/haskell_doctest/Bar.hs b/third_party/bazel/rules_haskell/tests/haskell_doctest/Bar.hs new file mode 100644 index 000000000000..cd82351855c3 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/haskell_doctest/Bar.hs @@ -0,0 +1,13 @@ +module Bar (bar) where + +import Foo (foo) +import Numeric + +-- | +-- >>> bar +-- 9 +-- >>> showInt bar "" ++ "!" +-- "9!" + +bar :: Int +bar = 4 + foo diff --git a/third_party/bazel/rules_haskell/tests/haskell_doctest/Baz.hs b/third_party/bazel/rules_haskell/tests/haskell_doctest/Baz.hs new file mode 100644 index 000000000000..d576235bf488 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/haskell_doctest/Baz.hs @@ -0,0 +1,14 @@ +{-# LANGUAGE CPP #-} + +module Baz (baz) where + +-- | +-- >>> baz +-- 101 + +baz :: Int +#ifndef MAGIC_DOCTEST_THING +baz = 100 +#else +baz = 101 +#endif diff --git a/third_party/bazel/rules_haskell/tests/haskell_doctest/Foo.hs b/third_party/bazel/rules_haskell/tests/haskell_doctest/Foo.hs new file mode 100644 index 000000000000..d2c97b77aeb3 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/haskell_doctest/Foo.hs @@ -0,0 +1,14 @@ +{-# LANGUAGE ForeignFunctionInterface #-} + +module Foo (foo) where + +import Foreign.C.Types (CInt(..)) + +foreign import ccall "c_add_one" + c_add_one :: CInt -> CInt + +-- | +-- >>> foo +-- 5 +foo :: Int +foo = fromIntegral (c_add_one 4) diff --git a/third_party/bazel/rules_haskell/tests/haskell_doctest/Main.hs b/third_party/bazel/rules_haskell/tests/haskell_doctest/Main.hs new file mode 100644 index 000000000000..1bc6f8abc905 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/haskell_doctest/Main.hs @@ -0,0 +1,6 @@ +module Main (main) where + +import Foo (foo) + +main :: IO () +main = print foo diff --git a/third_party/bazel/rules_haskell/tests/haskell_doctest/Quux.hsc b/third_party/bazel/rules_haskell/tests/haskell_doctest/Quux.hsc new file mode 100644 index 000000000000..3d437274c9aa --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/haskell_doctest/Quux.hsc @@ -0,0 +1,11 @@ +-- | This module is in a .hsc file, this way we test that improt directories +-- are passed correctly to the doctest executable. + +module Quux (quux) where + +-- | +-- >>> quux +-- 68 + +quux :: Int +quux = 68 diff --git a/third_party/bazel/rules_haskell/tests/haskell_lint/BUILD.bazel b/third_party/bazel/rules_haskell/tests/haskell_lint/BUILD.bazel new file mode 100644 index 000000000000..702dfdfe07bc --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/haskell_lint/BUILD.bazel @@ -0,0 +1,47 @@ +load( + "@io_tweag_rules_haskell//haskell:haskell.bzl", + "haskell_library", + "haskell_lint", + "haskell_test", +) + +package(default_testonly = 1) + +haskell_library( + name = "lib-a", + srcs = ["Foo.hs"], + visibility = ["//visibility:public"], + deps = ["//tests/hackage:base"], +) + +haskell_library( + name = "lib-b", + srcs = ["Bar.hs"], + visibility = ["//visibility:public"], + deps = [ + ":lib-a", + "//tests/hackage:base", + ], +) + +haskell_lint( + name = "lint-lib-b", + visibility = ["//visibility:public"], + deps = [":lib-b"], +) + +haskell_test( + name = "bin", + srcs = ["Main.hs"], + visibility = ["//visibility:public"], + deps = [ + ":lib-a", + "//tests/hackage:base", + ], +) + +haskell_lint( + name = "lint-bin", + visibility = ["//visibility:public"], + deps = [":bin"], +) diff --git a/third_party/bazel/rules_haskell/tests/haskell_lint/Bar.hs b/third_party/bazel/rules_haskell/tests/haskell_lint/Bar.hs new file mode 100644 index 000000000000..18e9583e5ad6 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/haskell_lint/Bar.hs @@ -0,0 +1,6 @@ +module Bar (bar) where + +import Foo (foo) + +bar :: Int +bar = 4 + foo :: Int diff --git a/third_party/bazel/rules_haskell/tests/haskell_lint/Foo.hs b/third_party/bazel/rules_haskell/tests/haskell_lint/Foo.hs new file mode 100644 index 000000000000..119192e6b12b --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/haskell_lint/Foo.hs @@ -0,0 +1,4 @@ +module Foo (foo) where + +foo :: Int +foo = 5 :: Int diff --git a/third_party/bazel/rules_haskell/tests/haskell_lint/Main.hs b/third_party/bazel/rules_haskell/tests/haskell_lint/Main.hs new file mode 100644 index 000000000000..1bc6f8abc905 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/haskell_lint/Main.hs @@ -0,0 +1,6 @@ +module Main (main) where + +import Foo (foo) + +main :: IO () +main = print foo diff --git a/third_party/bazel/rules_haskell/tests/haskell_proto_library/BUILD.bazel b/third_party/bazel/rules_haskell/tests/haskell_proto_library/BUILD.bazel new file mode 100644 index 000000000000..f5f8762b3aff --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/haskell_proto_library/BUILD.bazel @@ -0,0 +1,78 @@ +load( + "@io_tweag_rules_haskell//haskell:haskell.bzl", + "haskell_doc", + "haskell_library", + "haskell_proto_library", +) + +package(default_testonly = 1) + +proto_library( + name = "zip_code_proto", + srcs = ["zip_code.proto"], +) + +proto_library( + name = "address_proto", + srcs = ["address.proto"], + deps = [":zip_code_proto"], +) + +proto_library( + name = "person_proto", + srcs = ["person.proto"], + deps = [ + ":address_proto", + "@com_google_protobuf//:timestamp_proto", + ], +) + +proto_library( + name = "stripped_zip_code_proto", + srcs = ["stripped_zip_code.proto"], + strip_import_prefix = "/tests/haskell_proto_library/", +) + +proto_library( + name = "stripped_address_proto", + srcs = ["stripped_address.proto"], + strip_import_prefix = "/tests/haskell_proto_library/", + deps = [":stripped_zip_code_proto"], +) + +haskell_proto_library( + name = "address_haskell_proto", + tags = ["requires_hackage"], + deps = [":address_proto"], +) + +haskell_proto_library( + name = "stripped_address_haskell_proto", + tags = ["requires_hackage"], + deps = [":stripped_address_proto"], +) + +haskell_proto_library( + name = "person_haskell_proto", + tags = ["requires_hackage"], + deps = [":person_proto"], +) + +haskell_library( + name = "hs-lib", + srcs = ["Bar.hs"], + tags = ["requires_hackage"], + visibility = ["//visibility:public"], + deps = [ + ":address_haskell_proto", + ":person_haskell_proto", + ":stripped_address_haskell_proto", + "//tests/hackage:base", + ], +) + +haskell_doc( + name = "docs", + tags = ["requires_hackage"], + deps = [":hs-lib"], +) diff --git a/third_party/bazel/rules_haskell/tests/haskell_proto_library/Bar.hs b/third_party/bazel/rules_haskell/tests/haskell_proto_library/Bar.hs new file mode 100644 index 000000000000..fa95bf088c91 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/haskell_proto_library/Bar.hs @@ -0,0 +1,8 @@ +module Bar (bar) where + +import Proto.StrippedAddress +import Proto.Tests.HaskellProtoLibrary.Person +import Proto.Tests.HaskellProtoLibrary.Person_Fields + +bar :: Int +bar = 5 diff --git a/third_party/bazel/rules_haskell/tests/haskell_proto_library/address.proto b/third_party/bazel/rules_haskell/tests/haskell_proto_library/address.proto new file mode 100644 index 000000000000..d81642d8bcd4 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/haskell_proto_library/address.proto @@ -0,0 +1,11 @@ +syntax = "proto3"; + +package demo; // Required to generate valid code. + +// Always import protos with a full path relative to the WORKSPACE file. +import "tests/haskell_proto_library/zip_code.proto"; + +message Address { + string city = 1; + ZipCode zip_code = 2; +} diff --git a/third_party/bazel/rules_haskell/tests/haskell_proto_library/person.proto b/third_party/bazel/rules_haskell/tests/haskell_proto_library/person.proto new file mode 100644 index 000000000000..95bf3524f819 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/haskell_proto_library/person.proto @@ -0,0 +1,16 @@ +syntax = "proto3"; + +package demo; // Required to generate valid code. + +// Always import protos with a full path relative to the WORKSPACE file. +import "tests/haskell_proto_library/address.proto"; + +import "google/protobuf/timestamp.proto"; + +message Person { + string name = 1; + int32 id = 2; + string email = 3; + Address address = 4; + google.protobuf.Timestamp timestamp = 5; +} diff --git a/third_party/bazel/rules_haskell/tests/haskell_proto_library/stripped_address.proto b/third_party/bazel/rules_haskell/tests/haskell_proto_library/stripped_address.proto new file mode 100644 index 000000000000..5b5ce47be83a --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/haskell_proto_library/stripped_address.proto @@ -0,0 +1,10 @@ +syntax = "proto3"; + +package demo; // Required to generate valid code. + +import "stripped_zip_code.proto"; + +message StrippedAddress { + string city = 1; + StrippedZipCode zip_code = 2; +} diff --git a/third_party/bazel/rules_haskell/tests/haskell_proto_library/stripped_zip_code.proto b/third_party/bazel/rules_haskell/tests/haskell_proto_library/stripped_zip_code.proto new file mode 100644 index 000000000000..690d7c9d99cc --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/haskell_proto_library/stripped_zip_code.proto @@ -0,0 +1,7 @@ +syntax = "proto3"; + +package demo; // Required to generate valid code. + +message StrippedZipCode { + string code = 1; +} diff --git a/third_party/bazel/rules_haskell/tests/haskell_proto_library/zip_code.proto b/third_party/bazel/rules_haskell/tests/haskell_proto_library/zip_code.proto new file mode 100644 index 000000000000..e72578cf2178 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/haskell_proto_library/zip_code.proto @@ -0,0 +1,7 @@ +syntax = "proto3"; + +package demo; // Required to generate valid code. + +message ZipCode { + string code = 1; +} diff --git a/third_party/bazel/rules_haskell/tests/haskell_test/BUILD.bazel b/third_party/bazel/rules_haskell/tests/haskell_test/BUILD.bazel new file mode 100644 index 000000000000..eb00b2c31881 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/haskell_test/BUILD.bazel @@ -0,0 +1,29 @@ +load( + "@io_tweag_rules_haskell//haskell:haskell.bzl", + "haskell_library", + "haskell_test", +) + +package(default_testonly = 1) + +haskell_library( + name = "mylib", + srcs = ["Lib.hs"], + deps = ["//tests/hackage:base"], +) + +haskell_test( + name = "haskell_test", + # Use some parameters that only test rules have. + size = "small", + timeout = "short", + srcs = ["Test.hs"], + flaky = False, + main_function = "Test.test", + visibility = ["//visibility:public"], + deps = [ + ":mylib", + "//tests/data:ourclibrary", + "//tests/hackage:base", + ], +) diff --git a/third_party/bazel/rules_haskell/tests/haskell_test/Lib.hs b/third_party/bazel/rules_haskell/tests/haskell_test/Lib.hs new file mode 100644 index 000000000000..3553d6b6f493 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/haskell_test/Lib.hs @@ -0,0 +1,4 @@ +module Lib where + +foo :: Int +foo = 42 diff --git a/third_party/bazel/rules_haskell/tests/haskell_test/Test.hs b/third_party/bazel/rules_haskell/tests/haskell_test/Test.hs new file mode 100644 index 000000000000..5ba65f82c94b --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/haskell_test/Test.hs @@ -0,0 +1,4 @@ +module Test (test) where + +test :: IO () +test = putStrLn "haskell_test fired" diff --git a/third_party/bazel/rules_haskell/tests/haskell_toolchain_library/BUILD.bazel b/third_party/bazel/rules_haskell/tests/haskell_toolchain_library/BUILD.bazel new file mode 100644 index 000000000000..6c36ce4bdbf1 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/haskell_toolchain_library/BUILD.bazel @@ -0,0 +1,26 @@ +load( + "@io_tweag_rules_haskell//haskell:haskell.bzl", + "haskell_library", + "haskell_test", +) + +package(default_testonly = 1) + +haskell_library( + name = "Lib", + srcs = ["Lib.hs"], + deps = [ + "//tests/hackage:base", + "//tests/hackage:bytestring", + ], +) + +haskell_test( + name = "binary", + srcs = ["Bin.hs"], + deps = [ + ":Lib", + "//tests/hackage:base", + "//tests/hackage:text", + ], +) diff --git a/third_party/bazel/rules_haskell/tests/haskell_toolchain_library/Bin.hs b/third_party/bazel/rules_haskell/tests/haskell_toolchain_library/Bin.hs new file mode 100644 index 000000000000..a0e7117d2e22 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/haskell_toolchain_library/Bin.hs @@ -0,0 +1,8 @@ +module Main (main) where + +import qualified Data.Text.IO as T +import qualified Data.Text.Encoding as E + +import Lib (message) + +main = T.putStrLn $ E.decodeUtf8 message diff --git a/third_party/bazel/rules_haskell/tests/haskell_toolchain_library/Lib.hs b/third_party/bazel/rules_haskell/tests/haskell_toolchain_library/Lib.hs new file mode 100644 index 000000000000..66a2161a19c4 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/haskell_toolchain_library/Lib.hs @@ -0,0 +1,5 @@ +module Lib (message) where + +import qualified Data.ByteString.Char8 as B + +message = B.pack "hello, world" diff --git a/third_party/bazel/rules_haskell/tests/hidden-modules/BUILD.bazel b/third_party/bazel/rules_haskell/tests/hidden-modules/BUILD.bazel new file mode 100644 index 000000000000..5d79e56085a2 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/hidden-modules/BUILD.bazel @@ -0,0 +1,35 @@ +load( + "@io_tweag_rules_haskell//haskell:haskell.bzl", + "haskell_library", +) + +package( + default_testonly = 1, + default_visibility = ["//visibility:public"], +) + +haskell_library( + name = "lib-a", + srcs = glob(["lib-a/*.hs"]), + hidden_modules = ["Foo"], + src_strip_prefix = "lib-a", + deps = ["//tests/hackage:base"], +) + +haskell_library( + name = "lib-b", + srcs = glob(["lib-b/*.hs"]), + src_strip_prefix = "lib-b", + deps = ["//tests/hackage:base"], +) + +haskell_library( + name = "lib-c", + srcs = glob(["lib-c/*.hs"]), + src_strip_prefix = "lib-c", + deps = [ + ":lib-a", + ":lib-b", + "//tests/hackage:base", + ], +) diff --git a/third_party/bazel/rules_haskell/tests/hidden-modules/lib-a/Bar.hs b/third_party/bazel/rules_haskell/tests/hidden-modules/lib-a/Bar.hs new file mode 100644 index 000000000000..5bc9c68895bf --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/hidden-modules/lib-a/Bar.hs @@ -0,0 +1,6 @@ +module Bar (bar) where + +import Foo (foo) + +bar :: Int +bar = foo * 2 diff --git a/third_party/bazel/rules_haskell/tests/hidden-modules/lib-a/Foo.hs b/third_party/bazel/rules_haskell/tests/hidden-modules/lib-a/Foo.hs new file mode 100644 index 000000000000..664be00d5487 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/hidden-modules/lib-a/Foo.hs @@ -0,0 +1,4 @@ +module Foo (foo) where + +foo :: Int +foo = 15 diff --git a/third_party/bazel/rules_haskell/tests/hidden-modules/lib-b/Foo.hs b/third_party/bazel/rules_haskell/tests/hidden-modules/lib-b/Foo.hs new file mode 100644 index 000000000000..6fdd42f9a8cd --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/hidden-modules/lib-b/Foo.hs @@ -0,0 +1,4 @@ +module Foo (foo) where + +foo :: Int +foo = 16 diff --git a/third_party/bazel/rules_haskell/tests/hidden-modules/lib-c/Baz.hs b/third_party/bazel/rules_haskell/tests/hidden-modules/lib-c/Baz.hs new file mode 100644 index 000000000000..055b2e80ad79 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/hidden-modules/lib-c/Baz.hs @@ -0,0 +1,7 @@ +module Baz (bar) where + +import Foo (foo) +import Bar (bar) + +baz :: Int +baz = foo + bar diff --git a/third_party/bazel/rules_haskell/tests/hs-boot/A.hs-boot.in b/third_party/bazel/rules_haskell/tests/hs-boot/A.hs-boot.in new file mode 100644 index 000000000000..02d37ced950f --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/hs-boot/A.hs-boot.in @@ -0,0 +1,2 @@ +module A where + newtype TA = MkTA Int diff --git a/third_party/bazel/rules_haskell/tests/hs-boot/A.hs.in b/third_party/bazel/rules_haskell/tests/hs-boot/A.hs.in new file mode 100644 index 000000000000..deeff5470b77 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/hs-boot/A.hs.in @@ -0,0 +1,8 @@ +module A where + +import B (TB (..)) + +newtype TA = MkTA Int + +f :: TB -> TA +f (MkTB x) = MkTA x diff --git a/third_party/bazel/rules_haskell/tests/hs-boot/BUILD.bazel b/third_party/bazel/rules_haskell/tests/hs-boot/BUILD.bazel new file mode 100644 index 000000000000..4e69da0e6b34 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/hs-boot/BUILD.bazel @@ -0,0 +1,48 @@ +load( + "@io_tweag_rules_haskell//haskell:haskell.bzl", + "haskell_library", + "haskell_test", +) + +package(default_testonly = 1) + +genrule( + name = "gen-A-boot", + srcs = ["A.hs-boot.in"], + outs = ["srcs/A.hs-boot"], + cmd = "cp $< $@", +) + +genrule( + name = "gen-A", + srcs = ["A.hs.in"], + outs = ["srcs/A.hs"], + cmd = "cp $< $@", +) + +haskell_library( + name = "hs-boot-lib", + srcs = [ + "srcs/B.hs", + ":gen-A", + ":gen-A-boot", + ], + src_strip_prefix = "srcs", + visibility = ["//visibility:public"], + deps = ["//tests/hackage:base"], +) + +haskell_test( + name = "hs-boot", + srcs = [ + "MA.hs", + "MA.hs-boot", + "MB.hs", + "Main.hs", + ], + visibility = ["//visibility:public"], + deps = [ + ":hs-boot-lib", + "//tests/hackage:base", + ], +) diff --git a/third_party/bazel/rules_haskell/tests/hs-boot/MA.hs b/third_party/bazel/rules_haskell/tests/hs-boot/MA.hs new file mode 100644 index 000000000000..4e0128596242 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/hs-boot/MA.hs @@ -0,0 +1,8 @@ +module MA where + +import MB (TB (..)) + +newtype TA = MkTA Int + +f :: TB -> TA +f (MkTB x) = MkTA x diff --git a/third_party/bazel/rules_haskell/tests/hs-boot/MA.hs-boot b/third_party/bazel/rules_haskell/tests/hs-boot/MA.hs-boot new file mode 100644 index 000000000000..0ab8c899f2e1 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/hs-boot/MA.hs-boot @@ -0,0 +1,2 @@ +module MA where + newtype TA = MkTA Int diff --git a/third_party/bazel/rules_haskell/tests/hs-boot/MB.hs b/third_party/bazel/rules_haskell/tests/hs-boot/MB.hs new file mode 100644 index 000000000000..d90d041d578e --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/hs-boot/MB.hs @@ -0,0 +1,8 @@ +module MB where + +import {-# SOURCE #-} MA (TA (..)) + +data TB = MkTB !Int + +g :: TA -> TB +g (MkTA x) = MkTB x diff --git a/third_party/bazel/rules_haskell/tests/hs-boot/Main.hs b/third_party/bazel/rules_haskell/tests/hs-boot/Main.hs new file mode 100644 index 000000000000..15c0085fe079 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/hs-boot/Main.hs @@ -0,0 +1,9 @@ +module Main (main) where + +import A () +import B () +import MA () +import MB () + +main :: IO () +main = putStrLn "hsboot" diff --git a/third_party/bazel/rules_haskell/tests/hs-boot/srcs/B.hs b/third_party/bazel/rules_haskell/tests/hs-boot/srcs/B.hs new file mode 100644 index 000000000000..60e1ff5f3edd --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/hs-boot/srcs/B.hs @@ -0,0 +1,8 @@ +module B where + +import {-# SOURCE #-} A (TA (..)) + +data TB = MkTB !Int + +g :: TA -> TB +g (MkTA x) = MkTB x diff --git a/third_party/bazel/rules_haskell/tests/hsc/BUILD.bazel b/third_party/bazel/rules_haskell/tests/hsc/BUILD.bazel new file mode 100644 index 000000000000..1e9a07cd5e08 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/hsc/BUILD.bazel @@ -0,0 +1,35 @@ +load( + "@io_tweag_rules_haskell//haskell:haskell.bzl", + "haskell_library", + "haskell_test", +) + +package(default_testonly = 1) + +haskell_library( + name = "hsc-lib", + srcs = [ + "Bar.hsc", + "Bar/Baz.hsc", + "Flags.hsc", + "Foo.hsc", + ], + compiler_flags = [ + "-DTHIS_IS_TRUE", + "-optP-DTHIS_TOO_IS_TRUE", + ], + deps = ["//tests/hackage:base"], +) + +haskell_test( + name = "hsc", + srcs = [ + "BinHsc.hsc", + "Main.hs", + ], + visibility = ["//visibility:public"], + deps = [ + ":hsc-lib", + "//tests/hackage:base", + ], +) diff --git a/third_party/bazel/rules_haskell/tests/hsc/Bar.hsc b/third_party/bazel/rules_haskell/tests/hsc/Bar.hsc new file mode 100644 index 000000000000..a8bb791513b5 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/hsc/Bar.hsc @@ -0,0 +1,6 @@ +module Bar (hscFiredBar) where + +#ifndef _INTERNAL_HSC_DO_NOT_DEFINE_ME +hscFiredBar :: String +hscFiredBar = "hscFiredBar" +#endif diff --git a/third_party/bazel/rules_haskell/tests/hsc/Bar/Baz.hsc b/third_party/bazel/rules_haskell/tests/hsc/Bar/Baz.hsc new file mode 100644 index 000000000000..7db172485de5 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/hsc/Bar/Baz.hsc @@ -0,0 +1,6 @@ +module Bar.Baz (hscFiredBaz) where + +#ifndef _INTERNAL_HSC_DO_NOT_DEFINE_ME +hscFiredBaz :: String +hscFiredBaz = "hscFiredBaz" +#endif diff --git a/third_party/bazel/rules_haskell/tests/hsc/BinHsc.hsc b/third_party/bazel/rules_haskell/tests/hsc/BinHsc.hsc new file mode 100644 index 000000000000..ddfee79c137c --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/hsc/BinHsc.hsc @@ -0,0 +1 @@ +module BinHsc () where \ No newline at end of file diff --git a/third_party/bazel/rules_haskell/tests/hsc/Flags.hsc b/third_party/bazel/rules_haskell/tests/hsc/Flags.hsc new file mode 100644 index 000000000000..b090df576ab4 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/hsc/Flags.hsc @@ -0,0 +1,8 @@ +module Flags (hscFlags) where + +#ifdef THIS_IS_TRUE +#ifdef THIS_TOO_IS_TRUE +hscFlags :: String +hscFlags = "hscFlags" +#endif +#endif diff --git a/third_party/bazel/rules_haskell/tests/hsc/Foo.hsc b/third_party/bazel/rules_haskell/tests/hsc/Foo.hsc new file mode 100644 index 000000000000..2cb726e18110 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/hsc/Foo.hsc @@ -0,0 +1,8 @@ +module Foo (hscFiredFoo) where + +#if __GLASGOW_HASKELL__ >= 700 +#ifndef _INTERNAL_HSC_DO_NOT_DEFINE_ME +hscFiredFoo :: String +hscFiredFoo = "hscFiredFoo" +#endif +#endif diff --git a/third_party/bazel/rules_haskell/tests/hsc/Main.hs b/third_party/bazel/rules_haskell/tests/hsc/Main.hs new file mode 100644 index 000000000000..33ff7f10f78c --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/hsc/Main.hs @@ -0,0 +1,10 @@ +module Main (main) where + +import BinHsc () +import Foo (hscFiredFoo) +import Bar (hscFiredBar) +import Bar.Baz (hscFiredBaz) +import Flags (hscFlags) + +main :: IO () +main = putStrLn (hscFiredFoo ++ hscFiredBar ++ hscFiredBaz ++ hscFlags) diff --git a/third_party/bazel/rules_haskell/tests/indirect-link/BUILD.bazel b/third_party/bazel/rules_haskell/tests/indirect-link/BUILD.bazel new file mode 100644 index 000000000000..60403a4ef277 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/indirect-link/BUILD.bazel @@ -0,0 +1,52 @@ +load("@io_tweag_rules_haskell//haskell:haskell.bzl", "haskell_library", "haskell_test", "haskell_toolchain_library") + +cc_library( + name = "cbits-indirect", + srcs = ["cbits/impl.c"], +) + +cc_library( + name = "cbits", + srcs = ["cbits/intf.c"], + deps = ["cbits-indirect"], +) + +haskell_library( + name = "mypkg", + srcs = ["src/MyModule.hs"], + src_strip_prefix = "src", + deps = [ + ":cbits", + "//tests/hackage:base", + ], +) + +haskell_test( + name = "indirect-link-static", + srcs = ["test/Main.hs"], + linkstatic = True, + src_strip_prefix = "test", + deps = [ + ":mypkg", + "//tests/hackage:base", + ], +) + +haskell_test( + name = "indirect-link-dynamic", + srcs = ["test/Main.hs"], + linkstatic = False, + src_strip_prefix = "test", + deps = [ + ":mypkg", + "//tests/hackage:base", + ], +) + +test_suite( + name = "indirect-link", + tests = [ + ":indirect-link-dynamic", + ":indirect-link-static", + ], +) diff --git a/third_party/bazel/rules_haskell/tests/indirect-link/cbits/impl.c b/third_party/bazel/rules_haskell/tests/indirect-link/cbits/impl.c new file mode 100644 index 000000000000..666ce43962a3 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/indirect-link/cbits/impl.c @@ -0,0 +1,9 @@ +static int thing; + +int real_get_thing(void) { + return thing; +} + +void real_set_thing(int value) { + thing = value; +} diff --git a/third_party/bazel/rules_haskell/tests/indirect-link/cbits/intf.c b/third_party/bazel/rules_haskell/tests/indirect-link/cbits/intf.c new file mode 100644 index 000000000000..f7a8f5e9f2e8 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/indirect-link/cbits/intf.c @@ -0,0 +1,10 @@ +extern int real_get_thing(void); +extern void real_set_thing(int value); + +int get_thing(void) { + return real_get_thing(); +} + +void set_thing(int value) { + real_set_thing(value); +} diff --git a/third_party/bazel/rules_haskell/tests/indirect-link/src/MyModule.hs b/third_party/bazel/rules_haskell/tests/indirect-link/src/MyModule.hs new file mode 100644 index 000000000000..4b75cee13989 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/indirect-link/src/MyModule.hs @@ -0,0 +1,11 @@ +module MyModule where + +foreign import ccall get_thing :: IO Int + +getThing :: IO Int +getThing = get_thing + +foreign import ccall set_thing :: Int -> IO () + +setThing :: Int -> IO () +setThing = set_thing diff --git a/third_party/bazel/rules_haskell/tests/indirect-link/test/Main.hs b/third_party/bazel/rules_haskell/tests/indirect-link/test/Main.hs new file mode 100644 index 000000000000..0b3d188d736a --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/indirect-link/test/Main.hs @@ -0,0 +1,9 @@ +module Main (main) where + +import qualified MyModule + +main :: IO () +main = do + print =<< MyModule.getThing + MyModule.setThing 123 + print =<< MyModule.getThing diff --git a/third_party/bazel/rules_haskell/tests/inline_tests.bzl b/third_party/bazel/rules_haskell/tests/inline_tests.bzl new file mode 100644 index 000000000000..b1ba001c6ec7 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/inline_tests.bzl @@ -0,0 +1,90 @@ +# features sh_inline_test and py_inline_test, +# which are like their respective builtin rules, +# but their scripts can be given inline as a string. + +load("@bazel_skylib//lib:shell.bzl", "shell") + +def quote_make_variables(s): + """Quote all genrule “Make” Variables in a string.""" + return s.replace("$", "$$") + +def target_from_string(name, string): + """Write a skylark string to a target.""" + native.genrule( + name = name + "-file", + outs = [name], + # this is exceptionally ugly. + cmd = """echo -n {quoted} > $(@)""".format( + # but should at least be quoted right + quoted = shell.quote(quote_make_variables(string)), + ), + ) + +bash_runfiles_boilerplate = """\ +# Copy-pasted from Bazel's Bash runfiles library (tools/bash/runfiles/runfiles.bash). +set -euo pipefail +if [[ ! -d "${RUNFILES_DIR:-/dev/null}" && ! -f "${RUNFILES_MANIFEST_FILE:-/dev/null}" ]]; then + if [[ -f "$0.runfiles_manifest" ]]; then + export RUNFILES_MANIFEST_FILE="$0.runfiles_manifest" + elif [[ -f "$0.runfiles/MANIFEST" ]]; then + export RUNFILES_MANIFEST_FILE="$0.runfiles/MANIFEST" + elif [[ -f "$0.runfiles/bazel_tools/tools/bash/runfiles/runfiles.bash" ]]; then + export RUNFILES_DIR="$0.runfiles" + fi +fi +if [[ -f "${RUNFILES_DIR:-/dev/null}/bazel_tools/tools/bash/runfiles/runfiles.bash" ]]; then + source "${RUNFILES_DIR}/bazel_tools/tools/bash/runfiles/runfiles.bash" +elif [[ -f "${RUNFILES_MANIFEST_FILE:-/dev/null}" ]]; then + source "$(grep -m1 "^bazel_tools/tools/bash/runfiles/runfiles.bash " \ + "$RUNFILES_MANIFEST_FILE" | cut -d ' ' -f 2-)" +else + echo >&2 "ERROR: cannot find @bazel_tools//tools/bash/runfiles:runfiles.bash" + exit 1 +fi +# --- end runfiles.bash initialization --- +""" + +def sh_inline_test(name, script, **kwargs): + """Like sh_test, but instead of srcs takes the shell script + as verbatim bazel string. The bash runfiles are in scope, + using `rlocation` works by default. + """ + script_name = name + ".sh" + script = bash_runfiles_boilerplate + script + + target_from_string(script_name, script) + + deps = kwargs.pop("deps", []) + + native.sh_test( + name = name, + srcs = [script_name], + deps = ["@bazel_tools//tools/bash/runfiles"] + deps, + **kwargs + ) + +python_runfiles_boilerplate = """ +from bazel_tools.tools.python.runfiles import runfiles +r = runfiles.Create() +""" + +def py_inline_test(name, script, **kwargs): + """Like py_test, but instead of srcs takes the shell script + as verbatim bazel string. The python runfiles are in scope + as the `r` variable. Use `r.Rlocation()` + """ + script_name = name + ".py" + script = python_runfiles_boilerplate + script + + target_from_string(script_name, script) + + deps = kwargs.pop("deps", []) + srcs = kwargs.pop("srcs", []) + + native.py_test( + name = name, + srcs = [script_name] + srcs, + main = script_name, + deps = ["@bazel_tools//tools/python/runfiles"] + deps, + **kwargs + ) diff --git a/third_party/bazel/rules_haskell/tests/java_classpath/BUILD.bazel b/third_party/bazel/rules_haskell/tests/java_classpath/BUILD.bazel new file mode 100644 index 000000000000..b2e5b86daeb9 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/java_classpath/BUILD.bazel @@ -0,0 +1,17 @@ +load( + "@io_tweag_rules_haskell//haskell:haskell.bzl", + "haskell_test", +) + +package(default_testonly = 1) + +haskell_test( + name = "java_classpath", + srcs = ["Main.hs"], + visibility = ["//visibility:public"], + deps = [ + "//tests/hackage:base", + "//tests/hackage:template-haskell", + "@org_apache_spark_spark_core_2_10//jar", + ], +) diff --git a/third_party/bazel/rules_haskell/tests/java_classpath/Main.hs b/third_party/bazel/rules_haskell/tests/java_classpath/Main.hs new file mode 100644 index 000000000000..13f7b9d51684 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/java_classpath/Main.hs @@ -0,0 +1,17 @@ +{-# LANGUAGE LambdaCase #-} +{-# LANGUAGE TemplateHaskell #-} +module Main (main) where + +import qualified Language.Haskell.TH as TH (runIO) +import qualified Language.Haskell.TH.Syntax as TH (lift) +import System.Environment (lookupEnv) + +main :: IO () +main = putStrLn $( + let ensureClassPath :: IO String + ensureClassPath = lookupEnv "CLASSPATH" >>= \case + Nothing -> error "CLASSPATH not set when it was expected to be." + Just "" -> error "CLASSPATH empty when it was expected to have content." + Just cpath -> pure $ "java-classpath at compile time: " ++ cpath + in TH.runIO ensureClassPath >>= TH.lift + ) diff --git a/third_party/bazel/rules_haskell/tests/lhs/BUILD.bazel b/third_party/bazel/rules_haskell/tests/lhs/BUILD.bazel new file mode 100644 index 000000000000..e344ee6def1c --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/lhs/BUILD.bazel @@ -0,0 +1,23 @@ +load( + "@io_tweag_rules_haskell//haskell:haskell.bzl", + "haskell_library", + "haskell_test", +) + +package(default_testonly = 1) + +haskell_library( + name = "lhs-lib", + srcs = ["Lib.lhs"], + deps = ["//tests/hackage:base"], +) + +haskell_test( + name = "lhs-bin", + srcs = ["Main.lhs"], + visibility = ["//visibility:public"], + deps = [ + ":lhs-lib", + "//tests/hackage:base", + ], +) diff --git a/third_party/bazel/rules_haskell/tests/lhs/Lib.lhs b/third_party/bazel/rules_haskell/tests/lhs/Lib.lhs new file mode 100644 index 000000000000..f37350df70f7 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/lhs/Lib.lhs @@ -0,0 +1,4 @@ +> module Lib (lib) where + +> lib :: String +> lib = "lhs" diff --git a/third_party/bazel/rules_haskell/tests/lhs/Main.lhs b/third_party/bazel/rules_haskell/tests/lhs/Main.lhs new file mode 100644 index 000000000000..a9e0659dddf5 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/lhs/Main.lhs @@ -0,0 +1,6 @@ +> module Main (main) where + +> import Lib (lib) + +> main :: IO () +> main = putStrLn lib diff --git a/third_party/bazel/rules_haskell/tests/library-deps/BUILD.bazel b/third_party/bazel/rules_haskell/tests/library-deps/BUILD.bazel new file mode 100644 index 000000000000..d6844e1ac120 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/library-deps/BUILD.bazel @@ -0,0 +1,28 @@ +load( + "@io_tweag_rules_haskell//haskell:haskell.bzl", + "haskell_library", + "haskell_test", +) + +package(default_testonly = 1) + +haskell_library( + name = "library-deps", + srcs = ["TestLib.hs"], + visibility = ["//visibility:public"], + deps = [ + "//tests/hackage:base", + "//tests/library-deps/sublib", + ], +) + +haskell_test( + name = "bin-deps", + size = "small", + srcs = ["Bin.hs"], + visibility = ["//visibility:public"], + deps = [ + "//tests/hackage:base", + "//tests/library-deps/sublib", + ], +) diff --git a/third_party/bazel/rules_haskell/tests/library-deps/Bin.hs b/third_party/bazel/rules_haskell/tests/library-deps/Bin.hs new file mode 100644 index 000000000000..8d12d0bdd23f --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/library-deps/Bin.hs @@ -0,0 +1,6 @@ +module Main (main) where + +import TestSubLib (messageEnd) + +main :: IO () +main = putStrLn $ messageEnd diff --git a/third_party/bazel/rules_haskell/tests/library-deps/TestLib.hs b/third_party/bazel/rules_haskell/tests/library-deps/TestLib.hs new file mode 100644 index 000000000000..fe917fecf3b7 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/library-deps/TestLib.hs @@ -0,0 +1,9 @@ +module TestLib (testMessage) where + +import TestSubLib (messageEnd) + +testMessage :: String +testMessage = "hello " ++ messageEnd + +-- Force dynamic linking +{-# ANN testMessage () #-} diff --git a/third_party/bazel/rules_haskell/tests/library-deps/sublib/BUILD.bazel b/third_party/bazel/rules_haskell/tests/library-deps/sublib/BUILD.bazel new file mode 100644 index 000000000000..5f3028e2e02c --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/library-deps/sublib/BUILD.bazel @@ -0,0 +1,21 @@ +load( + "@io_tweag_rules_haskell//haskell:haskell.bzl", + "haskell_library", +) + +package(default_testonly = 1) + +haskell_library( + name = "sublib", + srcs = ["TestSubLib.hs"], + visibility = ["//visibility:public"], + deps = [ + ":sublib-c", + "//tests/hackage:base", + ], +) + +cc_library( + name = "sublib-c", + srcs = ["sublib-c.c"], +) diff --git a/third_party/bazel/rules_haskell/tests/library-deps/sublib/TestSubLib.hs b/third_party/bazel/rules_haskell/tests/library-deps/sublib/TestSubLib.hs new file mode 100644 index 000000000000..1e8d2d475552 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/library-deps/sublib/TestSubLib.hs @@ -0,0 +1,7 @@ +{-# LANGUAGE ForeignFunctionInterface #-} +module TestSubLib (messageEnd) where + +messageEnd :: String +messageEnd = "world " ++ show (foo 10) + +foreign import ccall foo :: Int -> Int diff --git a/third_party/bazel/rules_haskell/tests/library-deps/sublib/sublib-c.c b/third_party/bazel/rules_haskell/tests/library-deps/sublib/sublib-c.c new file mode 100644 index 000000000000..2f3be3eb9ed7 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/library-deps/sublib/sublib-c.c @@ -0,0 +1,3 @@ +int foo(int x) { + return x * 2; +} diff --git a/third_party/bazel/rules_haskell/tests/library-exports/BUILD.bazel b/third_party/bazel/rules_haskell/tests/library-exports/BUILD.bazel new file mode 100644 index 000000000000..c88e68ebbee4 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/library-exports/BUILD.bazel @@ -0,0 +1,41 @@ +load( + "@io_tweag_rules_haskell//haskell:haskell.bzl", + "haskell_library", + "haskell_test", +) + +package(default_testonly = 1) + +haskell_library( + name = "sublib", + srcs = ["TestSubLib.hs"], + exports = {"//tests/hackage:containers": "Data.Map as SubLib.Map"}, + deps = [ + "//tests/hackage:base", + "//tests/hackage:containers", + ], +) + +haskell_library( + name = "lib", + srcs = ["TestLib.hs"], + exports = { + ":sublib": "TestSubLib", + "//tests/hackage:containers": "Data.Map as Lib.Map", + }, + deps = [ + ":sublib", + "//tests/hackage:base", + ], +) + +haskell_test( + name = "library-exports", + size = "small", + srcs = ["Bin.hs"], + visibility = ["//visibility:public"], + deps = [ + ":lib", + "//tests/hackage:base", + ], +) diff --git a/third_party/bazel/rules_haskell/tests/library-exports/Bin.hs b/third_party/bazel/rules_haskell/tests/library-exports/Bin.hs new file mode 100644 index 000000000000..b724bb89d1c2 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/library-exports/Bin.hs @@ -0,0 +1,7 @@ +module Main (main) where + +import TestSubLib (messageEnd) +import Lib.Map + +main :: IO () +main = print $ Lib.Map.singleton 1 messageEnd diff --git a/third_party/bazel/rules_haskell/tests/library-exports/TestLib.hs b/third_party/bazel/rules_haskell/tests/library-exports/TestLib.hs new file mode 100644 index 000000000000..c889c2cc31ac --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/library-exports/TestLib.hs @@ -0,0 +1,7 @@ +module TestLib (testMessage) where + +import TestSubLib (messageEnd) +import SubLib.Map + +testMessage :: String +testMessage = "hello " ++ messageEnd diff --git a/third_party/bazel/rules_haskell/tests/library-exports/TestSubLib.hs b/third_party/bazel/rules_haskell/tests/library-exports/TestSubLib.hs new file mode 100644 index 000000000000..2e1f3f983f40 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/library-exports/TestSubLib.hs @@ -0,0 +1,5 @@ +{-# LANGUAGE ForeignFunctionInterface #-} +module TestSubLib (messageEnd) where + +messageEnd :: String +messageEnd = "world" diff --git a/third_party/bazel/rules_haskell/tests/library-linkstatic-flag/BUILD.bazel b/third_party/bazel/rules_haskell/tests/library-linkstatic-flag/BUILD.bazel new file mode 100644 index 000000000000..0b7cae3d7a65 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/library-linkstatic-flag/BUILD.bazel @@ -0,0 +1,112 @@ +load( + "@io_tweag_rules_haskell//haskell:haskell.bzl", + "haskell_library", +) +load("//tests:inline_tests.bzl", "sh_inline_test") +load(":get_library_files.bzl", "get_libraries_as_runfiles") + +# test whether `linkstatic` works as expected +package(default_testonly = 1) + +# only .a files +haskell_library( + name = "library-static-only", + srcs = ["Lib.hs"], + linkstatic = True, # <-- + visibility = ["//visibility:public"], + deps = [ + "//tests/hackage:base", + "//tests/hackage:bytestring", + ], +) + +# both .a and .so files +haskell_library( + name = "library-static-and-dynamic", + srcs = ["Lib.hs"], + linkstatic = False, # <-- + visibility = ["//visibility:public"], + deps = [ + "//tests/hackage:base", + "//tests/hackage:bytestring", + ], +) + +# extract all libraries from the haskell_library +get_libraries_as_runfiles( + name = "library-static-only-libraries", + library = ":library-static-only", +) + +get_libraries_as_runfiles( + name = "library-static-and-dynamic-libraries", + library = ":library-static-and-dynamic", +) + +# sh_test’s `data` doesn’t add stuff to runfiles :( +# sh_library can bundle different targets as runfiles for sh_test +# TODO(Profpatsch): add functionality to sh_inline_test by default? +sh_library( + name = "bundled-dependency-files-static-only", + data = [":library-static-only-libraries"], +) + +sh_library( + name = "bundled-dependency-files-static-and-dynamic", + data = [":library-static-and-dynamic-libraries"], +) + +# ensure that linkstatic=True only creates only .a, no .so +sh_inline_test( + name = "library-linkstatic-flag", + size = "small", + # pass the file names as arguments + args = ["$(rootpaths :library-static-only-libraries)"], + data = [ + # for rootpaths + ":library-static-only-libraries", + # to actually get the files … + ":bundled-dependency-files-static-only", + ], + script = """ +set -euo pipefail +for f in "$@"; do + if ! [[ "$f" =~ .a$ ]]; then + echo "not a static library: $f" + exit 1 + fi +done +""", +) + +# test whether .so is linked dynamically and .a statically +sh_inline_test( + name = "test-libraries-static-and-dynamic", + size = "small", + # pass the file names as arguments + args = ["$(rootpaths :library-static-and-dynamic-libraries)"], + data = [ + # for rootpaths + ":library-static-and-dynamic-libraries", + # to actually get the files … + ":bundled-dependency-files-static-and-dynamic", + ], + script = """ +set -euo pipefail +is_dynamic () { + # taken from https://github.com/NixOS/nixpkgs/blob/0b3f50f844e2a6b507b18d7c5259bb850b382f87/pkgs/build-support/setup-hooks/auto-patchelf.sh#L167-L170 + readelf -l -- "$1" | grep -q "^ *INTERP\\>" +} + +for f in "$@"; do + if [[ "$f" =~ .a$ ]] && is_dynamic "$f"; then + echo "should be a static executable: $f" + exit 1 + fi + if [[ "$f" =~ .so$ ]] && ! is_dynamic "$f"; then + echo "should be a dynamic executable: $f" + exit 1 + fi +done +""", +) diff --git a/third_party/bazel/rules_haskell/tests/library-linkstatic-flag/Lib.hs b/third_party/bazel/rules_haskell/tests/library-linkstatic-flag/Lib.hs new file mode 100644 index 000000000000..66a2161a19c4 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/library-linkstatic-flag/Lib.hs @@ -0,0 +1,5 @@ +module Lib (message) where + +import qualified Data.ByteString.Char8 as B + +message = B.pack "hello, world" diff --git a/third_party/bazel/rules_haskell/tests/library-linkstatic-flag/Main.hs b/third_party/bazel/rules_haskell/tests/library-linkstatic-flag/Main.hs new file mode 100644 index 000000000000..2048dbdecd9a --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/library-linkstatic-flag/Main.hs @@ -0,0 +1,3 @@ +module Main where + +main = putStrLn "hello world" diff --git a/third_party/bazel/rules_haskell/tests/library-linkstatic-flag/get_library_files.bzl b/third_party/bazel/rules_haskell/tests/library-linkstatic-flag/get_library_files.bzl new file mode 100644 index 000000000000..31702bfcfa07 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/library-linkstatic-flag/get_library_files.bzl @@ -0,0 +1,28 @@ +load( + "@io_tweag_rules_haskell//haskell:providers.bzl", + "HaskellInfo", + "HaskellLibraryInfo", +) +load("//haskell:private/set.bzl", "set") + +def _get_libraries_as_runfiles_impl(ctx): + """Extract all library files from a haskell_library target + and put them in this target’s files""" + bi = ctx.attr.library[HaskellInfo] + return [DefaultInfo( + # not necessarily complete + files = depset( + direct = bi.static_libraries, + transitive = [set.to_depset(bi.dynamic_libraries)], + ), + )] + +get_libraries_as_runfiles = rule( + _get_libraries_as_runfiles_impl, + attrs = { + "library": attr.label( + mandatory = True, + providers = [HaskellInfo, HaskellLibraryInfo], + ), + }, +) diff --git a/third_party/bazel/rules_haskell/tests/library-with-cbits/AddOne.hsc b/third_party/bazel/rules_haskell/tests/library-with-cbits/AddOne.hsc new file mode 100644 index 000000000000..b4c446d412c7 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/library-with-cbits/AddOne.hsc @@ -0,0 +1,3 @@ +module AddOne where + +foreign import ccall "c_add_one" addOne :: Int -> Int diff --git a/third_party/bazel/rules_haskell/tests/library-with-cbits/AddOne2.hs b/third_party/bazel/rules_haskell/tests/library-with-cbits/AddOne2.hs new file mode 100644 index 000000000000..f2088f1c6600 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/library-with-cbits/AddOne2.hs @@ -0,0 +1,7 @@ +module AddOne2 + ( addOne2 + ) where + +import AddOne + +addOne2 = addOne diff --git a/third_party/bazel/rules_haskell/tests/library-with-cbits/BUILD.bazel b/third_party/bazel/rules_haskell/tests/library-with-cbits/BUILD.bazel new file mode 100644 index 000000000000..c320502ebf3f --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/library-with-cbits/BUILD.bazel @@ -0,0 +1,36 @@ +load( + "@io_tweag_rules_haskell//haskell:haskell.bzl", + "haskell_library", + "haskell_toolchain_library", +) + +haskell_library( + name = "library-with-cbits", + srcs = ["AddOne.hsc"], + linkstatic = False, + visibility = ["//visibility:public"], + deps = [ + "//tests/data:ourclibrary", + "//tests/hackage:base", + ], +) + +haskell_library( + name = "library-with-cbits-indirect", + srcs = ["AddOne2.hs"], + visibility = ["//visibility:public"], + deps = [ + ":library-with-cbits", + "//tests/hackage:base", + ], +) + +haskell_library( + name = "library-with-cbits-static", + srcs = ["AddOne.hsc"], + visibility = ["//visibility:public"], + deps = [ + "//tests/data:ourclibrary-static", + "//tests/hackage:base", + ], +) diff --git a/third_party/bazel/rules_haskell/tests/library-with-includes/BUILD.bazel b/third_party/bazel/rules_haskell/tests/library-with-includes/BUILD.bazel new file mode 100644 index 000000000000..37b5a2ee986e --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/library-with-includes/BUILD.bazel @@ -0,0 +1,29 @@ +load( + "@io_tweag_rules_haskell//haskell:haskell.bzl", + "haskell_library", +) + +package(default_testonly = 1) + +genrule( + name = "gen-a", + outs = ["a.h"], + cmd = "echo '#define A 42' >> $@", +) + +cc_library( + name = "clib", + hdrs = [ + "b.h", + ":gen-a", + ], +) + +haskell_library( + name = "library-with-includes", + srcs = ["Lib.hs"], + deps = [ + ":clib", + "//tests/hackage:base", + ], +) diff --git a/third_party/bazel/rules_haskell/tests/library-with-includes/Lib.hs b/third_party/bazel/rules_haskell/tests/library-with-includes/Lib.hs new file mode 100644 index 000000000000..1ca98d615c4a --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/library-with-includes/Lib.hs @@ -0,0 +1,8 @@ +{-# LANGUAGE CPP #-} +module Lib (x) where + +#include "tests/library-with-includes/a.h" +#include "tests/library-with-includes/b.h" + +x :: Int +x = A + B diff --git a/third_party/bazel/rules_haskell/tests/library-with-includes/b.h b/third_party/bazel/rules_haskell/tests/library-with-includes/b.h new file mode 100644 index 000000000000..3425137bf9cf --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/library-with-includes/b.h @@ -0,0 +1 @@ +#define B 17 diff --git a/third_party/bazel/rules_haskell/tests/library-with-sysdeps/BUILD.bazel b/third_party/bazel/rules_haskell/tests/library-with-sysdeps/BUILD.bazel new file mode 100644 index 000000000000..0e34f688fd69 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/library-with-sysdeps/BUILD.bazel @@ -0,0 +1,32 @@ +load( + "@io_tweag_rules_haskell//haskell:haskell.bzl", + "haskell_library", + "haskell_test", +) + +package(default_testonly = 1) + +haskell_library( + name = "library-with-sysdeps", + srcs = ["Lib.hs"], + tags = ["requires_zlib"], + visibility = ["//visibility:public"], + deps = [ + "//tests/hackage:base", + "@zlib", + ], +) + +haskell_test( + name = "bin", + srcs = ["Main.hs"], + expected_covered_expressions_percentage = 100, + tags = [ + "coverage-compatible", + "requires_zlib", + ], + deps = [ + ":library-with-sysdeps", + "//tests/hackage:base", + ], +) diff --git a/third_party/bazel/rules_haskell/tests/library-with-sysdeps/Lib.hs b/third_party/bazel/rules_haskell/tests/library-with-sysdeps/Lib.hs new file mode 100644 index 000000000000..771dd7faf10f --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/library-with-sysdeps/Lib.hs @@ -0,0 +1,8 @@ +module Lib (crc) where + +import Foreign.Ptr +import Foreign.C.Types + +foreign import ccall crc32 :: CLong -> Ptr () -> CInt -> IO () + +crc = crc32 0 nullPtr 0 diff --git a/third_party/bazel/rules_haskell/tests/library-with-sysdeps/Main.hs b/third_party/bazel/rules_haskell/tests/library-with-sysdeps/Main.hs new file mode 100644 index 000000000000..b892de88c4a7 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/library-with-sysdeps/Main.hs @@ -0,0 +1,5 @@ +module Main where + +import Lib (crc) + +main = crc diff --git a/third_party/bazel/rules_haskell/tests/library-with-sysincludes/BUILD.bazel b/third_party/bazel/rules_haskell/tests/library-with-sysincludes/BUILD.bazel new file mode 100644 index 000000000000..ddd5de65198c --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/library-with-sysincludes/BUILD.bazel @@ -0,0 +1,86 @@ +load( + "@io_tweag_rules_haskell//haskell:haskell.bzl", + "haskell_library", +) + +package(default_testonly = 1) + +genrule( + name = "genrule-header", + outs = [ + "include/foo.h", + ], + cmd = "touch $(location include/foo.h)", +) + +# A locally-defined replica of @zlib.dev//:zlib. +# Since that shared library lives in another package, we must +# use an absolute path for strip_include_prefix. +cc_library( + name = "zlib", + hdrs = ["@zlib.dev//:include"], + strip_include_prefix = "/external/zlib.dev/include", + tags = ["requires_zlib"], + deps = ["@zlib"], +) + +cc_library( + name = "zlib-with-genrule-header", + hdrs = [":genrule-header"], + strip_include_prefix = "include", + tags = ["requires_zlib"], +) + +haskell_library( + name = "intermediate-library", + srcs = ["IntLib.hsc"], + tags = ["requires_zlib"], + deps = [ + ":zlib", + ":zlib-with-genrule-header", + "//tests/hackage:base", + ], +) + +haskell_library( + name = "library-with-sysincludes", + srcs = [ + "Lib.hs", + "TH.hs", + ], + tags = ["requires_zlib"], + visibility = ["//visibility:public"], + deps = [ + ":intermediate-library", + "//tests/hackage:base", + "//tests/hackage:template-haskell", + ], +) + +# Replicate the above example, but use the externally-defined +# cc_library rule. +haskell_library( + name = "intermediate-library-other", + srcs = ["IntLib.hsc"], + tags = ["requires_zlib"], + deps = [ + ":zlib-with-genrule-header", + "//tests/hackage:base", + "@zlib.dev//:zlib", + ], +) + +haskell_library( + name = "library-with-sysincludes-other", + srcs = [ + "Lib.hs", + "TH.hs", + ], + tags = ["requires_zlib"], + visibility = ["//visibility:public"], + deps = [ + ":intermediate-library-other", + "//tests/hackage:base", + "//tests/hackage:template-haskell", + ], +) diff --git a/third_party/bazel/rules_haskell/tests/library-with-sysincludes/IntLib.hsc b/third_party/bazel/rules_haskell/tests/library-with-sysincludes/IntLib.hsc new file mode 100644 index 000000000000..cf31e3d9a844 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/library-with-sysincludes/IntLib.hsc @@ -0,0 +1,15 @@ +{-# LANGUAGE CPP #-} + +module IntLib (crc) where + +import Foreign.Ptr +import Foreign.C.Types + +#include <zlib.h> +#include "foo.h" + +foreign import ccall crc32 :: CLong -> Ptr () -> CInt -> IO () + +crc = crc32 0 nullPtr 0 + +z = #{size struct gz_header_s} diff --git a/third_party/bazel/rules_haskell/tests/library-with-sysincludes/Lib.hs b/third_party/bazel/rules_haskell/tests/library-with-sysincludes/Lib.hs new file mode 100644 index 000000000000..55b1860fdddd --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/library-with-sysincludes/Lib.hs @@ -0,0 +1,8 @@ +{-# LANGUAGE TemplateHaskell #-} + +module Lib (bar) where + +import TH (foo) + +bar :: IO () +bar = $foo diff --git a/third_party/bazel/rules_haskell/tests/library-with-sysincludes/TH.hs b/third_party/bazel/rules_haskell/tests/library-with-sysincludes/TH.hs new file mode 100644 index 000000000000..45929ec84040 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/library-with-sysincludes/TH.hs @@ -0,0 +1,9 @@ +{-# LANGUAGE TemplateHaskell #-} + +module TH (foo) where + +import IntLib (crc) +import Language.Haskell.TH + +foo :: Q Exp +foo = [| crc |] diff --git a/third_party/bazel/rules_haskell/tests/multi_repl/BUILD.bazel b/third_party/bazel/rules_haskell/tests/multi_repl/BUILD.bazel new file mode 100644 index 000000000000..b2edce37ab0f --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/multi_repl/BUILD.bazel @@ -0,0 +1,16 @@ +load( + "@io_tweag_rules_haskell//haskell:haskell.bzl", + "haskell_repl", +) + +haskell_repl( + name = "c_only_repl", + # To only load :c by source. + experimental_from_source = ["//tests/multi_repl/bc:c"], + deps = ["//tests/multi_repl/bc:c"], +) + +haskell_repl( + name = "c_multi_repl", + deps = ["//tests/multi_repl/bc:c"], +) diff --git a/third_party/bazel/rules_haskell/tests/multi_repl/a/BUILD.bazel b/third_party/bazel/rules_haskell/tests/multi_repl/a/BUILD.bazel new file mode 100644 index 000000000000..7d17e834a9cd --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/multi_repl/a/BUILD.bazel @@ -0,0 +1,17 @@ +package(default_visibility = ["//visibility:public"]) + +load( + "@io_tweag_rules_haskell//haskell:haskell.bzl", + "haskell_library", +) + +haskell_library( + name = "a", + srcs = [ + "src/A/A.hs", + ], + src_strip_prefix = "src", + deps = [ + "//tests/hackage:base", + ], +) diff --git a/third_party/bazel/rules_haskell/tests/multi_repl/a/src/A/A.hs b/third_party/bazel/rules_haskell/tests/multi_repl/a/src/A/A.hs new file mode 100644 index 000000000000..92eb0e60759a --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/multi_repl/a/src/A/A.hs @@ -0,0 +1,4 @@ +module A.A ( a ) where + +a :: () +a = () diff --git a/third_party/bazel/rules_haskell/tests/multi_repl/bc/BUILD.bazel b/third_party/bazel/rules_haskell/tests/multi_repl/bc/BUILD.bazel new file mode 100644 index 000000000000..98372a4a1925 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/multi_repl/bc/BUILD.bazel @@ -0,0 +1,30 @@ +package(default_visibility = ["//visibility:public"]) + +load( + "@io_tweag_rules_haskell//haskell:haskell.bzl", + "haskell_library", +) + +haskell_library( + name = "b", + srcs = [ + "src/BC/B.hs", + ], + src_strip_prefix = "src", + deps = [ + "//tests/hackage:base", + "//tests/multi_repl/a", + ], +) + +haskell_library( + name = "c", + srcs = [ + "src/BC/C.hs", + ], + src_strip_prefix = "src", + deps = [ + ":b", + "//tests/hackage:base", + ], +) diff --git a/third_party/bazel/rules_haskell/tests/multi_repl/bc/src/BC/B.hs b/third_party/bazel/rules_haskell/tests/multi_repl/bc/src/BC/B.hs new file mode 100644 index 000000000000..b86223c41ea7 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/multi_repl/bc/src/BC/B.hs @@ -0,0 +1,6 @@ +module BC.B ( b ) where + +import A.A ( a ) + +b :: () +b = a diff --git a/third_party/bazel/rules_haskell/tests/multi_repl/bc/src/BC/C.hs b/third_party/bazel/rules_haskell/tests/multi_repl/bc/src/BC/C.hs new file mode 100644 index 000000000000..6e6f31f0c80a --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/multi_repl/bc/src/BC/C.hs @@ -0,0 +1,6 @@ +module BC.C ( c ) where + +import BC.B ( b ) + +c :: () +c = b diff --git a/third_party/bazel/rules_haskell/tests/package-id-clash-binary/BUILD.bazel b/third_party/bazel/rules_haskell/tests/package-id-clash-binary/BUILD.bazel new file mode 100644 index 000000000000..d64a8909c5f5 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/package-id-clash-binary/BUILD.bazel @@ -0,0 +1,15 @@ +load( + "@io_tweag_rules_haskell//haskell:haskell.bzl", + "haskell_test", + "haskell_toolchain_library", +) + +haskell_test( + name = "bin", + srcs = ["Main.hs"], + deps = [ + "//tests/hackage:base", + "//tests/package-id-clash-binary/a:foo", + "//tests/package-id-clash-binary/b:foo", + ], +) diff --git a/third_party/bazel/rules_haskell/tests/package-id-clash-binary/Main.hs b/third_party/bazel/rules_haskell/tests/package-id-clash-binary/Main.hs new file mode 100644 index 000000000000..0c341e6f47d2 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/package-id-clash-binary/Main.hs @@ -0,0 +1,6 @@ +module Main where + +import Foo +import Baz + +main = print $ x + y diff --git a/third_party/bazel/rules_haskell/tests/package-id-clash-binary/a/BUILD.bazel b/third_party/bazel/rules_haskell/tests/package-id-clash-binary/a/BUILD.bazel new file mode 100644 index 000000000000..02c3a6b36d3f --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/package-id-clash-binary/a/BUILD.bazel @@ -0,0 +1,12 @@ +load( + "@io_tweag_rules_haskell//haskell:haskell.bzl", + "haskell_library", + "haskell_toolchain_library", +) + +haskell_library( + name = "foo", + srcs = ["Foo.hs"], + visibility = ["//visibility:public"], + deps = ["//tests/hackage:base"], +) diff --git a/third_party/bazel/rules_haskell/tests/package-id-clash-binary/a/Foo.hs b/third_party/bazel/rules_haskell/tests/package-id-clash-binary/a/Foo.hs new file mode 100644 index 000000000000..ecac0701a07d --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/package-id-clash-binary/a/Foo.hs @@ -0,0 +1,3 @@ +module Foo where + +x = 2 diff --git a/third_party/bazel/rules_haskell/tests/package-id-clash-binary/b/BUILD.bazel b/third_party/bazel/rules_haskell/tests/package-id-clash-binary/b/BUILD.bazel new file mode 100644 index 000000000000..4bf734af5dd1 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/package-id-clash-binary/b/BUILD.bazel @@ -0,0 +1,12 @@ +load( + "@io_tweag_rules_haskell//haskell:haskell.bzl", + "haskell_library", + "haskell_toolchain_library", +) + +haskell_library( + name = "foo", + srcs = ["Baz.hs"], + visibility = ["//visibility:public"], + deps = ["//tests/hackage:base"], +) diff --git a/third_party/bazel/rules_haskell/tests/package-id-clash-binary/b/Baz.hs b/third_party/bazel/rules_haskell/tests/package-id-clash-binary/b/Baz.hs new file mode 100644 index 000000000000..3159fda6b00a --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/package-id-clash-binary/b/Baz.hs @@ -0,0 +1,3 @@ +module Baz where + +y = 2 diff --git a/third_party/bazel/rules_haskell/tests/package-id-clash/BUILD.bazel b/third_party/bazel/rules_haskell/tests/package-id-clash/BUILD.bazel new file mode 100644 index 000000000000..9c1b91cf9b83 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/package-id-clash/BUILD.bazel @@ -0,0 +1,24 @@ +load( + "@io_tweag_rules_haskell//haskell:haskell.bzl", + "haskell_library", +) + +package(default_testonly = 1) + +haskell_library( + name = "sublib", + srcs = ["Foo.hs"], + visibility = ["//visibility:public"], + deps = ["//tests/hackage:base"], +) + +haskell_library( + name = "lib", + srcs = ["Baz.hs"], + visibility = ["//visibility:public"], + deps = [ + ":sublib", + "//tests/hackage:base", + "//tests/package-id-clash/sublib", + ], +) diff --git a/third_party/bazel/rules_haskell/tests/package-id-clash/Baz.hs b/third_party/bazel/rules_haskell/tests/package-id-clash/Baz.hs new file mode 100644 index 000000000000..718a2dd99241 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/package-id-clash/Baz.hs @@ -0,0 +1,7 @@ +module Baz (baz) where + +import Foo (foo) +import Bar (bar) + +baz :: Int +baz = foo + bar diff --git a/third_party/bazel/rules_haskell/tests/package-id-clash/Foo.hs b/third_party/bazel/rules_haskell/tests/package-id-clash/Foo.hs new file mode 100644 index 000000000000..f325b2efcfbb --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/package-id-clash/Foo.hs @@ -0,0 +1,4 @@ +module Foo (foo) where + +foo :: Int +foo = 5 diff --git a/third_party/bazel/rules_haskell/tests/package-id-clash/sublib/BUILD.bazel b/third_party/bazel/rules_haskell/tests/package-id-clash/sublib/BUILD.bazel new file mode 100644 index 000000000000..e5d277c2a254 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/package-id-clash/sublib/BUILD.bazel @@ -0,0 +1,13 @@ +load( + "@io_tweag_rules_haskell//haskell:haskell.bzl", + "haskell_library", +) + +package(default_testonly = 1) + +haskell_library( + name = "sublib", + srcs = ["Bar.hs"], + visibility = ["//visibility:public"], + deps = ["//tests/hackage:base"], +) diff --git a/third_party/bazel/rules_haskell/tests/package-id-clash/sublib/Bar.hs b/third_party/bazel/rules_haskell/tests/package-id-clash/sublib/Bar.hs new file mode 100644 index 000000000000..6fbd9711f58b --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/package-id-clash/sublib/Bar.hs @@ -0,0 +1,4 @@ +module Bar (bar) where + +bar :: Int +bar = 6 diff --git a/third_party/bazel/rules_haskell/tests/package-name/BUILD.bazel b/third_party/bazel/rules_haskell/tests/package-name/BUILD.bazel new file mode 100644 index 000000000000..9d187f083636 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/package-name/BUILD.bazel @@ -0,0 +1,28 @@ +load( + "@io_tweag_rules_haskell//haskell:haskell.bzl", + "haskell_library", + "haskell_test", +) + +# Tests around our use of package names. +package(default_testonly = 1) + +haskell_library( + # The character "Z" should be untouched in the GHC package name. + # However, underscores (which are not legal) should be turned into dashes. + name = "lib-a_Z", + srcs = ["Lib.hs"], + version = "1.2.3.4", + deps = ["//tests/hackage:base"], +) + +haskell_test( + name = "bin", + size = "small", + srcs = ["Main.hs"], + version = "0.0.0", # This flags triggers the `MIN_VERSION` macro generation + deps = [ + ":lib-a_Z", + "//tests/hackage:base", + ], +) diff --git a/third_party/bazel/rules_haskell/tests/package-name/Lib.hs b/third_party/bazel/rules_haskell/tests/package-name/Lib.hs new file mode 100644 index 000000000000..e5e06b414ba0 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/package-name/Lib.hs @@ -0,0 +1,8 @@ +{-# LANGUAGE CPP #-} +module Lib (foo, libPackageKey) where + +foo :: Integer +foo = 42 + +libPackageKey :: String +libPackageKey = CURRENT_PACKAGE_KEY diff --git a/third_party/bazel/rules_haskell/tests/package-name/Main.hs b/third_party/bazel/rules_haskell/tests/package-name/Main.hs new file mode 100644 index 000000000000..b1e73dcbf716 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/package-name/Main.hs @@ -0,0 +1,33 @@ +{-# LANGUAGE CPP #-} +{-# LANGUAGE PackageImports #-} +module Main (main) where + +import Control.Monad (when) + +-- Test the PackageImports extension. +import "lib-a-Z" Lib + +-- Test macros that GHC creates automatically based on the package version. +versionHighEnoughTest, versionTooLowTest :: Bool +#if MIN_VERSION_lib_a_Z(1,2,3) +versionHighEnoughTest = True +#else +versionHighEnoughTest = False +#endif + +#if MIN_VERSION_lib_a_Z(1,2,4) +versionTooLowTest = False +#else +versionTooLowTest = True +#endif + +check :: (Show a, Eq a) => a -> a -> IO () +check x y = when (x /= y) $ error $ "Failed check: " ++ show (x, y) + +main :: IO () +main = do + check foo 42 + check VERSION_lib_a_Z "1.2.3.4" + check libPackageKey "testsZSpackage-nameZSlib-a-ZZ" + check versionHighEnoughTest True + check versionTooLowTest True diff --git a/third_party/bazel/rules_haskell/tests/repl-flags/BUILD.bazel b/third_party/bazel/rules_haskell/tests/repl-flags/BUILD.bazel new file mode 100644 index 000000000000..8fd099dc4d12 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/repl-flags/BUILD.bazel @@ -0,0 +1,45 @@ +load("@io_tweag_rules_haskell//haskell:haskell.bzl", "haskell_test") + +package(default_testonly = 1) + +# This test the `compiler` flags in many ways: +# - the test needs to be built with `-DTESTS_TOOLCHAIN_COMPILER_FLAGS`, provided by the toolchain attribute `compiler_flags` +# - the test needs `-XOverloadedStrings`, provided by this rule `compiler_flags` +# - toolchain and rule `compiler_flags` are additive, else one of the previous test will fail +# - the ordering is as such as rule flags are more important that toolchain flags + +# This rule must build correctly (using `bazel build`), but also as a repl (using `bazel run //tests/repl-flags:compiler_flags@repl`) +haskell_test( + name = "compiler_flags", + srcs = ["CompilerFlags.hs"], + + # This also ensure that local `compiler_flags` does not override the `global ones` + compiler_flags = ["-XOverloadedStrings"], + visibility = ["//visibility:public"], + deps = [ + "//tests/hackage:base", + "//tests/hackage:bytestring", + ], +) + +# This test the `repl_ghci_args` flags in a similar way +# - the test needs to be built with `-DTESTS_TOOLCHAIN_REPL_FLAGS`, provided by the toolchain attribute `compiler_flags` +# - the test needs `-XOverloadedStrings`, provided by toolchain `repl_ghci_args` +# - toolchain and rule `compiler_flags` are additive, else one of the previous test will fail +# - the ordering is as such as rule flags are more important that +# toolchain flags and that repl flags are more important that +# copmiler flags + +# This rule must build correctly (using `bazel build`), but also as a repl (using `bazel run //tests/repl-flags:compiler_flags@repl`). The final result between the repl and the binary must be different +haskell_test( + name = "repl_flags", + srcs = ["ReplFlags.hs"], + + # This also ensure that local `repl_flags` does not override the `global ones` + repl_ghci_args = ["-DTESTS_TOOLCHAIN_REPL_FLAGS"], + visibility = ["//visibility:public"], + deps = [ + "//tests/hackage:base", + "//tests/hackage:bytestring", + ], +) diff --git a/third_party/bazel/rules_haskell/tests/repl-flags/CompilerFlags.hs b/third_party/bazel/rules_haskell/tests/repl-flags/CompilerFlags.hs new file mode 100644 index 000000000000..5470fe11b57c --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/repl-flags/CompilerFlags.hs @@ -0,0 +1,10 @@ +{-# LANGUAGE CPP #-} + +module Main where + +import Data.ByteString + +#ifdef TESTS_TOOLCHAIN_COMPILER_FLAGS +main = print ("hello" :: ByteString) +#endif + diff --git a/third_party/bazel/rules_haskell/tests/repl-flags/ReplFlags.hs b/third_party/bazel/rules_haskell/tests/repl-flags/ReplFlags.hs new file mode 100644 index 000000000000..137ec93a72f4 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/repl-flags/ReplFlags.hs @@ -0,0 +1,17 @@ +{-# LANGUAGE CPP #-} +module Main where + +import Data.ByteString + +-- Ensure that `compiler-flags` are correctly set +#ifdef TESTS_TOOLCHAIN_COMPILER_FLAGS +main = print "hello" +#endif + +-- Ensure that `repl_ghci_args` are correctly set +-- OverloadedString is passed by toolchain +-- The CPP constant is unset by toolchain and set by rule, so ordering must be ensured +#ifdef TESTS_TOOLCHAIN_REPL_FLAGS +foo = ("world" :: ByteString) +#endif + diff --git a/third_party/bazel/rules_haskell/tests/repl-name-conflicts/BUILD.bazel b/third_party/bazel/rules_haskell/tests/repl-name-conflicts/BUILD.bazel new file mode 100644 index 000000000000..ea2366cf3e08 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/repl-name-conflicts/BUILD.bazel @@ -0,0 +1,15 @@ +load("@io_tweag_rules_haskell//haskell:haskell.bzl", "haskell_library") + +package(default_testonly = 1) + +# The module in this library hides a lot of identifiers from Prelude and other +# modules used in the repl init script. +# This shouldn't break the @repl target +haskell_library( + name = "lib", + srcs = ["PreludeShadowing.hs"], + deps = [ + "//tests/hackage:base", + "//tests/hackage:bytestring", + ], +) diff --git a/third_party/bazel/rules_haskell/tests/repl-name-conflicts/PreludeShadowing.hs b/third_party/bazel/rules_haskell/tests/repl-name-conflicts/PreludeShadowing.hs new file mode 100644 index 000000000000..02ecd02684ba --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/repl-name-conflicts/PreludeShadowing.hs @@ -0,0 +1,12 @@ +{-# LANGUAGE NoImplicitPrelude #-} +{-# LANGUAGE OverloadedStrings #-} + +module PreludeShadowing where + +import Data.ByteString + +(>>=) :: ByteString -> ByteString -> ByteString +_ >>= _ = "blah" + +stdin :: ByteString +stdin = "stdin" diff --git a/third_party/bazel/rules_haskell/tests/repl-targets/BUILD.bazel b/third_party/bazel/rules_haskell/tests/repl-targets/BUILD.bazel new file mode 100644 index 000000000000..2fd78bfd6621 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/repl-targets/BUILD.bazel @@ -0,0 +1,81 @@ +load("@io_tweag_rules_haskell//haskell:c2hs.bzl", "c2hs_library") +load( + "@io_tweag_rules_haskell//haskell:haskell.bzl", + "haskell_library", + "haskell_test", +) + +package(default_testonly = 1) + +genrule( + name = "codegen", + outs = [ + "Gen.hs", + ], + cmd = """ + echo "module Gen (gen) where" >> $(location :Gen.hs) + echo "gen :: String" >> $(location :Gen.hs) + echo "gen = \\"gen\\"" >> $(location :Gen.hs) +""", +) + +c2hs_library( + name = "chs", + srcs = ["Chs.chs"], + tags = ["requires_c2hs"], +) + +haskell_library( + name = "hs-lib", + srcs = [ + "Foo.hs", + "Hsc.hsc", + ":chs", + ":codegen", + ], + tags = [ + "requires_hackage", + "requires_zlib", + ], + visibility = ["//visibility:public"], + deps = [ + "//tests/data:ourclibrary", + "//tests/hackage:array", + "//tests/hackage:base", + "@zlib", + ], +) + +haskell_library( + name = "hs-lib-bad", + srcs = [ + "Bad.hs", + ], + tags = [ + "manual", + "requires_zlib", + ], + visibility = ["//visibility:public"], + deps = [ + "//tests/data:ourclibrary", + "//tests/hackage:base", + "@hackage//:array", + "@zlib", + ], +) + +haskell_library( + name = "QuuxLib", + srcs = ["QuuxLib.hs"], + deps = ["//tests/hackage:base"], +) + +haskell_test( + name = "hs-bin", + srcs = ["Quux.hs"], + visibility = ["//visibility:public"], + deps = [ + ":QuuxLib", + "//tests/hackage:base", + ], +) diff --git a/third_party/bazel/rules_haskell/tests/repl-targets/Bad.hs b/third_party/bazel/rules_haskell/tests/repl-targets/Bad.hs new file mode 100644 index 000000000000..2889be2ba757 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/repl-targets/Bad.hs @@ -0,0 +1,6 @@ +module Bad + ( bad ) +where + +bad :: Into +bad = "foo" diff --git a/third_party/bazel/rules_haskell/tests/repl-targets/Chs.chs b/third_party/bazel/rules_haskell/tests/repl-targets/Chs.chs new file mode 100644 index 000000000000..c66bae7d60fd --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/repl-targets/Chs.chs @@ -0,0 +1,6 @@ +module Chs + ( baz ) +where + +baz :: String +baz = "baz" diff --git a/third_party/bazel/rules_haskell/tests/repl-targets/Foo.hs b/third_party/bazel/rules_haskell/tests/repl-targets/Foo.hs new file mode 100644 index 000000000000..5e5138418d5d --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/repl-targets/Foo.hs @@ -0,0 +1,9 @@ +{-# LANGUAGE ForeignFunctionInterface #-} + +module Foo (foo) where + +foreign import ccall "c_add_one" + c_add_one :: Int -> Int + +foo :: Int -> Int +foo = (+ 5) . c_add_one diff --git a/third_party/bazel/rules_haskell/tests/repl-targets/Hsc.hsc b/third_party/bazel/rules_haskell/tests/repl-targets/Hsc.hsc new file mode 100644 index 000000000000..d4e3d6605c00 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/repl-targets/Hsc.hsc @@ -0,0 +1,8 @@ +module Hsc + ( bar ) +where + +#ifndef _INTERNAL_HSC_DO_NOT_DEFINE_ME +bar :: String +bar = "bar" +#endif diff --git a/third_party/bazel/rules_haskell/tests/repl-targets/Quux.hs b/third_party/bazel/rules_haskell/tests/repl-targets/Quux.hs new file mode 100644 index 000000000000..2e67d221fb22 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/repl-targets/Quux.hs @@ -0,0 +1,6 @@ +module Main (main) where + +import QuuxLib (message) + +main :: IO () +main = putStrLn message diff --git a/third_party/bazel/rules_haskell/tests/repl-targets/QuuxLib.hs b/third_party/bazel/rules_haskell/tests/repl-targets/QuuxLib.hs new file mode 100644 index 000000000000..d321de2adda3 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/repl-targets/QuuxLib.hs @@ -0,0 +1,4 @@ +module QuuxLib (message) where + +message :: String +message = "Hello GHCi!" diff --git a/third_party/bazel/rules_haskell/tests/repl-targets/src/Bar.hs b/third_party/bazel/rules_haskell/tests/repl-targets/src/Bar.hs new file mode 100644 index 000000000000..18fe359e0a2a --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/repl-targets/src/Bar.hs @@ -0,0 +1,4 @@ +module Bar (bar) where + +bar :: Int +bar = 4 diff --git a/third_party/bazel/rules_haskell/tests/repl-targets/src/Baz.hsc b/third_party/bazel/rules_haskell/tests/repl-targets/src/Baz.hsc new file mode 100644 index 000000000000..984ec4ff0ad9 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/repl-targets/src/Baz.hsc @@ -0,0 +1,4 @@ +module Baz (baz) where + +baz :: Int +baz = 8 diff --git a/third_party/bazel/rules_haskell/tests/rule_test_exe.bzl b/third_party/bazel/rules_haskell/tests/rule_test_exe.bzl new file mode 100644 index 000000000000..fdecbb385871 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/rule_test_exe.bzl @@ -0,0 +1,14 @@ +load("@bazel_tools//tools/build_rules:test_rules.bzl", "rule_test") + +def rule_test_exe(generates, **kwargs): + """ + Like 'rule_test' but appends ".exe" to the elements of + "generates". + """ + + new_generates = select({ + "@bazel_tools//src/conditions:windows": [e + ".exe" for e in generates], + "//conditions:default": generates, + }) + + rule_test(generates = new_generates, **kwargs) diff --git a/third_party/bazel/rules_haskell/tests/run-start-script.sh b/third_party/bazel/rules_haskell/tests/run-start-script.sh new file mode 100755 index 000000000000..6803581f0010 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/run-start-script.sh @@ -0,0 +1,30 @@ +#!/bin/sh + +# Run the start script in its own workspace +# and build the example binary target. + +set -e + +pwd=$(pwd) +cd $(mktemp -d) +$pwd/start + +# Copy the bazel configuration, this is only useful for CI +mkdir tools +cp $pwd/.bazelrc .bazelrc + +# Set Nixpkgs in environment variable to avoid hardcoding it in +# start script itself. + +# overrides the used rules_haskell, because +# when we're testing the start on a feature branch (CI), +# the latest rules_haskell version doesn't always work. +# If on the branch we update Bazel to a version with breaking +# changes, then we need to adapt to those changes in the branch. +# Which in turn means the start script should pull in those changes too. + +NIX_PATH=nixpkgs=$pwd/nixpkgs/default.nix \ + bazel build \ + --config=ci \ + --override_repository=io_tweag_rules_haskell=$pwd \ + //:example diff --git a/third_party/bazel/rules_haskell/tests/scripts/exec.sh b/third_party/bazel/rules_haskell/tests/scripts/exec.sh new file mode 100755 index 000000000000..2a6c2a810041 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/scripts/exec.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +set -e + +exec "$1" diff --git a/third_party/bazel/rules_haskell/tests/textual-hdrs/BUILD.bazel b/third_party/bazel/rules_haskell/tests/textual-hdrs/BUILD.bazel new file mode 100644 index 000000000000..e66f497c77f2 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/textual-hdrs/BUILD.bazel @@ -0,0 +1,17 @@ +load( + "@io_tweag_rules_haskell//haskell:haskell.bzl", + "haskell_test", +) + +package(default_testonly = 1) + +haskell_test( + name = "textual-hdrs", + srcs = [ + "Main.hs", + "include/main_definition.h", + ], + compiler_flags = ["-Itests/textual-hdrs/include"], + visibility = ["//visibility:public"], + deps = ["//tests/hackage:base"], +) diff --git a/third_party/bazel/rules_haskell/tests/textual-hdrs/Main.hs b/third_party/bazel/rules_haskell/tests/textual-hdrs/Main.hs new file mode 100644 index 000000000000..f741091275d8 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/textual-hdrs/Main.hs @@ -0,0 +1,5 @@ +{-# LANGUAGE CPP #-} + +module Main (main) where + +#include "main_definition.h" diff --git a/third_party/bazel/rules_haskell/tests/textual-hdrs/include/main_definition.h b/third_party/bazel/rules_haskell/tests/textual-hdrs/include/main_definition.h new file mode 100644 index 000000000000..071eeddd8706 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/textual-hdrs/include/main_definition.h @@ -0,0 +1,2 @@ +main :: IO () +main = putStrLn "extras-included-during-comp" diff --git a/third_party/bazel/rules_haskell/tests/two-libs/BUILD.bazel b/third_party/bazel/rules_haskell/tests/two-libs/BUILD.bazel new file mode 100644 index 000000000000..d69dba515c2d --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/two-libs/BUILD.bazel @@ -0,0 +1,42 @@ +load( + "@io_tweag_rules_haskell//haskell:haskell.bzl", + "haskell_library", + "haskell_test", +) + +package( + default_testonly = 1, + default_visibility = ["//visibility:public"], +) + +haskell_library( + name = "one", + srcs = ["One.hs"], + deps = [ + "//tests/hackage:base", + ], +) + +haskell_library( + name = "two", + srcs = ["Two.hs"], + deps = [ + ":one", + "//tests/hackage:base", + ], +) + +haskell_test( + name = "two-libs", + srcs = ["Main.hs"], + coverage_report_format = "html", + expected_covered_expressions_percentage = 55, + expected_uncovered_expression_count = 4, + experimental_coverage_source_patterns = [":two"], + strict_coverage_analysis = True, + tags = ["coverage-compatible"], + deps = [ + ":two", + "//tests/hackage:base", + ], +) diff --git a/third_party/bazel/rules_haskell/tests/two-libs/Main.hs b/third_party/bazel/rules_haskell/tests/two-libs/Main.hs new file mode 100644 index 000000000000..99ce449a5281 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/two-libs/Main.hs @@ -0,0 +1,6 @@ +module Main where + +import Two (two) + +main :: IO () +main = putStrLn ("Two: " ++ show two) diff --git a/third_party/bazel/rules_haskell/tests/two-libs/One.hs b/third_party/bazel/rules_haskell/tests/two-libs/One.hs new file mode 100644 index 000000000000..f8f04ab2640c --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/two-libs/One.hs @@ -0,0 +1,4 @@ +module One (one) where + +one :: Int +one = 1 diff --git a/third_party/bazel/rules_haskell/tests/two-libs/Two.hs b/third_party/bazel/rules_haskell/tests/two-libs/Two.hs new file mode 100644 index 000000000000..5672263c3d5f --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/two-libs/Two.hs @@ -0,0 +1,14 @@ +module Two (two) where + +import One (one) + +two :: Int +two = + if True then + one + one + else + if True then + 1 + else + 2 + \ No newline at end of file diff --git a/third_party/bazel/rules_haskell/tests/unit-tests/BUILD.bazel b/third_party/bazel/rules_haskell/tests/unit-tests/BUILD.bazel new file mode 100644 index 000000000000..990035af685f --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/unit-tests/BUILD.bazel @@ -0,0 +1,125 @@ +load( + ":tests.bzl", + "create_rpath_entry_test", + "dedup_on_test", + "parent_dir_path_test", +) + +parent_dir_path_test( + name = "parent_dir_just_file", + filename = "foo", + output = ["."], +) + +parent_dir_path_test( + name = "parent_dir", + filename = "foo/", + output = ["foo"], +) + +parent_dir_path_test( + name = "parent_dir_file", + filename = "foo/bar", + output = ["foo"], +) + +parent_dir_path_test( + name = "parent_dir_file_dots", + filename = "foo/../bar", + output = [ + "foo", + "..", + ], +) + +parent_dir_path_test( + name = "parent_dir_rooted", + filename = "/foo/bar", + output = [ + "", + "foo", + ], +) + +create_rpath_entry_test( + name = "rpath_entry_simple", + binary_short_path = "foo/a.so", + dependency_short_path = "bar/b.so", + output = "../bar", +) + +# checks that a binary in //:bin works properly +create_rpath_entry_test( + name = "rpath_entry_binary_root", + binary_short_path = "bin", + dependency_short_path = "xyz/b.so", + output = "xyz", +) + +# same for dependency +create_rpath_entry_test( + name = "rpath_entry_dep_root", + binary_short_path = "lib/bin", + dependency_short_path = "b.so", + output = "..", +) + +create_rpath_entry_test( + name = "rpath_entry_simple_filename", + binary_short_path = "foo/a.so", + dependency_short_path = "bar/b.so", + keep_filename = True, + output = "../bar/b.so", +) + +create_rpath_entry_test( + name = "rpath_entry_prefix", + binary_short_path = "foo/a.so", + dependency_short_path = "bar/b.so", + output = "$ORIGIN/../bar", + prefix = "$ORIGIN", +) + +# if the short-paths have leading dots, they are in `external` + +create_rpath_entry_test( + name = "rpath_entry_binary_leading_dots_dep", + # non-external + binary_short_path = "foo/a.so", + # external dep + dependency_short_path = "../bar/b.so", + output = "../external/bar", +) + +create_rpath_entry_test( + name = "rpath_entry_binary_leading_dots_bin", + # external dep + binary_short_path = "../foo/a.so", + # non-external + dependency_short_path = "bar/b.so", + # back through `external` + output = "../../bar", +) + +create_rpath_entry_test( + name = "rpath_entry_binary_leading_dots_both", + # external dep + binary_short_path = "../foo/a.so", + # external dep + dependency_short_path = "../bar/b.so", + # stay in `external` + output = "../bar", +) + +# we have no idea how to handle internal dots, should they arise +# create_rpath_entry_test( +# name = "rpath_entry_binary_internal_dots", +# binary_short_path = "foo/../../a.so", +# dependency_short_path = "../bar/../b.so", +# # but that doesn’t change anything for the runpath +# output = "../bar", +# ) + +dedup_on_test( + name = "dedup_on_test", +) diff --git a/third_party/bazel/rules_haskell/tests/unit-tests/tests.bzl b/third_party/bazel/rules_haskell/tests/unit-tests/tests.bzl new file mode 100644 index 000000000000..58a3f400adbe --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/unit-tests/tests.bzl @@ -0,0 +1,83 @@ +load( + "@bazel_skylib//lib:unittest.bzl", + "asserts", + unit = "unittest", +) +load("//haskell:private/actions/link.bzl", "create_rpath_entry", "parent_dir_path") +load("//haskell:private/list.bzl", "list") + +def parent_dir_path_test_impl(ctx): + env = unit.begin(ctx) + asserts.equals( + env, + expected = ctx.attr.output, + actual = parent_dir_path(ctx.attr.filename), + ) + unit.end(env) + +parent_dir_path_test = unit.make( + parent_dir_path_test_impl, + attrs = { + "filename": attr.string(), + "output": attr.string_list(), + }, +) + +def create_rpath_entry_test_impl(ctx): + env = unit.begin(ctx) + asserts.equals( + env, + expected = ctx.attr.output, + actual = create_rpath_entry( + struct( + short_path = ctx.attr.binary_short_path, + ), + struct( + short_path = ctx.attr.dependency_short_path, + ), + keep_filename = ctx.attr.keep_filename, + prefix = ctx.attr.prefix, + ), + ) + unit.end(env) + +create_rpath_entry_test = unit.make( + create_rpath_entry_test_impl, + attrs = { + "binary_short_path": attr.string(), + "dependency_short_path": attr.string(), + "keep_filename": attr.bool(default = False, mandatory = False), + "prefix": attr.string(default = "", mandatory = False), + "output": attr.string(), + }, +) + +def compare_x(el): + return el.x + +def dedup_on_test_impl(ctx): + env = unit.begin(ctx) + asserts.equals( + env, + expected = [], + actual = list.dedup_on(compare_x, []), + ) + asserts.equals( + env, + expected = [struct(x = 3)], + actual = list.dedup_on( + compare_x, + [struct(x = 3), struct(x = 3), struct(x = 3)], + ), + ) + asserts.equals( + env, + expected = [struct(x = 3), struct(x = 4), struct(x = 5)], + actual = list.dedup_on( + compare_x, + [struct(x = 3), struct(x = 4), struct(x = 3), struct(x = 5), struct(x = 3)], + ), + ) + unit.end(env) + +dedup_on_test = unit.make(dedup_on_test_impl) diff --git a/third_party/bazel/rules_haskell/tests/version-macros/BUILD.bazel b/third_party/bazel/rules_haskell/tests/version-macros/BUILD.bazel new file mode 100644 index 000000000000..b2be1b7d1598 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/version-macros/BUILD.bazel @@ -0,0 +1,59 @@ +load( + "@io_tweag_rules_haskell//haskell:haskell.bzl", + "haskell_library", + "haskell_test", +) +load( + "@io_tweag_rules_haskell//haskell:c2hs.bzl", + "c2hs_library", +) + +package(default_testonly = 1) + +haskell_library( + name = "versioned-lib", + srcs = ["VersionedLib.hs"], + version = "1.2.3.4", + deps = ["//tests/hackage:base"], +) + +haskell_test( + name = "version_macros", + size = "small", + srcs = [ + "HsLib.hs", + "HscLib.hsc", + "Main.hs", + ], + version = "3.4.5.6", + deps = [ + ":versioned-lib", + "//tests/hackage:base", + ], +) + +c2hs_library( + name = "c2hs-lib", + srcs = ["C2hsLib.chs"], + tags = ["requires_c2hs"], + version = "4.5.6.7", + deps = [ + ":versioned-lib", + "//tests/hackage:base", + ], +) + +haskell_test( + name = "version_macros_c2hs", + size = "small", + srcs = [ + "MainC2hs.hs", + ":c2hs-lib", + ], + tags = ["requires_c2hs"], + version = "4.5.6.7", + deps = [ + ":versioned-lib", + "//tests/hackage:base", + ], +) diff --git a/third_party/bazel/rules_haskell/tests/version-macros/C2hsLib.chs b/third_party/bazel/rules_haskell/tests/version-macros/C2hsLib.chs new file mode 100644 index 000000000000..4b484af2a3ed --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/version-macros/C2hsLib.chs @@ -0,0 +1,44 @@ +module C2hsLib where + +import Control.Monad (unless) + +check_version_versioned_lib :: IO () +#ifndef VERSION_versioned_lib +check_version_versioned_lib = fail "c2hs: VERSION_versioned_lib missing" +#else +check_version_versioned_lib = + unless ({#const VERSION_versioned_lib#} == "1.2.3.4") $ + fail "c2hs: VERSION_versioned_lib invalid" +#endif + +check_min_version_versioned_lib :: IO () +#ifndef MIN_VERSION_versioned_lib +check_min_version_versioned_lib = fail "c2hs: MIN_VERSION_versioned_lib missing" +#elif !MIN_VERSION_versioned_lib(1,2,3) +check_min_version_versioned_lib = fail "c2hs: MIN_VERSION_versioned_lib invalid" +#else +check_min_version_versioned_lib = pure () +#endif + +check_version_base :: IO () +#ifndef VERSION_base +check_version_base = fail "c2hs: VERSION_base missing" +#else +check_version_base = pure () +#endif + +check_min_version_base :: IO () +#ifndef MIN_VERSION_base +check_min_version_base = fail "c2hs: MIN_VERSION_base missing" +#elif !MIN_VERSION_base(0,0,0) +check_min_version_base = fail "c2hs: MIN_VERSION_base invalid" +#else +check_min_version_base = pure () +#endif + +check :: IO () +check = do + check_version_versioned_lib + check_min_version_versioned_lib + check_version_base + check_min_version_base diff --git a/third_party/bazel/rules_haskell/tests/version-macros/HsLib.hs b/third_party/bazel/rules_haskell/tests/version-macros/HsLib.hs new file mode 100644 index 000000000000..ce61906c81e6 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/version-macros/HsLib.hs @@ -0,0 +1,46 @@ +{-# LANGUAGE CPP #-} + +module HsLib where + +import Control.Monad (unless) + +check_version_versioned_lib :: IO () +#ifndef VERSION_versioned_lib +check_version_versioned_lib = fail "hs: VERSION_versioned_lib missing" +#else +check_version_versioned_lib = + unless (VERSION_versioned_lib == "1.2.3.4") $ + fail "hs: VERSION_versioned_lib invalid" +#endif + +check_min_version_versioned_lib :: IO () +#ifndef MIN_VERSION_versioned_lib +check_min_version_versioned_lib = fail "hs: MIN_VERSION_versioned_lib missing" +#elif !MIN_VERSION_versioned_lib(1,2,3) +check_min_version_versioned_lib = fail "hs: MIN_VERSION_versioned_lib invalid" +#else +check_min_version_versioned_lib = pure () +#endif + +check_version_base :: IO () +#ifndef VERSION_base +check_version_base = fail "hs: VERSION_base missing" +#else +check_version_base = pure () +#endif + +check_min_version_base :: IO () +#ifndef MIN_VERSION_base +check_min_version_base = fail "hs: MIN_VERSION_base missing" +#elif !MIN_VERSION_base(0,0,0) +check_min_version_base = fail "hs: MIN_VERSION_base invalid" +#else +check_min_version_base = pure () +#endif + +check :: IO () +check = do + check_version_versioned_lib + check_min_version_versioned_lib + check_version_base + check_min_version_base diff --git a/third_party/bazel/rules_haskell/tests/version-macros/HscLib.hsc b/third_party/bazel/rules_haskell/tests/version-macros/HscLib.hsc new file mode 100644 index 000000000000..387e73a08997 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/version-macros/HscLib.hsc @@ -0,0 +1,44 @@ +module HscLib where + +import Control.Monad (unless) + +check_version_versioned_lib :: IO () +#ifndef VERSION_versioned_lib +check_version_versioned_lib = fail "hsc2hs: VERSION_versioned_lib missing" +#else +check_version_versioned_lib = + unless (#{const_str VERSION_versioned_lib} == "1.2.3.4") $ + fail "hsc2hs: VERSION_versioned_lib invalid" +#endif + +check_min_version_versioned_lib :: IO () +#ifndef MIN_VERSION_versioned_lib +check_min_version_versioned_lib = fail "hsc2hs: MIN_VERSION_versioned_lib missing" +#elif !MIN_VERSION_versioned_lib(1,2,3) +check_min_version_versioned_lib = fail "hsc2hs: MIN_VERSION_versioned_lib invalid" +#else +check_min_version_versioned_lib = pure () +#endif + +check_version_base :: IO () +#ifndef VERSION_base +check_version_base = fail "hsc2hs: VERSION_base missing" +#else +check_version_base = pure () +#endif + +check_min_version_base :: IO () +#ifndef MIN_VERSION_base +check_min_version_base = fail "hsc2hs: MIN_VERSION_base missing" +#elif !MIN_VERSION_base(0,0,0) +check_min_version_base = fail "hsc2hs: MIN_VERSION_base invalid" +#else +check_min_version_base = pure () +#endif + +check :: IO () +check = do + check_version_versioned_lib + check_min_version_versioned_lib + check_version_base + check_min_version_base diff --git a/third_party/bazel/rules_haskell/tests/version-macros/Main.hs b/third_party/bazel/rules_haskell/tests/version-macros/Main.hs new file mode 100644 index 000000000000..bbcd108d0b6b --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/version-macros/Main.hs @@ -0,0 +1,9 @@ +module Main where + +import qualified HscLib +import qualified HsLib + +main :: IO () +main = do + HscLib.check + HsLib.check diff --git a/third_party/bazel/rules_haskell/tests/version-macros/MainC2hs.hs b/third_party/bazel/rules_haskell/tests/version-macros/MainC2hs.hs new file mode 100644 index 000000000000..82e4ec72e248 --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/version-macros/MainC2hs.hs @@ -0,0 +1,7 @@ +module Main where + +import qualified C2hsLib + +main :: IO () +main = do + C2hsLib.check diff --git a/third_party/bazel/rules_haskell/tests/version-macros/VersionedLib.hs b/third_party/bazel/rules_haskell/tests/version-macros/VersionedLib.hs new file mode 100644 index 000000000000..0dfd5577e7aa --- /dev/null +++ b/third_party/bazel/rules_haskell/tests/version-macros/VersionedLib.hs @@ -0,0 +1 @@ +module VersionedLib where |