{- -----------------------------------------------------------------------------
Copyright 2020 Kevin P. Barry

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
----------------------------------------------------------------------------- -}

-- Author: Kevin P. Barry [ta0kira@gmail.com]

module Test.IntegrationTest (tests) where

import Control.Monad (when)
import System.FilePath

import Base.CompilerError
import Base.TrackedErrors
import Parser.Common
import Parser.IntegrationTest ()
import Parser.TextParser
import Test.Common
import Types.DefinedCategory
import Types.IntegrationTest
import Types.TypeCategory


tests :: [IO (TrackedErrors ())]
tests :: [IO (TrackedErrors ())]
tests = [
    String
-> (IntegrationTest SourceContext -> TrackedErrors ())
-> IO (TrackedErrors ())
checkFileContents
      (String
"testfiles" String -> String -> String
</> String
"basic_compiles_test.0rt")
      (\IntegrationTest SourceContext
t -> do
        let h :: IntegrationTestHeader SourceContext
h = forall c. IntegrationTest c -> IntegrationTestHeader c
itHeader IntegrationTest SourceContext
t
        forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Bool -> Bool
not forall a b. (a -> b) -> a -> b
$ forall c. ExpectedResult c -> Bool
isExpectCompiles forall a b. (a -> b) -> a -> b
$ forall c. IntegrationTestHeader c -> ExpectedResult c
ithResult IntegrationTestHeader SourceContext
h) forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a. ErrorContextM m => String -> m a
compilerErrorM String
"Expected ExpectCompiles"
        forall a. (Eq a, Show a) => a -> a -> TrackedErrors ()
checkEquals (forall c. IntegrationTestHeader c -> String
ithTestName IntegrationTestHeader SourceContext
h) String
"basic compiles test"
        forall a. (Ord a, Show a) => [a] -> [a] -> TrackedErrors ()
containsExactly (forall c. IntegrationTestHeader c -> [String]
ithArgs IntegrationTestHeader SourceContext
h) []
        forall a. (Eq a, Show a) => a -> a -> TrackedErrors ()
checkEquals (forall c. IntegrationTestHeader c -> Maybe Integer
ithTimeout IntegrationTestHeader SourceContext
h) forall a. Maybe a
Nothing
        forall a. (Ord a, Show a) => [a] -> [a] -> TrackedErrors ()
containsExactly (forall c. ExpectedResult c -> [OutputPattern]
getRequirePattern forall a b. (a -> b) -> a -> b
$ forall c. IntegrationTestHeader c -> ExpectedResult c
ithResult IntegrationTestHeader SourceContext
h) [
            OutputScope -> String -> OutputPattern
OutputPattern OutputScope
OutputCompiler String
"pattern in output 1",
            OutputScope -> String -> OutputPattern
OutputPattern OutputScope
OutputAny      String
"pattern in output 2"
          ]
        forall a. (Ord a, Show a) => [a] -> [a] -> TrackedErrors ()
containsExactly (forall c. ExpectedResult c -> [OutputPattern]
getExcludePattern forall a b. (a -> b) -> a -> b
$ forall c. IntegrationTestHeader c -> ExpectedResult c
ithResult IntegrationTestHeader SourceContext
h) [
            OutputScope -> String -> OutputPattern
OutputPattern OutputScope
OutputStderr String
"pattern not in output 1",
            OutputScope -> String -> OutputPattern
OutputPattern OutputScope
OutputStdout String
"pattern not in output 2"
          ]
        forall a. (Ord a, Show a) => [a] -> [a] -> TrackedErrors ()
containsExactly (forall c. IntegrationTest c -> [String]
extractCategoryNames IntegrationTest SourceContext
t) [String
"Test"]
        forall a. (Ord a, Show a) => [a] -> [a] -> TrackedErrors ()
containsExactly (forall c. IntegrationTest c -> [String]
extractDefinitionNames IntegrationTest SourceContext
t) [String
"Test"]
        ),

    String
-> (IntegrationTest SourceContext -> TrackedErrors ())
-> IO (TrackedErrors ())
checkFileContents
      (String
"testfiles" String -> String -> String
</> String
"basic_error_test.0rt")
      (\IntegrationTest SourceContext
t -> do
        let h :: IntegrationTestHeader SourceContext
h = forall c. IntegrationTest c -> IntegrationTestHeader c
itHeader IntegrationTest SourceContext
t
        forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Bool -> Bool
not forall a b. (a -> b) -> a -> b
$ forall c. ExpectedResult c -> Bool
isExpectCompilerError forall a b. (a -> b) -> a -> b
$ forall c. IntegrationTestHeader c -> ExpectedResult c
ithResult IntegrationTestHeader SourceContext
h) forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a. ErrorContextM m => String -> m a
compilerErrorM String
"Expected ExpectCompilerError"
        forall a. (Eq a, Show a) => a -> a -> TrackedErrors ()
checkEquals (forall c. IntegrationTestHeader c -> String
ithTestName IntegrationTestHeader SourceContext
h) String
"basic error test"
        forall a. (Ord a, Show a) => [a] -> [a] -> TrackedErrors ()
containsExactly (forall c. IntegrationTestHeader c -> [String]
ithArgs IntegrationTestHeader SourceContext
h) []
        forall a. (Eq a, Show a) => a -> a -> TrackedErrors ()
checkEquals (forall c. IntegrationTestHeader c -> Maybe Integer
ithTimeout IntegrationTestHeader SourceContext
h) forall a. Maybe a
Nothing
        forall a. (Ord a, Show a) => [a] -> [a] -> TrackedErrors ()
containsExactly (forall c. ExpectedResult c -> [OutputPattern]
getRequirePattern forall a b. (a -> b) -> a -> b
$ forall c. IntegrationTestHeader c -> ExpectedResult c
ithResult IntegrationTestHeader SourceContext
h) [
            OutputScope -> String -> OutputPattern
OutputPattern OutputScope
OutputCompiler String
"pattern in output 1",
            OutputScope -> String -> OutputPattern
OutputPattern OutputScope
OutputAny      String
"pattern in output 2"
          ]
        forall a. (Ord a, Show a) => [a] -> [a] -> TrackedErrors ()
containsExactly (forall c. ExpectedResult c -> [OutputPattern]
getExcludePattern forall a b. (a -> b) -> a -> b
$ forall c. IntegrationTestHeader c -> ExpectedResult c
ithResult IntegrationTestHeader SourceContext
h) [
            OutputScope -> String -> OutputPattern
OutputPattern OutputScope
OutputStderr String
"pattern not in output 1",
            OutputScope -> String -> OutputPattern
OutputPattern OutputScope
OutputStdout String
"pattern not in output 2"
          ]
        forall a. (Ord a, Show a) => [a] -> [a] -> TrackedErrors ()
containsExactly (forall c. IntegrationTest c -> [String]
extractCategoryNames IntegrationTest SourceContext
t) [String
"Test"]
        forall a. (Ord a, Show a) => [a] -> [a] -> TrackedErrors ()
containsExactly (forall c. IntegrationTest c -> [String]
extractDefinitionNames IntegrationTest SourceContext
t) [String
"Test"]
        ),

    String
-> (IntegrationTest SourceContext -> TrackedErrors ())
-> IO (TrackedErrors ())
checkFileContents
      (String
"testfiles" String -> String -> String
</> String
"basic_crash_test.0rt")
      (\IntegrationTest SourceContext
t -> do
        let h :: IntegrationTestHeader SourceContext
h = forall c. IntegrationTest c -> IntegrationTestHeader c
itHeader IntegrationTest SourceContext
t
        forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Bool -> Bool
not forall a b. (a -> b) -> a -> b
$ forall c. ExpectedResult c -> Bool
isExpectRuntimeError forall a b. (a -> b) -> a -> b
$ forall c. IntegrationTestHeader c -> ExpectedResult c
ithResult IntegrationTestHeader SourceContext
h) forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a. ErrorContextM m => String -> m a
compilerErrorM String
"Expected ExpectRuntimeError"
        forall a. (Ord a, Show a) => [a] -> [a] -> TrackedErrors ()
containsExactly (forall c. IntegrationTestHeader c -> [String]
ithArgs IntegrationTestHeader SourceContext
h) [String
"arg1",String
"arg2",String
"arg3"]
        forall a. (Eq a, Show a) => a -> a -> TrackedErrors ()
checkEquals (forall c. IntegrationTestHeader c -> Maybe Integer
ithTimeout IntegrationTestHeader SourceContext
h) (forall a. a -> Maybe a
Just Integer
10)
        forall a. (Ord a, Show a) => [a] -> [a] -> TrackedErrors ()
containsExactly (forall c. ExpectedResult c -> [OutputPattern]
getRequirePattern forall a b. (a -> b) -> a -> b
$ forall c. IntegrationTestHeader c -> ExpectedResult c
ithResult IntegrationTestHeader SourceContext
h) [
            OutputScope -> String -> OutputPattern
OutputPattern OutputScope
OutputAny String
"pattern in output 1",
            OutputScope -> String -> OutputPattern
OutputPattern OutputScope
OutputAny String
"pattern in output 2"
          ]
        forall a. (Ord a, Show a) => [a] -> [a] -> TrackedErrors ()
containsExactly (forall c. ExpectedResult c -> [OutputPattern]
getExcludePattern forall a b. (a -> b) -> a -> b
$ forall c. IntegrationTestHeader c -> ExpectedResult c
ithResult IntegrationTestHeader SourceContext
h) [
            OutputScope -> String -> OutputPattern
OutputPattern OutputScope
OutputAny String
"pattern not in output 1",
            OutputScope -> String -> OutputPattern
OutputPattern OutputScope
OutputAny String
"pattern not in output 2"
          ]
        forall a. (Ord a, Show a) => [a] -> [a] -> TrackedErrors ()
containsExactly (forall c. IntegrationTest c -> [String]
extractCategoryNames IntegrationTest SourceContext
t) [String
"Test"]
        forall a. (Ord a, Show a) => [a] -> [a] -> TrackedErrors ()
containsExactly (forall c. IntegrationTest c -> [String]
extractDefinitionNames IntegrationTest SourceContext
t) [String
"Test"]
        ),

    String
-> (IntegrationTest SourceContext -> TrackedErrors ())
-> IO (TrackedErrors ())
checkFileContents
      (String
"testfiles" String -> String -> String
</> String
"basic_success_test.0rt")
      (\IntegrationTest SourceContext
t -> do
        let h :: IntegrationTestHeader SourceContext
h = forall c. IntegrationTest c -> IntegrationTestHeader c
itHeader IntegrationTest SourceContext
t
        forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Bool -> Bool
not forall a b. (a -> b) -> a -> b
$ forall c. ExpectedResult c -> Bool
isExpectRuntimeSuccess forall a b. (a -> b) -> a -> b
$ forall c. IntegrationTestHeader c -> ExpectedResult c
ithResult IntegrationTestHeader SourceContext
h) forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a. ErrorContextM m => String -> m a
compilerErrorM String
"Expected ExpectRuntimeSuccess"
        forall a. (Eq a, Show a) => a -> a -> TrackedErrors ()
checkEquals (forall c. IntegrationTestHeader c -> String
ithTestName IntegrationTestHeader SourceContext
h) String
"basic success test"
        forall a. (Ord a, Show a) => [a] -> [a] -> TrackedErrors ()
containsExactly (forall c. IntegrationTestHeader c -> [String]
ithArgs IntegrationTestHeader SourceContext
h) []
        forall a. (Eq a, Show a) => a -> a -> TrackedErrors ()
checkEquals (forall c. IntegrationTestHeader c -> Maybe Integer
ithTimeout IntegrationTestHeader SourceContext
h) (forall a. a -> Maybe a
Just Integer
0)
        forall a. (Ord a, Show a) => [a] -> [a] -> TrackedErrors ()
containsExactly (forall c. ExpectedResult c -> [OutputPattern]
getRequirePattern forall a b. (a -> b) -> a -> b
$ forall c. IntegrationTestHeader c -> ExpectedResult c
ithResult IntegrationTestHeader SourceContext
h) [
            OutputScope -> String -> OutputPattern
OutputPattern OutputScope
OutputAny String
"pattern in output 1",
            OutputScope -> String -> OutputPattern
OutputPattern OutputScope
OutputAny String
"pattern in output 2"
          ]
        forall a. (Ord a, Show a) => [a] -> [a] -> TrackedErrors ()
containsExactly (forall c. ExpectedResult c -> [OutputPattern]
getExcludePattern forall a b. (a -> b) -> a -> b
$ forall c. IntegrationTestHeader c -> ExpectedResult c
ithResult IntegrationTestHeader SourceContext
h) [
            OutputScope -> String -> OutputPattern
OutputPattern OutputScope
OutputAny String
"pattern not in output 1",
            OutputScope -> String -> OutputPattern
OutputPattern OutputScope
OutputAny String
"pattern not in output 2"
          ]
        forall a. (Ord a, Show a) => [a] -> [a] -> TrackedErrors ()
containsExactly (forall c. IntegrationTest c -> [String]
extractCategoryNames IntegrationTest SourceContext
t) [String
"Test"]
        forall a. (Ord a, Show a) => [a] -> [a] -> TrackedErrors ()
containsExactly (forall c. IntegrationTest c -> [String]
extractDefinitionNames IntegrationTest SourceContext
t) [String
"Test"]
        )
  ]

checkFileContents ::
  String -> (IntegrationTest SourceContext -> TrackedErrors ()) -> IO (TrackedErrors ())
checkFileContents :: String
-> (IntegrationTest SourceContext -> TrackedErrors ())
-> IO (TrackedErrors ())
checkFileContents String
f IntegrationTest SourceContext -> TrackedErrors ()
o = forall (m :: * -> *) a.
Monad m =>
TrackedErrorsT m a -> m (TrackedErrors a)
toTrackedErrors forall a b. (a -> b) -> a -> b
$ do
  String
s <- forall (m :: * -> *) a. (MonadIO m, ErrorContextM m) => IO a -> m a
errorFromIO forall a b. (a -> b) -> a -> b
$ String -> IO String
loadFile String
f
  IntegrationTest SourceContext
t <- forall (m :: * -> *) a.
ErrorContextM m =>
TextParser a -> String -> String -> m a
runTextParser (forall (m :: * -> *) open close a.
Applicative m =>
m open -> m close -> m a -> m a
between TextParser ()
optionalSpace TextParser ()
endOfDoc forall a. ParseFromSource a => TextParser a
sourceParser) String
f String
s
  forall (m :: * -> *) a.
Monad m =>
TrackedErrors a -> TrackedErrorsT m a
fromTrackedErrors forall a b. (a -> b) -> a -> b
$ IntegrationTest SourceContext -> TrackedErrors ()
o IntegrationTest SourceContext
t forall (m :: * -> *) a. ErrorContextM m => m a -> String -> m a
<!! String
"Check " forall a. [a] -> [a] -> [a]
++ String
f forall a. [a] -> [a] -> [a]
++ String
":"

extractCategoryNames :: IntegrationTest c -> [String]
extractCategoryNames :: forall c. IntegrationTest c -> [String]
extractCategoryNames = forall a b. (a -> b) -> [a] -> [b]
map (forall a. Show a => a -> String
show forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall c. AnyCategory c -> CategoryName
getCategoryName) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall c. IntegrationTest c -> [AnyCategory c]
itCategory

extractDefinitionNames :: IntegrationTest c -> [String]
extractDefinitionNames :: forall c. IntegrationTest c -> [String]
extractDefinitionNames = forall a b. (a -> b) -> [a] -> [b]
map (forall a. Show a => a -> String
show forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall c. DefinedCategory c -> CategoryName
dcName) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall c. IntegrationTest c -> [DefinedCategory c]
itDefinition