-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add basic and intermediate coverage exercises
- Loading branch information
1 parent
80cd8bc
commit 1870130
Showing
16 changed files
with
532 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
has_feedback: true | ||
feedback_kind: JaCoCo | ||
coverage_stats: | ||
- INSTRUCTION | ||
- BRANCH |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
package flavour; | ||
|
||
public class Maximum { | ||
|
||
/** | ||
* Find the maximum in an array | ||
* | ||
* @param array A non-null and non empty array of integers | ||
* @return The maximum value in the array | ||
*/ | ||
public static int maximum(int [] array) { | ||
int max = array[0]; | ||
for (int i = 1; i < array.length; i++) { | ||
if (array[i] > max) { | ||
max = array[i]; | ||
} | ||
} | ||
return max; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
#!/bin/python3 | ||
import importlib.util | ||
import sys | ||
|
||
|
||
# Dynamically load modules we need | ||
# Credits to https://stackoverflow.com/a/67692/6149867 | ||
# And for the explanation : http://www.blog.pythonlibrary.org/2016/05/27/python-201-an-intro-to-importlib/ | ||
def dynamically_load_module(module, path): | ||
spec = importlib.util.spec_from_file_location(module, path) | ||
mod = importlib.util.module_from_spec(spec) | ||
spec.loader.exec_module(mod) | ||
return mod | ||
|
||
|
||
##################################### | ||
# Our import for common run file # | ||
##################################### | ||
sys.path.append("/course/common") | ||
|
||
runfile = dynamically_load_module("runfile", "/course/common/runfile.py") | ||
runfile.main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package src; | ||
|
||
public interface ExerciseFlavour { | ||
|
||
/* | ||
* An exercise flavour is an exercise where you want to run a single test suite | ||
* on different implementations of the same algorithm / problem. Each flavour | ||
* MUST implement the method "correctness" stating whether the flavour is correct | ||
* or not. You may want to willingly implement wrong algorithm(s) if (for example) you | ||
* want to assess the quality of a test suite provided by students. | ||
*/ | ||
|
||
|
||
// Return if the flavour is correct or not. | ||
public boolean correctness(); | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
package src; | ||
|
||
import com.github.guillaumederval.javagrading.GradeClass; | ||
import com.github.guillaumederval.javagrading.TestSecurityManager; | ||
import org.junit.internal.runners.statements.FailOnTimeout; | ||
import org.junit.runners.BlockJUnit4ClassRunner; | ||
import org.junit.runners.model.FrameworkMethod; | ||
import org.junit.runners.model.InitializationError; | ||
import org.junit.runners.model.Statement; | ||
import java.security.*; | ||
import java.security.cert.Certificate; | ||
import java.util.concurrent.TimeUnit; | ||
|
||
|
||
/** | ||
* Custom runner that jails everything | ||
*/ | ||
public class JailRunner extends BlockJUnit4ClassRunner { | ||
|
||
public JailRunner(Class<?> klass) throws InitializationError { | ||
super(klass); | ||
} | ||
|
||
|
||
@Override | ||
protected Statement withPotentialTimeout(FrameworkMethod method, Object test, Statement next) { | ||
|
||
GradeClass annoGradeClass = method.getDeclaringClass().getAnnotation(GradeClass.class); | ||
|
||
long timeout = 0; | ||
|
||
if(annoGradeClass != null && timeout == 0 && annoGradeClass.defaultCpuTimeout() > 0) | ||
timeout = annoGradeClass.defaultCpuTimeout() * 3; | ||
|
||
if (timeout <= 0) { | ||
return next; | ||
} | ||
return FailOnTimeout.builder() | ||
.withTimeout(timeout, TimeUnit.MILLISECONDS) | ||
.build(next); | ||
} | ||
|
||
|
||
@Override | ||
protected Statement methodInvoker(FrameworkMethod method, Object test) { | ||
Statement base = super.methodInvoker(method, test); | ||
|
||
checkSecurity(); | ||
|
||
PermissionCollection coll = new Permissions(); | ||
|
||
ProtectionDomain pd = new ProtectionDomain(new CodeSource(null, (Certificate[]) null), coll); | ||
|
||
return new Statement() { | ||
@Override | ||
public void evaluate() throws Throwable { | ||
|
||
Throwable ex = AccessController.doPrivileged(new PrivilegedExceptionAction<Throwable>() { | ||
@Override | ||
public Throwable run() throws Exception { | ||
Throwable ex = null; | ||
try { | ||
base.evaluate(); | ||
} catch (Throwable throwable) { | ||
ex = throwable; | ||
} | ||
return ex; | ||
} | ||
}, new AccessControlContext(new ProtectionDomain[]{pd})); | ||
|
||
if(ex != null) | ||
throw ex; | ||
} | ||
}; | ||
} | ||
|
||
|
||
private static void checkSecurity() { | ||
if(!(System.getSecurityManager() instanceof TestSecurityManager)) { | ||
try { | ||
System.setSecurityManager(new TestSecurityManager()); | ||
} | ||
catch (SecurityException e) { | ||
System.out.println("/!\\ WARNING: Cannot set a TestSecurityManager as the security manager. Tests may not be jailed properly."); | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package src; | ||
|
||
import org.junit.runner.JUnitCore; | ||
import org.junit.runner.Result; | ||
|
||
public class StudentTestRunner { | ||
|
||
public static void main(String[] args) { | ||
JUnitCore runner = new JUnitCore(); | ||
Result result = runner.run(StudentTests.class); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
accessible: true | ||
author: Alexandre Dubray | ||
categories: | ||
- module4 | ||
contact_url: '' | ||
context: | | ||
In this task, you should provide a test suite for coverage check of the following class: | ||
.. code-block:: java | ||
public class Maximum { | ||
/** | ||
* Find the maximum in an array | ||
* | ||
* @param array A non-null and non empty array of integers | ||
* @return The maximum value in the array | ||
*/ | ||
public static int maximum(int [] array) { | ||
int max = array[0]; | ||
for (int i = 1; i < array.length; i++) { | ||
if (array[i] > max) { | ||
max = array[i]; | ||
} | ||
} | ||
return max; | ||
} | ||
} | ||
Here is a small example to show you how to call the method: | ||
.. code-block:: java | ||
@Test | ||
public void test() { | ||
int [] a = new int[]{}; // your test array | ||
int max = Maximum.maximum(a); // find the maximum | ||
// some asserts | ||
} | ||
// some other tests in order to have edge and node coverage | ||
environment: java8scala | ||
evaluate: best | ||
file: '' | ||
groups: false | ||
input_random: '0' | ||
limits: | ||
memory: '100' | ||
output: '2' | ||
time: '30' | ||
name: '[Module 4] Coverage Testing: the basics' | ||
network_grading: false | ||
order: 37 | ||
problems: | ||
student_code: | ||
type: code | ||
header: 'Insert the **BODY** (i.e., your test functions) of your test suite here:' | ||
language: java | ||
name: '' | ||
default: '' | ||
run_cmd: '' | ||
stored_submissions: 0 | ||
submission_limit: | ||
amount: -1 | ||
period: -1 | ||
weight: 1.0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package src; | ||
|
||
import com.github.guillaumederval.javagrading.GradeClass; | ||
import org.junit.Test; | ||
import org.junit.runner.RunWith; | ||
import flavour.*; | ||
|
||
import static org.junit.Assert.*; | ||
|
||
@RunWith(JailRunner.class) | ||
@GradeClass(totalValue = 1, defaultCpuTimeout = 2000) | ||
public class StudentTests { | ||
|
||
// STUDENT CODE WILL BE INSERTED HERE | ||
@ @student_code@@ | ||
// END OF STUDENT CODE | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
has_feedback: true | ||
feedback_kind: JaCoCo | ||
coverage_stats: | ||
- INSTRUCTION | ||
- BRANCH |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
package flavour; | ||
|
||
public class BinarySearch{ | ||
|
||
/** | ||
* Find a value in an integer array | ||
* | ||
* @param array A non-null array of distinct integer | ||
* values sorted in increasing order | ||
* @param value The value to look for in the array | ||
* @return The index of the value in the array of -1 | ||
* if the value is not in the array | ||
*/ | ||
public static int binarySearch(int [] array, int value) { | ||
int lo = 0; | ||
int hi = array.length - 1; | ||
|
||
while (lo <= hi) { | ||
if (array[lo] == value) | ||
return lo; | ||
if (array[hi] == value) | ||
return hi; | ||
|
||
int mid = lo + (hi - lo)/2; | ||
|
||
if (array[mid] == value) | ||
return mid; | ||
|
||
if (mid > value) | ||
hi = mid - 1; | ||
else | ||
lo = mid + 1; | ||
} | ||
return -1; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
#!/bin/python3 | ||
import importlib.util | ||
import sys | ||
|
||
|
||
# Dynamically load modules we need | ||
# Credits to https://stackoverflow.com/a/67692/6149867 | ||
# And for the explanation : http://www.blog.pythonlibrary.org/2016/05/27/python-201-an-intro-to-importlib/ | ||
def dynamically_load_module(module, path): | ||
spec = importlib.util.spec_from_file_location(module, path) | ||
mod = importlib.util.module_from_spec(spec) | ||
spec.loader.exec_module(mod) | ||
return mod | ||
|
||
|
||
##################################### | ||
# Our import for common run file # | ||
##################################### | ||
sys.path.append("/course/common") | ||
|
||
runfile = dynamically_load_module("runfile", "/course/common/runfile.py") | ||
runfile.main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package src; | ||
|
||
public interface ExerciseFlavour { | ||
|
||
/* | ||
* An exercise flavour is an exercise where you want to run a single test suite | ||
* on different implementations of the same algorithm / problem. Each flavour | ||
* MUST implement the method "correctness" stating whether the flavour is correct | ||
* or not. You may want to willingly implement wrong algorithm(s) if (for example) you | ||
* want to assess the quality of a test suite provided by students. | ||
*/ | ||
|
||
|
||
// Return if the flavour is correct or not. | ||
public boolean correctness(); | ||
|
||
} |
Oops, something went wrong.