{-# LANGUAGE Haskell2010 #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE ImportQualifiedPost #-}
{-# LANGUAGE NoFieldSelectors #-}
{-# LANGUAGE OverloadedRecordDot #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
module Main where
import Tax.Canada.Province.ON qualified as ON
import Tax.Canada.Province.AB qualified as AB (t1Fields)
import Tax.Canada.Province.BC qualified as BC (t1Fields)
import Tax.Canada.T1 (T1, fixT1)
import Tax.FDF as FDF
import Control.Monad.IO.Class (liftIO)
import Data.ByteString qualified as ByteString
import Data.ByteString.Lazy (fromStrict)
import Data.Foldable (toList)
import Data.Functor.Const (Const (Const, getConst))
import Data.List qualified as List
import Data.Map qualified as Map
import Data.Maybe (fromMaybe)
import Data.Semigroup (All (All, getAll))
import Data.Text (Text)
import Data.Text qualified as Text
import Rank2 qualified
import System.Directory (doesDirectoryExist, listDirectory)
import System.Exit (die)
import System.FilePath.Posix (combine)
import Text.FDF (FDF, parse, serialize)
import Text.FDF qualified
import Test.Tasty
import Test.Tasty.Golden
main = listDirectory inputDir >>= traverse test >>= defaultMain . testGroup "Regression"
rootDir, inputDir, outputDir, referenceDir :: FilePath
rootDir = combine "test" "regression"
inputDir = combine rootDir "inputs"
outputDir = combine rootDir "outputs"
referenceDir = combine rootDir "reference"
test :: FilePath -> IO TestTree
test path = do
let inputPath = combine inputDir path
isDir <- liftIO (doesDirectoryExist inputPath)
if isDir
then testReturn path
else testT1 path
testT1 :: FilePath -> IO TestTree
testT1 path = do
fdfBytes <- ByteString.readFile $ combine inputDir path
case parse fdfBytes of
Left err -> die err
Right fdf ->
pure $
goldenVsString path
(combine referenceDir path)
(pure $ fromStrict $ serialize $ either error id $ FDF.mapForm ON.t1Fields fixT1 fdf)
testReturn :: FilePath -> IO TestTree
testReturn path = do
let inputPath = combine inputDir path
fdfFileNames <- listDirectory inputPath
fdfBytes <- traverse (ByteString.readFile . combine inputPath) fdfFileNames
case traverse parse fdfBytes of
Left err -> die err
Right fdfs -> case FDF.mapForms ON.returnFields ON.fixReturns (Map.fromList $ zip (formKey <$> fdfFileNames) fdfs) of
Left err -> die err
Right filled
| let fdfOutputs = fromStrict . serialize <$> filled
diff ref new = ["diff", "-uw", ref, new]
compare key fdfOutput
| let Just fileName = List.find ((key ==) . formKey) fdfFileNames
= pure $ goldenVsStringDiff fileName diff (combine referenceDir $ combine path fileName) (pure fdfOutput)
-> testGroup path . toList <$> Map.traverseWithKey compare fdfOutputs
formKey :: FilePath -> Text
formKey "5000-s6-fill-23e.fdf" = "Schedule6"
formKey "5006-c-fill-23e.fdf" = "428"
formKey "5006-r-fill-23e.fdf" = "T1"
formKey name = error ("File name " <> name <> " is not recognized as a form.")