From c967b68f54e059cfb8a1eafd3961b9f772d06bc8 Mon Sep 17 00:00:00 2001 From: fendor Date: Sun, 27 Apr 2025 15:52:11 +0200 Subject: [PATCH 1/7] Run all tests with temporary 'XDG_CACHE_HOME' This makes sure each test run is independent. Makes the tests * iface-error-test-1 * iface-th-test less flaky locally. Should not have any effect on the CI flakiness issue. --- Fix test cases to work with the temporary `XDG_CACHE_HOME` Some tests were launching additional HLS instances for the tests. Fixed, which should make the test slightly faster. --- ghcide-test/exe/BootTests.hs | 37 ++++---- ghcide-test/exe/CradleTests.hs | 11 +-- .../exe/FindDefinitionAndHoverTests.hs | 2 +- hls-test-utils/src/Test/Hls.hs | 90 ++++++++++++++----- 4 files changed, 92 insertions(+), 48 deletions(-) diff --git a/ghcide-test/exe/BootTests.hs b/ghcide-test/exe/BootTests.hs index 06c05ba9b6..e6bec54dae 100644 --- a/ghcide-test/exe/BootTests.hs +++ b/ghcide-test/exe/BootTests.hs @@ -27,25 +27,24 @@ tests = testGroup "boot" let cPath = dir "C.hs" cSource <- liftIO $ readFileUtf8 cPath -- Dirty the cache - liftIO $ runInDir dir $ do - cDoc <- createDoc cPath "haskell" cSource - -- We send a hover request then wait for either the hover response or - -- `ghcide/reference/ready` notification. - -- Once we receive one of the above, we wait for the other that we - -- haven't received yet. - -- If we don't wait for the `ready` notification it is possible - -- that the `getDefinitions` request/response in the outer ghcide - -- session will find no definitions. - let hoverParams = HoverParams cDoc (Position 4 3) Nothing - hoverRequestId <- sendRequest SMethod_TextDocumentHover hoverParams - let parseReadyMessage = isReferenceReady cPath - let parseHoverResponse = responseForId SMethod_TextDocumentHover hoverRequestId - hoverResponseOrReadyMessage <- skipManyTill anyMessage ((Left <$> parseHoverResponse) <|> (Right <$> parseReadyMessage)) - _ <- skipManyTill anyMessage $ - case hoverResponseOrReadyMessage of - Left _ -> void parseReadyMessage - Right _ -> void parseHoverResponse - closeDoc cDoc + cDoc <- createDoc cPath "haskell" cSource + -- We send a hover request then wait for either the hover response or + -- `ghcide/reference/ready` notification. + -- Once we receive one of the above, we wait for the other that we + -- haven't received yet. + -- If we don't wait for the `ready` notification it is possible + -- that the `getDefinitions` request/response in the outer ghcide + -- session will find no definitions. + let hoverParams = HoverParams cDoc (Position 4 3) Nothing + hoverRequestId <- sendRequest SMethod_TextDocumentHover hoverParams + let parseReadyMessage = isReferenceReady cPath + let parseHoverResponse = responseForId SMethod_TextDocumentHover hoverRequestId + hoverResponseOrReadyMessage <- skipManyTill anyMessage ((Left <$> parseHoverResponse) <|> (Right <$> parseReadyMessage)) + _ <- skipManyTill anyMessage $ + case hoverResponseOrReadyMessage of + Left _ -> void parseReadyMessage + Right _ -> void parseHoverResponse + closeDoc cDoc cdoc <- createDoc cPath "haskell" cSource locs <- getDefinitions cdoc (Position 7 4) let floc = mkR 9 0 9 1 diff --git a/ghcide-test/exe/CradleTests.hs b/ghcide-test/exe/CradleTests.hs index 8edb258257..5ff19931bc 100644 --- a/ghcide-test/exe/CradleTests.hs +++ b/ghcide-test/exe/CradleTests.hs @@ -3,7 +3,7 @@ module CradleTests (tests) where -import Config (checkDefs, mkL, runInDir, +import Config (checkDefs, mkL, runWithExtraFiles, testWithDummyPluginEmpty') import Control.Applicative.Combinators @@ -180,12 +180,9 @@ simpleMultiDefTest variant = ignoreForWindows $ testCase testName $ runWithExtraFiles variant $ \dir -> do let aPath = dir "a/A.hs" bPath = dir "b/B.hs" - adoc <- liftIO $ runInDir dir $ do - aSource <- liftIO $ readFileUtf8 aPath - adoc <- createDoc aPath "haskell" aSource - skipManyTill anyMessage $ isReferenceReady aPath - closeDoc adoc - pure adoc + adoc <- openDoc aPath "haskell" + skipManyTill anyMessage $ isReferenceReady aPath + closeDoc adoc bSource <- liftIO $ readFileUtf8 bPath bdoc <- createDoc bPath "haskell" bSource locs <- getDefinitions bdoc (Position 2 7) diff --git a/ghcide-test/exe/FindDefinitionAndHoverTests.hs b/ghcide-test/exe/FindDefinitionAndHoverTests.hs index e4c0958f58..a2b67879db 100644 --- a/ghcide-test/exe/FindDefinitionAndHoverTests.hs +++ b/ghcide-test/exe/FindDefinitionAndHoverTests.hs @@ -188,7 +188,7 @@ tests = let cccL17 = Position 17 16 ; docLink = [ExpectHoverTextRegex "\\*Defined in 'GHC.Types'\\* \\*\\(ghc-prim-[0-9.]+\\)\\*\n\n"] imported = Position 56 13 ; importedSig = getDocUri "Foo.hs" >>= \foo -> return [ExpectHoverText ["foo", "Foo", "Haddock"], mkL foo 5 0 5 3] reexported = Position 55 14 - reexportedSig = getDocUri "Bar.hs" >>= \bar -> return [ExpectHoverText ["Bar", "Bar", "Haddock"], if ghcVersion < GHC910 || not isWindows then mkL bar 3 5 3 8 else mkL bar 3 0 3 14] + reexportedSig = getDocUri "Bar.hs" >>= \bar -> return [ExpectHoverText ["Bar", "Bar", "Haddock"], mkL bar 3 0 3 14] thLocL57 = Position 59 10 ; thLoc = [ExpectHoverText ["Identity"]] cmtL68 = Position 67 0 ; lackOfdEq = [ExpectHoverExcludeText ["$dEq"]] import310 = Position 3 10; pkgTxt = [ExpectHoverText ["Data.Text\n\ntext-"]] diff --git a/hls-test-utils/src/Test/Hls.hs b/hls-test-utils/src/Test/Hls.hs index 0ab203fe36..b695ad6b22 100644 --- a/hls-test-utils/src/Test/Hls.hs +++ b/hls-test-utils/src/Test/Hls.hs @@ -507,8 +507,28 @@ runSessionWithServerInTmpDir config plugin tree act = {testLspConfig=config, testPluginDescriptor = plugin, testDirLocation=Right tree} (const act) -runWithLockInTempDir :: VirtualFileTree -> (FileSystem -> IO a) -> IO a -runWithLockInTempDir tree act = withLock lockForTempDirs $ do +-- | Same as 'withTemporaryDataAndCacheDirectory', but materialises the given +-- 'VirtualFileTree' in the temporary directory. +withVfsTestDataDirectory :: VirtualFileTree -> (FileSystem -> IO a) -> IO a +withVfsTestDataDirectory tree act = do + withTemporaryDataAndCacheDirectory $ \tmpRoot -> do + fs <- FS.materialiseVFT tmpRoot tree + act fs + +-- | Run an action in a temporary directory. +-- Sets the 'XDG_CACHE_HOME' environment variable to a temporary directory as well. +-- +-- This sets up a temporary directory for HLS tests to run. +-- Typically, HLS tests copy their test data into the directory and then launch +-- the HLS session in that directory. +-- This makes sure that the tests are run in isolation, which is good for correctness +-- but also important to have fast tests. +-- +-- For improved isolation, we also make sure the 'XDG_CACHE_HOME' environment +-- variable points to a temporary directory. So, we never share interface files +-- or the 'hiedb' across tests. +withTemporaryDataAndCacheDirectory :: (FilePath -> IO a) -> IO a +withTemporaryDataAndCacheDirectory act = withLock lockForTempDirs $ do testRoot <- setupTestEnvironment helperRecorder <- hlsHelperTestRecorder -- Do not clean up the temporary directory if this variable is set to anything but '0'. @@ -516,23 +536,44 @@ runWithLockInTempDir tree act = withLock lockForTempDirs $ do cleanupTempDir <- lookupEnv "HLS_TEST_HARNESS_NO_TESTDIR_CLEANUP" let runTestInDir action = case cleanupTempDir of Just val | val /= "0" -> do - (tempDir, _) <- newTempDirWithin testRoot - a <- action tempDir + (tempDir, cacheHome, _) <- setupTemporaryTestDirectories testRoot + a <- withTempCacheHome cacheHome (action tempDir) logWith helperRecorder Debug LogNoCleanup pure a _ -> do - (tempDir, cleanup) <- newTempDirWithin testRoot - a <- action tempDir `finally` cleanup + (tempDir, cacheHome, cleanup) <- setupTemporaryTestDirectories testRoot + a <- withTempCacheHome cacheHome (action tempDir) `finally` cleanup logWith helperRecorder Debug LogCleanup pure a runTestInDir $ \tmpDir' -> do -- we canonicalize the path, so that we do not need to do - -- cannibalization during the test when we compare two paths + -- canonicalization during the test when we compare two paths tmpDir <- canonicalizePath tmpDir' logWith helperRecorder Info $ LogTestDir tmpDir - fs <- FS.materialiseVFT tmpDir tree - act fs + act tmpDir + where + cache_home_var = "XDG_CACHE_HOME" + -- Set the dir for "XDG_CACHE_HOME". + -- When the operation finished, make sure the old value is restored. + withTempCacheHome tempCacheHomeDir act = + bracket + (do + old_cache_home <- lookupEnv cache_home_var + setEnv cache_home_var tempCacheHomeDir + pure old_cache_home) + (\old_cache_home -> + maybe (pure ()) (setEnv cache_home_var) old_cache_home + ) + (\_ -> act) + + -- Set up a temporary directory for the test files and one for the 'XDG_CACHE_HOME'. + -- The 'XDG_CACHE_HOME' is important for independent test runs, i.e. completely empty + -- caches. + setupTemporaryTestDirectories testRoot = do + (tempTestCaseDir, cleanup1) <- newTempDirWithin testRoot + (tempCacheHomeDir, cleanup2) <- newTempDirWithin testRoot + pure (tempTestCaseDir, tempCacheHomeDir, cleanup1 >> cleanup2) runSessionWithServer :: Pretty b => Config -> PluginTestDescriptor b -> FilePath -> Session a -> IO a runSessionWithServer config plugin fp act = @@ -565,17 +606,11 @@ instance Default (TestConfig b) where -- It returns the root to the testing directory that tests should use. -- This directory is not fully cleaned between reruns. -- However, it is totally safe to delete the directory between runs. --- --- Additionally, this overwrites the 'XDG_CACHE_HOME' variable to isolate --- the tests from existing caches. 'hie-bios' and 'ghcide' honour the --- 'XDG_CACHE_HOME' environment variable and generate their caches there. setupTestEnvironment :: IO FilePath setupTestEnvironment = do tmpDirRoot <- getTemporaryDirectory let testRoot = tmpDirRoot "hls-test-root" - testCacheDir = testRoot ".cache" - createDirectoryIfMissing True testCacheDir - setEnv "XDG_CACHE_HOME" testCacheDir + createDirectoryIfMissing True testRoot pure testRoot goldenWithHaskellDocFormatter @@ -692,7 +727,6 @@ lockForTempDirs = unsafePerformIO newLock data TestConfig b = TestConfig { testDirLocation :: Either FilePath VirtualFileTree - -- ^ Client capabilities -- ^ The file tree to use for the test, either a directory or a virtual file tree -- if using a virtual file tree, -- Creates a temporary directory, and materializes the VirtualFileTree @@ -747,8 +781,20 @@ wrapClientLogger logger = do return (lspLogRecorder <> logger, cb1) -- | Host a server, and run a test session on it. --- For setting custom timeout, set the environment variable 'LSP_TIMEOUT' --- * LSP_TIMEOUT=10 cabal test +-- +-- Environment variables are used to influence logging verbosity, test cleanup and test execution: +-- +-- * @LSP_TIMEOUT@: Set a specific test timeout in seconds. +-- * @LSP_TEST_LOG_MESSAGES@: Log the LSP messages between the client and server. +-- * @LSP_TEST_LOG_STDERR@: Log the stderr of the server to the stderr of this process. +-- * @HLS_TEST_HARNESS_STDERR@: Log test setup messages. +-- +-- Test specific environment variables: +-- +-- * @HLS_TEST_PLUGIN_LOG_STDERR@: Log all messages of the hls plugin under test to stderr. +-- * @HLS_TEST_LOG_STDERR@: Log all HLS messages to stderr. +-- * @HLS_TEST_HARNESS_NO_TESTDIR_CLEANUP@: Don't remove the test directories after test execution. +-- -- For more detail of the test configuration, see 'TestConfig' runSessionWithTestConfig :: Pretty b => TestConfig b -> (FilePath -> Session a) -> IO a runSessionWithTestConfig TestConfig{..} session = @@ -792,8 +838,10 @@ runSessionWithTestConfig TestConfig{..} session = else f runSessionInVFS (Left testConfigRoot) act = do root <- makeAbsolute testConfigRoot - act root - runSessionInVFS (Right vfs) act = runWithLockInTempDir vfs $ \fs -> act (fsRoot fs) + withTemporaryDataAndCacheDirectory (const $ act root) + runSessionInVFS (Right vfs) act = + withVfsTestDataDirectory vfs $ \fs -> do + act (fsRoot fs) testingArgs prjRoot recorderIde plugins = let arguments@Arguments{ argsHlsPlugins, argsIdeOptions, argsLspOptions } = defaultArguments (cmapWithPrio LogIDEMain recorderIde) prjRoot plugins From 3944409bd597f11006b38ee25644c4d163e49ed5 Mon Sep 17 00:00:00 2001 From: fendor Date: Sun, 27 Apr 2025 17:13:54 +0200 Subject: [PATCH 2/7] Run ghcide-tests if the hls-test-utils changes Ghcide test infrastructure was refactored to depend on `hls-test-utils`. --- .github/workflows/test.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b2870d3076..ca2abd0084 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -48,8 +48,7 @@ jobs: uses: fkirc/skip-duplicate-actions@v5.3.1 with: cancel_others: false - paths_ignore: '[ "hls-test-utils/**" - , "plugins/**" + paths_ignore: '[ "plugins/**" , "src/**" , "exe/**" , "test/**" From 9295cfbcd3a4bd4fd6c690495d02cec29c5b4e60 Mon Sep 17 00:00:00 2001 From: Fendor Date: Mon, 5 May 2025 18:33:53 +0200 Subject: [PATCH 3/7] Always use the same `mkHomeModLocation` for `mAIN_NAME` --- ghcide/src/Development/IDE/Core/Compile.hs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/ghcide/src/Development/IDE/Core/Compile.hs b/ghcide/src/Development/IDE/Core/Compile.hs index 48439e2ff3..3c41aa260f 100644 --- a/ghcide/src/Development/IDE/Core/Compile.hs +++ b/ghcide/src/Development/IDE/Core/Compile.hs @@ -1122,11 +1122,7 @@ getModSummaryFromImports env fp _modTime mContents = do liftIO $ evaluate $ rnf textualImports - modLoc <- liftIO $ if mod == mAIN_NAME - -- specially in tests it's common to have lots of nameless modules - -- mkHomeModLocation will map them to the same hi/hie locations - then mkHomeModLocation dflags (pathToModuleName fp) fp - else mkHomeModLocation dflags mod fp + modLoc <- liftIO $ mkHomeModLocation dflags mod fp let modl = mkHomeModule (hscHomeUnit ppEnv) mod sourceType = if "-boot" `isSuffixOf` takeExtension fp then HsBootFile else HsSrcFile From f928aa50487e8a19be8c362a0ef6fe853680ee5d Mon Sep 17 00:00:00 2001 From: fendor Date: Wed, 14 May 2025 17:40:01 +0200 Subject: [PATCH 4/7] Make cabal-add test directories considerably shorter --- plugins/hls-cabal-plugin/test/CabalAdd.hs | 43 +++++++++---------- .../bench.cabal} | 0 .../{cabal-add-bench => bench}/bench/Main.hs | 0 .../cabal-add-testdata/bench/cabal.project | 1 + .../cabal-add-testdata/{ => bench}/hie.yaml | 0 .../testdata/cabal-add-testdata/cabal.project | 6 --- .../cabal-add-testdata/exe/cabal.project | 1 + .../cabal-add-exe.cabal => exe/exe.cabal} | 0 .../testdata/cabal-add-testdata/exe/hie.yaml | 2 + .../{cabal-add-exe => exe}/src/Main.hs | 0 .../cabal-add-testdata/lib/cabal.project | 1 + .../testdata/cabal-add-testdata/lib/hie.yaml | 2 + .../cabal-add-lib.cabal => lib/lib.cabal} | 0 .../{cabal-add-lib => lib}/src/MyLib.hs | 0 .../bench/Main.hs | 0 .../multitarget/cabal.project | 1 + .../cabal-add-testdata/multitarget/hie.yaml | 2 + .../lib/InternalLib.hs | 0 .../lib/MyLib.hs | 0 .../multitarget.cabal} | 0 .../src/Main.hs | 0 .../test/Main.hs | 0 .../packageYaml/cabal.project | 1 + .../cabal-add-testdata/packageYaml/hie.yaml | 2 + .../package.yaml | 0 .../packageYaml.cabal} | 0 .../src/Main.hs | 0 .../cabal-add-testdata/tests/cabal.project | 1 + .../cabal-add-testdata/tests/hie.yaml | 2 + .../{cabal-add-tests => tests}/test/Main.hs | 0 .../test/MainPackageImports.hs | 0 .../tests.cabal} | 0 32 files changed, 37 insertions(+), 28 deletions(-) rename plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/{cabal-add-bench/cabal-add-bench.cabal => bench/bench.cabal} (100%) rename plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/{cabal-add-bench => bench}/bench/Main.hs (100%) create mode 100644 plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/bench/cabal.project rename plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/{ => bench}/hie.yaml (100%) delete mode 100644 plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/cabal.project create mode 100644 plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/exe/cabal.project rename plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/{cabal-add-exe/cabal-add-exe.cabal => exe/exe.cabal} (100%) create mode 100644 plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/exe/hie.yaml rename plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/{cabal-add-exe => exe}/src/Main.hs (100%) create mode 100644 plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/lib/cabal.project create mode 100644 plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/lib/hie.yaml rename plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/{cabal-add-lib/cabal-add-lib.cabal => lib/lib.cabal} (100%) rename plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/{cabal-add-lib => lib}/src/MyLib.hs (100%) rename plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/{cabal-add-multitarget => multitarget}/bench/Main.hs (100%) create mode 100644 plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/multitarget/cabal.project create mode 100644 plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/multitarget/hie.yaml rename plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/{cabal-add-multitarget => multitarget}/lib/InternalLib.hs (100%) rename plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/{cabal-add-multitarget => multitarget}/lib/MyLib.hs (100%) rename plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/{cabal-add-multitarget/cabal-add-multitarget.cabal => multitarget/multitarget.cabal} (100%) rename plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/{cabal-add-multitarget => multitarget}/src/Main.hs (100%) rename plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/{cabal-add-multitarget => multitarget}/test/Main.hs (100%) create mode 100644 plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/packageYaml/cabal.project create mode 100644 plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/packageYaml/hie.yaml rename plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/{cabal-add-packageYaml => packageYaml}/package.yaml (100%) rename plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/{cabal-add-packageYaml/cabal-add-packageYaml.cabal => packageYaml/packageYaml.cabal} (100%) rename plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/{cabal-add-packageYaml => packageYaml}/src/Main.hs (100%) create mode 100644 plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/tests/cabal.project create mode 100644 plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/tests/hie.yaml rename plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/{cabal-add-tests => tests}/test/Main.hs (100%) rename plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/{cabal-add-tests => tests}/test/MainPackageImports.hs (100%) rename plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/{cabal-add-tests/cabal-add-tests.cabal => tests/tests.cabal} (100%) diff --git a/plugins/hls-cabal-plugin/test/CabalAdd.hs b/plugins/hls-cabal-plugin/test/CabalAdd.hs index 8cbac90e43..d91cac575b 100644 --- a/plugins/hls-cabal-plugin/test/CabalAdd.hs +++ b/plugins/hls-cabal-plugin/test/CabalAdd.hs @@ -83,30 +83,29 @@ cabalAddDependencyTests :: TestTree cabalAddDependencyTests = testGroup "Add dependency" - [ runHaskellTestCaseSession "Add to executable" ("cabal-add-testdata" "cabal-add-exe") - (generateAddDependencyTestSession "cabal-add-exe.cabal" ("src" "Main.hs") "split" [253]) - , runHaskellTestCaseSession "Add to library" ("cabal-add-testdata" "cabal-add-lib") - (generateAddDependencyTestSession "cabal-add-lib.cabal" ("src" "MyLib.hs") "split" [348]) - , runHaskellTestCaseSession "Add to testsuite" ("cabal-add-testdata" "cabal-add-tests") - (generateAddDependencyTestSession "cabal-add-tests.cabal" ("test" "Main.hs") "split" [478]) - , runHaskellTestCaseSession "Add to testsuite with PackageImports" ("cabal-add-testdata" "cabal-add-tests") - (generateAddDependencyTestSession "cabal-add-tests.cabal" ("test" "MainPackageImports.hs") "split" [731]) - , runHaskellTestCaseSession "Add to benchmark" ("cabal-add-testdata" "cabal-add-bench") - (generateAddDependencyTestSession "cabal-add-bench.cabal" ("bench" "Main.hs") "split" [403]) + [ runHaskellTestCaseSession "Add to executable" ("cabal-add-testdata" "exe") + (generateAddDependencyTestSession "exe.cabal" ("src" "Main.hs") "split" [253]) + , runHaskellTestCaseSession "Add to library" ("cabal-add-testdata" "lib") + (generateAddDependencyTestSession "lib.cabal" ("src" "MyLib.hs") "split" [348]) + , runHaskellTestCaseSession "Add to testsuite" ("cabal-add-testdata" "tests") + (generateAddDependencyTestSession "tests.cabal" ("test" "Main.hs") "split" [478]) + , runHaskellTestCaseSession "Add to testsuite with PackageImports" ("cabal-add-testdata" "tests") + (generateAddDependencyTestSession "tests.cabal" ("test" "MainPackageImports.hs") "split" [731]) + , runHaskellTestCaseSession "Add to benchmark" ("cabal-add-testdata" "bench") + (generateAddDependencyTestSession "bench.cabal" ("bench" "Main.hs") "split" [403]) - , runHaskellTestCaseSession "Add to executable, multiple targets" ("cabal-add-testdata" "cabal-add-multitarget") - (generateAddDependencyTestSession "cabal-add-multitarget.cabal" ("src" "Main.hs") "split" [269]) - , runHaskellTestCaseSession "Add to library, multiple targets" ("cabal-add-testdata" "cabal-add-multitarget") - (generateAddDependencyTestSession "cabal-add-multitarget.cabal" ("lib" "MyLib.hs") "split" [413]) - , runHaskellTestCaseSession "Add to internal library, multiple targets" ("cabal-add-testdata" "cabal-add-multitarget") - (generateAddDependencyTestSession "cabal-add-multitarget.cabal" ("lib" "InternalLib.hs") "split" [413]) - , runHaskellTestCaseSession "Add to testsuite, multiple targets" ("cabal-add-testdata" "cabal-add-multitarget") - (generateAddDependencyTestSession "cabal-add-multitarget.cabal" ("test" "Main.hs") "split" [655]) - , runHaskellTestCaseSession "Add to benchmark, multiple targets" ("cabal-add-testdata" "cabal-add-multitarget") - (generateAddDependencyTestSession "cabal-add-multitarget.cabal" ("bench" "Main.hs") "split" [776]) + , runHaskellTestCaseSession "Add to executable, multiple targets" ("cabal-add-testdata" "multitarget") + (generateAddDependencyTestSession "multitarget.cabal" ("src" "Main.hs") "split" [269]) + , runHaskellTestCaseSession "Add to library, multiple targets" ("cabal-add-testdata" "multitarget") + (generateAddDependencyTestSession "multitarget.cabal" ("lib" "MyLib.hs") "split" [413]) + , runHaskellTestCaseSession "Add to internal library, multiple targets" ("cabal-add-testdata" "multitarget") + (generateAddDependencyTestSession "multitarget.cabal" ("lib" "InternalLib.hs") "split" [413]) + , runHaskellTestCaseSession "Add to testsuite, multiple targets" ("cabal-add-testdata" "multitarget") + (generateAddDependencyTestSession "multitarget.cabal" ("test" "Main.hs") "split" [655]) + , runHaskellTestCaseSession "Add to benchmark, multiple targets" ("cabal-add-testdata" "multitarget") + (generateAddDependencyTestSession "multitarget.cabal" ("bench" "Main.hs") "split" [776]) - - , runHaskellTestCaseSession "Guard against HPack" ("cabal-add-testdata" "cabal-add-packageYaml") + , runHaskellTestCaseSession "Guard against HPack" ("cabal-add-testdata" "packageYaml") (generatePackageYAMLTestSession ("src" "Main.hs")) , testHiddenPackageSuggestions "Check CabalAdd's parser, no version" diff --git a/plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/cabal-add-bench/cabal-add-bench.cabal b/plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/bench/bench.cabal similarity index 100% rename from plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/cabal-add-bench/cabal-add-bench.cabal rename to plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/bench/bench.cabal diff --git a/plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/cabal-add-bench/bench/Main.hs b/plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/bench/bench/Main.hs similarity index 100% rename from plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/cabal-add-bench/bench/Main.hs rename to plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/bench/bench/Main.hs diff --git a/plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/bench/cabal.project b/plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/bench/cabal.project new file mode 100644 index 0000000000..6f920794c8 --- /dev/null +++ b/plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/bench/cabal.project @@ -0,0 +1 @@ +packages: ./ diff --git a/plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/hie.yaml b/plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/bench/hie.yaml similarity index 100% rename from plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/hie.yaml rename to plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/bench/hie.yaml diff --git a/plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/cabal.project b/plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/cabal.project deleted file mode 100644 index 21eb1f63eb..0000000000 --- a/plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/cabal.project +++ /dev/null @@ -1,6 +0,0 @@ -packages: cabal-add-exe - cabal-add-lib - cabal-add-tests - cabal-add-bench - cabal-add-multitarget - cabal-add-packageYaml diff --git a/plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/exe/cabal.project b/plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/exe/cabal.project new file mode 100644 index 0000000000..6f920794c8 --- /dev/null +++ b/plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/exe/cabal.project @@ -0,0 +1 @@ +packages: ./ diff --git a/plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/cabal-add-exe/cabal-add-exe.cabal b/plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/exe/exe.cabal similarity index 100% rename from plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/cabal-add-exe/cabal-add-exe.cabal rename to plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/exe/exe.cabal diff --git a/plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/exe/hie.yaml b/plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/exe/hie.yaml new file mode 100644 index 0000000000..f0c7014d7f --- /dev/null +++ b/plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/exe/hie.yaml @@ -0,0 +1,2 @@ +cradle: + cabal: \ No newline at end of file diff --git a/plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/cabal-add-exe/src/Main.hs b/plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/exe/src/Main.hs similarity index 100% rename from plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/cabal-add-exe/src/Main.hs rename to plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/exe/src/Main.hs diff --git a/plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/lib/cabal.project b/plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/lib/cabal.project new file mode 100644 index 0000000000..6f920794c8 --- /dev/null +++ b/plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/lib/cabal.project @@ -0,0 +1 @@ +packages: ./ diff --git a/plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/lib/hie.yaml b/plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/lib/hie.yaml new file mode 100644 index 0000000000..f0c7014d7f --- /dev/null +++ b/plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/lib/hie.yaml @@ -0,0 +1,2 @@ +cradle: + cabal: \ No newline at end of file diff --git a/plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/cabal-add-lib/cabal-add-lib.cabal b/plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/lib/lib.cabal similarity index 100% rename from plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/cabal-add-lib/cabal-add-lib.cabal rename to plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/lib/lib.cabal diff --git a/plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/cabal-add-lib/src/MyLib.hs b/plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/lib/src/MyLib.hs similarity index 100% rename from plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/cabal-add-lib/src/MyLib.hs rename to plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/lib/src/MyLib.hs diff --git a/plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/cabal-add-multitarget/bench/Main.hs b/plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/multitarget/bench/Main.hs similarity index 100% rename from plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/cabal-add-multitarget/bench/Main.hs rename to plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/multitarget/bench/Main.hs diff --git a/plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/multitarget/cabal.project b/plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/multitarget/cabal.project new file mode 100644 index 0000000000..6f920794c8 --- /dev/null +++ b/plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/multitarget/cabal.project @@ -0,0 +1 @@ +packages: ./ diff --git a/plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/multitarget/hie.yaml b/plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/multitarget/hie.yaml new file mode 100644 index 0000000000..f0c7014d7f --- /dev/null +++ b/plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/multitarget/hie.yaml @@ -0,0 +1,2 @@ +cradle: + cabal: \ No newline at end of file diff --git a/plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/cabal-add-multitarget/lib/InternalLib.hs b/plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/multitarget/lib/InternalLib.hs similarity index 100% rename from plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/cabal-add-multitarget/lib/InternalLib.hs rename to plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/multitarget/lib/InternalLib.hs diff --git a/plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/cabal-add-multitarget/lib/MyLib.hs b/plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/multitarget/lib/MyLib.hs similarity index 100% rename from plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/cabal-add-multitarget/lib/MyLib.hs rename to plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/multitarget/lib/MyLib.hs diff --git a/plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/cabal-add-multitarget/cabal-add-multitarget.cabal b/plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/multitarget/multitarget.cabal similarity index 100% rename from plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/cabal-add-multitarget/cabal-add-multitarget.cabal rename to plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/multitarget/multitarget.cabal diff --git a/plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/cabal-add-multitarget/src/Main.hs b/plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/multitarget/src/Main.hs similarity index 100% rename from plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/cabal-add-multitarget/src/Main.hs rename to plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/multitarget/src/Main.hs diff --git a/plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/cabal-add-multitarget/test/Main.hs b/plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/multitarget/test/Main.hs similarity index 100% rename from plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/cabal-add-multitarget/test/Main.hs rename to plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/multitarget/test/Main.hs diff --git a/plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/packageYaml/cabal.project b/plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/packageYaml/cabal.project new file mode 100644 index 0000000000..6f920794c8 --- /dev/null +++ b/plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/packageYaml/cabal.project @@ -0,0 +1 @@ +packages: ./ diff --git a/plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/packageYaml/hie.yaml b/plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/packageYaml/hie.yaml new file mode 100644 index 0000000000..f0c7014d7f --- /dev/null +++ b/plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/packageYaml/hie.yaml @@ -0,0 +1,2 @@ +cradle: + cabal: \ No newline at end of file diff --git a/plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/cabal-add-packageYaml/package.yaml b/plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/packageYaml/package.yaml similarity index 100% rename from plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/cabal-add-packageYaml/package.yaml rename to plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/packageYaml/package.yaml diff --git a/plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/cabal-add-packageYaml/cabal-add-packageYaml.cabal b/plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/packageYaml/packageYaml.cabal similarity index 100% rename from plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/cabal-add-packageYaml/cabal-add-packageYaml.cabal rename to plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/packageYaml/packageYaml.cabal diff --git a/plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/cabal-add-packageYaml/src/Main.hs b/plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/packageYaml/src/Main.hs similarity index 100% rename from plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/cabal-add-packageYaml/src/Main.hs rename to plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/packageYaml/src/Main.hs diff --git a/plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/tests/cabal.project b/plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/tests/cabal.project new file mode 100644 index 0000000000..6f920794c8 --- /dev/null +++ b/plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/tests/cabal.project @@ -0,0 +1 @@ +packages: ./ diff --git a/plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/tests/hie.yaml b/plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/tests/hie.yaml new file mode 100644 index 0000000000..f0c7014d7f --- /dev/null +++ b/plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/tests/hie.yaml @@ -0,0 +1,2 @@ +cradle: + cabal: \ No newline at end of file diff --git a/plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/cabal-add-tests/test/Main.hs b/plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/tests/test/Main.hs similarity index 100% rename from plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/cabal-add-tests/test/Main.hs rename to plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/tests/test/Main.hs diff --git a/plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/cabal-add-tests/test/MainPackageImports.hs b/plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/tests/test/MainPackageImports.hs similarity index 100% rename from plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/cabal-add-tests/test/MainPackageImports.hs rename to plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/tests/test/MainPackageImports.hs diff --git a/plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/cabal-add-tests/cabal-add-tests.cabal b/plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/tests/tests.cabal similarity index 100% rename from plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/cabal-add-tests/cabal-add-tests.cabal rename to plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/tests/tests.cabal From b2c0349381de9d55fef7dddd1ce6758a2e2273aa Mon Sep 17 00:00:00 2001 From: Fendor Date: Sat, 17 May 2025 18:09:03 +0200 Subject: [PATCH 5/7] Make hls-test-root name shorter --- hls-test-utils/src/Test/Hls.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hls-test-utils/src/Test/Hls.hs b/hls-test-utils/src/Test/Hls.hs index b695ad6b22..5e0852a0ff 100644 --- a/hls-test-utils/src/Test/Hls.hs +++ b/hls-test-utils/src/Test/Hls.hs @@ -609,7 +609,7 @@ instance Default (TestConfig b) where setupTestEnvironment :: IO FilePath setupTestEnvironment = do tmpDirRoot <- getTemporaryDirectory - let testRoot = tmpDirRoot "hls-test-root" + let testRoot = tmpDirRoot "hls-tests" createDirectoryIfMissing True testRoot pure testRoot From f294faa2ab34ae3fd95b247576ce31cf805fdb47 Mon Sep 17 00:00:00 2001 From: fendor Date: Sat, 14 Jun 2025 12:03:44 +0200 Subject: [PATCH 6/7] Revert `mkHomeModLocation` changes --- ghcide/src/Development/IDE/Core/Compile.hs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ghcide/src/Development/IDE/Core/Compile.hs b/ghcide/src/Development/IDE/Core/Compile.hs index 3c41aa260f..48439e2ff3 100644 --- a/ghcide/src/Development/IDE/Core/Compile.hs +++ b/ghcide/src/Development/IDE/Core/Compile.hs @@ -1122,7 +1122,11 @@ getModSummaryFromImports env fp _modTime mContents = do liftIO $ evaluate $ rnf textualImports - modLoc <- liftIO $ mkHomeModLocation dflags mod fp + modLoc <- liftIO $ if mod == mAIN_NAME + -- specially in tests it's common to have lots of nameless modules + -- mkHomeModLocation will map them to the same hi/hie locations + then mkHomeModLocation dflags (pathToModuleName fp) fp + else mkHomeModLocation dflags mod fp let modl = mkHomeModule (hscHomeUnit ppEnv) mod sourceType = if "-boot" `isSuffixOf` takeExtension fp then HsBootFile else HsSrcFile From 88c568708b3949fa08424520d97b1145e1c48186 Mon Sep 17 00:00:00 2001 From: fendor Date: Tue, 28 Oct 2025 09:33:14 +0100 Subject: [PATCH 7/7] Overwrite test root dir on windows CI job Adds support for the `HLS_TEST_ROOTDIR` which allows to overwrite the location for the test case artifacts. --- .github/actions/setup-build/action.yml | 7 +++++++ hls-test-utils/src/Test/Hls.hs | 14 ++++++++++---- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/.github/actions/setup-build/action.yml b/.github/actions/setup-build/action.yml index 60cd4738f6..c2d07d5228 100644 --- a/.github/actions/setup-build/action.yml +++ b/.github/actions/setup-build/action.yml @@ -44,6 +44,13 @@ runs: echo "CABAL_PKGS_DIR=C:\\cabal\\packages" >> $GITHUB_ENV shell: bash + - if: inputs.os == 'Windows' + name: (Windows) Platform config (root test directory) + run: | + mkdir C:\\hls-tests + echo "HLS_TEST_ROOTDIR=C:\\hls-tests" >> $GITHUB_ENV + shell: bash + - if: ( inputs.os == 'Linux' ) || ( inputs.os == 'macOS' ) name: (Linux,macOS) Platform config run: | diff --git a/hls-test-utils/src/Test/Hls.hs b/hls-test-utils/src/Test/Hls.hs index 5e0852a0ff..1e05e0fa20 100644 --- a/hls-test-utils/src/Test/Hls.hs +++ b/hls-test-utils/src/Test/Hls.hs @@ -608,10 +608,16 @@ instance Default (TestConfig b) where -- However, it is totally safe to delete the directory between runs. setupTestEnvironment :: IO FilePath setupTestEnvironment = do - tmpDirRoot <- getTemporaryDirectory - let testRoot = tmpDirRoot "hls-tests" - createDirectoryIfMissing True testRoot - pure testRoot + mRootDir <- lookupEnv "HLS_TEST_ROOTDIR" + case mRootDir of + Nothing -> do + tmpDirRoot <- getTemporaryDirectory + let testRoot = tmpDirRoot "hls-test-root" + createDirectoryIfMissing True testRoot + pure testRoot + Just rootDir -> do + createDirectoryIfMissing True rootDir + pure rootDir goldenWithHaskellDocFormatter :: Pretty b