Download test/Test/Backend/Integration.hs from Snapkitty/assertica: direct link, hf CLI and curl.
- Browser
- Download file 7.09 kB
-
https://huggingface.co/Snapkitty/assertica/resolve/main/test/Test/Backend/Integration.hs
- Command line
-
hf download hf://Snapkitty/assertica/test/Test/Backend/Integration.hs
-
curl -L -o Integration.hs https://huggingface.co/Snapkitty/assertica/resolve/main/test/Test/Backend/Integration.hs
7.09 kB
| module Test.Backend.Integration | |
| ( tests | |
| ) where | |
| import Test.Tasty | |
| import Test.Tasty.HUnit | |
| import qualified Data.Text as T | |
| import qualified Data.Map.Strict as Map | |
| import Assertica.Core.AST | |
| import Assertica.Core.Module | |
| import Assertica.Backend.CodeGen | |
| import Assertica.Backend.Emit | |
| -- ============================================================================ | |
| -- TEST SUITE | |
| -- ============================================================================ | |
| tests :: TestTree | |
| tests = testGroup "Assertica.Backend.Integration" | |
| [ testGroup "End-to-End Compilation" | |
| [ testCase "Compile simple lambda to Haskell" testSimpleLambdaE2E | |
| , testCase "Compile let binding to Haskell" testLetBindingE2E | |
| , testCase "Compile case expression to Haskell" testCaseExpressionE2E | |
| ] | |
| , testGroup "Round-Trip Properties" | |
| [ testCase "Deterministic: AST -> Haskell is idempotent" testDeterministicCompilation | |
| ] | |
| , testGroup "Error Handling" | |
| [ testCase "Invalid input generates error" testErrorHandling | |
| ] | |
| , testGroup "Haskell Output Validity" | |
| [ testCase "Generated module has correct syntax" testModuleSyntax | |
| , testCase "Generated definitions are syntactically valid" testDefinitionSyntax | |
| ] | |
| ] | |
| -- ============================================================================ | |
| -- END-TO-END TESTS | |
| -- ============================================================================ | |
| testSimpleLambdaE2E :: Assertion | |
| testSimpleLambdaE2E = do | |
| -- Compile: λx . x | |
| let lambda = Lam (Binder (Var "x" 0) Nothing) (Var (Var "x" 0)) | |
| result <- case compileExpression defaultConfig lambda of | |
| Right expr -> return (heExpr expr) | |
| Left err -> assertFailure $ "Compilation failed: " ++ err | |
| -- Generated code should be valid Haskell | |
| assertBool "Should be non-empty" (not (T.null result)) | |
| assertBool "Should contain lambda operator" ("\\" `T.isInfixOf` result) | |
| assertBool "Should contain variable" ("x" `T.isInfixOf` result) | |
| testLetBindingE2E :: Assertion | |
| testLetBindingE2E = do | |
| -- Compile: let x = 5 in x | |
| let letExpr = Let | |
| (Binder (Var "x" 0) Nothing) | |
| (Const (IntLit 5)) | |
| (Var (Var "x" 0)) | |
| result <- case compileExpression defaultConfig letExpr of | |
| Right expr -> return (heExpr expr) | |
| Left err -> assertFailure $ "Compilation failed: " ++ err | |
| assertBool "Should be non-empty" (not (T.null result)) | |
| assertBool "Should contain let" ("let" `T.isInfixOf` result) | |
| assertBool "Should contain 5" ("5" `T.isInfixOf` result) | |
| assertBool "Should contain in" ("in" `T.isInfixOf` result) | |
| testCaseExpressionE2E :: Assertion | |
| testCaseExpressionE2E = do | |
| -- Compile: case x of { True -> 1; False -> 0 } | |
| let trueClause = Clause (PatConstr (QName [] "True") []) (Const (IntLit 1)) | |
| let falseClause = Clause (PatConstr (QName [] "False") []) (Const (IntLit 0)) | |
| let caseExpr = Case (Var (Var "x" 0)) [trueClause, falseClause] Nothing | |
| result <- case compileExpression defaultConfig caseExpr of | |
| Right expr -> return (heExpr expr) | |
| Left err -> assertFailure $ "Compilation failed: " ++ err | |
| assertBool "Should be non-empty" (not (T.null result)) | |
| assertBool "Should contain case" ("case" `T.isInfixOf` result) | |
| assertBool "Should contain 1" ("1" `T.isInfixOf` result) | |
| assertBool "Should contain 0" ("0" `T.isInfixOf` result) | |
| -- ============================================================================ | |
| -- ROUND-TRIP AND IDEMPOTENCY TESTS | |
| -- ============================================================================ | |
| testDeterministicCompilation :: Assertion | |
| testDeterministicCompilation = do | |
| let lambda = Lam (Binder (Var "x" 0) Nothing) (Var (Var "x" 0)) | |
| -- Compile three times | |
| let result1 = compileExpression defaultConfig lambda | |
| let result2 = compileExpression defaultConfig lambda | |
| let result3 = compileExpression defaultConfig lambda | |
| case (result1, result2, result3) of | |
| (Right e1, Right e2, Right e3) -> do | |
| let r1 = heExpr e1 | |
| let r2 = heExpr e2 | |
| let r3 = heExpr e3 | |
| assertEqual "First and second should match" r1 r2 | |
| assertEqual "Second and third should match" r2 r3 | |
| (Left e, _, _) -> assertFailure $ "Compilation failed: " ++ e | |
| (_, Left e, _) -> assertFailure $ "Compilation failed: " ++ e | |
| (_, _, Left e) -> assertFailure $ "Compilation failed: " ++ e | |
| -- ============================================================================ | |
| -- ERROR HANDLING | |
| -- ============================================================================ | |
| testErrorHandling :: Assertion | |
| testErrorHandling = do | |
| -- Test that various error conditions are handled gracefully | |
| -- For now, most constructs compile, so test basic error path existence | |
| let x = Var (Var "x" 0) | |
| let result = compileExpression defaultConfig x | |
| case result of | |
| Right _ -> return () -- Success is also valid | |
| Left _ -> return () -- Error is acceptable | |
| -- ============================================================================ | |
| -- HASKELL OUTPUT VALIDITY | |
| -- ============================================================================ | |
| testModuleSyntax :: Assertion | |
| testModuleSyntax = do | |
| let modName = ["Test", "Module"] | |
| let def = HaskellDefinition | |
| { hdName = "main" | |
| , hdTypeSignature = Just "IO ()" | |
| , hdBody = "putStrLn \"Hello\"" | |
| , hdSourceLocation = Nothing | |
| } | |
| let mod = HaskellModule | |
| { hmName = modName | |
| , hmImports = ["Prelude"] | |
| , hmDefinitions = [def] | |
| , hmComments = ["Test module"] | |
| } | |
| let haskellCode = emitHaskellModule defaultEmitConfig mod | |
| -- Check basic Haskell syntax | |
| assertBool "Should start with comment or module" $ | |
| "-- " `T.isPrefixOf` haskellCode || "module" `T.isPrefixOf` haskellCode | |
| assertBool "Should contain module declaration" $ | |
| "module" `T.isInfixOf` haskellCode | |
| assertBool "Should contain where" $ | |
| "where" `T.isInfixOf` haskellCode | |
| -- Count the lines to ensure structure | |
| let lineCount = length (T.lines haskellCode) | |
| assertBool "Should have multiple lines" (lineCount > 3) | |
| testDefinitionSyntax :: Assertion | |
| testDefinitionSyntax = do | |
| let def1 = HaskellDefinition | |
| { hdName = "id" | |
| , hdTypeSignature = Just "a -> a" | |
| , hdBody = "\\x -> x" | |
| , hdSourceLocation = Just "identity function" | |
| } | |
| let def2 = HaskellDefinition | |
| { hdName = "const" | |
| , hdTypeSignature = Just "a -> b -> a" | |
| , hdBody = "\\x y -> x" | |
| , hdSourceLocation = Nothing | |
| } | |
| let code1 = emitHaskellDefinition defaultEmitConfig def1 | |
| let code2 = emitHaskellDefinition defaultEmitConfig def2 | |
| -- Both should have valid structure | |
| assertBool "def1 should contain name" ("id" `T.isInfixOf` code1) | |
| assertBool "def1 should contain type" ("a" `T.isInfixOf` code1) | |
| assertBool "def1 should contain arrow" ("->" `T.isInfixOf` code1) | |
| assertBool "def1 should contain comment" ("--" `T.isInfixOf` code1) | |
| assertBool "def2 should contain name" ("const" `T.isInfixOf` code2) | |
| assertBool "def2 should contain type" ("a" `T.isInfixOf` code2) | |