packages feed

demangler-1.1.0.0: test/Test.hs

{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TypeApplications #-}

module Main (main) where

import           Control.Monad.Trans.State
import           Data.Text ( Text )
import qualified Data.Text as T
import qualified Data.Text.IO as TIO
import qualified Prettyprinter as PP
import qualified Prettyprinter.Render.Text as PRT
import           System.Process
import           Test.Hspec
import           Test.Tasty
import           Test.Tasty.Hspec
import           Text.Sayable

import           Demangler ( demangle, demangle1, newDemangling )

-- n.b. Original conception was to use a Sandwich Context to retrieve the
-- contents of the input data files, but a Context can only be retrieved (via
-- getContext) inside an ExampleT, which is the body of an `it "something" body`
-- statement.  Thus, there's no way to iterate over the individual lines of the
-- input file and create an ExampleT test for each one.

main :: IO ()
main = do inps <- mapM getInputData  [ "test/initial-test-cases.txt"
                                     , "test/full-test-cases.txt"
                                     ]
          defaultMain =<< (testSpec "Demangle" $ demangleTests inps)


getInputData :: String -> IO (String, [(Text, Text)])
getInputData fname = do
  inputs <- TIO.readFile fname
  expects <- T.pack <$> readProcess "c++filt" [] (T.unpack inputs)
  let pairs = zip (T.lines inputs) (T.lines expects)
  return (fname, pairs)


demangleTests :: [(String, [(Text, Text)])] -> Spec
demangleTests testInputs = describe "Demangle tests" $
                           mapM_ demangleTestSet testInputs

demangleTestSet :: (String, [(Text, Text)]) -> Spec
demangleTestSet (inpFile, inpData) =
  describe inpFile $
  do describe "Individually" $ sequence_ (mkTest <$> inpData)
     describe "Batched" $ batchTest inpData


mkTest :: (Text, Text) -> Spec
mkTest (sym, expected) = it ("demangles " <> T.unpack sym) $
  (toText $ demangle1 sym) `shouldBe` expected

batchTest :: [(Text, Text)] -> Spec
batchTest symbols =
  let r = runState (sequence (state . demangle . fst <$> symbols)) newDemangling
      mkRes (dm, (inp, ex)) prs = (inp, toText (dm, snd r), ex) : prs
      results = foldr mkRes [] $ zip (fst r) symbols
      validate (i,rslt,e) = it ("demangles " <> T.unpack i) $ rslt `shouldBe` e
  in sequence_ (validate <$> results)

toText :: Sayable "normal" a => a -> Text
toText = PRT.renderStrict
         . PP.layoutPretty (PP.LayoutOptions PP.Unbounded)
         . saying . sayable @"normal"