Skip to content
This repository was archived by the owner on Jun 17, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/maintenance.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ jobs:
sudo bash ./llvm.sh 19 &&
(sudo rm /usr/bin/clang-format || exit 0) &&
sudo apt -y install clang-format-19
- run: gradle format
- run: gradle --no-daemon format

build:
timeout-minutes: 10
Expand All @@ -33,4 +33,4 @@ jobs:
java-version: '21'
distribution: 'temurin'

- run: ./gradlew --no-daemon build
- run: cabal update && ./gradlew --no-daemon build
15 changes: 14 additions & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,11 @@ pitest {
// Test generation

tasks.register<Exec>("generateQuickCheckTests") {
File("src/facadetests/java/MakeItFit").mkdirs()
dependsOn(tasks.jar)
workingDir = file("src/testgen")
commandLine = listOf("cabal", "run")
commandLine =
listOf("cabal", "run", "testgen", "--", "../facadetests/java/MakeItFit/MakeItFitTest.java")
}

tasks.register<JavaExec>("generateEvoSuiteTests") {
Expand All @@ -139,11 +142,21 @@ tasks.register<JavaExec>("generateEvoSuiteTests") {

// Other tasks

tasks.named<Task>("build") {
finalizedBy(tasks.named<Task>("buildHaskell"))
}

tasks.register<Exec>("buildHaskell") {
workingDir = file("src/testgen")
commandLine = listOf("cabal", "build")
}

tasks.named<JavaExec>("run") {
standardInput = System.`in`
}

tasks.register<Exec>("repl") {
dependsOn(tasks.jar)
workingDir = file("src/testgen")
commandLine = listOf("cabal", "repl")
standardInput = System.`in`
Expand Down
2 changes: 1 addition & 1 deletion src/testgen/testgen.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,4 @@ executable testgen
build-depends:
base >=4.15.1.0 && <5,
QuickCheck ^>=2.15.0.1,
process ^>=1.6.26.1
process ^>=1.6.25.0
31 changes: 27 additions & 4 deletions src/testgen/testgen/FacadeTemplates.hs
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,13 @@
-- limitations under the License.

module FacadeTemplates (
equalityTemplate
equalityTemplate,
emailTemplate
) where

import Java (assertEquals, toJavaExpression)
import TestTemplate (TestTemplate, genToTestTemplate)
import Test.QuickCheck (Gen, arbitrary)
import Java (assertEquals, runJava, toJavaExpression)
import TestTemplate (TestTemplate(..), genToTestTemplate)
import Test.QuickCheck (Gen, arbitrary, elements, generate, listOf)

equalityTestGenerator :: Gen [String]
equalityTestGenerator = do
Expand All @@ -32,3 +33,25 @@ equalityTestGenerator = do

equalityTemplate :: TestTemplate
equalityTemplate = genToTestTemplate "equals" equalityTestGenerator 3

genEmail :: Gen String
genEmail = do
before <- listOf $ elements (['a'..'z'] ++ ['A'..'Z'] ++ ['0'..'9'])
after <- listOf $ elements (['a'..'z'] ++ ['A'..'Z'] ++ ['0'..'9'])
return $ before ++ "@" ++ after ++ ".com"

emailTestGenerator :: IO [String]
emailTestGenerator = do
email <- generate $ genEmail
resultLines <- runJava
[
"import MakeItFit.utils.EmailValidator;"
, "System.out.println(EmailValidator.isValidEmail(" ++ toJavaExpression email ++ "));"
]
return
[
assertEquals (toJavaExpression email) (last resultLines)
]

emailTemplate :: TestTemplate
emailTemplate = TestTemplate "validEmail" emailTestGenerator 1
48 changes: 46 additions & 2 deletions src/testgen/testgen/Java.hs
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,27 @@ module Java
, assertTrue
, assertEquals
, assertSame
, assertThrows) where
, assertThrows
, runJava
) where

import Data.Char (isAscii, ord)
import Data.List (intercalate)
import Data.List (intercalate, isPrefixOf)
import Numeric (showHex)

import System.Process
(
StdStream(CreatePipe)
, createProcess
, proc
, std_in
, std_out
, std_err
, waitForProcess
)
import System.IO (Handle, hClose, hGetContents, hPutStr)
import Control.Exception (bracket, evaluate)

-- JavaData definition
class JavaData a where
-- | Gets the equivalent Java name for this Haskell type
Expand Down Expand Up @@ -181,3 +196,32 @@ assertThrows e b =
" }"
, ");"
]

-- JVM interop

-- | Runs Java code with classes the project classes loaded
runJava :: [String] -- ^ Java statements
-> IO [String] -- ^ Lines output by the statements
runJava statements = do
(Just stdin, Just stdout, Just stderr, process) <- createProcess
(proc "jshell" ["--class-path=../../build/libs/ATS.jar"])
{ std_in = CreatePipe, std_out = CreatePipe, std_err = CreatePipe }

bracket
(return ())
(\_ -> do
hClose stdin
hClose stdout
hClose stderr
)
(\_ -> do
hPutStr stdin (unlines statements)
hClose stdin

output <- hGetContents stdout
evaluate (length output) -- Force deep strict evaluation
let outputLines = lines output

waitForProcess process
return $ filter (not . isPrefixOf "| ") outputLines
)
16 changes: 15 additions & 1 deletion src/testgen/testgen/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,19 @@

module Main where

import Java (runJava)
import System.Environment (getArgs)
import System.Exit (ExitCode(ExitFailure), exitWith)
import System.IO (hPutStrLn, stderr)
import TestClass (generateTestClass)

main :: IO ()
main = putStrLn "Hello, Haskell!"
main = do
args <- getArgs
case args of
[file] -> do
test <- generateTestClass
writeFile file test
_ -> do
hPutStrLn stderr "Usage: cabal run testgen -- OutputFile.java"
exitWith (ExitFailure 1)
6 changes: 5 additions & 1 deletion src/testgen/testgen/TestClass.hs
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,12 @@ generateUnformattedTestClass = do
tests <- generateTests
return
$ concat
[ [ "import java.util.Arrays;"
[ [ "package MakeItFit;"
, ""
, "import java.util.Arrays;"
, "import java.util.List;"
, "import org.junit.jupiter.api.Test;"
, "import static org.junit.jupiter.api.Assertions.*;"
, ""
, "import MakeItFit.users.User;"
, ""
Expand Down