From a14638c2022fa00f7aba734735833b49f69f2d76 Mon Sep 17 00:00:00 2001 From: godfreyduke Date: Mon, 31 Oct 2016 16:35:15 -0700 Subject: [PATCH 01/30] Add coverage for Java 8's Base64 utility class. --- koans/app/config/PathToEnlightenment.xml | 1 + koans/src/java8/AboutBase64.java | 40 ++++++++++++++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 koans/src/java8/AboutBase64.java diff --git a/koans/app/config/PathToEnlightenment.xml b/koans/app/config/PathToEnlightenment.xml index 5aa2e209..dd104446 100755 --- a/koans/app/config/PathToEnlightenment.xml +++ b/koans/app/config/PathToEnlightenment.xml @@ -52,5 +52,6 @@ + diff --git a/koans/src/java8/AboutBase64.java b/koans/src/java8/AboutBase64.java new file mode 100644 index 00000000..ed1235e8 --- /dev/null +++ b/koans/src/java8/AboutBase64.java @@ -0,0 +1,40 @@ +package java8; + +import com.sandwich.koan.Koan; + +import java.util.Base64; +import java.io.UnsupportedEncodingException; + +import static com.sandwich.koan.constant.KoanConstants.__; +import static com.sandwich.util.Assert.assertEquals; + +public class AboutBase64 { + + private final String plainText = "lorem ipsum"; + private final String encodedText = "bG9yZW0gaXBzdW0="; + + @Koan + public void base64Encoding() { + try { + // Encode the plainText + // This uses the basic Base64 encoding scheme but there are corresponding + // getMimeEncoder and getUrlEncoder methods available if you require a + // different format/Base64 Alphabet + assertEquals(encodedText, Base64.getEncoder().encodeToString(__.getBytes("utf-8"))); + } catch (UnsupportedEncodingException ex) {} + } + + @Koan + public void base64Decoding() { + // Decode the Base64 encodedText + // This uses the basic Base64 decoding scheme but there are corresponding + // getMimeDecoder and getUrlDecoder methods available if you require a + // different format/Base64 Alphabet + byte[] decodedBytes = Base64.getDecoder().decode(__); + try { + String decodedText = new String(decodedBytes, "utf-8"); + assertEquals(plainText, decodedText); + } catch (UnsupportedEncodingException ex) {} + } + +} From 26b18911b679a28505212350bbd25c4c81214c41 Mon Sep 17 00:00:00 2001 From: gherson Date: Sun, 23 Apr 2017 22:08:57 -0400 Subject: [PATCH 02/30] space enabling filespecs Switches CLASSPATH's backslashes to slashes to allow spaces in file and folder paths --- koans/run.bat | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/koans/run.bat b/koans/run.bat index 1cf878ea..895e7179 100755 --- a/koans/run.bat +++ b/koans/run.bat @@ -1,16 +1,20 @@ -@echo off -cls +rem @echo off +rem cls setLocal EnableDelayedExpansion -set CLASSPATH="%~dp0app\bin;"%~dp0\app\config" -for /R "%~dp0\app\lib" %%a in (*.jar) do ( - set CLASSPATH=!CLASSPATH!;%%a +set string=%~dp0 +set string=%string:\=/% +set CLASSPATH="%string%app/bin";"%string%app/config" +for /R "%~dp0/app/lib" %%a in (*.jar) do ( + set string=%%a + set string=!string:\=/! + set CLASSPATH=!CLASSPATH!;"!string!" ) -set CLASSPATH=!CLASSPATH!;" +set CLASSPATH=!CLASSPATH!; javac -version if ERRORLEVEL 3 goto no_javac java -version if ERRORLEVEL 1 goto no_java -cls +rem cls java -Dapplication.basedir="%~dp0"" -classpath %CLASSPATH% com.sandwich.koan.runner.AppLauncher %1 %2 %3 %4 %5 %6 %7 %8 %9 goto end From 6f6371ebcfa0e1001c5ad0c6785ade171155f445 Mon Sep 17 00:00:00 2001 From: gherson Date: Sun, 23 Apr 2017 22:27:49 -0400 Subject: [PATCH 03/30] Re-enabling commented out lines --- koans/run.bat | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/koans/run.bat b/koans/run.bat index 895e7179..bd54d6c2 100755 --- a/koans/run.bat +++ b/koans/run.bat @@ -1,5 +1,5 @@ -rem @echo off -rem cls +@echo off +cls setLocal EnableDelayedExpansion set string=%~dp0 set string=%string:\=/% @@ -14,18 +14,18 @@ javac -version if ERRORLEVEL 3 goto no_javac java -version if ERRORLEVEL 1 goto no_java -rem cls +cls java -Dapplication.basedir="%~dp0"" -classpath %CLASSPATH% com.sandwich.koan.runner.AppLauncher %1 %2 %3 %4 %5 %6 %7 %8 %9 goto end :no_java -REM cls +cls @echo java is not bound to PATH variable. goto end :no_javac -REM cls +cls @echo javac is not bound to PATH variable. goto end From 95cb62169a492be7148018ef90a05aeb98364f8a Mon Sep 17 00:00:00 2001 From: Jason Desrosiers Date: Wed, 24 May 2017 15:42:39 -0700 Subject: [PATCH 04/30] Fix problem with ordering of Koans in AboutLambdas There are two Koans that jump to the front of the line and don't get executed in order like the rest. The problem seems to be in the way they are named. My best guess is that Java reflection is ordering them first because a member variable with the same name comes above it. However, adding characters to the end of the name doesn't fix the problem, you have the change something else. It's possible that this is a problem with Java reflection and there isn't anything else that can be done, but I suspect there might be a bug in the Koans library that could explain the odd behavior. Fixing that could help avoid similar issues elsewhere. --- koans/src/java8/AboutLambdas.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/koans/src/java8/AboutLambdas.java b/koans/src/java8/AboutLambdas.java index 2b1c436a..8cab569b 100644 --- a/koans/src/java8/AboutLambdas.java +++ b/koans/src/java8/AboutLambdas.java @@ -23,9 +23,9 @@ public String toString() { static String str = ""; //lambda has access to "this" - Caps lambdaField = s -> this.toString(); + Caps thisLambdaField = s -> this.toString(); //lambda has access to object methods - Caps lambdaField2 = s -> toString(); + Caps toStringLambdaField = s -> toString(); @Koan public void verySimpleLambda() throws InterruptedException { @@ -55,12 +55,12 @@ public void simpleSuccinctLambda() { @Koan public void lambdaField() { - assertEquals(lambdaField.capitalize(""), __); + assertEquals(thisLambdaField.capitalize(""), __); } @Koan public void lambdaField2() { - assertEquals(lambdaField2.capitalize(""), __); + assertEquals(toStringLambdaField.capitalize(""), __); } @Koan From 0674e681714399457d475605b1e8f4e9d0b168dd Mon Sep 17 00:00:00 2001 From: mat bentley Date: Thu, 25 May 2017 22:36:21 -0400 Subject: [PATCH 05/30] properly replacing hack in koan method sorting --- .../com/sandwich/util/KoanComparator.java | 35 +++++++++---------- .../com/sandwich/util/KoanComparatorTest.java | 24 +++++++++++-- 2 files changed, 39 insertions(+), 20 deletions(-) diff --git a/lib/src/main/java/com/sandwich/util/KoanComparator.java b/lib/src/main/java/com/sandwich/util/KoanComparator.java index c7b02423..b41499ad 100755 --- a/lib/src/main/java/com/sandwich/util/KoanComparator.java +++ b/lib/src/main/java/com/sandwich/util/KoanComparator.java @@ -1,29 +1,15 @@ package com.sandwich.util; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; import java.util.Comparator; -import java.util.HashSet; -import java.util.List; -import java.util.Set; import java.util.logging.Logger; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import com.sandwich.koan.KoanMethod; import com.sandwich.util.io.directories.DirectoryManager; import com.sandwich.util.io.filecompiler.FileCompiler; public class KoanComparator implements Comparator { - List orderedKeywords; - Set methodNamesCompared = new HashSet(); - - public KoanComparator(String...koans){ - this(Arrays.asList(koans)); - } - - public KoanComparator(Collection koans){ - this.orderedKeywords = new ArrayList(koans); - } public int compare(KoanMethod arg0, KoanMethod arg1) { Class declaringClass0 = arg0.getMethod().getDeclaringClass(); @@ -33,9 +19,22 @@ public int compare(KoanMethod arg0, KoanMethod arg1) { return 0; } String contentsOfOriginalJavaFile = FileCompiler.getContentsOfJavaFile(DirectoryManager.getSourceDir(), declaringClass0.getName()); - Integer index0 = Integer.valueOf( contentsOfOriginalJavaFile.indexOf(arg0.getMethod().getName())); - Integer index1 = Integer.valueOf( contentsOfOriginalJavaFile.indexOf(arg1.getMethod().getName())); + String pattern = ".*\\s%s(\\(|\\s*\\))"; + Integer index0 = indexOfMatch(contentsOfOriginalJavaFile, String.format(pattern, arg0.getMethod().getName())); + Integer index1 = indexOfMatch(contentsOfOriginalJavaFile, String.format(pattern, arg1.getMethod().getName())); return index0.compareTo(index1); } + + /* + * TODO: This is utility code... + */ + private int indexOfMatch(String inputString, String pattern) { + Pattern p = Pattern.compile(pattern); + Matcher m = p.matcher(inputString); + if (m.find()) { + return m.start(); + } + return -1; + } } \ No newline at end of file diff --git a/lib/src/test/java/com/sandwich/util/KoanComparatorTest.java b/lib/src/test/java/com/sandwich/util/KoanComparatorTest.java index ef16fb86..1e17c875 100755 --- a/lib/src/test/java/com/sandwich/util/KoanComparatorTest.java +++ b/lib/src/test/java/com/sandwich/util/KoanComparatorTest.java @@ -15,12 +15,16 @@ public class KoanComparatorTest extends CommandLineTestCase { + interface Caps { + public String capitalize(String name); + } + @Test public void testThatKomparatorBombsWhenNotFound() throws Exception { Method m = new Object(){ @Koan public void someMethod(){} }.getClass().getDeclaredMethod("someMethod"); - KoanComparator comparator = new KoanComparator("meh"); + KoanComparator comparator = new KoanComparator(); try{ comparator.compare(KoanMethod.getInstance("2",m), KoanMethod.getInstance("1",m)); }catch(RuntimeException fileNotFound){} @@ -35,9 +39,25 @@ public void testComparatorRanksByOrder() throws Exception { KoanMethod m1 = KoanMethod.getInstance("",clazz.getDeclaredMethod("someMethodOne")); KoanMethod m2 = KoanMethod.getInstance("",clazz.getDeclaredMethod("someMethodTwo")); List methods = Arrays.asList(m2,m1); - Collections.sort(methods, new KoanComparator("someMethodOne","someMethodTwo")); + Collections.sort(methods, new KoanComparator()); assertSame(m1,methods.get(0)); assertSame(m2,methods.get(1)); } + + @Test + public void testVariableNamesArentConfusedAsKoanMethodsWhenSorting() throws Exception { + Class clazz = new Object(){ + String foo; + @Koan public void bar(){} + @Koan public void foo(){} + }.getClass(); + KoanMethod m1 = KoanMethod.getInstance("", clazz.getDeclaredMethod("bar")); + KoanMethod m2 = KoanMethod.getInstance("", clazz.getDeclaredMethod("foo")); + List methods = Arrays.asList(m2,m1); + Collections.sort(methods, new KoanComparator()); + assertSame(m1,methods.get(0)); + assertSame(m2,methods.get(1)); + } + } From 8914a1013b3a17df25b03786c2111d91458798d0 Mon Sep 17 00:00:00 2001 From: mat bentley Date: Thu, 25 May 2017 23:01:15 -0400 Subject: [PATCH 06/30] updating build --- koans/app/lib/koans.jar | Bin 97942 -> 97842 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/koans/app/lib/koans.jar b/koans/app/lib/koans.jar index 8820ac3fa5359440b82c5a84f550a2619f8180b6..efeddec998f34efe29cf497a33d065fc11825b1b 100644 GIT binary patch delta 74434 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 6IEnk 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 z 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 delta 74323 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 Date: Sat, 8 Jul 2017 09:27:32 -0700 Subject: [PATCH 07/30] Fix markdown so github displays header properly. --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 34bd739e..61364ad1 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,6 @@ -#Java Koans [![Build Status](https://travis-ci.org/matyb/java-koans.png?branch=master)](https://travis-ci.org/matyb/java-koans) +# Java Koans + +[![Build Status](https://travis-ci.org/matyb/java-koans.png?branch=master)](https://travis-ci.org/matyb/java-koans) Running Instructions: ===================== From b4ed013ecbee027dc66d55820976ec1e456f503f Mon Sep 17 00:00:00 2001 From: matyb Date: Mon, 10 Jul 2017 22:24:53 -0400 Subject: [PATCH 08/30] temp files checked into git --- .gitignore | 1 + .../com/sandwich/koan/KoansResultTest.java | 33 -- .../lib/data/com/sandwich/koan/TestUtils.java | 315 ------------- .../data/com/sandwich/koan/TestUtilsTest.java | 436 ------------------ .../CommandLineArgumentBuilderTest.java | 79 ---- .../koan/constant/ArgumentTypeTest.java | 30 -- .../koan/path/CommandLineTestCase.java | 152 ------ .../koan/path/DefaultKoanDescriptionTest.java | 48 -- .../koan/path/XmlVariableInjectorTest.java | 70 --- .../FakeXmlToPathTransformer.java | 38 -- .../sandwich/koan/runner/AppLauncherTest.java | 56 --- .../runner/AppReadinessForDeploymentTest.java | 199 -------- .../koan/runner/CommandLineTestCaseTest.java | 143 ------ .../koan/runner/ConsolePresenterTest.java | 152 ------ .../koan/runner/KoanSuiteRunnerTest.java | 44 -- .../runner/ui/AbstractSuitePresenterTest.java | 80 ---- .../koan/suite/BlowUpOnLineEleven.java | 14 - .../sandwich/koan/suite/BlowUpOnLineTen.java | 12 - .../sandwich/koan/suite/OneFailingKoan.java | 12 - .../suite/OneFailingKoanDifferentName.java | 13 - .../sandwich/koan/suite/OnePassingKoan.java | 14 - .../suite/OnePassingKoanDifferentName.java | 5 - .../com/sandwich/util/KoanComparatorTest.java | 43 -- .../util/io/DirectoryManagerTest.java | 42 -- .../com/sandwich/util/io/FileMonitorTest.java | 24 - 25 files changed, 1 insertion(+), 2054 deletions(-) delete mode 100644 lib/out/test/lib/data/com/sandwich/koan/KoansResultTest.java delete mode 100644 lib/out/test/lib/data/com/sandwich/koan/TestUtils.java delete mode 100644 lib/out/test/lib/data/com/sandwich/koan/TestUtilsTest.java delete mode 100644 lib/out/test/lib/data/com/sandwich/koan/cmdline/CommandLineArgumentBuilderTest.java delete mode 100644 lib/out/test/lib/data/com/sandwich/koan/constant/ArgumentTypeTest.java delete mode 100644 lib/out/test/lib/data/com/sandwich/koan/path/CommandLineTestCase.java delete mode 100644 lib/out/test/lib/data/com/sandwich/koan/path/DefaultKoanDescriptionTest.java delete mode 100644 lib/out/test/lib/data/com/sandwich/koan/path/XmlVariableInjectorTest.java delete mode 100644 lib/out/test/lib/data/com/sandwich/koan/path/xmltransformation/FakeXmlToPathTransformer.java delete mode 100644 lib/out/test/lib/data/com/sandwich/koan/runner/AppLauncherTest.java delete mode 100644 lib/out/test/lib/data/com/sandwich/koan/runner/AppReadinessForDeploymentTest.java delete mode 100644 lib/out/test/lib/data/com/sandwich/koan/runner/CommandLineTestCaseTest.java delete mode 100644 lib/out/test/lib/data/com/sandwich/koan/runner/ConsolePresenterTest.java delete mode 100644 lib/out/test/lib/data/com/sandwich/koan/runner/KoanSuiteRunnerTest.java delete mode 100644 lib/out/test/lib/data/com/sandwich/koan/runner/ui/AbstractSuitePresenterTest.java delete mode 100644 lib/out/test/lib/data/com/sandwich/koan/suite/BlowUpOnLineEleven.java delete mode 100644 lib/out/test/lib/data/com/sandwich/koan/suite/BlowUpOnLineTen.java delete mode 100644 lib/out/test/lib/data/com/sandwich/koan/suite/OneFailingKoan.java delete mode 100644 lib/out/test/lib/data/com/sandwich/koan/suite/OneFailingKoanDifferentName.java delete mode 100644 lib/out/test/lib/data/com/sandwich/koan/suite/OnePassingKoan.java delete mode 100644 lib/out/test/lib/data/com/sandwich/koan/suite/OnePassingKoanDifferentName.java delete mode 100644 lib/out/test/lib/data/com/sandwich/util/KoanComparatorTest.java delete mode 100644 lib/out/test/lib/data/com/sandwich/util/io/DirectoryManagerTest.java delete mode 100644 lib/out/test/lib/data/com/sandwich/util/io/FileMonitorTest.java diff --git a/.gitignore b/.gitignore index b3d0261d..531f7b68 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ bin/* lib/build/bin/* lib/build/reports/* +lib/out koans/data koans/data* .classpath diff --git a/lib/out/test/lib/data/com/sandwich/koan/KoansResultTest.java b/lib/out/test/lib/data/com/sandwich/koan/KoansResultTest.java deleted file mode 100644 index b2011ebd..00000000 --- a/lib/out/test/lib/data/com/sandwich/koan/KoansResultTest.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.sandwich.koan; - -import static org.junit.Assert.assertTrue; - -import java.util.Arrays; - -import org.junit.Test; - -import com.sandwich.koan.result.KoanMethodResult; -import com.sandwich.koan.result.KoanSuiteResult; -import com.sandwich.koan.result.KoanSuiteResult.KoanResultBuilder; -import com.sandwich.koan.suite.OneFailingKoan; - -public class KoansResultTest { - - @Test - public void testToString() throws Exception { - KoanResultBuilder builder = new KoanResultBuilder() - .remainingCases(Arrays.asList(OneFailingKoan.class.getSimpleName())) - .methodResult(new KoanMethodResult(KoanMethod.getInstance("", OneFailingKoan.class.getDeclaredMethods()[0]), "msg", "2")) - .level("1") - .numberPassing(3); - KoanSuiteResult result = builder.build(); - String string = result.toString(); - assertTrue(string.contains("1")); - assertTrue(string.contains("2")); - assertTrue(string.contains("3")); - assertTrue(string.contains(OneFailingKoan.class.getSimpleName())); - assertTrue(string.contains(OneFailingKoan.class.getDeclaredMethods()[0].getName())); - assertTrue(string.contains("msg")); - } - -} diff --git a/lib/out/test/lib/data/com/sandwich/koan/TestUtils.java b/lib/out/test/lib/data/com/sandwich/koan/TestUtils.java deleted file mode 100644 index 52dd8dc2..00000000 --- a/lib/out/test/lib/data/com/sandwich/koan/TestUtils.java +++ /dev/null @@ -1,315 +0,0 @@ -package com.sandwich.koan; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.io.PrintStream; -import java.io.Serializable; -import java.lang.Thread.State; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.Random; - -import com.sandwich.koan.constant.KoanConstants; - -public class TestUtils { - - private static Random random = new Random(System.currentTimeMillis()); - public static final String EOL = System.getProperty("line.separator"); - public static final int MAX_UNIQUE_CHARS = 1000; - - public static long sizeInBytes(Serializable... objects) { - byte[] ba = null; - try { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - ObjectOutputStream oos = new ObjectOutputStream(baos); - oos.writeObject(objects); - oos.close(); - ba = baos.toByteArray(); - baos.close(); - } catch (IOException ioe) { - throw new RuntimeException(ioe); - } - return ba.length; - } - - public static void chewUpVM(){ - chewUpVM(100); - } - - public static void chewUpVM(long forApproxHowLongInMs){ - long start = System.currentTimeMillis(); - while(System.currentTimeMillis() - start > forApproxHowLongInMs){new Object();} - } - - public static String getRandomText(int i) { - return getRandomText(i,false); - } - - public static String getRandomText(int i, boolean enforceUnique) { - if(enforceUnique && i > MAX_UNIQUE_CHARS){ - throw new RuntimeException("call getRandomText w/ a value under 1000 if u wish to enforce unique"); - } - StringBuilder sb = new StringBuilder(); - int j = 0; - while(j < i){ - char nextChar = (char)random.nextInt(); - if(enforceUnique && sb.indexOf(String.valueOf(nextChar)) != -1){ - continue; - } - sb.append(nextChar); - j++; - } - return sb.toString(); - } - - public static long time(Runnable runnable) { - long start = System.currentTimeMillis(); - runnable.run(); - return System.currentTimeMillis() - start; - } - - public static void forEachLine(String text, ArgRunner runnable){ - String[] strings = text.split(KoanConstants.EOLS, -1); - for(String line : strings){ - runnable.run(line); - } - } - - @SuppressWarnings("unchecked") - public static T serialize(T t) { - try { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - ObjectOutputStream oos = new ObjectOutputStream(baos); - oos.writeObject(t); - oos.close(); - final byte[] ba = baos.toByteArray(); - baos.close(); - ByteArrayInputStream bais = new ByteArrayInputStream(ba); - ObjectInputStream ois = new ObjectInputStream(bais); - Object returnValue = ois.readObject(); - ois.close(); - return (T) returnValue; - } catch (IOException e) { - throw new RuntimeException(e); - } catch (ClassNotFoundException e) { - throw new RuntimeException(e); - } - } - - @SuppressWarnings("unchecked") - public static T getValue(String fieldName, Object target) { - Class clazz = target instanceof Class ? (Class)target : target.getClass(); - Field field = getField(clazz, fieldName); - try { - boolean wasAccessible = field.isAccessible(); - field.setAccessible(true); - Object value = field.get(target); - field.setAccessible(wasAccessible); - return (T)value; - } catch (IllegalArgumentException e) { - throw new RuntimeException(e); - } catch (IllegalAccessException e) { - throw new RuntimeException(e); - } - } - - public static void setValue(String fieldName, Object value, Object target) { - Class clazz = target instanceof Class ? (Class)target : target.getClass(); - Field field = getField(clazz, fieldName); - try { - boolean wasAccessible = field.isAccessible(); - field.setAccessible(true); - field.set(target, value); - field.setAccessible(wasAccessible); - return; - } catch (IllegalArgumentException e) { - throw new RuntimeException(e); - } catch (IllegalAccessException e) { - throw new RuntimeException(e); - } - } - - public static Field getField(Class clazz, String fieldName){ - String className = clazz.getName(); - do{ - for(Field field : clazz.getDeclaredFields()){ - if(field.getName().equals(fieldName)){ - return field; - } - } - clazz = (Class)clazz.getSuperclass(); - }while(clazz != null); - throw new IllegalArgumentException(fieldName+" was not found in class: "+className); - } - - /** - * Used to simulate multiple threads accessing the same method whilst busy. - * Will fail in insufficiently concurrent scenarios. - * - * @param assertion - * @param rs - * @throws InterruptedException - */ - public static void doSimultaneouslyAndRepetitively(TwoObjectAssertion assertion, final Runnable... rs) throws InterruptedException{ - assertTrue("Whats the point of testing for synchronization w/ less than two threads?", rs.length > 1); - final int[] c = new int[]{0}; - int startRuns = rs.length + 9; - final Thread[] threads = new Thread[rs.length]; - int totalRuns = 0; - for(int i = 0; i < rs.length; i++){ - final int it = i; - final int startRunsTemp = startRuns; - totalRuns += startRunsTemp; - startRuns--; - threads[i] = new Thread(new Runnable(){ - public void run() { - Runnable runnable = rs[it]; - for(int j = 0; j < startRunsTemp; j++){ - runnable.run(); - c[0]++; - } - } - }); - threads[i].start(); - } - allowThreadsToFinish(threads); - assertion.assertOn("Threads died before they could finish.", totalRuns, c[0]); - } - - public static void doSimultaneouslyAndRepetitively(TwoObjectAssertion assertion, - Class anticipatedExceptionClass, - final Runnable... rs) throws InterruptedException{ - PrintStream temp = System.err; - try { - ByteArrayOutputStream sysErr = new ByteArrayOutputStream(); - System.setErr(new PrintStream(sysErr)); - doSimultaneouslyAndRepetitively(assertion, rs); - String errors = sysErr.toString(); - int i = rs.length; - assertFalse(errors.contains("Thread-"+(i+1))); - for(;i > 0; i--){ - assertTrue(errors.contains("Thread-"+i+"\" "+anticipatedExceptionClass.getName())); - } - } finally { - System.setErr(temp); - } - } - - /** - * Will lock Thread accessible when called from Thread via repetitive sleep - * calls until the passed in threads are terminated. Generally used to keep - * the test exec thread alive while the other threads are still working. - * - * @param threads - * @throws InterruptedException - */ - public static void allowThreadsToFinish(final Thread[] threads) - throws InterruptedException { - boolean threadsDone = false; - while(!threadsDone){ - threadsDone = true; - for(Thread thread : threads){ - if(thread.getState() != State.TERMINATED){ - Thread.sleep(10); - threadsDone = false; - } - } - } - } - - public static void assertEqualsContractEnforcement(Object obj0, Object obj1, Object obj2){ - assertFalse(obj0.equals(null)); - assertFalse(obj1.equals(null)); - assertFalse(obj2.equals(null)); - - assertEquals(obj0, obj0); - assertEquals(obj1, obj1); - assertEquals(obj2, obj2); - - assertEquals(obj0, obj1); - assertEquals(obj1, obj0); - - assertEquals(obj1, obj2); - assertEquals(obj2, obj1); - - assertEquals(obj2, obj0); - assertEquals(obj0, obj2); - } - - public static void assertHashCodeContractEnforcement(Object obj0, Object obj1, Object obj2){ - assertEquals(obj0.hashCode(), obj0.hashCode()); - assertEquals(obj1.hashCode(), obj1.hashCode()); - assertEquals(obj2.hashCode(), obj2.hashCode()); - - assertEquals(obj0.hashCode(), obj1.hashCode()); - assertEquals(obj1.hashCode(), obj0.hashCode()); - - assertEquals(obj1.hashCode(), obj2.hashCode()); - assertEquals(obj2.hashCode(), obj1.hashCode()); - - assertEquals(obj2.hashCode(), obj0.hashCode()); - assertEquals(obj0.hashCode(), obj2.hashCode()); - } - - public static void assertHashCodeEqualsContracts(Object obj0, Object obj1, Object obj2){ - assertEqualsContractEnforcement(obj0, obj1, obj2); - assertHashCodeContractEnforcement(obj0, obj1, obj2); - } - - public static Object invokePrivate( - String name, - final Object obj, - Object[] objects) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException { - Method method = null; - Class objClass = obj instanceof Class ? (Class)obj : obj.getClass(); - while(objClass != null && method == null){ - for(Method m : objClass.getDeclaredMethods()){ - if (name.equals(m.getName()) && - (objects == null && m.getParameterTypes().length == 0) || - (objects != null && objects.length == m.getParameterTypes().length)){ - method = m; - break; - } - } - objClass = objClass.getSuperclass(); - } - if(method == null){ - throw new IllegalArgumentException("method with name "+name+" was not found, check class definition."); - } - final boolean wasAccessible = method.isAccessible(); - try{ - method.setAccessible(true); - return method.invoke(obj, objects); - }finally{ - if(wasAccessible != method.isAccessible()){ - method.setAccessible(wasAccessible); - } - } - } - - public static interface ArgRunner { - public void run(T t); - } - - public static interface TwoObjectAssertion { - /** - * Message to display when assertion fails. Followed by 2 objects to - * assertOn. Useful for reusing in object composition tests or a - * chain of command pattern based assertion chain. - * - * @param msg - * @param o0 - * @param o1 - */ - void assertOn(String msg, Object o0, Object o1); - } - -} diff --git a/lib/out/test/lib/data/com/sandwich/koan/TestUtilsTest.java b/lib/out/test/lib/data/com/sandwich/koan/TestUtilsTest.java deleted file mode 100644 index a5a66b8c..00000000 --- a/lib/out/test/lib/data/com/sandwich/koan/TestUtilsTest.java +++ /dev/null @@ -1,436 +0,0 @@ -package com.sandwich.koan; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import java.io.ByteArrayOutputStream; -import java.io.PrintStream; - -import org.easymock.EasyMock; -import org.junit.Test; - -import com.sandwich.koan.TestUtils.ArgRunner; -import com.sandwich.koan.TestUtils.TwoObjectAssertion; - -public class TestUtilsTest { - - @Test - public void testEqualsContractEnforcement_integerIdentity_happyPath() throws Exception { - Integer one = 1; - TestUtils.assertEqualsContractEnforcement(one, one, one); - } - - @Test - public void testEqualsContractEnforcement_integerObject_happyPath() throws Exception { - TestUtils.assertEqualsContractEnforcement(new Integer(1), new Integer(1), new Integer(1)); - } - - @Test(expected=AssertionError.class) - public void testEqualsContractEnforcement_integer_exceptionPath0() throws Exception { - TestUtils.assertEqualsContractEnforcement(new Integer(2), new Integer(1), new Integer(1)); - } - - @Test(expected=AssertionError.class) - public void testEqualsContractEnforcement_integer_exceptionPath1() throws Exception { - TestUtils.assertEqualsContractEnforcement(new Integer(1), new Integer(2), new Integer(1)); - } - - @Test(expected=AssertionError.class) - public void testEqualsContractEnforcement_integer_exceptionPath() throws Exception { - TestUtils.assertEqualsContractEnforcement(new Integer(1), new Integer(1), new Integer(2)); - } - - @Test - public void testHashCodeContractEnforcement_integerIdentity_happyPath() throws Exception { - Integer one = 1; - TestUtils.assertHashCodeContractEnforcement(one, one, one); - } - - @Test - public void testHashCodeContractEnforcement_integerObject_happyPath() throws Exception { - TestUtils.assertHashCodeContractEnforcement(new Integer(1), new Integer(1), new Integer(1)); - } - - @Test(expected=AssertionError.class) - public void testHashCodeContractEnforcement_integer_exceptionPath0() throws Exception { - TestUtils.assertHashCodeContractEnforcement(new Integer(2), new Integer(1), new Integer(1)); - } - - @Test(expected=AssertionError.class) - public void testHashCodeContractEnforcement_integer_exceptionPath1() throws Exception { - TestUtils.assertHashCodeContractEnforcement(new Integer(1), new Integer(2), new Integer(1)); - } - - @Test(expected=AssertionError.class) - public void testHashCodeContractEnforcement_integer_exceptionPath() throws Exception { - TestUtils.assertHashCodeContractEnforcement(new Integer(1), new Integer(1), new Integer(2)); - } - - @Test - public void testHashCodeContractEnforcement_testObj_happyPath() throws Exception { - TestUtils.assertHashCodeContractEnforcement(new ContractEnforcementBase(), - new ContractEnforcementBase(), - new ContractEnforcementBase()); - } - - @Test(expected=AssertionError.class) - public void testHashCodeContractEnforcement_testObj_exceptionPath0() throws Exception { - TestUtils.assertHashCodeContractEnforcement(new ContractEnforcementSubclass(), - new ContractEnforcementBase(), - new ContractEnforcementBase()); - } - - @Test(expected=AssertionError.class) - public void testHashCodeContractEnforcement_testObj_exceptionPath1() throws Exception { - TestUtils.assertHashCodeContractEnforcement(new ContractEnforcementBase(), - new ContractEnforcementSubclass(), - new ContractEnforcementBase()); - } - - @Test(expected=AssertionError.class) - public void testHashCodeContractEnforcement_testObj_exceptionPath2() throws Exception { - TestUtils.assertHashCodeContractEnforcement(new ContractEnforcementBase(), - new ContractEnforcementBase(), - new ContractEnforcementSubclass()); - } - - @Test - public void testEqualsContractEnforcement_testObj_happyPath() throws Exception { - TestUtils.assertEqualsContractEnforcement(new ContractEnforcementBase(), - new ContractEnforcementBase(), - new ContractEnforcementBase()); - } - - @Test(expected=AssertionError.class) - public void testEqualsContractEnforcement_testObj_exceptionPath0() throws Exception { - TestUtils.assertEqualsContractEnforcement(new ContractEnforcementSubclass(), - new ContractEnforcementBase(), - new ContractEnforcementBase()); - } - - @Test(expected=AssertionError.class) - public void testEqualsContractEnforcement_testObj_exceptionPath1() throws Exception { - TestUtils.assertEqualsContractEnforcement(new ContractEnforcementBase(), - new ContractEnforcementSubclass(), - new ContractEnforcementBase()); - } - - @Test(expected=AssertionError.class) - public void testEqualsContractEnforcement_testObj_exceptionPath2() throws Exception { - TestUtils.assertEqualsContractEnforcement(new ContractEnforcementBase(), - new ContractEnforcementBase(), - new ContractEnforcementSubclass()); - } - - static class ContractEnforcementBase { - int i = 1; - @Override - public boolean equals(Object o){ - return o instanceof ContractEnforcementBase && i == ((ContractEnforcementBase)o).i; - } - @Override - public int hashCode(){ - return 1; - } - } - - static class ContractEnforcementSubclass extends ContractEnforcementBase { - int j = 2; - @Override - public boolean equals(Object o){ - return o instanceof ContractEnforcementSubclass - && i == ((ContractEnforcementSubclass)o).i - && j == ((ContractEnforcementSubclass)o).j; - } - @Override - public int hashCode(){ - return 2; - } - } - - @Test(expected=AssertionError.class, timeout=1000) - public void testEqualsConcurrency_concurrentAccessFails() throws Exception { - final PrintStream temp = System.err; - try { - ByteArrayOutputStream sysErr = new ByteArrayOutputStream(); - System.setErr(new PrintStream(sysErr)); - TestUtils.doSimultaneouslyAndRepetitively(new TwoObjectAssertion() { - public void assertOn(String msg, Object o0, Object o1) { - assertEquals(msg, o0, o1); - } - }, IllegalMonitorStateException.class, - new Runnable() { - public void run() { - waste(10); - } - }, new Runnable() { - public void run() { - waste(11); - } - }, new Runnable() { - public void run() { - waste(3); - } - }); - String errors = sysErr.toString(); - assertTrue(errors.contains("Thread-1\" java.lang.IllegalMonitorStateException")); - assertTrue(errors.contains("Thread-2\" java.lang.IllegalMonitorStateException")); - assertTrue(errors.contains("Thread-3\" java.lang.IllegalMonitorStateException")); - assertFalse(errors.contains("Thread-4")); - } finally { - System.setErr(new PrintStream(temp)); - } - } - - @Test(expected=java.lang.AssertionError.class, timeout=500) - public void testEqualsConcurrency_concurrentAccessFails_assertIllegalMonitorStateException() throws Exception { - TestUtils.doSimultaneouslyAndRepetitively(new TwoObjectAssertion() { - public void assertOn(String msg, Object o0, Object o1) { - assertEquals(msg, o0, o1); - } - }, - IllegalMonitorStateException.class, - new Runnable() { - public void run() { - waste(10); - } - }, - new Runnable() { - public void run() { - waste(11); - } - }, - new Runnable() { - public void run() { - waste(3); - } - }); - } - - @Test - public void testEqualsConcurrency() throws Exception { - TestUtils.doSimultaneouslyAndRepetitively(new TwoObjectAssertion() { - public void assertOn(String msg, Object o0, Object o1) { - assertEquals(msg, o0, o1); - } - }, new Runnable(){ - public void run() { - wasteSynchronized(10); - } - }, new Runnable(){ - public void run() { - wasteSynchronized(11); - } - }, new Runnable(){ - public void run() { - wasteSynchronized(3); - } - }); - } - - @Test - public void testEqualsConcurrency_II() throws Exception { - TestUtils.doSimultaneouslyAndRepetitively(new TwoObjectAssertion() { - public void assertOn(String msg, Object o0, Object o1) { - assertEquals(msg, o0, o1); - } - }, new Runnable(){ - public void run() { - wasteSynchronized(10); - } - }, new Runnable(){ - public void run() { - wasteSynchronized(11); - } - }, new Runnable(){ - public void run() { - wasteSynchronized(4); - } - }, new Runnable(){ - public void run() { - wasteSynchronized(6); - } - }); - } - - private void waste(int i) { - try { - wait(i); - } catch (InterruptedException e) { - fail(e.getMessage()); - } - } - - private int wasteSynchronized(int i) { synchronized(this){ - try { - wait(i); - } catch (InterruptedException e) { - fail(e.getMessage()); - } - return i; - }} - - @Test - public void testForEachLine_threeNewLines() throws Exception { - @SuppressWarnings("unchecked") - ArgRunner runner = EasyMock.createStrictMock(ArgRunner.class); - - runner.run(""); - EasyMock.expectLastCall(); - - runner.run(""); - EasyMock.expectLastCall(); - - runner.run(""); - EasyMock.expectLastCall(); - - runner.run(""); - EasyMock.expectLastCall(); - - EasyMock.replay(runner); - - TestUtils.forEachLine("\n\n\n", runner); - EasyMock.verify(runner); - } - - @Test - public void testForEachLine_spaceNewLineNewLine(){ - @SuppressWarnings("unchecked") - ArgRunner runner = EasyMock.createStrictMock(ArgRunner.class); - - runner.run(" "); - EasyMock.expectLastCall(); - - runner.run(""); - EasyMock.expectLastCall(); - - runner.run(""); - EasyMock.expectLastCall(); - - EasyMock.replay(runner); - - TestUtils.forEachLine(" \n\n", runner); - EasyMock.verify(runner); - } - - @Test - public void testForEachLine_newLineNewLineSpace(){ - @SuppressWarnings("unchecked") - ArgRunner runner = EasyMock.createStrictMock(ArgRunner.class); - - runner.run(""); - EasyMock.expectLastCall(); - - runner.run(""); - EasyMock.expectLastCall(); - - runner.run(" "); - EasyMock.expectLastCall(); - - EasyMock.replay(runner); - - TestUtils.forEachLine("\n\n ", runner); - EasyMock.verify(runner); - } - - @Test - public void testMixingBackslashRAndBackslashNNewLines() throws Exception { - @SuppressWarnings("unchecked") - ArgRunner runner = EasyMock.createStrictMock(ArgRunner.class); - - runner.run(""); - EasyMock.expectLastCall(); - - runner.run(" "); - EasyMock.expectLastCall(); - - runner.run(" "); - EasyMock.expectLastCall(); - - EasyMock.replay(runner); - - TestUtils.forEachLine("\r \n ", runner); // can mix and match \r and \n - EasyMock.verify(runner); - } - - @Test - public void testMixingBackslashNAndBackslashRNewLines() throws Exception { - @SuppressWarnings("unchecked") - ArgRunner runner = EasyMock.createStrictMock(ArgRunner.class); - - runner.run(""); - EasyMock.expectLastCall(); - - runner.run(" "); - EasyMock.expectLastCall(); - - runner.run(" "); - EasyMock.expectLastCall(); - - EasyMock.replay(runner); - - TestUtils.forEachLine("\n \r ", runner); // can mix and match \r and \n - EasyMock.verify(runner); - } - - @Test - public void testForEachLine_emptyString() throws Exception { - @SuppressWarnings("unchecked") - ArgRunner runner = EasyMock.createStrictMock(ArgRunner.class); - runner.run(""); - EasyMock.expectLastCall(); - - EasyMock.replay(runner); - - TestUtils.forEachLine("", runner); - EasyMock.verify(runner); - } - - @Test - public void testForEachLine_nothingThreeNewLinesSeperatedBy1Space() throws Exception { - @SuppressWarnings("unchecked") - ArgRunner runner = EasyMock.createStrictMock(ArgRunner.class); - - runner.run(""); - EasyMock.expectLastCall(); - - runner.run(" "); - EasyMock.expectLastCall(); - - runner.run(" "); - EasyMock.expectLastCall(); - - runner.run(""); - EasyMock.expectLastCall(); - - EasyMock.replay(runner); - - TestUtils.forEachLine("\n \n \n", runner); - EasyMock.verify(runner); - } - - @Test - public void testForEachLine_nothingThreeNewLinesSeperatedBy1SpaceThen2Spaces() throws Exception { - @SuppressWarnings("unchecked") - ArgRunner runner = EasyMock.createStrictMock(ArgRunner.class); - - runner.run(""); - EasyMock.expectLastCall(); - - runner.run(" "); - EasyMock.expectLastCall(); - - runner.run(" "); - EasyMock.expectLastCall(); - - runner.run(""); - EasyMock.expectLastCall(); - - EasyMock.replay(runner); - - TestUtils.forEachLine("\n \n \n", runner); - EasyMock.verify(runner); - } -} diff --git a/lib/out/test/lib/data/com/sandwich/koan/cmdline/CommandLineArgumentBuilderTest.java b/lib/out/test/lib/data/com/sandwich/koan/cmdline/CommandLineArgumentBuilderTest.java deleted file mode 100644 index 5098f8da..00000000 --- a/lib/out/test/lib/data/com/sandwich/koan/cmdline/CommandLineArgumentBuilderTest.java +++ /dev/null @@ -1,79 +0,0 @@ -package com.sandwich.koan.cmdline; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import java.util.Map; -import java.util.Map.Entry; - -import org.junit.Test; - -import com.sandwich.koan.constant.ArgumentType; -import com.sandwich.util.SimpleEntry; - - -public class CommandLineArgumentBuilderTest { - - @Test - public void testNoArguments() throws Exception { - assertEquals(ArgumentType.RUN_KOANS, new CommandLineArgumentBuilder().entrySet().iterator().next().getKey()); - } - - @Test - public void testUnanticipatedArgument_yieldsMethodArg_constructedImplicitly() throws Exception { - String value = - "if string isn't a known command line arg (ArgumentType) or class - assume its a method"; - Entry anticipatedResult = - new SimpleEntry(ArgumentType.METHOD_ARG, - new CommandLineArgument(ArgumentType.METHOD_ARG, value)); - Map commandLineArgs = - new CommandLineArgumentBuilder(value); - assertEquals(1, commandLineArgs.size()); - assertEquals(anticipatedResult, commandLineArgs.entrySet().iterator().next()); - } - - @Test - public void testMethodArg_constructedExplicitly() throws Exception { - String value = "someMethodName"; - Entry anticipatedResult = - new SimpleEntry(ArgumentType.METHOD_ARG, - new CommandLineArgument(ArgumentType.METHOD_ARG, value)); - Map commandLineArgs = new CommandLineArgumentBuilder( - ArgumentType.METHOD_ARG.args().iterator().next(), - value); - assertEquals(1, commandLineArgs.size()); - assertEquals(anticipatedResult, commandLineArgs.entrySet().iterator().next()); - } - - @Test - public void testClassArg_constructedImplicitly() throws Exception { - String value = Object.class.getName(); - Map commandLineArgs = new CommandLineArgumentBuilder(value); - assertEquals(2, commandLineArgs.size()); - assertTrue(commandLineArgs.containsKey(ArgumentType.CLASS_ARG)); - assertTrue(commandLineArgs.containsKey(ArgumentType.RUN_KOANS)); - } - - @Test - public void testClassArg_constructedExplicitly() throws Exception { - String value = Object.class.getName(); - Map commandLineArgs = new CommandLineArgumentBuilder( - ArgumentType.CLASS_ARG.args().iterator().next(), value); - assertEquals(2, commandLineArgs.size()); - assertTrue(commandLineArgs.containsKey(ArgumentType.CLASS_ARG)); - assertTrue(commandLineArgs.containsKey(ArgumentType.RUN_KOANS)); - } - - @Test - public void testMultipleMethodOrUnknownArgs_throwsException() throws Exception { - String value = "someMethodName"; - try{ - new CommandLineArgumentBuilder(ArgumentType.METHOD_ARG.args().iterator().next(), value, value); - fail(); - }catch(IllegalArgumentException x){ - - } - } - -} diff --git a/lib/out/test/lib/data/com/sandwich/koan/constant/ArgumentTypeTest.java b/lib/out/test/lib/data/com/sandwich/koan/constant/ArgumentTypeTest.java deleted file mode 100644 index 48ec575a..00000000 --- a/lib/out/test/lib/data/com/sandwich/koan/constant/ArgumentTypeTest.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.sandwich.koan.constant; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -import org.junit.Test; - -import com.sandwich.koan.path.CommandLineTestCase; - -public class ArgumentTypeTest extends CommandLineTestCase { - - @Test - public void testClassPrecedesMethod() throws Exception { - assertTrue(ArgumentType.CLASS_ARG.compareTo(ArgumentType.METHOD_ARG) == -1); - // further drive point home - method inserted at index 0, class index 1 - List classVsMethod = Arrays.asList(ArgumentType.METHOD_ARG, ArgumentType.CLASS_ARG); - assertEquals(0, classVsMethod.indexOf(ArgumentType.METHOD_ARG)); - assertEquals(1, classVsMethod.indexOf(ArgumentType.CLASS_ARG)); - Collections.sort(classVsMethod); - // now - because of comparable impl was applied, class precedes method - this is necessary - // @ see KaonSuiteRunner.run() - assertEquals(1, classVsMethod.indexOf(ArgumentType.METHOD_ARG)); - assertEquals(0, classVsMethod.indexOf(ArgumentType.CLASS_ARG)); - } - -} diff --git a/lib/out/test/lib/data/com/sandwich/koan/path/CommandLineTestCase.java b/lib/out/test/lib/data/com/sandwich/koan/path/CommandLineTestCase.java deleted file mode 100644 index a39f265c..00000000 --- a/lib/out/test/lib/data/com/sandwich/koan/path/CommandLineTestCase.java +++ /dev/null @@ -1,152 +0,0 @@ -package com.sandwich.koan.path; -import static org.junit.Assert.assertEquals; - -import java.io.ByteArrayOutputStream; -import java.io.PrintStream; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; - -import org.junit.After; -import org.junit.Before; - -import com.sandwich.koan.Koan; -import com.sandwich.koan.KoanIncompleteException; -import com.sandwich.koan.TestUtils; -import com.sandwich.koan.TestUtils.ArgRunner; -import com.sandwich.koan.constant.ArgumentType; -import com.sandwich.koan.path.PathToEnlightenment.Path; -import com.sandwich.koan.path.xmltransformation.FakeXmlToPathTransformer; -import com.sandwich.koan.path.xmltransformation.KoanElementAttributes; -import com.sandwich.koan.runner.RunKoans; -import com.sandwich.util.io.DynamicClassLoader; -import com.sandwich.util.io.directories.DirectoryManager; -import com.sandwich.util.io.directories.Production; -import com.sandwich.util.io.directories.UnitTest; - -public abstract class CommandLineTestCase { - - private PrintStream console; - private ByteArrayOutputStream bytes; - - @Before - public void setUp() { - DirectoryManager.setDirectorySet(new UnitTest()); - bytes = new ByteArrayOutputStream(); - console = System.out; - TestUtils.setValue("behavior", new RunKoans(), ArgumentType.RUN_KOANS); - PathToEnlightenment.xmlToPathTransformer = new FakeXmlToPathTransformer(); - PathToEnlightenment.theWay = PathToEnlightenment.createPath(); - System.setOut(new PrintStream(bytes)); - } - - @After - public void tearDown() { - DirectoryManager.setDirectorySet(new Production()); - setRealPath(); - System.setOut(console); - } - - protected void setRealPath(){ - PathToEnlightenment.xmlToPathTransformer = null; - PathToEnlightenment.theWay = PathToEnlightenment.createPath(); - } - - protected Path stubAllKoans(String packageName, List path){ - Path oldKoans = PathToEnlightenment.getPathToEnlightenment(); - Map> tempSuitesAndMethods = - new LinkedHashMap>(); - DynamicClassLoader loader = new DynamicClassLoader(); - for(String suite : path){ - Map methodsByName = new LinkedHashMap(); - for(Method m : loader.loadClass(suite).getMethods()){ - if(m.getAnnotation(Koan.class) != null){ - methodsByName.put(m.getName(), new KoanElementAttributes("", m.getName(), "", m.getDeclaringClass().getName())); - } - } - tempSuitesAndMethods.put(suite, methodsByName); - } - Map>> stubbedPath = - new LinkedHashMap>>(); - stubbedPath.put(packageName, tempSuitesAndMethods); - PathToEnlightenment.theWay = new Path(null,stubbedPath); - return oldKoans; - } - - public Path stubAllKoans(List path){ - List classes = new ArrayList(); - for(Object o : path){ - String className; - if(o instanceof Class){ - className = ((Class)o).getName(); - }else{ - className = o.getClass().getName(); - } - classes.add(className); - } - return stubAllKoans("Test", classes); - } - - public void clearSysout(){ - bytes = new ByteArrayOutputStream(); - System.setOut(new PrintStream(bytes)); - } - - public void assertSystemOutEquals(String expectation){ - expectation = expectation == null ? "" : expectation; - if(!expectation.equals(bytes.toString())){ - throw new KoanIncompleteException("expected: <"+expectation+"> but found: <"+bytes.toString()+">"); - } - } - - public void assertSystemOutContains(String expectation){ - assertSystemOutContains(true, expectation); - } - - protected void assertSystemOutDoesntContain(String expectation){ - assertSystemOutContains(false, expectation); - } - - private void assertSystemOutContains(boolean assertContains, String expectation) { - String consoleOutput = bytes.toString(); - boolean containsTheSubstring = consoleOutput.contains(expectation); - if(assertContains && !containsTheSubstring || !assertContains && containsTheSubstring){ - throw new KoanIncompleteException(new StringBuilder( - "<").append( - expectation).append( - "> ").append( - (assertContains ? "wasn't" : "was")).append( - " found in: " ).append( - "<").append( - consoleOutput).append( - ">").toString()); - } - } - - public void assertSystemOutLineEquals(final int lineNumber, final String lineText){ - assertSystemOutLineEquals(lineNumber, lineText, false); - } - - public void assertSystemOutLineEquals(final int lineNumber, final String lineText, - final boolean trimLinesString) { - final int[] onLine = new int[]{0}; - final boolean[] found = new boolean[]{false}; - TestUtils.forEachLine(bytes.toString(), new ArgRunner(){ - public void run(String s){ - if(onLine[0] == lineNumber){ - if(trimLinesString){ - s = s.trim(); - } - assertEquals(lineText, s); - found[0] = true; - } - onLine[0]++; - } - }); - if(!found[0]){ - throw new KoanIncompleteException(lineText+" was expected, but not found in: "+bytes.toString()); - } - } -} diff --git a/lib/out/test/lib/data/com/sandwich/koan/path/DefaultKoanDescriptionTest.java b/lib/out/test/lib/data/com/sandwich/koan/path/DefaultKoanDescriptionTest.java deleted file mode 100644 index 8f4f6de0..00000000 --- a/lib/out/test/lib/data/com/sandwich/koan/path/DefaultKoanDescriptionTest.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.sandwich.koan.path; - -import java.util.Map; -import java.util.Map.Entry; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import com.sandwich.koan.Koan; -import com.sandwich.koan.KoanMethod; -import com.sandwich.koan.constant.KoanConstants; -import com.sandwich.koan.path.xmltransformation.KoanElementAttributes; - -public class DefaultKoanDescriptionTest extends CommandLineTestCase { - - @Before - public void setUp(){ - super.setUp(); - } - - @After - public void tearDown(){ - super.tearDown(); - } - - @Test - public void defaultKoanDescriptions() throws Exception { - StringBuilder exceptionStringBuilder = new StringBuilder(KoanConstants.EOL); - for (Entry> suiteAndKoans : - PathToEnlightenment.getPathToEnlightenment().getKoanMethodsBySuiteByPackage().next().getValue().entrySet()) { - for(Entry koanEntry : suiteAndKoans.getValue().entrySet()){ - KoanMethod koan = KoanMethod.getInstance(koanEntry.getValue()); - Koan annotation = koan.getMethod().getAnnotation(Koan.class); - if (annotation != null && KoanConstants.DEFAULT_KOAN_DESC.equals(koan.getLesson())) { - exceptionStringBuilder.append(suiteAndKoans.getKey().getClass().getName()).append('.') - .append(koan.getMethod().getName()).append(KoanConstants.EOL); - } - } - } - String exceptionString = exceptionStringBuilder.toString(); - if(exceptionString.trim().length() != 0){ - throw new RuntimeException(new StringBuilder(KoanConstants.EOL).append( - "Following still have default Koan description:").append(exceptionString).toString()); - } - } - -} diff --git a/lib/out/test/lib/data/com/sandwich/koan/path/XmlVariableInjectorTest.java b/lib/out/test/lib/data/com/sandwich/koan/path/XmlVariableInjectorTest.java deleted file mode 100644 index 0b12af7f..00000000 --- a/lib/out/test/lib/data/com/sandwich/koan/path/XmlVariableInjectorTest.java +++ /dev/null @@ -1,70 +0,0 @@ -package com.sandwich.koan.path; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import org.junit.Test; - -import com.sandwich.koan.path.xmltransformation.XmlVariableInjector; -import com.sandwich.koan.suite.OneFailingKoan; - -public class XmlVariableInjectorTest { - - @Test - public void construction_nullMethod() throws Exception { - try{ - new XmlVariableInjector("", null); - fail("why construct w/ null method?"); - }catch(IllegalArgumentException t){ - // this is ok - we want this! - } - } - -// @Test -// public void construction_nullLesson() throws Exception { -// try{ -// new XmlVariableInjector(null, Object.class.getDeclaredMethod("equals", Object.class)); -// fail("why construct w/ null lesson?"); -// }catch(IllegalArgumentException t){ -// // this is ok - we want this! -// } -// } - - @Test - public void injectInputVariables_filePath() throws Exception { - String lesson = "meh ${file_path}"; - String result = new XmlVariableInjector(lesson, OneFailingKoan.class.getDeclaredMethod("koanMethod")) - .injectLessonVariables(); - String firstPkgName = "com"; - // just inspect anything beyond the root of the project - result = result.substring(result.indexOf(firstPkgName)+firstPkgName.length(), result.length()); - assertTrue(result.indexOf(firstPkgName) < result.indexOf("sandwich")); - assertTrue(result.indexOf("sandwich") < result.indexOf("koan")); - assertTrue(result.indexOf("koan") < result.indexOf("suite")); - } - - @Test - public void injectInputVariables_fileName() throws Exception { - String lesson = "meh ${file_name}"; - String result = new XmlVariableInjector(lesson, OneFailingKoan.class.getDeclaredMethod("koanMethod")) - .injectLessonVariables(); - assertEquals("meh OneFailingKoan", result); - } - - @Test - public void injectInputVariables_methodName() throws Exception { - String lesson = "meh ${method_name}"; - String result = new XmlVariableInjector(lesson, OneFailingKoan.class.getDeclaredMethod("koanMethod")) - .injectLessonVariables(); - assertEquals("meh koanMethod", result); - } - - @Test - public void nothingToInject() throws Exception { - String lesson = " meh ea asdwdw s "; - assertSame(lesson, new XmlVariableInjector(lesson, - OneFailingKoan.class.getDeclaredMethod("koanMethod")).injectLessonVariables()); - } -} diff --git a/lib/out/test/lib/data/com/sandwich/koan/path/xmltransformation/FakeXmlToPathTransformer.java b/lib/out/test/lib/data/com/sandwich/koan/path/xmltransformation/FakeXmlToPathTransformer.java deleted file mode 100644 index 63f84368..00000000 --- a/lib/out/test/lib/data/com/sandwich/koan/path/xmltransformation/FakeXmlToPathTransformer.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.sandwich.koan.path.xmltransformation; - -import java.util.Collections; -import java.util.LinkedHashMap; -import java.util.Map; - -import com.sandwich.koan.path.PathToEnlightenment.Path; - -public class FakeXmlToPathTransformer extends XmlToPathTransformerImpl { - - private Map> methodsBySuite; - - @SuppressWarnings("unchecked") - public FakeXmlToPathTransformer() { - this(Collections.EMPTY_MAP); - } - - public FakeXmlToPathTransformer(Map> methodsBySuite){ - this.methodsBySuite = methodsBySuite; - } - - public Map> getMethodsBySuite() { - return methodsBySuite; - } - - public void setMethodsBySuite(Map> methodsBySuite) { - this.methodsBySuite = methodsBySuite; - } - - @Override - public Path transform(){ - Map>> koans = - new LinkedHashMap>>(); - koans.put("test", new LinkedHashMap>(methodsBySuite)); - return new Path(null,koans); - } - -} diff --git a/lib/out/test/lib/data/com/sandwich/koan/runner/AppLauncherTest.java b/lib/out/test/lib/data/com/sandwich/koan/runner/AppLauncherTest.java deleted file mode 100644 index a3559be1..00000000 --- a/lib/out/test/lib/data/com/sandwich/koan/runner/AppLauncherTest.java +++ /dev/null @@ -1,56 +0,0 @@ -package com.sandwich.koan.runner; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Map; - -import org.junit.Test; - -import com.sandwich.koan.cmdline.CommandLineArgument; -import com.sandwich.koan.cmdline.CommandLineArgumentBuilder; -import com.sandwich.koan.constant.ArgumentType; - -public class AppLauncherTest { - - @Test - public void testNecessityOfAddingRunKoansCommandLineArgument_addsIfNoArgsPresent(){ //default target - Map args = new CommandLineArgumentBuilder(); - assertArgsContains(true, args, ArgumentType.RUN_KOANS); - } - - @Test - public void testNecessityOfAddingRunKoansCommandLineArgument_ifClassArgIsPresent(){ - Map args = new CommandLineArgumentBuilder(Object.class.getName()); - assertArgsContains(true, args, ArgumentType.RUN_KOANS, ArgumentType.CLASS_ARG); - } - - @Test - public void testNecessityOfAddingRunKoansCommandLineArgument_doesntIfClassArgIsntPresent(){ - List types = new ArrayList(Arrays.asList(ArgumentType.values())); - assertTrue(types.remove(ArgumentType.CLASS_ARG)); - assertTrue(types.remove(ArgumentType.DEBUG)); - assertTrue(types.remove(ArgumentType.RUN_KOANS)); - for(ArgumentType type : types){ - Map args = new CommandLineArgumentBuilder(type.args().iterator().next()); - assertArgsContains(false, args, ArgumentType.RUN_KOANS); - assertArgsContains(true, args, type); - } - } - - private static void assertArgsContains( - boolean shouldContain, Map args, ArgumentType...types) { - if(shouldContain){ - assertEquals("expected arguments of a certain length, but found those built were of a differing size", - types.length, args.size()); - } - for(ArgumentType type : types){ - assertEquals("the arguments built should" - + (shouldContain ? "" : "n't") - + " contain the type: "+type, shouldContain, args.containsKey(type)); - } - } -} diff --git a/lib/out/test/lib/data/com/sandwich/koan/runner/AppReadinessForDeploymentTest.java b/lib/out/test/lib/data/com/sandwich/koan/runner/AppReadinessForDeploymentTest.java deleted file mode 100644 index 630ebb5c..00000000 --- a/lib/out/test/lib/data/com/sandwich/koan/runner/AppReadinessForDeploymentTest.java +++ /dev/null @@ -1,199 +0,0 @@ -package com.sandwich.koan.runner; - -import static com.sandwich.koan.constant.KoanConstants.EXPECTATION_LEFT_ARG; -import static com.sandwich.koan.constant.KoanConstants.__; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.fail; - -import java.util.Arrays; -import java.util.Map; -import java.util.Map.Entry; -import java.util.logging.Handler; -import java.util.logging.LogRecord; -import java.util.logging.Logger; - -import org.junit.Test; - -import com.sandwich.koan.Koan; -import com.sandwich.koan.KoanMethod; -import com.sandwich.koan.cmdline.CommandLineArgumentBuilder; -import com.sandwich.koan.cmdline.CommandLineArgumentRunner; -import com.sandwich.koan.constant.KoanConstants; -import com.sandwich.koan.path.CommandLineTestCase; -import com.sandwich.koan.path.PathToEnlightenment; -import com.sandwich.koan.path.xmltransformation.KoanElementAttributes; -import com.sandwich.koan.result.KoanSuiteResult; -import com.sandwich.koan.suite.BlowUpOnLineEleven; -import com.sandwich.koan.suite.BlowUpOnLineTen; -import com.sandwich.koan.suite.OneFailingKoan; -import com.sandwich.koan.suite.OnePassingKoan; -import com.sandwich.koan.ui.SuitePresenter; -import com.sandwich.util.io.directories.DirectoryManager; -import com.sandwich.util.io.directories.Production; - -/** - * Anything that absoutely has to happen before bundling client jar - to be sure: - * - all koans fail by default - * - necessary aspects of app presentation are preserved - * - progression through koans (the sequence of koans) is consistent - */ -public class AppReadinessForDeploymentTest extends CommandLineTestCase { - - @Test - public void testMainMethodWithClassNameArg_qualifiedWithPkgName() throws Throwable { - stubAllKoans(Arrays.asList(new OnePassingKoan())); - new CommandLineArgumentRunner().run(); - assertSystemOutContains(KoanConstants.PASSING_SUITES+" "+OnePassingKoan.class.getSimpleName()); - } - - @Test - public void testMainMethodWithClassNameArg_classSimpleName() throws Throwable { - stubAllKoans(Arrays.asList(new OnePassingKoan())); - new CommandLineArgumentRunner().run(); - assertSystemOutContains(KoanConstants.PASSING_SUITES+" "+OnePassingKoan.class.getSimpleName()); - } - - @Test - public void testMainMethodWithClassNameArg_classNameAndMethod() throws Throwable { - stubAllKoans(Arrays.asList(new TwoFailingKoans())); - String failingKoanMethodName = TwoFailingKoans.class.getMethod("koanTwo").getName(); - new CommandLineArgumentRunner().run(); - assertSystemOutContains(failingKoanMethodName); - assertSystemOutContains("0/2"); - } - - public static class TwoFailingKoans extends OneFailingKoan { - @Koan - public void koanTwo(){assertEquals(true, false);} - } - - @Test - public void testGetKoans() throws Exception { - stubAllKoans(Arrays.asList(new OnePassingKoan())); - Map> koans = PathToEnlightenment.getPathToEnlightenment().iterator().next().getValue(); - assertEquals(1, koans.size()); - Entry> entry = koans.entrySet().iterator().next(); - assertEquals(OnePassingKoan.class.getName(), entry.getKey()); - assertEquals( OnePassingKoan.class.getDeclaredMethod("koan").toString(), - KoanMethod.getInstance(entry.getValue().get("koan")).getMethod().toString()); - } - - @Test /** Ensures that koans are ready for packaging & distribution */ - public void testKoanSuiteRunner_firstKoanFail() throws Exception { - setRealPath(); - final KoanSuiteResult[] result = new KoanSuiteResult[]{null}; - final SuitePresenter presenter = new SuitePresenter(){ - public void displayResult(KoanSuiteResult actualAppResult) { - // don't display, capture them so we can analyze and ensure first failure is reported - result[0] = actualAppResult; - } - }; - doAsIfInProd(new Runnable(){ - public void run(){ - new RunKoans(presenter, PathToEnlightenment.getPathToEnlightenment()).run(null); - } - }); - String firstSuiteClassRan = PathToEnlightenment.getPathToEnlightenment() - .iterator().next().getValue().entrySet().iterator().next().getKey(); - assertEquals(result[0].getFailingCase(), firstSuiteClassRan.substring(firstSuiteClassRan.lastIndexOf(".") + 1)); - } - - @Test /** Ensures that koans are ready for packaging & distribution */ - public void testKoanSuiteRunner_allKoansFail() throws Exception { - setRealPath(); - final KoanSuiteResult[] result = new KoanSuiteResult[]{null}; - final SuitePresenter presenter = new SuitePresenter(){ - public void displayResult(KoanSuiteResult actualAppResult) { - // don't display, capture them so we can analyze and ensure first failure is reported - result[0] = actualAppResult; - } - }; - doAsIfInProd(new Runnable(){ - public void run(){ - new RunKoans(presenter, PathToEnlightenment.getPathToEnlightenment()).run(null); - } - }); - String message = "Not all koans need solving! Each should ship in a failing state."; - assertEquals(message, 0, result[0].getNumberPassing()); - // make sure test was actually useful (ie something actually failed) - assertNotNull(result[0].getFailingCase()); - } - - private void doAsIfInProd(Runnable runnable) { - DirectoryManager.setDirectorySet(new Production()); - runnable.run(); - } - - @Test - public void testLineExceptionIsThrownAtIsHintedAt() throws Exception { - stubAllKoans(Arrays.asList(new BlowUpOnLineTen())); - new CommandLineArgumentRunner().run(); - assertSystemOutContains("Line 10"); - assertSystemOutDoesntContain("Line 11"); - } - - @Test - public void testLineExceptionIsThrownAtIsHintedAtEvenIfThrownFromSuperClass() throws Exception { - stubAllKoans(Arrays.asList(new BlowUpOnLineEleven())); - new CommandLineArgumentRunner().run(); - assertSystemOutContains("Line 11"); - assertSystemOutDoesntContain("Line 10"); - } - - @Test - public void testWarningFromPlacingExpecationOnWrongSide() throws Throwable { - final String[] message = new String[1]; - stubAllKoans(Arrays.asList(new WrongExpectationOrderKoan())); - Logger.getLogger(CommandLineArgumentRunner.class.getSimpleName()).addHandler( - new Handler() { - @Override - public void close() throws SecurityException { - } - - @Override - public void flush() { - } - - @Override - public void publish(LogRecord arg0) { - message[0] = arg0.getMessage(); - } - }); - new CommandLineArgumentRunner(new CommandLineArgumentBuilder()).run(); - assertEquals( - new StringBuilder( - WrongExpectationOrderKoan.class.getSimpleName()) - .append(".expectationOnLeft ") - .append(EXPECTATION_LEFT_ARG).toString(), message[0]); - } - - @Test - public void testNoWarningFromPlacingExpecationOnRightSide() - throws Throwable { - stubAllKoans(Arrays.asList(new OnePassingKoan())); - Logger.getLogger(CommandLineArgumentRunner.class.getSimpleName()).addHandler( - new Handler() { - @Override - public void close() throws SecurityException { - } - - @Override - public void flush() { - } - - @Override - public void publish(LogRecord arg0) { - fail("No logging necessary when koan passes, otherwise - logging is new, adjust accordingly."); - } - }); - new CommandLineArgumentRunner().run(); - } - - public static class WrongExpectationOrderKoan { - @Koan - public void expectationOnLeft() { - com.sandwich.util.Assert.assertEquals(__, false); - } - } -} diff --git a/lib/out/test/lib/data/com/sandwich/koan/runner/CommandLineTestCaseTest.java b/lib/out/test/lib/data/com/sandwich/koan/runner/CommandLineTestCaseTest.java deleted file mode 100644 index 179d7f31..00000000 --- a/lib/out/test/lib/data/com/sandwich/koan/runner/CommandLineTestCaseTest.java +++ /dev/null @@ -1,143 +0,0 @@ -package com.sandwich.koan.runner; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotSame; -import static org.junit.Assert.assertSame; -import static org.junit.Assert.fail; - -import java.io.PrintStream; -import java.util.Collections; -import java.util.List; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import com.sandwich.koan.path.CommandLineTestCase; -import com.sandwich.koan.path.PathToEnlightenment; -import com.sandwich.koan.path.PathToEnlightenment.Path; - -public class CommandLineTestCaseTest { - - CommandLineTestCase testCase; - - @Before - public void setUp(){ - testCase = new CommandLineTestCase(){}; - } - - @After - public void tearDown(){ - testCase.tearDown(); // really important - will remove regular System.out if commented! - testCase = null; - } - - @Test - public void testThatConsoleIsInitializedBySetUp() throws Exception { - PrintStream originalOut = System.out; - testCase.setUp(); - assertNotSame(originalOut, System.out); - } - - @Test - public void testThatConsoleIsCleanAfterSetUp() throws Exception { - testCase.setUp(); - testCase.assertSystemOutLineEquals(0, ""); - } - - @Test - public void testThatConsoleIsAttachedToSystem() throws Exception { - testCase.setUp(); - System.out.print("hello \n world!"); - testCase.assertSystemOutLineEquals(0, "hello "); - testCase.assertSystemOutLineEquals(1, " world!"); - } - - @Test - public void testThatAssertSystemOutLineEquals_withTrimStringArg() throws Exception { - testCase.setUp(); - System.out.println(" hello \n world! "); - testCase.assertSystemOutLineEquals(0, "hello", true); - testCase.assertSystemOutLineEquals(1, "world!", true); - } - - @Test - public void testThatTearDownDetachesDummiedConsoleFromSystem(){ - PrintStream originalConsole = System.out; - testCase.setUp(); - PrintStream fakeConsole = System.out; - assertNotSame(fakeConsole, originalConsole); - testCase.tearDown(); - assertSame(originalConsole, System.out); - } - - @Test - public void testThatStubAllKoansStubsAllKoansReference() throws Exception { - Path oldKoans = PathToEnlightenment.getPathToEnlightenment(); - List newKoans = Collections.emptyList(); - testCase.stubAllKoans(newKoans); - assertNotSame(oldKoans, PathToEnlightenment.getPathToEnlightenment()); - // number of suites - assertEquals(0, PathToEnlightenment.getPathToEnlightenment() - .iterator().next().getValue().size()); - } - - @Test - public void testTestCaseRestoresAllKoansReference() throws Exception { - Path oldKoans = PathToEnlightenment.getPathToEnlightenment(); - List newKoans = Collections.emptyList(); - testCase.stubAllKoans(newKoans); - assertNotSame(oldKoans, PathToEnlightenment.getPathToEnlightenment()); - testCase.tearDown(); - // creates all new instance - assertNotSame(oldKoans, PathToEnlightenment.getPathToEnlightenment()); - assertEquals(oldKoans, PathToEnlightenment.getPathToEnlightenment()); - } - - @Test - public void testClearSysout() throws Exception { - testCase.setUp(); - System.out.print("!"); - testCase.assertSystemOutLineEquals(0, "!"); - testCase.clearSysout(); - testCase.assertSystemOutLineEquals(0, ""); - } - - @Test - public void testSystemOutEquals_freshStart(){ - testCase.setUp(); - testCase.assertSystemOutEquals(""); - } - - @Test - public void testSystemOutEquals_aString() throws Exception { - String helloWorld = "Hello World!"; - testCase.setUp(); - testCase.assertSystemOutEquals(""); - System.out.print(helloWorld); - testCase.assertSystemOutEquals(helloWorld); - } - - @Test - public void testSystemOutContains_happyPath() throws Exception { - testCase.setUp(); - String zeroThruOne = "01"; - System.out.print(zeroThruOne); - for(char c : zeroThruOne.toCharArray()){ - testCase.assertSystemOutContains(String.valueOf(c)); - } - } - - @Test - public void testSystemOutContains_failurePath() throws Exception { - testCase.setUp(); - String zeroThruOne = "01"; - System.out.print(zeroThruOne); - try{ - testCase.assertSystemOutContains(String.valueOf("a")); - fail(); - }catch(AssertionError ex){ - assertEquals(" wasn't found in: <01>", ex.getMessage()); - } - } -} diff --git a/lib/out/test/lib/data/com/sandwich/koan/runner/ConsolePresenterTest.java b/lib/out/test/lib/data/com/sandwich/koan/runner/ConsolePresenterTest.java deleted file mode 100644 index 748f9818..00000000 --- a/lib/out/test/lib/data/com/sandwich/koan/runner/ConsolePresenterTest.java +++ /dev/null @@ -1,152 +0,0 @@ -package com.sandwich.koan.runner; - -import static com.sandwich.koan.constant.KoanConstants.ALL_SUCCEEDED; -import static com.sandwich.koan.constant.KoanConstants.COMPLETE_CHAR; -import static com.sandwich.koan.constant.KoanConstants.CONQUERED; -import static com.sandwich.koan.constant.KoanConstants.ENCOURAGEMENT; -import static com.sandwich.koan.constant.KoanConstants.EOL; -import static com.sandwich.koan.constant.KoanConstants.FAILING_SUITES; -import static com.sandwich.koan.constant.KoanConstants.INCOMPLETE_CHAR; -import static com.sandwich.koan.constant.KoanConstants.INVESTIGATE_IN_THE; -import static com.sandwich.koan.constant.KoanConstants.KOAN; -import static com.sandwich.koan.constant.KoanConstants.OUT_OF; -import static com.sandwich.koan.constant.KoanConstants.PASSING_SUITES; -import static com.sandwich.koan.constant.KoanConstants.PROGRESS; -import static com.sandwich.koan.constant.KoanConstants.PROGRESS_BAR_START; -import static com.sandwich.koan.constant.KoanConstants.PROGRESS_BAR_WIDTH; -import static com.sandwich.koan.constant.KoanConstants.WHATS_WRONG; - -import java.util.Arrays; - -import org.junit.Test; - -import com.sandwich.koan.cmdline.CommandLineArgumentRunner; -import com.sandwich.koan.cmdline.CommandLineArgumentBuilder; -import com.sandwich.koan.constant.KoanConstants; -import com.sandwich.koan.path.CommandLineTestCase; -import com.sandwich.koan.suite.OneFailingKoan; -import com.sandwich.koan.suite.OneFailingKoanDifferentName; -import com.sandwich.koan.suite.OnePassingKoan; -import com.sandwich.koan.suite.OnePassingKoanDifferentName; - -public class ConsolePresenterTest extends CommandLineTestCase { - - @Test - public void hintPresentation() throws Throwable { - stubAllKoans(Arrays.asList(new OneFailingKoanDifferentName())); - new CommandLineArgumentRunner(new CommandLineArgumentBuilder()).run(); - assertSystemOutContains(new StringBuilder( - INVESTIGATE_IN_THE).append( - " ").append( - OneFailingKoanDifferentName.class.getSimpleName()).append( - " class's ").append( - OneFailingKoanDifferentName.class.getDeclaredMethod("koanMethod").getName()).append( - " method.").toString()); - assertSystemOutContains("Line 11 may offer a clue as to how you may progress, now make haste!"); - } - - @Test // uncomment enableEncouragement @ the top of ConsolePresenter class - public void encouragement() throws Throwable { - if(KoanConstants.ENABLE_ENCOURAGEMENT){ - stubAllKoans(Arrays.asList(new Class[] { - OneFailingKoan.class })); - new CommandLineArgumentRunner().run(); - assertSystemOutContains(new StringBuilder( - CONQUERED).append( - " 0 ").append( - OUT_OF).append( - " 1 ").append( - KOAN).append( - "! ").append( - ENCOURAGEMENT).toString()); - assertSystemOutDoesntContain(ALL_SUCCEEDED); - } - } - - @Test - public void testOneHundredPercentSuccessReward() throws Throwable { - stubAllKoans(Arrays.asList(new Class[] { - OnePassingKoan.class })); - new CommandLineArgumentRunner().run(); - assertSystemOutContains(ALL_SUCCEEDED); - assertSystemOutDoesntContain(CONQUERED); - assertSystemOutDoesntContain(ENCOURAGEMENT); - } - - @Test - public void passingSuites() throws Throwable { - stubAllKoans(Arrays.asList(new OnePassingKoan(), new OnePassingKoanDifferentName())); - new CommandLineArgumentRunner().run(); - assertSystemOutContains(PASSING_SUITES+" OnePassingKoan, OnePassingKoanDifferentName"); - } - - @Test - public void failingSuites() throws Throwable { - stubAllKoans(Arrays.asList(new OneFailingKoan(), new OneFailingKoanDifferentName())); - new CommandLineArgumentRunner().run(); - assertSystemOutContains(FAILING_SUITES+" OneFailingKoan, OneFailingKoanDifferentName"); - } - - @Test - public void failingAndPassingSuites() throws Throwable { - stubAllKoans(Arrays.asList(new OnePassingKoan(), new OneFailingKoan())); - new CommandLineArgumentRunner().run(); - assertSystemOutContains(PASSING_SUITES+" OnePassingKoan"+EOL+ - FAILING_SUITES+" OneFailingKoan"); - } - - @Test - public void progressAllPassing() throws Throwable { - stubAllKoans(Arrays.asList(new OnePassingKoan())); - new CommandLineArgumentRunner().run(); - StringBuilder sb = new StringBuilder(PROGRESS).append(" ") - .append(PROGRESS_BAR_START); - for(int i = 0; i < PROGRESS_BAR_WIDTH; i++){ // 100% success - sb.append(COMPLETE_CHAR); - } - sb.append("] 1/1").append(EOL); - assertSystemOutContains(sb.toString()); - } - - @Test - public void progressAllFailing() throws Throwable { - stubAllKoans(Arrays.asList(new OneFailingKoan(), new OneFailingKoanDifferentName())); - new CommandLineArgumentRunner().run(); - StringBuilder sb = new StringBuilder( - PROGRESS).append(" ").append( - PROGRESS_BAR_START); - for(int i = 0; i < PROGRESS_BAR_WIDTH; i++){ // 100% failed - sb.append(INCOMPLETE_CHAR); - } - sb.append("] 0/2").append(EOL); - assertSystemOutContains(sb.toString()); - } - - @Test - public void progressFiftyFifty() throws Throwable { - stubAllKoans(Arrays.asList(new OnePassingKoan(), new OneFailingKoan())); - new CommandLineArgumentRunner().run(); - StringBuilder sb = new StringBuilder( - PROGRESS).append(" ").append( - PROGRESS_BAR_START); - for(int i = 0; i < PROGRESS_BAR_WIDTH / 2; i++){ // 50% succeeded - sb.append(COMPLETE_CHAR); - } - for(int i = 0; i < PROGRESS_BAR_WIDTH / 2; i++){ // 50% failed - sb.append(INCOMPLETE_CHAR); - } - sb.append("] 1/2").append(EOL); - assertSystemOutContains(sb.toString()); - } - - @Test - public void whatWentWrongExplanation() throws Throwable { - stubAllKoans(Arrays.asList(new OneFailingKoan())); - new CommandLineArgumentRunner().run(); - assertSystemOutContains(new StringBuilder( - WHATS_WRONG).append( - EOL).append( - "expected: but was:").toString()); - } - -} diff --git a/lib/out/test/lib/data/com/sandwich/koan/runner/KoanSuiteRunnerTest.java b/lib/out/test/lib/data/com/sandwich/koan/runner/KoanSuiteRunnerTest.java deleted file mode 100644 index aa106442..00000000 --- a/lib/out/test/lib/data/com/sandwich/koan/runner/KoanSuiteRunnerTest.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.sandwich.koan.runner; - - -public class KoanSuiteRunnerTest { - -// @Test -// public void testRunSortsAndInvokesByComparableImplInArgumentType() throws Exception { -// // test depends on this - this is to ensure rest of test is true -// { -//// assertEquals(-1, ArgumentType.TEST.compareTo(ArgumentType.CLASS_ARG)); -// } -// Map args = new LinkedHashMap(); -// final boolean[] called = {false, false, false}; -// args.put(ArgumentType.TEST, new CommandLineArgument(ArgumentType.TEST, null){ -// @Override public void run(){ -// assertFalse(called[0]); -// assertFalse(called[1]); -// assertFalse(called[2]); -// called[0] = true; -// } -// }); -// args.put(ArgumentType.CLASS_ARG, new CommandLineArgument(ArgumentType.CLASS_ARG, null){ -// @Override public void run(){ -// assertTrue(called[0]); -// assertFalse(called[1]); -// assertFalse(called[2]); -// called[1] = true; -// } -// }); -// args.put(ArgumentType.RUN_KOANS, new CommandLineArgument(ArgumentType.RUN_KOANS, null){ -// @Override public void run(){ -// assertTrue(called[0]); -// assertTrue(called[1]); -// assertFalse(called[2]); -// called[2] = true; -// } -// }); -// new CommandLineArgumentRunner(args).run(); -// assertTrue(called[0]); -// assertTrue(called[1]); -// assertTrue(called[2]); -// } - -} diff --git a/lib/out/test/lib/data/com/sandwich/koan/runner/ui/AbstractSuitePresenterTest.java b/lib/out/test/lib/data/com/sandwich/koan/runner/ui/AbstractSuitePresenterTest.java deleted file mode 100644 index 1e22df3c..00000000 --- a/lib/out/test/lib/data/com/sandwich/koan/runner/ui/AbstractSuitePresenterTest.java +++ /dev/null @@ -1,80 +0,0 @@ -package com.sandwich.koan.runner.ui; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; - -import java.util.Arrays; - -import org.junit.Test; - -import com.sandwich.koan.KoanMethod; -import com.sandwich.koan.result.KoanMethodResult; -import com.sandwich.koan.result.KoanSuiteResult; -import com.sandwich.koan.result.KoanSuiteResult.KoanResultBuilder; -import com.sandwich.koan.suite.OneFailingKoan; -import com.sandwich.koan.ui.AbstractSuitePresenter; - -public class AbstractSuitePresenterTest { - - @Test - public void testForwardingOneHundredPercentSuccess() throws Exception { - final int state[] = new int[]{0}; - AbstractSuitePresenter presenter = new AbstractSuitePresenter() { - public void displayAllSuccess(KoanSuiteResult result) { - assertEquals(0, state[0]); - state[0] = 1; - } - public void displayChart(KoanSuiteResult result) { - assertEquals(1, state[0]); - state[0] = 2; - } - public void displayPassingFailing(KoanSuiteResult result) { - assertEquals(2, state[0]); - state[0] = 3; - } - public void displayHeader(KoanSuiteResult result) { - assertEquals(3, state[0]); - state[0] = 4; - } - public void displayOneOrMoreFailure(KoanSuiteResult result) { - fail(); - } - }; - - KoanSuiteResult kr = new KoanResultBuilder().build(); - presenter.displayResult(kr); - assertEquals(4, state[0]); - } - - @Test - public void testForwardingOneOrMoreFails() throws Exception { - final int state[] = new int[]{0}; - AbstractSuitePresenter presenter = new AbstractSuitePresenter() { - public void displayOneOrMoreFailure(KoanSuiteResult result) { - assertEquals(0, state[0]); - state[0] = 1; - } - public void displayChart(KoanSuiteResult result) { - assertEquals(1, state[0]); - state[0] = 2; - } - public void displayPassingFailing(KoanSuiteResult result) { - assertEquals(2, state[0]); - state[0] = 3; - } - public void displayHeader(KoanSuiteResult result) { - assertEquals(3, state[0]); - state[0] = 4; - } - public void displayAllSuccess(KoanSuiteResult result) { - fail(); - } - }; - - KoanSuiteResult kr = new KoanResultBuilder().remainingCases(Arrays.asList(OneFailingKoan.class.getSimpleName()) - ).methodResult(new KoanMethodResult(KoanMethod.getInstance("", OneFailingKoan.class.getDeclaredMethods()[0]), - "", "")).build(); - presenter.displayResult(kr); - assertEquals(4, state[0]); - } -} diff --git a/lib/out/test/lib/data/com/sandwich/koan/suite/BlowUpOnLineEleven.java b/lib/out/test/lib/data/com/sandwich/koan/suite/BlowUpOnLineEleven.java deleted file mode 100644 index 3d6753c3..00000000 --- a/lib/out/test/lib/data/com/sandwich/koan/suite/BlowUpOnLineEleven.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.sandwich.koan.suite; - -import com.sandwich.koan.Koan; -import com.sandwich.koan.KoanIncompleteException; - -public class BlowUpOnLineEleven { - // gotta put it on line 11 thus the two spaces here - // - @Koan - public void blowUpOnLineEleven() { - throw new KoanIncompleteException(null); - } - -} diff --git a/lib/out/test/lib/data/com/sandwich/koan/suite/BlowUpOnLineTen.java b/lib/out/test/lib/data/com/sandwich/koan/suite/BlowUpOnLineTen.java deleted file mode 100644 index 331e54d3..00000000 --- a/lib/out/test/lib/data/com/sandwich/koan/suite/BlowUpOnLineTen.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.sandwich.koan.suite; - -import com.sandwich.koan.Koan; - -public class BlowUpOnLineTen extends BlowUpOnLineEleven { - // gotta blow up on line 10 thus the two spaces - // - @Koan - public void blowUpOnLineTen(){ - super.blowUpOnLineEleven(); - } -} diff --git a/lib/out/test/lib/data/com/sandwich/koan/suite/OneFailingKoan.java b/lib/out/test/lib/data/com/sandwich/koan/suite/OneFailingKoan.java deleted file mode 100644 index e16e4296..00000000 --- a/lib/out/test/lib/data/com/sandwich/koan/suite/OneFailingKoan.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.sandwich.koan.suite; - -import static com.sandwich.util.Assert.assertEquals; - -import com.sandwich.koan.Koan; - -public class OneFailingKoan { - @Koan - public void koanMethod() { - assertEquals(true, false); - } -} diff --git a/lib/out/test/lib/data/com/sandwich/koan/suite/OneFailingKoanDifferentName.java b/lib/out/test/lib/data/com/sandwich/koan/suite/OneFailingKoanDifferentName.java deleted file mode 100644 index 64666e0d..00000000 --- a/lib/out/test/lib/data/com/sandwich/koan/suite/OneFailingKoanDifferentName.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.sandwich.koan.suite; - -import static org.junit.Assert.assertEquals; - -import com.sandwich.koan.Koan; - -public class OneFailingKoanDifferentName extends OneFailingKoan { - @Koan - @Override - public void koanMethod() { - assertEquals(true, false); - } -} diff --git a/lib/out/test/lib/data/com/sandwich/koan/suite/OnePassingKoan.java b/lib/out/test/lib/data/com/sandwich/koan/suite/OnePassingKoan.java deleted file mode 100644 index 2db4f932..00000000 --- a/lib/out/test/lib/data/com/sandwich/koan/suite/OnePassingKoan.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.sandwich.koan.suite; - -import com.sandwich.koan.Koan; - -public class OnePassingKoan { - boolean[] invoked; - public OnePassingKoan(){ - invoked = new boolean[]{false}; - } - @Koan - public void koan() { - invoked[0] = true; - } -} diff --git a/lib/out/test/lib/data/com/sandwich/koan/suite/OnePassingKoanDifferentName.java b/lib/out/test/lib/data/com/sandwich/koan/suite/OnePassingKoanDifferentName.java deleted file mode 100644 index 5a76b430..00000000 --- a/lib/out/test/lib/data/com/sandwich/koan/suite/OnePassingKoanDifferentName.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.sandwich.koan.suite; - -public class OnePassingKoanDifferentName extends OnePassingKoan { - -} diff --git a/lib/out/test/lib/data/com/sandwich/util/KoanComparatorTest.java b/lib/out/test/lib/data/com/sandwich/util/KoanComparatorTest.java deleted file mode 100644 index 78473088..00000000 --- a/lib/out/test/lib/data/com/sandwich/util/KoanComparatorTest.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.sandwich.util; - -import static org.junit.Assert.assertSame; - -import java.lang.reflect.Method; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -import org.junit.Test; - -import com.sandwich.koan.Koan; -import com.sandwich.koan.KoanMethod; -import com.sandwich.koan.path.CommandLineTestCase; - -public class KoanComparatorTest extends CommandLineTestCase { - - @Test - public void testThatKomparatorBombsWhenNotFound() throws Exception { - Method m = new Object(){ - @SuppressWarnings("unused") @Koan public void someMethod(){} - }.getClass().getDeclaredMethod("someMethod"); - KoanComparator comparator = new KoanComparator("meh"); - try{ - comparator.compare(KoanMethod.getInstance("2",m), KoanMethod.getInstance("1",m)); - }catch(RuntimeException fileNotFound){} - } - - @Test - public void testComparatorRanksByOrder() throws Exception { - Class clazz = new Object(){ - @SuppressWarnings("unused") @Koan public void someMethodOne(){} - @SuppressWarnings("unused") @Koan public void someMethodTwo(){} - }.getClass(); - KoanMethod m1 = KoanMethod.getInstance("",clazz.getDeclaredMethod("someMethodOne")); - KoanMethod m2 = KoanMethod.getInstance("",clazz.getDeclaredMethod("someMethodTwo")); - List methods = Arrays.asList(m2,m1); - Collections.sort(methods, new KoanComparator("someMethodOne","someMethodTwo")); - assertSame(m1,methods.get(0)); - assertSame(m2,methods.get(1)); - } -} - diff --git a/lib/out/test/lib/data/com/sandwich/util/io/DirectoryManagerTest.java b/lib/out/test/lib/data/com/sandwich/util/io/DirectoryManagerTest.java deleted file mode 100644 index d97f5ef6..00000000 --- a/lib/out/test/lib/data/com/sandwich/util/io/DirectoryManagerTest.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.sandwich.util.io; - -import static org.junit.Assert.assertEquals; - -import org.junit.Test; - -import com.sandwich.koan.path.CommandLineTestCase; -import com.sandwich.util.io.directories.DirectoryManager; - - -public class DirectoryManagerTest extends CommandLineTestCase { - - @Test - public void testFileSeparatorInjection_happyPath() throws Exception { - assertEquals("/home/wilford/liberty", DirectoryManager.injectFileSystemSeparators( - "home", "wilford", "liberty")); - } - - @Test - public void testFileSeparatorInjection_separatorsAtBeginning() throws Exception { - assertEquals("/home/wilford/liberty", DirectoryManager.injectFileSystemSeparators( - "/home", "/wilford", "/liberty")); - } - - @Test - public void testFileSeparatorInjection_separatorsAtEnding() throws Exception { - assertEquals("/home/wilford/liberty", DirectoryManager.injectFileSystemSeparators( - "home/", "wilford/", "liberty/")); - } - - @Test - public void testFileSeparatorInjection_separatorsAtBeginningAndEnding() throws Exception { - assertEquals("/home/wilford/liberty", DirectoryManager.injectFileSystemSeparators( - "home/", "wilford/", "/liberty/")); - } - - @Test - public void testFileSeparatorInjection_separatorsInMiddle() throws Exception { - assertEquals("/home/wilford/liberty", DirectoryManager.injectFileSystemSeparators( - "home", "wilford/liberty")); - } -} diff --git a/lib/out/test/lib/data/com/sandwich/util/io/FileMonitorTest.java b/lib/out/test/lib/data/com/sandwich/util/io/FileMonitorTest.java deleted file mode 100644 index 2f3d10e9..00000000 --- a/lib/out/test/lib/data/com/sandwich/util/io/FileMonitorTest.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.sandwich.util.io; - -import org.junit.After; -import org.junit.Before; - -import com.sandwich.koan.constant.KoanConstants; - - -public class FileMonitorTest { - - String SAMPLE_DIR = FileUtils.makeAbsoluteRelativeTo(KoanConstants.PROJ_TESTS_FOLDER); - FileMonitor monitor; - - @Before - public void createInstance() throws Exception{ - monitor = FileMonitorFactory.getInstance(SAMPLE_DIR); - } - - @After - public void destroyInstance(){ - monitor.close(); - } - -} From c1b60a23578f8b203b7a9d262c982d1e2136e280 Mon Sep 17 00:00:00 2001 From: Mat Bentley Date: Wed, 12 Jul 2017 00:28:45 -0400 Subject: [PATCH 09/30] closing #73 --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 61364ad1..a0519e70 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,7 @@ Developing a Koan: ================== * Follow any of the existing koans as an example to create a new class with koan methods (indicated by the @Koan annotation, they're public and specify no arguments) * Define the order the koan suite (if it's new) will run in the koans/app/config/PathToEnlightenment.xml file +* [Override the lesson text](https://github.com/matyb/java-koans/blob/master/koans/app/config/i18n/messages_en.properties#L1) when it fails (default is expected 'X' found 'Y') * Optionally you may use dynamic content in your lesson, examples are located in the XmlVariableInjector class (and Test) and the AboutKoans.java file Something's wrong: From 3cbe8fcdf585096030de3cd6eff3b24838327925 Mon Sep 17 00:00:00 2001 From: matyb Date: Wed, 12 Jul 2017 00:10:52 -0400 Subject: [PATCH 10/30] This closes #72 - ignore idea's temporary files --- .gitignore | 4 +- koans/app/config/config.properties | 1 + koans/app/lib/koans.jar | Bin 97842 -> 98681 bytes lib/build.gradle | 2 +- .../sandwich/koan/ApplicationSettings.java | 4 + .../sandwich/util/io/ExistingFileAction.java | 4 + .../com/sandwich/util/io/FileMonitor.java | 4 +- .../com/sandwich/util/io/FileOperation.java | 45 ++++++-- .../sandwich/util/io/ForEachFileAction.java | 4 + .../java/com/sandwich/koan/TestUtilsTest.java | 7 +- .../sandwich/util/io/FileOperationTest.java | 96 ++++++++++++++++++ 11 files changed, 156 insertions(+), 15 deletions(-) create mode 100644 lib/src/test/java/com/sandwich/util/io/FileOperationTest.java diff --git a/.gitignore b/.gitignore index 531f7b68..5392375c 100644 --- a/.gitignore +++ b/.gitignore @@ -2,8 +2,7 @@ */bin/* .metadata bin/* -lib/build/bin/* -lib/build/reports/* +lib/build lib/out koans/data koans/data* @@ -17,3 +16,4 @@ lib/file-compiler/bin *.iml *.ipr *.iws +.idea diff --git a/koans/app/config/config.properties b/koans/app/config/config.properties index 50b21fde..ed64a7eb 100644 --- a/koans/app/config/config.properties +++ b/koans/app/config/config.properties @@ -1,4 +1,5 @@ compile_timeout_in_ms=5000 +ignore_from_monitoring=.*\\.idea debug=false exit_character=Q enable_encouragement=false diff --git a/koans/app/lib/koans.jar b/koans/app/lib/koans.jar index efeddec998f34efe29cf497a33d065fc11825b1b..492231ba7b028f4b27ba5685bfff1c4dd785fe63 100644 GIT binary patch delta 14902 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 listeners = new Vector(); @@ -69,7 +71,7 @@ synchronized void notifyListeners(){ Map getFilesystemHashes() throws IOException { final HashMap fileHashes = new HashMap(); - new ForEachFileAction(){ + new ForEachFileAction(ApplicationSettings.getMonitorIgnorePattern()){ public void onFile(File src) throws IOException { fileHashes.put(src.getAbsolutePath(), src.lastModified()); } diff --git a/lib/src/main/java/com/sandwich/util/io/FileOperation.java b/lib/src/main/java/com/sandwich/util/io/FileOperation.java index c6e2e167..1cea8894 100644 --- a/lib/src/main/java/com/sandwich/util/io/FileOperation.java +++ b/lib/src/main/java/com/sandwich/util/io/FileOperation.java @@ -2,19 +2,48 @@ import java.io.File; import java.io.IOException; +import java.util.Arrays; +import java.util.List; public abstract class FileOperation implements FileAction { + private List ignoredPaths; + + public FileOperation(String... ignoredPaths){ + this(Arrays.asList(ignoredPaths)); + } + + public FileOperation(List ignoredPaths){ + this.ignoredPaths = ignoredPaths; + } + public void operate(File file) throws IOException { - if(file == null){ - onNull(file); - }else if(!file.exists()){ - onNew(file); - }else if(file.isDirectory()){ - onDirectory(file); - }else{ - onFile(file); + if(!isIgnored(file)){ + if(file == null){ + onNull(file); + }else if(!file.exists()){ + onNew(file); + }else if(file.isDirectory()){ + onDirectory(file); + }else{ + onFile(file); + } + } + } + + boolean isIgnored(File file){ + boolean ignore = false; + while(file != null){ + String end = file.getAbsolutePath().substring(file.getAbsolutePath().lastIndexOf(System.getProperty("file.separator")) + 1); + for(String pathToIgnore: ignoredPaths){ + ignore = end.matches(pathToIgnore); + if(ignore){ + return true; + } + } + file = file.getParentFile(); } + return ignore; } } diff --git a/lib/src/main/java/com/sandwich/util/io/ForEachFileAction.java b/lib/src/main/java/com/sandwich/util/io/ForEachFileAction.java index 44499b77..cfd04179 100644 --- a/lib/src/main/java/com/sandwich/util/io/ForEachFileAction.java +++ b/lib/src/main/java/com/sandwich/util/io/ForEachFileAction.java @@ -5,6 +5,10 @@ public abstract class ForEachFileAction extends ExistingFileAction { + public ForEachFileAction(String... strings) { + super(strings); + } + public void onDirectory(File dir) throws IOException { for (String fileName : dir.list()) { operate(new File(dir, fileName)); diff --git a/lib/src/test/java/com/sandwich/koan/TestUtilsTest.java b/lib/src/test/java/com/sandwich/koan/TestUtilsTest.java index ad047315..19ccd88a 100755 --- a/lib/src/test/java/com/sandwich/koan/TestUtilsTest.java +++ b/lib/src/test/java/com/sandwich/koan/TestUtilsTest.java @@ -4,6 +4,7 @@ import static org.junit.Assert.fail; import org.easymock.EasyMock; +import org.junit.Ignore; import org.junit.Test; import com.sandwich.koan.TestUtils.ArgRunner; @@ -146,7 +147,7 @@ public int hashCode(){ } } - @Test(expected=AssertionError.class, timeout=1000) + @Test(expected=AssertionError.class, timeout=2000) public void testEqualsConcurrency_concurrentAccessFails() throws Exception { TestUtils.doSimultaneouslyAndRepetitively(new TwoObjectAssertion() { public void assertOn(String msg, Object o0, Object o1) { @@ -197,7 +198,7 @@ public void run() { }); } - @Test + @Test @Ignore // disk/os access causing random failures at this low a deviation in timing public void testEqualsConcurrency() throws Exception { TestUtils.doSimultaneouslyAndRepetitively(new TwoObjectAssertion() { public void assertOn(String msg, Object o0, Object o1) { @@ -218,7 +219,7 @@ public void run() { }); } - @Test + @Test @Ignore // disk/os access causing random failures at this low a deviation in timing public void testEqualsConcurrency_II() throws Exception { TestUtils.doSimultaneouslyAndRepetitively(new TwoObjectAssertion() { public void assertOn(String msg, Object o0, Object o1) { diff --git a/lib/src/test/java/com/sandwich/util/io/FileOperationTest.java b/lib/src/test/java/com/sandwich/util/io/FileOperationTest.java new file mode 100644 index 00000000..f24a8b5a --- /dev/null +++ b/lib/src/test/java/com/sandwich/util/io/FileOperationTest.java @@ -0,0 +1,96 @@ +package com.sandwich.util.io; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.io.IOException; + +import org.junit.Test; + +import com.sandwich.util.io.directories.DirectoryManager; + +public class FileOperationTest { + + @Test + public void givenAnExistingFileNoFilterIsNotIgnored() throws Exception { + assertFalse(new FileOperation() { + public void onDirectory(File dir) throws IOException {} + public void onFile(File file) throws IOException {} + public void onNull(File nullFile) throws IOException {} + public void onNew(File newFile) throws IOException {} + }.isIgnored(new File(DirectoryManager.getBinDir()))); + } + + @Test + public void givenAnExistingFileWithNonMatchingFilterIsNotIgnored() throws Exception { + assertFalse(new FileOperation("nowayimpartofafoldername") { + public void onDirectory(File dir) throws IOException {} + public void onFile(File file) throws IOException {} + public void onNull(File nullFile) throws IOException {} + public void onNew(File newFile) throws IOException {} + }.isIgnored(new File(DirectoryManager.getBinDir()))); + } + + @Test + public void givenAnExistingFileWithMatchingFilterIsIgnored() throws Exception { + assertTrue(new FileOperation("bin") { + public void onDirectory(File dir) throws IOException {} + public void onFile(File file) throws IOException {} + public void onNull(File nullFile) throws IOException {} + public void onNew(File newFile) throws IOException {} + }.isIgnored(new File(DirectoryManager.getBinDir()))); + } + + @Test + public void givenAnExistingFileWithFilterMatchingOnParentFolderIsIgnored() throws Exception { + assertTrue(new FileOperation("app") { + public void onDirectory(File dir) throws IOException {} + public void onFile(File file) throws IOException {} + public void onNull(File nullFile) throws IOException {} + public void onNew(File newFile) throws IOException {} + }.isIgnored(new File(DirectoryManager.getBinDir()))); + } + + @Test + public void givenAnExistingFileWithPartiallyMatchingFilterIsNotIgnored() throws Exception { + assertFalse(new FileOperation("bi") { + public void onDirectory(File dir) throws IOException {} + public void onFile(File file) throws IOException {} + public void onNull(File nullFile) throws IOException {} + public void onNew(File newFile) throws IOException {} + }.isIgnored(new File(DirectoryManager.getBinDir()))); + } + + @Test + public void givenAnExistingFileWithRegexMatchingFilterIsIgnored() throws Exception { + assertTrue(new FileOperation("b.n") { + public void onDirectory(File dir) throws IOException {} + public void onFile(File file) throws IOException {} + public void onNull(File nullFile) throws IOException {} + public void onNew(File newFile) throws IOException {} + }.isIgnored(new File(DirectoryManager.getBinDir()))); + } + + @Test + public void givenAnExistingFileWithRegexMatchingFilterIsIgnored_compliment() throws Exception { + assertFalse(new FileOperation("nowayimpart..afoldername") { + public void onDirectory(File dir) throws IOException {} + public void onFile(File file) throws IOException {} + public void onNull(File nullFile) throws IOException {} + public void onNew(File newFile) throws IOException {} + }.isIgnored(new File(DirectoryManager.getBinDir()))); + } + + @Test + public void givenIntellijFoldersSpecificallyFileInIdeaFolderAreIgnored() throws Exception { + // not sure why idea ide's would be a problem... TODO: testing this specifically smells like a bigger problem... + assertTrue(new FileOperation(".*\\.idea") { + public void onDirectory(File dir) throws IOException {} + public void onFile(File file) throws IOException {} + public void onNull(File nullFile) throws IOException {} + public void onNew(File newFile) throws IOException {} + }.isIgnored(new File("/java-dojo/labs/01-koans/java-koans\\koans.idea/workspace.xml___jb_old___"))); + } + +} From fbce46c8f301bd4434fd91d663b88d9d9be4146f Mon Sep 17 00:00:00 2001 From: Mat Bentley Date: Wed, 12 Jul 2017 01:17:12 -0400 Subject: [PATCH 11/30] Fixing formatting of build status --- koans/README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/koans/README.md b/koans/README.md index 657fe638..45fa441e 100755 --- a/koans/README.md +++ b/koans/README.md @@ -1,4 +1,6 @@ -#Java Koans [![Build Status](https://travis-ci.org/matyb/java-koans.png?branch=master)](https://travis-ci.org/matyb/java-koans) +#Java Koans + +[![Build Status](https://travis-ci.org/matyb/java-koans.png?branch=master)](https://travis-ci.org/matyb/java-koans) ## Quick Start * Download and unarchive the contents of the most recent java-koans in development from: From 79c0467a815b0d366acdc6b54857020a516791d3 Mon Sep 17 00:00:00 2001 From: Mat Bentley Date: Wed, 12 Jul 2017 01:17:30 -0400 Subject: [PATCH 12/30] Update README.md --- koans/README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/koans/README.md b/koans/README.md index 45fa441e..cd09a361 100755 --- a/koans/README.md +++ b/koans/README.md @@ -1,5 +1,3 @@ -#Java Koans - [![Build Status](https://travis-ci.org/matyb/java-koans.png?branch=master)](https://travis-ci.org/matyb/java-koans) ## Quick Start From 69f791bb326626da3c0ba84bd612646e80ec0c0f Mon Sep 17 00:00:00 2001 From: Mat Bentley Date: Wed, 12 Jul 2017 01:17:53 -0400 Subject: [PATCH 13/30] Update README.md --- koans/README.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/koans/README.md b/koans/README.md index cd09a361..044f12ce 100755 --- a/koans/README.md +++ b/koans/README.md @@ -1,9 +1,7 @@ -[![Build Status](https://travis-ci.org/matyb/java-koans.png?branch=master)](https://travis-ci.org/matyb/java-koans) - ## Quick Start * Download and unarchive the contents of the most recent java-koans in development from: https://github.com/matyb/java-koans/archive/master.zip -* Open a console (termina) and cd to the directory you unarchived: +* Open a console (terminal) and cd to the directory you unarchived: ```cd ``` * Change directory to the koans directory: ```cd koans``` * To export koans to run below command and open in IDE: From 1fda3eab8f05c4af07a93e4ccf53be1ccdc86b66 Mon Sep 17 00:00:00 2001 From: Mat Bentley Date: Sat, 7 Oct 2017 20:38:29 -0400 Subject: [PATCH 14/30] Update .travis.yml --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 2ebee51c..5472f8cc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,2 +1,3 @@ language: java +before_script: chmod +x gradlew script: "./lib/gradlew -b lib/build.gradle test" From 35a02566259e68e6c5d6524496c4cd00564037fe Mon Sep 17 00:00:00 2001 From: Mat Bentley Date: Sat, 7 Oct 2017 20:40:12 -0400 Subject: [PATCH 15/30] Update .travis.yml --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 5472f8cc..2ebee51c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,3 +1,2 @@ language: java -before_script: chmod +x gradlew script: "./lib/gradlew -b lib/build.gradle test" From a91241492d3b1b903e2fd1708369048130c73959 Mon Sep 17 00:00:00 2001 From: Mat Bentley Date: Wed, 7 Feb 2018 00:54:45 -0500 Subject: [PATCH 16/30] Update AboutConditionals.java maybe it's convoluted, but this should close #77 --- koans/src/beginner/AboutConditionals.java | 37 +++++++++++++++++++---- 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/koans/src/beginner/AboutConditionals.java b/koans/src/beginner/AboutConditionals.java index f7883dfb..81f6a7a5 100644 --- a/koans/src/beginner/AboutConditionals.java +++ b/koans/src/beginner/AboutConditionals.java @@ -147,11 +147,36 @@ public void switchStatementSwitchValues() { @Koan public void shortCircuit() { - int i = 1; - int a = 6; - // Why did we use a variable here? - // What happens if you replace 'a' with '6' below? - if ((a < 9) || (++i < 8)) i = i + 1; - assertEquals(i, __); + counter trueCount = new Counter(true); + counter falseCount = new Counter(false); + String x = "Hai"; + if (trueCount.count() || falseCount.count()) { + x = "kthxbai"; + } + assertEquals(x, __); + assertEquals(trueCount.count, __); + assertEquals(falseCount.count, __); + } + + @Koan + public void bitwise() { + counter trueCount = new Counter(true); + counter falseCount = new Counter(false); + String x = "Hai"; + if (trueCount.count() | falseCount.count()) { + x = "kthxbai"; + } + assertEquals(x, __); + assertEquals(trueCount.count, __); + assertEquals(falseCount.count, __); + } + + class Counter { + boolean returnValue; + int count = 0; + boolean count() { + count++; + return returnValue; + } } } From 896765775d4db5ef75149080c8097cec6d640ef1 Mon Sep 17 00:00:00 2001 From: Mat Bentley Date: Wed, 7 Feb 2018 11:12:29 -0500 Subject: [PATCH 17/30] compile error, editing on github + phone @LifeIsALesson good catch --- koans/src/beginner/AboutConditionals.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/koans/src/beginner/AboutConditionals.java b/koans/src/beginner/AboutConditionals.java index 81f6a7a5..1fda562c 100644 --- a/koans/src/beginner/AboutConditionals.java +++ b/koans/src/beginner/AboutConditionals.java @@ -174,6 +174,9 @@ public void bitwise() { class Counter { boolean returnValue; int count = 0; + Counter(boolean returnValue) { + this.returnValue = returnValue; + } boolean count() { count++; return returnValue; From e88011d61115b2357c072e44014a27e7361ed643 Mon Sep 17 00:00:00 2001 From: Mat Bentley Date: Wed, 7 Feb 2018 11:24:50 -0500 Subject: [PATCH 18/30] Update AboutConditionals.java --- koans/src/beginner/AboutConditionals.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/koans/src/beginner/AboutConditionals.java b/koans/src/beginner/AboutConditionals.java index 1fda562c..f97a9bc9 100644 --- a/koans/src/beginner/AboutConditionals.java +++ b/koans/src/beginner/AboutConditionals.java @@ -147,8 +147,8 @@ public void switchStatementSwitchValues() { @Koan public void shortCircuit() { - counter trueCount = new Counter(true); - counter falseCount = new Counter(false); + Counter trueCount = new Counter(true); + Counter falseCount = new Counter(false); String x = "Hai"; if (trueCount.count() || falseCount.count()) { x = "kthxbai"; @@ -160,8 +160,8 @@ public void shortCircuit() { @Koan public void bitwise() { - counter trueCount = new Counter(true); - counter falseCount = new Counter(false); + Counter trueCount = new Counter(true); + Counter falseCount = new Counter(false); String x = "Hai"; if (trueCount.count() | falseCount.count()) { x = "kthxbai"; From 56e03617011a5d6f0e74514adbfe45e4845f9390 Mon Sep 17 00:00:00 2001 From: Mat Bentley Date: Wed, 7 Feb 2018 13:46:39 -0500 Subject: [PATCH 19/30] Update AppReadinessForDeploymentTest.java --- .../com/sandwich/koan/runner/AppReadinessForDeploymentTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/test/java/com/sandwich/koan/runner/AppReadinessForDeploymentTest.java b/lib/src/test/java/com/sandwich/koan/runner/AppReadinessForDeploymentTest.java index 581b542e..4ae4d80f 100755 --- a/lib/src/test/java/com/sandwich/koan/runner/AppReadinessForDeploymentTest.java +++ b/lib/src/test/java/com/sandwich/koan/runner/AppReadinessForDeploymentTest.java @@ -165,7 +165,7 @@ public void testLineExceptionIsThrownAtIsHintedAtEvenIfThrownFromSuperClass() th assertSystemOutDoesntContain("Line 10"); } - @Test + @Test @Ignore /** Passes locally, fails in CI? */ public void testWarningFromPlacingExpectationOnWrongSide() throws Throwable { final String[] message = new String[1]; stubAllKoans(Arrays.asList(new WrongExpectationOrderKoan())); From b05a5b35912afae6258bc6479deb9b23724b4ff1 Mon Sep 17 00:00:00 2001 From: "Kevin J. Chase" Date: Sat, 10 Feb 2018 22:04:34 -0500 Subject: [PATCH 20/30] Possible fix for Issue 79 - use of assertNotSame. [Issue 79](https://github.com/matyb/java-koans/issues/79) questions the need for the `AboutAssertions.assertNotSameInstance` method, specifically the `aboutNotSame` assertion. This is my attempt to make both the positive assertion in `assertSameInstance` and the negative assertion more clear (if much longer) by making them more similar, and by giving each an example of how equality is different from "sameness". I'm still not sure it justifies the existence of `aboutNotSame`, which is used literally nowhere else. --- koans/src/beginner/AboutAssertions.java | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) mode change 100755 => 100644 koans/src/beginner/AboutAssertions.java diff --git a/koans/src/beginner/AboutAssertions.java b/koans/src/beginner/AboutAssertions.java old mode 100755 new mode 100644 index 818662e9..a83ba2ae --- a/koans/src/beginner/AboutAssertions.java +++ b/koans/src/beginner/AboutAssertions.java @@ -62,17 +62,25 @@ public void assertEqualsWithDescriptiveMessage() { @Koan public void assertSameInstance() { - // Just because something is equal doesn't mean that it is the same. - // It's only the same if the reference is the same. - Object same = new Integer(1); - Object sameReference = __; - assertSame(same, sameReference); + Integer original = new Integer(1); + Integer same = original; + Integer different = new Integer(1); + // These are both equal to the original... + assertEquals(original, same); + assertEquals(original, different); + // ...but only one refers to the same instance as the original. + assertSame(original, __); } @Koan public void assertNotSameInstance() { - Integer same = new Integer(1); - Integer sameReference = same; - assertNotSame(same, sameReference); + Integer original = new Integer(1); + Integer same = original; + Integer different = new Integer(1); + // These are both equal to the original... + assertEquals(original, same); + assertEquals(original, different); + // ...but only one of them refers to a different instance. + assertNotSame(original, same); // We want equal, but _not_ the same. } } From 4be9929d5d9a1e7c1bc5607f47c58b9e887eca3e Mon Sep 17 00:00:00 2001 From: matyb Date: Wed, 21 Feb 2018 21:57:42 -0500 Subject: [PATCH 21/30] dockerizing build verification, adding back ignored integration tests --- .travis.yml | 14 +++++++-- docker/Dockerfile | 18 +++++++++++ docker/spec/Dockerfile_spec.rb | 30 +++++++++++++++++++ .../runner/AppReadinessForDeploymentTest.java | 7 ++--- 4 files changed, 63 insertions(+), 6 deletions(-) create mode 100644 docker/Dockerfile create mode 100644 docker/spec/Dockerfile_spec.rb diff --git a/.travis.yml b/.travis.yml index 2ebee51c..10a793e9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,2 +1,12 @@ -language: java -script: "./lib/gradlew -b lib/build.gradle test" +sudo: required + +language: ruby + +services: + - docker + +before_install: + - docker build -t java/koans . + +script: + - docker run java/koans /bin/bash -c "git clone https://github.com/matyb/java-koans && gradle -p java-koans/lib buildApp" diff --git a/docker/Dockerfile b/docker/Dockerfile new file mode 100644 index 00000000..f7c564aa --- /dev/null +++ b/docker/Dockerfile @@ -0,0 +1,18 @@ +FROM centos:7 +MAINTAINER Mat Bentley + +ENV JAVA_VERSION 1.8.0 +ENV GRADLE_VERSION 3.4.1 + +# install wget, git, curl, jdk, which +RUN yum remove -y java &&\ + yum install -y wget git curl unzip java-$JAVA_VERSION-openjdk-devel which + +# install gradle +RUN wget https://services.gradle.org/distributions/gradle-$GRADLE_VERSION-bin.zip &&\ + mkdir -p /etc/alternatives/gradle &&\ + unzip -d /etc/alternatives/gradle gradle-$GRADLE_VERSION-bin.zip &&\ + ln -s /etc/alternatives/gradle/gradle-$GRADLE_VERSION /opt/gradle + +ENV PATH $PATH:/opt/gradle/bin +RUN JAVA_HOME=$(readlink $(readlink `which java`) | gawk '$0=gensub(/\/jre\/bin\/java/,"",1)') diff --git a/docker/spec/Dockerfile_spec.rb b/docker/spec/Dockerfile_spec.rb new file mode 100644 index 00000000..85bc02b8 --- /dev/null +++ b/docker/spec/Dockerfile_spec.rb @@ -0,0 +1,30 @@ +#! /usr/bin/ruby + +require "serverspec" +require "docker" + +describe "Dockerfile" do + before(:all) do + image = Docker::Image.build_from_dir('.') + + set :os, family: :redhat + set :backend, :docker + set :docker_image, image.id + end + + it "has jdk8 installed" do + expect(command("javac -version").stderr).to include(" 1.8.") + end + + it "has gradle installed" do + expect(command("gradle -version").stdout).to include("Build time") + end + + it "can build app" do + output = command("git clone https://github.com/matyb/java-koans && gradle -p java-koans/lib buildApp").stdout + expect(output).to include(":test\n") + expect(output).to include("BUILD SUCCESSFUL") + end + +end + diff --git a/lib/src/test/java/com/sandwich/koan/runner/AppReadinessForDeploymentTest.java b/lib/src/test/java/com/sandwich/koan/runner/AppReadinessForDeploymentTest.java index 4ae4d80f..ae156b72 100755 --- a/lib/src/test/java/com/sandwich/koan/runner/AppReadinessForDeploymentTest.java +++ b/lib/src/test/java/com/sandwich/koan/runner/AppReadinessForDeploymentTest.java @@ -15,7 +15,6 @@ import org.junit.After; import org.junit.Before; import org.junit.Test; -import org.junit.Ignore; import com.sandwich.koan.KoanMethod; import com.sandwich.koan.cmdline.CommandLineArgumentBuilder; @@ -94,7 +93,7 @@ public void testGetKoans() throws Exception { KoanMethod.getInstance(entry.getValue().get("koan")).getMethod().toString()); } - @Test @Ignore /** Ensures that koans are ready for packaging & distribution */ + @Test public void testKoanSuiteRunner_firstKoanFail() throws Exception { final KoanSuiteResult[] result = new KoanSuiteResult[]{null}; stubPresenter(new SuitePresenter(){ @@ -116,7 +115,7 @@ public void run(){ assertEquals(result[0].getFailingCase(), firstSuiteClassRan.substring(firstSuiteClassRan.lastIndexOf(".") + 1)); } - @Test @Ignore /** Ensures that koans are ready for packaging & distribution */ + @Test public void testKoanSuiteRunner_allKoansFail() throws Exception { setRealPath(); final KoanSuiteResult[] result = new KoanSuiteResult[]{null}; @@ -165,7 +164,7 @@ public void testLineExceptionIsThrownAtIsHintedAtEvenIfThrownFromSuperClass() th assertSystemOutDoesntContain("Line 10"); } - @Test @Ignore /** Passes locally, fails in CI? */ + @Test public void testWarningFromPlacingExpectationOnWrongSide() throws Throwable { final String[] message = new String[1]; stubAllKoans(Arrays.asList(new WrongExpectationOrderKoan())); From 5856f75997d2219ef94f2c38617e87a65e3762b6 Mon Sep 17 00:00:00 2001 From: matyb Date: Wed, 21 Feb 2018 22:02:09 -0500 Subject: [PATCH 22/30] pathed Dockerfile wrong --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 10a793e9..705ea2eb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,7 +6,7 @@ services: - docker before_install: - - docker build -t java/koans . + - docker build -t java/koans docker script: - docker run java/koans /bin/bash -c "git clone https://github.com/matyb/java-koans && gradle -p java-koans/lib buildApp" From 8023ff1b4bf7f86c1321c92c9ed9094f8fea2f90 Mon Sep 17 00:00:00 2001 From: matyb Date: Wed, 21 Mar 2018 23:46:22 -0400 Subject: [PATCH 23/30] Revert "removed unnecessary TODO; enriched one koan" This reverts commit 609e479c7a54f6d5354518a81f54df4170ddf809. --- koans/src/beginner/AboutObjects.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/koans/src/beginner/AboutObjects.java b/koans/src/beginner/AboutObjects.java index df66e647..b93e5e28 100755 --- a/koans/src/beginner/AboutObjects.java +++ b/koans/src/beginner/AboutObjects.java @@ -29,6 +29,7 @@ class Foo { @Koan public void objectToString() { Object object = new Object(); + // TODO: Why is it best practice to ALWAYS override toString? String expectedToString = MessageFormat.format("{0}@{1}", Object.class.getName(), Integer.toHexString(object.hashCode())); assertEquals(expectedToString, __); // hint: object.toString() } @@ -48,9 +49,7 @@ public String toString() { @Koan public void toStringIsTestedForNullWhenInvokedImplicitly() { String string = "string"; - Integer i = new Integer(128); - Short s = new Short((short) 15); - assertEquals(string + " " + i + " " + s, __); + assertEquals(string + null, __); } private Class[] getAncestors(Object object) { From 1cd8c1ec7a7e32285791b0d9e3a6ebb7cab408e4 Mon Sep 17 00:00:00 2001 From: "Kevin J. Chase" Date: Thu, 22 Mar 2018 00:17:26 -0400 Subject: [PATCH 24/30] Restored nestedIfsWithoutCurlysAreReallyMisleading ...and ifAsIntended. Closes #84 (I hope). Removing the curly braces makes the dangling else actually, um, dangle. The conditional is once again misleading, as intended. Also, changed the conditional(s) and variables in ifAsIntended to match those in nestedIfsWithoutCurlysAreReallyMisleading, so there is no question that the curly braces caused the as-intended result. --- koans/src/beginner/AboutConditionals.java | 24 +++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/koans/src/beginner/AboutConditionals.java b/koans/src/beginner/AboutConditionals.java index f97a9bc9..706ef725 100644 --- a/koans/src/beginner/AboutConditionals.java +++ b/koans/src/beginner/AboutConditionals.java @@ -52,15 +52,31 @@ public void nestedIfsWithoutCurlysAreReallyMisleading() { boolean secretBoolean = false; boolean otherBooleanCondition = true; // Ifs without curly braces are ugly and not recommended but still valid: + if (secretBoolean) + x++; + if (otherBooleanCondition) + x = 10; + else + x--; + // Where does this else belong to!? + assertEquals(x, __); + } + + @Koan + public void ifAsIntended() { + int x = 1; + boolean secretBoolean = false; + boolean otherBooleanCondition = true; if (secretBoolean) { x++; - } - if (otherBooleanCondition) { - x = 10; + if (otherBooleanCondition) { + x = 10; + } } else { x--; } - // Where does this else belong to!? + // There are different opinions on where the curly braces go... + // But as long as you put them here. You avoid problems as seen above. assertEquals(x, __); } From bb1a863cd060a7582edc66190e79667a8dccdebd Mon Sep 17 00:00:00 2001 From: "Kevin J. Chase" Date: Thu, 22 Mar 2018 22:30:38 -0400 Subject: [PATCH 25/30] Focus comments on the "dangling else" problem. --- koans/src/beginner/AboutConditionals.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/koans/src/beginner/AboutConditionals.java b/koans/src/beginner/AboutConditionals.java index 706ef725..ca3d3fd6 100644 --- a/koans/src/beginner/AboutConditionals.java +++ b/koans/src/beginner/AboutConditionals.java @@ -47,18 +47,17 @@ public void basicIfElseIfElse() { @Koan public void nestedIfsWithoutCurlysAreReallyMisleading() { - // Why are these ugly you ask? Well, try for yourself int x = 1; boolean secretBoolean = false; boolean otherBooleanCondition = true; - // Ifs without curly braces are ugly and not recommended but still valid: + // Curly braces after an "if" or "else" are not required... if (secretBoolean) x++; if (otherBooleanCondition) x = 10; else x--; - // Where does this else belong to!? + // ...but they are recommended. assertEquals(x, __); } @@ -67,6 +66,8 @@ public void ifAsIntended() { int x = 1; boolean secretBoolean = false; boolean otherBooleanCondition = true; + // Adding curly braces avoids the "dangling else" problem seen + // above. if (secretBoolean) { x++; if (otherBooleanCondition) { @@ -75,8 +76,6 @@ public void ifAsIntended() { } else { x--; } - // There are different opinions on where the curly braces go... - // But as long as you put them here. You avoid problems as seen above. assertEquals(x, __); } From d443efae6093b8cfbc89258c137be2fdadcfd18b Mon Sep 17 00:00:00 2001 From: matyb Date: Thu, 14 Feb 2019 21:39:52 -0500 Subject: [PATCH 26/30] fixes #33 --- koans/app/config/config.properties | 2 +- .../com/sandwich/util/io/StreamUtils.java | 5 +++- .../com/sandwich/util/KoanComparatorTest.java | 30 +++++++++---------- 3 files changed, 20 insertions(+), 17 deletions(-) diff --git a/koans/app/config/config.properties b/koans/app/config/config.properties index ed64a7eb..5d078c19 100644 --- a/koans/app/config/config.properties +++ b/koans/app/config/config.properties @@ -1,5 +1,5 @@ compile_timeout_in_ms=5000 -ignore_from_monitoring=.*\\.idea +ignore_from_monitoring=(.*\\.idea|^\\.#.*\\..*|^#.*\\..*) debug=false exit_character=Q enable_encouragement=false diff --git a/lib/src/main/java/com/sandwich/util/io/StreamUtils.java b/lib/src/main/java/com/sandwich/util/io/StreamUtils.java index 3c562893..1038ce97 100644 --- a/lib/src/main/java/com/sandwich/util/io/StreamUtils.java +++ b/lib/src/main/java/com/sandwich/util/io/StreamUtils.java @@ -7,10 +7,13 @@ public class StreamUtils { public static String convertStreamToString(InputStream stream) { + Scanner scanner = new Scanner(stream); try { - return new Scanner(stream).useDelimiter("\\A").next(); + return scanner.useDelimiter("\\A").next(); } catch (NoSuchElementException e) { return ""; + } finally { + scanner.close(); } } diff --git a/lib/src/test/java/com/sandwich/util/KoanComparatorTest.java b/lib/src/test/java/com/sandwich/util/KoanComparatorTest.java index 1e17c875..8b709d23 100755 --- a/lib/src/test/java/com/sandwich/util/KoanComparatorTest.java +++ b/lib/src/test/java/com/sandwich/util/KoanComparatorTest.java @@ -44,20 +44,20 @@ public void testComparatorRanksByOrder() throws Exception { assertSame(m2,methods.get(1)); } - @Test - public void testVariableNamesArentConfusedAsKoanMethodsWhenSorting() throws Exception { - Class clazz = new Object(){ - String foo; - @Koan public void bar(){} - @Koan public void foo(){} - }.getClass(); - KoanMethod m1 = KoanMethod.getInstance("", clazz.getDeclaredMethod("bar")); - KoanMethod m2 = KoanMethod.getInstance("", clazz.getDeclaredMethod("foo")); - List methods = Arrays.asList(m2,m1); - Collections.sort(methods, new KoanComparator()); - assertSame(m1,methods.get(0)); - assertSame(m2,methods.get(1)); - } - + @Test + public void testVariableNamesArentConfusedAsKoanMethodsWhenSorting() throws Exception { + Class clazz = new Object(){ + @SuppressWarnings("unused") + String foo; + @Koan public void bar(){} + @Koan public void foo(){} + }.getClass(); + KoanMethod m1 = KoanMethod.getInstance("", clazz.getDeclaredMethod("bar")); + KoanMethod m2 = KoanMethod.getInstance("", clazz.getDeclaredMethod("foo")); + List methods = Arrays.asList(m2,m1); + Collections.sort(methods, new KoanComparator()); + assertSame(m1,methods.get(0)); + assertSame(m2,methods.get(1)); + } } From 364e65c487ac43f92ecf7a41ac2ae0957ee7be22 Mon Sep 17 00:00:00 2001 From: matyb Date: Thu, 25 Jul 2019 22:17:46 -0700 Subject: [PATCH 27/30] Fixes #96 --- koans/src/intermediate/AboutFileIO.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/koans/src/intermediate/AboutFileIO.java b/koans/src/intermediate/AboutFileIO.java index 4649ebc9..3fb98e7d 100644 --- a/koans/src/intermediate/AboutFileIO.java +++ b/koans/src/intermediate/AboutFileIO.java @@ -12,7 +12,7 @@ public class AboutFileIO { @Koan public void fileObjectDoesntCreateFile() { - File f = new File("foo.txt"); + File f = new File("i-never.exist"); assertEquals(f.exists(), __); } @@ -29,11 +29,12 @@ public void fileCreationAndDeletion() throws IOException { public void basicFileWritingAndReading() throws IOException { File file = new File("file.txt"); FileWriter fw = new FileWriter(file); - fw.write("First line\nSecond line"); + String data = "First line\nSecond line"; + fw.write(data); fw.flush(); fw.close(); - char[] in = new char[50]; + char[] in = new char[data.length()]; int size = 0; FileReader fr = new FileReader(file); size = fr.read(in); From bcbb23675fd0654d80249942d81bcaa1253f8dfa Mon Sep 17 00:00:00 2001 From: matyb Date: Thu, 25 Jul 2019 22:44:17 -0700 Subject: [PATCH 28/30] Fixes #95 --- koans/src/java8/AboutStreams.java | 7 ------- 1 file changed, 7 deletions(-) diff --git a/koans/src/java8/AboutStreams.java b/koans/src/java8/AboutStreams.java index 42e7b2db..ee0c90e4 100644 --- a/koans/src/java8/AboutStreams.java +++ b/koans/src/java8/AboutStreams.java @@ -68,13 +68,6 @@ public void join() { assertEquals(join, __); } - @Koan - public void reduceWithBinaryOperator() { - String join = places.stream() - .reduce("", String::concat); - assertEquals(join, __); - } - @Koan public void stringJoin() { String join = places.stream() From 2c664c819eb432dd0945a0bbf3a86508b7ae19ff Mon Sep 17 00:00:00 2001 From: Chen Zhang <340355960@qq.com> Date: Wed, 18 Aug 2021 16:47:32 +0800 Subject: [PATCH 29/30] Improve Travis CI build Performance --- .travis.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.travis.yml b/.travis.yml index 705ea2eb..c0eb7f08 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,3 +10,8 @@ before_install: script: - docker run java/koans /bin/bash -c "git clone https://github.com/matyb/java-koans && gradle -p java-koans/lib buildApp" + +cache: + directories: + - $HOME/.gradle/caches/ + - $HOME/.gradle/wrapper/ From b1b58914e2195b82f2c81c365366f0d9ad6b9a06 Mon Sep 17 00:00:00 2001 From: Mat Bentley Date: Sat, 11 Feb 2023 13:32:26 -0500 Subject: [PATCH 30/30] Close issue #101 (#102) --- koans/src/beginner/AboutPrimitives.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/koans/src/beginner/AboutPrimitives.java b/koans/src/beginner/AboutPrimitives.java index f8a240b5..2f196653 100644 --- a/koans/src/beginner/AboutPrimitives.java +++ b/koans/src/beginner/AboutPrimitives.java @@ -117,7 +117,7 @@ public void primitivesOfTypeCharHaveAnObjectTypeCharacter() { } @Koan - public void charsCanOnlyBePositive() { + public void charsAreNotNegative() { assertEquals((int) Character.MIN_VALUE, __); assertEquals((int) Character.MAX_VALUE, __);