Skip to content
Permalink
Browse files

Merge #1101

1101: tests: Use TH for getting data directory r=rvl a=rvl

Relates to a previous PR #976 and is needed for running tests on Windows/Wine.

# Overview

We need a method of locating the data directories of the test suites that works in multiple situations:

 - stack build (working directory at .cabal file)
 - stack ghci (working directory is project root)
 - ghci (not using cabal)
 - in the Nix build (working directory is at project root)
 - when running windows tests (the install prefix baked in to Paths_
   will always be wrong)

With `Paths_cardano_wallet_jormungandr.getDataDir`, only the first two work.

Using `makeRelativeToProject` in a TH splice seems to work in all situations.

Example error with ghci and `Paths_`

    :l lib/jormungandr/test/unit/Cardano/Wallet/Jormungandr/BinarySpec.hs
    Ok, 24 modules loaded.
    λ> hspec spec
    *** Exception: /home/rodney/.cabal/share/x86_64-linux-ghc-8.6.5/cardano-wallet-jormungandr-2019.11.18/block0s: getDirectoryContents:openDirStream: does not exist (No such file or directory)

Example error with nix-build:

    Linking dist/build/unit/unit ...
    running tests
    unit: /nix/store/8kgw4dkyx6yl68if3vdk83vx64v7zkw7-cardano-wallet-jormungandr-2019.11.18-test-unit/share/x86_64-osx-ghc-8.6.5/cardano-wallet-jormungandr-2019.11.18/block0s: getDirectoryContents:openDirStream: does not exist (No such file or directory)
    builder for '/nix/store/z5dphvdqafx9y2nvzch4clhg5j6iyvh6-cardano-wallet-jormungandr-2019.11.18-test-unit.drv' failed with exit code 1

This nix-build error is arguably a bug in Haskell.nix (or maybe it's even a limitation of Cabal). The tests install prefix is different from the library install prefix. Either the tests should be referring to paths in the library install prefix, or the data files should be copied into the tests install prefix. Either way, something needs to be fixed.

Example error on Windows:

    C:\Users\win\cw>cardano-wallet-jormungandr-2019.11.18-test-unit.exe
    cardano-wallet-jormungandr-2019.11.18-test-unit.exe: /nix/store/rhdan17ab6f4310ibfcjiyhgjx48b7yh-cardano-wallet-jormungandr-2019.11.18-test-unit-x86_64-pc-mingw32/share/x86_64-windows-ghc-8.6.5/cardano-wallet-jormungandr-2019.11.18\block0s: getDirectoryContents:findFirstFile: does not exist (The system cannot find the path specified.)

Under Windows, installation prefixes such as /usr/local do not make sense. So it should just be searching for data in the current directory.


Co-authored-by: Rodney Lorrimar <rodney.lorrimar@iohk.io>
Co-authored-by: KtorZ <matthias.benkort@gmail.com>
  • Loading branch information
3 people committed Dec 3, 2019
2 parents c762580 + a81625b commit fe457b6294bffaaa8e48a5a94f01ae0cd4a0553f
@@ -38,8 +38,6 @@ import Data.Aeson
( encode )
import Data.ByteString
( ByteString )
import Data.FileEmbed
( makeRelativeToProject )
import Data.Maybe
( mapMaybe )
import Network.Wai.Application.Static
@@ -67,11 +65,12 @@ import Test.QuickCheck
)
import Test.QuickCheck.Monadic
( assert, monadicIO, monitor, run )
import Test.Utils.Paths
( getTestData )

import qualified Data.ByteString.Char8 as B8
import qualified Data.ByteString.Lazy as BL
import qualified Data.Text as T
import qualified Language.Haskell.TH.Syntax as TH

spec :: Spec
spec = do
@@ -110,8 +109,7 @@ testServer root = withApplication (pure app)
where app = staticApp $ defaultWebAppSettings root

dataDir :: FilePath
dataDir = $( TH.LitE . TH.StringL <$>
makeRelativeToProject "test/data/stake-pool-registry" )
dataDir = $(getTestData) </> "stake-pool-registry"

-- | Make a file server URL for the test data file.
-- This file was downloaded from <https://github.com/input-output-hk/testnet-stake-pool-registry/archive/master.zip>
@@ -236,6 +236,8 @@ import Test.QuickCheck.Arbitrary.Generic
( genericArbitrary, genericShrink )
import Test.Text.Roundtrip
( textRoundtrip )
import Test.Utils.Paths
( getTestData )
import Test.Utils.Time
( genUniformTime )
import Web.HttpApiData
@@ -788,8 +790,7 @@ jsonRoundtripAndGolden proxy = do
settings :: Settings
settings = defaultSettings
{ goldenDirectoryOption =
CustomDirectoryName $ foldr (</>) mempty
[ "test", "data", "Cardano", "Wallet", "Api" ]
CustomDirectoryName ($(getTestData) </> "Cardano" </> "Wallet" </> "Api")
, useModuleNameAsSubDirectory =
False
, sampleSize = 10
@@ -12,13 +12,6 @@ build-type: Simple
extra-source-files: README.md
cabal-version: >=1.10

data-dir: test/data
data-files:
block0s/*.bin
jormungandr/block0.bin
jormungandr/config.yaml
jormungandr/secret.yaml

flag development
description: Disable `-Werror`
default: False
@@ -175,7 +168,6 @@ test-suite unit
Cardano.Wallet.Jormungandr.CompatibilitySpec
Cardano.Wallet.Jormungandr.NetworkSpec
Cardano.Wallet.Jormungandr.TransactionSpec
Paths_cardano_wallet_jormungandr

test-suite integration
default-language:
@@ -259,4 +251,3 @@ test-suite integration
Test.Integration.Jormungandr.Scenario.CLI.Server
Test.Integration.Jormungandr.Scenario.CLI.StakePools
Test.Integration.Jormungandr.Scenario.CLI.Transactions
Paths_cardano_wallet_jormungandr
@@ -1,6 +1,7 @@
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeApplications #-}

module Cardano.Faucet
@@ -57,8 +58,6 @@ import Data.ByteString
( ByteString )
import Data.Text
( Text )
import Paths_cardano_wallet_jormungandr
( getDataFileName )
import System.Command
( CmdResult, Stdout (..), command )
import System.FilePath
@@ -67,6 +66,8 @@ import System.IO.Temp
( withSystemTempDirectory )
import Test.Integration.Faucet
( Faucet (..) )
import Test.Utils.Paths
( getTestData )

import qualified Codec.Binary.Bech32 as Bech32
import qualified Data.ByteString as BS
@@ -84,10 +85,9 @@ initFaucet = Faucet
<*> newMVar (mkTxBuilder <$> externalAddresses)

getBlock0H :: IO (Hash "Genesis")
getBlock0H = do
block0 <- getDataFileName "jormungandr/block0.bin"
extractId <$> BL.readFile block0
getBlock0H = extractId <$> BL.readFile block0
where
block0 = $(getTestData) </> "jormungandr" </> "block0.bin"
extractId = Hash . getHash . runGet getBlockId

getBlock0HText :: IO Text
@@ -1,4 +1,5 @@
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TemplateHaskell #-}

-- |
-- Copyright: © 2018-2019 IOHK
@@ -22,8 +23,6 @@ import Cardano.Wallet.Jormungandr.Network
( JormungandrConfig (..), JormungandrConnParams, withJormungandr )
import Control.Exception
( bracket, throwIO )
import Paths_cardano_wallet_jormungandr
( getDataFileName )
import System.Directory
( doesDirectoryExist, removeDirectoryRecursive )
import System.Environment
@@ -34,6 +33,8 @@ import System.IO
( IOMode (..), hClose, openFile )
import System.IO.Temp
( createTempDirectory, getCanonicalTemporaryDirectory )
import Test.Utils.Paths
( getTestData )

-- | Starts jormungandr on a random port using the integration tests config.
-- The data directory will be stored in a unique location under the system
@@ -43,9 +44,10 @@ withConfig = bracket setupConfig teardownConfig

setupConfig :: IO JormungandrConfig
setupConfig = do
block0 <- getDataFileName "jormungandr/block0.bin"
secret <- getDataFileName "jormungandr/secret.yaml"
config <- getDataFileName "jormungandr/config.yaml"
let testData = $(getTestData) </> "jormungandr"
let block0 = testData </> "block0.bin"
let secret = testData </> "secret.yaml"
let config = testData </> "config.yaml"
tmp <- getCanonicalTemporaryDirectory
stateDir <- createTempDirectory tmp "cardano-wallet-jormungandr"
logFile <- openFile (stateDir </> "jormungandr.log") WriteMode
@@ -1,6 +1,7 @@
{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TupleSections #-}
{-# LANGUAGE TypeApplications #-}

@@ -30,8 +31,6 @@ import Data.Text.Class
( toText )
import Network.HTTP.Client
( defaultManagerSettings, newManager )
import Paths_cardano_wallet_jormungandr
( getDataFileName )
import System.Command
( Exit (..), Stderr (..), Stdout (..) )
import System.Directory
@@ -47,7 +46,7 @@ import System.IO.Temp
import System.Process
( terminateProcess, withCreateProcess )
import Test.Hspec
( Spec, describe, it, pendingWith, runIO )
( Spec, describe, it, pendingWith )
import Test.Hspec.Expectations.Lifted
( shouldBe, shouldContain )
import Test.Integration.Framework.DSL
@@ -63,15 +62,18 @@ import Test.Integration.Framework.DSL
, state
, waitForServer
)
import Test.Utils.Paths
( getTestData )
import Test.Utils.Ports
( findPort )

import qualified Data.Text.IO as TIO

spec :: forall t. (KnownCommand t) => Spec
spec = do
block0 <- runIO $ getDataFileName "jormungandr/block0.bin"
secret <- runIO $ getDataFileName "jormungandr/secret.yaml"
let testData = $(getTestData) </> "jormungandr"
let block0 = testData </> "block0.bin"
let secret = testData </> "secret.yaml"
describe "LAUNCH - cardano-wallet launch [SERIAL]" $ do
it "LAUNCH - Stop when --state-dir is an existing file" $ withTempFile $ \f _ -> do
let args =
@@ -5,6 +5,7 @@
{-# LANGUAGE OverloadedLabels #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TupleSections #-}
{-# LANGUAGE TypeApplications #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}
@@ -70,8 +71,6 @@ import Data.Word
( Word8 )
import GHC.Generics
( Generic )
import Paths_cardano_wallet_jormungandr
( getDataDir, getDataFileName )
import System.Directory
( getDirectoryContents )
import System.FilePath
@@ -100,6 +99,8 @@ import Test.QuickCheck.Arbitrary.Generic
( genericArbitrary, genericShrink )
import Test.QuickCheck.Monadic
( assert, monadicIO, monitor, run )
import Test.Utils.Paths
( getTestData )

import qualified Data.ByteString as BS
import qualified Data.ByteString.Char8 as B8
@@ -109,12 +110,12 @@ spec :: Spec
spec = do
describe "Decoding" $ do
it "should decode the block0.bin used for integration tests" $ do
bs <- BL.readFile =<< getDataFileName "jormungandr/block0.bin"
bs <- BL.readFile ($(getTestData) </> "jormungandr/block0.bin")
res <- try' (runGet getBlock bs)
res `shouldSatisfy` isRight

describe "golden block0s generated in jormungandr-lib" $ do
dir <- (</> "block0s") <$> runIO getDataDir
let dir = $(getTestData) </> "block0s"
files <- runIO $ filter (".bin" `isSuffixOf`)
<$> getDirectoryContents dir
forM_ files $ \filename -> do
@@ -31,18 +31,22 @@ library
build-depends:
base
, async
, filepath
, file-embed
, hspec
, hspec-core
, hspec-expectations
, network
, QuickCheck
, random-shuffle
, template-haskell
, time
, unliftio
hs-source-dirs:
src
exposed-modules:
Test.Hspec.Extra
Test.Utils.Paths
Test.Utils.Ports
Test.Utils.Time
Test.Utils.Windows
@@ -0,0 +1,24 @@
-- |
-- Copyright: © 2018-2019 IOHK
-- License: Apache-2.0
--
-- Utility function for finding the package test data directory.

module Test.Utils.Paths
( getTestData
) where

import Prelude

import Data.FileEmbed
( makeRelativeToProject )
import Language.Haskell.TH.Syntax
( Exp, Q, liftData )
import System.FilePath
( (</>) )

-- | A TH function to get the test data directory. It combines the current
-- source file location and cabal file to locate the package directory in such a
-- way that works in both the package build and ghci.
getTestData :: Q Exp
getTestData = makeRelativeToProject ("test" </> "data") >>= liftData

Some generated files are not rendered by default. Learn more.

0 comments on commit fe457b6

Please sign in to comment.
You can’t perform that action at this time.