@@ -507,32 +507,73 @@ runSessionWithServerInTmpDir config plugin tree act =
507
507
{testLspConfig= config, testPluginDescriptor = plugin, testDirLocation= Right tree}
508
508
(const act)
509
509
510
- runWithLockInTempDir :: VirtualFileTree -> (FileSystem -> IO a ) -> IO a
511
- runWithLockInTempDir tree act = withLock lockForTempDirs $ do
510
+ -- | Same as 'withTemporaryDataAndCacheDirectory', but materialises the given
511
+ -- 'VirtualFileTree' in the temporary directory.
512
+ withVfsTestDataDirectory :: VirtualFileTree -> (FileSystem -> IO a ) -> IO a
513
+ withVfsTestDataDirectory tree act = do
514
+ withTemporaryDataAndCacheDirectory $ \ tmpRoot -> do
515
+ fs <- FS. materialiseVFT tmpRoot tree
516
+ act fs
517
+
518
+ -- | Run an action in a temporary directory.
519
+ -- Sets the 'XDG_CACHE_HOME' environment variable to a temporary directory as well.
520
+ --
521
+ -- This sets up a temporary directory for HLS tests to run.
522
+ -- Typically, HLS tests copy their test data into the directory and then launch
523
+ -- the HLS session in that directory.
524
+ -- This makes sure that the tests are run in isolation, which is good for correctness
525
+ -- but also important to have fast tests.
526
+ --
527
+ -- For improved isolation, we also make sure the 'XDG_CACHE_HOME' environment
528
+ -- variable points to a temporary directory. So, we never share interface files
529
+ -- or the 'hiedb' across tests.
530
+ withTemporaryDataAndCacheDirectory :: (FilePath -> IO a ) -> IO a
531
+ withTemporaryDataAndCacheDirectory act = withLock lockForTempDirs $ do
512
532
testRoot <- setupTestEnvironment
513
533
helperRecorder <- hlsHelperTestRecorder
514
534
-- Do not clean up the temporary directory if this variable is set to anything but '0'.
515
535
-- Aids debugging.
516
536
cleanupTempDir <- lookupEnv " HLS_TEST_HARNESS_NO_TESTDIR_CLEANUP"
517
537
let runTestInDir action = case cleanupTempDir of
518
538
Just val | val /= " 0" -> do
519
- (tempDir, _) <- newTempDirWithin testRoot
520
- a <- action tempDir
539
+ (tempDir, cacheHome, _) <- setupTemporaryTestDirectories testRoot
540
+ a <- withTempCacheHome cacheHome ( action tempDir)
521
541
logWith helperRecorder Debug LogNoCleanup
522
542
pure a
523
543
524
544
_ -> do
525
- (tempDir, cleanup) <- newTempDirWithin testRoot
526
- a <- action tempDir `finally` cleanup
545
+ (tempDir, cacheHome, cleanup) <- setupTemporaryTestDirectories testRoot
546
+ a <- withTempCacheHome cacheHome ( action tempDir) `finally` cleanup
527
547
logWith helperRecorder Debug LogCleanup
528
548
pure a
529
549
runTestInDir $ \ tmpDir' -> do
530
550
-- we canonicalize the path, so that we do not need to do
531
- -- cannibalization during the test when we compare two paths
551
+ -- canonicalization during the test when we compare two paths
532
552
tmpDir <- canonicalizePath tmpDir'
533
553
logWith helperRecorder Info $ LogTestDir tmpDir
534
- fs <- FS. materialiseVFT tmpDir tree
535
- act fs
554
+ act tmpDir
555
+ where
556
+ cache_home_var = " XDG_CACHE_HOME"
557
+ -- Set the dir for "XDG_CACHE_HOME".
558
+ -- When the operation finished, make sure the old value is restored.
559
+ withTempCacheHome tempCacheHomeDir act =
560
+ bracket
561
+ (do
562
+ old_cache_home <- lookupEnv cache_home_var
563
+ setEnv cache_home_var tempCacheHomeDir
564
+ pure old_cache_home)
565
+ (\ old_cache_home ->
566
+ maybe (pure () ) (setEnv cache_home_var) old_cache_home
567
+ )
568
+ (\ _ -> act)
569
+
570
+ -- Set up a temporary directory for the test files and one for the 'XDG_CACHE_HOME'.
571
+ -- The 'XDG_CACHE_HOME' is important for independent test runs, i.e. completely empty
572
+ -- caches.
573
+ setupTemporaryTestDirectories testRoot = do
574
+ (tempTestCaseDir, cleanup1) <- newTempDirWithin testRoot
575
+ (tempCacheHomeDir, cleanup2) <- newTempDirWithin testRoot
576
+ pure (tempTestCaseDir, tempCacheHomeDir, cleanup1 >> cleanup2)
536
577
537
578
runSessionWithServer :: Pretty b => Config -> PluginTestDescriptor b -> FilePath -> Session a -> IO a
538
579
runSessionWithServer config plugin fp act =
@@ -565,17 +606,11 @@ instance Default (TestConfig b) where
565
606
-- It returns the root to the testing directory that tests should use.
566
607
-- This directory is not fully cleaned between reruns.
567
608
-- However, it is totally safe to delete the directory between runs.
568
- --
569
- -- Additionally, this overwrites the 'XDG_CACHE_HOME' variable to isolate
570
- -- the tests from existing caches. 'hie-bios' and 'ghcide' honour the
571
- -- 'XDG_CACHE_HOME' environment variable and generate their caches there.
572
609
setupTestEnvironment :: IO FilePath
573
610
setupTestEnvironment = do
574
611
tmpDirRoot <- getTemporaryDirectory
575
612
let testRoot = tmpDirRoot </> " hls-test-root"
576
- testCacheDir = testRoot </> " .cache"
577
- createDirectoryIfMissing True testCacheDir
578
- setEnv " XDG_CACHE_HOME" testCacheDir
613
+ createDirectoryIfMissing True testRoot
579
614
pure testRoot
580
615
581
616
goldenWithHaskellDocFormatter
@@ -692,7 +727,6 @@ lockForTempDirs = unsafePerformIO newLock
692
727
data TestConfig b = TestConfig
693
728
{
694
729
testDirLocation :: Either FilePath VirtualFileTree
695
- -- ^ Client capabilities
696
730
-- ^ The file tree to use for the test, either a directory or a virtual file tree
697
731
-- if using a virtual file tree,
698
732
-- Creates a temporary directory, and materializes the VirtualFileTree
@@ -747,8 +781,20 @@ wrapClientLogger logger = do
747
781
return (lspLogRecorder <> logger, cb1)
748
782
749
783
-- | Host a server, and run a test session on it.
750
- -- For setting custom timeout, set the environment variable 'LSP_TIMEOUT'
751
- -- * LSP_TIMEOUT=10 cabal test
784
+ --
785
+ -- Environment variables are used to influence logging verbosity, test cleanup and test execution:
786
+ --
787
+ -- * @LSP_TIMEOUT@: Set a specific test timeout in seconds.
788
+ -- * @LSP_TEST_LOG_MESSAGES@: Log the LSP messages between the client and server.
789
+ -- * @LSP_TEST_LOG_STDERR@: Log the stderr of the server to the stderr of this process.
790
+ -- * @HLS_TEST_HARNESS_STDERR@: Log test setup messages.
791
+ --
792
+ -- Test specific environment variables:
793
+ --
794
+ -- * @HLS_TEST_PLUGIN_LOG_STDERR@: Log all messages of the hls plugin under test to stderr.
795
+ -- * @HLS_TEST_LOG_STDERR@: Log all HLS messages to stderr.
796
+ -- * @HLS_TEST_HARNESS_NO_TESTDIR_CLEANUP@: Don't remove the test directories after test execution.
797
+ --
752
798
-- For more detail of the test configuration, see 'TestConfig'
753
799
runSessionWithTestConfig :: Pretty b => TestConfig b -> (FilePath -> Session a ) -> IO a
754
800
runSessionWithTestConfig TestConfig {.. } session =
@@ -792,8 +838,10 @@ runSessionWithTestConfig TestConfig{..} session =
792
838
else f
793
839
runSessionInVFS (Left testConfigRoot) act = do
794
840
root <- makeAbsolute testConfigRoot
795
- act root
796
- runSessionInVFS (Right vfs) act = runWithLockInTempDir vfs $ \ fs -> act (fsRoot fs)
841
+ withTemporaryDataAndCacheDirectory (const $ act root)
842
+ runSessionInVFS (Right vfs) act =
843
+ withVfsTestDataDirectory vfs $ \ fs -> do
844
+ act (fsRoot fs)
797
845
testingArgs prjRoot recorderIde plugins =
798
846
let
799
847
arguments@ Arguments { argsHlsPlugins, argsIdeOptions, argsLspOptions } = defaultArguments (cmapWithPrio LogIDEMain recorderIde) prjRoot plugins
0 commit comments