diff --git a/README.adoc b/README.adoc
index f9a26ec..070c922 100644
--- a/README.adoc
+++ b/README.adoc
@@ -1,7 +1,7 @@
:title: Ares
:description: The Artemis Java Test Sandbox
-:keywords: java, testing, students, deadline, education, tum, test, feedback, sandbox, thread, exercise, teaching, junit, test-framework, ares, junit5, artemis, jqwik, ajts
-:author: Christian Femers
+:keywords: java, testing, students, deadline, education, tum, test, feedback, sandbox, thread, exercise, teaching, junit, test-framework, ares, junit5, artemis, jqwik, ajts, architecture, aspectJ, Instrumentaion
+:author:
:showtitle:
:sectnums:
:toc: preamble
@@ -28,8 +28,7 @@ https://ls1intum.github.io/Ares/[*View this documentation on GitHub Pages!*]
endif::env-github[]
-Ares, also known as Artemis Java Test Sandbox _(abbr. AJTS)_, is a JUnit
-5 extension for easy and secure Java testing on the interactive learning
+Ares, also known as Artemis Java Test Sandbox _(abbr. AJTS)_, is a JUnit extension for easy and secure Java testing on the interactive learning
platform https://github.com/ls1intum/Artemis[Artemis].
Its main features are:
@@ -38,8 +37,9 @@ Its main features are:
* more robust tests and builds due to limits on time, threads and io
* support for public and hidden Artemis tests, where hidden ones obey a custom deadline
* utilities for improved feedback in Artemis like processing multiline error
- messages or pointing to a possible location that caused an Exception
+messages or pointing to a possible location that caused an Exception
* utilities to test exercises using System.out and System.in comfortably
+* possibilities to block potential dangerous methods in different ways like Architecture Tests, Instrumentation or AspectJ
*Project Status*
@@ -64,7 +64,7 @@ Lines (%)]]
== Installation
-_Note: Ares requires at least Java 11._
+_Note: Ares requires at least Java 21._
Ares is provided as Maven/Gradle dependency. To use Ares in the test
environment of a Maven project, include
@@ -104,14 +104,14 @@ in production._
=== Setup
-Assume you have a Java 11 Maven project, and the inside of `pom.xml`
+Assume you have a Java 21 Maven project, and the inside of `pom.xml`
looks like this:
[source,xml]
----
- 11
- 11
+ 21
+ 21
@@ -169,9 +169,9 @@ public class PenguinTest {
In this example,
- `testPenguinPublic()` is supposed to be executed
- after each push and directly give the students their feedback, while
+after each push and directly give the students their feedback, while
- `testPenguinHidden()` should be executed only after the exercise
- deadline, and the results should not be visible before the deadline.
+deadline, and the results should not be visible before the deadline.
While Artemis has a feature to mark test cases as hidden, this will not
prevent the contents of the test case leaking through static variables,
@@ -261,256 +261,183 @@ set, Ares will warn you about that in the logs.
=== What about Security?
-The hidden test case was not executed and static variables cannot leak
-its contents. If you change `getName()` to
+[[advanced-blocking]]
+== Advanced Blocking and Security Policies with AOP, AspectJ, Instrumentation, and Architecture Testing
-[source,java]
-----
-public String getName() {
- System.exit(0);
- return name;
-}
-----
+In addition to its standard security features, Ares now supports advanced blocking mechanisms using **AspectJ**, **AOP (Aspect-Oriented Programming)**, **Instrumentation**, and **Architecture Tests**. These tools provide fine-grained control over student submissions, allowing testers to block specific actions like filesystem access, networking, and thread management through customizable policies defined in YAML files. Moreover, architecture-based tests enforce structural constraints on student code.
-You will now with Ares get the following error message:
-
-....
-java.lang.SecurityException: do not use System.exit(int)
-/// potential problem location: Penguin.getName(Penguin.java:12) ///
-....
-
-As you might be able to see, Ares threw a SecurityException. But it also
-added
-`/// potential problem location: Penguin.getName(Penguin.java:12) ///`.
-This is the line from the stack trace which Ares thinks is most relevant
-for the student, essentially, it searches for the uppermost stack frame
-that is located in the student's code. Student code is basically
-everything that is not whitelisted.
-
-But what is whitelisted?
-
-* The test class itself (in case of nested classes, the outermost class
- is whitelisted) and therefore, _all_ its nested classes and methods,
- too.
-* A predefined set of packages, like everything that starts with
- `java.`, `sun.`, `com.sun.`, `org.junit`, `org.apache.`, …
- Therefore, *never use such package names for student assignments!*
-* Single classes whitelisted using `@WhitelistClass` and
- all classes matching `@AddTrustedPackage`
-* Additional package prefixes provided with by system property
- `ares.security.trustedpackages` separated by a comma `,`.
-
-Ares also grants permissions that are requested by certain actions
-(`System.exit`, File IO, Networking, Threads, …) based on whitelisted
-stack frames. *Ares granting a permission requires all stack frames to
-be whitelisted.*
-
-Another test: +
-Adding one of the following lines to `testPenguinPublic()`
-itself, and it will still pass using the correct student code:
+Our goal is to prevent unauthorized access to key system resources, such as:
-[source,java]
-----
-Files.readString(Path.of("pom.xml"));
-// or
-Files.readString(Path.of("src/test/java/PenguinTest.java")); // assuming default maven structure
-----
+* Filesystem operations (read, write, execute, delete)
+* Networking
+* Thread creation and management
+* Command Execution
+* Usage of unsupported or dangerous methods
-If you instead add one of the lines to the `getName()` method again, you
-will get something like: +
-`java.lang.SecurityException: access to path src\test\java\PenguinTest.java denied in line 16 in Penguin.java`. +
-Which is exactly what you want, students should not be able to read the
-code of the test classes. By default, student code has no access to any
-path, not even read access.
+These policies are defined via the `@Policy` annotation, which applies restrictions according to the YAML configuration files.
-By the way, adding `@WhitelistClass(Penguin.class)` to the test class or
-method will make the test run fine again because `Penguin` is now
-whitelisted and can therefore access all files without problems. *So
-never whitelist classes that students can edit.*
+=== Blocking Categories in Ares
-[#what-you-need-to-do-outside-ares]
-==== What you need to do outside Ares
+You can control access and enforce restrictions in several ways:
-Sadly, due to the way classes are loaded and the class path works when
-testing student code with maven, there are still vulnerabilities if
-students manage to load classes that would be in trusted packages. This
-is especially problematic if they shadow library classes, such as
-JUnit’s `Assertions`.
+1. **AOP**: Apply AOP-based policies to block methods or entire categories of operations.
+1.1 **AspectJ**: Use aspect-oriented programming to intercept method calls at runtime and block access to specified operations.
+1.2 **Instrumentation**: Use Java instrumentation to modify bytecode at runtime and restrict dangerous operations, such as thread management or file deletion.
+2. **Architecture Tests**: Use architecture-based tests to enforce rules on the structure and organization of the student code, preventing the usage of certain packages or methods.
-To prevent that, you have to use the Maven Enforcer Plugin to make sure
-no student content lands in trusted packages:
+=== Example YAML Policy for Filesystem Access Blocking
-Maven:
-[source,xml]
+For example, here is a sample policy file (`EverythingForbiddenPolicy.yaml`) that blocks all access to the filesystem, network, and threads and commands:
+
+```yaml
+regardingTheSupervisedCode:
+ theFollowingProgrammingLanguageConfigurationIsUsed: JAVA_USING_MAVEN_ARCHUNIT_AND_ASPECTJ
+ theProgrammingLanguageUsesTheFollowingPackage: "de.tum.cit.ase.ares"
+ theMainClassInsideThisPackageIs: "Main"
+ theFollowingClassesAreTestClasses: []
+ theFollowingResourceAccessesArePermitted:
+ regardingFileSystemInteractions: []
+ regardingNetworkConnections: []
+ regardingCommandExecutions: []
+ regardingThreadCreations: []
+ regardingPackageImports:
+ - importTheFollowingPackage: "java.io"
+ - importTheFollowingPackage: "java.util"
+ - importTheFollowingPackage: "java.nio"
+ - importTheFollowingPackage: "java.net"
+ - importTheFollowingPackage: "java.awt"
+ - importTheFollowingPackage: "javax.swing"
+ - importTheFollowingPackage: "javax.sound"
+```
+
+This policy blocks all read, write, execute, and delete actions on the filesystem, prevents network connections, blocks all command execution methods and disallows thread creation and management.
+
+=== Applying Security Policies in Tests
+
+You can apply these policies in your test cases using the @Policy annotation, pointing to the relevant YAML file. Here’s how you can block filesystem access in a test:
+
+[source,java]
----
-
- org.apache.maven.plugins
- maven-enforcer-plugin
- 3.1.0
-
-
- enforce-no-student-code-in-trusted-packages
- process-classes
-
- enforce
-
-
-
-
-
-
-
-
- ${project.build.outputDirectory}/ch/qos/logback/
- ${project.build.outputDirectory}/com/github/javaparser/
- ${project.build.outputDirectory}/com/intellij/
- ${project.build.outputDirectory}/com/sun/
- ${project.build.outputDirectory}/de/tum/cit/ase/ares/api/
- ${project.build.outputDirectory}/java/
- ${project.build.outputDirectory}/javax/
- ${project.build.outputDirectory}/jdk/
- ${project.build.outputDirectory}/net/jqwik/
- ${project.build.outputDirectory}/org/apache/
- ${project.build.outputDirectory}/org/assertj/
- ${project.build.outputDirectory}/org/eclipse/
- ${project.build.outputDirectory}/org/jacoco/
- ${project.build.outputDirectory}/org/json/
- ${project.build.outputDirectory}/org/junit/
- ${project.build.outputDirectory}/org/opentest4j/
- ${project.build.outputDirectory}/sun/
- ${project.build.outputDirectory}/org/gradle/
- ${project.build.outputDirectory}/worker/org/gradle/
-
-
-
-
-
+import de.tum.cit.ase.ares.api.Policy;
+
+@Policy("securitypolicies/EverythingForbiddenPolicy.yaml")
+public class FileAccessTest {
+
+ @Test
+ void testFileAccessBlocked() {
+ assertThrows(SecurityException.class, () -> Files.readString(Path.of("test.txt")));
+ }
+}
----
-Gradle:
-[source,groovy]
+In this example, any attempt by the student code to access the file system (like reading from test.txt) will be blocked according to the EverythingForbiddenPolicy.yaml.
+
+=== AspectJ and Instrumentation Integration
+
+Ares also supports the use of AspectJ and Instrumentation to enforce method-level restrictions dynamically. This allows you to intercept method calls and block potentially dangerous operations. Here’s an example of how AspectJ is applied to block filesystem write access:
+
+```yaml
+regardingTheSupervisedCode:
+ theFollowingProgrammingLanguageConfigurationIsUsed: JAVA_USING_GRADLE_ARCHUNIT_AND_ASPECTJ
+ theProgrammingLanguageUsesTheFollowingPackage: "de.tum.cit.ase.ares"
+ theMainClassInsideThisPackageIs: "Main"
+ theFollowingClassesAreTestClasses:
+ theFollowingResourceAccessesArePermitted:
+ regardingFileSystemInteractions:
+ - readAllFiles: true
+ overwriteAllFiles: false
+ executeAllFiles: false
+ deleteAllFiles: false
+ onThisPathAndAllPathsBelow:
+ regardingNetworkConnections: []
+ regardingCommandExecutions: []
+ regardingThreadCreations: []
+ regardingPackageImports:
+ - importTheFollowingPackage: "java.io"
+ - importTheFollowingPackage: "java.util"
+ - importTheFollowingPackage: "java.nio"
+ - importTheFollowingPackage: "java.net"
+ - importTheFollowingPackage: "java.awt"
+ - importTheFollowingPackage: "javax.swing"
+ - importTheFollowingPackage: "javax.sound"
+```
+
+In your test, you can enforce this using:
+
+[source,java]
----
+@Policy("securitypolicies/OnePathAllowedAspectJWrite.yaml")
+public class AspectJWriteBlockTest {
-def forbiddenPackageFolders = [ //<2>
- "$studentOutputDir/ch/qos/logback/",
- "$studentOutputDir/com/github/javaparser/",
- "$studentOutputDir/com/intellij/",
- "$studentOutputDir/com/sun/",
- "$studentOutputDir/de/tum/cit/ase/ares/api/",
- "$studentOutputDir/java/",
- "$studentOutputDir/javax/",
- "$studentOutputDir/jdk/",
- "$studentOutputDir/net/jqwik/",
- "$studentOutputDir/org/assertj/",
- "$studentOutputDir/org/apache/",
- "$studentOutputDir/org/eclipse/",
- "$studentOutputDir/org/gradle/",
- "$studentOutputDir/org/jacoco/",
- "$studentOutputDir/org/json/",
- "$studentOutputDir/org/junit/",
- "$studentOutputDir/org/opentest4j/",
- "$studentOutputDir/sun/",
- "$studentOutputDir/worker/org/gradle/"
-]
-test {
- doFirst { //<1>
- for (String packageFolder in forbiddenPackageFolders) {
- assert !file(packageFolder).exists(): "$packageFolder must not exist within the submission."
- }
+ @Test
+ void testWriteAccessBlocked() {
+ assertThrows(SecurityException.class, () -> Files.write(Path.of("test.txt"), "content".getBytes()));
}
- // ...
}
----
-<1> Important: you want to enforce the non-existence of classes after
- their generation but before testing.
-<2> This is where all folders/packages go that we don't want to exist
- in student code. You will always find the most recent recommendation
- for Ares here. If you use additional third-party libraries that need
- to be configured using `@AddTrustedPackage`, you should add those
- packages here as well. Ares will check that all entries are present. +
- If you don't want Ares to do so, set the `ares.maven.ignore` or
- `ares.gradle.ignore` system property to `true`. In case you want Ares
- to look into a different file, you can set the `ares.maven.pom` or
- `ares.gradle.build` to a path other than the default `pom.xml` or
- `build.gradle`.
-
-=== Further Important Options
-
-Are we done now? With the most fundamental parts yes, but there is a bit
-more you need to know about testing with Ares, as this was just a very
-basic example with a single class and not much testing. Without further
-knowledge, you might not get Ares to work and consequently get rather
-annoyed or even enraged. To prevent that, please read on.
-
-==== Path Access and Class Loading
-
-You can use `@WhitelistPath` and `@BlacklistPath` to control access to
-paths. By default, no access is granted, and so you need to use
-`@WhitelistPath` to give student code the permission to read and write
-files explicitly. You can specify exceptions using `@BlacklistPath`
-which will overpower the whitelisted paths.
-
-_The following examples will make use of `course1920xyz` as placeholder
-value for the real Artemis exercise name/id. Replace it with the real
-one when borrowing code snippets, or nothing will work as expected._
-
-Most importantly, this does not only apply to explicit file IO, but also
-to the `.class` files that the class loader reads, as needed. This
-already happens if one student class requires another one, that has not
-been loaded after that. You can recognize that in the standard error
-output:
-
-....
-[WARN] [main] BAD PATH ACCESS: K:\repo\course1920xyz-solution\bin\some\Thing.class (BL:false, WL:false)
-....
-
-This usually means the class loader could not load the class. The
-parentheses show, that the problem is the missing whitelisting.
-*Therefore, all test setups should have some whitelisting.*
-
-A number of examples how you can whitelist paths in Ares:
-
-* `@WhitelistPath("")` will grant read access to the paths in the
- directory of execution, which is usually where the `pom.xml` is.
-* `@WhitelistPath("pom.xml")` will allow students to read the `pom.xml`.
-* `@WhitelistPath("..")` will allow read access to the level above the
- maven project. In Eclipse, that is the level of your workspace.
-* `@WhitelistPath(value = "../course1920xyz**", type = PathType.GLOB)`
- grants read access to projects beginning with the exercise "id" used
- by Artemis. Should you use the Eclipse feature "Referenced Projects"
- (or the analog to that in your IDE) to link the student/solution project
- to the tests, you will need a setting like this.
-* `@WhitelistPath(value = "data", level = PathActionLevel.DELETE)` will
- allow students to read, write and delete files in the `data` directory
- and subdirectories.
-* `@WhitelistPath("target")` allows reading files in target (Maven output folder)
-* `@BlacklistPath(value = "**Test*.{java,class}", type = PathType.GLOB)`
- prevents access to classes in source code or compiled form that contain
- `Test`. If you leave away the `*` after `Test`, nested classes are not
- blacklisted. Student classes should not be called something with
- "Test" then.
-
-That was not everything but already quite a lot. Take a look at the
-Javadoc of the annotations and enums used, if you want to know more.
-Before you give up, here is my recommendation how to start:
+
+=== Instrumentation Example
+Similarly, Instrumentation can be used to block method execution for certain actions. For instance, you can prevent file deletion:
[source,java]
----
-@WhitelistPath(value = "../course1920xyz**", type = PathType.GLOB) // for manual assessment and development
-@WhitelistPath("target") // mainly for Artemis
-@BlacklistPath("target/test-classes") // prevent access to test-related classes and resources
+@Policy("securitypolicies/OnePathAllowedInstrumentationDelete.yaml")
+public class InstrumentationDeleteBlockTest {
+
+ @Test
+ void testDeleteAccessBlocked() {
+ assertThrows(SecurityException.class, () -> Files.delete(Path.of("test.txt")));
+ }
+}
----
-Add a `@BlacklistPath` for other important classes, like your reference
-implementations of the solution to test against should you use that
-approach.
+=== Architecture Testing for Structural Constraints
+
+Architecture tests enforce restrictions on the structure and organization of student code. For example, you can block the use of specific packages or enforce architectural rules that prevent students from bypassing security measures.
+These measures are automatically applied if you decide to use them and no further action is required via annotations or yaml files.
+
+=== Example Output for Security Violations
+
+When a student violates security policies, Ares provides detailed feedback. Below are some example outputs that can result from the blocking mechanisms applied using AspectJ, Instrumentation, and Architecture Tests.
+
+==== AspectJ Blocking Example Output
+
+If a student attempts to execute a forbidden action such as executing a file via `Files.isExecutable(Path)` while an AspectJ rule is in place, Ares will throw a `SecurityException`:
+
+```plaintext
+org.opentest4j.AssertionFailedError: Could not invoke the method 'accessFileSystemViaFilesExecute'
+in the class FileSystemAccessDemo because of an exception within the method:
+java.lang.SecurityException: Ares Security Error (Reason: Student-Code; Stage: Execution):
+de.tum.cit.ase.FileSystemAccessDemo tried to illegally execute from /Users/student/Project/pom123.xml
+via public static boolean java.nio.file.Files.isExecutable(java.nio.file.Path)
+but was blocked by Ares.
+```
+
+In this example, the student code attempted to execute a file located at pom123.xml using the Files.isExecutable(Path) method, but the attempt was blocked by Ares due to an AspectJ rule.
+
+==== Instrumentation Blocking Example Output
+
+Instrumentation can block method execution and raise detailed exceptions when students try to bypass restrictions. For example, when a student tries to set execute permissions on a file:
+
+```plaintext
+org.opentest4j.AssertionFailedError: Could not invoke the method 'accessFileSystemViaFilesExecute'
+in the class FileSystemAccessDemo because of an exception within the method:
+java.lang.RuntimeException: Error setting execute permissions on file: pom123.xml
+```
+
+This error shows that the student’s attempt to modify file permissions using the Files.setPosixFilePermissions(Path) method triggered a runtime exception, as Ares blocked the action.
+
+==== Architecture Test Violation Example Output
+
+When architecture rules are violated, Ares generates an output indicating the specific violation. For instance, if the student’s code violates a rule that blocks access to filesystem-related classes:
-_Note: the Artemis project starts with `course1920xyz`, but the build in
-Bamboo (by Artemis) will happen in a directory named after the build
-plan, which is in upper case and therefore, begins with `COURSE1920XYZ`.
-Make sure that you do not build multiple student solutions in the same
-directory on the same machine using the git clone (lower case) approach.
-Otherwise, adjust the whitelisting to your needs._
+```plaintext
+java.lang.SecurityException: Ares Security Error (Reason: Student-Code; Stage: Execution):
+Illegal Statement found: Architecture Violation [Priority: MEDIUM] - Rule 'no classes should transitively
+depend on classes that access the file system' was violated (12 times):
+```
+
+This example shows that the student’s code violated a rule defined in an architecture test, where it attempted to depend on filesystem-related classes, triggering an architecture violation.
==== Timeouts
@@ -521,36 +448,36 @@ possible way". What is meant by that?
There are three different ways how the timeouts can work:
* like `org.junit.jupiter.api.Timeout` +
- This timeout is not preemptive, and the test itself runs in the same
- thread executing the tests. It will only try to stop the test via an
- interrupt. If that fails like it does for an endless loop, the test
- will definitively fail. After it is finished. Which might never
- happen and the main reason not to use this when it comes to testing
- unknown code.
+This timeout is not preemptive, and the test itself runs in the same
+thread executing the tests. It will only try to stop the test via an
+interrupt. If that fails like it does for an endless loop, the test
+will definitively fail. After it is finished. Which might never
+happen and the main reason not to use this when it comes to testing
+unknown code.
* like `org.junit.jupiter.api.Assertions.assertTimeoutPreemptively` +
- This will fail the test preemptively by executing the `Executable`
- argument itself in a different thread than the thread executing all
- tests. It will only try to stop the test via an interrupt, but if
- that fails it will simply carry on. The test thread might still run,
- though.
+This will fail the test preemptively by executing the `Executable`
+argument itself in a different thread than the thread executing all
+tests. It will only try to stop the test via an interrupt, but if
+that fails it will simply carry on. The test thread might still run,
+though.
* like `de.tum.cit.ase.ares.api.StrictTimeout` +
- This uses a mechanism similar to `assertTimeoutPreemptively`, but
- will resort to harder means if necessary.
- It will in the following order:
- 1. wait the given duration
- 2. interrupt the thread executing the test and wait no longer (like
- `assertTimeoutPreemptively`)
- 3. block the creation of new threads
- 4. interrupt all threads created during the test and try to join the
- threads
- 5. if that fails, use `Thread.stop()` on all remaining threads
- and try to join again
- 6. repeat step 5 multiple times, if required
- 7. Should that fail, report a special SecurityException that not all
- threads could be stopped. (see the standard error output for a detailed
- report then) _If that happens, no more tests can be properly executed
- because the security cannot be guaranteed and the test cases cannot be
- executed "in isolation". All following tests will fail._
+This uses a mechanism similar to `assertTimeoutPreemptively`, but
+will resort to harder means if necessary.
+It will in the following order:
+1. wait the given duration
+2. interrupt the thread executing the test and wait no longer (like
+`assertTimeoutPreemptively`)
+3. block the creation of new threads
+4. interrupt all threads created during the test and try to join the
+threads
+5. if that fails, use `Thread.stop()` on all remaining threads
+and try to join again
+6. repeat step 5 multiple times, if required
+7. Should that fail, report a special SecurityException that not all
+threads could be stopped. (see the standard error output for a detailed
+report then) _If that happens, no more tests can be properly executed
+because the security cannot be guaranteed and the test cases cannot be
+executed "in isolation". All following tests will fail._
*Rule 1: When testing with Ares, always use `@StrictTimeout` for
timeouts, the others will not work reliably, especially in conjunction
@@ -601,105 +528,6 @@ If you use the annotation on different levels (e.g. class and method)
without stating a new deadline (e.g. deadline only on class level), the
extensions will be added together.
-==== Threads and Concurrency
-
-By default, Ares will not allow non-whitelisted code to use threads at
-all. That includes thread pools, but excludes the common pool and its
-users, like parallel streams. To allow the use of Threads, use the
-annotation `@AllowThreads`. The number of active threads is also
-limited, the default value of that is 1000, but can be changed in the
-annotation. Please keep in mind that this limit should not be larger
-than 1000 to prevent performance and timeout chaos.
-
-New threads are for security reasons not directly whitelisted by Ares
-and will not be allowed to do anything security critical. If you trust a
-thread (at least its entry point), you can explicitly request the thread
-to be whitelisted using
-`ArtemisSecurityManager.requestThreadWhitelisting(Thread)`. The thread
-calling the method and its stack must be whitelisted, of course.
-
-[#testing-console-interaction]
-==== Testing Console Interaction
-
-One example showing some possibilities here:
-
-[source,java]
-----
-void testSquareCorrect(IOTester tester) { //<1>
- tester.provideInputLines("5"); //<2>
-
- InputOutputPenguin.calculateSquare(); //<3>
-
- tester.err().assertThat().isEmpty(); //<4>
- tester.out().assertThat().isEqualTo("""
- Enter Number:
- Answer:
- 25"""); //<5>
-}
-----
-<1> Declare `IOTester` as parameter.
-<2> Provide input lines before calling the student code.
- This content will be used for reading lines from `System.in`.
-<3> Call the student code to process the input and produce output.
-<4> Assert that nothing was printed to `System.err`.
-<5> Assert that the standard output (in this case excluding the final
- line break) is equal to the given text block (if you use text
- blocks, be aware of their newline handling).
-
-Note that Ares normalizes the line breaks to `\n`, and
-https://github.com/ls1intum/Ares/blob/master/src/main/java/de/tum/cit/ase/ares/api/io/OutputTester.java[`OutputTester`]
-offers many different approaches to checking output (e.g. single string, list of strings, ...).
-
-If students read more lines than provided, they get the following feedback:
-...
-java.lang.IllegalStateException: no further console input request after the last(number 1: "5") expected.
-...
-
-See also `IOTester` and for more examples, the
-https://github.com/ls1intum/Ares/blob/master/src/test/java/de/tum/cit/ase/ares/integration/testuser/InputOutputUser.java[`InputOutputUser`]
-test.
-
-<> covers how the student output is
-managed and shown in the test logs.
-
-[TIP]
-====
-In case the default `IOTester` from Ares does not meet your requirements,
-you can provide a custom implementation by applying `@WithIOManager(MyCustomOne.class)`
-to e.g. the test class or individual methods. This also allows you to register
-a custom parameter to control IO testing with ease inside the test method.
-Have a look into the test class linked above to learn more or read the documentation of
-https://github.com/ls1intum/Ares/blob/master/src/main/java/de/tum/cit/ase/ares/api/io/IOManager.java[`IOManager`].
-====
-
-==== Networking
-
-Ares allows for local network connections by using the `@AllowLocalPort`
-annotation.
-
-There are plenty of configuration options, and the code can get complicated
-quickly due to the threads required to test network connections.
-One issue can be that waiting network connections block threads in such
-a way that they cannot be stopped (waiting in native code), so we
-recommend using timeouts for connections at least on one end consistently.
-
-For examples, have a look at the test
-https://github.com/ls1intum/Ares/blob/master/src/test/java/de/tum/cit/ase/ares/integration/testuser/NetworkUser.java[`NetworkUser`].
-
-==== Locale
-
-You can set a locale for Ares (and the rest of Java) by adding the
-`@UseLocale` JUnit extension to classes/methods, which will set the Java
-https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Locale.html#setDefault(java.util.Locale)[default locale]
-that is also used by Ares. The locale is changed only for the scope
-where the annotation is applied.
-
-Ares is currently localized in German (`de_DE`) and English (`en_US`),
-where `en_US` is the fallback for any other locale.
-
-See also the https://github.com/ls1intum/Ares/blob/master/src/test/java/de/tum/cit/ase/ares/integration/testuser/LocaleUser.java[`LocaleUser`]
-test for more examples.
-
== Additional Notes
=== Older Versions
@@ -734,3 +562,4 @@ use
Ares was created by Christian Femers and is licensed under the
https://github.com/ls1intum/Ares/blob/master/LICENSE[MIT License, see
`LICENSE.md`].
+