2019-10-21 19:01:05 +03:00
|
|
|
module Main (main) where
|
|
|
|
|
|
|
|
import Hasura.Prelude
|
|
|
|
|
2019-12-14 09:47:38 +03:00
|
|
|
import Data.Aeson (eitherDecodeStrict)
|
|
|
|
import Data.Either (isRight)
|
|
|
|
import Data.Time.Clock (getCurrentTime)
|
|
|
|
import Hasura.EncJSON
|
2019-10-21 19:01:05 +03:00
|
|
|
import Options.Applicative
|
2019-12-14 09:47:38 +03:00
|
|
|
import System.Environment (getEnvironment)
|
|
|
|
import System.Exit (exitFailure)
|
2019-10-21 19:01:05 +03:00
|
|
|
import Test.Hspec
|
2019-12-14 09:47:38 +03:00
|
|
|
import Test.QuickCheck
|
|
|
|
|
|
|
|
import qualified Data.Aeson.Ordered as AO
|
|
|
|
import qualified Database.PG.Query as Q
|
|
|
|
import qualified Network.HTTP.Client as HTTP
|
|
|
|
import qualified Network.HTTP.Client.TLS as HTTP
|
|
|
|
import qualified Test.Hspec.Runner as Hspec
|
|
|
|
|
|
|
|
import Hasura.Db (PGExecCtx (..))
|
|
|
|
import Hasura.RQL.DDL.Metadata (ClearMetadata (..),
|
|
|
|
runClearMetadata)
|
|
|
|
import Hasura.RQL.DDL.Metadata.Generator (genReplaceMetadata)
|
|
|
|
import Hasura.RQL.DDL.Metadata.Types (ReplaceMetadata,
|
|
|
|
replaceMetadataToOrdJSON)
|
|
|
|
import Hasura.RQL.Types (QErr, SQLGenCtx (..),
|
|
|
|
adminUserInfo,
|
|
|
|
emptySchemaCache,
|
|
|
|
successMsg)
|
|
|
|
import Hasura.Server.Init (RawConnInfo, mkConnInfo,
|
|
|
|
mkRawConnInfo,
|
|
|
|
parseRawConnInfo,
|
|
|
|
runWithEnv)
|
2019-10-21 19:01:05 +03:00
|
|
|
import Hasura.Server.Migrate
|
|
|
|
import Hasura.Server.PGDump
|
2019-12-14 09:47:38 +03:00
|
|
|
import Hasura.Server.Query (Run, RunCtx (..), peelRun)
|
2019-10-21 19:01:05 +03:00
|
|
|
|
2019-12-14 09:47:38 +03:00
|
|
|
data TestCommand
|
|
|
|
= TCMigrate !RawConnInfo -- ^ Run migrate tests
|
|
|
|
| TCProperty -- ^ Run property tests
|
|
|
|
|
|
|
|
data TestArgs
|
|
|
|
= TANoCommand !RawConnInfo -- ^ Run all tests
|
|
|
|
| TACommand !TestCommand -- ^ Run specified tests
|
|
|
|
|
|
|
|
parseArgs :: ParserInfo TestArgs
|
|
|
|
parseArgs =
|
|
|
|
info (helper <*> (parseNoCommand <|> (TACommand <$> parseSubCommand))) $
|
2019-10-21 19:01:05 +03:00
|
|
|
fullDesc <> header "Hasura GraphQL Engine test suite"
|
2019-12-14 09:47:38 +03:00
|
|
|
where
|
|
|
|
parseNoCommand = TANoCommand <$> parseRawConnInfo
|
|
|
|
parseSubCommand = subparser
|
|
|
|
( command "migrate" (info (helper <*> (TCMigrate <$> parseRawConnInfo))
|
|
|
|
(progDesc "Run catalog migrate tests")
|
|
|
|
)
|
|
|
|
<> command "property" (info (pure TCProperty)
|
|
|
|
(progDesc "Run property tests")
|
|
|
|
)
|
|
|
|
)
|
2019-10-21 19:01:05 +03:00
|
|
|
|
2019-12-14 09:47:38 +03:00
|
|
|
main :: IO ()
|
|
|
|
main = do
|
|
|
|
testArgs <- execParser parseArgs
|
|
|
|
case testArgs of
|
|
|
|
TANoCommand pgConnOptions -> runMigrateTests pgConnOptions >> runPropertyTests
|
|
|
|
TACommand (TCMigrate pgConnOptions) -> runMigrateTests pgConnOptions
|
|
|
|
TACommand TCProperty -> runPropertyTests
|
2019-10-21 19:01:05 +03:00
|
|
|
where
|
2019-12-14 09:47:38 +03:00
|
|
|
runMigrateTests pgConnOptions = do
|
|
|
|
env <- getEnvironment
|
|
|
|
rawPGConnInfo <- flip onLeft printErrExit $ runWithEnv env (mkRawConnInfo pgConnOptions)
|
|
|
|
pgConnInfo <- flip onLeft printErrExit $ mkConnInfo rawPGConnInfo
|
|
|
|
pgPool <- Q.initPGPool pgConnInfo Q.defaultConnParams { Q.cpConns = 1 } print
|
|
|
|
|
|
|
|
httpManager <- HTTP.newManager HTTP.tlsManagerSettings
|
|
|
|
let runContext = RunCtx adminUserInfo httpManager (SQLGenCtx False)
|
|
|
|
pgContext = PGExecCtx pgPool Q.Serializable
|
|
|
|
|
|
|
|
runAsAdmin :: Run a -> IO (Either QErr a)
|
|
|
|
runAsAdmin = runExceptT . fmap fst . peelRun emptySchemaCache runContext pgContext Q.ReadWrite
|
|
|
|
|
|
|
|
runHspec $ do
|
|
|
|
describe "Hasura.Server.Migrate" $ do
|
|
|
|
let dropAndInit time = runAsAdmin (dropCatalog *> migrateCatalog time)
|
|
|
|
|
|
|
|
describe "migrateCatalog" $ do
|
|
|
|
it "initializes the catalog" $ do
|
|
|
|
(dropAndInit =<< getCurrentTime) `shouldReturn` Right MRInitialized
|
|
|
|
|
|
|
|
it "is idempotent" $ do
|
|
|
|
let dumpSchema = runAsAdmin $
|
|
|
|
execPGDump (PGDumpReqBody ["--schema-only"] (Just False)) pgConnInfo
|
|
|
|
time <- getCurrentTime
|
|
|
|
dropAndInit time `shouldReturn` Right MRInitialized
|
|
|
|
firstDump <- dumpSchema
|
|
|
|
firstDump `shouldSatisfy` isRight
|
|
|
|
dropAndInit time `shouldReturn` Right MRInitialized
|
|
|
|
secondDump <- dumpSchema
|
|
|
|
secondDump `shouldBe` firstDump
|
|
|
|
|
|
|
|
describe "recreateSystemMetadata" $ do
|
|
|
|
let dumpMetadata = runAsAdmin $
|
|
|
|
execPGDump (PGDumpReqBody ["--schema=hdb_catalog"] (Just False)) pgConnInfo
|
|
|
|
|
|
|
|
it "is idempotent" $ do
|
|
|
|
(dropAndInit =<< getCurrentTime) `shouldReturn` Right MRInitialized
|
|
|
|
firstDump <- dumpMetadata
|
|
|
|
firstDump `shouldSatisfy` isRight
|
|
|
|
runAsAdmin recreateSystemMetadata `shouldReturn` Right ()
|
|
|
|
secondDump <- dumpMetadata
|
|
|
|
secondDump `shouldBe` firstDump
|
|
|
|
|
|
|
|
it "does not create any objects affected by ClearMetadata" $ do
|
|
|
|
(dropAndInit =<< getCurrentTime) `shouldReturn` Right MRInitialized
|
|
|
|
firstDump <- dumpMetadata
|
|
|
|
firstDump `shouldSatisfy` isRight
|
|
|
|
runAsAdmin (runClearMetadata ClearMetadata) `shouldReturn` Right successMsg
|
|
|
|
secondDump <- dumpMetadata
|
|
|
|
secondDump `shouldBe` firstDump
|
|
|
|
|
|
|
|
runPropertyTests = do
|
|
|
|
putStrLn "Running property tests"
|
|
|
|
passed <- isSuccess <$> quickCheckResult (withMaxSuccess 30 prop_replacemetadata)
|
|
|
|
unless passed $ printErrExit "Property tests failed"
|
|
|
|
where
|
|
|
|
prop_replacemetadata =
|
|
|
|
forAll (resize 3 genReplaceMetadata) $ \metadata ->
|
|
|
|
let encodedString = encJToBS $ AO.toEncJSON $ replaceMetadataToOrdJSON metadata
|
|
|
|
eitherResult :: Either String ReplaceMetadata
|
|
|
|
= eitherDecodeStrict encodedString
|
|
|
|
in case eitherResult of
|
|
|
|
Left err -> counterexample err False
|
|
|
|
Right _ -> property True
|
|
|
|
|
2019-10-21 19:01:05 +03:00
|
|
|
runHspec :: Spec -> IO ()
|
|
|
|
runHspec m = do
|
|
|
|
config <- Hspec.readConfig Hspec.defaultConfig []
|
|
|
|
Hspec.evaluateSummary =<< Hspec.runSpec m config
|
|
|
|
|
|
|
|
printErrExit :: String -> IO a
|
|
|
|
printErrExit = (*> exitFailure) . putStrLn
|