GeneratorTestUtil.hs 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
  1. {-# LANGUAGE TemplateHaskell, QuasiQuotes, OverloadedStrings #-}
  2. module GeneratorTestUtil where
  3. import Control.Applicative
  4. import Control.Monad (when)
  5. import Data.List (sortBy)
  6. import Language.Haskell.TH
  7. import Test.HUnit hiding (Location)
  8. import Yesod.EmbeddedStatic.Types
  9. import qualified Data.ByteString.Lazy as BL
  10. -- We test the generators by executing them at compile time
  11. -- and sticking the result into the GenTestResult. We then
  12. -- test the GenTestResult at runtime. But to test the ebDevelReload
  13. -- we must run the action at runtime so that is also embedded.
  14. -- Because of template haskell stage restrictions, this code
  15. -- needs to be in a separate module.
  16. data GenTestResult = GenError String
  17. | GenSuccessWithDevel (IO BL.ByteString)
  18. -- | Creates a GenTestResult at compile time by testing the entry.
  19. testEntry :: Maybe String -> Location -> IO BL.ByteString -> Entry -> ExpQ
  20. testEntry name _ _ e | ebHaskellName e /= (mkName <$> name) =
  21. [| GenError ("haskell name " ++ $(litE $ stringL $ show $ ebHaskellName e)
  22. ++ " /= "
  23. ++ $(litE $ stringL $ show name)) |]
  24. testEntry _ loc _ e | ebLocation e /= loc =
  25. [| GenError ("location " ++ $(litE $ stringL $ show $ ebLocation e)) |]
  26. testEntry _ _ act e = do
  27. expected <- runIO act
  28. actual <- runIO $ ebProductionContent e
  29. if expected == actual
  30. then [| GenSuccessWithDevel $(ebDevelReload e) |]
  31. else [| GenError "production content" |]
  32. testOneEntry :: Maybe String -> Location -> IO BL.ByteString -> [Entry] -> ExpQ
  33. testOneEntry name loc ct [e] = testEntry name loc ct e
  34. testOneEntry _ _ _ _ = [| GenError "not exactly one entry" |]
  35. -- | Tests a list of entries
  36. testEntries :: [(Maybe String, Location, IO BL.ByteString)] -> [Entry] -> ExpQ
  37. testEntries a b | length a /= length b = [| [GenError "lengths differ"] |]
  38. testEntries a b = listE $ zipWith f a' b'
  39. where
  40. a' = sortBy (\(_,l1,_) (_,l2,_) -> compare l1 l2) a
  41. b' = sortBy (\e1 e2 -> ebLocation e1 `compare` ebLocation e2) b
  42. f (name, loc, ct) e = testEntry name loc ct e
  43. -- | Use this at runtime to assert the 'GenTestResult' is OK
  44. assertGenResult :: (IO BL.ByteString) -- ^ expected development content
  45. -> GenTestResult -- ^ test result created at compile time
  46. -> Assertion
  47. assertGenResult _ (GenError e) = assertFailure ("invalid " ++ e)
  48. assertGenResult mexpected (GenSuccessWithDevel mactual) = do
  49. expected <- mexpected
  50. actual <- mactual
  51. when (expected /= actual) $
  52. assertFailure "invalid devel content"