Arthur Brandao 6 lat temu
rodzic
commit
c2311b345a
36 zmienionych plików z 3198 dodań i 0 usunięć
  1. 0 0
      test/src/.gitkeep
  2. 49 0
      test/src/migl/bdd/EvalTest.java
  3. 64 0
      test/src/migl/bdd/JschemeEval.java
  4. 50 0
      test/src/migl/bdd/LispEval.java
  5. 134 0
      test/src/migl/bdd/basic_lisp_operators.story
  6. 84 0
      test/src/migl/bdd/basic_operators.story
  7. 118 0
      test/src/migl/bdd/excluded-bonus-math_operators.story
  8. 42 0
      test/src/migl/bdd/excluded-magniez.story
  9. 22 0
      test/src/migl/bdd/more_operator_tests.story
  10. 23 0
      test/src/migl/bdd/sem8-list_manipulation.story
  11. 184 0
      test/src/migl/bdd/sem8-simplecontext.story
  12. 116 0
      test/src/migl/bdd/sem9-advancedcontext.story
  13. 44 0
      test/src/migl/bdd/sem9-jscheme_behavior.story
  14. 13 0
      test/src/migl/lisp/AbstractTDD.java
  15. 56 0
      test/src/migl/lisp/LispBooleanOwnTest.java
  16. 245 0
      test/src/migl/lisp/LispElementOwnTest.java
  17. 39 0
      test/src/migl/lisp/LispErrorTest.java
  18. 307 0
      test/src/migl/lisp/LispEvalOwnTest.java
  19. 70 0
      test/src/migl/lisp/LispFactoryOwnTest.java
  20. 44 0
      test/src/migl/lisp/LispImplOwnTest.java
  21. 119 0
      test/src/migl/lisp/LispListOwnTest.java
  22. 67 0
      test/src/migl/lisp/LispParserOwnTest.java
  23. 109 0
      test/src/migl/lisp/LispParserTest.java
  24. 118 0
      test/src/migl/lisp/MoreLispParserTest.java
  25. 34 0
      test/src/migl/lisp/REPLOwnTest.java
  26. 34 0
      test/src/migl/lisp/ReplTest.java
  27. 85 0
      test/src/migl/lisp/operator/ComparatorOperatorOwnTest.java
  28. 97 0
      test/src/migl/lisp/operator/ConsOperatorOwnTest.java
  29. 220 0
      test/src/migl/lisp/operator/DefineOperatorOwnTest.java
  30. 65 0
      test/src/migl/lisp/operator/MathOperatorOwnTest.java
  31. 79 0
      test/src/migl/lisp/operator/MinMaxOperatorOwnTest.java
  32. 93 0
      test/src/migl/util/ConsListOwnTest.java
  33. 108 0
      test/src/migl/util/ConsListTest.java
  34. 16 0
      test/src/migl/util/ConsOwnTest.java
  35. 94 0
      test/src/migl/util/ConsTest.java
  36. 156 0
      test/src/migl/util/MoreConsListTest.java

+ 0 - 0
test/src/.gitkeep


+ 49 - 0
test/src/migl/bdd/EvalTest.java

@@ -0,0 +1,49 @@
+package migl.bdd;
+
+import static org.jbehave.core.io.CodeLocations.codeLocationFromClass;
+
+import java.util.List;
+
+import org.jbehave.core.configuration.Configuration;
+import org.jbehave.core.configuration.MostUsefulConfiguration;
+import org.jbehave.core.io.StoryFinder;
+import org.jbehave.core.junit.JUnitStories;
+import org.jbehave.core.reporters.Format;
+import org.jbehave.core.reporters.StoryReporterBuilder;
+import org.jbehave.core.steps.InjectableStepsFactory;
+import org.jbehave.core.steps.InstanceStepsFactory;
+import org.junit.Test;
+
+
+public class EvalTest extends JUnitStories {
+
+    public EvalTest() {
+        configuredEmbedder().embedderControls().doGenerateViewAfterStories(false).doIgnoreFailureInStories(false)
+                .doIgnoreFailureInView(false).doVerboseFailures(true);
+    }
+
+    @Override
+    public Configuration configuration() {
+        return new MostUsefulConfiguration()
+                // CONSOLE reporting
+                .useStoryReporterBuilder(new StoryReporterBuilder().withDefaultFormats().withFormats(Format.CONSOLE));
+    }
+
+    // Here we specify the steps classes
+    @Override
+    public InjectableStepsFactory stepsFactory() {
+        // varargs, can have more that one steps classes
+        return new InstanceStepsFactory(configuration(), new LispEval(), new JschemeEval());
+    }
+
+    @Override
+    protected List<String> storyPaths() {
+        return new StoryFinder().findPaths(codeLocationFromClass(this.getClass()), "**/*.story", "**/excluded*.story");
+    }
+    
+    @Override
+    @Test
+    public void run() throws Throwable {
+    	super.run();
+    }
+}

+ 64 - 0
test/src/migl/bdd/JschemeEval.java

@@ -0,0 +1,64 @@
+package migl.bdd;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.not;
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.junit.Assert.assertThat;
+
+import org.jbehave.core.annotations.Given;
+import org.jbehave.core.annotations.Then;
+import org.jbehave.core.annotations.When;
+
+import jscheme.JScheme;
+import migl.lisp.Lisp;
+import migl.lisp.LispFactory;
+
+public class JschemeEval {
+
+    private JScheme js;
+    private Lisp lisp;
+
+    private Object eval;
+    private Throwable ex;
+    private Object expected;
+
+    @Given("jscheme and a lisp interpreter")
+    public void newInterpreter() {
+        lisp = LispFactory.makeIntepreter();
+        js = new JScheme();
+    }
+
+    @When("the expression evaluated is $expression")
+    public void eval(String expression) {
+        try {
+            ex = null;
+            eval = null;
+            expected = null;
+            eval = lisp.eval(expression);
+            expected = js.eval(expression);
+        } catch (Throwable e) {
+            ex = e;
+        }
+    }
+
+    @Then("the results should be identical")
+    public void checkResultsAreIdentifcal() {
+        assertThat("No own eval?", eval, is(notNullValue()));
+        assertThat("No jscheme eval?", expected, is(notNullValue()));
+        assertThat(eval.toString(), is(equalTo(expected.toString())));
+    }
+
+    @Then("the results should be different")
+    public void checkResultsAreDifferent() {
+        assertThat("No own eval?", eval, is(notNullValue()));
+        assertThat("No jscheme eval?", expected, is(notNullValue()));
+        assertThat(eval.toString(), is(not(equalTo(expected.toString()))));
+    }
+
+    @Then("the error message should be identical")
+    public void checkError() {
+        assertThat("No exception launched?", ex, is(notNullValue()));
+        assertThat(ex.getMessage(), is(equalTo(expected.toString())));
+    }
+}

+ 50 - 0
test/src/migl/bdd/LispEval.java

@@ -0,0 +1,50 @@
+package migl.bdd;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.hamcrest.CoreMatchers.nullValue;
+import static org.junit.Assert.assertThat;
+
+import org.jbehave.core.annotations.Given;
+import org.jbehave.core.annotations.Then;
+import org.jbehave.core.annotations.When;
+
+import migl.lisp.Lisp;
+import migl.lisp.LispError;
+import migl.lisp.LispFactory;
+
+public class LispEval {
+
+    private Lisp lisp;
+
+    private Object eval;
+    private LispError ex;
+
+    @Given("a lisp interpreter")
+    public void newInterpreter() {
+        lisp = LispFactory.makeIntepreter();
+    }
+
+    @When("the expression entered is $expression")
+    public void eval(String expression) {
+        try {
+            eval = lisp.eval(expression);
+            ex = null;
+        } catch (LispError e) {
+            ex = e;
+        }
+    }
+
+    @Then("the result should be $expectedValue")
+    public void checkValue(String expectedValue) {
+        assertThat("An exception launched?", ex, is(nullValue()));
+        assertThat(eval.toString(), equalTo(expectedValue));
+    }
+
+    @Then("the result should display the error message $message")
+    public void checkError(String message) {
+        assertThat("No exception launched?", ex, is(notNullValue()));
+        assertThat(ex.getMessage(), equalTo(message));
+    }
+}

+ 134 - 0
test/src/migl/bdd/basic_lisp_operators.story

@@ -0,0 +1,134 @@
+Some additional lisp operations
+
+Narrative:
+Our lisp interpreter should be able to 
+perform those lisp operations. 
+
+Scenario: built-in lisp operators
+
+Given a lisp interpreter
+
+When the expression entered is <expression>
+Then the result should be <result>
+
+Examples:
+
+|expression  |result|
+
+|(quote (+ 1 2))|(+ 1 2)|
+|(if #t 3 4)|3|
+|(if #f 3 4)|4|
+|(if (> 10 20) (+ 1 1) (+ 3 3))|6|
+|(if (> 1 2) 3 5)|5|
+|(cons 1 2)|(1 . 2)|
+|(cons 1 ())|(1)|
+|(cons () 1)|(() . 1)|
+|(cons () ())|(())|
+|(cons (cons 1 2)  3)|((1 . 2) . 3)|
+|(cons 1 (cons 2 ())) |(1 2)|
+|(and #f (+ 2 3))|#f|
+|(or #t (+ 2 3))|#t|
+
+Scenario: additional tests from V. Valembois
+
+Given a lisp interpreter
+
+When the expression entered is <expression>
+Then the result should be <result>
+
+Examples:
+
+|expression  |result|
+
+|(= 2 2 2)|#t|
+|(= 2)|#t|
+|(< 1)|#t|
+|(> 1)|#t|
+|(< 1 2 3)|#t|
+|(> 1 2 3)|#f|
+|(or)|#f|
+|(or #t)|#t|
+|(or #f)|#f|
+|(or #f #f #t)|#t|
+|(or #f #f #f #f)|#f|
+|(and)|#t|
+|(and #t)|#t|
+|(and #f)|#f|
+|(and #t #t #f)|#f|
+|(and #t #t #t #t)|#t|
+|(and #t #t #t #f)|#f|
+
+Scenario: additional tests from M. Miceli
+
+Given a lisp interpreter
+
+When the expression entered is <expression>
+Then the result should be <result>
+
+Examples:
+
+|expression  |result|
+|(= 2.0 2.0)|#t|
+|(= 2.0 3.0)|#f|
+|(<= 3.0 2.0)|#f|
+|(<= 2.0 3.0)|#t|
+|(<= 3.0 2)|#f|
+|(<= 2 3.0)|#t|
+|(>= 3.0 2.0)|#t|
+|(>= 2.0 3.0)|#f|
+|(>= 3 2.0)|#t|
+|(>= 2.0 3)|#f|
+
+
+Scenario: additional tests from A. Franco
+
+ Given a lisp interpreter
+
+When the expression entered is <expression>
+Then the result should be <result>
+
+Examples:
+
+|expression  |result|
+|(< 1 2 1.5)|#f|
+|(= 1 1 1 3)|#f|
+|(> 2 1 1.5)|#f|
+
+Scenario: basic error messages
+
+Given a lisp interpreter
+When the expression entered is <expression>
+Then the result should display the error message <result>
+
+Examples:
+
+|expression  |result|
+|(cons 1)|Invalid number of operands|
+|(cons)|Invalid number of operands|
+|(quote)|Invalid number of operands|
+|(quote (+ 1 2) (+ 1 2))|Invalid number of operands|
+|(+ - 2)|Not a number|
+|(- 2 3 4)|Invalid number of operands|
+|(/)|Invalid number of operands|
+|(/ 2)|Invalid number of operands|
+|(/ 2 4 6)|Invalid number of operands|
+|(if)|Invalid number of operands|
+|(if #t)|Invalid number of operands|
+|(if #t 3)|Invalid number of operands|
+|(if #t 3 4 5)|Invalid number of operands|
+|(if (+ 1 2) 3 4)|Not a Boolean|
+|(not (+ 2 3))|Not a Boolean|
+|(and (+ 2 3) #t)|Not a Boolean|
+|(and #t (+ 2 3))|Not a Boolean|
+|(or (+ 2 3) #f)|Not a Boolean|
+|(or #f (+ 2 3))|Not a Boolean|
+|(<)|Invalid number of operands|
+|(>)|Invalid number of operands|
+|(not)|Invalid number of operands|
+|(not #t #t)|Invalid number of operands|
+
+Scenario: Division by zero
+
+Given a lisp interpreter
+When the expression entered is (/ 3 0)
+Then the result should display the error message Division by zero

+ 84 - 0
test/src/migl/bdd/basic_operators.story

@@ -0,0 +1,84 @@
+Some additional mathematical operations
+
+Narrative:
+Our lisp interpreter should be able to 
+perform those maths operations. 
+
+Scenario: built-in operators
+
+Given a lisp interpreter
+
+When the expression entered is <expression>
+Then the result should be <result>
+
+Examples:
+
+|expression  |result|
+|(not #f)   |#t|
+|(not #t)   |#f|
+|(and #t #t)|#t|
+|(and #t #f)|#f|
+|(and #f #t)|#f|
+|(and #f #f)|#f|
+|(or #t #t) |#t|
+|(or #t #f) |#t|
+|(or #f #t) |#t|
+|(or #f #f) |#f|
+|(> 2 3)|#f|
+|(> 2 2)|#f|
+|(> 2.0 3)|#f|
+|(> 2 3.0)|#f|
+|(> 2.0 3.0)|#f|
+|(> 4 2.0)|#t|
+|(> 4.0 2.0)|#t|
+|(> 5 4)|#t|
+|(>= 2 3)|#f|
+|(>= 2 2)|#t|
+|(< 2 3)|#t|
+|(< 2 2)|#f|
+|(< 2 3.0)|#t|
+|(< 2.0 2)|#f|
+|(< 2.0 2.0)|#f|
+|(<= 2 3)|#t|
+|(<= 2 2)|#t|
+|(<= 3 2)|#f|
+|(= 2 3)|#f|
+|(= 2 2)|#t|
+|(= 2 2.0)|#t|
+|(= 2.0 2)|#t|
+|(= 3.0 2)|#f|
+|(= 2 3.0)|#f|
+|(+ 1 2)|3|
+|(+ 1.0 2)|3.0|
+|(+ 1 2.0)|3.0|
+|(+ 1.0 2.0)|3.0|
+|(+)|0|
+|(+ 1)|1|
+|(+ 1 2)|3|
+|(+ 1 2 3)|6|
+|(+ 1.0)|1.0|
+|(+ 1.0 2.0)|3.0|
+|(+ 1.0 2.0 3.0)|6.0|
+|(*)|1|
+|(* 2)|2|
+|(* 1 2)|2|
+|(* 1 2 3)|6|
+|(* 1.0)|1.0|
+|(* 1.0 2.0)|2.0|
+|(* 1.0 2.0 3.0)|6.0|
+|(* 1.25 2.789 5.5678)|19.41074275|
+|(- 1)|-1|
+|(- 1 2)|-1|
+|(- 3 7)|-4|
+|(- 7 3)|4|
+|(- 1.0)|-1.0|
+|(- 1.0 3.0)|-2.0|
+|(- 2.0 8.0)|-6.0|
+|(- 8.0 2.0)|6.0|
+|(/ 4 2)|2|
+|(/ 5 2)|2|
+|(/ 2 5)|0|
+|(/ 4 2.0)|2.0|
+|(/ 5 2.0)|2.5|
+|(/ 2 5.0)|0.4|
+|(/ 2.0 5.0)|0.4|

+ 118 - 0
test/src/migl/bdd/excluded-bonus-math_operators.story

@@ -0,0 +1,118 @@
+Some basic mathematical operations
+
+Narrative:
+Our lisp interpreter should be able to 
+perform basic maths. It will rely on the
+methods found in java.lang.Math for functions
+like cos, sin, abs, etc.
+
+Scenario: built-in operators
+
+Given a lisp interpreter
+
+When the expression entered is <expression>
+Then the result should be <result>
+
+Examples:
+
+|expression  |result|
+|(+ 1 1)     |  2   |
+|(+ 1 2 3 4) | 10   |
+|(- 5)       | -5   |
+|(- 1 3)     | -2   |
+|(* 1 3)     |  3   |
+|(* 1 3 5 7) |105   |
+|(/ 3 2)     |  1   |
+|(max 2 3)   |  3   |
+
+Scenario: Division by zero
+
+Given a lisp interpreter
+When the expression entered is (/ 3 0)
+Then the result should display the error message Division by zero
+
+Scenario: operands must be evaluated
+
+Given a lisp interpreter
+
+When the expression entered is <expression>
+Then the result should be <result>
+
+Examples:
+
+|expression  |result|
+|(+ (* 2 3) (- 8 5))  |  9   |
+|(* (+ 1 (* 2 3) 4) 9) | 99   |
+|(- (* 2 3) (* 3 4))| -6|
+|(/ (* 2 7) (* 4 5.0))|0.7|
+|(if (or (> 4 5) (< 4 5)) (+ 2 3) (- 3 2))| 5   |
+|(or (= (+ 2 3) 5 (/ 10 2)) (> 5 0))|#t|
+|(and (> (+ 2 3) (- 9 8)) (= (* 3 3) (+ 3 6) (/ 27 3) (- 12 3)))|#t|
+|(not (> 26 56))|#t|
+
+Scenario: java.lang.Math functions
+
+Given a lisp interpreter
+
+When the expression entered is <expression>
+Then the result should be <result>
+
+Examples:
+
+|expression|result|
+|(abs (- 8))  |8 |
+|(abs (- 8.0))|8.0 |
+|(cbrt 8.0)|2.0|
+|(ceil 8.45)|9.0|
+|(floor 8.45)|8.0|
+|(log10 100)|2.0|
+|(cos 0)   |1.0   |
+|(pow 2 3) |8.0   |
+|(min 2 3) |2     |
+|(min 2.0 3.0)|2.0|
+|(max 2 3) |3     |
+|(max 2.0 3.0)|3.0|
+|(rint 8.45)|8.0|
+|(rint 8.55)|9.0|
+|(round 8.45)|8|
+|(round 8.55)|9|
+|(signum 5.9)|1.0|
+|(signum (- 5.9))|-1.0|
+|(signum 0.0)|0.0|
+
+Scenario: Wrong number of operands for Math methods poke M. Valembois
+
+Given a lisp interpreter
+When the expression entered is <expression>
+Then the result should display the error message Invalid number of operands
+
+Examples:
+
+|expression|
+|(abs 8 9)  |
+|(abs)|
+|(abs 8.0 9.0)|
+|(cbrt 8.0 16.0)|
+|(cbrt)|
+|(ceil 8.45 9.1)|
+|(ceil)|
+|(floor 8.45 9.12)|
+|(floor)|
+|(log10 100 1000)|
+|(log10)|
+|(cos 0 90)|
+|(cos)|
+|(pow 2 3 4)|
+|(pow)|
+|(min 2 3 4) |
+|(min)|
+|(min 2.0 3.0 4.0)|
+|(max 2 3 4) |
+|(max)|
+|(max 2.0 3.0 4.0)|
+|(rint 8.45 9.45)|
+|(rint)|
+|(round 8.45 9.55)|
+|(round)|
+|(signum 5.9 (- 7.8))|
+|(signum)|

+ 42 - 0
test/src/migl/bdd/excluded-magniez.story

@@ -0,0 +1,42 @@
+Some basic mathematical operations
+
+Narrative:
+Examples contributed by Alexandre Magniez to improve tests code coverage.
+
+Scenario: built-in operators
+
+Given a lisp interpreter
+
+When the expression entered is <expression>
+Then the result should be <result>
+
+Examples:
+
+|expression  |result|
+|(max 1.2 2.2)|	 2.2|
+|(min 1.2 2.2)|	1.2|
+|(+ 1.0 2.0) |	3.0|
+|(- 2.0 1.0)|	1.0|
+|(* 2.0 1.0)| 	2.0|
+|(/ 2.0 1.0)| 	2.0|
+|(< 1 2)	|    #t|
+|(< 1.2 2.2)|    #t|
+|(> 1 2)	|	 #f|
+|(> 1.2 2.2)|	 #f|
+|(abs -5.0)	|	5.0|
+|(pow 1.0 2.0)|	1.0|
+
+
+
+Scenario: basic error messages
+
+Given a lisp interpreter
+When the expression entered is <expression>
+Then the result should display the error message <result>
+
+Examples:
+
+|expression  |result|
+|(/ 1 2 3)|Invalid number of operands|
+|(abs 1 2)|Invalid number of operands|
+|(pow 1 2 3)|Invalid number of operands|

+ 22 - 0
test/src/migl/bdd/more_operator_tests.story

@@ -0,0 +1,22 @@
+Some additional mathematical operations
+
+Narrative:
+Our lisp interpreter should be able to 
+perform those maths operations. 
+
+Scenario: built-in operators
+
+Given a lisp interpreter
+
+When the expression entered is <expression>
+Then the result should be <result>
+
+Examples:
+
+|expression  |result|
+|(- (+ 2 3))|-5|
+|(- 9 20)|-11|
+|(- (+ (* 2 3) (/ 9 3)) 20)|-11|
+|(- 9 (* 4 5))|-11|
+|(- (* 4 5) 9)|11|
+|(- (+ (* 2 3) (/ 9 3)) (* 4 5))|-11|

+ 23 - 0
test/src/migl/bdd/sem8-list_manipulation.story

@@ -0,0 +1,23 @@
+Some list related operations
+
+Narrative:
+Most of the features of the interpreter rely
+on the use of cons and lists. As such, it is important
+to test thoroughly those features.
+
+Scenario: cons operator
+
+Given a lisp interpreter
+
+When the expression entered is <expression>
+Then the result should be <result>
+
+Examples:
+
+|expression|result|
+|(cons 1 2)   |(1 . 2)     |
+|(cons 1 nil) |(1)   |
+|(cons nil 1) |(() . 1)     |
+|(cons nil nil)   |(())     |
+|(cons (cons 1 2)  3) |((1 . 2) . 3)   |
+|(cons 1 (cons 2 nil)) |(1 2)   |

+ 184 - 0
test/src/migl/bdd/sem8-simplecontext.story

@@ -0,0 +1,184 @@
+Some simple context-aware operations
+
+Description:
+
+As in any language, lisp interpreters allow to
+store information in "variables".
+
+A variable is an identifier, which is associated to a lisp
+expression using the operator "define". 
+
+To update the value associated with a variable,
+a specific "set!" operator must be used.
+
+The scope of those variables is by default global, i.e. 
+they can be accessed in any lisp expression after being 
+defined.
+
+A specific case is the one of function (lambda expression) parameters.
+Those variables are not defined explicitly.
+Their scope is limited to the body of the lambda expression.
+
+Narrative:
+
+In order to reuse information, 
+as a casual lisp user
+I want to associate expressions to identifiers using the keyword define.
+
+Scenario: simple definitions
+
+Given a lisp interpreter
+
+When the expression entered is (define a 5)
+Then the result should be 5
+
+When the expression entered is (define b 10)
+Then the result should be 10
+
+When the expression entered is <expression>
+Then the result should be <result>
+
+Examples:
+
+|expression  |result|
+|(+ a b)       | 15   |
+|(- a b)     | -5   |
+|(* a b)     |  50   |
+|(* 1 a 2 b) | 100   |
+|(/ b a)     |  2   |
+|(if (> a b) a b)   |  10   |
+|(if (< a b) a b)   |  5   |
+|(cons a (cons b ()))| (5 10) |
+
+Scenario: overriding definitions
+
+Given a lisp interpreter
+
+When the expression entered is (define a 5)
+Then the result should be 5
+
+When the expression entered is (define b 10)
+Then the result should be 10
+
+When the expression entered is (+ a b)
+Then the result should be 15
+
+When the expression entered is (define b 30)
+Then the result should be 30
+
+When the expression entered is (+ a b)
+Then the result should be 35
+
+When the expression entered is (define a 20)
+Then the result should be 20
+
+When the expression entered is (+ a b)
+Then the result should be 50
+
+Scenario: some students are picky about testing
+
+Given a lisp interpreter
+
+When the expression entered is <expression>
+Then the result should display the error message <result>
+
+Examples:
+
+|expression|result|
+|(define 12 20)|12 is not a valid identifier|
+|(define + 20)|+ is not a valid identifier|
+|(define - 20)|- is not a valid identifier|
+|(define * 20)|* is not a valid identifier|
+|(define / 20)|/ is not a valid identifier|
+|(define or 20)|or is not a valid identifier|
+|(define not 20)|not is not a valid identifier|
+|(define and 20)|and is not a valid identifier|
+|(define lambda 20)|lambda is not a valid identifier|
+|(define define 20)|define is not a valid identifier|
+|(define set! 20)|set! is not a valid identifier|
+|(define cons 20)|cons is not a valid identifier|
+
+
+
+Scenario: modifying the value of an identifier using set!
+
+Given a lisp interpreter
+When the expression entered is (define a 50)
+Then the result should be 50
+
+When the expression entered is (set! a 30)
+Then the result should be 30
+
+When the expression entered is (set! b 20)
+Then the result should display the error message b is undefined
+
+Scenario: defining a function (a lambda expression) with one parameter
+
+Given a lisp interpreter
+
+When the expression entered is (define surprise (lambda (x) (* x x)))
+Then the result should be lambda (x) (* x x)
+
+When the expression entered is (surprise 10)
+Then the result should be 100
+
+Scenario: defining a function (a lambda expression) with two parameters
+
+Given a lisp interpreter
+
+When the expression entered is (define surprise (lambda (x y) (* x y)))
+Then the result should be lambda (x y) (* x y)
+
+When the expression entered is (surprise 10 20)
+Then the result should be 200
+
+Scenario: a function has its own context
+
+Given a lisp interpreter
+
+When the expression entered is (define x 10)
+Then the result should be 10
+
+When the expression entered is x
+Then the result should be 10
+
+When the expression entered is (define surprise (lambda (x) (* x x)))
+Then the result should be lambda (x) (* x x)
+
+When the expression entered is (surprise 15)
+Then the result should be 225
+
+When the expression entered is x
+Then the result should be 10
+
+
+Scenario: identifier is not defined
+
+Given a lisp interpreter
+
+When the expression entered is x
+Then the result should display the error message x is undefined
+
+When the expression entered is (surprise 15)
+Then the result should display the error message surprise is undefined
+
+
+Scenario: first group inspiration
+
+Given a lisp interpreter
+
+When the expression entered is (define n 10)
+Then the result should be 10
+
+When the expression entered is (define f (lambda (x) (* n x)))
+Then the result should be lambda (x) (* n x)
+
+When the expression entered is (f 4)
+Then the result should be 40
+
+When the expression entered is (set! n 100)
+Then the result should be 100
+
+When the expression entered is (f 4)
+Then the result should be 400
+

+ 116 - 0
test/src/migl/bdd/sem9-advancedcontext.story

@@ -0,0 +1,116 @@
+The final touch to our interpreter
+
+Narrative:
+
+In order to have a fully working interpreter, 
+
+as a casual lisp user
+
+I want to better manipulate lists, and express functions (lambda).
+
+Scenario: cons and list operations
+
+Given a lisp interpreter
+
+When the expression entered is <expression>
+Then the result should be <result>
+
+Examples:
+
+|expression  |result|
+|(cons 1 2)  | (1 . 2)|
+|(car (cons 1 2))| 1  |
+|(cdr (cons 1 2))| 2  |
+|(cons 1 (cons 2 ())) | (1 2)   |
+|(car (cons 1 (cons 2 ()))) | 1 |
+|(cdr (cons 1 (cons 2 ()))) | (2) |
+|(list 1 2 3)   |  (1 2 3)   |
+
+Scenario: more complex functions (lambdas)
+
+Given a lisp interpreter
+
+When the expression entered is (define twice (lambda (x) (* 2 x)))
+Then the result should be lambda (x) (* 2 x)
+
+When the expression entered is (define strange (lambda (f x) (f (f x))))
+Then the result should be lambda (f x) (f (f x))
+
+When the expression entered is (strange twice 10)
+Then the result should be 40
+
+Scenario: recursive functions - factorial
+
+Given a lisp interpreter
+
+When the expression entered is (define fact (lambda (n) (if (<= n 1) 1 (* n (fact (- n 1))))))
+Then the result should be lambda (n) (if (<= n 1) 1 (* n (fact (- n 1))))
+
+When the expression entered is (fact 0)
+Then the result should be 1
+
+When the expression entered is (fact 1)
+Then the result should be 1
+
+When the expression entered is (fact 2)
+Then the result should be 2
+
+When the expression entered is (fact 3)
+Then the result should be 6
+
+When the expression entered is (fact 10)
+Then the result should be 3628800
+
+When the expression entered is (fact 100)
+Then the result should be 93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000
+
+Scenario: recursive functions - fibonacci
+
+Given a lisp interpreter
+
+When the expression entered is (define fib (lambda (n) (if (< n 2) 1 (+ (fib (- n 1)) (fib (- n 2))))))
+Then the result should be lambda (n) (if (< n 2) 1 (+ (fib (- n 1)) (fib (- n 2))))
+
+When the expression entered is (define range (lambda (a b) (if (= a b) (list) (cons a (range (+ a 1) b)))))
+Then the result should be lambda (a b) (if (= a b) (list) (cons a (range (+ a 1) b)))
+
+When the expression entered is (range 0 10)
+Then the result should be (0 1 2 3 4 5 6 7 8 9)
+
+When the expression entered is (map fib (range 0 10))
+Then the result should be (1 1 2 3 5 8 13 21 34 55)
+
+When the expression entered is (map fib (range 0 20))
+Then the result should be (1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765)
+
+Scenario: back to LCPF
+
+Given a lisp interpreter
+
+When the expression entered is (define f (lambda (x) (lambda (y) (* x y))))
+Then the result should be lambda (x) (lambda (y) (* x y))
+
+When the expression entered is ((f 10) 20)
+Then the result should be 200
+
+Scenario: some potential error
+
+Given a lisp interpreter
+
+When the expression entered is (define f (lambda (+ 2 3)))
+Then the result should display the error message Invalid number of operands
+
+Scenario: some students are picky about testing
+
+Given a lisp interpreter
+
+When the expression entered is <expression>
+Then the result should display the error message <result>
+
+Examples:
+
+|expression|result|
+|(define car 20)|car is not a valid identifier|
+|(define cdr 20)|cdr is not a valid identifier|
+|(define list 20)|list is not a valid identifier|
+

+ 44 - 0
test/src/migl/bdd/sem9-jscheme_behavior.story

@@ -0,0 +1,44 @@
+Some basic mathematical operations
+
+Narrative:
+We need to check that our interpreter performs the
+same operations as jscheme (at least on classical
+lisp/scheme operations). It may differ on some 
+specific but documented cases.
+
+Scenario: built-in operators
+
+Given jscheme and a lisp interpreter
+
+When the expression evaluated is <expression>
+Then the results should be identical
+
+Examples:
+
+|expression|
+|(+ 1 1)   |
+|(+ 1 1 1) |
+|(+ 1 1 1 2) |
+|(- 1 3)   |
+|(* 1 3)   |
+|(* 1 3 5) |
+|(* 1 3 5 7) |
+|(/ 3 2)   |
+|(max 2 3) |
+
+Scenario: cons
+
+Given jscheme and a lisp interpreter
+
+When the expression evaluated is <expression>
+Then the results should be identical
+
+Examples:
+
+|expression|
+|(cons 1 2)   |
+|(cons 1 ()) |
+|(cons () 1) |
+|(cons () ())   |
+|(cons (cons 1 2)  3) |
+|(cons 1 (cons 2 ())) |

+ 13 - 0
test/src/migl/lisp/AbstractTDD.java

@@ -0,0 +1,13 @@
+package migl.lisp;
+
+import org.junit.Before;
+
+public abstract class AbstractTDD {
+
+    protected Lisp lisp;
+
+    @Before
+    public void init() {
+        lisp = LispFactory.makeIntepreter();
+    }
+}

+ 56 - 0
test/src/migl/lisp/LispBooleanOwnTest.java

@@ -0,0 +1,56 @@
+package migl.lisp;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertEquals;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.Test;
+
+public class LispBooleanOwnTest {
+	
+	@Test
+	public void testLispBooleanValue(){
+		assertTrue(LispBoolean.TRUE.value());
+		assertFalse(LispBoolean.FALSE.value());
+	}
+	
+	@Test
+	public void testLispBooleanToString() {
+		assertEquals("#t", LispBoolean.TRUE.toString());
+		assertEquals("#f", LispBoolean.FALSE.toString());
+	}
+	
+	@Test
+	public void testLispBooleanValueOfBoolean() {
+		assertEquals(LispBoolean.TRUE, LispBoolean.valueOf(true));
+		assertEquals(LispBoolean.FALSE, LispBoolean.valueOf(false));
+	}
+	
+	@Test
+	public void testLispBooleanHashCode() {
+		assertEquals(new Boolean(true).hashCode(), LispBoolean.TRUE.hashCode());
+		assertEquals(new Boolean(false).hashCode(), LispBoolean.FALSE.hashCode());
+		Map<LispBoolean, String> map = new HashMap<>();
+		map.put(LispBoolean.TRUE, "#t");
+		map.put(LispBoolean.FALSE, "#f");
+		assertEquals("#t", map.get(LispBoolean.TRUE));
+		assertEquals("#f", map.get(LispBoolean.FALSE));
+	}
+	
+	@Test
+	public void testLisbBooleanEquals() {
+		assertTrue(LispBoolean.TRUE.equals(LispBoolean.TRUE));
+		assertFalse(LispBoolean.TRUE.equals(LispBoolean.FALSE));
+		assertTrue(LispBoolean.FALSE.equals(LispBoolean.FALSE));
+		assertTrue(LispBoolean.TRUE.equals(LispBoolean.valueOf(true)));
+		assertTrue(LispBoolean.FALSE.equals(LispBoolean.valueOf(false)));
+		assertTrue(LispBoolean.TRUE.equals(LispBoolean.valueOf("#t")));
+		assertTrue(LispBoolean.FALSE.equals(LispBoolean.valueOf("#f")));
+		assertFalse(LispBoolean.TRUE.equals(true));
+		assertFalse(LispBoolean.FALSE.equals(false));
+	}
+
+}

+ 245 - 0
test/src/migl/lisp/LispElementOwnTest.java

@@ -0,0 +1,245 @@
+package migl.lisp;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.math.BigInteger;
+import java.util.Map;
+import java.util.HashMap;
+
+import org.junit.Test;
+
+import migl.util.Cons;
+
+public class LispElementOwnTest {
+
+	@Test(expected = IllegalArgumentException.class)
+	public void testGenerateBadElement() {
+		Object obj = new Object();
+		LispElement.generate(obj);
+	}
+	
+	@Test(expected = IllegalStateException.class)
+	public void testToIntFail() {
+		LispElement elt = LispElement.valueOf("5.8");
+		elt.toInt();
+	}
+	
+	@Test(expected = IllegalStateException.class)
+	public void testToNumberFail() {
+		LispElement elt = LispElement.valueOf("test");
+		elt.toNumber();
+	}
+	
+	@Test(expected = IllegalStateException.class)
+	public void testToBooleanFail() {
+		LispElement elt = LispElement.valueOf("5.8");
+		elt.toBoolean();
+	}
+	
+	@Test(expected = IllegalStateException.class)
+	public void testToStrFail() {
+		LispElement elt = LispElement.valueOf("5.8");
+		elt.toStr();
+	}
+	
+	@Test(expected = IllegalStateException.class)
+	public void testToListFail() {
+		LispElement elt = LispElement.valueOf("5.8");
+		elt.toList();
+	}
+	
+	@Test(expected = IllegalStateException.class)
+	public void testToConsFail() {
+		LispElement elt = LispElement.valueOf("5.8");
+		elt.toCons();
+	}
+	
+	@Test
+	public void testToInt() {
+		LispElement elt = LispElement.valueOf("8888888888888888");
+		BigInteger expected = new BigInteger("8888888888888888");
+		assertEquals(expected, elt.toInt());
+	}
+	
+	@Test
+	public void testToNumberFromDouble() {
+		LispElement elt = LispElement.valueOf("5.8");
+		Double expected = Double.valueOf(5.8);
+		Double value = elt.toNumber();
+		assertEquals(expected, value);
+	}
+	
+	@Test
+	public void testToNumberFromInt() {
+		LispElement elt = LispElement.valueOf("8");
+		Double expected = Double.valueOf(8.0);
+		Integer notExpected = 8;
+		assertEquals(expected, (Double) elt.toNumber());
+		assertNotEquals(notExpected, elt.toNumber());
+	}
+	
+	@Test
+	public void testToBoolean() {
+		LispElement elt1 = LispElement.valueOf("#t");
+		LispElement elt2 = LispElement.generate(false);
+		assertTrue(elt1.toBoolean());
+		assertFalse(elt2.toBoolean());
+	}
+	
+	@Test
+	public void testToStr() {
+		LispElement elt1 = LispElement.valueOf("test");
+		LispElement elt2 = LispElement.valueOf("test ");
+		assertEquals("test", elt1.toStr());
+		assertNotEquals("test", elt2.toStr());
+	}
+	
+	@Test
+	public void testToList() {
+		LispList list = LispList.valueOf("(1 2 4 8)");
+		LispElement elt = LispElement.generate(list);
+		assertEquals(LispList.valueOf("(1 2 4 8)"), elt.toList());
+		assertNotEquals(LispList.nil(), elt.toList());
+	}
+	
+	@Test
+	public void testToCons() {
+		Cons<Integer, Integer> cons = new Cons<>(8, 4);
+		LispElement elt = LispElement.generate(cons);
+		assertEquals(new Cons<Integer, Integer>(8, 4), elt.toCons());
+		assertNotEquals(new Cons<String, String>("8", "4"), elt.toCons());
+	}
+	
+	@Test
+	public void testHashCode() {
+		LispElement elt1 = LispElement.valueOf("test");
+		LispElement elt2 = LispElement.valueOf("#t");
+		LispElement elt3 = LispElement.valueOf("8");
+		LispElement elt4 = LispElement.valueOf("8.0");
+		Map<LispElement, String> map = new HashMap<>();
+		map.put(elt1, "elt1");
+		map.put(elt2, "elt2");
+		map.put(elt3, "elt3");
+		map.put(elt4, "elt4");
+		assertEquals("elt1", map.get(elt1));
+		assertEquals("elt2", map.get(elt2));
+		assertEquals("elt3", map.get(elt3));
+		assertEquals("elt4", map.get(elt4));
+	}
+	
+	@Test
+	public void testEquals() {
+		LispElement elt1 = LispElement.valueOf("test");
+		LispElement elt2 = LispElement.valueOf("test");
+		LispElement elt3 = LispElement.valueOf("Test");
+		LispElement elt4 = LispElement.valueOf("#t");
+		LispElement elt5 = LispElement.valueOf("#t");
+		LispElement elt6 = LispElement.valueOf("#f");
+		LispElement elt7 = LispElement.valueOf("8");
+		LispElement elt8 = LispElement.valueOf("8.0");
+		Object other = new Object();
+		assertTrue(elt1.equals(elt2));
+		assertFalse(elt1.equals(elt3));
+		assertTrue(elt1.equals(elt1));
+		assertFalse(elt1.equals(null));
+		assertFalse(elt1.equals(elt4));
+		assertTrue(elt4.equals(elt5));
+		assertFalse(elt4.equals(elt6));
+		assertFalse(elt7.equals(elt8));
+		assertFalse(elt1.equals(other));
+		assertEquals(elt1.hashCode(), elt2.hashCode());
+		assertNotEquals(elt1.hashCode(), elt3.hashCode());
+		assertEquals(elt4.hashCode(), elt5.hashCode());
+		assertNotEquals(elt4.hashCode(), elt6.hashCode());
+		assertNotEquals(elt7.hashCode(), elt8.hashCode());
+	}
+
+	@Test
+	public void testGenerateBigIntFromInt() {
+		LispElement elt = LispElement.generate(Integer.valueOf(8));
+		BigInteger expected = new BigInteger("8");
+		assertEquals(expected, elt.getValue());
+	}
+	
+	@Test
+	public void testGenerateBigIntFromLong() {
+		Long l = 8L;
+		BigInteger expected = new BigInteger("8");
+		assertEquals(expected, LispElement.generate(l).getValue());
+	}
+	
+	@Test
+	public void testGenerateNull() {
+		assertNull(LispElement.generate(null).getValue());
+	}
+	
+	@Test
+	public void testIsType() {
+		LispElement entier = LispElement.generate(8);
+		LispElement nombre = LispElement.generate(4.2);
+		LispElement bool = LispElement.generate(true);
+		LispElement str = LispElement.generate("str");
+		LispElement list = LispElement.generate(LispList.nil());
+		LispElement cons = LispElement.generate(new Cons<Integer, Integer>(8, 4));
+		//Entier
+		assertTrue(entier.isInt());
+		assertFalse(nombre.isInt());
+		assertFalse(bool.isInt());
+		assertFalse(str.isInt());
+		assertFalse(list.isInt());
+		assertFalse(cons.isInt());
+		//Nombre
+		assertTrue(entier.isNumber());
+		assertTrue(nombre.isNumber());
+		assertFalse(bool.isNumber());
+		assertFalse(str.isNumber());
+		assertFalse(list.isNumber());
+		assertFalse(cons.isNumber());
+		//Boolean
+		assertFalse(entier.isBoolean());
+		assertFalse(nombre.isBoolean());
+		assertTrue(bool.isBoolean());
+		assertFalse(str.isBoolean());
+		assertFalse(list.isBoolean());
+		assertFalse(cons.isBoolean());
+		//String
+		assertFalse(entier.isStr());
+		assertFalse(nombre.isStr());
+		assertFalse(bool.isStr());
+		assertTrue(str.isStr());
+		assertFalse(list.isStr());
+		assertFalse(cons.isStr());
+		//List
+		assertFalse(entier.isList());
+		assertFalse(nombre.isList());
+		assertFalse(bool.isList());
+		assertFalse(str.isList());
+		assertTrue(list.isList());
+		assertFalse(cons.isList());
+		//Cons
+		assertFalse(entier.isCons());
+		assertFalse(nombre.isCons());
+		assertFalse(bool.isCons());
+		assertFalse(str.isCons());
+		assertFalse(list.isCons());
+		assertTrue(cons.isCons());
+	}
+	
+	@Test
+	public void testCacheSize() {
+		LispElement.clear();
+		assertEquals(0, LispElement.getCacheSize());
+		LispElement.generate(8.4);
+		LispElement.generate("str");
+		LispElement.generate(true);
+		LispElement.generate(new Cons<Integer, Integer>(8, 4));
+		LispElement.generate(8.4);
+		assertEquals(4, LispElement.getCacheSize());
+		LispElement.clear();
+		assertEquals(0, LispElement.getCacheSize());
+	}
+}

+ 39 - 0
test/src/migl/lisp/LispErrorTest.java

@@ -0,0 +1,39 @@
+package migl.lisp;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+
+public class LispErrorTest {
+
+	@Test
+	public void testLispErrorMessageCause() {
+		Throwable cause = new IllegalArgumentException();
+		try {
+			throw new LispError("Erreur test", cause);
+		} catch (LispError ex) {
+			assertEquals("Erreur test", ex.getMessage());
+			assertEquals(cause, ex.getCause());
+		}
+	}
+	
+	@Test
+	public void testLispErrorMessage() {
+		try {
+			throw new LispError("Erreur test");
+		} catch (LispError ex) {
+			assertEquals("Erreur test", ex.getMessage());
+		}
+	}
+	
+	@Test
+	public void testLispErrorCause() {
+		Throwable cause = new IllegalArgumentException();
+		try {
+			throw new LispError(cause);
+		} catch (LispError ex) {
+			assertEquals(cause, ex.getCause());
+		}
+	}
+	
+}

+ 307 - 0
test/src/migl/lisp/LispEvalOwnTest.java

@@ -0,0 +1,307 @@
+package migl.lisp;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import migl.util.ConsList;
+import migl.util.ConsListFactory;
+
+public class LispEvalOwnTest {
+	
+	private LispImpl interpreter;
+	private LispEval eval;
+
+	@Before
+	public void init() {
+		interpreter = (LispImpl) LispFactory.makeIntepreter();
+		eval = interpreter.getEval();
+	}
+	
+	@Test
+	public void testConstructWithNull() throws LispError {
+		assertNull(eval.evaluate());
+	}
+	
+	@Test(expected = IllegalArgumentException.class)
+	public void testSetLispWithNull() throws LispError {
+		eval.setLisp(null);
+	}
+	
+	@Test(expected = LispError.class)
+	public void testIncorrectNumberArgumentQuote() throws LispError {
+		eval.setLisp(interpreter.parse("(quote #t #f"));
+		eval.evaluate();
+	}
+	
+	@Test(expected = LispError.class)
+	public void testIncorrectNumberArgumentNot() throws LispError {
+		eval.setLisp(interpreter.parse("(not #t #f"));
+		eval.evaluate();
+	}
+
+	@Test(expected = LispError.class)
+	public void testIncorrectNumberArgumentSup() throws LispError {
+		eval.setLisp(interpreter.parse("(> #t)"));
+		eval.evaluate();
+	}
+
+	@Test(expected = LispError.class)
+	public void testIncorrectNumberArgumentSupEqu() throws LispError {
+		eval.setLisp(interpreter.parse("(>= #f)"));
+		eval.evaluate();
+	}
+
+	@Test(expected = LispError.class)
+	public void testIncorrectNumberArgumentInf() throws LispError {
+		eval.setLisp(interpreter.parse("(< #t)"));
+		eval.evaluate();
+	}
+
+	@Test(expected = LispError.class)
+	public void testIncorrectNumberArgumentInfEqu() throws LispError {
+		eval.setLisp(interpreter.parse("(<= #f)"));
+		eval.evaluate();
+	}
+
+	@Test(expected = LispError.class)
+	public void testIncorrectNumberArgumentEqu() throws LispError {
+		eval.setLisp(interpreter.parse("(= #t)"));
+		eval.evaluate();
+	}
+
+	@Test(expected = LispError.class)
+	public void testIncorrectNumberArgumentSubstract1() throws LispError {
+		eval.setLisp(interpreter.parse("(- 8 5 4)"));
+		eval.evaluate();
+	}
+
+	@Test(expected = LispError.class)
+	public void testIncorrectNumberArgumentSubstract2() throws LispError {
+		eval.setLisp(interpreter.parse("(-)"));
+		eval.evaluate();
+	}
+
+	@Test(expected = LispError.class)
+	public void testIncorrectNumberArgumentDivide1() throws LispError {
+		eval.setLisp(interpreter.parse("(/ 8)"));
+		eval.evaluate();
+	}
+
+	@Test(expected = LispError.class)
+	public void testIncorrectNumberArgumentDivide2() throws LispError {
+		eval.setLisp(interpreter.parse("(/)"));
+		eval.evaluate();
+	}
+	
+	@Test(expected = LispError.class)
+	public void testIncorrectNumberArgumentDivide3() throws LispError {
+		eval.setLisp(interpreter.parse("(/ 8 5 4)"));
+		eval.evaluate();
+	}
+	
+	@Test(expected = LispError.class)
+	public void testDivideByZero() throws LispError {
+		eval.setLisp(interpreter.parse("(/ 8 0)"));
+		eval.evaluate();
+	}
+	
+	@Test(expected = LispError.class)
+	public void testIncorrectNumberArgumentAbs() throws LispError {
+		eval.setLisp(interpreter.parse("(abs 8 8)"));
+		eval.evaluate();
+	}
+	
+	@Test(expected = LispError.class)
+	public void testIncorrectNumberArgumentPow() throws LispError {
+		eval.setLisp(interpreter.parse("(pow 8)"));
+		eval.evaluate();
+	}
+	
+	@Test(expected = LispError.class)
+	public void testIncorrectNumberArgumentMap() throws LispError {
+		eval.setLisp(interpreter.parse("(map 8)"));
+		eval.evaluate();
+	}
+	
+	@Test(expected = LispError.class)
+	public void testMapException1() throws LispError {
+		eval.setLisp(interpreter.parse("(map 8 4)"));
+		eval.evaluate();
+	}
+	
+	@Test(expected = LispError.class)
+	public void testMapException2() throws LispError {
+		eval.setLisp(interpreter.parse("(define f (lambda (x) (- x x)))"));
+		eval.evaluate();
+		eval.setLisp(interpreter.parse("(map f 8)"));
+		eval.evaluate();
+	}
+	
+	/* --- */
+	
+	@Test
+	public void testEvaluateSingleton() throws LispError {
+		eval.setLisp(interpreter.parse("8"));
+		assertEquals(LispElement.generate(8), eval.evaluate());
+	}
+	
+	@Test(expected = LispError.class)
+	public void testUnknowOperator() throws LispError {
+		eval.setLisp(interpreter.parse("(gl2 #t)"));
+		eval.evaluate();
+	}
+	
+	@Test(expected = LispError.class)
+	public void testMalformedList() throws LispError {
+		ConsList<Object> list = ConsListFactory.nil();
+		list = list.prepend(new Object()).prepend("not");
+		eval.setLisp(list);
+		eval.evaluate();
+	}
+	
+	@Test
+	public void testOriginMalformedListException() {
+		ConsList<Object> list = ConsListFactory.nil();
+		list = list.prepend(new Object()).prepend("not");
+		try {
+			eval.setLisp(list);
+			eval.evaluate();
+			fail("No exception thrown");
+		} catch (LispError ex) {
+			assertTrue(ex.getCause() instanceof IllegalArgumentException);
+		}
+	}
+	
+	@Test
+	public void testOriginBadArgumentTypeException() {
+		try {
+			eval.setLisp(interpreter.parse("(not 8)"));
+			eval.evaluate();
+			fail("No exception thrown");
+		} catch (LispError ex) {
+			assertTrue(ex.getCause() instanceof IllegalStateException);
+		}
+	}
+	
+	@Test(expected = LispError.class)
+	public void testEvaluateIncorrectObject() throws LispError {
+		eval.setLisp(interpreter);
+		eval.evaluate();
+	}
+	
+	@Test
+	public void testSubList() throws LispError {
+		eval.setLisp(interpreter.parse("(+ (- 8 4.2) (* 2 3))"));
+		assertEquals(LispElement.generate(9.8), eval.evaluate());
+	}
+	
+	@Test(expected = LispError.class)
+	public void testForbiddenName1() throws LispError {
+		eval.verifyForbiddenName("#t");
+	}
+	
+	@Test(expected = LispError.class)
+	public void testForbiddenName2() throws LispError {
+		eval.verifyForbiddenName("8");
+	}
+	
+	@Test(expected = LispError.class)
+	public void testForbiddenName3() throws LispError {
+		eval.verifyForbiddenName("8.4");
+	}
+	
+	@Test(expected = LispError.class)
+	public void testForbiddenName4() throws LispError {
+		eval.verifyForbiddenName("+");
+	}
+	
+	@Test
+	public void testForbiddenName5() throws LispError {
+		eval.verifyForbiddenName("var");
+	}
+	
+	@Test
+	public void testEvaluateList() throws LispError {
+		ConsList<Object> cl = ConsListFactory.nil();
+		cl = cl.prepend(8).prepend(4).prepend("+");
+		assertEquals(LispElement.generate(12), eval.evaluateList(cl));
+	}
+	
+	@Test
+	public void testEvaluateListLambda() throws LispError {
+		LispParser parser = new LispParser("(define fonction (lambda (x) (+ x 2)))");
+		eval.setLisp(parser.parse());
+		eval.evaluate();
+		ConsList<Object> cl = ConsListFactory.nil();
+		cl = cl.prepend(8).prepend("fonction");
+		assertEquals(LispElement.generate(10), eval.evaluateList(cl));
+	}
+	
+	@Test(expected = LispError.class)
+	public void testEvaluateListError() throws LispError {
+		ConsList<Object> cl = ConsListFactory.nil();
+		cl = cl.prepend(8).prepend("undef");
+		assertEquals(LispElement.generate(10), eval.evaluateList(cl));
+	}
+	
+	@Test
+	public void testVarNameGetElement() throws LispError {
+		LispParser parser = new LispParser("(define . 8)");
+		eval.setLisp(parser.parse());
+		eval.evaluate();
+		assertEquals(LispElement.generate("-"), eval.getElement("-"));
+		assertEquals(LispElement.generate(8), eval.getElement("."));
+	}
+	
+	@Test
+	public void testOperators() throws LispError {
+		assertEquals(LispElement.generate(true), interpreter.eval("(not #f)"));
+		assertEquals(LispElement.generate(false), interpreter.eval("(not #t)"));
+		assertEquals(LispElement.generate(true), interpreter.eval("(and #t #t)"));
+		assertEquals(LispElement.generate(false), interpreter.eval("(and #f #t)"));
+		assertEquals(LispElement.generate(true), interpreter.eval("(or #f #t)"));
+		assertEquals(LispElement.generate(false), interpreter.eval("(or #f #f)"));
+		assertEquals(LispElement.generate(4.2), interpreter.eval("(if #f 8 4.2)"));
+		assertEquals(LispElement.generate(8), interpreter.eval("(if #t 8 4.2)"));
+		assertEquals(LispElement.generate(8), interpreter.eval("(+ 5 3)"));
+		assertEquals(LispElement.generate(8.4), interpreter.eval("(+ 5 3.4)"));
+		assertEquals(LispElement.generate(8.8), interpreter.eval("(+ 4.4 4.4)"));
+		assertEquals(LispElement.generate(8.0), interpreter.eval("(+ 4 4 0.0)"));
+		assertEquals(LispElement.generate(16), interpreter.eval("(* 4 2 2)"));
+		assertEquals(LispElement.generate(8.0), interpreter.eval("(* 4.0 2)"));
+		assertEquals(LispElement.generate(10.0), interpreter.eval("(* 2.0 5.0)"));
+		assertEquals(LispElement.generate(-8), interpreter.eval("(- 8)"));
+		assertEquals(LispElement.generate(-8.4), interpreter.eval("(- 8.4)"));
+		assertEquals(LispElement.generate(8), interpreter.eval("(- 16 8)"));
+		assertEquals(LispElement.generate(10.0), interpreter.eval("(- 18.0 8)"));
+		assertEquals(LispElement.generate(2.0), interpreter.eval("(- 10.0 8.0)"));
+		assertEquals(LispElement.generate(-11), interpreter.eval("(- 9 (* 4 5))"));
+		assertEquals(LispElement.generate(2), interpreter.eval("(/ 8 4)"));
+		assertEquals(LispElement.generate(4.0), interpreter.eval("(/ 12 3.0)"));
+		assertEquals(LispElement.generate(10.0), interpreter.eval("(/ 80.0 8.0)"));
+		assertEquals(LispElement.generate("(+ 8 4)"), interpreter.eval("(quote (+ 8 4))"));
+		assertEquals(LispElement.generate(8), interpreter.eval("(abs 8)"));
+		assertEquals(LispElement.generate(8), interpreter.eval("(abs -8)"));
+		assertEquals(LispElement.generate(8.4), interpreter.eval("(abs 8.4)"));
+		assertEquals(LispElement.generate(8.4), interpreter.eval("(abs -8.4)"));
+		assertEquals(LispElement.generate(8.4), interpreter.eval("(abs (- 8.4))"));
+		assertEquals(LispElement.generate(8.0), interpreter.eval("(pow 2 3)"));
+		assertEquals(LispElement.generate(8.0), interpreter.eval("(pow 2.0 3)"));
+		assertEquals(LispElement.generate(8.0), interpreter.eval("(pow 2 3.0)"));
+		assertEquals(LispElement.generate(8.0), interpreter.eval("(pow 2.0 3.0)"));
+	}
+	
+	@Test
+	public void testMapOperator() throws LispError {
+		interpreter.eval("(define g (lambda (x) (+ x x)))");
+		assertEquals(LispElement.generate(LispList.nil()), interpreter.eval("(map g (- 8 0))"));
+		interpreter.eval("(define h (lambda (x y) (list x y)))");
+		assertEquals(LispList.valueOf("(8 16)").toString(), interpreter.eval("(map g (h 4 8))").toString());
+	}
+
+}

+ 70 - 0
test/src/migl/lisp/LispFactoryOwnTest.java

@@ -0,0 +1,70 @@
+package migl.lisp;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+
+import org.junit.Before;
+import org.junit.Test;
+
+public class LispFactoryOwnTest {
+	
+	private Lisp firstInstance;
+
+	@Before
+	public void init() {
+		firstInstance = LispFactory.getInterpreter();
+		try {
+			firstInstance.eval("(define var 8)");
+		} catch (LispError e) {
+			fail();
+		}
+	}
+
+	@Test(expected = LispError.class)
+	public void testMakeInterpreter() throws LispError {
+		Lisp l = LispFactory.makeIntepreter();
+		assertTrue(firstInstance != l);
+		l.eval("var");
+	}
+	
+	@Test
+	public void testGetInterpreter() throws LispError {
+		Lisp l = LispFactory.getInterpreter();
+		assertTrue(firstInstance == l);
+		assertEquals(LispElement.generate(8), l.eval("var"));
+	}
+	
+	@Test
+	public void testDefineDontUseTheLastInterpreter1() throws LispError {
+		assertEquals(LispElement.generate(8), firstInstance.eval("var"));
+		LispFactory.makeIntepreter();
+		assertEquals(LispElement.generate(8), firstInstance.eval("var"));
+	}
+	
+	@Test
+	public void testDefineDontUseTheLastInterpreter2() throws LispError {
+		firstInstance.eval("(define f (lambda (x) (* x 2)))");
+		assertEquals(LispElement.generate(8), firstInstance.eval("(f 4)"));
+		LispFactory.makeIntepreter();
+		assertEquals(LispElement.generate(8), firstInstance.eval("(f 4)"));
+	}
+	
+	@Test
+	public void testDefineDontUseTheLastInterpreter3() throws LispError {
+		firstInstance.eval("(define func (lambda (x) (+ x var)))");
+		assertEquals(LispElement.generate(12), firstInstance.eval("(func 4)"));
+		LispFactory.makeIntepreter();
+		assertEquals(LispElement.generate(12), firstInstance.eval("(func 4)"));
+	}
+	
+	@Test
+	public void testLispElementCacheIsClear() {
+		LispElement.generate(8.4);
+		assertTrue(LispElement.getCacheSize() > 0);
+		LispFactory.makeIntepreter();
+		assertEquals(0, LispElement.getCacheSize());
+	}
+	
+}

+ 44 - 0
test/src/migl/lisp/LispImplOwnTest.java

@@ -0,0 +1,44 @@
+package migl.lisp;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Before;
+import org.junit.Test;
+
+public class LispImplOwnTest {
+
+	private LispImpl interpreter;
+
+	@Before
+	public void init() {
+		interpreter = (LispImpl) LispFactory.makeIntepreter();
+	}
+
+	@Test
+	public void testParse() throws LispError {
+		LispParser expected = new LispParser("(+ (* 2 4) (- 2 2))");
+		assertEquals(expected.parse(), interpreter.parse("(+ (* 2 4) (- 2 2))"));
+	}
+	
+	@Test
+	public void testEval() throws LispError {
+		LispParser lp = new LispParser("(+ (* 2 4) (- 2 2))");
+		Object lisp = lp.parse();
+		LispEval expected = interpreter.getEval();
+		expected.setLisp(lisp);
+		assertEquals(expected.evaluate(), interpreter.evaluate(lisp));
+		assertEquals(expected.evaluate(), interpreter.eval("(+ (* 2 4) (- 2 2))"));
+	}
+	
+	@Test
+	public void testGetParser() {
+		assertTrue(interpreter.getParser().getClass() == LispParser.class);
+	}
+	
+	@Test
+	public void testGetEval() {
+		assertTrue(interpreter.getEval().getClass() == LispEval.class);
+	}
+	
+}

+ 119 - 0
test/src/migl/lisp/LispListOwnTest.java

@@ -0,0 +1,119 @@
+package migl.lisp;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.Before;
+import org.junit.Test;
+
+public class LispListOwnTest {
+	
+	private LispList list;
+
+	@Before
+	public void init() {
+		list = LispList.nil();
+	}
+	
+	@Test
+	public void testValueOf1() {
+		list.prepend("8").prepend("4").prepend("2").prepend("1").append("16");
+		assertEquals(list, LispList.valueOf("(1 2 4 8 16)"));
+	}
+	
+	@Test
+	public void testValueOf2() {
+		LispList list = LispList.valueOf("(8 )");
+		LispList expected = LispList.valueOf("(8)");
+		assertEquals(expected, list);
+	}
+	
+	@Test
+	public void testIsEmpty() {
+		assertTrue(list.isEmpty());
+		assertEquals(0, list.size());
+		list.prepend(8);
+		assertFalse(list.isEmpty());
+		assertEquals(1, list.size());
+	}
+	
+	@Test
+	public void testSize() {
+		list.prepend(8).prepend(4).prepend(2).prepend(1).append(16);
+		assertEquals(5, list.size());
+		assertEquals(3, list.getSubList(2).size());
+	}
+	
+	@Test
+	public void testPrepend() {
+		list.prepend("8").prepend("4").prepend("2").prepend("1");
+		assertEquals(LispList.valueOf("(1 2 4 8)"), list);
+	}
+	
+	@Test
+	public void testAppend() {
+		list.append("8").append("4").append("2").append("1");
+		assertEquals(LispList.valueOf("(8 4 2 1)"), list);
+	}
+	
+	@Test
+	public void testGetElement() {
+		list.prepend(8).prepend(4).prepend(2).prepend(1).append(16);
+		assertEquals(8, list.get(3));
+		assertEquals(4, list.get(2));
+		assertEquals(2, list.get(1));
+		assertEquals(1, list.get(0));
+		assertEquals(16, list.get(4));
+		assertNull(list.get(5));
+		assertNull(list.get(-1));
+	}
+	
+	@Test
+	public void testGetSubList() {
+		list.prepend(8).prepend(4).prepend(2).prepend(1).append(16);
+		LispList expected = LispList.nil();
+		expected.prepend(8).prepend(4).append(16);
+		assertEquals(expected, list.getSubList(2));
+	}
+	
+	@Test
+	public void testToString() {
+		list.prepend(8).prepend(4).prepend(2).prepend(1).append(16);
+		assertEquals("(1 2 4 8 16)", list.toString());
+		assertEquals("()", LispList.nil().toString());
+	}
+	
+	@Test
+	public void testEquals() {
+		list.prepend(8).prepend(4).prepend(2).prepend(1);
+		LispList l = LispList.nil();
+		l.prepend(8).prepend(4).prepend(2).prepend(1);
+		assertTrue(list.equals(list));
+		assertFalse(list.equals(null));
+		assertTrue(list.equals(l));
+		assertFalse(list.equals(new Object()));
+	}
+	
+	@Test
+	public void testHashCode() {
+		list.prepend(8).prepend(4).prepend(2).prepend(1).append(16);
+		LispList list2 = list.getSubList(2);
+		LispList list3 = LispList.nil();
+		LispList list4 = LispList.valueOf("(8 4)");
+		Map<LispList, String> map = new HashMap<>();
+		map.put(list, "L1");
+		map.put(list2, "L2");
+		map.put(list3, "L3");
+		map.put(list4, "L4");
+		assertEquals("L1", map.get(list));
+		assertEquals("L2", map.get(list2));
+		assertEquals("L3", map.get(list3));
+		assertEquals("L4", map.get(list4));
+	}
+
+}

+ 67 - 0
test/src/migl/lisp/LispParserOwnTest.java

@@ -0,0 +1,67 @@
+package migl.lisp;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.fail;
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+
+public class LispParserOwnTest {
+	
+	@Test(expected = IllegalArgumentException.class)
+	public void testConstructWithNull() throws LispError {
+		new LispParser(null);
+	}
+	
+	@Test(expected = LispError.class)
+	public void testMultiElementParser() throws LispError {
+		LispParser lp = new LispParser("10 str");
+		lp.parse();
+	}
+	
+	@Test
+	public void testExplode() {
+		try {
+			LispParser lp = new LispParser("(aze (10 5.8))");
+			lp.parse();
+		} catch (LispError e) {
+			fail("Erreur pendant l'analyse");
+		}
+	}
+	
+	@Test
+	public void testBadEndList() throws LispError {
+		LispParser lp = new LispParser("(aze 158 8.6");
+		assertFalse(lp.verify());
+	}
+	
+	@Test
+	public void testListandElementAfter() throws LispError {
+		LispParser lp = new LispParser("(aze (aze rty)) aze");
+		assertFalse(lp.verify());
+	}
+	
+	@Test
+	public void testGetExpression() {
+		String expr = "(+ 4 8)";
+		LispParser lp = new LispParser(expr);
+		assertEquals(expr, lp.getExpression());
+	}
+	
+	@Test
+	public void testParserNotSet() {
+		LispParser lp = new LispParser();
+		assertEquals("", lp.getExpression());
+	}
+	
+	@Test
+	public void testMultipleParse() throws LispError {
+		LispParser expected = new LispParser("(8 4)");
+		LispParser lp = new LispParser();
+		lp.setExpr("(8 4)");
+		assertEquals(expected.parse(), lp.parse());
+		lp.setExpr("(8 4)");
+		assertEquals(expected.parse(), lp.parse());
+	}
+
+}

+ 109 - 0
test/src/migl/lisp/LispParserTest.java

@@ -0,0 +1,109 @@
+package migl.lisp;
+
+import static org.junit.Assert.assertEquals;
+
+import java.math.BigInteger;
+
+import org.junit.Test;
+
+import migl.util.ConsList;
+import migl.util.ConsListFactory;
+
+/**
+ * The aim of those tests is to check that a basic lisp String can be translated
+ * into a list of Java objects.
+ * 
+ * The main issue here is to be able to return the proper Java type for each
+ * object. Note that Lisp using arbitrary precision arithmetic, it is important
+ * to use the BigInteger and Double classes to represent numbers.
+ * 
+ * Note that all inputs are valid for now. Invalid inputs will be tested in
+ * future test cases.
+ * 
+ * @author leberre
+ *
+ */
+public class LispParserTest extends AbstractTDD {
+
+    @Test
+    public void testParsingSingleElement() throws LispError {
+        assertEquals("r", lisp.parse("r"));
+        assertEquals(BigInteger.valueOf(18), lisp.parse("18"));
+        assertEquals(Double.valueOf("-3.14E12"), lisp.parse("-3.14E12"));
+    }
+
+    @Test
+    public void testParsingSingleElementInList() throws LispError {
+        ConsList<Object> expected = ConsListFactory.nil().prepend("r");
+        assertEquals(expected, lisp.parse("(r)"));
+        expected = ConsListFactory.nil().prepend(BigInteger.valueOf(18));
+        assertEquals(expected, lisp.parse("(18)"));
+        expected = ConsListFactory.nil().prepend(Double.valueOf("-3.14E12"));
+        assertEquals(expected, lisp.parse("(-3.14E12)"));
+    }
+
+    @Test
+    public void testParsingSingleExpression() throws LispError {
+        ConsList<Object> expected = ConsListFactory.nil().prepend("r").prepend("r").prepend("+");
+        assertEquals(expected, lisp.parse("(+ r r)"));
+        expected = ConsListFactory.nil().prepend(BigInteger.valueOf(2)).prepend("x").prepend(">");
+        assertEquals(expected, lisp.parse("(> x 2)"));
+        expected = ConsListFactory.nil().prepend(BigInteger.valueOf(10)).prepend("z").prepend("define");
+        assertEquals(expected, lisp.parse("(define z 10)"));
+    }
+
+    @Test
+    public void testParsingSimpleImbricatedExpressions() throws LispError {
+        ConsList<Object> l1 = ConsListFactory.nil().prepend("r").prepend("r").prepend("+");
+        ConsList<Object> expected = ConsListFactory.nil().prepend(BigInteger.valueOf(10)).prepend(l1).prepend("*");
+        assertEquals(expected, lisp.parse("(* (+ r r) 10)"));
+        l1 = ConsListFactory.nil().prepend(BigInteger.valueOf(2)).prepend(BigInteger.valueOf(1)).prepend("+");
+        expected = ConsListFactory.nil().prepend(l1).prepend("quote");
+        assertEquals(expected, lisp.parse("(quote (+ 1 2))"));
+    }
+
+    @Test
+    public void testParsingOtherLispKeyworkds() throws LispError {
+        ConsList<Object> l1 = ConsListFactory.nil().prepend(BigInteger.valueOf(2)).prepend(BigInteger.valueOf(1))
+                .prepend(">");
+        ConsList<Object> expected = ConsListFactory.nil().prepend(BigInteger.valueOf(5)).prepend(BigInteger.valueOf(3))
+                .prepend(l1).prepend("if");
+        assertEquals(expected, lisp.parse("(if (> 1 2) 3 5)"));
+        expected = ConsListFactory.nil().prepend(BigInteger.valueOf(15)).prepend("bb8").prepend("define");
+        assertEquals(expected, lisp.parse("(define bb8 15)"));
+    }
+
+    @Test
+    public void testTypeOfTheObjectsInTheList() throws LispError {
+        @SuppressWarnings("unchecked")
+        ConsList<Object> objects = (ConsList<Object>) lisp.parse("(+ 1 2.0)");
+        assertEquals(3, objects.size());
+        assertEquals(String.class, objects.car().getClass());
+        assertEquals(BigInteger.class, objects.cdr().car().getClass());
+        assertEquals(Double.class, objects.cdr().cdr().car().getClass());
+    }
+
+    @Test
+    public void testTypeOfBooleanConstants() throws LispError {
+        @SuppressWarnings("unchecked")
+        ConsList<Object> objects = (ConsList<Object>) lisp.parse("(or #t #f)");
+        assertEquals(3, objects.size());
+        assertEquals(String.class, objects.car().getClass());
+        assertEquals(LispBoolean.class, objects.cdr().car().getClass());
+        assertEquals(LispBoolean.TRUE, objects.cdr().car());
+        assertEquals(LispBoolean.class, objects.cdr().cdr().car().getClass());
+        assertEquals(LispBoolean.FALSE, objects.cdr().cdr().car());
+    }
+    
+    @Test
+    public void testParsingSingleExpressionMHachinLikesSpaces() throws LispError {
+        ConsList<Object> expected = ConsListFactory.nil().prepend("r").prepend("r").prepend("+");
+        assertEquals(expected, lisp.parse("(+ r   r)"));
+        expected = ConsListFactory.nil().prepend(BigInteger.valueOf(2)).prepend("x").prepend(">");
+        assertEquals(expected, lisp.parse("(> x 2) "));
+        expected = ConsListFactory.nil().prepend(BigInteger.valueOf(10)).prepend("z").prepend("define");
+        assertEquals(expected, lisp.parse(" (define z 10)"));
+        assertEquals(expected, lisp.parse(" (define z 10) "));
+        assertEquals(expected, lisp.parse(" (  define   z     10  )  "));
+    }
+}

+ 118 - 0
test/src/migl/lisp/MoreLispParserTest.java

@@ -0,0 +1,118 @@
+package migl.lisp;
+
+import static org.junit.Assert.assertEquals;
+
+import java.math.BigInteger;
+
+import org.junit.Test;
+
+import migl.util.ConsList;
+import migl.util.ConsListFactory;
+
+/**
+ * Those tests represent incorrect input for our lisp interpreter.
+ * 
+ * @author leberre
+ *
+ */
+public class MoreLispParserTest extends AbstractTDD {
+
+    @Test(expected = LispError.class)
+    public void testNoEndingParenthesis() throws LispError {
+        lisp.parse("(r");
+    }
+
+    @Test(expected = LispError.class)
+    public void testNoOpeningingParenthesis() throws LispError {
+        lisp.parse("r)");
+    }
+
+    @Test(expected = LispError.class)
+    public void testMissingEndOfList() throws LispError {
+        lisp.parse("(< (+ 1 3) 4");
+    }
+
+    @Test(expected = LispError.class)
+    public void testAlternativeMissingEndOfList() throws LispError {
+        lisp.parse("(< (+ 1 3 4)");
+    }
+
+    @Test(expected = LispError.class)
+    public void testMissingBeginningOfList() throws LispError {
+        lisp.parse("< (+ 1 3 4))");
+    }
+
+    @Test(expected = LispError.class)
+    public void testAlternativeMissingBeginningOfList() throws LispError {
+        lisp.parse("(< + 1 3 4))");
+    }
+
+    @Test(expected = LispError.class)
+    public void testCountingIsNotEnoughAkaTestDessaint() throws LispError {
+        lisp.parse(")< + 1 3 4(");
+    }
+
+    @Test(expected = LispError.class)
+    public void testAlternativeCountingIsNotEnoughAkaTestDessaint() throws LispError {
+        lisp.parse("(< )+ 1 3 4()");
+    }
+
+    @Test
+    public void testSpacesInExpressionShouldNotMatterAkaDessaintAgain() throws LispError {
+        ConsList<Object> l1 = ConsListFactory.nil().prepend("r").prepend("r").prepend("+");
+        ConsList<Object> expected = ConsListFactory.nil().prepend(BigInteger.valueOf(10)).prepend(l1).prepend("*");
+        assertEquals(expected, lisp.parse("(*  (+ r r) 10)"));
+        assertEquals(expected, lisp.parse("(* ( + r r ) 10)"));
+        assertEquals(expected, lisp.parse("(* (+ r r) 10 ) "));
+        assertEquals(expected, lisp.parse(" (* (+ r r) 10) "));
+        assertEquals(expected, lisp.parse(" ( * ( + r r ) 10 ) "));
+    }
+
+    @Test
+    public void testTabsInExpressionShouldNotMatterAkaTestVrand() throws LispError {
+        ConsList<Object> l1 = ConsListFactory.nil().prepend("r").prepend("r").prepend("+");
+        ConsList<Object> expected = ConsListFactory.nil().prepend(BigInteger.valueOf(10)).prepend(l1).prepend("*");
+        assertEquals(expected, lisp.parse("(*\t(+\tr\tr)\t10)"));
+        assertEquals(expected, lisp.parse("(*\t\t(\t+\tr\tr\t)\t10)"));
+        assertEquals(expected, lisp.parse("(*\t(+\tr\tr)\t10\t)\t"));
+        assertEquals(expected, lisp.parse("\t(*\t(+\tr\tr)\t10)\t"));
+        assertEquals(expected, lisp.parse("\t(\t* (\t+\tr\tr\t)\t10\t)\t"));
+    }
+
+    @Test(expected = LispError.class)
+    public void testThatEmptyStringCannotBeEvaluatedAkaVrandIsBack() throws LispError {
+        lisp.parse("");
+    }
+
+    @Test(expected = LispError.class)
+    public void testThatOnlySpacesCannotBeEvaluatedAkaVrandIsBack() throws LispError {
+        lisp.parse("   ");
+    }
+
+    @Test(expected = LispError.class)
+    public void testThatOnlyTabsCannotBeEvaluatedAkaVrandIsBack() throws LispError {
+        lisp.parse("\t\t");
+    }
+
+    @Test(expected = LispError.class)
+    public void testThatTwoElementsIsNotCorrect() throws LispError {
+        lisp.parse("foo bar");
+    }
+
+    @Test(expected = LispError.class)
+    public void testThatRemainingDataCannotBeIgnored() throws LispError {
+        lisp.parse("(* x y) foo");
+    }
+
+    @Test(expected = LispError.class)
+    public void testThatRemainingDataCannotBeIgnoredTwoLists() throws LispError {
+        lisp.parse("(* x y)(- y 20)");
+    }
+
+    @Test
+    public void testParsingSingleExpressionHachinLovesSpaces() throws LispError {
+        assertEquals("r", lisp.parse("r   "));
+        ConsList<Object> expected = ConsListFactory.nil().prepend("+");
+        assertEquals(expected, lisp.parse("(+        ) "));
+    }
+}

+ 34 - 0
test/src/migl/lisp/REPLOwnTest.java

@@ -0,0 +1,34 @@
+package migl.lisp;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+
+import org.junit.Before;
+import org.junit.Test;
+
+public class REPLOwnTest {
+
+	private ByteArrayOutputStream myout;
+
+    @Before
+    public void setUp() {
+        myout = new ByteArrayOutputStream();
+        System.setOut(new PrintStream(myout));
+    }
+
+    @Test
+    public void test() {
+        String sep = System.lineSeparator();
+        ByteArrayInputStream myin = new ByteArrayInputStream(("+ 1 2" + sep + "quit" + sep).getBytes());
+        System.setIn(myin);
+        REPL.main(new String[] {});
+        assertEquals("My super own Lisp/Scheme interpreter 2019" + sep
+                + "Enter a valid Lisp expression followed by Enter. type 'quit' to exit." + sep + "> " +  "Error: " + "Invalid Format" + sep
+                + "> " + "Bye." + sep, myout.toString());
+
+    }
+	
+}

+ 34 - 0
test/src/migl/lisp/ReplTest.java

@@ -0,0 +1,34 @@
+package migl.lisp;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+
+import org.junit.Before;
+import org.junit.Test;
+
+public class ReplTest {
+
+    private ByteArrayOutputStream myout;
+
+    @Before
+    public void setUp() {
+        myout = new ByteArrayOutputStream();
+        System.setOut(new PrintStream(myout));
+    }
+
+    @Test
+    public void test() {
+        String sep = System.lineSeparator();
+        ByteArrayInputStream myin = new ByteArrayInputStream(("(+ 1 2)" + sep + "quit" + sep).getBytes());
+        System.setIn(myin);
+        REPL.main(new String[] {});
+        assertEquals("My super own Lisp/Scheme interpreter 2019" + sep
+                + "Enter a valid Lisp expression followed by Enter. type 'quit' to exit." + sep + "> " + "3" + sep
+                + "> " + "Bye." + sep, myout.toString());
+
+    }
+
+}

+ 85 - 0
test/src/migl/lisp/operator/ComparatorOperatorOwnTest.java

@@ -0,0 +1,85 @@
+package migl.lisp.operator;
+
+import static org.junit.Assert.assertEquals;
+
+import java.math.BigInteger;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import migl.lisp.Lisp;
+import migl.lisp.LispElement;
+import migl.lisp.LispError;
+import migl.lisp.LispEval;
+import migl.lisp.LispFactory;
+import migl.util.ConsList;
+import migl.util.ConsListFactory;
+
+public class ComparatorOperatorOwnTest {
+	
+	private Lisp interpreter;
+
+	@Before
+	public void init() {
+		interpreter = LispFactory.makeIntepreter();
+	}
+	
+	@Test
+	public void testSupOperator() throws LispError {
+		assertEquals(LispElement.generate(true), interpreter.eval("(> 8 5)"));
+		assertEquals(LispElement.generate(false), interpreter.eval("(> 8 8)"));
+		assertEquals(LispElement.generate(false), interpreter.eval("(> 5 8)"));
+		assertEquals(LispElement.generate(false), interpreter.eval("(> 8 8 10)"));
+		assertEquals(LispElement.generate(false), interpreter.eval("(> 5 5 8)"));
+	}
+	
+	@Test
+	public void testSupOrEquOperator() throws LispError {
+		assertEquals(LispElement.generate(true), interpreter.eval("(>= 8 5)"));
+		assertEquals(LispElement.generate(true), interpreter.eval("(>= 8 8)"));
+		assertEquals(LispElement.generate(false), interpreter.eval("(>= 5 8)"));
+		assertEquals(LispElement.generate(true), interpreter.eval("(>= 8 8 8)"));
+		assertEquals(LispElement.generate(false), interpreter.eval("(>= 5 4 8)"));
+	}
+	
+	@Test
+	public void testInfOperator() throws LispError {
+		assertEquals(LispElement.generate(true), interpreter.eval("(< 5 8)"));
+		assertEquals(LispElement.generate(false), interpreter.eval("(< 8 8)"));
+		assertEquals(LispElement.generate(false), interpreter.eval("(< 8 5)"));
+		assertEquals(LispElement.generate(false), interpreter.eval("(< 8 8 8)"));
+		assertEquals(LispElement.generate(false), interpreter.eval("(< 8 8 5)"));
+	}
+	
+	@Test
+	public void testInfOrEquOperator() throws LispError {
+		assertEquals(LispElement.generate(true), interpreter.eval("(<= 5 8)"));
+		assertEquals(LispElement.generate(true), interpreter.eval("(<= 8 8)"));
+		assertEquals(LispElement.generate(false), interpreter.eval("(<= 8 5)"));
+		assertEquals(LispElement.generate(true), interpreter.eval("(<= 8 8 10)"));
+		assertEquals(LispElement.generate(false), interpreter.eval("(<= 8 8 10 5)"));
+	}
+	
+	@Test
+	public void testEquOperator() throws LispError {
+		assertEquals(LispElement.generate(true), interpreter.eval("(= 8 8)"));
+		assertEquals(LispElement.generate(false), interpreter.eval("(= 8 5)"));
+		assertEquals(LispElement.generate(true), interpreter.eval("(= 8 8 8 8)"));
+		assertEquals(LispElement.generate(false), interpreter.eval("(= 8 8 5 8)"));
+	}
+	
+	@Test(expected = LispError.class)
+	public void testIncorrectNumberArgumentComparator() throws LispError {
+		interpreter.eval("(=)");
+	}
+	
+	@Test(expected = LispError.class)
+	public void testComparatorOperatorException() throws LispError {
+		LispOperator comp = new ComparatorOperator();
+		ConsList<Object> cl = ConsListFactory.nil();
+		cl = cl.prepend(new BigInteger("8"));
+		cl = cl.prepend(4.2);
+		comp.apply(new LispEval(interpreter), "_", cl);
+	}
+
+}

+ 97 - 0
test/src/migl/lisp/operator/ConsOperatorOwnTest.java

@@ -0,0 +1,97 @@
+package migl.lisp.operator;
+
+import static org.junit.Assert.assertEquals;
+
+import java.math.BigInteger;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import migl.lisp.LispElement;
+import migl.lisp.LispError;
+import migl.lisp.LispEval;
+import migl.lisp.LispFactory;
+import migl.lisp.LispImpl;
+import migl.lisp.LispList;
+import migl.util.ConsList;
+import migl.util.ConsListFactory;
+
+public class ConsOperatorOwnTest {
+	
+	private LispImpl interpreter;
+
+	@Before
+	public void init() {
+		interpreter = (LispImpl) LispFactory.makeIntepreter();
+	}
+	
+	@Test
+	public void testConsOperator() throws LispError {
+		assertEquals("(4 . 8)", interpreter.eval("(cons 4 8)").toString());
+		assertEquals("(())", interpreter.eval("(cons () ())").toString());
+		assertEquals("(8)", interpreter.eval("(cons 8 ())").toString());
+		assertEquals("(() . 8)", interpreter.eval("(cons () 8)").toString());
+		assertEquals("(8 4)", interpreter.eval("(cons 8 (cons 4 ()))").toString());
+	}
+	
+	@Test(expected = LispError.class)
+	public void testIncorrectNumberArgumentCons() throws LispError {
+		interpreter.eval("(cons 8)");
+	}
+	
+	@Test
+	public void testCar() throws LispError {
+		assertEquals(LispElement.generate(8), interpreter.eval("(car (cons 8 4))"));
+		assertEquals(LispElement.generate(8), interpreter.eval("(car (cons 8 (cons 4 ())))"));
+		assertEquals(LispElement.generate(LispList.nil()), interpreter.eval("(car (list))"));
+	}
+	
+	@Test
+	public void testCarWithSingletonList() throws LispError {
+		ConsOperator cons = new ConsOperator();
+		LispList list = LispList.nil().prepend(8.4);
+		ConsList<Object> cl = ConsListFactory.singleton(list);
+		assertEquals(list.get(0), cons.apply(interpreter.getEval(), "car", cl).getValue());
+	}
+	
+	@Test(expected = LispError.class)
+	public void testIncorrectNumberArgumentCar() throws LispError {
+		interpreter.eval("(car 8 4)");
+	}
+	
+	@Test
+	public void testCdr() throws LispError {
+		assertEquals(LispElement.generate(4), interpreter.eval("(cdr (cons 8 4))"));
+		assertEquals(LispElement.generate(LispList.valueOf("(4)")), interpreter.eval("(cdr (cons 8 (cons 4 ())))"));
+		assertEquals(LispElement.generate(LispList.nil()), interpreter.eval("(cdr (list))"));
+	}
+	
+	@Test(expected = LispError.class)
+	public void testIncorrectNumberArgumentCdr() throws LispError {
+		interpreter.eval("(cdr 8 4)");
+	}
+
+	@Test(expected = LispError.class)
+	public void testMinMaxOperatorException2() throws LispError {
+		LispOperator cons = new ConsOperator();
+		ConsList<Object> cl = ConsListFactory.nil();
+		cl = cl.prepend(new BigInteger("8"));
+		cl = cl.prepend(new BigInteger("4"));
+		cons.apply(new LispEval(interpreter), "_", cl);
+	}
+	
+	@Test(expected = LispError.class)
+	public void testCarException() throws LispError {
+		ConsOperator cons = new ConsOperator();
+		ConsList<Object> cl = ConsListFactory.singleton(8.4);
+		cons.car(interpreter.getEval(), cl);
+	}
+	
+	@Test(expected = LispError.class)
+	public void testCdrException() throws LispError {
+		ConsOperator cons = new ConsOperator();
+		ConsList<Object> cl = ConsListFactory.singleton(8.4);
+		cons.cdr(interpreter.getEval(), cl);
+	}
+
+}

+ 220 - 0
test/src/migl/lisp/operator/DefineOperatorOwnTest.java

@@ -0,0 +1,220 @@
+package migl.lisp.operator;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import migl.lisp.LispElement;
+import migl.lisp.LispError;
+import migl.lisp.LispFactory;
+import migl.lisp.LispImpl;
+import migl.util.ConsList;
+import migl.util.ConsListFactory;
+
+public class DefineOperatorOwnTest {
+	
+	private LispImpl interpreter;
+
+	@Before
+	public void init() {
+		interpreter = (LispImpl) LispFactory.makeIntepreter();
+	}
+	
+	@Test(expected = LispError.class)
+	public void testIncorrectNumberDefine() throws LispError {
+		interpreter.eval("(define var)");
+	}
+	
+	@Test(expected = LispError.class)
+	public void testIncorrectNumberSet() throws LispError {
+		interpreter.eval("(define var 8)");
+		interpreter.eval("(define set!)");
+	}
+	
+	@Test(expected = LispError.class)
+	public void testIncorrectNumberLambda() throws LispError {
+		interpreter.eval("(define l (lambda (x) (+ x 8)))");
+		interpreter.eval("(l)");
+	}
+	
+	@Test
+	public void testDefineOperator() throws LispError {
+		assertEquals(LispElement.generate(8), interpreter.eval("(define var 8)"));
+		assertEquals(LispElement.generate(4.6), interpreter.eval("(define iable 4.6)"));
+		assertEquals(LispElement.generate(8), interpreter.eval("var"));
+		assertEquals(LispElement.generate(4.6), interpreter.eval("iable"));
+		assertEquals(LispElement.generate(12.6), interpreter.eval("(+ var iable)"));
+	}
+	
+	@Test(expected = LispError.class)
+	public void testDefineOperatorException1() throws LispError {
+		interpreter.eval("(define * 8)");
+	}
+	
+	@Test(expected = LispError.class)
+	public void testDefineOperatorException2() throws LispError {
+		interpreter.eval("(define #f 8)");
+	}
+	
+	@Test(expected = LispError.class)
+	public void testDefineOperatorException3() throws LispError {
+		interpreter.eval("(define var)");
+	}
+	
+	@Test
+	public void testSetOperator() throws LispError {
+		assertEquals(LispElement.generate(8), interpreter.eval("(define var 8)"));
+		assertEquals(LispElement.generate(8), interpreter.eval("var"));
+		assertEquals(LispElement.generate(4.8), interpreter.eval("(set! var 4.8)"));
+		assertEquals(LispElement.generate(4.8), interpreter.eval("var"));
+	}
+	
+	@Test(expected = LispError.class)
+	public void testSetOperatorException1() throws LispError {
+		assertEquals(LispElement.generate(4.8), interpreter.eval("(set! var 4.8)"));
+	}
+	
+	@Test(expected = LispError.class)
+	public void testSetOperatorException2() throws LispError {
+		assertEquals(LispElement.generate(4.8), interpreter.eval("(set! * 4.8)"));
+	}
+	
+	@Test(expected = LispError.class)
+	public void testSetOperatorException3() throws LispError {
+		assertEquals(LispElement.generate(4.8), interpreter.eval("(set! #f 4.8)"));
+	}
+	
+	@Test(expected = LispError.class)
+	public void testSetOperatorException4() throws LispError {
+		interpreter.eval("(define var 8)");
+		interpreter.eval("(set! var)");
+	}
+	
+	@Test
+	public void testLambda() throws LispError {
+		assertEquals(LispElement.generate("lambda (var) (+ var 1)"), interpreter.eval("(define plus1 (lambda (var) (+ var 1)))"));
+		assertEquals(LispElement.generate(101), interpreter.eval("(plus1 100)"));
+		assertEquals(LispElement.generate(1), interpreter.eval("(define n 1)"));
+		assertEquals(LispElement.generate("lambda (var) (- var n)"), interpreter.eval("(define moinsn (lambda (var) (- var n)))"));
+		assertEquals(LispElement.generate(99), interpreter.eval("(moinsn 100)"));
+		assertEquals(LispElement.generate("lambda (var) (if (> var 0) (plus1 var) (moinsn var))"), interpreter.eval("(define plusmoins (lambda (var) (if (> var 0) (plus1 var) (moinsn var))))"));
+		assertEquals(LispElement.generate(101), interpreter.eval("(plusmoins 100)"));
+		assertEquals(LispElement.generate(-11), interpreter.eval("(plusmoins -10)"));
+	}
+	
+	@Test(expected = LispError.class)
+	public void testMalformedLambda1() throws LispError {
+		assertEquals(LispElement.generate("lambda var (+ var 1)"), interpreter.eval("(define plus1 (lambda (var)))"));
+		interpreter.eval("(plus1 100)");
+	}
+	
+	@Test(expected = LispError.class)
+	public void testMalformedLambda2() throws LispError {
+		assertEquals(LispElement.generate("lambda var (+ var 1)"), interpreter.eval("(define plus1 (lambda var (+ var 1)))"));
+		interpreter.eval("(plus1 100)");
+	}
+	
+	@Test(expected = LispError.class)
+	public void testLambdaException1() throws LispError {
+		assertEquals(LispElement.generate("lambda (var) (+ var 1)"), interpreter.eval("(define plus1 (lambda (var) (+ var 1)))"));
+		assertEquals(LispElement.generate(101), interpreter.eval("(plus1 100 101)"));
+	}
+	
+	@Test(expected = LispError.class)
+	public void testLambdaException2() throws LispError {
+		assertEquals(LispElement.generate(101), interpreter.eval("(moins1 100)"));
+	}
+	
+	@Test(expected = LispError.class)
+	public void testLambdaException3() throws LispError {
+		LispOperator lo = new DefineOperator();
+		lo.apply(interpreter.getEval(), "nop", null);
+	}
+	
+	@Test(expected = LispError.class)
+	public void testLambdaException4() throws LispError {
+		assertEquals(LispElement.generate("function (param) (* param 2)"), interpreter.eval("(define azerty (function (param) (* param 2)))"));
+		interpreter.eval("(azerty 4)");
+	}
+	
+	@Test
+	public void testIsLambda1() throws LispError {
+		interpreter.eval("(define var 8)");
+		interpreter.eval("(define var2 (+ 2 6))");
+		interpreter.eval("(define func (lambda  (x) (quote x)))");
+		interpreter.eval("(define aaa (function (param) (* param 2)))");
+		ConsList<Object> param = ConsListFactory.singleton("param");
+		ConsList<Object> func = ConsListFactory.asList("*", "param", 2.0);
+		ConsList<Object> lambda = ConsListFactory.asList(8.4, param, func);
+		ConsList<Object> lisp = ConsListFactory.asList("define", "bbb", lambda);
+		interpreter.evaluate(lisp);
+		assertFalse(interpreter.getEval().getDefine().isLambda(new Object()));
+		assertFalse(interpreter.getEval().getDefine().isLambda("var"));
+		assertFalse(interpreter.getEval().getDefine().isLambda("var2"));
+		assertTrue(interpreter.getEval().getDefine().isLambda("func"));
+		assertFalse(interpreter.getEval().getDefine().isLambda("aaa"));
+		assertFalse(interpreter.getEval().getDefine().isLambda("bbb"));
+	}
+	
+	@Test
+	public void testIsLambda2() throws LispError {
+		LispOperator define = new DefineOperator();
+		ConsList<Object> cl = ConsListFactory.asList("nullFunc", null);
+		define.apply(interpreter.getEval(), "define", cl);
+		assertFalse(interpreter.getEval().getDefine().isLambda("nullFunc"));
+	}
+	
+	@Test
+	public void testEval() throws LispError {
+		ConsList<Object> cl = ConsListFactory.nil();
+		cl = cl.prepend(8).prepend("x").prepend("lambda");
+		cl = ConsListFactory.singleton(cl);
+		assertEquals(LispElement.generate("lambda x 8"), interpreter.getEval().getDefine().eval(cl));
+		assertEquals(LispElement.generate("lambda x 8"), interpreter.getEval().getDefine().eval((Object) cl));
+	}
+	
+	@Test(expected = LispError.class)
+	public void testEvalException() throws LispError {
+		interpreter.getEval().getDefine().eval(new Double(4.8));
+	}
+	
+	@Test
+	public void testLCPF() throws LispError {
+		interpreter.eval("(define lcpf (lambda (x y) (lambda (z) (* x (+ y z)))))");
+		assertEquals(LispElement.generate(8), interpreter.eval("((lcpf 2 1) 3)"));
+	}
+	
+	@Test
+	public void testLCPF2() throws LispError {
+		interpreter.eval("(define lcpf2 (lambda (x) (lambda (y) (lambda (z) (* x (+ y z))))))");
+		assertEquals(LispElement.generate(8), interpreter.eval("(((lcpf2 2) 1) 3)"));
+	}
+	
+	@Test
+	public void testGenerateRandomName1() {
+		DefineOperator define = new DefineOperator();
+		String str1 = define.generateRandomName();
+		String str2 = define.generateRandomName();
+		assertEquals(8, str1.length());
+		assertEquals(8, str2.length());
+		assertNotEquals(str1, str2);
+	}
+	
+	@Test
+	public void testGenerateRandomName2() {
+		DefineOperator define = new DefineOperator();
+		for(int i = 0; i < 100; i++) {
+			String str = define.generateRandomName();
+			for(char c : str.toCharArray()) {
+				assertTrue(c >= 'a');
+				assertTrue(c <= 'z');
+			}
+		}
+
+	}
+
+}

+ 65 - 0
test/src/migl/lisp/operator/MathOperatorOwnTest.java

@@ -0,0 +1,65 @@
+package migl.lisp.operator;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import migl.lisp.Lisp;
+import migl.lisp.LispElement;
+import migl.lisp.LispError;
+import migl.lisp.LispEval;
+import migl.lisp.LispFactory;
+import migl.util.ConsList;
+import migl.util.ConsListFactory;
+
+public class MathOperatorOwnTest {
+	
+	private Lisp interpreter;
+
+	@Before
+	public void init() {
+		interpreter = LispFactory.makeIntepreter();
+	}
+	
+	@Test(expected = LispError.class)
+	public void testIncorrectNumberArgumentMathOperator() throws LispError {
+		LispEval le = new LispEval(interpreter, interpreter.parse("(cbrt 8.0 8.0)"));
+		le.evaluate();
+	}
+	
+	@Test
+	public void testMathOperator() throws LispError {
+		assertEquals(LispElement.generate(2.0), interpreter.eval("(cbrt 8)"));
+		assertEquals(LispElement.generate(2.0), interpreter.eval("(cbrt 8.0)"));
+		assertEquals(LispElement.generate(2.0), interpreter.eval("(cbrt (/ 16 2.0))"));
+		assertEquals(LispElement.generate(8.0), interpreter.eval("(ceil 8)"));
+		assertEquals(LispElement.generate(9.0), interpreter.eval("(ceil 8.24)"));
+		assertEquals(LispElement.generate(8.0), interpreter.eval("(floor 8)"));
+		assertEquals(LispElement.generate(8.0), interpreter.eval("(floor 8.24)"));
+		assertEquals(LispElement.generate(2.0), interpreter.eval("(log10 100)"));
+		assertEquals(LispElement.generate(2.0), interpreter.eval("(log10 100.0)"));
+		assertEquals(LispElement.generate(1.0), interpreter.eval("(cos 0)"));
+		assertEquals(LispElement.generate(1.0), interpreter.eval("(cos 0.0)"));
+		assertEquals(LispElement.generate(8.0), interpreter.eval("(rint 8)"));
+		assertEquals(LispElement.generate(8.0), interpreter.eval("(rint 8.49)"));
+		assertEquals(LispElement.generate(9.0), interpreter.eval("(rint 8.51)"));
+		assertEquals(LispElement.generate(8), interpreter.eval("(round 8)"));
+		assertEquals(LispElement.generate(8), interpreter.eval("(round 8.49)"));
+		assertEquals(LispElement.generate(9), interpreter.eval("(round 8.51)"));
+		assertEquals(LispElement.generate(1.0), interpreter.eval("(signum 5.9)"));
+		assertEquals(LispElement.generate(-1.0), interpreter.eval("(signum -5.9)"));
+		assertEquals(LispElement.generate(-1.0), interpreter.eval("(signum (- 5.9))"));
+		assertEquals(LispElement.generate(0.0), interpreter.eval("(signum 0)"));
+		assertEquals(LispElement.generate(0.0), interpreter.eval("(signum 0.0)"));
+	}
+	
+	@Test(expected = LispError.class)
+	public void testMathOperatorException() throws LispError {
+		LispOperator math = new MathOperator();
+		ConsList<Object> cl = ConsListFactory.nil();
+		cl = cl.prepend(4.2);
+		math.apply(new LispEval(interpreter), "_", cl);
+	}
+
+}

+ 79 - 0
test/src/migl/lisp/operator/MinMaxOperatorOwnTest.java

@@ -0,0 +1,79 @@
+package migl.lisp.operator;
+
+import static org.junit.Assert.assertEquals;
+
+import java.math.BigInteger;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import migl.lisp.Lisp;
+import migl.lisp.LispElement;
+import migl.lisp.LispError;
+import migl.lisp.LispEval;
+import migl.lisp.LispFactory;
+import migl.util.ConsList;
+import migl.util.ConsListFactory;
+
+public class MinMaxOperatorOwnTest {
+
+	private Lisp interpreter;
+
+	@Before
+	public void init() {
+		interpreter = LispFactory.makeIntepreter();
+	}
+	
+	@Test
+	public void testMinOperator() throws LispError {
+		//Commentaire gestion uniquement de deux variable car desactivé
+		//assertEquals(LispElement.generate(8), interpreter.eval("(min 8)"));
+		//assertEquals(LispElement.generate(8.4), interpreter.eval("(min 8.4)"));
+		assertEquals(LispElement.generate(5), interpreter.eval("(min 8 5)"));
+		//assertEquals(LispElement.generate(2), interpreter.eval("(min 8 5 4 6 2)"));
+		assertEquals(LispElement.generate(5.0), interpreter.eval("(min 8 5.0)"));
+		//assertEquals(LispElement.generate(4.2), interpreter.eval("(min 8 5.0 8 4.2)"));
+		assertEquals(LispElement.generate(5.0), interpreter.eval("(min 8.0 5.0)"));
+	}
+	
+	@Test(expected = LispError.class)
+	public void testIncorrectNumberArgumentMin() throws LispError {
+		interpreter.eval("(min)");
+	}
+	
+	@Test
+	public void testMaxOperator() throws LispError {
+		//Commentaire gestion de plus de deux variable car desactivé
+		//assertEquals(LispElement.generate(8), interpreter.eval("(max 8)"));
+		//assertEquals(LispElement.generate(8.4), interpreter.eval("(max 8.4)"));
+		assertEquals(LispElement.generate(8), interpreter.eval("(max 8 5)"));
+		//assertEquals(LispElement.generate(8), interpreter.eval("(max 8 5 4 6 2)"));
+		assertEquals(LispElement.generate(8.0), interpreter.eval("(max 8 5.0)"));
+		//assertEquals(LispElement.generate(8.4), interpreter.eval("(max 8.4 5.0 8 4.2)"));
+		assertEquals(LispElement.generate(8.0), interpreter.eval("(max 8.0 5.0)"));
+	}
+	
+	@Test(expected = LispError.class)
+	public void testIncorrectNumberArgumentMax() throws LispError {
+		interpreter.eval("(max)");
+	}
+	
+	@Test(expected = LispError.class)
+	public void testMinMaxOperatorException1() throws LispError {
+		LispOperator comp = new MinMaxOperator();
+		ConsList<Object> cl = ConsListFactory.nil();
+		cl = cl.prepend(new BigInteger("8"));
+		cl = cl.prepend(4.2);
+		comp.apply(new LispEval(interpreter), "_", cl);
+	}
+	
+	@Test(expected = LispError.class)
+	public void testMinMaxOperatorException2() throws LispError {
+		LispOperator minMax = new MinMaxOperator();
+		ConsList<Object> cl = ConsListFactory.nil();
+		cl = cl.prepend(new BigInteger("8"));
+		cl = cl.prepend(new BigInteger("4"));
+		minMax.apply(new LispEval(interpreter), "_", cl);
+	}
+	
+}

+ 93 - 0
test/src/migl/util/ConsListOwnTest.java

@@ -0,0 +1,93 @@
+package migl.util;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.Before;
+import org.junit.Test;
+
+public class ConsListOwnTest {
+	
+	private ConsList<Integer> list;
+
+	@Before
+	public void init() {
+		list = ConsListFactory.nil();
+	}
+	
+	@Test
+	public void testConsListImplEquals() {
+		ConsList<Integer> list2 = ConsListFactory.asList(8, 88);
+		ConsList<Integer> list3 = ConsListFactory.asList(88, 8);
+		list = list.prepend(88).prepend(8);
+		assertTrue(list.equals(list));
+		assertTrue(list.equals(list2));
+		assertFalse(list.equals(list3));
+		assertFalse(list.equals(null));
+		assertTrue(list.equals(ConsListFactory.asList(8, 88)));
+		assertTrue(list.equals(ConsListFactory.singleton(88).prepend(8)));
+		assertFalse(list.equals(ConsListFactory.singleton(88).prepend(888)));
+		assertEquals(list.hashCode(), list2.hashCode());
+		assertNotEquals(list.hashCode(), list3.hashCode());
+	}
+	
+	@Test
+	public void testConsListImplHashCode() {
+		ConsList<Integer> list2 = ConsListFactory.asList(8, 888);
+		ConsList<Integer> list3 = ConsListFactory.asList(88, 8);
+		list = list.prepend(88).prepend(8);
+		Map<ConsList<Integer>, String> map = new HashMap<>();
+		map.put(list, "L1");
+		map.put(list2, "L2");
+		map.put(list3, "L3");
+		assertEquals("L1", map.get(list));
+		assertEquals("L2", map.get(list2));
+		assertEquals("L3", map.get(list3));
+	}
+
+	@Test
+	public void testAsListEmpty() {
+		ConsList<Integer> list2 = ConsListFactory.asList();
+		assertEquals(list, list2);
+	}
+	
+	@Test
+	public void testAsListSingleton() {
+		ConsList<Integer> list1 = ConsListFactory.singleton(8);
+		ConsList<Integer> list2 = ConsListFactory.asList(8);
+		assertEquals(list1, list2);
+	}
+	
+	@Test
+	public void testConsEmptyListMap() {
+		ConsList<String> list2 = ConsListFactory.nil();
+		assertEquals(list2, list.map(p -> Integer.valueOf(p)));
+	}
+	
+	@Test
+	public void testIsEmpty() {
+		assertTrue(list.isEmpty());
+		assertEquals(list.size(), 0);
+		list = list.prepend(8);
+		assertFalse(list.isEmpty());
+		assertNotEquals(list.size(), 0);
+	}
+	
+	@Test(expected = IllegalArgumentException.class)
+    public void testCreateEmptyConsListImpl() {
+        list = new ConsListImpl<Integer>(null, null);
+    }
+	
+	@Test
+	public void testListWithNull() {
+		list = list.prepend(null);
+		assertEquals(1, list.size());
+		assertEquals("(null)", list.toString());
+	}
+	
+}

+ 108 - 0
test/src/migl/util/ConsListTest.java

@@ -0,0 +1,108 @@
+package migl.util;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Before;
+import org.junit.Test;
+
+public class ConsListTest {
+
+	private ConsList<Integer> list;
+
+	@Before
+	public void init() {
+		list = ConsListFactory.nil();
+	}
+
+	@Test
+	public void testListIsEmptyByDefault() {
+		assertTrue(list.isEmpty());
+		assertEquals(0, list.size());
+	}
+
+	@Test
+	public void testPrepend() {
+		assertEquals(0, list.size());
+		list = list.prepend(1);
+		assertEquals(1, list.size());
+		assertEquals(1, list.car().intValue());
+		list = list.prepend(2);
+		assertEquals(2, list.size());
+		assertEquals(2, list.car().intValue());
+		list = list.prepend(3);
+		assertEquals(3, list.size());
+		assertEquals(3, list.car().intValue());
+	}
+
+	@Test
+	public void testPrependSharesSublist() {
+		ConsList<Integer> list2 = list.prepend(2);
+		assertEquals(list, list2.cdr());
+		assertSame(list, list2.cdr());
+		ConsList<Integer> list3 = list2.prepend(1);
+		assertEquals(list2, list3.cdr());
+		assertSame(list2, list3.cdr());
+	}
+
+	@Test
+	public void testAppend() {
+		assertEquals(0, list.size());
+		list = list.append(1);
+		assertEquals(1, list.size());
+		assertEquals(1, list.car().intValue());
+		list = list.append(2);
+		assertEquals(2, list.size());
+		assertEquals(1, list.car().intValue());
+		assertEquals(2, list.cdr().car().intValue());
+		list = list.append(3);
+		assertEquals(3, list.size());
+		assertEquals(1, list.car().intValue());
+		assertEquals(2, list.cdr().car().intValue());
+		assertEquals(3, list.cdr().cdr().car().intValue());
+	}
+
+	@Test
+	public void testAppendDoesNoShareSublist() {
+		ConsList<Integer> list2 = list.append(1);
+		assertEquals(list, list2.cdr());
+		ConsList<Integer> list3 = list2.append(2);
+		assertEquals(list2.car(), list3.car());
+		assertNotSame(list2, list3.cdr());
+	}
+
+	@Test
+	public void testToStringEmpty() {
+		assertEquals("()", list.toString());
+	}
+
+	@Test
+	public void testToStringSingleton() {
+		list = list.prepend(1);
+		assertEquals("(1)", list.toString());
+	}
+
+	@Test
+	public void testToStringTwoElements() {
+		list = list.prepend(2);
+		list = list.prepend(1);
+		assertEquals("(1 2)", list.toString());
+	}
+
+	@Test
+	public void testEqualsToArray() {
+		list = list.prepend(3).prepend(2).prepend(1);
+		Object[] liste = { 1, 2, 3 };
+		assertArrayEquals(liste, list.toArray());
+
+	}
+
+	@Test
+	public void testEqualsReduce() {
+		list = list.prepend(3).prepend(2).prepend(1);
+		assertEquals(6, list.reduce(0, Integer::sum).intValue());
+	}
+}

+ 16 - 0
test/src/migl/util/ConsOwnTest.java

@@ -0,0 +1,16 @@
+package migl.util;
+
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+
+public class ConsOwnTest {
+
+	@Test
+	public void testEquals() {
+		Cons<String, String> c1 = new Cons<>(null, "str");
+		Cons<String, String> c2 = new Cons<>("not null", "str");
+		assertFalse(c1.equals(c2));
+	}
+
+}

+ 94 - 0
test/src/migl/util/ConsTest.java

@@ -0,0 +1,94 @@
+package migl.util;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.Test;
+
+public class ConsTest {
+
+    @Test
+    public void testNilCons() {
+        Cons<String, String> c1 = Cons.nil();
+        assertNull(c1.left());
+        assertNull(c1.right());
+        assertEquals("(null . null)", c1.toString());
+    }
+
+    @Test
+    public void testSimpleCons() {
+        Cons<String, String> c1 = new Cons<>("a", "b");
+        assertEquals("(a . b)", c1.toString());
+        assertEquals("a", c1.left());
+        assertEquals("b", c1.right());
+    }
+
+    @Test
+    public void testNestedCons() {
+        Cons<String, Cons<String, String>> c1 = new Cons<>("a", new Cons<>("b", "c"));
+        assertEquals("(a . (b . c))", c1.toString());
+    }
+
+    @Test
+    public void testEquals() {
+        Cons<String, String> c1 = new Cons<>("a", "b");
+        Cons<String, String> c2 = new Cons<>("a", "b");
+        Cons<String, String> c3 = new Cons<>("a", "c");
+        Cons<String, String> c4 = new Cons<>("c", "b");
+        Cons<String, String> c5 = new Cons<>("c", "d");
+        assertEquals(c1, c2);
+        assertNotEquals(c1, null);
+        assertNotEquals(c1, true);
+        assertNotEquals(null, c2);
+        assertNotEquals(true, c2);
+        assertNotEquals(c1, c3);
+        assertNotEquals(c1, c4);
+        assertNotEquals(c1, c5);
+    }
+
+    @Test
+    public void testConsEquals() {
+        Cons<String, String> c1 = new Cons<>("a", "b");
+        Cons<String, String> c2 = new Cons<>("a", null);
+        Cons<String, String> c3 = new Cons<>("a", "c");
+        Cons<String, String> c4 = new Cons<>("a", "a");
+        Cons<String, String> c5 = new Cons<>(null, "a");
+        Cons<String, String> c6 = new Cons<>("a", "c");
+        Cons<String, String> c7 = new Cons<>("a", null);
+
+        assertTrue(c1.equals(c1));
+        assertFalse(c2.equals(c3));
+        assertFalse(c2.equals(new Cons<>("b", null)));
+        assertTrue(c3.equals(c6));
+        assertFalse(c4.equals(c5));
+        assertFalse(c5.equals(c6));
+        assertTrue(c2.equals(c7));
+        assertFalse(c5.equals(new Cons<>(null, "b")));
+        assertEquals(c1.hashCode(), c1.hashCode());
+        assertEquals(c3.hashCode(), c6.hashCode());
+        assertEquals(c2.hashCode(), c7.hashCode());
+    }
+
+    @Test
+    public void testConsHashCode() {
+        Cons<String, String> c1 = new Cons<>("a", "b");
+        Cons<String, String> c2 = new Cons<>("a", null);
+        Cons<String, String> c3 = new Cons<>(null, "a");
+        Cons<String, String> c4 = new Cons<>(null, null);
+        Map<Cons<String, String>, String> map = new HashMap<>();
+        map.put(c1, "C1");
+        map.put(c2, "C2");
+        map.put(c3, "C3");
+        map.put(c4, "C4");
+        assertEquals("C1", map.get(c1));
+        assertEquals("C2", map.get(c2));
+        assertEquals("C3", map.get(c3));
+        assertEquals("C4", map.get(c4));
+    }
+}

+ 156 - 0
test/src/migl/util/MoreConsListTest.java

@@ -0,0 +1,156 @@
+package migl.util;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+import org.junit.Before;
+import org.junit.Test;
+
+public class MoreConsListTest {
+
+    private ConsList<Integer> list;
+
+    @Before
+    public void init() {
+        list = ConsListFactory.nil();
+    }
+
+    @Test(timeout = 20000)
+    public void testPrepend() {
+        for (int i = 0; i < 10000; i++) {
+            list = list.prepend(i);
+        }
+        assertEquals(10000, list.size());
+        ConsList<Integer> list2 = list.prepend(666);
+        assertSame(list, list2.cdr());
+    }
+
+    @Test(timeout = 20000)
+    public void testEqualsEfficiency() {
+        for (int i = 0; i <= 10000; i++) {
+            list = list.prepend(i);
+        }
+        ConsList<Integer> list2 = list.prepend(666);
+        assertEquals(list, list2.cdr());
+    }
+
+    @Test
+    public void testIteratorOnEmptyList() {
+        for (Integer i : list) {
+            fail("there should be no element " + i + " in the list!!!");
+        }
+    }
+
+    @Test(expected = NoSuchElementException.class)
+    public void testIteratorNextOnEmptyList() {
+        list.iterator().next();
+    }
+
+    @Test(expected = NoSuchElementException.class)
+    public void testIteratorWithNonEmptyList() {
+        list = list.prepend(4).prepend(3).prepend(2).prepend(1);
+        Iterator<Integer> it = list.iterator();
+        assertTrue(it.hasNext());
+        assertEquals(1, it.next().intValue());
+        assertTrue(it.hasNext());
+        assertEquals(2, it.next().intValue());
+        assertTrue(it.hasNext());
+        assertEquals(3, it.next().intValue());
+        assertTrue(it.hasNext());
+        assertEquals(4, it.next().intValue());
+        assertFalse(it.hasNext());
+        it.next();
+    }
+
+    @Test
+    public void testSingletonFactory() {
+        ConsList<Integer> list2 = ConsListFactory.singleton(5);
+        assertEquals(1, list2.size());
+        assertEquals(5, list2.car().intValue());
+    }
+
+    @Test
+    public void testListFromVarargs() {
+        ConsList<Integer> list2 = ConsListFactory.asList(6, 66, 666);
+        assertEquals(3, list2.size());
+        Iterator<Integer> it = list2.iterator();
+        assertTrue(it.hasNext());
+        assertEquals(6, it.next().intValue());
+        assertTrue(it.hasNext());
+        assertEquals(66, it.next().intValue());
+        assertTrue(it.hasNext());
+        assertEquals(666, it.next().intValue());
+        assertFalse(it.hasNext());
+    }
+
+    @Test
+    public void testMap() {
+        ConsList<Integer> list2 = ConsListFactory.asList(6, 66, 666);
+        ConsList<String> list3 = ConsListFactory.asList("6", "66", "666");
+        assertEquals(list2, list3.map(Integer::valueOf));
+        assertEquals(list3, list2.map((i) -> Integer.toString(i)));
+    }
+
+    @Test
+    public void testAdditionalToString() {
+        list = list.prepend(10).prepend(9).prepend(8);
+        assertEquals("(8 9 10)", list.toString());
+        ConsList<Object> olist = ConsListFactory.nil();
+        olist = olist.prepend("Truc").prepend(list).prepend(45);
+        assertEquals("(45 (8 9 10) Truc)", olist.toString());
+    }
+
+    @Test
+    public void testAllowNullInList() {
+        ConsList<Object> olist = ConsListFactory.nil();
+        olist = olist.prepend("Truc").prepend(null).prepend(45);
+        assertEquals("(45 null Truc)", olist.toString());
+    }
+
+    @Test
+    public void testEqualsWithNull() {
+        assertNotEquals(list, null);
+    }
+
+    @Test
+    public void testEqualsWithDifferentLists() {
+        list = list.prepend(10).prepend(9).prepend(8);
+        ConsList<Integer> list2 = ConsListFactory.nil();
+        list2 = list2.prepend(8).prepend(9).prepend(10);
+        assertNotEquals(list, list2);
+    }
+
+    @Test
+    public void testEqualsWithEqualLists() {
+        list = list.prepend(10).prepend(9).prepend(8);
+        ConsList<Integer> list2 = ConsListFactory.nil();
+        list2 = list2.prepend(10).prepend(9).prepend(8);
+        assertEquals(list, list2);
+    }
+
+    @Test
+    public void testEqualsWithDifferentTypes() {
+        list = list.prepend(10).prepend(9).prepend(8);
+        ConsList<String> list2 = ConsListFactory.nil();
+        list2 = list2.prepend("10").prepend("9").prepend("8");
+        assertNotEquals(list, list2);
+    }
+
+    @Test(expected = NoSuchElementException.class)
+    public void testCarOnEmptyList() {
+        list.car();
+    }
+
+    @Test
+    public void testCdrOnEmptyList() {
+        assertEquals(ConsListFactory.nil(), list.cdr());
+    }
+
+}