diff --git a/FuzzLib.scala b/FuzzLib.scala new file mode 100644 index 0000000..ebd6004 --- /dev/null +++ b/FuzzLib.scala @@ -0,0 +1,25 @@ +// Copyright 2024-2025 DCal Team +// +// 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. + +package distcompiler + +class FuzzLib: + def fillerFunction(flag: Boolean, value: Int): Int = + if flag then + if value > 100 then value * 2 + else if value > 50 then value + 10 + else if value > 0 then value + else if value > -50 then value - 5 + else value / 2 + else throw new RuntimeException("Found a failure case") diff --git a/FuzzLibTests.scala b/FuzzLibTests.scala new file mode 100644 index 0000000..3a2cc5c --- /dev/null +++ b/FuzzLibTests.scala @@ -0,0 +1,37 @@ +// Copyright 2024-2025 DCal Team +// +// 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. + +package distcompiler + +import edu.berkeley.cs.jqf.fuzz.Fuzz +import edu.berkeley.cs.jqf.fuzz.JQF +import org.junit.runner.RunWith +import org.junit.Assert.* + +@RunWith(classOf[JQF]) +class FuzzLibTests: + private val fuzzLib = new FuzzLib() + + @Fuzz + def simpleTest(flag: Boolean, value: Int): Unit = + try + val result = fuzzLib.fillerFunction(flag, value) + + if !flag then fail("Expected exception was not thrown") + else if value > 0 then assertTrue("Positive value", result > 0) + else assertTrue("Non-positive value", result <= 0) + catch + case e: RuntimeException => + assertTrue("Exception thrown when flag was true", !flag) + assertEquals("Found a failure case", e.getMessage) diff --git a/RunFuzzLib.scala b/RunFuzzLib.scala new file mode 100644 index 0000000..61acd35 --- /dev/null +++ b/RunFuzzLib.scala @@ -0,0 +1,68 @@ +// Copyright 2024-2025 DCal Team +// +// 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. + +package distcompiler + +import edu.berkeley.cs.jqf.fuzz.junit.GuidedFuzzing +import edu.berkeley.cs.jqf.fuzz.guidance.Guidance +import edu.berkeley.cs.jqf.fuzz.guidance.Result +import edu.berkeley.cs.jqf.fuzz.ei.ZestGuidance + +import java.io.File +import java.io.PrintStream +import java.util.Random + +object RunFuzzLib { + def main(args: Array[String]): Unit = { + val testClassName = "distcompiler.FuzzLibTests" + val testMethod = "simpleTest" + + val outputDir = new File("fuzz-output") + + if (!outputDir.exists()) { + outputDir.mkdirs() + } + + val guidance = new ZestGuidance( + testMethod, // Name of the test method + null, // Duration (null for unlimited time) + 10L, // Trial limit + outputDir, // Output directory for results + new Random() // Random number generator + ) + + println(s"Running JQF test: $testClassName#$testMethod") + println(s"Output directory: ${outputDir.getAbsolutePath}") + + val classLoader = Thread.currentThread().getContextClassLoader() + + val result = GuidedFuzzing.run( + testClassName, + testMethod, + classLoader, + guidance, + System.out + ) + + if (result.wasSuccessful()) { + println("Test completed successfully without finding failures.") + } else { + println(s"Test found ${result.getFailureCount()} failures!") + result.getFailures().forEach { failure => + println(s"Failure: ${failure.getMessage()}") + failure.getException().printStackTrace() + } + } + } +} diff --git a/project.scala b/project.scala index a3fbb24..0a831b6 100644 --- a/project.scala +++ b/project.scala @@ -21,6 +21,7 @@ //> using dep com.lihaoyi::ujson::4.1.0 //> using dependency "io.github.java-diff-utils:java-diff-utils:4.15" //> using test.dep org.scalameta::munit:1.1.0 +//> using dep edu.berkeley.cs.jqf:jqf-fuzz:2.0 //> using javaProp distcompiler.Node.assertErrorRefCorrectness=no