hledger-flow-0.19.0: test/ReleaseNotice/Unit.hs
{-# LANGUAGE OverloadedStrings #-}
module ReleaseNotice.Unit (tests) where
import Control.Concurrent.MVar
import Control.Exception (AsyncException (UserInterrupt), throwIO, try)
import Control.Monad (forM_)
import Data.Aeson (encode, object, (.=))
import Data.IORef
import qualified Data.Text as T
import Data.Version (showVersion)
import Paths_hledger_flow (version)
import Hledger.Flow.ReleaseNotice (checkRelease, finishCommand, startCheck)
import Path (toFilePath)
import System.Directory (createDirectoryIfMissing)
import System.Exit (ExitCode (ExitFailure))
import System.FilePath ((</>))
import System.Timeout (timeout)
import Test.HUnit
import TestHelpers (withTestDir)
tests :: Test
tests = TestLabel "release notice" $ TestList
[ "ignore malformed, nonstable and non-newer releases" ~: TestCase $
forM_ [Nothing, Just "invalid", Just "{\"tag_name\":\"v0\"}",
Just (encode (object ["tag_name" .= ("v" ++ showVersion version)])),
Just "{\"tag_name\":\"v999-rc1\"}", Just "{\"tag_name\":\"v999x\"}",
Just "{\"tag_name\":\"v999\",\"prerelease\":true}",
Just "{\"tag_name\":\"v999\",\"draft\":true}"] $ \body -> do
notice <- checkRelease (const $ pure body) (fail "unexpected ownership check")
Nothing @=? notice
, "verified Homebrew ownership and published formula" ~: TestCase $
withTestDir $ \dir -> do
let keg = toFilePath dir </> "Cellar" </> "hledger-flow" </> "1.2.3"
exe = keg </> "bin" </> "hledger-flow"
receipt = keg </> "INSTALL_RECEIPT.json"
fetch formula url
| url == "https://api.github.com/repos/apauley/hledger-flow/releases/latest" =
pure $ Just "{\"tag_name\":\"v999.10.0\"}"
| url == "https://raw.githubusercontent.com/FernTrail/homebrew-tap/main/Formula/hledger-flow.rb" =
pure formula
| otherwise = assertFailure ("unexpected URL " ++ url) >> pure Nothing
check advice formula = do
notice <- checkRelease (fetch formula) (pure exe)
assertBool ("expected " ++ T.unpack advice) (maybe False (T.isInfixOf advice) notice)
published = Just " tag = \"v999.10.0\"\n"
releases = "https://github.com/apauley/hledger-flow/releases/latest"
createDirectoryIfMissing True (keg </> "bin")
writeFile exe ""
check releases published
writeFile receipt "{\"source\":{\"tap\":\"other/tap\"}}"
check releases published
writeFile receipt "{\"source\":{\"tap\":\"ferntrail/tap\"}}"
check releases Nothing
check releases (Just " tag = \"v999.9.0\"\n")
check "brew update && brew upgrade ferntrail/tap/hledger-flow" published
, "command finishes with worker still pending" ~: TestCase $ do
started <- newEmptyMVar
release <- newEmptyMVar
finish <- startCheck (putMVar started () >> takeMVar release)
takeMVar started
success <- timeout 1000000 $ finishCommand finish (pure ())
failure <- timeout 1000000 $ try (finishCommand finish (throwIO (ExitFailure 37)))
Just () @=? success
Just (Left (ExitFailure 37)) @=? failure
putMVar release Nothing
, "ready notice follows diagnostics and preserves the exit code" ~: TestCase $ do
events <- newIORef ([] :: [String])
let record msg = modifyIORef' events (++ [msg])
result <- try $ finishCommand (record "notice") (record "diagnostic" >> throwIO (ExitFailure 23))
Left (ExitFailure 23) @=? result
readIORef events >>= assertEqual "order" ["diagnostic", "notice"]
, "interrupt skips a ready notice" ~: TestCase $ do
result <- try $ finishCommand (assertFailure "printed on interrupt") (throwIO UserInterrupt)
Left UserInterrupt @=? result
, "notice write failure preserves success and failure" ~: TestCase $ do
let broken = ioError (userError "closed stderr")
finishCommand broken (pure ())
result <- try $ finishCommand broken (throwIO (ExitFailure 19))
Left (ExitFailure 19) @=? result
]