{-# OPTIONS_GHC -fno-warn-unused-binds #-} {-# Language OverloadedStrings #-} {-# Language DeriveGeneric #-} import Control.Lens import Control.Monad import Data.Aeson import Data.ByteString.Lazy.UTF8 (toString) import Data.Maybe import qualified Data.Vector as V import Expectations import GHC.Generics import Network.Wreq import Prelude.Compat import System.Environment import System.IO import System.Random.MWC import System.Random.MWC.Distributions import Data.ByteString.Lazy (toStrict) import System.IO import Test.Hspec import Prelude.Compat import qualified Data.Vector as V import Test.Hspec.Core.Spec import Expectations import Test.Hspec import Test.Hspec.Core.Spec import Text.Read (readMaybe) newtype GetPackage = GetPackage { packageName :: String } deriving (Show, Generic) data GetRevision = GetRevision { time :: String , user :: String , number :: Integer } deriving (Show, Generic) instance FromJSON GetPackage instance FromJSON GetRevision getJson :: FromJSON b => String -> IO b getJson x = fmap (view responseBody) $ asJSON =<< getWith (defaults & header "Accept" .~ ["application/json"]) x -- if we make a significant change to cabal file rendering, we want to -- rerun on *all* of hackage, but the normal testsuite shouldn't do that -- because it takes so long. set SKIP=0 to run on all packages testHackage = do skip <- runIO $ (readMaybe =<<) <$> lookupEnv "SKIP" packages <- runIO $ do hSetBuffering stdout NoBuffering putStrLn "getting package list..." packages' <- getJson "http://hackage.haskell.org/packages/" let packages = filter (not . isProblematic) packages' putStrLn "done, running tests..." if isNothing skip then createSystemRandom >>= fmap (V.take 100) . uniformShuffle (V.fromList packages) else pure $ V.fromList packages parallel $ describe "for 100 random Hackage packages" $ forM_ (drop (fromMaybe 0 skip) $ zip [0 ..] $ V.toList packages) $ \(n, GetPackage pname) -> mapSpecItem_ applySkips $ it (mkHeader n pname) $ do revs <- getJson $ "http://hackage.haskell.org/package/" ++ pname ++ "/revisions/" let recent = last revs cabalFile <- get $ "http://hackage.haskell.org/package/" ++ pname ++ "/revision/" ++ show (number recent) ++ ".cabal" expectParse $ toStrict $ view responseBody cabalFile isProblematic _ = False main :: IO () main = hspecColor $ describe "comprehensive check" testHackage