aboutsummaryrefslogtreecommitdiff
path: root/tests/CompileTest.hs
blob: b5d900357bad75cffa54465b69a81d04c4e81e8f (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
{-# LANGUAGE ScopedTypeVariables, GADTs, ImplicitParams #-}

{-| This test tries to compile the Helper against every supported version of the
  Cabal library. Since we compile the Helper at runtime, on the user's machine,
  it is very important to make sure this will not fail.
-}

import System.Environment (getArgs)
import System.Directory
import System.FilePath
import System.Process
import System.Exit
import System.IO
import Control.Exception as E
import Data.List
import Data.Maybe
import Data.Version
import Data.Functor
import Data.Function
import qualified Distribution.Compat.ReadP as Dist
import Distribution.Version (VersionRange, withinRange)
import Distribution.Text
import Control.Arrow
import Control.Monad
import Prelude

import CabalHelper.Compiletime.Compat.Environment
import CabalHelper.Compiletime.Compat.Version
import CabalHelper.Compiletime.Cabal
import CabalHelper.Compiletime.Compile
import CabalHelper.Compiletime.Program.CabalInstall
import CabalHelper.Compiletime.Program.GHC
import CabalHelper.Compiletime.Types
import CabalHelper.Shared.Common

runReadP'Dist :: Dist.ReadP t t -> String -> t
runReadP'Dist p i = case filter ((=="") . snd) $ Dist.readP_to_S p i of
                 (a,""):[] -> a
                 _ -> error $ "Error parsing: " ++ show i

withinRange'CH :: Version -> VersionRange -> Bool
withinRange'CH v r =
    withinRange (fromDataVersion v) r

setupHOME :: IO ()
setupHOME = do
  tmp <- fromMaybe "/tmp" <$> lookupEnv "TMPDIR"
  let home = tmp </> "compile-test-home"
  _ <- rawSystem "rm" ["-r", home]
  createDirectory    home
  setEnv "HOME" home

main :: IO ()
main = do
  let ?progs = defaultPrograms
  let ?cprogs = defaultCompPrograms
  let ?opts = defaultCompileOptions { oVerbose = True }
  let ?verbose = True

  args <- getArgs
  case args of
    "list-versions":[] -> do
        mapM_ print =<< (allCabalVersions <$> ghcVersion)
    "list-versions":ghc_ver_str:[] ->
        mapM_ print $ allCabalVersions (parseVer ghc_ver_str)
    _ ->
        test args

test :: Env => [String] -> IO ()
test args = do
  let action
       | null args = testAllCabalVersions
       | otherwise = testCabalVersions $ map parseVer' args

  setupHOME

  _ <- rawSystem "cabal" ["update"]

  action

parseVer' :: String -> Either HEAD Version
parseVer' "HEAD" = Left HEAD
parseVer' v      = Right $ parseVer v

allCabalVersions :: Version -> [Version]
allCabalVersions ghc_ver = let
    cabal_versions :: [Version]
    cabal_versions = map parseVer
         -- , "1.18.0"
         -- , "1.18.1"
         -- , "1.18.1.1"
         -- , "1.18.1.2"
         -- , "1.18.1.3"
         -- , "1.18.1.4"
         -- , "1.18.1.5"
         -- , "1.18.1.6"
         -- , "1.18.1.7"
         -- , "1.20.0.0"
         -- , "1.20.0.1"
         -- , "1.20.0.2"
         -- , "1.20.0.3"
         -- , "1.20.0.4"
         -- , "1.22.0.0"
         -- , "1.22.1.0"
         -- , "1.22.1.1"
         [ "1.22.2.0"
         , "1.22.3.0"
         , "1.22.4.0"
         , "1.22.5.0"
         , "1.22.6.0"
         , "1.22.7.0"
         , "1.22.8.0"
         , "1.24.0.0"
         , "1.24.1.0"
         , "1.24.2.0"
         , "2.0.0.2"
         , "2.0.1.0"
         , "2.0.1.1"
         , "2.2.0.0"
         , "2.2.0.1"
         , "2.4.0.0"
         , "2.4.0.1"
         ]

    constraint :: VersionRange
    constraint =
        fromMaybe (snd $ last constraint_table) $
        fmap snd $
        find (and . (zipWith (==) `on` versionBranch) ghc_ver . fst) $
        constraint_table

    constraint_table =
        map (parseVer *** runReadP'Dist parse) $
            -- , ("7.8"  , ">= 1.18    && < 2")
            [ ("7.10" , ">= 1.22.2  && < 2")
            , ("8.0.1", ">= 1.24          ")
            , ("8.0.2", ">= 1.24.2        ")
            , ("8.2.1", ">= 2.0.0.2       ")
            , ("8.2.2", ">= 2.0.0.2       ")
            , ("8.4.1", ">= 2.0.0.2       ")
            , ("8.4.2", ">= 2.2.0.1       ")
            , ("8.6.1", ">= 2.4.0.0       ")
            ]
  in
    reverse $ filter (flip withinRange'CH constraint) cabal_versions


testAllCabalVersions :: Env => IO ()
testAllCabalVersions = do
  ghc_ver <- ghcVersion
  let relevant_cabal_versions = allCabalVersions ghc_ver
  testCabalVersions $ map Right relevant_cabal_versions ++ [Left HEAD]

testCabalVersions :: Env => [Either HEAD Version] -> IO ()
testCabalVersions versions = do
  rvs <- forM versions $ \ver -> do
           let sver = either show showVersion ver
           hPutStrLn stderr $ "\n\n\n\n\n\n====== Compiling with Cabal-" ++ sver
           compilePrivatePkgDb ver

  let printStatus (cv, rv) = putStrLn $ "- Cabal "++ver++" "++status
        where  ver = case cv of Left _ -> "HEAD"; Right v -> showVersion v
               status = case rv of
                         Right _ ->
                             "succeeded"
                         Left rvc ->
                             "failed (exit code "++show rvc++")"

  let drvs = versions `zip` rvs

  mapM_ printStatus drvs
  if any isLeft' $ map snd $ filter ((/=Left HEAD) . fst) drvs
     then exitFailure
     else exitSuccess

 where
   isLeft' (Left _) = True
   isLeft' (Right _) = False

compilePrivatePkgDb
    :: Env => Either HEAD Version -> IO (Either ExitCode FilePath)
compilePrivatePkgDb eCabalVer = do
    res <- E.try $ installCabalLib eCabalVer
    case res of
      Right (db, cabalVer) ->
          compileWithPkg db cabalVer
      Left (ioe :: IOException) -> do
          print ioe
          return $ Left (ExitFailure 1)

compileWithPkg :: Env
               => PackageDbDir
               -> CabalVersion
               -> IO (Either ExitCode FilePath)
compileWithPkg db cabalVer = do
    appdir <- appCacheDir
    let comp =
          CompileWithCabalPackage (Just db) cabalVer [cabalPkgId cabalVer] CPSGlobal
    compile
      comp
      (compPaths appdir (error "compile-test: distdir not available") comp)


cabalPkgId :: CabalVersion -> String
cabalPkgId (CabalHEAD _commitid) = "Cabal"
cabalPkgId (CabalVersion v) = "Cabal-" ++ showVersion v