Ares 2 Setup in Detail¶
The templates example-gradle/build.gradle (Gradle) and
example-maven/pom.xml (Maven), together with the test/ folder, already contain everything
below. This page explains it, so you know what you may not remove. Both builds run the same pipeline:
flowchart LR
A["Compile student code<br/>+ weave Ares aspects"] --> B["Reserved-package<br/>guard"]
B --> C["Compile tests"]
C --> D["Run tests with<br/>the Ares agent"]
Gradle needs version 9.1+ to run on JDK 25 (8.14 cannot even read the build script); the template ships a wrapper for 9.8.0.
1. Dependencies. Ares must be visible to the student sources (the weaver needs it there) and to the
tests. In Maven that is the scope provided, not test: with test scope AspectJ silently weaves nothing.
Gradle
repositories {
mavenCentral()
}
configurations {
aresAgent { transitive = false } // just the agent JAR, see 2.
// Maven's "provided": Ares is also on the test classpath
testImplementation.extendsFrom compileOnly
}
dependencies {
compileOnly "de.tum.cit.ase:ares:2.2.1"
// the aspect library the weaver applies to the student classes
aspect "de.tum.cit.ase:ares:2.2.1"
implementation "org.aspectj:aspectjrt:1.9.25.1"
aresAgent "de.tum.cit.ase:ares:2.2.1:agent"
testImplementation(
"io.github.valentinherrmann:levenshtein-testing-framework:latest.release")
testImplementation platform("org.junit:junit-bom:6.1.3")
testImplementation 'org.junit.jupiter:junit-jupiter'
// only the example's TimeoutControlTest needs it: remove it in an exam
testImplementation 'org.junit.platform:junit-platform-testkit'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}
Maven
<dependency>
<groupId>de.tum.cit.ase</groupId>
<artifactId>ares</artifactId>
<version>2.2.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.9.25.1</version>
</dependency>
<dependency>
<groupId>io.github.valentinherrmann</groupId>
<artifactId>levenshtein-testing-framework</artifactId>
<version>[2000.0.0,)</version>
<scope>test</scope>
</dependency>
2. Ares 2 build wiring. Three things: weave the Ares aspects into the compiled student classes, put the
Ares agent where the test JVM can find it, and start the tests with -javaagent plus the module flags.
- Gradle: the plugin
io.freefair.aspectj.post-compile-weaving(weaves; it uses theaspectdependency above), aCopytask for the agent andaspectjrt, andjvmArgsplusforkEvery = 1on thetesttask. Copy these blocks fromexample-gradle/build.gradle. Two details that are easy to miss: forkEvery = 1is Gradle's counterpart of Surefire'sreuseForks=false(see below).exclude '**/*$*'keeps nested classes out of the test run. Surefire skips them by default, Gradle does not, and the example'sTimeoutControlTest$TimeoutProbedeliberately halts its JVM.- Maven:
aspectj-maven-plugin(weaves),maven-dependency-plugin(copies the agent) and Surefire. Copy the plugin blocks fromexample-maven/pom.xml; they follow the Ares guide "transform an Ares 1 protected project into an Ares 2 protected project" (Postcompile, Maven).
3. Reserved-package guard: mandatory. Student classes in the build output come before every dependency
JAR on the test classpath. A student who submits io/github/valentinherrmann/levenshtein/StructuralLevenshtein.java
would replace the framework, and with it every structural test. The guard therefore lists the Ares prefixes
plus io/github/valentinherrmann/levenshtein/**, the instructor test package, org/junit/**,
org/assertj/** and org/opentest4j/**, and fails the build if the student output contains any of them.
- Gradle: the task
verifyAresReservedPackagesinbuild.gradle. It runs right after the student code is compiled and before the tests are compiled, and fails with the offending class files. - Maven: the antrun execution
verify-ares-reserved-packages-v2inexample-maven/pom.xml.
4. Security policy and annotations.
@LevenshteinTest // = @Public + @StrictTimeout(5) + @MirrorOutput
@Policy(value = "test/SecurityPolicy.yaml",
withinPath = "classes/org/example/exam")
class ExamTest {
// @Test, @TestFactory ... (plain JUnit annotations)
}
@LevenshteinTest(or@HiddenLevenshteinTestplus@Deadline) activates Ares. A class with@Policybut without an Ares test-type annotation runs completely unsupervised, silently.@Policyis exam specific and therefore not part of@LevenshteinTest. The nearest@Policywins; policies are never merged.SecurityPolicy.yaml: seeexample-gradle/test/SecurityPolicy.yaml(Gradle) orexample-maven/test/SecurityPolicy.yaml(Maven). The two files differ in one line only.- Use
JAVA_USING_GRADLE_ARCHUNIT_AND_ASPECTJwith Gradle andJAVA_USING_MAVEN_ARCHUNIT_AND_ASPECTJwith Maven. Ares uses it to find the build output. With the Gradle setting Ares reads thebuild.gradleof the working directory of the test JVM (the project directory, which is Gradle's default); if it is not there, every test fails with "Gradle was selected but no Gradle descriptor is present". withinPathisclasses/<student/package/path>for both build tools. A path likebuild/classes/java/main/...is rejected ("should start with classes or test-classes").theFollowingClassesAreTestClassesmust list the exact fully qualified names of every instructor test, helper, constant and wrapper class. Never use a package name there, and never a class students can edit.- For an exam, normally keep all six permission lists empty.
- Use a student package that is not a prefix of your test or wrapper packages.
Ares 2 behaviour worth knowing¶
- Endless loops end the JVM. On a timeout, Ares 2 interrupts the student code. Student code cannot
react to that interrupt (all thread operations, including
Thread.sleepandObject.wait, are blocked), so Ares halts the test JVM with exit code 124. Start a fresh JVM per test class (SurefirereuseForks=false, GradleforkEvery = 1, as in the templates), so only the tests of the affected class are lost, and keep tests that might loop in their own classes. - Static analysis looks at the whole submission. A single forbidden call anywhere in the student code
(e.g.
Thread.sleep, file access) fails every supervised test, not only the one that runs the code. (If the policy permits some file access, as the example's does forallowed.txt, the static analysis leaves file access to the runtime layer; with empty permission lists, as in an exam, it rejects up front.) - No negative package rules. Ares 1's
@BlacklistPackage("java.util.stream.*")has no Ares 2 counterpart (java.*is always permitted). If an exam must forbid streams, write a dedicated structural/ArchUnit test for it. *_INSTRUMENTATIONmodes are not usable with Ares 2.2.1: the agent fails to transform student classes that declare records.- The examples contain self-checks that fail if the sandbox is not active (for example when the weaving
is missing):
SecurityControlTest(permitted/forbidden file read) andTimeoutControlTest(deadline). They need theSandboxControlclass in the student sources, so do not copy them into a real exam. Use them to validate your setup once.