1
votes

I'm trying to correctly compile my test suite for a haskell project which uses the CPP extension to conditionally import different modules. One module will send output to the network, and the other to the terminal, for debugging.

This works fine, but when I try and set up my test suite, it doesn't seem to respect the cpp-options set in the .cabal file, and instead always builds the networked version.

Cabal file:

name:           server
version:        0.1.0.0
build-type:     Simple
cabal-version:  >= 1.10

library
  hs-source-dirs:
      src
  build-depends:
      base >=4.9 && <=4.11
    , lens
    , random
    , transformers
    , safe
    , uuid-types
    , QuickCheck
    , network
    , bytestring
    , binary
  exposed-modules:
      Betting
      Game
      Input.Network.Input
      Input.Terminal.Input
      Lenses
      Main
      Output.Network.Output
      Output.Terminal.InputMessages
      Output.Terminal.Output
      Output.Terminal.OutputMessages
      RunLocal
      RunNetwork
      Showdown
      Showdown.Best
      Showdown.Ord
      Showdown.Value
      TestStates
      Types
      Utilities.Card
      Utilities.Player
      Utilities.Showdown
      Utilities.Terminal.Output
      Utilities.Types
  other-modules:
      Paths_server
  default-language: Haskell2010

executable local-server
  main-is: Main.hs
  hs-source-dirs:
      src
  cpp-options: -DDEBUG
  build-depends:
      base >=4.9 && <=4.11
    , lens
    , random
    , transformers
    , safe
    , uuid-types
    , QuickCheck
    , server
  other-modules:
      Betting
      Game
      Input.Network.Input
      Input.Terminal.Input
      Lenses
      Output.Network.Output
      Output.Terminal.InputMessages
      Output.Terminal.Output
      Output.Terminal.OutputMessages
      RunLocal
      RunNetwork
      Showdown
      Showdown.Best
      Showdown.Ord
      Showdown.Value
      TestStates
      Types
      Utilities.Card
      Utilities.Player
      Utilities.Showdown
      Utilities.Terminal.Output
      Utilities.Types
  default-language: Haskell2010

executable networked-server
  main-is: Main.hs
  hs-source-dirs:
      src
  build-depends:
      base >=4.9 && <=4.11
    , lens
    , random
    , transformers
    , safe
    , uuid-types
    , QuickCheck
    , server
    , network
    , bytestring
    , binary
  other-modules:
      Betting
      Game
      Input.Network.Input
      Input.Terminal.Input
      Lenses
      Output.Network.Output
      Output.Terminal.InputMessages
      Output.Terminal.Output
      Output.Terminal.OutputMessages
      RunLocal
      RunNetwork
      Showdown
      Showdown.Best
      Showdown.Ord
      Showdown.Value
      TestStates
      Types
      Utilities.Card
      Utilities.Player
      Utilities.Showdown
      Utilities.Terminal.Output
      Utilities.Types
  default-language: Haskell2010

test-suite test-server
  type: exitcode-stdio-1.0
  main-is: Tests.hs
  hs-source-dirs:
      tests
  cpp-options: -DDEBUG
  build-depends:
      base >=4.9 && <=4.11
    , lens
    , random
    , transformers
    , safe
    , uuid-types
    , QuickCheck
    , server
    , poker-eval
  other-modules:
      BettingTests
      CardTests
      PlayerTests
      ShowdownTests
  default-language: Haskell2010

An example of one of the modules that get compiled conditionally:

{-# LANGUAGE CPP #-}

module Utilities.Card where

#ifdef DEBUG
import Output.Terminal.Output (outputPlayerCards)
#else
import Output.Network.Output (outputPlayerCards)
#endif

dealCards :: GameStateT ()
dealCards = do
    updateCards =<< numPlayersT
    outputPlayerCards

In my test suite, the network version of outputPlayerCards always gets called, despite have in the cpp-options: -DDEBUG set.

However, the networked-server and local-server are correctly compiled, and call the appropriate functions.

My previous method of having just one executable which was compiled for network or local with a flag worked, however I read that it's not the correct way to write a test suite, as I wasn't linking aginst it, and rather building it directly by including its source directory in the .cabal file.

I'm using stack to build, and can include that file if needed.

1

1 Answers

1
votes

I would use a cabal flag: when set to true, compile the local debug version of the library and test suite; when set to false, compile the networked version of the library but disable the test suite.

You should also put the main files for the executables in a separate directory from the library, which is the main reason behind the issue you mention about not linking against the library.