content: module Harness ( goldenOutput
                 , crossGolden
                 ) where
  
  import qualified Data.ByteString.Lazy       as BSL
  import qualified Data.ByteString.Lazy.Char8 as ASCII
  import           Data.Functor               (void)
  import           Kempe.File
  import           System.FilePath            ((</>))
  import           System.IO.Temp
  import           System.Info                (arch)
  import           System.Process             (CreateProcess (env, std_err), StdStream (Inherit), proc, readCreateProcess)
  import           Test.Tasty
  import           Test.Tasty.Golden          (goldenVsString)
  
  data CC = CC
          | ArmCC
  
  instance Show CC where
      show CC    = "cc"
      show ArmCC = "aarch64-linux-gnu-gcc"
  
  runGcc :: CC
         -> [FilePath]
         -> FilePath
         -> IO ()
  runGcc cc fps o =
      void $ readCreateProcess ((proc (show cc) (fps ++ ["-o", o])) { std_err = Inherit }) ""
  
  compileOutput :: FilePath
                -> FilePath
                -> IO BSL.ByteString
  compileOutput fp harness =
      withSystemTempDirectory "kmp" $ \dir -> do
          let oFile = dir </> "kempe.o"
              exe = dir </> "kempe"
              compiler = case arch of
                  "x86_64"  -> compile
                  "aarch64" -> armCompile
                  _         -> error "Internal error in test suite! Must run on either x86_64 or aarch64"
          compiler fp oFile False
          runGcc CC [oFile, harness] exe
          readExe exe
      where readExe fp' = ASCII.pack <$> readCreateProcess ((proc fp' []) { std_err = Inherit }) ""
  
  crossCompileOutput :: FilePath
                     -> FilePath
                     -> IO BSL.ByteString
  crossCompileOutput fp harness =
      withSystemTempDirectory "kmp" $ \dir -> do
          let oFile = dir </> "kempe.o"
              exe = dir </> "kempe"
          armCompile fp oFile False
          runGcc ArmCC [oFile, harness] exe
          readExe exe
      where readExe fp' = ASCII.pack <$> readCreateProcess ((proc "qemu-aarch64-static" [fp']) { std_err = Inherit, env = qemuEnv }) ""
            qemuEnv = Just [("QEMU_LD_PREFIX", "/usr/aarch64-linux-gnu/")]
  
  goldenOutput :: FilePath -- ^ Kempe file
               -> FilePath -- ^ C test harness
               -> FilePath -- ^ Golden file path
               -> TestTree
  goldenOutput kFp cFp golden =
      goldenVsString kFp golden (compileOutput kFp cFp)
  
  crossGolden :: FilePath -- ^ Kempe file
              -> FilePath -- ^ C test harness
              -> FilePath -- ^ Golden file path
              -> TestTree
  crossGolden kFp cFp golden =
      goldenVsString kFp golden (crossCompileOutput kFp cFp)
  