Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions koans/app/config/PathToEnlightenment.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
<packages>
<package pkg="beginner" name="Novice">
<suite class="AboutKoans">
<koan name="findAboutKoansFile" displayIncompleteKoanException="false" />
<koan name="definitionOfKoanCompletion" displayIncompleteKoanException="false" />
<koan name="findAboutKoansFile" displayIncompleteKoanException="false" requireAssertion="false" />
<koan name="definitionOfKoanCompletion" displayIncompleteKoanException="false" requireAssertion="false" />
</suite>
<suite class="AboutAssertions"/>
<suite class="AboutEquality"/>
Expand Down
6 changes: 3 additions & 3 deletions koans/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
<parent>
<groupId>io.github.davidwhitlock.joy.com.sandwich</groupId>
<artifactId>koans-parent</artifactId>
<version>1.2.4-SNAPSHOT</version>
<version>1.3.0-SNAPSHOT</version>
</parent>
<artifactId>java-koans</artifactId>
<packaging>jar</packaging>
<version>1.2.4-SNAPSHOT</version>
<version>1.3.0-SNAPSHOT</version>
<name>Java Koans</name>
<inceptionYear>2012</inceptionYear>
<description>Java Koans to learn the Java language and APIs</description>
Expand Down Expand Up @@ -64,7 +64,7 @@
<dependency>
<groupId>io.github.davidwhitlock.joy.com.sandwich</groupId>
<artifactId>koans-lib</artifactId>
<version>1.2.3</version>
<version>1.3.0-SNAPSHOT</version>
</dependency>
</dependencies>
<properties>
Expand Down
3 changes: 2 additions & 1 deletion koans/src/advanced/AboutMocks.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.sandwich.koan.Koan;

import static com.sandwich.util.Assert.assertTrue;
import static com.sandwich.util.Assert.fail;

public class AboutMocks {
Expand Down Expand Up @@ -40,7 +41,7 @@ public void simpleAnonymousMock() {
// HINT: pass a safe Collaborator implementation to constructor
// new ClassUnderTest(new Collaborator(){... it should not be the
// objective of this test to test that collaborator, so replace it
new ClassUnderTest().doSomething();
assertTrue(new ClassUnderTest().doSomething());
}

}
1 change: 1 addition & 0 deletions koans/src/beginner/AboutArrays.java
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ public void arrayIndexOutOfBounds() {
int[] array = new int[]{1};
@SuppressWarnings("unused")
int meh = array[1]; // remember 0 based indexes, 1 is the 2nd element (which doesn't exist)
assertEquals(meh, __);
}

@Koan
Expand Down
2 changes: 2 additions & 0 deletions koans/src/beginner/AboutExceptions.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

import static com.sandwich.koan.constant.KoanConstants.__;
import static com.sandwich.util.Assert.assertEquals;
import static com.sandwich.util.Assert.assertTrue;

public class AboutExceptions {

Expand Down Expand Up @@ -103,6 +104,7 @@ private void doUncheckedStuff() {
public void catchUncheckedExceptions() {
// What do you need to do to catch the unchecked exception?
doUncheckedStuff();
assertTrue(true);
}

@SuppressWarnings("serial")
Expand Down
4 changes: 2 additions & 2 deletions lib/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
<parent>
<groupId>io.github.davidwhitlock.joy.com.sandwich</groupId>
<artifactId>koans-parent</artifactId>
<version>1.2.4-SNAPSHOT</version>
<version>1.3.0-SNAPSHOT</version>
</parent>
<artifactId>koans-lib</artifactId>
<packaging>jar</packaging>
<version>1.2.4-SNAPSHOT</version>
<version>1.3.0-SNAPSHOT</version>
<name>Java Koans Framework</name>
<description>Supporting library code for running Java Koans</description>
<url>https://github.com/DavidWhitlock/java-koans</url>
Expand Down
24 changes: 19 additions & 5 deletions lib/src/main/java/com/sandwich/koan/KoanMethod.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ public class KoanMethod {
private final transient Method method;
private final String lesson;
private final boolean displayIncompleteException;
private final boolean requiresAssertion;
private static final KoanSuiteCompilationListener listener = new KoanSuiteCompilationListener();

private KoanMethod(KoanElementAttributes koanAttributes) throws SecurityException, NoSuchMethodException{
Expand All @@ -26,27 +27,33 @@ public static KoanMethod getInstance(KoanElementAttributes koanAttributes){
}

public static KoanMethod getInstance(Method method){
return new KoanMethod(null, method, true);
return new KoanMethod(null, method, true, true);
}

public static KoanMethod getInstance(Method method, boolean requiresAssertion){
return new KoanMethod(null, method, true, requiresAssertion);
}

public static KoanMethod getInstance(String lesson, Method method){
return new KoanMethod(lesson, method, true);
return new KoanMethod(lesson, method, true, true);
}

private KoanMethod(String lesson, Method method, boolean displayIncompleteException){
private KoanMethod(String lesson, Method method, boolean displayIncompleteException, boolean requiresAssertion){
if(method == null){
throw new IllegalArgumentException("method may not be null");
}
this.method = method;
this.lesson = new RbVariableInjector(lesson, method).injectLessonVariables();
this.displayIncompleteException = displayIncompleteException;
this.requiresAssertion = requiresAssertion;
}

public KoanMethod(String lesson, KoanElementAttributes koanAttributes) throws SecurityException, NoSuchMethodException {
this( lesson,
KoanClassLoader.getInstance().loadClass(koanAttributes.className, listener)
.getMethod(koanAttributes.name),
!"false".equalsIgnoreCase(koanAttributes.displayIncompleteKoanException));
!"false".equalsIgnoreCase(koanAttributes.displayIncompleteKoanException),
!"false".equalsIgnoreCase(koanAttributes.requireAssertion));
}

public String getLesson() {
Expand All @@ -60,9 +67,13 @@ public Method getMethod() {
public boolean displayIncompleteException() {
return displayIncompleteException;
}

public boolean requiresAssertion() {
return requiresAssertion;
}

public KoanMethod clone(Method method){
return new KoanMethod(lesson, method, displayIncompleteException);
return new KoanMethod(lesson, method, displayIncompleteException, requiresAssertion);
}

@Override public String toString(){
Expand All @@ -75,6 +86,7 @@ public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (displayIncompleteException ? 1231 : 1237);
result = prime * result + (requiresAssertion ? 1231 : 1237);
result = prime * result + ((lesson == null) ? 0 : lesson.hashCode());
return result;
}
Expand All @@ -90,6 +102,8 @@ public boolean equals(Object obj) {
KoanMethod other = (KoanMethod) obj;
if (displayIncompleteException != other.displayIncompleteException)
return false;
if (requiresAssertion != other.requiresAssertion)
return false;
if (lesson == null) {
if (other.lesson != null)
return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@

public class KoanElementAttributes{

public String name, displayIncompleteKoanException, className;
public String name, displayIncompleteKoanException, requireAssertion, className;

public KoanElementAttributes(String name, String displayIncompleteKoanException, String className){
public KoanElementAttributes(String name, String displayIncompleteKoanException, String requireAssertion, String className){
this.name = name;
this.displayIncompleteKoanException = displayIncompleteKoanException;
this.requireAssertion = requireAssertion;
this.className = className;
}

Expand All @@ -21,6 +22,8 @@ public int hashCode() {
* result
+ ((displayIncompleteKoanException == null) ? 0
: displayIncompleteKoanException.hashCode());
result = prime * result
+ ((requireAssertion == null) ? 0 : requireAssertion.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
Expand All @@ -45,6 +48,11 @@ public boolean equals(Object obj) {
} else if (!displayIncompleteKoanException
.equals(other.displayIncompleteKoanException))
return false;
if (requireAssertion == null) {
if (other.requireAssertion != null)
return false;
} else if (!requireAssertion.equals(other.requireAssertion))
return false;
if (name == null) {
if (other.name != null)
return false;
Expand All @@ -57,7 +65,8 @@ public boolean equals(Object obj) {
public String toString() {
return "KoanElementAttributes [name=" + name
+ ", displayIncompleteKoanException="
+ displayIncompleteKoanException + ", className=" + className
+ displayIncompleteKoanException + ", requireAssertion="
+ requireAssertion + ", className=" + className
+ "]";
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,11 +95,14 @@ Map<String, KoanElementAttributes> extractKoansAndRawLessons(
.getNamedItem("displayIncompleteKoanException");
String displayIncompleteKoanException = displayKoanIncompleteExceptionNode == null ? null
: displayKoanIncompleteExceptionNode.getNodeValue();
Node requireAssertionNode = attributes.getNamedItem("requireAssertion");
String requireAssertion = requireAssertionNode == null ? null
: requireAssertionNode.getNodeValue();
if (rawKoanAttributesByMethodName.containsKey(name)) {
throw new DuplicateKoanException(className, name);
}
rawKoanAttributesByMethodName.put(name, new KoanElementAttributes(
name, displayIncompleteKoanException, className));
name, displayIncompleteKoanException, requireAssertion, className));
}
}
return rawKoanAttributesByMethodName;
Expand All @@ -113,4 +116,3 @@ public DuplicateKoanException(String className, String name){
}

}

Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import com.sandwich.koan.constant.KoanConstants;
import com.sandwich.koan.result.KoanMethodResult;
import com.sandwich.util.ExceptionUtils;
import com.sandwich.util.Assert;
import com.sandwich.util.Strings;
import com.sandwich.util.io.directories.DirectoryManager;
import com.sandwich.util.io.filecompiler.CompilerConfig;
Expand All @@ -23,12 +24,17 @@
public class KoanMethodRunner {

private static final String EXPECTED_PROPERTY_KEY = "expected";
private static final String NO_ASSERTION_MESSAGE = "No assertion was invoked in this koan.";

public static KoanMethodResult run(Object suite, KoanMethod koan){
Assert.resetAssertionTracking();
try {
Method method = koan.getMethod();
method.setAccessible(true);
method.invoke(suite);
if(koan.requiresAssertion() && !Assert.wasAssertionInvoked()){
return new KoanMethodResult(koan, NO_ASSERTION_MESSAGE, null);
}
} catch (Throwable t) {
Throwable tempException = t;
String message = ExceptionUtils.convertToPopulatedStackTraceString(t);
Expand All @@ -44,6 +50,8 @@ public static KoanMethodResult run(Object suite, KoanMethod koan){
tempException = tempException.getCause();
}
return new KoanMethodResult(koan, message, getOriginalLineNumber(t, suite.getClass()));
} finally {
Assert.resetAssertionTracking();
}
return KoanMethodResult.PASSED;
}
Expand Down Expand Up @@ -84,4 +92,4 @@ static String getOriginalLineNumber(Throwable t, Class<?> failingSuite){
return null;
}

}
}
21 changes: 21 additions & 0 deletions lib/src/main/java/com/sandwich/util/Assert.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,22 @@ public class Assert {
static final String EXPECTED = "expected:<";
static final String END = ">";
static final String BUT_WAS = "> but was:<";
private static final ThreadLocal<Integer> ASSERTION_COUNT = ThreadLocal.withInitial(() -> 0);

public static void resetAssertionTracking() {
ASSERTION_COUNT.set(0);
}

public static boolean wasAssertionInvoked() {
return ASSERTION_COUNT.get() > 0;
}

private static void assertionInvoked() {
ASSERTION_COUNT.set(ASSERTION_COUNT.get() + 1);
}

public static void assertEquals(String msg, Object o0, Object o1){
assertionInvoked();
if(o0 == null && o1 != null){
fail(msg, o0, o1);
}
Expand All @@ -34,30 +48,36 @@ public static void assertEquals(Object o0, Object o1){
}

public static void assertTrue(Object t){
assertionInvoked();
assertEquals(true,t);
}

public static void assertFalse(Object f){
assertionInvoked();
assertEquals(false,f);
}

public static void assertNull(Object o){
assertionInvoked();
assertEquals(null, o);
}

public static void assertNotNull(Object o){
assertionInvoked();
if(o == null){
fail("something other than null",o);
}
}

public static void assertSame(Object o0, Object o1){
assertionInvoked();
if(o0 != o1){
fail("Are the same instance... ",o0,o1);
}
}

public static void assertNotSame(Object o0, Object o1){
assertionInvoked();
if(o0 == o1){
fail("Not the same instance... ",o0,o1);
}
Expand Down Expand Up @@ -92,6 +112,7 @@ private static boolean wasNotAttempted(Object actual) {
}

public static void fail(String msg){
assertionInvoked();
throw new KoanIncompleteException(msg);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ protected Path stubAllKoans(String packageName, List<String> path){
KoanSuiteCompilationListener listener = new KoanSuiteCompilationListener();
for(Method m : loader.loadClass(suite, listener).getMethods()){
if(m.getAnnotation(Koan.class) != null){
methodsByName.put(m.getName(), new KoanElementAttributes(m.getName(), "", m.getDeclaringClass().getName()));
methodsByName.put(m.getName(), new KoanElementAttributes(m.getName(), "", "", m.getDeclaringClass().getName()));
}
}
tempSuitesAndMethods.put(suite, methodsByName);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.sandwich.koan.path.xmltransformation;

import static org.junit.Assert.assertEquals;

import java.io.ByteArrayInputStream;

import javax.xml.parsers.DocumentBuilderFactory;

import org.junit.Test;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;

public class XmlToPathTransformerImplTest {

@Test
public void extractKoansReadsRequireAssertionAttribute() throws Exception {
Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder()
.parse(new ByteArrayInputStream((
"<suite class=\"AboutKoans\">"
+ "<koan name=\"findAboutKoansFile\" displayIncompleteKoanException=\"false\" requireAssertion=\"false\" />"
+ "</suite>").getBytes("UTF-8")));
NodeList nodes = document.getDocumentElement().getChildNodes();
KoanElementAttributes koan = new XmlToPathTransformerImpl()
.extractKoansAndRawLessons("beginner.AboutKoans", nodes)
.get("findAboutKoansFile");

assertEquals("false", koan.displayIncompleteKoanException);
assertEquals("false", koan.requireAssertion);
}
}
Loading
Loading