diff --git a/.gitignore b/.gitignore index 3a109ac2..5392375c 100644 --- a/.gitignore +++ b/.gitignore @@ -2,12 +2,18 @@ */bin/* .metadata bin/* -lib/build/bin/* -lib/build/reports/* +lib/build +lib/out koans/data koans/data* .classpath .project +.settings koans/app/data lib/file-compiler/bin -koans/app/config/file_hashes.dat +**/file_hashes.dat +.gradle +*.iml +*.ipr +*.iws +.idea diff --git a/.travis.yml b/.travis.yml index 0722f6fd..c0eb7f08 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,3 +1,17 @@ -language: java -before_script: "cd lib/build/" -script: "ant test" +sudo: required + +language: ruby + +services: + - docker + +before_install: + - 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" + +cache: + directories: + - $HOME/.gradle/caches/ + - $HOME/.gradle/wrapper/ diff --git a/README.md b/README.md index 72f1496b..a0519e70 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: ===================== @@ -8,18 +10,16 @@ https://github.com/matyb/java-koans/archive/master.zip ```cd ``` * Within it you'll find: * *koans*: this directory contains the application and its lessons, it is all that is needed to advance through the koans themselves and **it can be distributed independently** - * *lib/koans-lib*: the directory for source code for the engine that executes the koans - * *lib/koans-tests*: the directory for tests to check the sanity of the application - * *lib/file-compiler*: the dynamic compiler module that loads newly saved java files into the JVM as classes - * *lib/file-monitor*: the file monitoring module for notifying the app when files are saved - * *lib/util*: application agnostic interfaces and utilities shared in projects + * *lib*: this directory contains the code the koans engine is comprised of and built with + * *gradle*: wrapper for build library used to build koans source, setup project files in eclipse/idea, run tests, etc. you probably don't need to touch anything in here * Change directory to the koans directory: ```cd koans``` -* If you are using windows enter: ```run.bat``` or ```./run.sh``` if you are using Mac or Linux. +* If you are using windows enter: ```run.bat``` or ```./run.sh``` if you are using Mac or Linux 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: 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/koans/README.md b/koans/README.md index 5445e5a4..044f12ce 100755 --- a/koans/README.md +++ b/koans/README.md @@ -1,27 +1,11 @@ -#Java Koans [![Build Status](https://travis-ci.org/darsen/java-koans.png?branch=master)](https://travis-ci.org/darsen/java-koans) - -Running Instructions: -===================== +## 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 terminal and cd to the directory you unarchived: -```cd ``` -* Within it you'll find: - * *koans*: this directory contains the application and its lessons, it is all that is needed to advance through the koans themselves and **it can be distributed independently** - * *lib/koans-lib*: the directory for source code for the engine that executes the koans - * *lib/koans-tests*: the directory for tests to check the sanity of the application - * *lib/file-compiler*: the dynamic compiler module that loads newly saved java files into the JVM as classes - * *lib/file-monitor*: the file monitoring module for notifying the app when files are saved - * *lib/util*: application agnostic interfaces and utilities shared in projects +* Open a console (terminal) and cd to the directory you unarchived: + ```cd ``` * Change directory to the koans directory: ```cd koans``` -* If you are using windows enter: ```run.bat``` or ```./run.sh``` if you are using Mac or Linux. - -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 -* 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: -================== -* If the koans app is constantly timing out compiling a koan, your computer may be too slow to compile the koan classes with the default timeout value. Update the compile_timeout_in_ms property in koans/app/config/config.properties with a larger value and try again. +* To export koans to run below command and open in IDE: + * IDEA IntelliJ: ```./gradlew idea (WINDOWS: gradlew.bat idea)``` + * Eclipse ```./gradlew eclipse (WINDOWS: gradlew.bat eclipse)``` +* Back to the console and run ```./run.sh``` (WINDOWS: ```run.bat```) +* Follow the instructions and start hacking diff --git a/koans/app/config/PathToEnlightenment.xml b/koans/app/config/PathToEnlightenment.xml index 929bfcd8..dd104446 100755 --- a/koans/app/config/PathToEnlightenment.xml +++ b/koans/app/config/PathToEnlightenment.xml @@ -1,56 +1,57 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/file-compiler/src/com/sandwich/util/io/filecompiler/compilationcommands.properties b/koans/app/config/compilationcommands.properties similarity index 51% rename from lib/file-compiler/src/com/sandwich/util/io/filecompiler/compilationcommands.properties rename to koans/app/config/compilationcommands.properties index 40af192a..d8b12bd0 100644 --- a/lib/file-compiler/src/com/sandwich/util/io/filecompiler/compilationcommands.properties +++ b/koans/app/config/compilationcommands.properties @@ -1,2 +1,3 @@ .groovy=groovyc -d ${bindir} -classpath ${classpath} ${filename} -.java=javac -d ${bindir} -classpath ${classpath} ${filename} \ No newline at end of file +.java=javac -d ${bindir} -classpath ${classpath} ${filename} + diff --git a/koans/app/config/config.properties b/koans/app/config/config.properties index 8583f821..5d078c19 100644 --- a/koans/app/config/config.properties +++ b/koans/app/config/config.properties @@ -1,5 +1,8 @@ compile_timeout_in_ms=5000 +ignore_from_monitoring=(.*\\.idea|^\\.#.*\\..*|^#.*\\..*) debug=false exit_character=Q enable_encouragement=false path_xml_filename=PathToEnlightenment.xml +enable_expectation_result=true +interactive=true diff --git a/koans/app/lib/file-compiler.jar b/koans/app/lib/file-compiler.jar deleted file mode 100644 index 92802779..00000000 Binary files a/koans/app/lib/file-compiler.jar and /dev/null differ diff --git a/koans/app/lib/file-monitor.jar b/koans/app/lib/file-monitor.jar deleted file mode 100644 index 71a9cf3c..00000000 Binary files a/koans/app/lib/file-monitor.jar and /dev/null differ diff --git a/koans/app/lib/koans.jar b/koans/app/lib/koans.jar index 9a223add..492231ba 100644 Binary files a/koans/app/lib/koans.jar and b/koans/app/lib/koans.jar differ diff --git a/koans/app/lib/util.jar b/koans/app/lib/util.jar deleted file mode 100644 index 4b0de74d..00000000 Binary files a/koans/app/lib/util.jar and /dev/null differ diff --git a/koans/build.gradle b/koans/build.gradle new file mode 100644 index 00000000..cc82be26 --- /dev/null +++ b/koans/build.gradle @@ -0,0 +1,21 @@ +apply plugin: 'java' +apply plugin: 'idea' +apply plugin: 'eclipse' + +repositories { + flatDir { + dirs 'app/lib' + } +} + +sourceSets { + main { + java { + srcDir 'src' + } + } +} + +dependencies { + compile name: 'koans' +} \ No newline at end of file diff --git a/koans/gradle/wrapper/gradle-wrapper.jar b/koans/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 00000000..94114481 Binary files /dev/null and b/koans/gradle/wrapper/gradle-wrapper.jar differ diff --git a/koans/gradle/wrapper/gradle-wrapper.properties b/koans/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000..c2030d0d --- /dev/null +++ b/koans/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Sat Mar 26 18:10:52 GMT 2016 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-2.12-bin.zip diff --git a/koans/gradlew b/koans/gradlew new file mode 100755 index 00000000..9d82f789 --- /dev/null +++ b/koans/gradlew @@ -0,0 +1,160 @@ +#!/usr/bin/env bash + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn ( ) { + echo "$*" +} + +die ( ) { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; +esac + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules +function splitJvmOpts() { + JVM_OPTS=("$@") +} +eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS +JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" + +exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/koans/gradlew.bat b/koans/gradlew.bat new file mode 100644 index 00000000..aec99730 --- /dev/null +++ b/koans/gradlew.bat @@ -0,0 +1,90 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windowz variants + +if not "%OS%" == "Windows_NT" goto win9xME_args +if "%@eval[2+2]" == "4" goto 4NT_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* +goto execute + +:4NT_args +@rem Get arguments from the 4NT Shell from JP Software +set CMD_LINE_ARGS=%$ + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/koans/run.bat b/koans/run.bat index 2487cf47..bd54d6c2 100755 --- a/koans/run.bat +++ b/koans/run.bat @@ -1,11 +1,15 @@ @echo off cls setLocal EnableDelayedExpansion -set CLASSPATH="%~dp0app\bin -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 @@ -16,13 +20,13 @@ java -Dapplication.basedir="%~dp0"" -classpath %CLASSPATH% com.sandwich.koan.run 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 -:end +:end \ No newline at end of file diff --git a/koans/run.sh b/koans/run.sh index 7c92a107..cbee3bb0 100755 --- a/koans/run.sh +++ b/koans/run.sh @@ -14,7 +14,7 @@ buildClasspath() appDir=$1 classpath=$appDir/bin IFS=$'\n' - + classpath=$classpath:$appDir/config/ for jar in $appDir/lib/* do classpath=$classpath:$jar @@ -26,4 +26,4 @@ java -version > /dev/null 2>&1 exitOnError 'java' buildClasspath "$DIR"/app cmd="java -Dapplication.basedir=\"$DIR\" -classpath \"$classpath\" com.sandwich.koan.runner.AppLauncher "$1" "$2" "$3" "$4" "$5" "$6" "$7" "$8" "$9"" -eval $cmd \ No newline at end of file +eval $cmd diff --git a/koans/src/advanced/AboutMocks.java b/koans/src/advanced/AboutMocks.java index 12b4765f..fd03e982 100755 --- a/koans/src/advanced/AboutMocks.java +++ b/koans/src/advanced/AboutMocks.java @@ -1,42 +1,46 @@ package advanced; import com.sandwich.koan.Koan; + import static com.sandwich.util.Assert.fail; public class AboutMocks { - - static interface Collaborator { - public void doBusinessStuff(); - } - - static class ExplosiveCollaborator implements Collaborator { - public void doBusinessStuff() { - fail("Default collaborator's behavior is complicating testing."); - } - } - - static class ClassUnderTest { - Collaborator c; - public ClassUnderTest(){ - // default is to pass a broken Collaborator, test should pass one - // that doesn't throw exception - this(new ExplosiveCollaborator()); - } - public ClassUnderTest(Collaborator c){ - this.c = c; - } - public boolean doSomething(){ - c.doBusinessStuff(); - return true; - } - } - - @Koan - public void simpleAnonymousMock(){ - // HINT: pass a safe Collaborator implementation to constructor - // new ClassUnderTest(new Collaborator(){... it should not be the - // objective of this test to test that collaborator, so replace it - new ClassUnderTest().doSomething(); - } - + + static interface Collaborator { + public void doBusinessStuff(); + } + + static class ExplosiveCollaborator implements Collaborator { + public void doBusinessStuff() { + fail("Default collaborator's behavior is complicating testing."); + } + } + + static class ClassUnderTest { + Collaborator c; + + public ClassUnderTest() { + // default is to pass a broken Collaborator, test should pass one + // that doesn't throw exception + this(new ExplosiveCollaborator()); + } + + public ClassUnderTest(Collaborator c) { + this.c = c; + } + + public boolean doSomething() { + c.doBusinessStuff(); + return true; + } + } + + @Koan + public void simpleAnonymousMock() { + // HINT: pass a safe Collaborator implementation to constructor + // new ClassUnderTest(new Collaborator(){... it should not be the + // objective of this test to test that collaborator, so replace it + new ClassUnderTest().doSomething(); + } + } diff --git a/koans/src/beginner/AboutArithmeticOperators.java b/koans/src/beginner/AboutArithmeticOperators.java new file mode 100644 index 00000000..422647f4 --- /dev/null +++ b/koans/src/beginner/AboutArithmeticOperators.java @@ -0,0 +1,57 @@ +package beginner; + +import com.sandwich.koan.Koan; + +import static com.sandwich.koan.constant.KoanConstants.__; +import static com.sandwich.util.Assert.assertEquals; + +public class AboutArithmeticOperators { + + @Koan + public void simpleOperations() { + assertEquals(1, __); + assertEquals(1 + 1, __); + assertEquals(2 + 3 * 4, __); + assertEquals((2 + 3) * 4, __); + assertEquals(2 * 3 + 4, __); + assertEquals(2 - 3 + 4, __); + assertEquals(2 + 4 / 2, __); + assertEquals((2 + 4) / 2, __); + } + + @Koan + public void notSoSimpleOperations() { + assertEquals(1 / 2, __); + assertEquals(3 / 2, __); + assertEquals(1 % 2, __); + assertEquals(3 % 2, __); + } + + @Koan + public void minusMinusVariableMinusMinus() { + int i = 1; + assertEquals(--i, __); + assertEquals(i, __); + assertEquals(i--, __); + assertEquals(i, __); + } + + @Koan + public void plusPlusVariablePlusPlus() { + int i = 1; + assertEquals(++i, __); + assertEquals(i, __); + assertEquals(i++, __); + assertEquals(i, __); + } + + @Koan + public void timesAndDivInPlace() { + int i = 1; + i *= 2; + assertEquals(i, __); + i /= 2; + assertEquals(i, __); + } + +} diff --git a/koans/src/beginner/AboutArrays.java b/koans/src/beginner/AboutArrays.java index 5fe26ea9..0596e5da 100755 --- a/koans/src/beginner/AboutArrays.java +++ b/koans/src/beginner/AboutArrays.java @@ -1,76 +1,76 @@ package beginner; -import static com.sandwich.koan.constant.KoanConstants.__; -import static com.sandwich.util.Assert.assertEquals; +import com.sandwich.koan.Koan; import java.util.Arrays; -import com.sandwich.koan.Koan; +import static com.sandwich.koan.constant.KoanConstants.__; +import static com.sandwich.util.Assert.assertEquals; public class AboutArrays { - @Koan - public void arraysDoNotConsiderElementsWhenEvaluatingEquality(){ - // arrays utilize default object equality (A == {1} B == {1}, though A - // and B contain the same thing, the container is not the same - // referenced array instance... - assertEquals(new int[] {1}.equals(new int[] {1}), __); - } - - @Koan - public void cloneEqualityIsNotRespected(){ //! - int[] original = new int[] { 1 }; - assertEquals(original.equals(original.clone()), __); - } - - @Koan - public void anArraysHashCodeMethodDoesNotConsiderElements(){ - int[] array0 = new int[]{0}; - int[] array1 = new int[]{0}; - assertEquals(Integer.valueOf(array0.hashCode()).equals(array1.hashCode()), __); // not equal! - // TODO: ponder the consequences when arrays are used in Hash Collection implementations. - } - - @Koan - public void arraysHelperClassEqualsMethodConsidersElementsWhenDeterminingEquality(){ - int[] array0 = new int[]{0}; - int[] array1 = new int[]{0}; - assertEquals(Arrays.equals(array0, array1), __); // whew - what most people assume - // about equals in regard to arrays! (logical equality) - } + @Koan + public void arraysDoNotConsiderElementsWhenEvaluatingEquality() { + // arrays utilize default object equality (A == {1} B == {1}, though A + // and B contain the same thing, the container is not the same + // referenced array instance... + assertEquals(new int[]{1}.equals(new int[]{1}), __); + } + + @Koan + public void cloneEqualityIsNotRespected() { //! + int[] original = new int[]{1}; + assertEquals(original.equals(original.clone()), __); + } + + @Koan + public void anArraysHashCodeMethodDoesNotConsiderElements() { + int[] array0 = new int[]{0}; + int[] array1 = new int[]{0}; + assertEquals(Integer.valueOf(array0.hashCode()).equals(array1.hashCode()), __); // not equal! + // TODO: ponder the consequences when arrays are used in Hash Collection implementations. + } + + @Koan + public void arraysHelperClassEqualsMethodConsidersElementsWhenDeterminingEquality() { + int[] array0 = new int[]{0}; + int[] array1 = new int[]{0}; + assertEquals(Arrays.equals(array0, array1), __); // whew - what most people assume + // about equals in regard to arrays! (logical equality) + } + + @Koan + public void arraysHelperClassHashCodeMethodConsidersElementsWhenDeterminingHashCode() { + int[] array0 = new int[]{0}; + int[] array1 = new int[]{0}; + // whew - what most people assume about hashCode in regard to arrays! + assertEquals(Integer.valueOf(Arrays.hashCode(array0)).equals(Arrays.hashCode(array1)), __); + } + + @Koan + public void arraysAreMutable() { + final boolean[] oneBoolean = new boolean[]{false}; + oneBoolean[0] = true; + assertEquals(oneBoolean[0], __); + } + + @Koan + public void arraysAreIndexedAtZero() { + int[] integers = new int[]{1, 2}; + assertEquals(integers[0], __); + assertEquals(integers[1], __); + } + + @Koan + public void arrayIndexOutOfBounds() { + int[] array = new int[]{1}; + @SuppressWarnings("unused") + int meh = array[1]; // remember 0 based indexes, 1 is the 2nd element (which doesn't exist) + } + + @Koan + public void arrayLengthCanBeChecked() { + assertEquals(new int[1].length, __); + } - @Koan - public void arraysHelperClassHashCodeMethodConsidersElementsWhenDeterminingHashCode(){ - int[] array0 = new int[]{0}; - int[] array1 = new int[]{0}; - // whew - what most people assume about hashCode in regard to arrays! - assertEquals(Integer.valueOf(Arrays.hashCode(array0)).equals(Arrays.hashCode(array1)), __); - } - - @Koan - public void arraysAreMutable(){ - final boolean[] oneBoolean = new boolean[]{false}; - oneBoolean[0] = true; - assertEquals(oneBoolean[0], __); - } - - @Koan - public void arraysAreIndexedAtZero(){ - int[] integers = new int[]{1,2}; - assertEquals(integers[0], __); - assertEquals(integers[1], __); - } - - @Koan - public void arrayIndexOutOfBounds(){ - int[] array = new int[]{1}; - @SuppressWarnings("unused") - int meh = array[1]; // remember 0 based indexes, 1 is the 2nd element (which doesn't exist) - } - - @Koan - public void arrayLengthCanBeChecked(){ - assertEquals(new int[1].length, __); - } - } diff --git a/koans/src/beginner/AboutAssertions.java b/koans/src/beginner/AboutAssertions.java old mode 100755 new mode 100644 index 5525d448..a83ba2ae --- a/koans/src/beginner/AboutAssertions.java +++ b/koans/src/beginner/AboutAssertions.java @@ -1,68 +1,86 @@ package beginner; -// FYI - usually bad practice to import statically, but can make code cleaner -import static com.sandwich.koan.constant.KoanConstants.__; -import static com.sandwich.util.Assert.assertEquals; -import static com.sandwich.util.Assert.assertFalse; -import static com.sandwich.util.Assert.assertNotNull; -import static com.sandwich.util.Assert.assertNotSame; -import static com.sandwich.util.Assert.assertNull; -import static com.sandwich.util.Assert.assertSame; -import static com.sandwich.util.Assert.assertTrue; - import com.sandwich.koan.Koan; +import static com.sandwich.koan.constant.KoanConstants.__; +import static com.sandwich.util.Assert.*; + public class AboutAssertions { - @Koan - public void assertBooleanTrue() { - assertTrue(__); // should be true really - } + @Koan + public void assertBooleanTrue() { + // there are two possibilities, true or false, what would it be here? + assertTrue(__); + } + + @Koan + public void assertBooleanFalse() { + assertFalse(__); + } + + @Koan + public void assertNullObject() { + // reference to the object can be null, a magic keyword, null, which means + // that there is nothing there + assertNull(__); + } + + @Koan + public void assertNullObjectReference() { + Object someObject = __; + assertNull(someObject); + } + + @Koan + public void assertNotNullObject() { + // but what when there should not be a null value? + assertNotNull(null); + } + + @Koan + public void assertEqualsUsingExpression() { + assertTrue("Hello World!".equals(__)); + } - @Koan - public void assertBooleanFalse() { - assertFalse(__); - } - - @Koan - public void assertNullObject(){ - assertNull(__); - } - - @Koan - public void assertNotNullObject(){ - assertNotNull(null); // anything other than null should pass here... - } + @Koan + public void assertEqualsWithAFewExpressions() { + assertEquals("Hello World!", __); + assertEquals(1, __); + assertEquals(2 + 2, __); + assertEquals(2 * 3, __); + assertEquals(3 - 8, __); + assertEquals(10 / 2, __); + } - @Koan - public void assertEqualsUsingExpression(){ - assertTrue("Hello World!".equals(__)); - } + @Koan + public void assertEqualsWithDescriptiveMessage() { + // Generally, when using an assertXXX methods, expectation is on the + // left and it is best practice to use a String for the first arg + // indication what has failed + assertEquals("The answer to 'life the universe and everything' should be 42", 42, __); + } - @Koan - public void assertEqualsWithBetterFailureMessage(){ - assertEquals(1, __); - } + @Koan + public void assertSameInstance() { + 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 assertEqualsWithDescriptiveMessage() { - // Generally, when using an assertXXX methods, expectation is on the - // left and it is best practice to use a String for the first arg - // indication what has failed - assertEquals("The answer to 'life the universe and everything' should be 42", 42, __); - } - - @Koan - public void assertSameInstance(){ - Object same = new Integer(1); - Object sameReference = __; - assertSame(same, sameReference); - } - - @Koan - public void assertNotSameInstance(){ - Integer same = new Integer(1); - Integer sameReference = same; - assertNotSame(same, sameReference); - } + @Koan + public void assertNotSameInstance() { + 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. + } } diff --git a/koans/src/beginner/AboutBitwiseOperators.java b/koans/src/beginner/AboutBitwiseOperators.java new file mode 100644 index 00000000..b2d17451 --- /dev/null +++ b/koans/src/beginner/AboutBitwiseOperators.java @@ -0,0 +1,65 @@ +package beginner; + +import com.sandwich.koan.Koan; + +import static com.sandwich.koan.constant.KoanConstants.__; +import static com.sandwich.util.Assert.assertEquals; + +public class AboutBitwiseOperators { + + @Koan + public void fullAnd() { + int i = 1; + if (true & (++i < 8)) i = i + 1; + assertEquals(i, __); + } + + @Koan + public void shortCircuitAnd() { + int i = 1; + if (true && (i < -28)) i = i + 1; + assertEquals(i, __); + } + + @Koan + public void aboutXOR() { + int i = 1; + int a = 6; + if ((a < 9) ^ false) i = i + 1; + assertEquals(i, __); + } + + @Koan + public void dontMistakeEqualsForEqualsEquals() { + int i = 1; + boolean a = false; + if (a = true) i++; + assertEquals(a, __); + assertEquals(i, __); + // How could you write the condition 'with a twist' to avoid this trap? + } + + @Koan + public void aboutBitShiftingRightShift() { + int rightShift = 8; + rightShift = rightShift >> 1; + assertEquals(rightShift, __); + } + + @Koan + public void aboutBitShiftingLeftShift() { + int leftShift = 0x80000000; // Is this number positive or negative? + leftShift = leftShift << 1; + assertEquals(leftShift, __); + } + + @Koan + public void aboutBitShiftingRightUnsigned() { + int rightShiftNegativeStaysNegative = 0x80000000; + rightShiftNegativeStaysNegative = rightShiftNegativeStaysNegative >> 4; + assertEquals(rightShiftNegativeStaysNegative, __); + int unsignedRightShift = 0x80000000; // always fills with 0 + unsignedRightShift >>>= 4; // Just like += + assertEquals(unsignedRightShift, __); + } +} diff --git a/koans/src/beginner/AboutCasting.java b/koans/src/beginner/AboutCasting.java index aa0a0425..a0520b50 100644 --- a/koans/src/beginner/AboutCasting.java +++ b/koans/src/beginner/AboutCasting.java @@ -1,114 +1,114 @@ package beginner; +import com.sandwich.koan.Koan; + import static com.sandwich.koan.constant.KoanConstants.__; import static com.sandwich.util.Assert.assertEquals; import static com.sandwich.util.Assert.fail; -import com.sandwich.koan.Koan; - @SuppressWarnings("unused") public class AboutCasting { - @Koan - public void longPlusInt() { - int a = 6; - long b = 10; - Object c = a + b; - assertEquals(c, __); - assertEquals(c instanceof Integer, __); - assertEquals(c instanceof Long, __); - } - - @Koan - public void forceIntTypecast() { - long a = 2147483648L; - // What happens if we force a long value into an int? - int b = (int) a; - assertEquals(b, __); - } - - @Koan - public void implicitTypecast() { - int a = 1; - int b = Integer.MAX_VALUE; - long c = a + b; // still overflows int... which is the Integer.MIN_VALUE, the operation occurs prior to assignment to long - assertEquals(c, __); - } - - interface Sleepable { - String sleep(); - } - - class Grandparent implements Sleepable { - public String sleep() { - return "zzzz"; - } - } - - class Parent extends Grandparent { - public String complain() { - return "TPS reports don't even have a cover letter!"; - } - } - - class Child extends Parent { - public String complain() { - return "Are we there yet!!"; - } - } - - @Koan - public void downCastWithInheritance() { - Child child = new Child(); - Parent parentReference = child; // Why isn't there an explicit cast? - assertEquals(child instanceof Child, __); - assertEquals(parentReference instanceof Child, __); - assertEquals(parentReference instanceof Parent, __); - assertEquals(parentReference instanceof Grandparent, __); - } - - @Koan - public void downCastAndPolymorphism() { - Child child = new Child(); - Parent parentReference = child; - // If the result is unexpected, consider the difference between an instance and its reference - assertEquals(parentReference.complain(), __); - } - - @Koan - public void upCastWithInheritance() { - Grandparent child = new Child(); - Parent parentReference = (Parent) child; // Why do we need an explicit cast here? - Child childReference = (Child) parentReference; // Or here? - assertEquals(childReference instanceof Child, __); - assertEquals(childReference instanceof Parent, __); - assertEquals(childReference instanceof Grandparent, __); - } - - @Koan - public void upCastAndPolymorphism() { - Grandparent child = new Child(); - Parent parent = (Child) child; - // Think about the result. Did you expect that? Why? - // How is that different from above? - assertEquals(parent.complain(), __); - } - - @Koan - public void classCasting() { - try { - Object o = new Object(); - ((Sleepable) o).sleep(); // would this even compile without the cast? - } catch (ClassCastException x) { - fail("Object does not implement Sleepable, maybe one of the people classes do?"); - } - } - - @Koan - public void complicatedCast() { - Grandparent parent = new Parent(); - // How can we access the parent's ability to "complain" - if the reference is held as a superclass? - assertEquals("TPS reports don't even have a cover letter!", __); - } + @Koan + public void longPlusInt() { + int a = 6; + long b = 10; + Object c = a + b; + assertEquals(c, __); + assertEquals(c instanceof Integer, __); + assertEquals(c instanceof Long, __); + } + + @Koan + public void forceIntTypecast() { + long a = 2147483648L; + // What happens if we force a long value into an int? + int b = (int) a; + assertEquals(b, __); + } + + @Koan + public void implicitTypecast() { + int a = 1; + int b = Integer.MAX_VALUE; + long c = a + b; // still overflows int... which is the Integer.MIN_VALUE, the operation occurs prior to assignment to long + assertEquals(c, __); + } + + interface Sleepable { + String sleep(); + } + + class Grandparent implements Sleepable { + public String sleep() { + return "zzzz"; + } + } + + class Parent extends Grandparent { + public String complain() { + return "TPS reports don't even have a cover letter!"; + } + } + + class Child extends Parent { + public String complain() { + return "Are we there yet!!"; + } + } + + @Koan + public void upcastWithInheritance() { + Child child = new Child(); + Parent parentReference = child; // Why isn't there an explicit cast? + assertEquals(child instanceof Child, __); + assertEquals(parentReference instanceof Child, __); + assertEquals(parentReference instanceof Parent, __); + assertEquals(parentReference instanceof Grandparent, __); + } + + @Koan + public void upcastAndPolymorphism() { + Child child = new Child(); + Parent parentReference = child; + // If the result is unexpected, consider the difference between an instance and its reference + assertEquals(parentReference.complain(), __); + } + + @Koan + public void downcastWithInheritance() { + Grandparent child = new Child(); + Parent parentReference = (Parent) child; // Why do we need an explicit cast here? + Child childReference = (Child) parentReference; // Or here? + assertEquals(childReference instanceof Child, __); + assertEquals(childReference instanceof Parent, __); + assertEquals(childReference instanceof Grandparent, __); + } + + @Koan + public void downcastAndPolymorphism() { + Grandparent child = new Child(); + Parent parent = (Child) child; + // Think about the result. Did you expect that? Why? + // How is that different from above? + assertEquals(parent.complain(), __); + } + + @Koan + public void classCasting() { + try { + Object o = new Object(); + ((Sleepable) o).sleep(); // would this even compile without the cast? + } catch (ClassCastException x) { + fail("Object does not implement Sleepable, maybe one of the people classes do?"); + } + } + + @Koan + public void complicatedCast() { + Grandparent parent = new Parent(); + // How can we access the parent's ability to "complain" - if the reference is held as a superclass? + assertEquals("TPS reports don't even have a cover letter!", __); + } } diff --git a/koans/src/beginner/AboutConditionals.java b/koans/src/beginner/AboutConditionals.java index b1ee8bc9..ca3d3fd6 100644 --- a/koans/src/beginner/AboutConditionals.java +++ b/koans/src/beginner/AboutConditionals.java @@ -2,154 +2,199 @@ import com.sandwich.koan.Koan; + import static com.sandwich.koan.constant.KoanConstants.__; import static com.sandwich.util.Assert.assertEquals; public class AboutConditionals { - @Koan - public void basicIfWithoutCurly(){ - // Ifs without curly braces are ugly and not recommended but still valid: - int x = 1; - if (true) - x++; - assertEquals(x, __); - } - - @Koan - public void basicIfElseWithoutCurly(){ - // Ifs without curly braces are ugly and not recommended but still valid: - int x = 1; - boolean secretBoolean = false; - if (secretBoolean) - x++; - else - x--; - assertEquals(x, __); - } - - @Koan - public void basicIfElseIfElseWithoutCurly(){ - int x = 1; - boolean secretBoolean = false; - boolean otherBooleanCondition = true; - // Ifs without curly braces are ugly and not recommended but still valid: - if (secretBoolean) - x++; - else if (otherBooleanCondition) - x = 10; - else - x--; - assertEquals(x, __); - } - - @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: - if (secretBoolean) x++; - if (otherBooleanCondition) x = 10; - else x--; - // Where does this else belong to!? - assertEquals(x, __); - } - - @Koan - public void ifAsIntended() { - boolean secretBoolean = true; - int x = 1; - if (secretBoolean) { - x++; - } else { - x = 0; - } - // 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, __); - } - - @Koan - public void basicSwitchStatement() { - int i = 1; - String result = "Basic "; - switch(i) { - case 1: - result += "One"; - break; - case 2: - result += "Two"; - break; - default: - result += "Nothing"; - } - assertEquals(result, __); - } - - @Koan - public void switchStatementFallThrough() { - int i = 1; - String result = "Basic "; - switch(i) { - case 1: - result += "One"; - case 2: - result += "Two"; - default: - result += "Nothing"; - } - assertEquals(result, __); - } - - @Koan - public void switchStatementCrazyFallThrough() { - int i = 5; - String result = "Basic "; - switch(i) { - case 1: - result += "One"; - default: - result += "Nothing"; - case 2: - result += "Two"; - } - assertEquals(result, __); - } - - @Koan - public void switchStatementConstants() { - int i = 5; - // What happens if you remove the 'final' modifier? - // What does this mean for case values? - final int caseOne = 1; - String result = "Basic "; - switch(i) { - case caseOne: - result += "One"; - break; - default: - result += "Nothing"; - } - assertEquals(result, __); - } - - @Koan - public void switchStatementSwitchValues() { - // Try different (primitive) types for 'c' - // Which types do compile? - // Does boxing work? - byte c = 'a'; - String result = "Basic "; - switch(c) { - case 'a': - result += "One"; - break; - default: - result += "Nothing"; - } - assertEquals(result, __); - } + @Koan + public void basicIf() { + int x = 1; + if (true) { + x++; + } + assertEquals(x, __); + } + + @Koan + public void basicIfElse() { + int x = 1; + boolean secretBoolean = false; + if (secretBoolean) { + x++; + } else { + x--; + } + assertEquals(x, __); + } + + @Koan + public void basicIfElseIfElse() { + int x = 1; + boolean secretBoolean = false; + boolean otherBooleanCondition = true; + if (secretBoolean) { + x++; + } else if (otherBooleanCondition) { + x = 10; + } else { + x--; + } + assertEquals(x, __); + } + + @Koan + public void nestedIfsWithoutCurlysAreReallyMisleading() { + int x = 1; + boolean secretBoolean = false; + boolean otherBooleanCondition = true; + // Curly braces after an "if" or "else" are not required... + if (secretBoolean) + x++; + if (otherBooleanCondition) + x = 10; + else + x--; + // ...but they are recommended. + assertEquals(x, __); + } + + @Koan + 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) { + x = 10; + } + } else { + x--; + } + assertEquals(x, __); + } + + @Koan + public void basicSwitchStatement() { + int i = 1; + String result = "Basic "; + switch (i) { + case 1: + result += "One"; + break; + case 2: + result += "Two"; + break; + default: + result += "Nothing"; + } + assertEquals(result, __); + } + + @Koan + public void switchStatementFallThrough() { + int i = 1; + String result = "Basic "; + switch (i) { + case 1: + result += "One"; + case 2: + result += "Two"; + default: + result += "Nothing"; + } + assertEquals(result, __); + } + + @Koan + public void switchStatementCrazyFallThrough() { + int i = 5; + String result = "Basic "; + switch (i) { + case 1: + result += "One"; + default: + result += "Nothing"; + case 2: + result += "Two"; + } + assertEquals(result, __); + } + + @Koan + public void switchStatementConstants() { + int i = 5; + // What happens if you remove the 'final' modifier? + // What does this mean for case values? + final int caseOne = 1; + String result = "Basic "; + switch (i) { + case caseOne: + result += "One"; + break; + default: + result += "Nothing"; + } + assertEquals(result, __); + } + + @Koan + public void switchStatementSwitchValues() { + // Try different (primitive) types for 'c' + // Which types do compile? + // Does boxing work? + char c = 'a'; + String result = "Basic "; + switch (c) { + case 'a': + result += "One"; + break; + default: + result += "Nothing"; + } + assertEquals(result, __); + } + + @Koan + public void shortCircuit() { + 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; + Counter(boolean returnValue) { + this.returnValue = returnValue; + } + boolean count() { + count++; + return returnValue; + } + } } diff --git a/koans/src/beginner/AboutConstructors.java b/koans/src/beginner/AboutConstructors.java index 208ea860..e2cd6855 100644 --- a/koans/src/beginner/AboutConstructors.java +++ b/koans/src/beginner/AboutConstructors.java @@ -2,41 +2,56 @@ import com.sandwich.koan.Koan; + import static com.sandwich.koan.constant.KoanConstants.__; import static com.sandwich.util.Assert.assertEquals; public class AboutConstructors { - class A { - String someString = "a"; - public A() { someString += "x"; } - - } - - class B extends A { - public B() { someString += "g"; }; - } - - @Koan - public void simpleConstructorOrder(){ - assertEquals(new B().someString, __); - } - - class Aa { - String someString = "a"; - public Aa() { someString += "x"; } - public Aa(String s) { - someString += s; - } - } - - class Bb extends Aa { - public Bb() { super("Boo"); someString += "g"; }; - } - - @Koan - public void complexConstructorOrder(){ - assertEquals(new Bb().someString, __); - } - + class A { + String someString = "a"; + + public A() { + someString += "x"; + } + + } + + class B extends A { + public B() { + someString += "g"; + } + + } + + @Koan + public void simpleConstructorOrder() { + assertEquals(new B().someString, __); + } + + class Aa { + String someString = "a"; + + public Aa() { + someString += "x"; + } + + public Aa(String s) { + someString += s; + } + } + + class Bb extends Aa { + public Bb() { + super("Boo"); + someString += "g"; + } + + } + + @Koan + public void complexConstructorOrder() { + assertEquals(new Bb().someString, __); + } + } diff --git a/koans/src/beginner/AboutEnums.java b/koans/src/beginner/AboutEnums.java index 25874ecc..807f5567 100644 --- a/koans/src/beginner/AboutEnums.java +++ b/koans/src/beginner/AboutEnums.java @@ -1,59 +1,67 @@ package beginner; import com.sandwich.koan.Koan; + import static com.sandwich.koan.constant.KoanConstants.__; import static com.sandwich.util.Assert.assertEquals; public class AboutEnums { - enum Colors { - Red, Blue, Green, Yellow // what happens if you add a ; here? - // What happens if you type Red() instead? - } - - @Koan - public void basicEnums() { - Colors blue = Colors.Blue; - assertEquals(blue == Colors.Blue, __); - assertEquals(blue == Colors.Red, __); - assertEquals(blue instanceof Colors, __); - } - - @Koan - public void basicEnumsAccess() { - Colors[] colorArray = Colors.values(); - assertEquals(colorArray[2], __); - } - - enum SkatSuits { - Clubs(12), Spades(11), Hearts(10), Diamonds(9); - SkatSuits(int v) { value = v; } - private int value; - } - - @Koan - public void enumsWithAttributes() { - // value is private but we still can access it. Why? - // Try moving the enum outside the AboutEnum class... What do you expect? - // What happens? - assertEquals(SkatSuits.Clubs.value > SkatSuits.Spades.value, __); - } - - enum OpticalMedia { - CD(650), DVD(4300), BluRay(50000); - OpticalMedia(int c) { - capacityInMegaBytes = c; - } - int capacityInMegaBytes; - int getCoolnessFactor() { - return (capacityInMegaBytes - 1000) * 10; - } - } - - @Koan - public void enumsWithMethods() { - assertEquals(OpticalMedia.CD.getCoolnessFactor(), __); - assertEquals(OpticalMedia.BluRay.getCoolnessFactor(), __); - } + enum Colors { + Red, Blue, Green, Yellow // what happens if you add a ; here? + // What happens if you type Red() instead? + } + + @Koan + public void basicEnums() { + Colors blue = Colors.Blue; + assertEquals(blue == Colors.Blue, __); + assertEquals(blue == Colors.Red, __); + assertEquals(blue instanceof Colors, __); + } + + @Koan + public void basicEnumsAccess() { + Colors[] colorArray = Colors.values(); + assertEquals(colorArray[2], __); + } + + enum SkatSuits { + Clubs(12), Spades(11), Hearts(10), Diamonds(9); + + SkatSuits(int v) { + value = v; + } + + private int value; + } + + @Koan + public void enumsWithAttributes() { + // value is private but we still can access it. Why? + // Try moving the enum outside the AboutEnum class... What do you expect? + // What happens? + assertEquals(SkatSuits.Clubs.value > SkatSuits.Spades.value, __); + } + + enum OpticalMedia { + CD(650), DVD(4300), BluRay(50000); + + OpticalMedia(int c) { + capacityInMegaBytes = c; + } + + int capacityInMegaBytes; + + int getCoolnessFactor() { + return (capacityInMegaBytes - 1000) * 10; + } + } + + @Koan + public void enumsWithMethods() { + assertEquals(OpticalMedia.CD.getCoolnessFactor(), __); + assertEquals(OpticalMedia.BluRay.getCoolnessFactor(), __); + } } diff --git a/koans/src/beginner/AboutEquality.java b/koans/src/beginner/AboutEquality.java index edc8efff..18ac70cf 100644 --- a/koans/src/beginner/AboutEquality.java +++ b/koans/src/beginner/AboutEquality.java @@ -3,41 +3,50 @@ import com.sandwich.koan.Koan; import static com.sandwich.koan.constant.KoanConstants.__; -import static com.sandwich.util.Assert.*; +import static com.sandwich.util.Assert.assertEquals; public class AboutEquality { - @Koan - public void doubleEqualsTestsIfTwoObjectsAreTheSame(){ - Object object = new Object(); - Object sameObject = object; - assertEquals(object == sameObject, __); - assertEquals(object == new Object(), __); - } - - @Koan - public void equalsMethodByDefaultTestsIfTwoObjectsAreTheSame(){ - Object object = new Object(); - assertEquals(object.equals(object), __); - assertEquals(object.equals(new Object()), __); - } - - @Koan - public void equalsMethodCanBeChangedBySubclassesToTestsIfTwoObjectsAreEqual(){ - Object object = new Integer(1); - assertEquals(object.equals(object), __); - assertEquals(object.equals(new Integer(1)), __); - // Note: This means that for the class 'Object' there is no difference between 'equal' and 'same' - } - - @Koan - public void objectsNeverEqualNull(){ - assertEquals(new Object().equals(null), __); - } - - @Koan - public void objectsEqualThemselves(){ - Object obj = new Object(); - assertEquals(obj.equals(obj), __); - } + @Koan + public void doubleEqualsTestsIfTwoObjectsAreTheSame() { + Object object = new Object(); + Object sameObject = object; + assertEquals(object == sameObject, __); + assertEquals(object == new Object(), __); + } + + @Koan + public void equalsMethodByDefaultTestsIfTwoObjectsAreTheSame() { + Object object = new Object(); + assertEquals(object.equals(object), __); + assertEquals(object.equals(new Object()), __); + } + + @Koan + public void equalsMethodCanBeChangedBySubclassesToTestsIfTwoObjectsAreEqual() { + Object object = new Integer(1); + assertEquals(object.equals(object), __); + assertEquals(object.equals(new Integer(1)), __); + // Note: This means that for the class 'Object' there is no difference between 'equal' and 'same' + // but for the class 'Integer' there is difference - see below + } + + @Koan + public void equalsMethodCanBeChangedBySubclassesToTestsIfTwoObjectsAreEqualExample() { + Integer value1 = new Integer(4); + Integer value2 = new Integer(2 + 2); + assertEquals(value1.equals(value2), __); + assertEquals(value1, __); + } + + @Koan + public void objectsNeverEqualNull() { + assertEquals(new Object().equals(null), __); + } + + @Koan + public void objectsEqualThemselves() { + Object obj = new Object(); + assertEquals(obj.equals(obj), __); + } } diff --git a/koans/src/beginner/AboutExceptions.java b/koans/src/beginner/AboutExceptions.java index 02e8548f..b54ee194 100644 --- a/koans/src/beginner/AboutExceptions.java +++ b/koans/src/beginner/AboutExceptions.java @@ -1,161 +1,166 @@ package beginner; +import com.sandwich.koan.Koan; + import java.io.IOException; -import com.sandwich.koan.Koan; import static com.sandwich.koan.constant.KoanConstants.__; import static com.sandwich.util.Assert.assertEquals; public class AboutExceptions { - - private void doStuff() throws IOException { - throw new IOException(); - } - - @Koan - public void catchCheckedExceptions() { - String s; - try { - doStuff(); - s = "code ran normally"; - } catch(IOException e) { - s = "exception thrown"; - } - assertEquals(s, __); - } - - @Koan - public void useFinally() { - String s = ""; - try { - doStuff(); - s += "code ran normally"; - } catch(IOException e) { - s += "exception thrown"; - } finally { - s += " and finally ran as well"; - } - assertEquals(s, __); - } - - @Koan - public void finallyWithoutCatch() { - String s = ""; - try { - s = "code ran normally"; - } finally { - s += " and finally ran as well"; - } - assertEquals(s, __); - } - - private void tryCatchFinallyWithVoidReturn(StringBuilder whatHappened) { - try { - whatHappened.append("did something dangerous"); - doStuff(); - } catch(IOException e) { - whatHappened.append("; the catch block executed"); - return; - } finally { - whatHappened.append(", but so did the finally!"); - } - } - - @Koan - public void finallyIsAlwaysRan() { - StringBuilder whatHappened = new StringBuilder(); - tryCatchFinallyWithVoidReturn(whatHappened); - assertEquals(whatHappened.toString(), __); - } - - @SuppressWarnings("finally") // this is suppressed because returning in finally block is obviously a compiler warning - private String returnStatementsEverywhere(StringBuilder whatHappened) { - try { - whatHappened.append("try"); - doStuff(); - return "from try"; - } catch (IOException e) { - whatHappened.append(", catch"); - return "from catch"; - } finally { - whatHappened.append(", finally"); - // Think about how bad an idea it is to put a return statement in the finally block - // DO NOT DO THIS! - return "from finally"; - } - } - - @Koan - public void returnInFinallyBlock() { - StringBuilder whatHappened = new StringBuilder(); - // Which value will be returned here? - assertEquals(returnStatementsEverywhere(whatHappened), __); - assertEquals(whatHappened.toString(), __); - } - - private void doUncheckedStuff() { - throw new RuntimeException(); - } - - @Koan - public void catchUncheckedExceptions() { - // What do you need to do to catch the unchecked exception? - doUncheckedStuff(); - } - - @SuppressWarnings("serial") - static class ParentException extends Exception {} - @SuppressWarnings("serial") - static class ChildException extends ParentException {} - - private void throwIt() throws ParentException { - throw new ChildException(); - } - - @Koan - public void catchOrder() { - String s = ""; - try { - throwIt(); - } catch(ChildException e) { - s = "ChildException"; - } catch(ParentException e) { - s = "ParentException"; - } - assertEquals(s, __); - } - - @Koan - public void failArgumentValidationWithAnIllegalArgumentException(){ - // This koan demonstrates the use of exceptions in argument validation - String s = ""; - try { - s += validateUsingIllegalArgumentException(null); - } catch (IllegalArgumentException ex) { - s = "caught an IllegalArgumentException"; - } - assertEquals(s, __); - } - - @Koan - public void passArgumentValidationWithAnIllegalArgumentException(){ - // This koan demonstrates the use of exceptions in argument validation - String s = ""; - try { - s += validateUsingIllegalArgumentException("valid"); - } catch (IllegalArgumentException ex) { - s = "caught an IllegalArgumentException"; - } - assertEquals(s, __); - } - - private int validateUsingIllegalArgumentException(String str) { - // This is effective and both the evaluation and the error message - // can be tailored which can be particularly handy if you're guarding - // against more than null values - if (null == str) { - throw new IllegalArgumentException("str should not be null"); - } - return str.length(); - } + + private void doStuff() throws IOException { + throw new IOException(); + } + + @Koan + public void catchCheckedExceptions() { + String s; + try { + doStuff(); + s = "code ran normally"; + } catch (IOException e) { + s = "exception thrown"; + } + assertEquals(s, __); + } + + @Koan + public void useFinally() { + String s = ""; + try { + doStuff(); + s += "code ran normally"; + } catch (IOException e) { + s += "exception thrown"; + } finally { + s += " and finally ran as well"; + } + assertEquals(s, __); + } + + @Koan + public void finallyWithoutCatch() { + String s = ""; + try { + s = "code ran normally"; + } finally { + s += " and finally ran as well"; + } + assertEquals(s, __); + } + + private void tryCatchFinallyWithVoidReturn(StringBuilder whatHappened) { + try { + whatHappened.append("did something dangerous"); + doStuff(); + } catch (IOException e) { + whatHappened.append("; the catch block executed"); + return; + } finally { + whatHappened.append(", but so did the finally!"); + } + } + + @Koan + public void finallyIsAlwaysRan() { + StringBuilder whatHappened = new StringBuilder(); + tryCatchFinallyWithVoidReturn(whatHappened); + assertEquals(whatHappened.toString(), __); + } + + @SuppressWarnings("finally") + // this is suppressed because returning in finally block is obviously a compiler warning + private String returnStatementsEverywhere(StringBuilder whatHappened) { + try { + whatHappened.append("try"); + doStuff(); + return "from try"; + } catch (IOException e) { + whatHappened.append(", catch"); + return "from catch"; + } finally { + whatHappened.append(", finally"); + // Think about how bad an idea it is to put a return statement in the finally block + // DO NOT DO THIS! + return "from finally"; + } + } + + @Koan + public void returnInFinallyBlock() { + StringBuilder whatHappened = new StringBuilder(); + // Which value will be returned here? + assertEquals(returnStatementsEverywhere(whatHappened), __); + assertEquals(whatHappened.toString(), __); + } + + private void doUncheckedStuff() { + throw new RuntimeException(); + } + + @Koan + public void catchUncheckedExceptions() { + // What do you need to do to catch the unchecked exception? + doUncheckedStuff(); + } + + @SuppressWarnings("serial") + static class ParentException extends Exception { + } + + @SuppressWarnings("serial") + static class ChildException extends ParentException { + } + + private void throwIt() throws ParentException { + throw new ChildException(); + } + + @Koan + public void catchOrder() { + String s = ""; + try { + throwIt(); + } catch (ChildException e) { + s = "ChildException"; + } catch (ParentException e) { + s = "ParentException"; + } + assertEquals(s, __); + } + + @Koan + public void failArgumentValidationWithAnIllegalArgumentException() { + // This koan demonstrates the use of exceptions in argument validation + String s = ""; + try { + s += validateUsingIllegalArgumentException(null); + } catch (IllegalArgumentException ex) { + s = "caught an IllegalArgumentException"; + } + assertEquals(s, __); + } + + @Koan + public void passArgumentValidationWithAnIllegalArgumentException() { + // This koan demonstrates the use of exceptions in argument validation + String s = ""; + try { + s += validateUsingIllegalArgumentException("valid"); + } catch (IllegalArgumentException ex) { + s = "caught an IllegalArgumentException"; + } + assertEquals(s, __); + } + + private int validateUsingIllegalArgumentException(String str) { + // This is effective and both the evaluation and the error message + // can be tailored which can be particularly handy if you're guarding + // against more than null values + if (null == str) { + throw new IllegalArgumentException("str should not be null"); + } + return str.length(); + } } diff --git a/koans/src/beginner/AboutInheritance.java b/koans/src/beginner/AboutInheritance.java index d810865f..22068058 100644 --- a/koans/src/beginner/AboutInheritance.java +++ b/koans/src/beginner/AboutInheritance.java @@ -1,44 +1,111 @@ package beginner; +import com.sandwich.koan.Koan; + import static com.sandwich.koan.constant.KoanConstants.__; import static com.sandwich.util.Assert.assertEquals; -import java.util.Collection; -import java.util.Collections; -import java.util.List; +public class AboutInheritance { -import com.sandwich.koan.Koan; + abstract class Animal { + abstract public String makeSomeNoise(); + } -public class AboutInheritance { + class Cow extends Animal { + @Override + public String makeSomeNoise() { + return "Moo!"; + } + } + + class Dog extends Animal { + @Override + public String makeSomeNoise() { + return "Woof!"; + } + + public boolean canFetch() { + return true; + } + } + + class Puppy extends Dog { + @Override + public String makeSomeNoise() { + return "Squeak!"; + } + public boolean canFetch() { + return false; + } + } + + @Koan + public void methodOverloading() { + Cow bob = new Cow(); + Dog max = new Dog(); + Puppy barney = new Puppy(); + assertEquals(bob.makeSomeNoise(), __); + assertEquals(max.makeSomeNoise(), __); + assertEquals(barney.makeSomeNoise(), __); + + assertEquals(max.canFetch(), __); + assertEquals(barney.canFetch(), __); + // but can Bob the Cow fetch? + } + + @Koan + public void methodOverloadingUsingPolymorphism() { + Animal bob = new Cow(); + Animal max = new Dog(); + Animal barney = new Puppy(); + assertEquals(bob.makeSomeNoise(), __); + assertEquals(max.makeSomeNoise(), __); + assertEquals(barney.makeSomeNoise(), __); + // but can max or barney (here as an Animal) fetch? + // try to write it down here + } + + @Koan + public void inheritanceHierarchy() { + Animal someAnimal = new Cow(); + Animal bob = new Cow(); + assertEquals(someAnimal.makeSomeNoise().equals(bob.makeSomeNoise()), __); + // cow is a Cow, but it can also be an animal + assertEquals(bob instanceof Animal, __); + assertEquals(bob instanceof Cow, __); + // but is it a Puppy? + assertEquals(bob instanceof Puppy, __); + } + + @Koan + public void deeperInheritanceHierarchy() { + Dog max = new Dog(); + Puppy barney = new Puppy(); + assertEquals(max instanceof Puppy, __); + assertEquals(max instanceof Dog, __); + assertEquals(barney instanceof Puppy, __); + assertEquals(barney instanceof Dog, __); + } - class Parent { - public String doStuff() { return "parent"; } - } - class Child extends Parent { - public String doStuff() { return "child"; } - public String doStuff(String s) { return s; } - } - - @Koan - public void differenceBetweenOverloadingAndOverriding() { - assertEquals(new Parent().doStuff(), __); - assertEquals(new Child().doStuff(), __); - assertEquals(new Child().doStuff("oh no"), __); - } - - abstract class ParentTwo { - abstract public Collection doStuff(); - } - - class ChildTwo extends ParentTwo { - public Collection doStuff() { return Collections.emptyList(); }; - } - - @Koan - public void overriddenMethodsMayReturnSubtype() { - // What do you need to change in order to get rid of the type cast? - // Why does this work? - List list = (List) new ChildTwo().doStuff(); - assertEquals(list instanceof List, __); - } + // TODO overriding +// +// abstract class ParentTwo { +// abstract public Collection doStuff(); +// } +// +// class ChildTwo extends ParentTwo { +// public Collection doStuff() { +// return Collections.emptyList(); +// } +// +// ; +// } +// +// @Koan +// public void overriddenMethodsMayReturnSubtype() { +// // What do you need to change in order to get rid of the type cast? +// // Why does this work? +// List list = (List) new ChildTwo().doStuff(); +// assertEquals(list instanceof List, __); +// } } diff --git a/koans/src/beginner/AboutKoans.java b/koans/src/beginner/AboutKoans.java index fb73f732..5ab0c236 100644 --- a/koans/src/beginner/AboutKoans.java +++ b/koans/src/beginner/AboutKoans.java @@ -1,22 +1,22 @@ package beginner; -import static com.sandwich.util.Assert.fail; - import com.sandwich.koan.Koan; +import static com.sandwich.util.Assert.fail; + public class AboutKoans { - @Koan - public void findAboutKoansFile(){ - fail("delete this line"); - } - - @Koan - public void definitionOfKoanCompletion(){ - boolean koanIsComplete = false; - if(!koanIsComplete){ - fail("what if koanIsComplete was true?"); - } - } - + @Koan + public void findAboutKoansFile() { + fail("delete this line to advance"); + } + + @Koan + public void definitionOfKoanCompletion() { + boolean koanIsComplete = false; + if (!koanIsComplete) { + fail("what if koanIsComplete variable was true?"); + } + } + } diff --git a/koans/src/beginner/AboutLoops.java b/koans/src/beginner/AboutLoops.java index 67f2e792..2a27e89c 100644 --- a/koans/src/beginner/AboutLoops.java +++ b/koans/src/beginner/AboutLoops.java @@ -2,121 +2,167 @@ import com.sandwich.koan.Koan; + import static com.sandwich.koan.constant.KoanConstants.__; import static com.sandwich.util.Assert.assertEquals; public class AboutLoops { - @Koan - public void basicForLoop() { - String s = ""; - for(int i = 0; i < 5; i++) { - s += i + " "; - } - assertEquals(s, __); - } - - @Koan - public void basicForLoopWithTwoVariables() { - String s = ""; - for(int i = 0, j = 10; i < 5 && j > 5; i++, j--) { - s += i + " " + j + " "; - } - assertEquals(s, __); - } - - @Koan - public void extendedForLoop() { - int[] is = {1,2,3,4}; - String s = "-"; - for(int j : is) { - s += "." + j; - } - assertEquals(s, __); - } - - @Koan - public void whileLoop() { - int result = 0; - while(result < 3) { - result++; - } - assertEquals(result, __); - } - - @Koan - public void doLoop() { - int result = 0; - do { - result++; - } while(false); - assertEquals(result, __); - } - - @Koan - public void extendedForLoopBreak() { - String[] sa = {"Dog", "Cat", "Tiger"}; - int count = 0; - for(String current : sa) { - if("Cat".equals(current)) { - break; - } - count++; - } - assertEquals(count, __); - } - - @Koan - public void extendedForLoopContinue() { - String[] sa = {"Dog", "Cat", "Tiger"}; - int count = 0; - for(String current : sa) { - if("Dog".equals(current)) { - continue; - } else { - count++; - } - } - assertEquals(count, __); - } - - @Koan - public void forLoopContinueLabel() { - int count = 0; - outerLabel: - for(int i = 0; i < 5; i++) { - for(int j = 0; j < 5; j++) - { - count++; - if(count > 2) { - continue outerLabel; - } - } - count += 10; - } - // What does continue with a label mean? - // What gets executed? Where does the program flow continue? - assertEquals(count, __); - } - - @Koan - public void forLoopBreakLabel() { - int count = 0; - outerLabel: - for(int i = 0; i < 5; i++) { - for(int j = 0; j < 5; j++) - { - count++; - if(count > 2) { - break outerLabel; - } - } - count += 10; - } - // What does break with a label mean? - // What gets executed? Where does the program flow continue? - assertEquals(count, __); - } + @Koan + public void basicForLoop1() { + String s = ""; + for (int i = 0; i < 5; i++) { + s += i + " "; + } + assertEquals(s, __); + } + + @Koan + public void basicForLoop2() { + String s = ""; + for (int i = -5; i < 1; i++) { + s += i + " "; + } + assertEquals(s, __); + } + + @Koan + public void basicForLoop3() { + String s = ""; + for (int i = 5; i > 0; i--) { + s += i + " "; + } + assertEquals(s, __); + } + + @Koan + public void basicForLoop4() { + String s = ""; + for (int i = 0; i < 11; i += 2) { + s += i + " "; + } + assertEquals(s, __); + } + + @Koan + public void basicForLoop5() { + String s = ""; + for (int i = 1; i <= 16; i *= 2) { + s += i + " "; + } + assertEquals(s, __); + } + + @Koan + public void basicForLoopWithTwoVariables1() { + String s = ""; + for (int i = 0, j = 10; i < 5 && j > 5; i++, j--) { + s += i + " " + j + " "; + } + assertEquals(s, __); + } + + @Koan + public void nestedLoops() { + String s = ""; + for (int i = 0; i < 3; i++) { + for (int j = 0; j < 3; j++) { + s += "(" + i + ", " + j + ") "; + } + s += " - "; + } + assertEquals(s, __); + } + + @Koan + public void extendedForLoop() { + int[] is = {1, 2, 3, 4}; + String s = ""; + for (int j : is) { + s += j + " "; + } + assertEquals(s, __); + } + + @Koan + public void whileLoop() { + int result = 0; + while (result < 3) { + result++; + } + assertEquals(result, __); + } + + @Koan + public void doLoop() { + int result = 0; + do { + result++; + } while (false); + assertEquals(result, __); + } + + @Koan + public void extendedForLoopBreak() { + String[] sa = {"Dog", "Cat", "Tiger"}; + int count = 0; + for (String current : sa) { + if ("Cat".equals(current)) { + break; + } + count++; + } + assertEquals(count, __); + } + + @Koan + public void extendedForLoopContinue() { + String[] sa = {"Dog", "Cat", "Tiger"}; + int count = 0; + for (String current : sa) { + if ("Dog".equals(current)) { + continue; + } else { + count++; + } + } + assertEquals(count, __); + } + + @Koan + public void forLoopContinueLabel() { + int count = 0; + outerLabel: + for (int i = 0; i < 6; i++) { + for (int j = 0; j < 6; j++) { + count++; + if (count > 2) { + continue outerLabel; + } + } + count += 10; + } + // What does continue with a label mean? + // What gets executed? Where does the program flow continue? + assertEquals(count, __); + } + @Koan + public void forLoopBreakLabel() { + int count = 0; + outerLabel: + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + count++; + if (count > 2) { + break outerLabel; + } + } + count += 10; + } + // What does break with a label mean? + // What gets executed? Where does the program flow continue? + assertEquals(count, __); + } } diff --git a/koans/src/beginner/AboutMethodPreference.java b/koans/src/beginner/AboutMethodPreference.java index 67ce20f8..52063487 100644 --- a/koans/src/beginner/AboutMethodPreference.java +++ b/koans/src/beginner/AboutMethodPreference.java @@ -1,51 +1,63 @@ package beginner; import com.sandwich.koan.Koan; + import static com.sandwich.koan.constant.KoanConstants.__; import static com.sandwich.util.Assert.assertEquals; public class AboutMethodPreference { - class A { - public String doStuff(int i) { return "int"; } - public String doStuff(Integer i) { return "Integer"; } - public String doStuff(Object i) { return "Object"; } - public String doStuff(int...i) { return "int vararg"; } - } - - @Koan - public void methodPreferenceInt() { - assertEquals(new A().doStuff(1), __); - } - - @Koan - public void methodPreferenceInteger() { - assertEquals(new A().doStuff(Integer.valueOf(1)), __); - } - - @Koan - public void methodPreferenceLong() { - long l = 1; - assertEquals(new A().doStuff(l), __); - } - - @Koan - public void methodPreferenceBoxedLong() { - Long l = Long.valueOf(1); - assertEquals(new A().doStuff(l), __); - } - - @Koan - public void methodPreferenceDouble() { - Double l = Double.valueOf(1); - assertEquals(new A().doStuff(l), __); - } - - @Koan - public void methodPreferenceMore() { - // What happens if you change 'Integer' to 'Double' - // Does this explain 'methodPreferenceDouble'? - // Think about why this happens? - assertEquals(new A().doStuff(1, Integer.valueOf(2)), __); - } + class A { + public String doStuff(int i) { + return "int"; + } + + public String doStuff(Integer i) { + return "Integer"; + } + + public String doStuff(Object i) { + return "Object"; + } + + public String doStuff(int... i) { + return "int vararg"; + } + } + + @Koan + public void methodPreferenceInt() { + assertEquals(new A().doStuff(1), __); + } + + @Koan + public void methodPreferenceInteger() { + assertEquals(new A().doStuff(Integer.valueOf(1)), __); + } + + @Koan + public void methodPreferenceLong() { + long l = 1; + assertEquals(new A().doStuff(l), __); + } + + @Koan + public void methodPreferenceBoxedLong() { + Long l = Long.valueOf(1); + assertEquals(new A().doStuff(l), __); + } + + @Koan + public void methodPreferenceDouble() { + Double l = Double.valueOf(1); + assertEquals(new A().doStuff(l), __); + } + + @Koan + public void methodPreferenceMore() { + // What happens if you change 'Integer' to 'Double' + // Does this explain 'methodPreferenceDouble'? + // Think about why this happens? + assertEquals(new A().doStuff(1, Integer.valueOf(2)), __); + } } diff --git a/koans/src/beginner/AboutObjects.java b/koans/src/beginner/AboutObjects.java index df9f3181..b93e5e28 100755 --- a/koans/src/beginner/AboutObjects.java +++ b/koans/src/beginner/AboutObjects.java @@ -1,63 +1,65 @@ package beginner; -import static com.sandwich.koan.constant.KoanConstants.__; -import static com.sandwich.util.Assert.assertEquals; +import com.sandwich.koan.Koan; import java.text.MessageFormat; import java.util.ArrayList; import java.util.List; -import com.sandwich.koan.Koan; +import static com.sandwich.koan.constant.KoanConstants.__; +import static com.sandwich.util.Assert.assertEquals; public class AboutObjects { - @Koan - public void newObjectInstancesCanBeCreatedDirectly() { - assertEquals(new Object() instanceof Object, __); - } - - @Koan - public void allClassesInheritFromObject() { - class Foo {} - - Class[] ancestors = getAncestors(new Foo()); - assertEquals(ancestors[0], __); - assertEquals(ancestors[1], __); - } - - @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() - } - - @Koan - public void toStringConcatenates() { - final String string = "ha"; - Object object = new Object() { - @Override public String toString() { - return string; - } - }; - assertEquals(string + object, __); - } - - @Koan - public void toStringIsTestedForNullWhenInvokedImplicitly() { - String string = "string"; - assertEquals(string + null, __); - } - - private Class[] getAncestors(Object object) { - List> ancestors = new ArrayList>(); - Class clazz = object.getClass(); - while(clazz != null) { - ancestors.add(clazz); - clazz = clazz.getSuperclass(); - } - return ancestors.toArray(new Class[]{}); - } - + @Koan + public void newObjectInstancesCanBeCreatedDirectly() { + assertEquals(new Object() instanceof Object, __); + } + + @Koan + public void allClassesInheritFromObject() { + class Foo { + } + + Class[] ancestors = getAncestors(new Foo()); + assertEquals(ancestors[0], __); + assertEquals(ancestors[1], __); + } + + @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() + } + + @Koan + public void toStringConcatenates() { + final String string = "ha"; + Object object = new Object() { + @Override + public String toString() { + return string; + } + }; + assertEquals(string + object, __); + } + + @Koan + public void toStringIsTestedForNullWhenInvokedImplicitly() { + String string = "string"; + assertEquals(string + null, __); + } + + private Class[] getAncestors(Object object) { + List> ancestors = new ArrayList>(); + Class clazz = object.getClass(); + while (clazz != null) { + ancestors.add(clazz); + clazz = clazz.getSuperclass(); + } + return ancestors.toArray(new Class[]{}); + } + } diff --git a/koans/src/beginner/AboutOperators.java b/koans/src/beginner/AboutOperators.java deleted file mode 100644 index 1f6aff8a..00000000 --- a/koans/src/beginner/AboutOperators.java +++ /dev/null @@ -1,84 +0,0 @@ -package beginner; - -import com.sandwich.koan.Koan; -import static com.sandwich.koan.constant.KoanConstants.__; -import static com.sandwich.util.Assert.assertEquals; - -public class AboutOperators { - - @Koan - public void plusPlusVariablePlusPlus(){ - int i = 1; - assertEquals(++i, __); - assertEquals(i, __); - assertEquals(i++, __); - assertEquals(i, __); - } - - @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? - // Try this with an IDE like Eclipse... - if ( (a < 9 ) || (++i < 8) ) i = i + 1; - assertEquals(i, __); - } - - @Koan - public void fullAnd(){ - int i = 1; - if ( true & (++i < 8) ) i = i + 1; - assertEquals(i, __); - } - - @Koan - public void shortCircuitAnd(){ - int i = 1; - if ( true && (i < -28) ) i = i + 1; - assertEquals(i, __); - } - - @Koan - public void aboutXOR() { - int i = 1; - int a = 6; - if ( (a < 9 ) ^ false) i = i + 1; - assertEquals(i, __); - } - - @Koan - public void dontMistakeEqualsForEqualsEquals() { - int i = 1; - boolean a = false; - if (a = true) i++; - assertEquals(a, __); - assertEquals(i, __); - // How could you write the condition 'with a twist' to avoid this trap? - } - - @Koan - public void aboutBitShiftingRightShift() { - int rightShift = 8; - rightShift = rightShift >> 1; - assertEquals(rightShift, __); - } - - @Koan - public void aboutBitShiftingLeftShift() { - int leftShift = 0x80000000; // Is this number positive or negative? - leftShift = leftShift << 1; - assertEquals(leftShift, __); - } - - @Koan - public void aboutBitShiftingRightUnsigned() { - int rightShiftNegativeStaysNegative = 0x80000000; - rightShiftNegativeStaysNegative = rightShiftNegativeStaysNegative >> 4; - assertEquals(rightShiftNegativeStaysNegative, __); - int unsignedRightShift = 0x80000000; // always fills with 0 - unsignedRightShift >>>= 4; // Just like += - assertEquals(unsignedRightShift, __); - } - -} diff --git a/koans/src/beginner/AboutPrimitives.java b/koans/src/beginner/AboutPrimitives.java index 078238d3..2f196653 100644 --- a/koans/src/beginner/AboutPrimitives.java +++ b/koans/src/beginner/AboutPrimitives.java @@ -1,227 +1,227 @@ package beginner; +import com.sandwich.koan.Koan; + import static com.sandwich.koan.constant.KoanConstants.__; import static com.sandwich.util.Assert.assertEquals; -import com.sandwich.koan.Koan; - public class AboutPrimitives { - @Koan - public void wholeNumbersAreOfTypeInt() { - assertEquals(getType(1), __); // hint: int.class - } - - @Koan - public void primitivesOfTypeIntHaveAnObjectTypeInteger() { - Object number = 1; - assertEquals(getType(number), __); - - // Primitives can be automatically changed into their object type via a process called auto-boxing - // We will explore this in more detail in intermediate.AboutAutoboxing - } - - @Koan - public void integersHaveAFairlyLargeRange() { - assertEquals(Integer.MIN_VALUE, __); - assertEquals(Integer.MAX_VALUE, __); - } - - @Koan - public void integerSize() { - assertEquals(Integer.SIZE, __); // This is the amount of bits used to store an int - } - - @Koan - public void wholeNumbersCanAlsoBeOfTypeLong() { - assertEquals(getType(1L), __); - } - - @Koan - public void primitivesOfTypeLongHaveAnObjectTypeLong() { - Object number = 1L; - assertEquals(getType(number), __); - } - - @Koan - public void longsHaveALargerRangeThanInts() { - assertEquals(Long.MIN_VALUE, __); - assertEquals(Long.MAX_VALUE, __); - } - - @Koan - public void longSize() { - assertEquals(Long.SIZE, __); - } - - @Koan - public void wholeNumbersCanAlsoBeOfTypeShort() { - assertEquals(getType((short) 1), __); // The '(short)' is called an explicit cast - to type 'short' - } - - @Koan - public void primitivesOfTypeShortHaveAnObjectTypeShort() { - Object number = (short) 1; - assertEquals(getType(number), __); - } - - @Koan - public void shortsHaveASmallerRangeThanInts() { - assertEquals(Short.MIN_VALUE, __); // hint: You'll need an explicit cast - assertEquals(Short.MAX_VALUE, __); - } - - @Koan - public void shortSize() { - assertEquals(Short.SIZE, __); - } - - @Koan - public void wholeNumbersCanAlsoBeOfTypeByte() { - assertEquals(getType((byte) 1), __); - } - - @Koan - public void primitivesOfTypeByteHaveAnObjectTypeByte() { - Object number = (byte) 1; - assertEquals(getType(number), __); - } - - @Koan - public void bytesHaveASmallerRangeThanShorts() { - assertEquals(Byte.MIN_VALUE, __); - assertEquals(Byte.MAX_VALUE, __); - - // Why would you use short or byte considering that you need to do explicit casts? - } - - @Koan - public void byteSize() { - assertEquals(Byte.SIZE, __); - } - - @Koan - public void wholeNumbersCanAlsoBeOfTypeChar() { - assertEquals(getType((char) 1), __); - } - - @Koan - public void singleCharactersAreOfTypeChar() { - assertEquals(getType('a'), __); - } - - @Koan - public void primitivesOfTypeCharHaveAnObjectTypeCharacter() { - Object number = (char) 1; - assertEquals(getType(number), __); - } - - @Koan - public void charsCanOnlyBePositive() { - assertEquals((int) Character.MIN_VALUE, __); - assertEquals((int) Character.MAX_VALUE, __); - - // Why did we cast MIN_VALUE and MAX_VALUE to int? Try it without the cast. - } - - @Koan - public void charSize() { - assertEquals(Character.SIZE, __); - } - - @Koan - public void decimalNumbersAreOfTypeDouble() { - assertEquals(getType(1.0), __); - } - - @Koan - public void primitivesOfTypeDoubleCanBeDeclaredWithoutTheDecimalPoint() { - assertEquals(getType(1d), __); - } - - @Koan - public void primitivesOfTypeDoubleCanBeDeclaredWithExponents() { - assertEquals(getType(1e3), __); - assertEquals(1.0e3, __); - assertEquals(1E3, __); - } - - @Koan - public void primitivesOfTypeDoubleHaveAnObjectTypeDouble() { - Object number = 1.0; - assertEquals(getType(number), __); - } - - @Koan - public void doublesHaveALargeRange() { - assertEquals(Double.MIN_VALUE, __); - assertEquals(Double.MAX_VALUE, __); - } - - @Koan - public void doubleSize() { - assertEquals(Double.SIZE, __); - } - - @Koan - public void decimalNumbersCanAlsoBeOfTypeFloat() { - assertEquals(getType(1f), __); - } - - @Koan - public void primitivesOfTypeFloatCanBeDeclaredWithExponents() { - assertEquals(getType(1e3f), __); - assertEquals(1.0e3f, __); - assertEquals(1E3f, __); - } - - @Koan - public void primitivesOfTypeFloatHaveAnObjectTypeFloat() { - Object number = 1f; - assertEquals(getType(number), __); - } - - @Koan - public void floatsHaveASmallerRangeThanDoubles() { - assertEquals(Float.MIN_VALUE, __); - assertEquals(Float.MAX_VALUE, __); - } - - @Koan - public void floatSize() { - assertEquals(Float.SIZE, __); - } - - private Class getType(int value) { - return int.class; - } - - private Class getType(long value) { - return long.class; - } - - private Class getType(float value) { - return float.class; - } - - private Class getType(double value) { - return double.class; - } - - private Class getType(byte value) { - return byte.class; - } - - private Class getType(char value) { - return char.class; - } - - private Class getType(short value) { - return short.class; - } - - private Class getType(Object value) { - return value.getClass(); - } - + @Koan + public void wholeNumbersAreOfTypeInt() { + assertEquals(getType(1), __); // hint: int.class + } + + @Koan + public void primitivesOfTypeIntHaveAnObjectTypeInteger() { + Object number = 1; + assertEquals(getType(number), __); + + // Primitives can be automatically changed into their object type via a process called auto-boxing + // We will explore this in more detail in intermediate.AboutAutoboxing + } + + @Koan + public void integersHaveAFairlyLargeRange() { + assertEquals(Integer.MIN_VALUE, __); + assertEquals(Integer.MAX_VALUE, __); + } + + @Koan + public void integerSize() { + assertEquals(Integer.SIZE, __); // This is the amount of bits used to store an int + } + + @Koan + public void wholeNumbersCanAlsoBeOfTypeLong() { + assertEquals(getType(1L), __); + } + + @Koan + public void primitivesOfTypeLongHaveAnObjectTypeLong() { + Object number = 1L; + assertEquals(getType(number), __); + } + + @Koan + public void longsHaveALargerRangeThanInts() { + assertEquals(Long.MIN_VALUE, __); + assertEquals(Long.MAX_VALUE, __); + } + + @Koan + public void longSize() { + assertEquals(Long.SIZE, __); + } + + @Koan + public void wholeNumbersCanAlsoBeOfTypeShort() { + assertEquals(getType((short) 1), __); // The '(short)' is called an explicit cast - to type 'short' + } + + @Koan + public void primitivesOfTypeShortHaveAnObjectTypeShort() { + Object number = (short) 1; + assertEquals(getType(number), __); + } + + @Koan + public void shortsHaveASmallerRangeThanInts() { + assertEquals(Short.MIN_VALUE, __); // hint: You'll need an explicit cast + assertEquals(Short.MAX_VALUE, __); + } + + @Koan + public void shortSize() { + assertEquals(Short.SIZE, __); + } + + @Koan + public void wholeNumbersCanAlsoBeOfTypeByte() { + assertEquals(getType((byte) 1), __); + } + + @Koan + public void primitivesOfTypeByteHaveAnObjectTypeByte() { + Object number = (byte) 1; + assertEquals(getType(number), __); + } + + @Koan + public void bytesHaveASmallerRangeThanShorts() { + assertEquals(Byte.MIN_VALUE, __); + assertEquals(Byte.MAX_VALUE, __); + + // Why would you use short or byte considering that you need to do explicit casts? + } + + @Koan + public void byteSize() { + assertEquals(Byte.SIZE, __); + } + + @Koan + public void wholeNumbersCanAlsoBeOfTypeChar() { + assertEquals(getType((char) 1), __); + } + + @Koan + public void singleCharactersAreOfTypeChar() { + assertEquals(getType('a'), __); + } + + @Koan + public void primitivesOfTypeCharHaveAnObjectTypeCharacter() { + Object number = (char) 1; + assertEquals(getType(number), __); + } + + @Koan + public void charsAreNotNegative() { + assertEquals((int) Character.MIN_VALUE, __); + assertEquals((int) Character.MAX_VALUE, __); + + // Why did we cast MIN_VALUE and MAX_VALUE to int? Try it without the cast. + } + + @Koan + public void charSize() { + assertEquals(Character.SIZE, __); + } + + @Koan + public void decimalNumbersAreOfTypeDouble() { + assertEquals(getType(1.0), __); + } + + @Koan + public void primitivesOfTypeDoubleCanBeDeclaredWithoutTheDecimalPoint() { + assertEquals(getType(1d), __); + } + + @Koan + public void primitivesOfTypeDoubleCanBeDeclaredWithExponents() { + assertEquals(getType(1e3), __); + assertEquals(1.0e3, __); + assertEquals(1E3, __); + } + + @Koan + public void primitivesOfTypeDoubleHaveAnObjectTypeDouble() { + Object number = 1.0; + assertEquals(getType(number), __); + } + + @Koan + public void doublesHaveALargeRange() { + assertEquals(Double.MIN_VALUE, __); + assertEquals(Double.MAX_VALUE, __); + } + + @Koan + public void doubleSize() { + assertEquals(Double.SIZE, __); + } + + @Koan + public void decimalNumbersCanAlsoBeOfTypeFloat() { + assertEquals(getType(1f), __); + } + + @Koan + public void primitivesOfTypeFloatCanBeDeclaredWithExponents() { + assertEquals(getType(1e3f), __); + assertEquals(1.0e3f, __); + assertEquals(1E3f, __); + } + + @Koan + public void primitivesOfTypeFloatHaveAnObjectTypeFloat() { + Object number = 1f; + assertEquals(getType(number), __); + } + + @Koan + public void floatsHaveASmallerRangeThanDoubles() { + assertEquals(Float.MIN_VALUE, __); + assertEquals(Float.MAX_VALUE, __); + } + + @Koan + public void floatSize() { + assertEquals(Float.SIZE, __); + } + + private Class getType(int value) { + return int.class; + } + + private Class getType(long value) { + return long.class; + } + + private Class getType(float value) { + return float.class; + } + + private Class getType(double value) { + return double.class; + } + + private Class getType(byte value) { + return byte.class; + } + + private Class getType(char value) { + return char.class; + } + + private Class getType(short value) { + return short.class; + } + + private Class getType(Object value) { + return value.getClass(); + } + } diff --git a/koans/src/beginner/AboutStrings.java b/koans/src/beginner/AboutStrings.java index 7a3a4a48..600cfa0a 100644 --- a/koans/src/beginner/AboutStrings.java +++ b/koans/src/beginner/AboutStrings.java @@ -2,93 +2,185 @@ import com.sandwich.koan.Koan; -import java.util.*; import java.text.MessageFormat; -import static com.sandwich.koan.constant.KoanConstants.*; -import static com.sandwich.util.Assert.*; +import static com.sandwich.koan.constant.KoanConstants.__; +import static com.sandwich.util.Assert.assertEquals; +import static com.sandwich.util.Assert.fail; public class AboutStrings { - @Koan - public void implicitStrings() { - assertEquals("just a plain ole string".getClass(), __); - } - - @Koan - public void newString() { - // very rarely if ever should Strings be created via new String() in - // practice - generally it is redundant, and done repetitively can be slow - String string = new String(); - String empty = ""; - assertEquals(string.equals(empty), __); - } - - @Koan - public void newStringIsRedundant() { - String stringInstance = "zero"; - String stringReference = new String(stringInstance); - assertEquals(stringInstance.equals(stringReference), __); - } - - @Koan - public void newStringIsNotIdentical() { - String stringInstance = "zero"; - String stringReference = new String(stringInstance); - assertEquals(stringInstance == stringReference, __); - } - - @Koan - public void stringConcatenation() { - String one = "one"; - String space = " "; - String two = "two"; - assertEquals(one + space + two, __); - } - - @Koan - public void stringBuilderCanActAsAMutableString() { - // StringBuilder concatenation looks uglier, but is useful when you need a - // mutable String like object. It used to be more efficient than using + - // to concatenate numerous strings, however this is optimized in the compiler now. - // Usually + concatenation is more appropriate than StringBuilder. - assertEquals(new StringBuilder("one").append(" ").append("two").toString(), __); - } - - @Koan - public void readableStringFormattingWithStringFormat() { - assertEquals(String.format("%s %s %s", "a", "b", "a"), __); - } - - @Koan - public void extraArgumentsToStringFormatGetIgnored() { - assertEquals(String.format("%s %s %s", "a", "b", "c", "d"), __); - } - - @Koan - public void insufficientArgumentsToStringFormatCausesAnError() { - try { - String.format("%s %s %s", "a", "b"); - fail("No Exception was thrown!"); - } catch (Exception e) { - assertEquals(e.getClass(), __); - assertEquals(e.getMessage(), __); - } - } - - @Koan - public void readableStringFormattingWithMessageFormat() { - assertEquals(MessageFormat.format("{0} {1} {0}", "a", "b"), __); - } - - @Koan - public void extraArgumentsToMessageFormatGetIgnored() { - assertEquals(MessageFormat.format("{0} {1} {0}", "a", "b", "c"), __); - } - - @Koan - public void insufficientArgumentsToMessageFormatDoesNotReplaceTheToken() { - assertEquals(MessageFormat.format("{0} {1} {0}", "a"), __); - } - + @Koan + public void implicitStrings() { + assertEquals("just a plain ole string".getClass(), __); + } + + @Koan + public void newString() { + // very rarely if ever should Strings be created via new String() in + // practice - generally it is redundant, and done repetitively can be slow + String string = new String(); + String empty = ""; + assertEquals(string.equals(empty), __); + } + + @Koan + public void newStringIsRedundant() { + String stringInstance = "zero"; + String stringReference = new String(stringInstance); + assertEquals(stringInstance.equals(stringReference), __); + } + + @Koan + public void newStringIsNotIdentical() { + String stringInstance = "zero"; + String stringReference = new String(stringInstance); + assertEquals(stringInstance == stringReference, __); + } + + @Koan + public void stringIsEmpty() { + assertEquals("".isEmpty(), __); + assertEquals("one".isEmpty(), __); + assertEquals(new String().isEmpty(), __); + assertEquals(new String("").isEmpty(), __); + assertEquals(new String("one").isEmpty(), __); + } + + @Koan + public void stringLength() { + assertEquals("".length(), __); + assertEquals("one".length(), __); + assertEquals("the number is one".length(), __); + } + + @Koan + public void stringTrim() { + assertEquals("".trim(), __); + assertEquals("one".trim(), "one"); + assertEquals(" one more time".trim(), __); + assertEquals(" one more time ".trim(), __); + assertEquals(" and again\t".trim(), __); + assertEquals("\t\t\twhat about now?\t".trim(), __); + } + + @Koan + public void stringConcatenation() { + String one = "one"; + String space = " "; + String two = "two"; + assertEquals(one + space + two, __); + assertEquals(space + one + two, __); + assertEquals(two + space + one, __); + } + + @Koan + public void stringUpperCase() { + String str = "I am a number one!"; + assertEquals(str.toUpperCase(), __); + } + + @Koan + public void stringLowerCase() { + String str = "I AM a number ONE!"; + assertEquals(str.toLowerCase(), __); + } + + @Koan + public void stringCompare() { + String str = "I AM a number ONE!"; + assertEquals(str.compareTo("I AM a number ONE!") == 0, __); + assertEquals(str.compareTo("I am a number one!") == 0, __); + assertEquals(str.compareTo("I AM A NUMBER ONE!") == 0, __); + } + + @Koan + public void stringCompareIgnoreCase() { + String str = "I AM a number ONE!"; + assertEquals(str.compareToIgnoreCase("I AM a number ONE!") == 0, __); + assertEquals(str.compareToIgnoreCase("I am a number one!") == 0, __); + assertEquals(str.compareToIgnoreCase("I AM A NUMBER ONE!") == 0, __); + } + + @Koan + public void stringStartsWith() { + assertEquals("".startsWith("one"), __); + assertEquals("one".startsWith("one"), __); + assertEquals("one is the number".startsWith("one"), __); + assertEquals("ONE is the number".startsWith("one"), __); + } + + @Koan + public void stringEndsWith() { + assertEquals("".endsWith("one"), __); + assertEquals("one".endsWith("one"), __); + assertEquals("the number is one".endsWith("one"), __); + assertEquals("the number is two".endsWith("one"), __); + assertEquals("the number is One".endsWith("one"), __); + } + + @Koan + public void stringSubstring() { + String str = "I AM a number ONE!"; + assertEquals(str.substring(0), __); + assertEquals(str.substring(1), __); + assertEquals(str.substring(5), __); + assertEquals(str.substring(14, 17), __); + assertEquals(str.substring(7, str.length()), __); + } + + @Koan + public void stringContains() { + String str = "I AM a number ONE!"; + assertEquals(str.contains("one"), __); + assertEquals(str.contains("ONE"), __); + } + + @Koan + public void stringReplace() { + String str = "I am a number ONE!"; + assertEquals(str.replace("ONE", "TWO"), __); + assertEquals(str.replace("I am", "She is"), __); + } + + @Koan + public void stringBuilderCanActAsAMutableString() { + assertEquals(new StringBuilder("one").append(" ").append("two").toString(), __); + } + + @Koan + public void readableStringFormattingWithStringFormat() { + assertEquals(String.format("%s %s %s", "a", "b", "a"), __); + } + + @Koan + public void extraArgumentsToStringFormatGetIgnored() { + assertEquals(String.format("%s %s %s", "a", "b", "c", "d"), __); + } + + @Koan + public void insufficientArgumentsToStringFormatCausesAnError() { + try { + String.format("%s %s %s", "a", "b"); + fail("No Exception was thrown!"); + } catch (Exception e) { + assertEquals(e.getClass(), __); + assertEquals(e.getMessage(), __); + } + } + + @Koan + public void readableStringFormattingWithMessageFormat() { + assertEquals(MessageFormat.format("{0} {1} {0}", "a", "b"), __); + } + + @Koan + public void extraArgumentsToMessageFormatGetIgnored() { + assertEquals(MessageFormat.format("{0} {1} {0}", "a", "b", "c"), __); + } + + @Koan + public void insufficientArgumentsToMessageFormatDoesNotReplaceTheToken() { + assertEquals(MessageFormat.format("{0} {1} {0}", "a"), __); + } } diff --git a/koans/src/beginner/AboutVarArgs.java b/koans/src/beginner/AboutVarArgs.java index 5ecf3094..d187336b 100644 --- a/koans/src/beginner/AboutVarArgs.java +++ b/koans/src/beginner/AboutVarArgs.java @@ -1,43 +1,50 @@ package beginner; +import com.sandwich.koan.Koan; + import static com.sandwich.koan.constant.KoanConstants.__; import static com.sandwich.util.Assert.assertEquals; -import com.sandwich.koan.Koan; - public class AboutVarArgs { - class ExampleClass { - public boolean canBeTreatedAsArray(Integer... arguments) { return arguments instanceof Integer[]; } - public int getLength(Integer... arguments) { return arguments.length; } - public String verboseLength(String prefix, Object... arguments) { return prefix + arguments.length; } - - // ******* - // The following methods won't compile because Java doesn't allow this type of method declaration - // ******* - // public String invalidMethodDeclaration(String... arguments, String... otherArguments) { return ""; } - // public String otherInvalidMethodDeclaration(String... arguments, String otherArgument) { return ""; } - } - - @Koan - public void varArgsCanBeTreatedAsArrays() { - assertEquals(new ExampleClass().canBeTreatedAsArray(1, 2, 3), __); - } - - @Koan - public void youCanPassInAsManyArgumentsAsYouLike() { - assertEquals(new ExampleClass().getLength(1, 2, 3), __); - assertEquals(new ExampleClass().getLength(1, 2, 3, 4, 5, 6, 7, 8), __); - } - - @Koan - public void youCanPassInZeroArgumentsIfYouLike() { - assertEquals(new ExampleClass().getLength(), __); - } - - @Koan - public void youCanHaveOtherTypesInTheMethodSignature() { - assertEquals(new ExampleClass().verboseLength("This is how many items were passed in: ", 1, 2, 3, 4), - __); - } + class ExampleClass { + public boolean canBeTreatedAsArray(Integer... arguments) { + return arguments instanceof Integer[]; + } + + public int getLength(Integer... arguments) { + return arguments.length; + } + + public String verboseLength(String prefix, Object... arguments) { + return prefix + arguments.length; + } + + // ******* + // The following methods won't compile because Java only permits varargs as last argument + // ******* + // public String invalidMethodDeclaration(String... arguments, String... otherArguments) { return ""; } + // public String otherInvalidMethodDeclaration(String... arguments, String otherArgument) { return ""; } + } + + @Koan + public void varArgsCanBeTreatedAsArrays() { + assertEquals(new ExampleClass().canBeTreatedAsArray(1, 2, 3), __); + } + + @Koan + public void youCanPassInAsManyArgumentsAsYouLike() { + assertEquals(new ExampleClass().getLength(1, 2, 3), __); + assertEquals(new ExampleClass().getLength(1, 2, 3, 4, 5, 6, 7, 8), __); + } + + @Koan + public void youCanPassInZeroArgumentsIfYouLike() { + assertEquals(new ExampleClass().getLength(), __); + } + + @Koan + public void youCanHaveOtherTypesInTheMethodSignature() { + assertEquals(new ExampleClass().verboseLength("This is how many items were passed in: ", 1, 2, 3, 4), __); + } } diff --git a/koans/src/intermediate/AboutAutoboxing.java b/koans/src/intermediate/AboutAutoboxing.java index 6480360a..4063eb2d 100755 --- a/koans/src/intermediate/AboutAutoboxing.java +++ b/koans/src/intermediate/AboutAutoboxing.java @@ -1,52 +1,52 @@ package intermediate; -import static com.sandwich.koan.constant.KoanConstants.__; -import static com.sandwich.util.Assert.assertEquals; +import com.sandwich.koan.Koan; import java.util.ArrayList; import java.util.List; -import com.sandwich.koan.Koan; +import static com.sandwich.koan.constant.KoanConstants.__; +import static com.sandwich.util.Assert.assertEquals; public class AboutAutoboxing { - @Koan - public void addPrimitivesToCollection() { - List list = new ArrayList(); - list.add(0, new Integer(42)); - assertEquals(list.get(0), __); - } - - @Koan - public void addPrimitivesToCollectionWithAutoBoxing() { - List list = new ArrayList(); - list.add(0, 42); - assertEquals(list.get(0), __); - } - - @Koan - public void migrateYourExistingCodeToAutoBoxingWithoutFear() { - List list = new ArrayList(); - list.add(0, new Integer(42)); - assertEquals(list.get(0), __); - - list.add(1, 84); - assertEquals(list.get(1), __); - } - - @Koan - public void allPrimitivesCanBeAutoboxed() { - List doubleList = new ArrayList(); - doubleList.add(0, new Double(42)); - assertEquals(doubleList.get(0), __); - - List longList = new ArrayList(); - longList.add(0, new Long(42)); - assertEquals(longList.get(0), __); - - List characterList = new ArrayList(); - characterList.add(0, new Character('z')); - assertEquals(characterList.get(0), __); - } - + @Koan + public void addPrimitivesToCollection() { + List list = new ArrayList(); + list.add(0, new Integer(42)); + assertEquals(list.get(0), __); + } + + @Koan + public void addPrimitivesToCollectionWithAutoBoxing() { + List list = new ArrayList(); + list.add(0, 42); + assertEquals(list.get(0), __); + } + + @Koan + public void migrateYourExistingCodeToAutoBoxingWithoutFear() { + List list = new ArrayList(); + list.add(0, new Integer(42)); + assertEquals(list.get(0), __); + + list.add(1, 84); + assertEquals(list.get(1), __); + } + + @Koan + public void allPrimitivesCanBeAutoboxed() { + List doubleList = new ArrayList(); + doubleList.add(0, new Double(42)); + assertEquals(doubleList.get(0), __); + + List longList = new ArrayList(); + longList.add(0, new Long(42)); + assertEquals(longList.get(0), __); + + List characterList = new ArrayList(); + characterList.add(0, new Character('z')); + assertEquals(characterList.get(0), __); + } + } diff --git a/koans/src/intermediate/AboutCollections.java b/koans/src/intermediate/AboutCollections.java index de3dbbba..3d4cca35 100644 --- a/koans/src/intermediate/AboutCollections.java +++ b/koans/src/intermediate/AboutCollections.java @@ -1,133 +1,121 @@ package intermediate; +import com.sandwich.koan.Koan; + +import java.util.*; + import static com.sandwich.koan.constant.KoanConstants.__; import static com.sandwich.util.Assert.assertEquals; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.PriorityQueue; -import java.util.Queue; -import java.util.Set; -import java.util.SortedMap; -import java.util.TreeMap; -import java.util.TreeSet; -import com.sandwich.koan.Koan; +public class AboutCollections { + @Koan + public void usingAnArrayList() { + // List = interface + // The generic syntax and special generic cases will be handled in + // AboutGenerics. We just use collections here to keep it + // simple. + List list = new ArrayList(); + // ArrayList: simple List implementation + list.add("Chicken"); + list.add("Dog"); + list.add("Chicken"); + assertEquals(list.get(0), __); + assertEquals(list.get(1), __); + assertEquals(list.get(2), __); + } -public class AboutCollections { - - @Koan - public void usingAnArrayList() { - // List = interface - // The generic syntax and special generic cases will be handled in - // AboutGenerics. We just use collections here to keep it - // simple. - List list = new ArrayList(); - // ArrayList: simple List implementation - list.add("Chicken"); - list.add("Dog"); - list.add("Chicken"); - assertEquals(list.get(0), __); - assertEquals(list.get(1), __); - assertEquals(list.get(2), __); - } - - @Koan - public void usingAQueue() { - // Queue = interface - Queue queue = new PriorityQueue(); - // PriorityQueue: simple queue implementation - queue.add("Cat"); - queue.add("Dog"); - assertEquals(queue.peek(), __); - assertEquals(queue.size(), __); - assertEquals(queue.poll(), __); - assertEquals(queue.size(), __); - assertEquals(queue.poll(), __); - assertEquals(queue.isEmpty(), __); - } - - @Koan - public void usingABasicSet() { - Set set = new HashSet(); - set.add("Dog"); - set.add("Cat"); - set.add("Dog"); - assertEquals(set.size(), __); - assertEquals(set.contains("Dog"), __); - assertEquals(set.contains("Cat"), __); - assertEquals(set.contains("Chicken"), __); - } - - @Koan - public void usingABasicMap() { - Map map = new HashMap(); - map.put("first key", "first value"); - map.put("second key", "second value"); - map.put("first key", "other value"); - assertEquals(map.size(), __); - assertEquals(map.containsKey("first key"), __); - assertEquals(map.containsKey("second key"), __); - assertEquals(map.containsValue("first value"), __); - assertEquals(map.get("first key"), __); - } - - @Koan - public void usingBackedArrayList() { - String[] array = {"a","b","c"}; - List list = Arrays.asList(array); - list.set(0, "x"); - assertEquals(array[0], __); - array[0] = "a"; - assertEquals(list.get(0), __); - // Just think of it as quantum state teleportation... - } - - @Koan - public void usingBackedSubMap() { - TreeMap map = new TreeMap(); - map.put("a", "Aha"); - map.put("b", "Boo"); - map.put("c", "Coon"); - map.put("e", "Emu"); - map.put("f", "Fox"); - SortedMap backedMap = map.subMap("c", "f"); - assertEquals(backedMap.size(), __); - assertEquals(map.size(), __); - backedMap.put("d", "Dog"); - assertEquals(backedMap.size(), __); - assertEquals(map.size(), __); - assertEquals(map.containsKey("d"), __); - // Again: backed maps are just like those little quantum states - // that are connected forever... - } - - @Koan - public void differenceBetweenOrderedAndSorted() { - TreeSet sorted = new TreeSet(); - sorted.add("c"); - sorted.add("z"); - sorted.add("a"); - assertEquals(sorted.first(), __); - assertEquals(sorted.last(), __); - // Look at the different constructors for a TreeSet (or TreeMap) - // Ponder how you might influence the sort order. Hold that thought - // until you approach AboutComparison - - LinkedHashSet ordered = new LinkedHashSet(); - ordered.add("c"); - ordered.add("z"); - ordered.add("a"); - StringBuffer sb = new StringBuffer(); - for(String s: ordered) { - sb.append(s); - } - assertEquals(sb.toString(), __); - } + @Koan + public void usingAQueue() { + // Queue = interface + Queue queue = new PriorityQueue(); + // PriorityQueue: simple queue implementation + queue.add("Cat"); + queue.add("Dog"); + assertEquals(queue.peek(), __); + assertEquals(queue.size(), __); + assertEquals(queue.poll(), __); + assertEquals(queue.size(), __); + assertEquals(queue.poll(), __); + assertEquals(queue.isEmpty(), __); + } + + @Koan + public void usingABasicSet() { + Set set = new HashSet(); + set.add("Dog"); + set.add("Cat"); + set.add("Dog"); + assertEquals(set.size(), __); + assertEquals(set.contains("Dog"), __); + assertEquals(set.contains("Cat"), __); + assertEquals(set.contains("Chicken"), __); + } + + @Koan + public void usingABasicMap() { + Map map = new HashMap(); + map.put("first key", "first value"); + map.put("second key", "second value"); + map.put("first key", "other value"); + assertEquals(map.size(), __); + assertEquals(map.containsKey("first key"), __); + assertEquals(map.containsKey("second key"), __); + assertEquals(map.containsValue("first value"), __); + assertEquals(map.get("first key"), __); + } + + @Koan + public void usingBackedArrayList() { + String[] array = {"a", "b", "c"}; + List list = Arrays.asList(array); + list.set(0, "x"); + assertEquals(array[0], __); + array[0] = "a"; + assertEquals(list.get(0), __); + // Just think of it as quantum state teleportation... + } + + @Koan + public void usingBackedSubMap() { + TreeMap map = new TreeMap(); + map.put("a", "Aha"); + map.put("b", "Boo"); + map.put("c", "Coon"); + map.put("e", "Emu"); + map.put("f", "Fox"); + SortedMap backedMap = map.subMap("c", "f"); + assertEquals(backedMap.size(), __); + assertEquals(map.size(), __); + backedMap.put("d", "Dog"); + assertEquals(backedMap.size(), __); + assertEquals(map.size(), __); + assertEquals(map.containsKey("d"), __); + // Again: backed maps are just like those little quantum states + // that are connected forever... + } + + @Koan + public void differenceBetweenOrderedAndSorted() { + TreeSet sorted = new TreeSet(); + sorted.add("c"); + sorted.add("z"); + sorted.add("a"); + assertEquals(sorted.first(), __); + assertEquals(sorted.last(), __); + // Look at the different constructors for a TreeSet (or TreeMap) + // Ponder how you might influence the sort order. Hold that thought + // until you approach AboutComparison + + LinkedHashSet ordered = new LinkedHashSet(); + ordered.add("c"); + ordered.add("z"); + ordered.add("a"); + StringBuffer sb = new StringBuffer(); + for (String s : ordered) { + sb.append(s); + } + assertEquals(sb.toString(), __); + } } diff --git a/koans/src/intermediate/AboutComparison.java b/koans/src/intermediate/AboutComparison.java index c371b11c..ee58ab64 100644 --- a/koans/src/intermediate/AboutComparison.java +++ b/koans/src/intermediate/AboutComparison.java @@ -1,76 +1,83 @@ package intermediate; -import static com.sandwich.koan.constant.KoanConstants.__; -import static com.sandwich.util.Assert.assertEquals; +import com.sandwich.koan.Koan; import java.util.Arrays; import java.util.Comparator; -import com.sandwich.koan.Koan; +import static com.sandwich.koan.constant.KoanConstants.__; +import static com.sandwich.util.Assert.assertEquals; public class AboutComparison { - @Koan - public void compareObjects() { - String a = "abc"; - String b = "bcd"; - assertEquals(a.compareTo(b), __); - assertEquals(a.compareTo(a), __); - assertEquals(b.compareTo(a), __); - } - - static class Car implements Comparable { - int horsepower; - // For an explanation for this implementation look at - // http://download.oracle.com/javase/6/docs/api/java/lang/Comparable.html#compareTo(T) - public int compareTo(Car o) { - return horsepower - o.horsepower; - } - - } - - @Koan - public void makeObjectsComparable() { - Car vwbeetle = new Car(); - vwbeetle.horsepower = 50; - Car porsche = new Car(); - porsche.horsepower = 300; - assertEquals(vwbeetle.compareTo(porsche), __); - } - - static class RaceHorse { - int speed; - int age; - @Override - public String toString() { - return "Speed: " + speed + " Age: " + age; - } - } - static class HorseSpeedComparator implements Comparator { - public int compare(RaceHorse o1, RaceHorse o2) { - return o1.speed - o2.speed; - } - } - static class HorseAgeComparator implements Comparator { - public int compare(RaceHorse o1, RaceHorse o2) { - return o1.age - o2.age; - } - } - - @Koan - public void makeObjectsComparableWithoutComparable() { - RaceHorse lindy = new RaceHorse(); - lindy.age = 10; lindy.speed = 2; - RaceHorse lightning = new RaceHorse(); - lightning.age = 2; lightning.speed = 10; - RaceHorse slowy = new RaceHorse(); - slowy.age = 12; slowy.speed = 1; - - RaceHorse[] horses = {lindy, slowy, lightning}; - - Arrays.sort(horses, new HorseAgeComparator()); - assertEquals(horses[0], __); - Arrays.sort(horses, new HorseSpeedComparator()); - assertEquals(horses[0], __); - } + @Koan + public void compareObjects() { + String a = "abc"; + String b = "bcd"; + assertEquals(a.compareTo(b), __); + assertEquals(a.compareTo(a), __); + assertEquals(b.compareTo(a), __); + } + + static class Car implements Comparable { + int horsepower; + + // For an explanation for this implementation look at + // http://download.oracle.com/javase/6/docs/api/java/lang/Comparable.html#compareTo(T) + public int compareTo(Car o) { + return horsepower - o.horsepower; + } + + } + + @Koan + public void makeObjectsComparable() { + Car vwbeetle = new Car(); + vwbeetle.horsepower = 50; + Car porsche = new Car(); + porsche.horsepower = 300; + assertEquals(vwbeetle.compareTo(porsche), __); + } + + static class RaceHorse { + int speed; + int age; + + @Override + public String toString() { + return "Speed: " + speed + " Age: " + age; + } + } + + static class HorseSpeedComparator implements Comparator { + public int compare(RaceHorse o1, RaceHorse o2) { + return o1.speed - o2.speed; + } + } + + static class HorseAgeComparator implements Comparator { + public int compare(RaceHorse o1, RaceHorse o2) { + return o1.age - o2.age; + } + } + + @Koan + public void makeObjectsComparableWithoutComparable() { + RaceHorse lindy = new RaceHorse(); + lindy.age = 10; + lindy.speed = 2; + RaceHorse lightning = new RaceHorse(); + lightning.age = 2; + lightning.speed = 10; + RaceHorse slowy = new RaceHorse(); + slowy.age = 12; + slowy.speed = 1; + + RaceHorse[] horses = {lindy, slowy, lightning}; + + Arrays.sort(horses, new HorseAgeComparator()); + assertEquals(horses[0], __); + Arrays.sort(horses, new HorseSpeedComparator()); + assertEquals(horses[0], __); + } } diff --git a/koans/src/intermediate/AboutDates.java b/koans/src/intermediate/AboutDates.java index d6012cbe..6a157b76 100644 --- a/koans/src/intermediate/AboutDates.java +++ b/koans/src/intermediate/AboutDates.java @@ -1,7 +1,6 @@ package intermediate; -import static com.sandwich.koan.constant.KoanConstants.__; -import static com.sandwich.util.Assert.assertEquals; +import com.sandwich.koan.Koan; import java.text.DateFormat; import java.text.ParseException; @@ -9,65 +8,66 @@ import java.util.Calendar; import java.util.Date; -import com.sandwich.koan.Koan; +import static com.sandwich.koan.constant.KoanConstants.__; +import static com.sandwich.util.Assert.assertEquals; public class AboutDates { - - private Date date = new Date(100010001000L); - - @Koan - public void dateToString() { - assertEquals(date.toString(), __); - } - - @Koan - public void changingDateValue() { - int oneHourInMiliseconds = 3600000; - date.setTime(date.getTime() + oneHourInMiliseconds); - assertEquals(date.toString(), __); - } - - @Koan - public void usingCalendarToChangeDates() { - Calendar cal = Calendar.getInstance(); - cal.setTime(date); - cal.add(Calendar.MONTH, 1); - assertEquals(cal.getTime().toString(), __); - } - @Koan - public void usingRollToChangeDatesDoesntWrapOtherFields() { - Calendar cal = Calendar.getInstance(); - cal.setTime(date); - cal.roll(Calendar.MONTH, 12); - assertEquals(cal.getTime().toString(), __); - } - - @Koan - public void usingDateFormatToFormatDate() { - String formattedDate = DateFormat.getDateInstance().format(date); - assertEquals(formattedDate, __); - } - - @Koan - public void usingDateFormatToFormatDateShort() { - String formattedDate = DateFormat.getDateInstance(DateFormat.SHORT).format(date); - assertEquals(formattedDate, __); - } - - @Koan - public void usingDateFormatToFormatDateFull() { - String formattedDate = DateFormat.getDateInstance(DateFormat.FULL).format(date); - // There is also DateFormat.MEDIUM and DateFormat.LONG... you get the idea ;-) - assertEquals(formattedDate, __); - } - - @Koan - public void usingDateFormatToParseDates() throws ParseException { - DateFormat dateFormat = new SimpleDateFormat("MM-dd-yyyy"); - Date date2 = dateFormat.parse("01-01-2000"); - assertEquals(date2.toString(), __); - // What happened to the time? What do you need to change to keep the time as well? - } + private Date date = new Date(100010001000L); + + @Koan + public void dateToString() { + assertEquals(date.toString(), __); + } + + @Koan + public void changingDateValue() { + int oneHourInMiliseconds = 3600000; + date.setTime(date.getTime() + oneHourInMiliseconds); + assertEquals(date.toString(), __); + } + + @Koan + public void usingCalendarToChangeDates() { + Calendar cal = Calendar.getInstance(); + cal.setTime(date); + cal.add(Calendar.MONTH, 1); + assertEquals(cal.getTime().toString(), __); + } + + @Koan + public void usingRollToChangeDatesDoesntWrapOtherFields() { + Calendar cal = Calendar.getInstance(); + cal.setTime(date); + cal.roll(Calendar.MONTH, 12); + assertEquals(cal.getTime().toString(), __); + } + + @Koan + public void usingDateFormatToFormatDate() { + String formattedDate = DateFormat.getDateInstance().format(date); + assertEquals(formattedDate, __); + } + + @Koan + public void usingDateFormatToFormatDateShort() { + String formattedDate = DateFormat.getDateInstance(DateFormat.SHORT).format(date); + assertEquals(formattedDate, __); + } + + @Koan + public void usingDateFormatToFormatDateFull() { + String formattedDate = DateFormat.getDateInstance(DateFormat.FULL).format(date); + // There is also DateFormat.MEDIUM and DateFormat.LONG... you get the idea ;-) + assertEquals(formattedDate, __); + } + + @Koan + public void usingDateFormatToParseDates() throws ParseException { + DateFormat dateFormat = new SimpleDateFormat("MM-dd-yyyy"); + Date date2 = dateFormat.parse("01-01-2000"); + assertEquals(date2.toString(), __); + // What happened to the time? What do you need to change to keep the time as well? + } } diff --git a/koans/src/intermediate/AboutEquality.java b/koans/src/intermediate/AboutEquality.java index 7eb9ef98..f3f50e8e 100644 --- a/koans/src/intermediate/AboutEquality.java +++ b/koans/src/intermediate/AboutEquality.java @@ -1,122 +1,128 @@ package intermediate; import com.sandwich.koan.Koan; + import static com.sandwich.koan.constant.KoanConstants.__; import static com.sandwich.util.Assert.assertEquals; public class AboutEquality { - // This suite of Koans expands on the concepts introduced in beginner.AboutEquality - - @Koan - public void sameObject() { - Object a = new Object(); - Object b = a; - assertEquals(a == b, __); - } - - @Koan - public void equalObject() { - Integer a = new Integer(1); - Integer b = new Integer(1); - assertEquals(a.equals(b), __); - assertEquals(b.equals(a), __); - } - - @Koan - public void noObjectShouldBeEqualToNull() { - assertEquals(new Object().equals(null), __); - } - - static class Car { - @SuppressWarnings("unused") - private String name = ""; - @SuppressWarnings("unused") - private int horsepower = 0; - public Car(String s, int p) { - name = s; horsepower = p; - } - @Override - public boolean equals(Object other) { - // Change this implementation to match the equals contract - // Car objects with same horsepower and name values should be considered equal - // http://download.oracle.com/javase/6/docs/api/java/lang/Object.html#equals(java.lang.Object) - return false; - } - - @Override - public int hashCode() { - // see koan ownHashCode - return super.hashCode(); - } - } - @Koan - public void equalForOwnObjects() { - Car car1 = new Car("Beetle", 50); - Car car2 = new Car("Beetle", 50); - // See line 37 for the task you have to solve - assertEquals(car1.equals(car2), true); - assertEquals(car2.equals(car1), true); - } - - @Koan - public void unequalForOwnObjects() { - Car car1 = new Car("Beetle", 50); - Car car2 = new Car("Porsche", 300); - // See line 37 for the task you have to solve - assertEquals(car1.equals(car2), false); - } - - @Koan - public void unequalForOwnObjectsWithDifferentType() { - Car car1 = new Car("Beetle", 50); - String s = "foo"; - // See line 37 for the task you have to solve - assertEquals(car1.equals(s), false); - } - - @Koan - public void equalNullForOwnObjects() { - Car car1 = new Car("Beetle", 50); - // See line 37 for the task you have to solve - assertEquals(car1.equals(null), false); - } - - @Koan - public void ownHashCode() { - // As a general rule: When you override equals you should override - // hash code - // Read the hash code contract to figure out why - // http://download.oracle.com/javase/6/docs/api/java/lang/Object.html#hashCode() - - // Implement a hash code version in line 47 so that the following assertions pass - Car car1 = new Car("Beetle", 50); - Car car2 = new Car("Beetle", 50); - assertEquals(car1.equals(car2), true); - assertEquals(car1.hashCode() == car2.hashCode(), true); - } - - static class Chicken { - String color = "green"; - @Override - public int hashCode() { - return 4000; - } - @Override - public boolean equals(Object other) { - if(!(other instanceof Chicken)) - return false; - return ((Chicken)other).color.equals(color); - } - } - - @Koan - public void ownHashCodeImplementationPartTwo() { - Chicken chicken1 = new Chicken(); chicken1.color = "black"; - Chicken chicken2 = new Chicken(); - assertEquals(chicken1.equals(chicken2), __); - assertEquals(chicken1.hashCode() == chicken2.hashCode(), __); - // Does this still fit the hashCode contract? Why? - // If it's valid why is this still not a good idea? - } - + // This suite of Koans expands on the concepts introduced in beginner.AboutEquality + + @Koan + public void sameObject() { + Object a = new Object(); + Object b = a; + assertEquals(a == b, __); + } + + @Koan + public void equalObject() { + Integer a = new Integer(1); + Integer b = new Integer(1); + assertEquals(a.equals(b), __); + assertEquals(b.equals(a), __); + } + + @Koan + public void noObjectShouldBeEqualToNull() { + assertEquals(new Object().equals(null), __); + } + + static class Car { + private String name = ""; + private int horsepower = 0; + + public Car(String s, int p) { + name = s; + horsepower = p; + } + + @Override + public boolean equals(Object other) { + // Change this implementation to match the equals contract + // Car objects with same horsepower and name values should be considered equal + // http://download.oracle.com/javase/6/docs/api/java/lang/Object.html#equals(java.lang.Object) + return false; + } + + @Override + public int hashCode() { + // @see http://download.oracle.com/javase/6/docs/api/java/lang/Object.html#hashCode() + return super.hashCode(); + } + } + + @Koan + public void equalForOwnObjects() { + Car car1 = new Car("Beetle", 50); + Car car2 = new Car("Beetle", 50); + // @see Car.equals (around line 45) for the place to solve this + assertEquals(car1.equals(car2), true); + assertEquals(car2.equals(car1), true); + } + + @Koan + public void unequalForOwnObjects() { + Car car1 = new Car("Beetle", 50); + Car car2 = new Car("Porsche", 300); + // @see Car.equals (around line 45) for the place to solve this + assertEquals(car1.equals(car2), false); + } + + @Koan + public void unequalForOwnObjectsWithDifferentType() { + Car car1 = new Car("Beetle", 50); + String s = "foo"; + // @see Car.equals (around line 45) for the place to solve this + assertEquals(car1.equals(s), false); + } + + @Koan + public void equalNullForOwnObjects() { + Car car1 = new Car("Beetle", 50); + // @see Car.equals (around line 45) for the place to solve this + assertEquals(car1.equals(null), false); + } + + @Koan + public void ownHashCode() { + // As a general rule: When you override equals you should override + // hash code + // Read the hash code contract to figure out why + // http://download.oracle.com/javase/6/docs/api/java/lang/Object.html#hashCode() + + // Implement Car.hashCode around line 51 so that the following assertions pass + Car car1 = new Car("Beetle", 50); + Car car2 = new Car("Beetle", 50); + assertEquals(car1.equals(car2), true); + assertEquals(car1.hashCode() == car2.hashCode(), true); + } + + static class Chicken { + String color = "green"; + + @Override + public int hashCode() { + return 4000; + } + + @Override + public boolean equals(Object other) { + if (!(other instanceof Chicken)) + return false; + return ((Chicken) other).color.equals(color); + } + } + + @Koan + public void ownHashCodeImplementationPartTwo() { + Chicken chicken1 = new Chicken(); + chicken1.color = "black"; + Chicken chicken2 = new Chicken(); + assertEquals(chicken1.equals(chicken2), __); + assertEquals(chicken1.hashCode() == chicken2.hashCode(), __); + // Does this still fit the hashCode contract? Why (not)? + // Fix the Chicken class to correct this. + } + } diff --git a/koans/src/intermediate/AboutFileIO.java b/koans/src/intermediate/AboutFileIO.java index 4c5e74d1..3fb98e7d 100644 --- a/koans/src/intermediate/AboutFileIO.java +++ b/koans/src/intermediate/AboutFileIO.java @@ -1,98 +1,98 @@ package intermediate; -import static com.sandwich.koan.constant.KoanConstants.__; -import static com.sandwich.util.Assert.assertEquals; +import com.sandwich.koan.Koan; -import java.io.BufferedReader; -import java.io.File; -import java.io.FileReader; -import java.io.FileWriter; -import java.io.IOException; -import java.io.PrintWriter; +import java.io.*; import java.util.logging.Logger; -import com.sandwich.koan.Koan; +import static com.sandwich.koan.constant.KoanConstants.__; +import static com.sandwich.util.Assert.assertEquals; public class AboutFileIO { - @Koan - public void fileObjectDoesntCreateFile() { - File f = new File("foo.txt"); - assertEquals(f.exists(), __); - } + @Koan + public void fileObjectDoesntCreateFile() { + File f = new File("i-never.exist"); + assertEquals(f.exists(), __); + } + + @Koan + public void fileCreationAndDeletion() throws IOException { + File f = new File("foo.txt"); + f.createNewFile(); + assertEquals(f.exists(), __); + f.delete(); + assertEquals(f.exists(), __); + } - @Koan - public void fileCreationAndDeletion() throws IOException { - File f = new File("foo.txt"); - f.createNewFile(); - assertEquals(f.exists(), __); - f.delete(); - assertEquals(f.exists(), __); - } + @Koan + public void basicFileWritingAndReading() throws IOException { + File file = new File("file.txt"); + FileWriter fw = new FileWriter(file); + String data = "First line\nSecond line"; + fw.write(data); + fw.flush(); + fw.close(); - @Koan - public void basicFileWritingAndReading() throws IOException { - File file = new File("file.txt"); - FileWriter fw = new FileWriter(file); - fw.write("First line\nSecond line"); - fw.flush(); - fw.close(); + char[] in = new char[data.length()]; + int size = 0; + FileReader fr = new FileReader(file); + size = fr.read(in); + // No flush necessary! + fr.close(); + assertEquals(size, __); + String expected = new String(in); + assertEquals(expected.length(), __); + assertEquals(expected, __); + file.delete(); + } - char[] in = new char[50]; - int size = 0; - FileReader fr = new FileReader(file); - size = fr.read(in); - // No flush necessary! - fr.close(); - assertEquals(size, __); - assertEquals(new String(in), __); - file.delete(); - } + @Koan + public void betterFileWritingAndReading() throws IOException { + File file = new File("file.txt"); + file.deleteOnExit(); + FileWriter fw = new FileWriter(file); + PrintWriter pw = new PrintWriter(fw); + pw.println("First line"); + pw.println("Second line"); + pw.close(); - @Koan - public void betterFileWritingAndReading() throws IOException { - File file = new File("file.txt"); - file.deleteOnExit(); - FileWriter fw = new FileWriter(file); - PrintWriter pw = new PrintWriter(fw); - pw.println("First line"); - pw.println("Second line"); - pw.close(); + FileReader fr = new FileReader(file); + BufferedReader br = null; + try { + br = new BufferedReader(fr); + assertEquals(br.readLine(), __); // first line + assertEquals(br.readLine(), __); // second line + assertEquals(br.readLine(), __); // what now? + } finally { + // anytime you open access to a file, you should close it or you may + // lock it from other processes (ie frustrate people) + closeStream(br); + } + } - FileReader fr = new FileReader(file); - BufferedReader br = null; - try{ - br = new BufferedReader(fr); - assertEquals(br.readLine(), __); // first line - assertEquals(br.readLine(), __); // second line - assertEquals(br.readLine(), __); // what now? - } finally { - closeStream(br); // anytime you open access to a - } - } + private void closeStream(BufferedReader br) { + if (br != null) { + try { + br.close(); + } catch (IOException x) { + Logger.getAnonymousLogger().severe("Unable to close reader."); + } + } + } - private void closeStream(BufferedReader br) { - if(br != null){ - try{ - br.close(); - } catch (IOException x) { - Logger.getAnonymousLogger().severe("Unable to close reader."); - } - } - } - - @Koan - public void directChainingForReadingAndWriting() throws IOException { - File file = new File("file.txt"); - PrintWriter pw = new PrintWriter(file); - pw.println("1. line"); - pw.println("2. line"); - pw.close(); + @Koan + public void directChainingForReadingAndWriting() throws IOException { + File file = new File("file.txt"); + PrintWriter pw = new PrintWriter(file); + pw.println("1. line"); + pw.println("2. line"); + pw.close(); - StringBuffer sb = new StringBuffer(); - // Add the loop to go through the file line by line and add the line - // to the StringBuffer - assertEquals(sb.toString(), "1. line\n2. line"); - } + StringBuffer sb = new StringBuffer(); + // Add the loop to go through the file line by line and add the line + // to the StringBuffer + assertEquals(sb.toString(), "1. line\n2. line"); + } } diff --git a/koans/src/intermediate/AboutInnerClasses.java b/koans/src/intermediate/AboutInnerClasses.java index 841264e1..8d9c7d0f 100644 --- a/koans/src/intermediate/AboutInnerClasses.java +++ b/koans/src/intermediate/AboutInnerClasses.java @@ -1,133 +1,150 @@ package intermediate; +import com.sandwich.koan.Koan; + import static com.sandwich.koan.constant.KoanConstants.__; import static com.sandwich.util.Assert.assertEquals; -import com.sandwich.koan.Koan; - public class AboutInnerClasses { - interface Ignoreable { - String ignoreAll(); - } - - class Inner { - public String doStuff() { return "stuff"; } - public int returnOuter() { return x; } - } - - @Koan - public void creatingInnerClassInstance() { - Inner someObject = new Inner(); - assertEquals(someObject.doStuff(),__); - } - - @Koan - public void creatingInnerClassInstanceWithOtherSyntax() { - AboutInnerClasses.Inner someObject = this.new Inner(); - assertEquals(someObject.doStuff(),__); - } - - private int x = 10; - - @Koan - public void accessingOuterClassMembers() { - Inner someObject = new Inner(); - assertEquals(someObject.returnOuter(),__); - } - - @Koan - public void innerClassesInMethods() { - class MethodInnerClass { - int oneHundred() { return 100; } - } - assertEquals(new MethodInnerClass().oneHundred(), __); - // Where can you use this class? - } - - class AnotherInnerClass { - int thousand() { return 1000; } - - AnotherInnerClass crazyReturn() { - class SpecialInnerClass extends AnotherInnerClass { - int thousand() { - return 2000; - } - }; - return new SpecialInnerClass(); - } - } - - @Koan - public void innerClassesInMethodsThatEscape() { - AnotherInnerClass ic = new AnotherInnerClass(); - assertEquals(ic.thousand(), __); - AnotherInnerClass theCrazyIC = ic.crazyReturn(); - assertEquals(theCrazyIC.thousand(), __); - } - - int theAnswer() { return 42; } - - @Koan - public void creatingAnonymousInnerClasses() { - AboutInnerClasses anonymous = new AboutInnerClasses() { - int theAnswer() { return 23; } - };// <- Why do you need a semicolon here? - assertEquals(anonymous.theAnswer(), __); - } - - @Koan - public void creatingAnonymousInnerClassesToImplementInterface() { - Ignoreable ignoreable = new Ignoreable(){ - public String ignoreAll() { - return null; - } - }; // Complete the code so that the statement below is correct. - // Look at the koan above for inspiration - assertEquals(ignoreable.ignoreAll(), "SomeInterestingString"); - // Did you just created an object of an interface type? - // Or did you create a class that implemented this interface and - // an object of that type? - } - - @Koan - public void innerClassAndInheritance() { - Inner someObject = new Inner(); - // The statement below is obvious... - // Try to change the 'Inner' below to "AboutInnerClasses' - // Why do you get an error? - // What does that imply for inner classes and inheritance? - assertEquals(someObject instanceof Inner, __); - } - - class OtherInner extends AboutInnerClasses { } - - @Koan - public void innerClassAndInheritanceOther() { - OtherInner someObject = new OtherInner(); - // What do you expect here? - // Compare this result with the last koan. What does that mean? - assertEquals(someObject instanceof AboutInnerClasses, __); - } - - static class StaticInnerClass { - public int importantNumber() { return 3; } - } - - @Koan - public void staticInnerClass() { - StaticInnerClass someObject = new StaticInnerClass(); - assertEquals(someObject.importantNumber(), __); - // What happens if you try to access 'x' or 'theAnswer' from the outer class? - // What does this mean for static inner classes? - // Try to create a sub package of this package which is named 'StaticInnerClass' - // Does it work? Why not? - } - - @Koan - public void staticInnerClassFullyQualified() { - AboutInnerClasses.StaticInnerClass someObject = new AboutInnerClasses.StaticInnerClass(); - assertEquals(someObject.importantNumber(), __); - } + interface Ignoreable { + String ignoreAll(); + } + + class Inner { + public String doStuff() { + return "stuff"; + } + + public int returnOuter() { + return x; + } + } + + @Koan + public void creatingInnerClassInstance() { + Inner someObject = new Inner(); + assertEquals(someObject.doStuff(), __); + } + + @Koan + public void creatingInnerClassInstanceWithOtherSyntax() { + AboutInnerClasses.Inner someObject = this.new Inner(); + assertEquals(someObject.doStuff(), __); + } + + private int x = 10; + + @Koan + public void accessingOuterClassMembers() { + Inner someObject = new Inner(); + assertEquals(someObject.returnOuter(), __); + } + + @Koan + public void innerClassesInMethods() { + class MethodInnerClass { + int oneHundred() { + return 100; + } + } + assertEquals(new MethodInnerClass().oneHundred(), __); + // Where can you use this class? + } + + class AnotherInnerClass { + int thousand() { + return 1000; + } + + AnotherInnerClass crazyReturn() { + class SpecialInnerClass extends AnotherInnerClass { + int thousand() { + return 2000; + } + } + ; + return new SpecialInnerClass(); + } + } + + @Koan + public void innerClassesInMethodsThatEscape() { + AnotherInnerClass ic = new AnotherInnerClass(); + assertEquals(ic.thousand(), __); + AnotherInnerClass theCrazyIC = ic.crazyReturn(); + assertEquals(theCrazyIC.thousand(), __); + } + + int theAnswer() { + return 42; + } + + @Koan + public void creatingAnonymousInnerClasses() { + AboutInnerClasses anonymous = new AboutInnerClasses() { + int theAnswer() { + return 23; + } + };// <- Why do you need a semicolon here? + assertEquals(anonymous.theAnswer(), __); + } + + @Koan + public void creatingAnonymousInnerClassesToImplementInterface() { + Ignoreable ignoreable = new Ignoreable() { + public String ignoreAll() { + return null; + } + }; // Complete the code so that the statement below is correct. + // Look at the koan above for inspiration + assertEquals(ignoreable.ignoreAll(), "SomeInterestingString"); + // Did you just created an object of an interface type? + // Or did you create a class that implemented this interface and + // an object of that type? + } + + @Koan + public void innerClassAndInheritance() { + Inner someObject = new Inner(); + // The statement below is obvious... + // Try to change the 'Inner' below to "AboutInnerClasses' + // Why do you get an error? + // What does that imply for inner classes and inheritance? + assertEquals(someObject instanceof Inner, __); + } + + class OtherInner extends AboutInnerClasses { + } + + @Koan + public void innerClassAndInheritanceOther() { + OtherInner someObject = new OtherInner(); + // What do you expect here? + // Compare this result with the last koan. What does that mean? + assertEquals(someObject instanceof AboutInnerClasses, __); + } + + static class StaticInnerClass { + public int importantNumber() { + return 3; + } + } + + @Koan + public void staticInnerClass() { + StaticInnerClass someObject = new StaticInnerClass(); + assertEquals(someObject.importantNumber(), __); + // What happens if you try to access 'x' or 'theAnswer' from the outer class? + // What does this mean for static inner classes? + // Try to create a sub package of this package which is named 'StaticInnerClass' + // Does it work? Why not? + } + + @Koan + public void staticInnerClassFullyQualified() { + AboutInnerClasses.StaticInnerClass someObject = new AboutInnerClasses.StaticInnerClass(); + assertEquals(someObject.importantNumber(), __); + } } diff --git a/koans/src/intermediate/AboutLocale.java b/koans/src/intermediate/AboutLocale.java index 18d7a210..48729987 100644 --- a/koans/src/intermediate/AboutLocale.java +++ b/koans/src/intermediate/AboutLocale.java @@ -1,7 +1,6 @@ package intermediate; -import static com.sandwich.koan.constant.KoanConstants.__; -import static com.sandwich.util.Assert.assertEquals; +import com.sandwich.koan.Koan; import java.text.DateFormat; import java.text.NumberFormat; @@ -9,42 +8,43 @@ import java.util.Date; import java.util.Locale; -import com.sandwich.koan.Koan; +import static com.sandwich.koan.constant.KoanConstants.__; +import static com.sandwich.util.Assert.assertEquals; public class AboutLocale { - @Koan - public void localizedOutputOfDates() { - Calendar cal = Calendar.getInstance(); - cal.set(2011, 3, 3); - Date date = cal.getTime(); - Locale localeBR = new Locale("pt","BR"); // portuguese, Brazil - DateFormat dateformatBR = DateFormat.getDateInstance(DateFormat.FULL, localeBR); - assertEquals(dateformatBR.format(date), __); - - Locale localeJA = new Locale("ja"); // Japan - DateFormat dateformatJA = DateFormat.getDateInstance(DateFormat.FULL, localeJA); - // Well if you don't know how to type these characters, try "de", "it" or "us" ;-) - assertEquals(dateformatJA.format(date), __); - } - - @Koan - public void getCountryInformation() { - Locale locBR = new Locale("pt","BR"); - assertEquals(locBR.getDisplayCountry(), __); - assertEquals(locBR.getDisplayCountry(locBR), __); - - Locale locCH = new Locale("it","CH"); - assertEquals(locCH.getDisplayCountry(), __); - assertEquals(locCH.getDisplayCountry(locCH), __); - assertEquals(locCH.getDisplayCountry(new Locale("de","CH")), __); - } - - @Koan - public void formatCurrency() { - float someAmount = 442.23f; // Don't use floats for money in real life. Really. It's a bad idea. - Locale locBR = new Locale("pt","BR"); - NumberFormat nf = NumberFormat.getCurrencyInstance(locBR); - assertEquals(nf.format(someAmount), __); - } + @Koan + public void localizedOutputOfDates() { + Calendar cal = Calendar.getInstance(); + cal.set(2011, 3, 3); + Date date = cal.getTime(); + Locale localeBR = new Locale("pt", "BR"); // portuguese, Brazil + DateFormat dateformatBR = DateFormat.getDateInstance(DateFormat.FULL, localeBR); + assertEquals(dateformatBR.format(date), __); + + Locale localeJA = new Locale("ja"); // Japan + DateFormat dateformatJA = DateFormat.getDateInstance(DateFormat.FULL, localeJA); + // Well if you don't know how to type these characters, try "de", "it" or "us" ;-) + assertEquals(dateformatJA.format(date), __); + } + + @Koan + public void getCountryInformation() { + Locale locBR = new Locale("pt", "BR"); + assertEquals(locBR.getDisplayCountry(), __); + assertEquals(locBR.getDisplayCountry(locBR), __); + + Locale locCH = new Locale("it", "CH"); + assertEquals(locCH.getDisplayCountry(), __); + assertEquals(locCH.getDisplayCountry(locCH), __); + assertEquals(locCH.getDisplayCountry(new Locale("de", "CH")), __); + } + + @Koan + public void formatCurrency() { + float someAmount = 442.23f; // Don't use floats for money in real life. Really. It's a bad idea. + Locale locBR = new Locale("pt", "BR"); + NumberFormat nf = NumberFormat.getCurrencyInstance(locBR); + assertEquals(nf.format(someAmount), __); + } } diff --git a/koans/src/intermediate/AboutRegularExpressions.java b/koans/src/intermediate/AboutRegularExpressions.java index ad0ad011..d5999645 100644 --- a/koans/src/intermediate/AboutRegularExpressions.java +++ b/koans/src/intermediate/AboutRegularExpressions.java @@ -1,57 +1,57 @@ package intermediate; -import static com.sandwich.koan.constant.KoanConstants.__; -import static com.sandwich.util.Assert.assertEquals; +import com.sandwich.koan.Koan; import java.util.regex.Matcher; import java.util.regex.Pattern; -import com.sandwich.koan.Koan; +import static com.sandwich.koan.constant.KoanConstants.__; +import static com.sandwich.util.Assert.assertEquals; public class AboutRegularExpressions { - - @Koan - public void basicMatching() { - Pattern p = Pattern.compile("xyz"); - Matcher m = p.matcher("xyzxxxxyz"); - // index 012345678 - assertEquals(m.find(), __); - assertEquals(m.start(), __); - assertEquals(m.find(), __); - assertEquals(m.start(), __); - assertEquals(m.find(), __); - } - - @Koan - public void extendedMatching() { - Pattern p = Pattern.compile("x.z"); - Matcher m = p.matcher("xyz u x z u xfz"); - // index 012345678901234 - assertEquals(m.find(), __); - assertEquals(m.start(), __); - assertEquals(m.find(), __); - assertEquals(m.start(), __); - assertEquals(m.find(), __); - assertEquals(m.start(), __); - } - - @Koan - public void escapingMetaCharacters() { - Pattern p = Pattern.compile("end\\."); - Matcher m = p.matcher("begin. end."); - // index 01234567890 - assertEquals(m.find(), __); - assertEquals(m.start(), __); - } - - @Koan - public void splittingStrings() { - String csvDataLine = "1,name,description"; - String[] data = csvDataLine.split(","); // you can use any regex here - assertEquals(data[0], __); - assertEquals(data[1], __); - assertEquals(data[2], __); - } + + @Koan + public void basicMatching() { + Pattern p = Pattern.compile("xyz"); + Matcher m = p.matcher("xyzxxxxyz"); + // index 012345678 + assertEquals(m.find(), __); + assertEquals(m.start(), __); + assertEquals(m.find(), __); + assertEquals(m.start(), __); + assertEquals(m.find(), __); + } + + @Koan + public void extendedMatching() { + Pattern p = Pattern.compile("x.z"); + Matcher m = p.matcher("xyz u x z u xfz"); + // index 012345678901234 + assertEquals(m.find(), __); + assertEquals(m.start(), __); + assertEquals(m.find(), __); + assertEquals(m.start(), __); + assertEquals(m.find(), __); + assertEquals(m.start(), __); + } + + @Koan + public void escapingMetaCharacters() { + Pattern p = Pattern.compile("end\\."); + Matcher m = p.matcher("begin. end."); + // index 01234567890 + assertEquals(m.find(), __); + assertEquals(m.start(), __); + } + + @Koan + public void splittingStrings() { + String csvDataLine = "1,name,description"; + String[] data = csvDataLine.split(","); // you can use any regex here + assertEquals(data[0], __); + assertEquals(data[1], __); + assertEquals(data[2], __); + } } diff --git a/koans/src/intermediate/AboutSerialization.java b/koans/src/intermediate/AboutSerialization.java index 3771f1f9..b4b428e7 100644 --- a/koans/src/intermediate/AboutSerialization.java +++ b/koans/src/intermediate/AboutSerialization.java @@ -1,221 +1,224 @@ package intermediate; -import static com.sandwich.koan.constant.KoanConstants.__; -import static com.sandwich.util.Assert.assertEquals; +import com.sandwich.koan.Koan; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.NotSerializableException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.io.Serializable; +import java.io.*; import java.util.logging.Logger; -import com.sandwich.koan.Koan; +import static com.sandwich.koan.constant.KoanConstants.__; +import static com.sandwich.util.Assert.assertEquals; public class AboutSerialization { - - @Koan - public void simpleSerialization() throws FileNotFoundException, IOException, ClassNotFoundException { - String s = "Hello world"; - // serialize - File file = new File("SerializeFile"); - file.deleteOnExit(); - ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream(file)); - os.writeObject(s); - os.close(); - - // deserialize - ObjectInputStream is = null; - try{ - is = new ObjectInputStream(new FileInputStream("SerializeFile")); - String otherString = (String)is.readObject(); - assertEquals(otherString, __); - }finally{ - closeStream(is); - } - } - - static class Starship implements Serializable { - - // Although it is not enforced, you should define this constant - // to make sure you serialize/deserialize only compatible versions - // of your objects - private static final long serialVersionUID = 1L; - int maxWarpSpeed; - } - - @Koan - public void customObjectSerialization() throws IOException, ClassNotFoundException { - Starship s = new Starship(); - s.maxWarpSpeed = 9; - File file = new File("SerializeFile"); - file.deleteOnExit(); - ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream(file)); - os.writeObject(s); - os.close(); - - ObjectInputStream is = null; - try{ - is = new ObjectInputStream(new FileInputStream("SerializeFile")); - Starship onTheOtherSide = (Starship)is.readObject(); - assertEquals(onTheOtherSide.maxWarpSpeed, __); - }finally{ - closeStream(is); - } - } - - static class Engine { - String type; - public Engine(String t) { type = t; } - }; - - @SuppressWarnings("serial") - static class Car implements Serializable { - // Transient means: Ignore field for serialization - transient Engine engine; - // Notice these methods are private and will be called by the JVM - // internally - as if they where defined by the Serializable interface - // but they aren't defined as part of the interface - private void writeObject(ObjectOutputStream os) throws IOException { - os.defaultWriteObject(); - os.writeObject(engine.type); - } - private void readObject(ObjectInputStream is) throws IOException, ClassNotFoundException { - is.defaultReadObject(); - engine = new Engine((String)is.readObject()); - } - } - - @Koan - public void customObjectSerializationWithTransientFields() throws FileNotFoundException, IOException, ClassNotFoundException { - // Note that this kind of access of fields is not good OO practice. - // But let's focus on serialization here :) - Car car = new Car(); - car.engine = new Engine("diesel"); - File file = new File("SerializeFile"); - file.deleteOnExit(); - ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream(file)); - os.writeObject(car); - os.close(); - - ObjectInputStream is = null; - try{ - is = new ObjectInputStream(new FileInputStream("SerializeFile")); - Car deserializedCar = (Car)is.readObject(); - assertEquals(deserializedCar.engine.type, __); - }finally{ - closeStream(is); - } - } - - @SuppressWarnings("serial") - class Boat implements Serializable { - Engine engine; - } - - @Koan - public void customSerializationWithUnserializableFields() throws FileNotFoundException, IOException { - Boat boat = new Boat(); - boat.engine = new Engine("diesel"); - File file = new File("SerializeFile"); - file.deleteOnExit(); - ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream(file)); - String marker = "Start "; - try { - os.writeObject(boat); - } catch(NotSerializableException e) { - marker += "Exception"; - } - os.close(); - assertEquals(marker, __); - } - - @SuppressWarnings("serial") - static class Animal implements Serializable { - String name; - public Animal(String s) { - name = s; - } - } - - @SuppressWarnings("serial") - static class Dog extends Animal { - public Dog(String s) { - super(s); - } - } - - @Koan - public void serializeWithInheritance() throws IOException, ClassNotFoundException { - Dog d = new Dog("snoopy"); - File file = new File("SerializeFile"); - file.deleteOnExit(); - ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream(file)); - os.writeObject(d); - os.close(); - - ObjectInputStream is = null; - try{ - is = new ObjectInputStream(new FileInputStream("SerializeFile")); - Dog otherDog = (Dog)is.readObject(); - assertEquals(otherDog.name, __); - }finally{ - closeStream(is); - } - } - - static class Plane { - String name; - public Plane(String s) { - name = s; - } - public Plane() {}; - } - @SuppressWarnings("serial") - static class MilitaryPlane extends Plane implements Serializable { - public MilitaryPlane(String s) { - super(s); - } - } - - @Koan - public void serializeWithInheritanceWhenParentNotSerializable() throws FileNotFoundException, IOException, ClassNotFoundException { - MilitaryPlane p = new MilitaryPlane("F22"); - - ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream("SerializeFile")); - os.writeObject(p); - os.close(); - - ObjectInputStream is = null; - try{ - is = new ObjectInputStream(new FileInputStream("SerializeFile")); - MilitaryPlane otherPlane = (MilitaryPlane)is.readObject(); - // Does this surprise you? - assertEquals(otherPlane.name, __); - - // Think about how serialization creates objects... - // It does not use constructors! But if a parent object is not serializable - // it actually uses constructors and if the fields are not in a serializable class... - // unexpected things - like this - may happen - }finally{ - closeStream(is); - } - } - - private void closeStream(ObjectInputStream ois) { - if(ois != null){ - try{ - ois.close(); - } catch (IOException x) { - Logger.getAnonymousLogger().severe("Unable to close reader."); - } - } - } - + + @Koan + public void simpleSerialization() throws FileNotFoundException, IOException, ClassNotFoundException { + String s = "Hello world"; + // serialize + File file = new File("SerializeFile"); + file.deleteOnExit(); + ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream(file)); + os.writeObject(s); + os.close(); + + // deserialize + ObjectInputStream is = null; + try { + is = new ObjectInputStream(new FileInputStream("SerializeFile")); + String otherString = (String) is.readObject(); + assertEquals(otherString, __); + } finally { + closeStream(is); + } + } + + static class Starship implements Serializable { + + // Although it is not enforced, you should define this constant + // to make sure you serialize/deserialize only compatible versions + // of your objects + private static final long serialVersionUID = 1L; + int maxWarpSpeed; + } + + @Koan + public void customObjectSerialization() throws IOException, ClassNotFoundException { + Starship s = new Starship(); + s.maxWarpSpeed = 9; + File file = new File("SerializeFile"); + file.deleteOnExit(); + ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream(file)); + os.writeObject(s); + os.close(); + + ObjectInputStream is = null; + try { + is = new ObjectInputStream(new FileInputStream("SerializeFile")); + Starship onTheOtherSide = (Starship) is.readObject(); + assertEquals(onTheOtherSide.maxWarpSpeed, __); + } finally { + closeStream(is); + } + } + + static class Engine { + String type; + + public Engine(String t) { + type = t; + } + } + + @SuppressWarnings("serial") + static class Car implements Serializable { + // Transient means: Ignore field for serialization + transient Engine engine; + + // Notice these methods are private and will be called by the JVM + // internally - as if they where defined by the Serializable interface + // but they aren't defined as part of the interface + private void writeObject(ObjectOutputStream os) throws IOException { + os.defaultWriteObject(); + os.writeObject(engine.type); + } + + private void readObject(ObjectInputStream is) throws IOException, ClassNotFoundException { + is.defaultReadObject(); + engine = new Engine((String) is.readObject()); + } + } + + @Koan + public void customObjectSerializationWithTransientFields() throws FileNotFoundException, IOException, ClassNotFoundException { + // Note that this kind of access of fields is not good OO practice. + // But let's focus on serialization here :) + Car car = new Car(); + car.engine = new Engine("diesel"); + File file = new File("SerializeFile"); + file.deleteOnExit(); + ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream(file)); + os.writeObject(car); + os.close(); + + ObjectInputStream is = null; + try { + is = new ObjectInputStream(new FileInputStream("SerializeFile")); + Car deserializedCar = (Car) is.readObject(); + assertEquals(deserializedCar.engine.type, __); + } finally { + closeStream(is); + } + } + + @SuppressWarnings("serial") + class Boat implements Serializable { + Engine engine; + } + + @Koan + public void customSerializationWithUnserializableFields() throws FileNotFoundException, IOException { + Boat boat = new Boat(); + boat.engine = new Engine("diesel"); + File file = new File("SerializeFile"); + file.deleteOnExit(); + ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream(file)); + String marker = "Start "; + try { + os.writeObject(boat); + } catch (NotSerializableException e) { + marker += "Exception"; + } + os.close(); + assertEquals(marker, __); + } + + @SuppressWarnings("serial") + static class Animal implements Serializable { + String name; + + public Animal(String s) { + name = s; + } + } + + @SuppressWarnings("serial") + static class Dog extends Animal { + public Dog(String s) { + super(s); + } + } + + @Koan + public void serializeWithInheritance() throws IOException, ClassNotFoundException { + Dog d = new Dog("snoopy"); + File file = new File("SerializeFile"); + file.deleteOnExit(); + ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream(file)); + os.writeObject(d); + os.close(); + + ObjectInputStream is = null; + try { + is = new ObjectInputStream(new FileInputStream("SerializeFile")); + Dog otherDog = (Dog) is.readObject(); + assertEquals(otherDog.name, __); + } finally { + closeStream(is); + } + } + + static class Plane { + String name; + + public Plane(String s) { + name = s; + } + + public Plane() { + } + + } + + @SuppressWarnings("serial") + static class MilitaryPlane extends Plane implements Serializable { + public MilitaryPlane(String s) { + super(s); + } + } + + @Koan + public void serializeWithInheritanceWhenParentNotSerializable() throws FileNotFoundException, IOException, ClassNotFoundException { + MilitaryPlane p = new MilitaryPlane("F22"); + + ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream("SerializeFile")); + os.writeObject(p); + os.close(); + + ObjectInputStream is = null; + try { + is = new ObjectInputStream(new FileInputStream("SerializeFile")); + MilitaryPlane otherPlane = (MilitaryPlane) is.readObject(); + // Does this surprise you? + assertEquals(otherPlane.name, __); + + // Think about how serialization creates objects... + // It does not use constructors! But if a parent object is not serializable + // it actually uses constructors and if the fields are not in a serializable class... + // unexpected things - like this - may happen + } finally { + closeStream(is); + } + } + + private void closeStream(ObjectInputStream ois) { + if (ois != null) { + try { + ois.close(); + } catch (IOException x) { + Logger.getAnonymousLogger().severe("Unable to close reader."); + } + } + } + } diff --git a/koans/src/java7/AboutDiamondOperator.java b/koans/src/java7/AboutDiamondOperator.java index 87a97d41..a9c32ac0 100644 --- a/koans/src/java7/AboutDiamondOperator.java +++ b/koans/src/java7/AboutDiamondOperator.java @@ -12,7 +12,7 @@ public class AboutDiamondOperator { @Koan - public void diamondOperator () { + public void diamondOperator() { String[] animals = {"Dog", "Cat", "Tiger", "Elephant", "Zebra"}; //Generic type of array list inferred - empty <> operator List animalsList = new ArrayList<>(Arrays.asList(animals)); @@ -20,14 +20,14 @@ public void diamondOperator () { } @Koan - public void diamondOperatorInMethodCall () { + public void diamondOperatorInMethodCall() { String[] animals = {"Dog", "Cat", "Tiger", "Elephant", "Zebra"}; //type of new ArrayList<>() inferred from method parameter List animalsList = fill(new ArrayList<>()); assertEquals(animalsList, __); } - private List fill(List list){ + private List fill(List list) { String[] animals = {"Dog", "Cat", "Tiger", "Elephant", "Zebra"}; list.addAll(Arrays.asList(animals)); return list; diff --git a/koans/src/java7/AboutJava7LiteralsEnhancements.java b/koans/src/java7/AboutJava7LiteralsEnhancements.java index ef7842e1..4d8e2a38 100644 --- a/koans/src/java7/AboutJava7LiteralsEnhancements.java +++ b/koans/src/java7/AboutJava7LiteralsEnhancements.java @@ -10,14 +10,14 @@ public class AboutJava7LiteralsEnhancements { @Koan public void binaryLiterals() { //binary literals are marked with 0b prefix - short binaryLiteral = 0b1111; + short binaryLiteral = 0b1111; assertEquals(binaryLiteral, __); } @Koan public void binaryLiteralsWithUnderscores() { //literals can use underscores for improved readability - short binaryLiteral = 0b1111_1111; + short binaryLiteral = 0b1111_1111; assertEquals(binaryLiteral, __); } diff --git a/koans/src/java7/AboutRequireNotNull.java b/koans/src/java7/AboutRequireNotNull.java index 2fed11e2..de4b017f 100644 --- a/koans/src/java7/AboutRequireNotNull.java +++ b/koans/src/java7/AboutRequireNotNull.java @@ -1,47 +1,46 @@ package java7; -import static com.sandwich.koan.constant.KoanConstants.__; -import static com.sandwich.util.Assert.assertEquals; -import static com.sandwich.util.Assert.fail; +import com.sandwich.koan.Koan; import java.util.Objects; -import com.sandwich.koan.Koan; +import static com.sandwich.koan.constant.KoanConstants.__; +import static com.sandwich.util.Assert.assertEquals; public class AboutRequireNotNull { - - @Koan - public void failArgumentValidationWithRequireNotNull(){ - // This koan demonstrates the use of Objects.requireNotNull - // in place of traditional argument validation using exceptions - String s = ""; - try { - s += validateUsingRequireNotNull(null); - } catch (NullPointerException ex) { - s = "caught a NullPointerException"; - } - assertEquals(s, __); - } - - @Koan - public void passArgumentValidationWithRequireNotNull(){ - // This koan demonstrates the use of Objects.requireNotNull - // in place of traditional argument validation using exceptions - String s = ""; - try { - s += validateUsingRequireNotNull("valid"); - } catch (NullPointerException ex) { - s = "caught a NullPointerException"; - } - assertEquals(s, __); - } - - private int validateUsingRequireNotNull(String str) { - // If you're only concerned with null values requireNotNull - // is concise and the point of the NullPointerException it - // throws is clear, though you can optionally provide a - // description as well - return Objects.requireNonNull(str).length(); - } - + + @Koan + public void failArgumentValidationWithRequireNotNull() { + // This koan demonstrates the use of Objects.requireNotNull + // in place of traditional argument validation using exceptions + String s = ""; + try { + s += validateUsingRequireNotNull(null); + } catch (NullPointerException ex) { + s = "caught a NullPointerException"; + } + assertEquals(s, __); + } + + @Koan + public void passArgumentValidationWithRequireNotNull() { + // This koan demonstrates the use of Objects.requireNotNull + // in place of traditional argument validation using exceptions + String s = ""; + try { + s += validateUsingRequireNotNull("valid"); + } catch (NullPointerException ex) { + s = "caught a NullPointerException"; + } + assertEquals(s, __); + } + + private int validateUsingRequireNotNull(String str) { + // If you're only concerned with null values requireNotNull + // is concise and the point of the NullPointerException it + // throws is clear, though you can optionally provide a + // description as well + return Objects.requireNonNull(str).length(); + } + } diff --git a/koans/src/java7/AboutStringsInSwitch.java b/koans/src/java7/AboutStringsInSwitch.java index 86e26605..31a79c6f 100644 --- a/koans/src/java7/AboutStringsInSwitch.java +++ b/koans/src/java7/AboutStringsInSwitch.java @@ -8,15 +8,18 @@ public class AboutStringsInSwitch { @Koan - public void stringsInSwitchStatement () { + public void stringsInSwitchStatement() { String[] animals = {"Dog", "Cat", "Tiger", "Elephant", "Zebra"}; - String dangerous=null; - String notDangerous=null; - for (String animal : animals){ + String dangerous = null; + String notDangerous = null; + for (String animal : animals) { switch (animal) { case "Tiger": - dangerous = animal; - case "Dog" :case "Cat" :case "Elephant" :case "Zebra": + dangerous = animal; + case "Dog": + case "Cat": + case "Elephant": + case "Zebra": notDangerous = animal; } } diff --git a/koans/src/java7/AboutTryWithResources.java b/koans/src/java7/AboutTryWithResources.java index 952b89f4..4934b1e1 100644 --- a/koans/src/java7/AboutTryWithResources.java +++ b/koans/src/java7/AboutTryWithResources.java @@ -9,11 +9,12 @@ public class AboutTryWithResources { - class AutoClosableResource implements AutoCloseable{ - public void foo() throws WorkException{ + class AutoClosableResource implements AutoCloseable { + public void foo() throws WorkException { throw new WorkException("Exception thrown while working"); } - public void close() throws CloseException{ + + public void close() throws CloseException { throw new CloseException("Exception thrown while closing"); } } @@ -56,7 +57,7 @@ public void lookMaNoCloseWithException() throws IOException { new BufferedReader( new FileReader("I do not exist!"))) { line = br.readLine(); - }catch(FileNotFoundException e){ + } catch (FileNotFoundException e) { line = "no more leaking!"; } assertEquals(line, __); @@ -79,14 +80,14 @@ public void lookMaNoCloseWithMultipleResources() throws IOException { ) { line = br.readLine(); line += brFromString.readLine(); - }catch (IOException e) { + } catch (IOException e) { line = "error"; } assertEquals(line, __); } @Koan - public void supressException(){ + public void supressException() { String message = ""; try { bar(); 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) {} + } + +} diff --git a/koans/src/java8/AboutDefaultMethods.java b/koans/src/java8/AboutDefaultMethods.java index 4a1f5e15..d2a5c994 100644 --- a/koans/src/java8/AboutDefaultMethods.java +++ b/koans/src/java8/AboutDefaultMethods.java @@ -28,7 +28,7 @@ public void interfaceStaticMethod() { interface StringUtil { //static method in interface - static String enclose(String in){ + static String enclose(String in) { return "[" + in + "]"; } diff --git a/koans/src/java8/AboutLambdas.java b/koans/src/java8/AboutLambdas.java index f8fa2d33..8cab569b 100644 --- a/koans/src/java8/AboutLambdas.java +++ b/koans/src/java8/AboutLambdas.java @@ -3,10 +3,9 @@ import com.sandwich.koan.Koan; import java.util.function.Function; -import java.util.function.Predicate; -import static com.sandwich.util.Assert.assertEquals; import static com.sandwich.koan.constant.KoanConstants.__; +import static com.sandwich.util.Assert.assertEquals; public class AboutLambdas { @@ -24,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 { @@ -56,18 +55,19 @@ public void simpleSuccinctLambda() { @Koan public void lambdaField() { - assertEquals(lambdaField.capitalize(""), __); + assertEquals(thisLambdaField.capitalize(""), __); } @Koan public void lambdaField2() { - assertEquals(lambdaField2.capitalize(""), __); + assertEquals(toStringLambdaField.capitalize(""), __); } @Koan public void effectivelyFinal() { //final can be omitted like this: - /* final */ String effectivelyFinal = "I'm effectively final"; + /* final */ + String effectivelyFinal = "I'm effectively final"; Caps caps = s -> effectivelyFinal.toUpperCase(); assertEquals(caps.capitalize(effectivelyFinal), __); } @@ -82,7 +82,7 @@ public void methodReference() { @Koan public void thisIsSurroundingClass() { //"this" in lambda points to surrounding class - Function foo = s -> s + this.fieldFoo + s; + Function foo = s -> s + this.fieldFoo + s; assertEquals(foo.apply("|"), __); } diff --git a/koans/src/java8/AboutLocalTime.java b/koans/src/java8/AboutLocalTime.java index 5af11d55..c99e1dc1 100644 --- a/koans/src/java8/AboutLocalTime.java +++ b/koans/src/java8/AboutLocalTime.java @@ -11,13 +11,13 @@ public class AboutLocalTime { @Koan - public void localTime () { - LocalTime t1 = LocalTime.of(7,30); + public void localTime() { + LocalTime t1 = LocalTime.of(7, 30); assertEquals(t1, LocalTime.parse(__)); } @Koan - public void localTimeMinus () { + public void localTimeMinus() { LocalTime t1 = LocalTime.parse("10:30"); LocalTime t2 = t1.minus(2, ChronoUnit.HOURS); assertEquals(t2, LocalTime.parse(__)); diff --git a/koans/src/java8/AboutMultipleInheritance.java b/koans/src/java8/AboutMultipleInheritance.java index 0d4769d4..40a54c56 100644 --- a/koans/src/java8/AboutMultipleInheritance.java +++ b/koans/src/java8/AboutMultipleInheritance.java @@ -2,34 +2,34 @@ import com.sandwich.koan.Koan; -import static com.sandwich.util.Assert.assertEquals; import static com.sandwich.koan.constant.KoanConstants.__; +import static com.sandwich.util.Assert.assertEquals; public class AboutMultipleInheritance { - - interface Human{ - default String sound(){ + + interface Human { + default String sound() { return "hello"; } } - interface Bull{ - default String sound(){ + interface Bull { + default String sound() { return "moo"; } } - class Minotaur implements Human, Bull{ + class Minotaur implements Human, Bull { //both interfaces implement same default method //has to be overridden @Override - public String sound(){ + public String sound() { return Bull.super.sound(); } } @Koan - public void multipleInheritance(){ + public void multipleInheritance() { Minotaur minotaur = new Minotaur(); assertEquals(minotaur.sound(), __); } diff --git a/koans/src/java8/AboutOptional.java b/koans/src/java8/AboutOptional.java index d5110ef0..d2ba6b53 100644 --- a/koans/src/java8/AboutOptional.java +++ b/koans/src/java8/AboutOptional.java @@ -10,6 +10,7 @@ public class AboutOptional { boolean optionalIsPresentField = false; + @Koan public void isPresent() { boolean optionalIsPresent = false; @@ -23,7 +24,7 @@ public void isPresent() { @Koan public void ifPresentLambda() { Optional value = notPresent(); - value.ifPresent( x -> optionalIsPresentField = true); + value.ifPresent(x -> optionalIsPresentField = true); assertEquals(optionalIsPresentField, __); } diff --git a/koans/src/java8/AboutStreams.java b/koans/src/java8/AboutStreams.java index f0130499..ee0c90e4 100644 --- a/koans/src/java8/AboutStreams.java +++ b/koans/src/java8/AboutStreams.java @@ -31,7 +31,7 @@ public void filteredCount() { } @Koan - public void max(){ + public void max() { String longest = places.stream() .max(Comparator.comparing(cityName -> cityName.length())) .get(); @@ -39,7 +39,7 @@ public void max(){ } @Koan - public void min(){ + public void min() { String shortest = places.stream() .min(Comparator.comparing(cityName -> cityName.length())) .get(); @@ -47,21 +47,21 @@ public void min(){ } @Koan - public void reduce(){ + public void reduce() { String join = places.stream() .reduce("", String::concat); assertEquals(join, __); } @Koan - public void reduceWithoutStarterReturnsOptional(){ + public void reduceWithoutStarterReturnsOptional() { Optional join = places.stream() .reduce(String::concat); assertEquals(join.get(), __); } @Koan - public void join(){ + public void join() { String join = places.stream() .reduce((accumulated, cityName) -> accumulated + "\", \"" + cityName) .get(); @@ -69,21 +69,14 @@ public void join(){ } @Koan - public void reduceWithBinaryOperator(){ - String join = places.stream() - .reduce("", String::concat); - assertEquals(join, __); - } - - @Koan - public void stringJoin(){ + public void stringJoin() { String join = places.stream() .collect(Collectors.joining("\", \"")); assertEquals(join, __); } @Koan - public void mapReduce(){ + public void mapReduce() { OptionalDouble averageLengthOptional = places.stream() .mapToInt(String::length) .average(); @@ -92,7 +85,7 @@ public void mapReduce(){ } @Koan - public void parallelMapReduce(){ + public void parallelMapReduce() { int lengthSum = places.parallelStream() .mapToInt(String::length) .sum(); @@ -100,7 +93,7 @@ public void parallelMapReduce(){ } @Koan - public void limitSkip(){ + public void limitSkip() { int lengthSum_Limit_3_Skip_1 = places.stream() .mapToInt(String::length) .limit(3) @@ -120,14 +113,14 @@ public void lazyEvaluation() { } @Koan - public void sumRange(){ + public void sumRange() { int sum = IntStream.range(1, 4).sum(); assertEquals(sum, __); } @Koan - public void rangeToList(){ - List range = IntStream.range(1,4) + public void rangeToList() { + List range = IntStream.range(1, 4) .boxed() .collect(Collectors.toList()); assertEquals(range, __); diff --git a/lib/build.gradle b/lib/build.gradle new file mode 100644 index 00000000..0f6aae3d --- /dev/null +++ b/lib/build.gradle @@ -0,0 +1,47 @@ +apply plugin: 'java' +apply plugin: 'idea' +apply plugin: 'eclipse' + +repositories { + mavenCentral() +} + +dependencies { + testCompile 'junit:junit:4.+' + testCompile 'org.easymock:easymock:3.4' +} + +task createJar(type: Jar){ + archiveName = 'koans.jar' + manifest { + attributes 'Implementation-Title': 'Java Koans', + 'Implementation-Version': 2.0, + 'Main-Class': 'com.sandwich.koan.runner.AppLauncher' + } + baseName = "java-koans" + from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }} + with jar +} + +task copyJarToBin { + doLast { + copy { + from './build/libs/koans.jar' + into '../koans/app/lib' + } + } +} + +test { + + classpath = project.sourceSets.test.runtimeClasspath + files("${projectDir}/../koans/app/config") + +} + +allprojects { + sourceCompatibility = 1.5 + targetCompatibility = 1.5 +} + +task buildApp (dependsOn: [clean, test, createJar, copyJarToBin]) + diff --git a/lib/build/build.properties b/lib/build/build.properties deleted file mode 100644 index 50a1489e..00000000 --- a/lib/build/build.properties +++ /dev/null @@ -1,24 +0,0 @@ -koans.dir=koans -app.dir=${koans.dir}/app -dist=${app.dir}/lib -config=${app.dir}/config -lib.dir=lib - -util.src.dir=${lib.dir}/util/src -file.compiler.src.dir=${lib.dir}/file-compiler/src -file.monitor.src.dir=${lib.dir}/file-monitor/src -koans.lib.src.dir=${lib.dir}/koans-lib/src -koans.src.dir=${koans.dir}/src -koans.tests.src.dir=${lib.dir}/koans-tests/test - -build.dir=${lib.dir}/build -bin.dir=${build.dir}/bin -util.bin.dir=${bin.dir}/util -file.compiler.bin.dir=${bin.dir}/file-compiler -file.monitor.bin.dir=${bin.dir}/file-monitor -koans.lib.bin.dir=${bin.dir}/koans-lib -koans.bin.dir=${bin.dir}/koans -koans.tests.bin.dir=${bin.dir}/koans-tests - -bin.lib.dir=${koans.tests.bin.dir}/lib -reports.dir=${build.dir}/reports \ No newline at end of file diff --git a/lib/build/build.xml b/lib/build/build.xml deleted file mode 100644 index 9e69ead6..00000000 --- a/lib/build/build.xml +++ /dev/null @@ -1,105 +0,0 @@ - - - - - - A simple set of lessons to learn Java from - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/lib/file-compiler/.classpath b/lib/file-compiler/.classpath deleted file mode 100644 index 1cbdf16a..00000000 --- a/lib/file-compiler/.classpath +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/lib/file-compiler/.project b/lib/file-compiler/.project deleted file mode 100644 index 8f7123fe..00000000 --- a/lib/file-compiler/.project +++ /dev/null @@ -1,17 +0,0 @@ - - - file-compiler - - - - - - org.eclipse.jdt.core.javabuilder - - - - - - org.eclipse.jdt.core.javanature - - diff --git a/lib/file-compiler/src/com/sandwich/util/io/filecompiler/CompilerConfig.java b/lib/file-compiler/src/com/sandwich/util/io/filecompiler/CompilerConfig.java deleted file mode 100644 index 4b4df46e..00000000 --- a/lib/file-compiler/src/com/sandwich/util/io/filecompiler/CompilerConfig.java +++ /dev/null @@ -1,74 +0,0 @@ -package com.sandwich.util.io.filecompiler; - -import java.io.File; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Enumeration; -import java.util.List; -import java.util.ResourceBundle; - -public class CompilerConfig { - - private static final ResourceBundle commandBySuffixRB = ResourceBundle.getBundle("com.sandwich.util.io.filecompiler.compilationcommands"); - - public static boolean isSourceFile(String fileName) { - // TODO when supporting java > 5, change to return resourcebundle.containsKey(... - Enumeration keys = commandBySuffixRB.getKeys(); - String suffix = getSuffix(fileName).toLowerCase(); - while(keys.hasMoreElements()){ - String key = keys.nextElement(); - if(key.equals(suffix)){ - return true; - } - } - return false; - } - - public static String[] getCompilationCommand(File src, String destinationPath, String classPath) { - String absolutePath = src.getAbsolutePath(); - String command = commandBySuffixRB.getString(getSuffix(absolutePath)); - if(command == null){ - throw new RuntimeException("Do not know how to compile " + absolutePath); - } - List splitCommand = Arrays.asList(command.split(" ")); - List commandSegments = new ArrayList(); - for(String segment : splitCommand){ - String lowerCaseSegment = segment.toLowerCase(); - if("${bindir}".equals(lowerCaseSegment)){ - commandSegments.add(destinationPath); - }else if("${classpath}".equals(lowerCaseSegment)){ - commandSegments.add(classPath); - }else if("${filename}".equals(lowerCaseSegment)){ - commandSegments.add(src.getAbsolutePath()); - }else{ - commandSegments.add(segment); - } - } - return commandSegments.toArray(new String[commandSegments.size()]); - } - - public static Collection getSupportedFileSuffixes() { - Enumeration keysEnumeration = commandBySuffixRB.getKeys(); - Collection keys = new ArrayList(); - while(keysEnumeration.hasMoreElements()){ - keys.add(keysEnumeration.nextElement()); - } - return keys; - } - - public static String getSuffix(String fileName) { - if(fileName != null){ - int periodIndex = fileName.lastIndexOf('.'); - if(periodIndex > -1){ - return fileName.substring(periodIndex).toLowerCase(); - } - } - return ""; - } - - public static boolean isSuffixSupported(String suffix) { - return getSupportedFileSuffixes().contains(suffix); - } - -} diff --git a/lib/file-monitor/.classpath b/lib/file-monitor/.classpath deleted file mode 100644 index bda1618b..00000000 --- a/lib/file-monitor/.classpath +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/lib/file-monitor/.project b/lib/file-monitor/.project deleted file mode 100644 index 1932145d..00000000 --- a/lib/file-monitor/.project +++ /dev/null @@ -1,17 +0,0 @@ - - - file-monitor - - - - - - org.eclipse.jdt.core.javabuilder - - - - - - org.eclipse.jdt.core.javanature - - diff --git a/lib/gradle/wrapper/gradle-wrapper.jar b/lib/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 00000000..94114481 Binary files /dev/null and b/lib/gradle/wrapper/gradle-wrapper.jar differ diff --git a/lib/gradle/wrapper/gradle-wrapper.properties b/lib/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000..c2030d0d --- /dev/null +++ b/lib/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Sat Mar 26 18:10:52 GMT 2016 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-2.12-bin.zip diff --git a/lib/gradlew b/lib/gradlew new file mode 100755 index 00000000..9d82f789 --- /dev/null +++ b/lib/gradlew @@ -0,0 +1,160 @@ +#!/usr/bin/env bash + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn ( ) { + echo "$*" +} + +die ( ) { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; +esac + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules +function splitJvmOpts() { + JVM_OPTS=("$@") +} +eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS +JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" + +exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/lib/gradlew.bat b/lib/gradlew.bat new file mode 100644 index 00000000..8a0b282a --- /dev/null +++ b/lib/gradlew.bat @@ -0,0 +1,90 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windowz variants + +if not "%OS%" == "Windows_NT" goto win9xME_args +if "%@eval[2+2]" == "4" goto 4NT_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* +goto execute + +:4NT_args +@rem Get arguments from the 4NT Shell from JP Software +set CMD_LINE_ARGS=%$ + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/lib/koans-lib/.classpath b/lib/koans-lib/.classpath deleted file mode 100755 index fe068eec..00000000 --- a/lib/koans-lib/.classpath +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/lib/koans-lib/.project b/lib/koans-lib/.project deleted file mode 100755 index 119dcdc9..00000000 --- a/lib/koans-lib/.project +++ /dev/null @@ -1,17 +0,0 @@ - - - koans-lib - - - - - - org.eclipse.jdt.core.javabuilder - - - - - - org.eclipse.jdt.core.javanature - - diff --git a/lib/koans-lib/.settings/org.eclipse.jdt.core.prefs b/lib/koans-lib/.settings/org.eclipse.jdt.core.prefs deleted file mode 100755 index 6ed0deb7..00000000 --- a/lib/koans-lib/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,12 +0,0 @@ -#Wed Apr 06 21:04:13 PDT 2011 -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 -org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.compliance=1.5 -org.eclipse.jdt.core.compiler.debug.lineNumber=generate -org.eclipse.jdt.core.compiler.debug.localVariable=generate -org.eclipse.jdt.core.compiler.debug.sourceFile=generate -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.source=1.5 diff --git a/lib/koans-lib/MANIFEST.MF b/lib/koans-lib/MANIFEST.MF deleted file mode 100755 index 8ab9ca42..00000000 --- a/lib/koans-lib/MANIFEST.MF +++ /dev/null @@ -1,4 +0,0 @@ -Manifest-Version: 1.0 -Class-Path: . ../bin/temp.jar -Main-Class: com.sandwich.koan.runner.KoanSuiteRunner - diff --git a/lib/koans-lib/src/com/sandwich/koan/runner/AppLauncher.java b/lib/koans-lib/src/com/sandwich/koan/runner/AppLauncher.java deleted file mode 100755 index b026efa0..00000000 --- a/lib/koans-lib/src/com/sandwich/koan/runner/AppLauncher.java +++ /dev/null @@ -1,57 +0,0 @@ -package com.sandwich.koan.runner; - -import java.io.File; -import java.io.IOException; -import java.util.Map; - -import com.sandwich.koan.ApplicationSettings; -import com.sandwich.koan.cmdline.CommandLineArgument; -import com.sandwich.koan.cmdline.CommandLineArgumentBuilder; -import com.sandwich.koan.cmdline.CommandLineArgumentRunner; -import com.sandwich.koan.constant.ArgumentType; -import com.sandwich.koan.util.ApplicationUtils; -import com.sandwich.util.io.FileMonitor; -import com.sandwich.util.io.FileMonitorFactory; -import com.sandwich.util.io.KoanFileCompileAndRunListener; -import com.sandwich.util.io.directories.DirectoryManager; - -public class AppLauncher { - - public static void main(final String... args) throws Throwable { - Map argsMap = new CommandLineArgumentBuilder(args); - if(argsMap.containsKey(ArgumentType.RUN_KOANS)){ - new Thread(new Runnable(){ - public void run() { - do{ - try { - char c = (char)System.in.read(); - if(Character.toUpperCase(c) == - Character.toUpperCase(ApplicationSettings.getExitChar())){ - FileMonitorFactory.closeAll(); - System.exit(0); - } - } catch (IOException e) { - throw new RuntimeException(e); - } - }while(true); - } - }).start(); - FileMonitor monitor = FileMonitorFactory.getInstance( - new File(DirectoryManager.getProdMainDir()), - new File(DirectoryManager.getDataFile())); - if(ApplicationUtils.isFirstTimeAppHasBeenRun()){ - monitor.writeChanges(); - } - monitor.addFileSavedListener(new KoanFileCompileAndRunListener(argsMap)); - } - new CommandLineArgumentRunner(argsMap).run(); - if(ApplicationSettings.isDebug()){ - StringBuilder argsBuilder = new StringBuilder(); - int argNumber = 0; - for(String arg : args){ - argsBuilder.append("Argument number "+String.valueOf(++argNumber)+": '"+arg+"'"); - } - ApplicationUtils.getPresenter().displayMessage(argsBuilder.toString()); - } - } -} diff --git a/lib/koans-tests/.classpath b/lib/koans-tests/.classpath deleted file mode 100755 index 9112adfa..00000000 --- a/lib/koans-tests/.classpath +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/lib/koans-tests/.project b/lib/koans-tests/.project deleted file mode 100755 index 4d6ea963..00000000 --- a/lib/koans-tests/.project +++ /dev/null @@ -1,17 +0,0 @@ - - - koans-tests - - - - - - org.eclipse.jdt.core.javabuilder - - - - - - org.eclipse.jdt.core.javanature - - diff --git a/lib/koans-tests/.settings/org.eclipse.jdt.core.prefs b/lib/koans-tests/.settings/org.eclipse.jdt.core.prefs deleted file mode 100755 index 7b345363..00000000 --- a/lib/koans-tests/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,12 +0,0 @@ -#Wed Apr 06 21:08:03 PDT 2011 -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 -org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.compliance=1.5 -org.eclipse.jdt.core.compiler.debug.lineNumber=generate -org.eclipse.jdt.core.compiler.debug.localVariable=generate -org.eclipse.jdt.core.compiler.debug.sourceFile=generate -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.source=1.5 diff --git a/lib/koans-tests/bin/cglib-nodep-2.2.jar b/lib/koans-tests/bin/cglib-nodep-2.2.jar deleted file mode 100755 index ed07cb50..00000000 Binary files a/lib/koans-tests/bin/cglib-nodep-2.2.jar and /dev/null differ diff --git a/lib/koans-tests/bin/easymock-3.0.jar b/lib/koans-tests/bin/easymock-3.0.jar deleted file mode 100755 index f6d7a3f9..00000000 Binary files a/lib/koans-tests/bin/easymock-3.0.jar and /dev/null differ diff --git a/lib/koans-tests/data/file_hashes.dat b/lib/koans-tests/data/file_hashes.dat deleted file mode 100644 index ff3347b5..00000000 Binary files a/lib/koans-tests/data/file_hashes.dat and /dev/null differ diff --git a/lib/koans-tests/data/src/cglib-nodep-2.2.jar b/lib/koans-tests/data/src/cglib-nodep-2.2.jar deleted file mode 100644 index ed07cb50..00000000 Binary files a/lib/koans-tests/data/src/cglib-nodep-2.2.jar and /dev/null differ diff --git a/lib/koans-tests/data/src/com/sandwich/koan/KoansResultTest.java b/lib/koans-tests/data/src/com/sandwich/koan/KoansResultTest.java deleted file mode 100644 index b2011ebd..00000000 --- a/lib/koans-tests/data/src/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/koans-tests/data/src/com/sandwich/koan/TestUtils.java b/lib/koans-tests/data/src/com/sandwich/koan/TestUtils.java deleted file mode 100644 index 52dd8dc2..00000000 --- a/lib/koans-tests/data/src/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/koans-tests/data/src/com/sandwich/koan/TestUtilsTest.java b/lib/koans-tests/data/src/com/sandwich/koan/TestUtilsTest.java deleted file mode 100644 index a5a66b8c..00000000 --- a/lib/koans-tests/data/src/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/koans-tests/data/src/com/sandwich/koan/cmdline/CommandLineArgumentBuilderTest.java b/lib/koans-tests/data/src/com/sandwich/koan/cmdline/CommandLineArgumentBuilderTest.java deleted file mode 100644 index 5098f8da..00000000 --- a/lib/koans-tests/data/src/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/koans-tests/data/src/com/sandwich/koan/constant/ArgumentTypeTest.java b/lib/koans-tests/data/src/com/sandwich/koan/constant/ArgumentTypeTest.java deleted file mode 100644 index 48ec575a..00000000 --- a/lib/koans-tests/data/src/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/koans-tests/data/src/com/sandwich/koan/path/CommandLineTestCase.java b/lib/koans-tests/data/src/com/sandwich/koan/path/CommandLineTestCase.java deleted file mode 100644 index a39f265c..00000000 --- a/lib/koans-tests/data/src/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/koans-tests/data/src/com/sandwich/koan/path/DefaultKoanDescriptionTest.java b/lib/koans-tests/data/src/com/sandwich/koan/path/DefaultKoanDescriptionTest.java deleted file mode 100644 index 8f4f6de0..00000000 --- a/lib/koans-tests/data/src/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/koans-tests/data/src/com/sandwich/koan/path/XmlVariableInjectorTest.java b/lib/koans-tests/data/src/com/sandwich/koan/path/XmlVariableInjectorTest.java deleted file mode 100644 index 0b12af7f..00000000 --- a/lib/koans-tests/data/src/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/koans-tests/data/src/com/sandwich/koan/runner/AppReadinessForDeploymentTest.java b/lib/koans-tests/data/src/com/sandwich/koan/runner/AppReadinessForDeploymentTest.java deleted file mode 100644 index 630ebb5c..00000000 --- a/lib/koans-tests/data/src/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/koans-tests/data/src/com/sandwich/koan/runner/CommandLineTestCaseTest.java b/lib/koans-tests/data/src/com/sandwich/koan/runner/CommandLineTestCaseTest.java deleted file mode 100644 index 179d7f31..00000000 --- a/lib/koans-tests/data/src/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/koans-tests/data/src/com/sandwich/koan/runner/ConsolePresenterTest.java b/lib/koans-tests/data/src/com/sandwich/koan/runner/ConsolePresenterTest.java deleted file mode 100644 index 748f9818..00000000 --- a/lib/koans-tests/data/src/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/koans-tests/data/src/com/sandwich/koan/runner/KoanSuiteRunnerTest.java b/lib/koans-tests/data/src/com/sandwich/koan/runner/KoanSuiteRunnerTest.java deleted file mode 100644 index aa106442..00000000 --- a/lib/koans-tests/data/src/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/koans-tests/data/src/com/sandwich/koan/runner/ui/AbstractSuitePresenterTest.java b/lib/koans-tests/data/src/com/sandwich/koan/runner/ui/AbstractSuitePresenterTest.java deleted file mode 100644 index 1e22df3c..00000000 --- a/lib/koans-tests/data/src/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/koans-tests/data/src/com/sandwich/koan/suite/BlowUpOnLineEleven.java b/lib/koans-tests/data/src/com/sandwich/koan/suite/BlowUpOnLineEleven.java deleted file mode 100644 index 3d6753c3..00000000 --- a/lib/koans-tests/data/src/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/koans-tests/data/src/com/sandwich/koan/suite/BlowUpOnLineTen.java b/lib/koans-tests/data/src/com/sandwich/koan/suite/BlowUpOnLineTen.java deleted file mode 100644 index 331e54d3..00000000 --- a/lib/koans-tests/data/src/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/koans-tests/data/src/com/sandwich/koan/suite/OnePassingKoanDifferentName.java b/lib/koans-tests/data/src/com/sandwich/koan/suite/OnePassingKoanDifferentName.java deleted file mode 100644 index 5a76b430..00000000 --- a/lib/koans-tests/data/src/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/koans-tests/data/src/com/sandwich/util/KoanComparatorTest.java b/lib/koans-tests/data/src/com/sandwich/util/KoanComparatorTest.java deleted file mode 100644 index 78473088..00000000 --- a/lib/koans-tests/data/src/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/koans-tests/data/src/com/sandwich/util/io/DirectoryManagerTest.java b/lib/koans-tests/data/src/com/sandwich/util/io/DirectoryManagerTest.java deleted file mode 100644 index d97f5ef6..00000000 --- a/lib/koans-tests/data/src/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/koans-tests/data/src/com/sandwich/util/io/FileMonitorTest.java b/lib/koans-tests/data/src/com/sandwich/util/io/FileMonitorTest.java deleted file mode 100644 index 2f3d10e9..00000000 --- a/lib/koans-tests/data/src/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(); - } - -} diff --git a/lib/koans-tests/data/src/easymock-3.0.jar b/lib/koans-tests/data/src/easymock-3.0.jar deleted file mode 100644 index f6d7a3f9..00000000 Binary files a/lib/koans-tests/data/src/easymock-3.0.jar and /dev/null differ diff --git a/lib/koans-tests/test/cglib-nodep-2.2.jar b/lib/koans-tests/test/cglib-nodep-2.2.jar deleted file mode 100755 index ed07cb50..00000000 Binary files a/lib/koans-tests/test/cglib-nodep-2.2.jar and /dev/null differ diff --git a/lib/koans-tests/test/com/sandwich/koan/path/xmltransformation/FakeXmlToPathTransformer.java b/lib/koans-tests/test/com/sandwich/koan/path/xmltransformation/FakeXmlToPathTransformer.java deleted file mode 100644 index 63f84368..00000000 --- a/lib/koans-tests/test/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/koans-tests/test/com/sandwich/koan/runner/AppLauncherTest.java b/lib/koans-tests/test/com/sandwich/koan/runner/AppLauncherTest.java deleted file mode 100644 index a3559be1..00000000 --- a/lib/koans-tests/test/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/koans-tests/test/com/sandwich/koan/suite/OneFailingKoan.java b/lib/koans-tests/test/com/sandwich/koan/suite/OneFailingKoan.java deleted file mode 100755 index e16e4296..00000000 --- a/lib/koans-tests/test/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/koans-tests/test/com/sandwich/koan/suite/OneFailingKoanDifferentName.java b/lib/koans-tests/test/com/sandwich/koan/suite/OneFailingKoanDifferentName.java deleted file mode 100755 index 64666e0d..00000000 --- a/lib/koans-tests/test/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/koans-tests/test/com/sandwich/koan/suite/OnePassingKoan.java b/lib/koans-tests/test/com/sandwich/koan/suite/OnePassingKoan.java deleted file mode 100755 index 2db4f932..00000000 --- a/lib/koans-tests/test/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/koans-tests/test/com/sandwich/util/io/directories/ProductionExecutedFromTestsDirectories.java b/lib/koans-tests/test/com/sandwich/util/io/directories/ProductionExecutedFromTestsDirectories.java deleted file mode 100644 index efea688b..00000000 --- a/lib/koans-tests/test/com/sandwich/util/io/directories/ProductionExecutedFromTestsDirectories.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.sandwich.util.io.directories; - -public class ProductionExecutedFromTestsDirectories extends ProductionDirectories { - - @Override - public String getBaseDir() { - String baseDir = super.getBaseDir(); - return baseDir.substring(0, baseDir.length() - getLibrariesDir().length() - 1); - } - -} diff --git a/lib/koans-tests/test/com/sandwich/util/io/directories/UnitTestDirectories.java b/lib/koans-tests/test/com/sandwich/util/io/directories/UnitTestDirectories.java deleted file mode 100644 index c33122cf..00000000 --- a/lib/koans-tests/test/com/sandwich/util/io/directories/UnitTestDirectories.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.sandwich.util.io.directories; - - - -public class UnitTestDirectories extends ProductionExecutedFromTestsDirectories { - - public String getSourceDir() { - return "test"; - } - - public String getProjectDir() { - return super.getLibrariesDir() + System.getProperty("file.separator") - + "koans-tests"; - } - -} diff --git a/lib/koans-tests/test/easymock-3.0.jar b/lib/koans-tests/test/easymock-3.0.jar deleted file mode 100755 index f6d7a3f9..00000000 Binary files a/lib/koans-tests/test/easymock-3.0.jar and /dev/null differ diff --git a/lib/koans-tests/test/hamcrest-core-1.3.jar b/lib/koans-tests/test/hamcrest-core-1.3.jar deleted file mode 100644 index 9d5fe16e..00000000 Binary files a/lib/koans-tests/test/hamcrest-core-1.3.jar and /dev/null differ diff --git a/lib/koans-tests/test/junit-4.11.jar b/lib/koans-tests/test/junit-4.11.jar deleted file mode 100644 index aaf74448..00000000 Binary files a/lib/koans-tests/test/junit-4.11.jar and /dev/null differ diff --git a/lib/koans-lib/src/com/sandwich/koan/ApplicationSettings.java b/lib/src/main/java/com/sandwich/koan/ApplicationSettings.java similarity index 80% rename from lib/koans-lib/src/com/sandwich/koan/ApplicationSettings.java rename to lib/src/main/java/com/sandwich/koan/ApplicationSettings.java index c3a14417..168e1b7d 100644 --- a/lib/koans-lib/src/com/sandwich/koan/ApplicationSettings.java +++ b/lib/src/main/java/com/sandwich/koan/ApplicationSettings.java @@ -23,6 +23,14 @@ public static boolean isDebug(){ public static boolean isEncouragementEnabled(){ return isEqual(getConfigBundle().getString("enable_encouragement"), true, true); } + + public static boolean isExpectationResultVisible(){ + return isEqual(getConfigBundle().getString("enable_expectation_result"), true, true); + } + + public static boolean isInteractive(){ + return isEqual(getConfigBundle().getString("interactive"), true, true); + } public static char getExitChar(){ return getConfigBundle().getString("exit_character").charAt(0); @@ -35,6 +43,10 @@ public static String getPathXmlFileName(){ public static long getFileCompilationTimeoutInMs(){ return Long.valueOf(getConfigBundle().getString("compile_timeout_in_ms")); } + + public static String getMonitorIgnorePattern(){ + return getConfigBundle().getString("ignore_from_monitoring"); + } private static boolean isEqual(String value, Object e2, boolean ignoreCase){ if(value == e2){ diff --git a/lib/koans-lib/src/com/sandwich/koan/Koan.java b/lib/src/main/java/com/sandwich/koan/Koan.java similarity index 100% rename from lib/koans-lib/src/com/sandwich/koan/Koan.java rename to lib/src/main/java/com/sandwich/koan/Koan.java diff --git a/lib/koans-lib/src/com/sandwich/koan/KoanClassLoader.java b/lib/src/main/java/com/sandwich/koan/KoanClassLoader.java similarity index 100% rename from lib/koans-lib/src/com/sandwich/koan/KoanClassLoader.java rename to lib/src/main/java/com/sandwich/koan/KoanClassLoader.java diff --git a/lib/koans-lib/src/com/sandwich/koan/KoanIncompleteException.java b/lib/src/main/java/com/sandwich/koan/KoanIncompleteException.java similarity index 100% rename from lib/koans-lib/src/com/sandwich/koan/KoanIncompleteException.java rename to lib/src/main/java/com/sandwich/koan/KoanIncompleteException.java diff --git a/lib/koans-lib/src/com/sandwich/koan/KoanMethod.java b/lib/src/main/java/com/sandwich/koan/KoanMethod.java similarity index 100% rename from lib/koans-lib/src/com/sandwich/koan/KoanMethod.java rename to lib/src/main/java/com/sandwich/koan/KoanMethod.java diff --git a/lib/koans-lib/src/com/sandwich/koan/cmdline/CommandLineArgument.java b/lib/src/main/java/com/sandwich/koan/cmdline/CommandLineArgument.java similarity index 100% rename from lib/koans-lib/src/com/sandwich/koan/cmdline/CommandLineArgument.java rename to lib/src/main/java/com/sandwich/koan/cmdline/CommandLineArgument.java diff --git a/lib/koans-lib/src/com/sandwich/koan/cmdline/CommandLineArgumentBuilder.java b/lib/src/main/java/com/sandwich/koan/cmdline/CommandLineArgumentBuilder.java similarity index 100% rename from lib/koans-lib/src/com/sandwich/koan/cmdline/CommandLineArgumentBuilder.java rename to lib/src/main/java/com/sandwich/koan/cmdline/CommandLineArgumentBuilder.java diff --git a/lib/koans-lib/src/com/sandwich/koan/cmdline/CommandLineArgumentRunner.java b/lib/src/main/java/com/sandwich/koan/cmdline/CommandLineArgumentRunner.java similarity index 100% rename from lib/koans-lib/src/com/sandwich/koan/cmdline/CommandLineArgumentRunner.java rename to lib/src/main/java/com/sandwich/koan/cmdline/CommandLineArgumentRunner.java diff --git a/lib/koans-lib/src/com/sandwich/koan/cmdline/behavior/AbstractArgumentBehavior.java b/lib/src/main/java/com/sandwich/koan/cmdline/behavior/AbstractArgumentBehavior.java similarity index 100% rename from lib/koans-lib/src/com/sandwich/koan/cmdline/behavior/AbstractArgumentBehavior.java rename to lib/src/main/java/com/sandwich/koan/cmdline/behavior/AbstractArgumentBehavior.java diff --git a/lib/koans-lib/src/com/sandwich/koan/cmdline/behavior/ArgumentBehavior.java b/lib/src/main/java/com/sandwich/koan/cmdline/behavior/ArgumentBehavior.java similarity index 100% rename from lib/koans-lib/src/com/sandwich/koan/cmdline/behavior/ArgumentBehavior.java rename to lib/src/main/java/com/sandwich/koan/cmdline/behavior/ArgumentBehavior.java diff --git a/lib/koans-lib/src/com/sandwich/koan/cmdline/behavior/Backup.java b/lib/src/main/java/com/sandwich/koan/cmdline/behavior/Backup.java similarity index 100% rename from lib/koans-lib/src/com/sandwich/koan/cmdline/behavior/Backup.java rename to lib/src/main/java/com/sandwich/koan/cmdline/behavior/Backup.java diff --git a/lib/koans-lib/src/com/sandwich/koan/cmdline/behavior/ClassArg.java b/lib/src/main/java/com/sandwich/koan/cmdline/behavior/ClassArg.java similarity index 100% rename from lib/koans-lib/src/com/sandwich/koan/cmdline/behavior/ClassArg.java rename to lib/src/main/java/com/sandwich/koan/cmdline/behavior/ClassArg.java diff --git a/lib/koans-lib/src/com/sandwich/koan/cmdline/behavior/Clear.java b/lib/src/main/java/com/sandwich/koan/cmdline/behavior/Clear.java similarity index 100% rename from lib/koans-lib/src/com/sandwich/koan/cmdline/behavior/Clear.java rename to lib/src/main/java/com/sandwich/koan/cmdline/behavior/Clear.java diff --git a/lib/koans-lib/src/com/sandwich/koan/cmdline/behavior/Debug.java b/lib/src/main/java/com/sandwich/koan/cmdline/behavior/Debug.java similarity index 100% rename from lib/koans-lib/src/com/sandwich/koan/cmdline/behavior/Debug.java rename to lib/src/main/java/com/sandwich/koan/cmdline/behavior/Debug.java diff --git a/lib/koans-lib/src/com/sandwich/koan/cmdline/behavior/Help.java b/lib/src/main/java/com/sandwich/koan/cmdline/behavior/Help.java similarity index 100% rename from lib/koans-lib/src/com/sandwich/koan/cmdline/behavior/Help.java rename to lib/src/main/java/com/sandwich/koan/cmdline/behavior/Help.java diff --git a/lib/koans-lib/src/com/sandwich/koan/cmdline/behavior/KoanFileCopying.java b/lib/src/main/java/com/sandwich/koan/cmdline/behavior/KoanFileCopying.java similarity index 100% rename from lib/koans-lib/src/com/sandwich/koan/cmdline/behavior/KoanFileCopying.java rename to lib/src/main/java/com/sandwich/koan/cmdline/behavior/KoanFileCopying.java diff --git a/lib/koans-lib/src/com/sandwich/koan/cmdline/behavior/MethodArg.java b/lib/src/main/java/com/sandwich/koan/cmdline/behavior/MethodArg.java similarity index 100% rename from lib/koans-lib/src/com/sandwich/koan/cmdline/behavior/MethodArg.java rename to lib/src/main/java/com/sandwich/koan/cmdline/behavior/MethodArg.java diff --git a/lib/koans-lib/src/com/sandwich/koan/cmdline/behavior/Reset.java b/lib/src/main/java/com/sandwich/koan/cmdline/behavior/Reset.java similarity index 100% rename from lib/koans-lib/src/com/sandwich/koan/cmdline/behavior/Reset.java rename to lib/src/main/java/com/sandwich/koan/cmdline/behavior/Reset.java diff --git a/lib/koans-lib/src/com/sandwich/koan/constant/ArgumentType.java b/lib/src/main/java/com/sandwich/koan/constant/ArgumentType.java similarity index 100% rename from lib/koans-lib/src/com/sandwich/koan/constant/ArgumentType.java rename to lib/src/main/java/com/sandwich/koan/constant/ArgumentType.java diff --git a/lib/koans-lib/src/com/sandwich/koan/constant/KoanConstants.java b/lib/src/main/java/com/sandwich/koan/constant/KoanConstants.java similarity index 100% rename from lib/koans-lib/src/com/sandwich/koan/constant/KoanConstants.java rename to lib/src/main/java/com/sandwich/koan/constant/KoanConstants.java diff --git a/lib/koans-lib/src/com/sandwich/koan/path/PathToEnlightenment.java b/lib/src/main/java/com/sandwich/koan/path/PathToEnlightenment.java similarity index 100% rename from lib/koans-lib/src/com/sandwich/koan/path/PathToEnlightenment.java rename to lib/src/main/java/com/sandwich/koan/path/PathToEnlightenment.java diff --git a/lib/koans-lib/src/com/sandwich/koan/path/xmltransformation/KoanElementAttributes.java b/lib/src/main/java/com/sandwich/koan/path/xmltransformation/KoanElementAttributes.java similarity index 100% rename from lib/koans-lib/src/com/sandwich/koan/path/xmltransformation/KoanElementAttributes.java rename to lib/src/main/java/com/sandwich/koan/path/xmltransformation/KoanElementAttributes.java diff --git a/lib/koans-lib/src/com/sandwich/koan/path/xmltransformation/RbVariableInjector.java b/lib/src/main/java/com/sandwich/koan/path/xmltransformation/RbVariableInjector.java similarity index 100% rename from lib/koans-lib/src/com/sandwich/koan/path/xmltransformation/RbVariableInjector.java rename to lib/src/main/java/com/sandwich/koan/path/xmltransformation/RbVariableInjector.java diff --git a/lib/koans-lib/src/com/sandwich/koan/path/xmltransformation/XmlToPathTransformer.java b/lib/src/main/java/com/sandwich/koan/path/xmltransformation/XmlToPathTransformer.java similarity index 100% rename from lib/koans-lib/src/com/sandwich/koan/path/xmltransformation/XmlToPathTransformer.java rename to lib/src/main/java/com/sandwich/koan/path/xmltransformation/XmlToPathTransformer.java diff --git a/lib/koans-lib/src/com/sandwich/koan/path/xmltransformation/XmlToPathTransformerImpl.java b/lib/src/main/java/com/sandwich/koan/path/xmltransformation/XmlToPathTransformerImpl.java similarity index 97% rename from lib/koans-lib/src/com/sandwich/koan/path/xmltransformation/XmlToPathTransformerImpl.java rename to lib/src/main/java/com/sandwich/koan/path/xmltransformation/XmlToPathTransformerImpl.java index f363d9f8..8a729526 100755 --- a/lib/koans-lib/src/com/sandwich/koan/path/xmltransformation/XmlToPathTransformerImpl.java +++ b/lib/src/main/java/com/sandwich/koan/path/xmltransformation/XmlToPathTransformerImpl.java @@ -1,116 +1,116 @@ -package com.sandwich.koan.path.xmltransformation; - -import java.io.File; -import java.io.FileNotFoundException; -import java.util.LinkedHashMap; -import java.util.Map; - -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; - -import org.w3c.dom.DOMException; -import org.w3c.dom.Document; -import org.w3c.dom.NamedNodeMap; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -import com.sandwich.koan.path.PathToEnlightenment.Path; - -public class XmlToPathTransformerImpl implements XmlToPathTransformer { - - private final File xmlFile; - private final String suiteName; - private final String methodName; - - public XmlToPathTransformerImpl(){ - xmlFile = null; - suiteName = null; - methodName = null; - } - - public XmlToPathTransformerImpl(String xmlFileLocation, String suiteName, String methodName) throws FileNotFoundException { - this.xmlFile = new File(xmlFileLocation); - this.suiteName = suiteName; - this.methodName = methodName; - if(!xmlFile.exists()){ - throw new FileNotFoundException(xmlFile.getAbsolutePath() - + " was not found. it may have been deleted, renamed."); - } - } - - public Path transform(){ - try{ - DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); - DocumentBuilder db = dbf.newDocumentBuilder(); - Document doc = db.parse(xmlFile); - doc.getDocumentElement().normalize(); - NodeList nodeLst = doc.getElementsByTagName("package"); - /* - * Map of string values read from xml in following form - * package - * |-suite class name - * |-method name - * |-method attributes from xml - */ - Map>> koans = - new LinkedHashMap>>(); - for(int i = 0; i < nodeLst.getLength(); i++){ - Node node = nodeLst.item(i); - String packageTitle = node.getAttributes().getNamedItem("name").getNodeValue(); - String pkg = node.getAttributes().getNamedItem("pkg").getNodeValue(); - koans.put(packageTitle, getKoanElementAttributesByMethodNameBySuite(pkg, node.getChildNodes())); - } - return new Path(methodName, koans); - }catch(Exception x){ - throw new RuntimeException(x); - } - } - - Map> getKoanElementAttributesByMethodNameBySuite(String pkg, - NodeList childNodes) throws DOMException, ClassNotFoundException, - InstantiationException, IllegalAccessException { - Map> koansByMethodNameByClass = - new LinkedHashMap>(); - for (int i = 0; i < childNodes.getLength(); i++) { - Node node = childNodes.item(i); - if ("suite".equalsIgnoreCase(node.getNodeName())) { - String className = pkg + '.' + node.getAttributes().getNamedItem("class").getNodeValue(); - if (suiteName == null || suiteName.equalsIgnoreCase(className)) { - koansByMethodNameByClass.put(className, extractKoansAndRawLessons(className, node.getChildNodes())); - } - } - } - return koansByMethodNameByClass; - } - - Map extractKoansAndRawLessons( - String className, NodeList nodes) { - Map rawKoanAttributesByMethodName = new LinkedHashMap(); - for (int i = 0; i < nodes.getLength(); i++) { - Node node = nodes.item(i); - if ("koan".equalsIgnoreCase(node.getNodeName())) { - NamedNodeMap attributes = node.getAttributes(); - String name = attributes.getNamedItem("name").getNodeValue(); - Node displayKoanIncompleteExceptionNode = attributes - .getNamedItem("displayIncompleteKoanException"); - String displayIncompleteKoanException = displayKoanIncompleteExceptionNode == null ? null - : displayKoanIncompleteExceptionNode.getNodeValue(); - if (rawKoanAttributesByMethodName.containsKey(name)) { - throw new DuplicateKoanException(className, name); - } - rawKoanAttributesByMethodName.put(name, new KoanElementAttributes( - name, displayIncompleteKoanException, className)); - } - } - return rawKoanAttributesByMethodName; - } - - static class DuplicateKoanException extends RuntimeException { - private static final long serialVersionUID = 3846796580641690961L; - public DuplicateKoanException(String className, String name){ - super("Duplicate koans in the same suite: "+className+" with the name "+name); - } - } - -} - +package com.sandwich.koan.path.xmltransformation; + +import java.io.File; +import java.io.FileNotFoundException; +import java.util.LinkedHashMap; +import java.util.Map; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; + +import org.w3c.dom.DOMException; +import org.w3c.dom.Document; +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import com.sandwich.koan.path.PathToEnlightenment.Path; + +public class XmlToPathTransformerImpl implements XmlToPathTransformer { + + private final File xmlFile; + private final String suiteName; + private final String methodName; + + public XmlToPathTransformerImpl(){ + xmlFile = null; + suiteName = null; + methodName = null; + } + + public XmlToPathTransformerImpl(String xmlFileLocation, String suiteName, String methodName) throws FileNotFoundException { + this.xmlFile = new File(xmlFileLocation); + this.suiteName = suiteName; + this.methodName = methodName; + if(!xmlFile.exists()){ + throw new FileNotFoundException(xmlFile.getAbsolutePath() + + " was not found. it may have been deleted, renamed."); + } + } + + public Path transform(){ + try{ + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + DocumentBuilder db = dbf.newDocumentBuilder(); + Document doc = db.parse(xmlFile); + doc.getDocumentElement().normalize(); + NodeList nodeLst = doc.getElementsByTagName("package"); + /* + * Map of string values read from xml in following form + * package + * |-suite class name + * |-method name + * |-method attributes from xml + */ + Map>> koans = + new LinkedHashMap>>(); + for(int i = 0; i < nodeLst.getLength(); i++){ + Node node = nodeLst.item(i); + String packageTitle = node.getAttributes().getNamedItem("name").getNodeValue(); + String pkg = node.getAttributes().getNamedItem("pkg").getNodeValue(); + koans.put(packageTitle, getKoanElementAttributesByMethodNameBySuite(pkg, node.getChildNodes())); + } + return new Path(methodName, koans); + }catch(Exception x){ + throw new RuntimeException(x); + } + } + + Map> getKoanElementAttributesByMethodNameBySuite(String pkg, + NodeList childNodes) throws DOMException, ClassNotFoundException, + InstantiationException, IllegalAccessException { + Map> koansByMethodNameByClass = + new LinkedHashMap>(); + for (int i = 0; i < childNodes.getLength(); i++) { + Node node = childNodes.item(i); + if ("suite".equalsIgnoreCase(node.getNodeName())) { + String className = pkg + '.' + node.getAttributes().getNamedItem("class").getNodeValue(); + if (suiteName == null || suiteName.equalsIgnoreCase(className)) { + koansByMethodNameByClass.put(className, extractKoansAndRawLessons(className, node.getChildNodes())); + } + } + } + return koansByMethodNameByClass; + } + + Map extractKoansAndRawLessons( + String className, NodeList nodes) { + Map rawKoanAttributesByMethodName = new LinkedHashMap(); + for (int i = 0; i < nodes.getLength(); i++) { + Node node = nodes.item(i); + if ("koan".equalsIgnoreCase(node.getNodeName())) { + NamedNodeMap attributes = node.getAttributes(); + String name = attributes.getNamedItem("name").getNodeValue(); + Node displayKoanIncompleteExceptionNode = attributes + .getNamedItem("displayIncompleteKoanException"); + String displayIncompleteKoanException = displayKoanIncompleteExceptionNode == null ? null + : displayKoanIncompleteExceptionNode.getNodeValue(); + if (rawKoanAttributesByMethodName.containsKey(name)) { + throw new DuplicateKoanException(className, name); + } + rawKoanAttributesByMethodName.put(name, new KoanElementAttributes( + name, displayIncompleteKoanException, className)); + } + } + return rawKoanAttributesByMethodName; + } + + static class DuplicateKoanException extends RuntimeException { + private static final long serialVersionUID = 3846796580641690961L; + public DuplicateKoanException(String className, String name){ + super("Duplicate koans in the same suite: "+className+" with the name "+name); + } + } + +} + diff --git a/lib/koans-lib/src/com/sandwich/koan/path/xmltransformation/XmlVariableDictionary.java b/lib/src/main/java/com/sandwich/koan/path/xmltransformation/XmlVariableDictionary.java similarity index 100% rename from lib/koans-lib/src/com/sandwich/koan/path/xmltransformation/XmlVariableDictionary.java rename to lib/src/main/java/com/sandwich/koan/path/xmltransformation/XmlVariableDictionary.java diff --git a/lib/koans-lib/src/com/sandwich/koan/result/KoanMethodResult.java b/lib/src/main/java/com/sandwich/koan/result/KoanMethodResult.java similarity index 100% rename from lib/koans-lib/src/com/sandwich/koan/result/KoanMethodResult.java rename to lib/src/main/java/com/sandwich/koan/result/KoanMethodResult.java diff --git a/lib/koans-lib/src/com/sandwich/koan/result/KoanSuiteResult.java b/lib/src/main/java/com/sandwich/koan/result/KoanSuiteResult.java similarity index 100% rename from lib/koans-lib/src/com/sandwich/koan/result/KoanSuiteResult.java rename to lib/src/main/java/com/sandwich/koan/result/KoanSuiteResult.java diff --git a/lib/src/main/java/com/sandwich/koan/runner/AppLauncher.java b/lib/src/main/java/com/sandwich/koan/runner/AppLauncher.java new file mode 100755 index 00000000..af6cab9b --- /dev/null +++ b/lib/src/main/java/com/sandwich/koan/runner/AppLauncher.java @@ -0,0 +1,68 @@ +package com.sandwich.koan.runner; + +import java.io.File; +import java.io.IOException; +import java.util.Map; + +import com.sandwich.koan.ApplicationSettings; +import com.sandwich.koan.cmdline.CommandLineArgument; +import com.sandwich.koan.cmdline.CommandLineArgumentBuilder; +import com.sandwich.koan.cmdline.CommandLineArgumentRunner; +import com.sandwich.koan.constant.ArgumentType; +import com.sandwich.koan.util.ApplicationUtils; +import com.sandwich.util.io.FileMonitor; +import com.sandwich.util.io.FileMonitorFactory; +import com.sandwich.util.io.KoanFileCompileAndRunListener; +import com.sandwich.util.io.directories.DirectoryManager; + +public class AppLauncher { + + public static void main(final String... args) throws Throwable { + Map argsMap = new CommandLineArgumentBuilder( + args); + if (argsMap.containsKey(ArgumentType.RUN_KOANS)) { + if (ApplicationSettings.isInteractive()) { + new Thread(new Runnable() { + public void run() { + do { + try { + char c = (char) System.in.read(); + char exitChar = ApplicationSettings.getExitChar(); + if (Character.toUpperCase(c) == Character.toUpperCase(exitChar)) { + exit(0); + } + } catch (IOException e) { + throw new RuntimeException(e); + } + } while (true); + } + + }).start(); + FileMonitor monitor = FileMonitorFactory.getInstance(new File( + DirectoryManager.getProdMainDir()), new File( + DirectoryManager.getDataFile())); + if (ApplicationUtils.isFirstTimeAppHasBeenRun()) { + monitor.writeChanges(); + } + monitor.addFileSavedListener(new KoanFileCompileAndRunListener(argsMap)); + } + } + new CommandLineArgumentRunner(argsMap).run(); + if (ApplicationSettings.isDebug()) { + StringBuilder argsBuilder = new StringBuilder(); + int argNumber = 0; + for (String arg : args) { + argsBuilder.append("Argument number " + + String.valueOf(++argNumber) + ": '" + arg + "'"); + } + ApplicationUtils.getPresenter().displayMessage( + argsBuilder.toString()); + } + } + + static void exit(int status) { + FileMonitorFactory.closeAll(); + System.exit(status); + } + +} diff --git a/lib/koans-lib/src/com/sandwich/koan/runner/KoanMethodRunner.java b/lib/src/main/java/com/sandwich/koan/runner/KoanMethodRunner.java similarity index 100% rename from lib/koans-lib/src/com/sandwich/koan/runner/KoanMethodRunner.java rename to lib/src/main/java/com/sandwich/koan/runner/KoanMethodRunner.java diff --git a/lib/koans-lib/src/com/sandwich/koan/runner/RunKoans.java b/lib/src/main/java/com/sandwich/koan/runner/RunKoans.java similarity index 91% rename from lib/koans-lib/src/com/sandwich/koan/runner/RunKoans.java rename to lib/src/main/java/com/sandwich/koan/runner/RunKoans.java index fe0cf967..b945537d 100755 --- a/lib/koans-lib/src/com/sandwich/koan/runner/RunKoans.java +++ b/lib/src/main/java/com/sandwich/koan/runner/RunKoans.java @@ -9,6 +9,7 @@ import java.util.Map; import java.util.Map.Entry; +import com.sandwich.koan.ApplicationSettings; import com.sandwich.koan.Koan; import com.sandwich.koan.KoanClassLoader; import com.sandwich.koan.KoanMethod; @@ -42,9 +43,15 @@ public RunKoans(Path pathToEnlightenment){ } public void run(String... values) { - ApplicationUtils.getPresenter().clearMessages(); - ApplicationUtils.getPresenter().displayResult(runKoans()); - } + ApplicationUtils.getPresenter().clearMessages(); + KoanSuiteResult result = runKoans(); + ApplicationUtils.getPresenter().displayResult(result); + if (!ApplicationSettings.isInteractive()) { + // could overflow past 255 resulting in 0 (ie all koans succeed) + // or otherwise misleading # of failed koans + AppLauncher.exit(Math.min(255, result.getTotalNumberOfKoans() - result.getNumberPassing())); + } + } KoanSuiteResult runKoans() { List passingSuites = new ArrayList(); @@ -101,6 +108,9 @@ private Object safelyConstructSuite(DynamicClassLoader loader, while(suite == null || compilationListener.isLastCompilationAttemptFailure()) { suite = constructSuite(loader, e.getKey(), compilationListener); if(compilationListener.isLastCompilationAttemptFailure()){ + if(!ApplicationSettings.isInteractive()){ + AppLauncher.exit(255); + } try { Thread.sleep(1000); } catch (InterruptedException e1) {} diff --git a/lib/koans-lib/src/com/sandwich/koan/ui/AbstractSuitePresenter.java b/lib/src/main/java/com/sandwich/koan/ui/AbstractSuitePresenter.java similarity index 100% rename from lib/koans-lib/src/com/sandwich/koan/ui/AbstractSuitePresenter.java rename to lib/src/main/java/com/sandwich/koan/ui/AbstractSuitePresenter.java diff --git a/lib/koans-lib/src/com/sandwich/koan/ui/ConsolePresenter.java b/lib/src/main/java/com/sandwich/koan/ui/ConsolePresenter.java similarity index 91% rename from lib/koans-lib/src/com/sandwich/koan/ui/ConsolePresenter.java rename to lib/src/main/java/com/sandwich/koan/ui/ConsolePresenter.java index b094aa7e..0463c6c2 100755 --- a/lib/koans-lib/src/com/sandwich/koan/ui/ConsolePresenter.java +++ b/lib/src/main/java/com/sandwich/koan/ui/ConsolePresenter.java @@ -31,7 +31,10 @@ protected void displayPassingFailing(KoanSuiteResult result) { StringBuilder sb = new StringBuilder(); appendLabeledClassesList(Strings.getMessage("passing_suites")+":", result.getPassingSuites(), sb); appendLabeledClassesList(Strings.getMessage("remaining_suites")+":", result.getRemainingSuites(), sb); - sb.append(EOL).append("Edit & save a koan to reload or enter '"+ ApplicationSettings.getExitChar() +"' to exit"); + sb.append(EOL).append("Edit & save a koan").append( + ApplicationSettings.isInteractive() ? + " to test your progress, or enter '" + ApplicationSettings.getExitChar() +"' to exit." : + ", then rerun to test your progress"); displayMessage(sb.toString()); } @@ -78,13 +81,15 @@ protected void displayAllSuccess(KoanSuiteResult result) { protected void displayOneOrMoreFailure(KoanSuiteResult result) { printSuggestion(result); String message = result.getMessage(); - StringBuilder sb = new StringBuilder( - message == null || message.length() == 0 || !result.displayIncompleteException() ? "" + StringBuilder sb = new StringBuilder(); + if (ApplicationSettings.isExpectationResultVisible()) { + sb.append(message == null || message.length() == 0 || !result.displayIncompleteException() ? "" : new StringBuilder(Strings.getMessage("what_went_wrong")).append( ": ").append( EOL).append( message).append( EOL)); + } if(ApplicationSettings.isEncouragementEnabled()){ // added noise to console output, and no real value int totalKoans = result.getTotalNumberOfKoans(); int numberPassing = result.getNumberPassing(); diff --git a/lib/koans-lib/src/com/sandwich/koan/ui/SuitePresenter.java b/lib/src/main/java/com/sandwich/koan/ui/SuitePresenter.java similarity index 100% rename from lib/koans-lib/src/com/sandwich/koan/ui/SuitePresenter.java rename to lib/src/main/java/com/sandwich/koan/ui/SuitePresenter.java diff --git a/lib/koans-lib/src/com/sandwich/koan/util/ApplicationUtils.java b/lib/src/main/java/com/sandwich/koan/util/ApplicationUtils.java similarity index 100% rename from lib/koans-lib/src/com/sandwich/koan/util/ApplicationUtils.java rename to lib/src/main/java/com/sandwich/koan/util/ApplicationUtils.java diff --git a/lib/koans-lib/src/com/sandwich/util/Assert.java b/lib/src/main/java/com/sandwich/util/Assert.java similarity index 95% rename from lib/koans-lib/src/com/sandwich/util/Assert.java rename to lib/src/main/java/com/sandwich/util/Assert.java index b49c4736..6e4f62ae 100755 --- a/lib/koans-lib/src/com/sandwich/util/Assert.java +++ b/lib/src/main/java/com/sandwich/util/Assert.java @@ -1,75 +1,75 @@ -package com.sandwich.util; - -import com.sandwich.koan.KoanIncompleteException; -import com.sandwich.koan.constant.KoanConstants; - -public class Assert { - - static final String EXPECTED = "expected:<"; - static final String END = ">"; - static final String BUT_WAS = "> but was:<"; - - public static void assertEquals(String msg, Object o0, Object o1){ - if(o0 == null && o1 != null){ - fail(msg, o0, o1); - } - if(o1 == null && o0 != null){ - fail(msg, o0, o1); - } - // not if o0 == o1 return, because equals may violate contract (though - // that's obviously strongly discouraged), but cannot invoke equals on - // null pointer w/o sacrificing functionality from anticipating failure - if(o1 == null && o0 == null){ - return; - } - if(!o0.equals(o1)){ - fail(msg, o0, o1); - } - } - - public static void assertEquals(Object o0, Object o1){ - assertEquals("", o0, o1); - } - - public static void assertTrue(Object t){ - assertEquals(true,t); - } - - public static void assertFalse(Object f){ - assertEquals(false,f); - } - - public static void assertNull(Object o){ - assertEquals(null, o); - } - - public static void assertNotNull(Object o){ - if(o == null){ - fail("something other than null",o); - } - } - - public static void assertSame(Object o0, Object o1){ - if(o0 != o1){ - fail("Are the same instance... ",o0,o1); - } - } - - public static void assertNotSame(Object o0, Object o1){ - if(o0 == o1){ - fail("Not the same instance... ",o0,o1); - } - } - - public static void fail(Object o0, Object o1) throws KoanIncompleteException { - fail("", o0, o1); - } - - public static void fail(String msg, Object o0, Object o1){ - fail(msg+(msg.length() == 0 ? "" : KoanConstants.EOL)+EXPECTED+o0+BUT_WAS+o1+END); - } - - public static void fail(String msg){ - throw new KoanIncompleteException(msg); - } -} +package com.sandwich.util; + +import com.sandwich.koan.KoanIncompleteException; +import com.sandwich.koan.constant.KoanConstants; + +public class Assert { + + static final String EXPECTED = "expected:<"; + static final String END = ">"; + static final String BUT_WAS = "> but was:<"; + + public static void assertEquals(String msg, Object o0, Object o1){ + if(o0 == null && o1 != null){ + fail(msg, o0, o1); + } + if(o1 == null && o0 != null){ + fail(msg, o0, o1); + } + // not if o0 == o1 return, because equals may violate contract (though + // that's obviously strongly discouraged), but cannot invoke equals on + // null pointer w/o sacrificing functionality from anticipating failure + if(o1 == null && o0 == null){ + return; + } + if(!o0.equals(o1)){ + fail(msg, o0, o1); + } + } + + public static void assertEquals(Object o0, Object o1){ + assertEquals("", o0, o1); + } + + public static void assertTrue(Object t){ + assertEquals(true,t); + } + + public static void assertFalse(Object f){ + assertEquals(false,f); + } + + public static void assertNull(Object o){ + assertEquals(null, o); + } + + public static void assertNotNull(Object o){ + if(o == null){ + fail("something other than null",o); + } + } + + public static void assertSame(Object o0, Object o1){ + if(o0 != o1){ + fail("Are the same instance... ",o0,o1); + } + } + + public static void assertNotSame(Object o0, Object o1){ + if(o0 == o1){ + fail("Not the same instance... ",o0,o1); + } + } + + public static void fail(Object o0, Object o1) throws KoanIncompleteException { + fail("", o0, o1); + } + + public static void fail(String msg, Object o0, Object o1){ + fail(msg+(msg.length() == 0 ? "" : KoanConstants.EOL)+EXPECTED+o0+BUT_WAS+o1+END); + } + + public static void fail(String msg){ + throw new KoanIncompleteException(msg); + } +} diff --git a/lib/koans-lib/src/com/sandwich/util/Builder.java b/lib/src/main/java/com/sandwich/util/Builder.java similarity index 100% rename from lib/koans-lib/src/com/sandwich/util/Builder.java rename to lib/src/main/java/com/sandwich/util/Builder.java diff --git a/lib/util/src/com/sandwich/util/ExceptionUtils.java b/lib/src/main/java/com/sandwich/util/ExceptionUtils.java similarity index 100% rename from lib/util/src/com/sandwich/util/ExceptionUtils.java rename to lib/src/main/java/com/sandwich/util/ExceptionUtils.java diff --git a/lib/koans-lib/src/com/sandwich/util/KoanComparator.java b/lib/src/main/java/com/sandwich/util/KoanComparator.java similarity index 58% rename from lib/koans-lib/src/com/sandwich/util/KoanComparator.java rename to lib/src/main/java/com/sandwich/util/KoanComparator.java index c7b02423..b41499ad 100755 --- a/lib/koans-lib/src/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/koans-lib/src/com/sandwich/util/Strings.java b/lib/src/main/java/com/sandwich/util/Strings.java similarity index 100% rename from lib/koans-lib/src/com/sandwich/util/Strings.java rename to lib/src/main/java/com/sandwich/util/Strings.java diff --git a/lib/util/src/com/sandwich/util/io/CopyFileOperation.java b/lib/src/main/java/com/sandwich/util/io/CopyFileOperation.java similarity index 100% rename from lib/util/src/com/sandwich/util/io/CopyFileOperation.java rename to lib/src/main/java/com/sandwich/util/io/CopyFileOperation.java diff --git a/lib/file-monitor/src/com/sandwich/util/io/DataFileHelper.java b/lib/src/main/java/com/sandwich/util/io/DataFileHelper.java similarity index 100% rename from lib/file-monitor/src/com/sandwich/util/io/DataFileHelper.java rename to lib/src/main/java/com/sandwich/util/io/DataFileHelper.java diff --git a/lib/util/src/com/sandwich/util/io/ExistingFileAction.java b/lib/src/main/java/com/sandwich/util/io/ExistingFileAction.java similarity index 88% rename from lib/util/src/com/sandwich/util/io/ExistingFileAction.java rename to lib/src/main/java/com/sandwich/util/io/ExistingFileAction.java index f082da5c..fb6e6f10 100644 --- a/lib/util/src/com/sandwich/util/io/ExistingFileAction.java +++ b/lib/src/main/java/com/sandwich/util/io/ExistingFileAction.java @@ -5,6 +5,10 @@ public abstract class ExistingFileAction extends FileOperation { + public ExistingFileAction(String... strings) { + super(strings); + } + public void onNull(File file) throws IOException { throwNonExistentFileError(String.valueOf(file)); } diff --git a/lib/util/src/com/sandwich/util/io/FileAction.java b/lib/src/main/java/com/sandwich/util/io/FileAction.java similarity index 100% rename from lib/util/src/com/sandwich/util/io/FileAction.java rename to lib/src/main/java/com/sandwich/util/io/FileAction.java diff --git a/lib/file-monitor/src/com/sandwich/util/io/FileListener.java b/lib/src/main/java/com/sandwich/util/io/FileListener.java similarity index 100% rename from lib/file-monitor/src/com/sandwich/util/io/FileListener.java rename to lib/src/main/java/com/sandwich/util/io/FileListener.java diff --git a/lib/file-monitor/src/com/sandwich/util/io/FileMonitor.java b/lib/src/main/java/com/sandwich/util/io/FileMonitor.java similarity index 95% rename from lib/file-monitor/src/com/sandwich/util/io/FileMonitor.java rename to lib/src/main/java/com/sandwich/util/io/FileMonitor.java index d90c5e64..eb9f1415 100644 --- a/lib/file-monitor/src/com/sandwich/util/io/FileMonitor.java +++ b/lib/src/main/java/com/sandwich/util/io/FileMonitor.java @@ -7,6 +7,8 @@ import java.util.Map; import java.util.Vector; +import com.sandwich.koan.ApplicationSettings; + public class FileMonitor { private final List 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/file-monitor/src/com/sandwich/util/io/FileMonitorFactory.java b/lib/src/main/java/com/sandwich/util/io/FileMonitorFactory.java similarity index 77% rename from lib/file-monitor/src/com/sandwich/util/io/FileMonitorFactory.java rename to lib/src/main/java/com/sandwich/util/io/FileMonitorFactory.java index 707ed12c..eca510cd 100644 --- a/lib/file-monitor/src/com/sandwich/util/io/FileMonitorFactory.java +++ b/lib/src/main/java/com/sandwich/util/io/FileMonitorFactory.java @@ -5,6 +5,8 @@ import java.util.Map; import java.util.Map.Entry; +import com.sandwich.koan.ApplicationSettings; + public class FileMonitorFactory { private static Map monitors = new LinkedHashMap(); @@ -22,22 +24,26 @@ public void run() { Thread pollingThread = new Thread(new Runnable(){ public void run() { do{ - try { - Thread.sleep(SLEEP_TIME_IN_MS); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } + if(ApplicationSettings.isInteractive()){ + try { + Thread.sleep(SLEEP_TIME_IN_MS); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } for(Entry filePathAndMonitor : monitors.entrySet()){ FileMonitor monitor = filePathAndMonitor.getValue(); if(monitor != null){ monitor.notifyListeners(); } } - }while(true); + }while(ApplicationSettings.isInteractive()); } }); pollingThread.setName("FileMonitorPolling"); - pollingThread.start(); + if (ApplicationSettings.isInteractive()) { + pollingThread.start(); + } } public static FileMonitor getInstance(File monitoredFile, File dataFile) { diff --git a/lib/src/main/java/com/sandwich/util/io/FileOperation.java b/lib/src/main/java/com/sandwich/util/io/FileOperation.java new file mode 100644 index 00000000..1cea8894 --- /dev/null +++ b/lib/src/main/java/com/sandwich/util/io/FileOperation.java @@ -0,0 +1,49 @@ +package com.sandwich.util.io; + +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(!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/util/src/com/sandwich/util/io/FileUtils.java b/lib/src/main/java/com/sandwich/util/io/FileUtils.java similarity index 100% rename from lib/util/src/com/sandwich/util/io/FileUtils.java rename to lib/src/main/java/com/sandwich/util/io/FileUtils.java diff --git a/lib/util/src/com/sandwich/util/io/ForEachFileAction.java b/lib/src/main/java/com/sandwich/util/io/ForEachFileAction.java similarity index 80% rename from lib/util/src/com/sandwich/util/io/ForEachFileAction.java rename to lib/src/main/java/com/sandwich/util/io/ForEachFileAction.java index 44499b77..cfd04179 100644 --- a/lib/util/src/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/koans-lib/src/com/sandwich/util/io/KoanFileCompileAndRunListener.java b/lib/src/main/java/com/sandwich/util/io/KoanFileCompileAndRunListener.java similarity index 100% rename from lib/koans-lib/src/com/sandwich/util/io/KoanFileCompileAndRunListener.java rename to lib/src/main/java/com/sandwich/util/io/KoanFileCompileAndRunListener.java diff --git a/lib/koans-lib/src/com/sandwich/util/io/KoanSuiteCompilationListener.java b/lib/src/main/java/com/sandwich/util/io/KoanSuiteCompilationListener.java similarity index 100% rename from lib/koans-lib/src/com/sandwich/util/io/KoanSuiteCompilationListener.java rename to lib/src/main/java/com/sandwich/util/io/KoanSuiteCompilationListener.java diff --git a/lib/util/src/com/sandwich/util/io/SourceAndDestinationFileAction.java b/lib/src/main/java/com/sandwich/util/io/SourceAndDestinationFileAction.java similarity index 100% rename from lib/util/src/com/sandwich/util/io/SourceAndDestinationFileAction.java rename to lib/src/main/java/com/sandwich/util/io/SourceAndDestinationFileAction.java diff --git a/lib/file-compiler/src/com/sandwich/util/io/StreamUtils.java b/lib/src/main/java/com/sandwich/util/io/StreamUtils.java similarity index 70% rename from lib/file-compiler/src/com/sandwich/util/io/StreamUtils.java rename to lib/src/main/java/com/sandwich/util/io/StreamUtils.java index 3c562893..1038ce97 100644 --- a/lib/file-compiler/src/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/file-compiler/src/com/sandwich/util/io/classloader/DynamicClassLoader.java b/lib/src/main/java/com/sandwich/util/io/classloader/DynamicClassLoader.java similarity index 87% rename from lib/file-compiler/src/com/sandwich/util/io/classloader/DynamicClassLoader.java rename to lib/src/main/java/com/sandwich/util/io/classloader/DynamicClassLoader.java index cc9d507f..354c5c93 100644 --- a/lib/file-compiler/src/com/sandwich/util/io/classloader/DynamicClassLoader.java +++ b/lib/src/main/java/com/sandwich/util/io/classloader/DynamicClassLoader.java @@ -29,17 +29,17 @@ public DynamicClassLoader(String binDir, String sourceDir, String[] classPath){ } public DynamicClassLoader(String binDir, String sourceDir, String[] classPath, ClassLoader parent) { - this(binDir, sourceDir, classPath, parent, 5000l); - } + this(binDir, sourceDir, classPath, parent, 5000l); + } public DynamicClassLoader(String binDir, String sourceDir, String[] classPath, ClassLoader parent, long timeout) { super(parent); - this.binDir = binDir; - this.sourceDir = sourceDir; - this.classPath = classPath; - this.timeout = timeout; + this.binDir = binDir; + this.sourceDir = sourceDir; + this.classPath = classPath; + this.timeout = timeout; } public abstract boolean isFileModifiedSinceLastPoll(String sourcePath, long lastModified); @@ -69,14 +69,14 @@ public static void remove(Class clas){ } public Class loadClass(String className){ - return loadClass(className, FileCompilerAction.LOGGING_HANDLER); + return loadClass(className, FileCompilerAction.LOGGING_HANDLER); } public Class loadClass(String className, CompilationListener listener){ String fileSeparator = System.getProperty("file.separator"); String fileName = binDir + fileSeparator - + className.replace(".", fileSeparator) - + FileCompiler.CLASS_SUFFIX; + + className.replace(".", fileSeparator) + + FileCompiler.CLASS_SUFFIX; File classFile = new File(fileName); try { // file may have never been compiled, go ahead and compile it now @@ -128,11 +128,11 @@ public Class loadClass(URL url, String className){ e.printStackTrace(); } - byte[] classData = buffer.toByteArray(); - clazz = defineClass(className, classData, 0, classData.length); - classesByLocation.put(url, clazz); - locationByClass.put(clazz, url); - return clazz; + byte[] classData = buffer.toByteArray(); + clazz = defineClass(className, classData, 0, classData.length); + classesByLocation.put(url, clazz); + locationByClass.put(clazz, url); + return clazz; } public long getTimeout() { diff --git a/lib/koans-lib/src/com/sandwich/util/io/directories/DirectoryManager.java b/lib/src/main/java/com/sandwich/util/io/directories/DirectoryManager.java similarity index 100% rename from lib/koans-lib/src/com/sandwich/util/io/directories/DirectoryManager.java rename to lib/src/main/java/com/sandwich/util/io/directories/DirectoryManager.java diff --git a/lib/koans-lib/src/com/sandwich/util/io/directories/DirectorySet.java b/lib/src/main/java/com/sandwich/util/io/directories/DirectorySet.java similarity index 100% rename from lib/koans-lib/src/com/sandwich/util/io/directories/DirectorySet.java rename to lib/src/main/java/com/sandwich/util/io/directories/DirectorySet.java diff --git a/lib/koans-lib/src/com/sandwich/util/io/directories/ProductionDirectories.java b/lib/src/main/java/com/sandwich/util/io/directories/ProductionDirectories.java similarity index 100% rename from lib/koans-lib/src/com/sandwich/util/io/directories/ProductionDirectories.java rename to lib/src/main/java/com/sandwich/util/io/directories/ProductionDirectories.java diff --git a/lib/file-compiler/src/com/sandwich/util/io/filecompiler/CompilationFailureLogger.java b/lib/src/main/java/com/sandwich/util/io/filecompiler/CompilationFailureLogger.java similarity index 100% rename from lib/file-compiler/src/com/sandwich/util/io/filecompiler/CompilationFailureLogger.java rename to lib/src/main/java/com/sandwich/util/io/filecompiler/CompilationFailureLogger.java diff --git a/lib/file-compiler/src/com/sandwich/util/io/filecompiler/CompilationListener.java b/lib/src/main/java/com/sandwich/util/io/filecompiler/CompilationListener.java similarity index 100% rename from lib/file-compiler/src/com/sandwich/util/io/filecompiler/CompilationListener.java rename to lib/src/main/java/com/sandwich/util/io/filecompiler/CompilationListener.java diff --git a/lib/src/main/java/com/sandwich/util/io/filecompiler/CompilerConfig.java b/lib/src/main/java/com/sandwich/util/io/filecompiler/CompilerConfig.java new file mode 100644 index 00000000..4713069b --- /dev/null +++ b/lib/src/main/java/com/sandwich/util/io/filecompiler/CompilerConfig.java @@ -0,0 +1,74 @@ +package com.sandwich.util.io.filecompiler; + +import java.io.File; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Enumeration; +import java.util.List; +import java.util.ResourceBundle; + +public class CompilerConfig { + + private static final ResourceBundle commandBySuffixRB = ResourceBundle.getBundle("compilationcommands"); + + public static boolean isSourceFile(String fileName) { + // TODO when supporting java > 5, change to return resourcebundle.containsKey(... + Enumeration keys = commandBySuffixRB.getKeys(); + String suffix = getSuffix(fileName).toLowerCase(); + while(keys.hasMoreElements()){ + String key = keys.nextElement(); + if(key.equals(suffix)){ + return true; + } + } + return false; + } + + public static String[] getCompilationCommand(File src, String destinationPath, String classPath) { + String absolutePath = src.getAbsolutePath(); + String command = commandBySuffixRB.getString(getSuffix(absolutePath)); + if(command == null){ + throw new RuntimeException("Do not know how to compile " + absolutePath); + } + List splitCommand = Arrays.asList(command.split(" ")); + List commandSegments = new ArrayList(); + for(String segment : splitCommand){ + String lowerCaseSegment = segment.toLowerCase(); + if("${bindir}".equals(lowerCaseSegment)){ + commandSegments.add(destinationPath); + }else if("${classpath}".equals(lowerCaseSegment)){ + commandSegments.add(classPath); + }else if("${filename}".equals(lowerCaseSegment)){ + commandSegments.add(src.getAbsolutePath()); + }else{ + commandSegments.add(segment); + } + } + return commandSegments.toArray(new String[commandSegments.size()]); + } + + public static Collection getSupportedFileSuffixes() { + Enumeration keysEnumeration = commandBySuffixRB.getKeys(); + Collection keys = new ArrayList(); + while(keysEnumeration.hasMoreElements()){ + keys.add(keysEnumeration.nextElement()); + } + return keys; + } + + public static String getSuffix(String fileName) { + if(fileName != null){ + int periodIndex = fileName.lastIndexOf('.'); + if(periodIndex > -1){ + return fileName.substring(periodIndex).toLowerCase(); + } + } + return ""; + } + + public static boolean isSuffixSupported(String suffix) { + return getSupportedFileSuffixes().contains(suffix); + } + +} diff --git a/lib/file-compiler/src/com/sandwich/util/io/filecompiler/FileCompiler.java b/lib/src/main/java/com/sandwich/util/io/filecompiler/FileCompiler.java similarity index 99% rename from lib/file-compiler/src/com/sandwich/util/io/filecompiler/FileCompiler.java rename to lib/src/main/java/com/sandwich/util/io/filecompiler/FileCompiler.java index f97d2e67..599d69bf 100644 --- a/lib/file-compiler/src/com/sandwich/util/io/filecompiler/FileCompiler.java +++ b/lib/src/main/java/com/sandwich/util/io/filecompiler/FileCompiler.java @@ -64,11 +64,13 @@ public static File getSourceFileFromClass(String sourceDir, String className) { if(className.contains(DOLLAR_SIGN)){ className = className.substring(0, className.indexOf(DOLLAR_SIGN)); } + File possibleSourceFile = new File(sourceDir); File sourceFile = null; for(String folder : className.split("\\.")){ possibleSourceFile = new File(possibleSourceFile, folder); } + for(String suffix : CompilerConfig.getSupportedFileSuffixes()){ File file = new File(possibleSourceFile.getAbsolutePath() + suffix); if(file.exists()){ diff --git a/lib/file-compiler/src/com/sandwich/util/io/filecompiler/FileCompilerAction.java b/lib/src/main/java/com/sandwich/util/io/filecompiler/FileCompilerAction.java similarity index 100% rename from lib/file-compiler/src/com/sandwich/util/io/filecompiler/FileCompilerAction.java rename to lib/src/main/java/com/sandwich/util/io/filecompiler/FileCompilerAction.java diff --git a/lib/util/src/com/sandwich/util/io/ui/DefaultErrorPresenter.java b/lib/src/main/java/com/sandwich/util/io/ui/DefaultErrorPresenter.java similarity index 100% rename from lib/util/src/com/sandwich/util/io/ui/DefaultErrorPresenter.java rename to lib/src/main/java/com/sandwich/util/io/ui/DefaultErrorPresenter.java diff --git a/lib/util/src/com/sandwich/util/io/ui/ErrorPresenter.java b/lib/src/main/java/com/sandwich/util/io/ui/ErrorPresenter.java similarity index 100% rename from lib/util/src/com/sandwich/util/io/ui/ErrorPresenter.java rename to lib/src/main/java/com/sandwich/util/io/ui/ErrorPresenter.java diff --git a/lib/koans-tests/test/com/sandwich/koan/AnonymousInnerClassTest.java b/lib/src/test/java/com/sandwich/koan/AnonymousInnerClassTest.java similarity index 100% rename from lib/koans-tests/test/com/sandwich/koan/AnonymousInnerClassTest.java rename to lib/src/test/java/com/sandwich/koan/AnonymousInnerClassTest.java diff --git a/lib/koans-tests/test/com/sandwich/koan/KoansResultTest.java b/lib/src/test/java/com/sandwich/koan/KoansResultTest.java similarity index 100% rename from lib/koans-tests/test/com/sandwich/koan/KoansResultTest.java rename to lib/src/test/java/com/sandwich/koan/KoansResultTest.java diff --git a/lib/koans-tests/test/com/sandwich/koan/LocaleSwitchingTestCase.java b/lib/src/test/java/com/sandwich/koan/LocaleSwitchingTestCase.java similarity index 100% rename from lib/koans-tests/test/com/sandwich/koan/LocaleSwitchingTestCase.java rename to lib/src/test/java/com/sandwich/koan/LocaleSwitchingTestCase.java diff --git a/lib/koans-tests/test/com/sandwich/koan/TestUtils.java b/lib/src/test/java/com/sandwich/koan/TestUtils.java similarity index 100% rename from lib/koans-tests/test/com/sandwich/koan/TestUtils.java rename to lib/src/test/java/com/sandwich/koan/TestUtils.java diff --git a/lib/koans-tests/test/com/sandwich/koan/TestUtilsTest.java b/lib/src/test/java/com/sandwich/koan/TestUtilsTest.java similarity index 97% rename from lib/koans-tests/test/com/sandwich/koan/TestUtilsTest.java rename to lib/src/test/java/com/sandwich/koan/TestUtilsTest.java index ad047315..19ccd88a 100755 --- a/lib/koans-tests/test/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/koans-tests/test/com/sandwich/koan/cmdline/CommandLineArgumentBuilderTest.java b/lib/src/test/java/com/sandwich/koan/cmdline/CommandLineArgumentBuilderTest.java similarity index 100% rename from lib/koans-tests/test/com/sandwich/koan/cmdline/CommandLineArgumentBuilderTest.java rename to lib/src/test/java/com/sandwich/koan/cmdline/CommandLineArgumentBuilderTest.java diff --git a/lib/koans-tests/test/com/sandwich/koan/constant/ArgumentTypeTest.java b/lib/src/test/java/com/sandwich/koan/constant/ArgumentTypeTest.java similarity index 100% rename from lib/koans-tests/test/com/sandwich/koan/constant/ArgumentTypeTest.java rename to lib/src/test/java/com/sandwich/koan/constant/ArgumentTypeTest.java diff --git a/lib/koans-tests/test/com/sandwich/koan/path/CommandLineTestCase.java b/lib/src/test/java/com/sandwich/koan/path/CommandLineTestCase.java similarity index 98% rename from lib/koans-tests/test/com/sandwich/koan/path/CommandLineTestCase.java rename to lib/src/test/java/com/sandwich/koan/path/CommandLineTestCase.java index ddef20e1..0f80b9e0 100755 --- a/lib/koans-tests/test/com/sandwich/koan/path/CommandLineTestCase.java +++ b/lib/src/test/java/com/sandwich/koan/path/CommandLineTestCase.java @@ -33,7 +33,7 @@ import com.sandwich.util.io.KoanSuiteCompilationListener; import com.sandwich.util.io.classloader.DynamicClassLoader; import com.sandwich.util.io.directories.DirectoryManager; -import com.sandwich.util.io.directories.ProductionExecutedFromTestsDirectories; +import com.sandwich.util.io.directories.ProductionDirectories; import com.sandwich.util.io.directories.UnitTestDirectories; public abstract class CommandLineTestCase { @@ -63,7 +63,7 @@ public void setUp() throws Exception { @After public void tearDown() throws Exception { - DirectoryManager.setDirectorySet(new ProductionExecutedFromTestsDirectories()); + DirectoryManager.setDirectorySet(new ProductionDirectories()); setRealPath(); if(out != null){ System.setOut(out); diff --git a/lib/koans-tests/test/com/sandwich/koan/path/PathToEnlightenmentTest.java b/lib/src/test/java/com/sandwich/koan/path/PathToEnlightenmentTest.java similarity index 100% rename from lib/koans-tests/test/com/sandwich/koan/path/PathToEnlightenmentTest.java rename to lib/src/test/java/com/sandwich/koan/path/PathToEnlightenmentTest.java diff --git a/lib/koans-tests/test/com/sandwich/koan/path/RbVariableInjectorTest.java b/lib/src/test/java/com/sandwich/koan/path/RbVariableInjectorTest.java similarity index 100% rename from lib/koans-tests/test/com/sandwich/koan/path/RbVariableInjectorTest.java rename to lib/src/test/java/com/sandwich/koan/path/RbVariableInjectorTest.java diff --git a/lib/koans-tests/data/src/com/sandwich/koan/path/xmltransformation/FakeXmlToPathTransformer.java b/lib/src/test/java/com/sandwich/koan/path/xmltransformation/FakeXmlToPathTransformer.java similarity index 100% rename from lib/koans-tests/data/src/com/sandwich/koan/path/xmltransformation/FakeXmlToPathTransformer.java rename to lib/src/test/java/com/sandwich/koan/path/xmltransformation/FakeXmlToPathTransformer.java diff --git a/lib/koans-tests/data/src/com/sandwich/koan/runner/AppLauncherTest.java b/lib/src/test/java/com/sandwich/koan/runner/AppLauncherTest.java similarity index 100% rename from lib/koans-tests/data/src/com/sandwich/koan/runner/AppLauncherTest.java rename to lib/src/test/java/com/sandwich/koan/runner/AppLauncherTest.java diff --git a/lib/koans-tests/test/com/sandwich/koan/runner/AppReadinessForDeploymentTest.java b/lib/src/test/java/com/sandwich/koan/runner/AppReadinessForDeploymentTest.java similarity index 96% rename from lib/koans-tests/test/com/sandwich/koan/runner/AppReadinessForDeploymentTest.java rename to lib/src/test/java/com/sandwich/koan/runner/AppReadinessForDeploymentTest.java index 435f1eb0..ae156b72 100755 --- a/lib/koans-tests/test/com/sandwich/koan/runner/AppReadinessForDeploymentTest.java +++ b/lib/src/test/java/com/sandwich/koan/runner/AppReadinessForDeploymentTest.java @@ -31,7 +31,7 @@ import com.sandwich.koan.ui.SuitePresenter; import com.sandwich.util.Strings; import com.sandwich.util.io.directories.DirectoryManager; -import com.sandwich.util.io.directories.ProductionExecutedFromTestsDirectories; +import com.sandwich.util.io.directories.ProductionDirectories; /** * Anything that absolutely has to happen before bundling client jar - to be sure: @@ -93,7 +93,7 @@ public void testGetKoans() throws Exception { KoanMethod.getInstance(entry.getValue().get("koan")).getMethod().toString()); } - @Test /** Ensures that koans are ready for packaging & distribution */ + @Test public void testKoanSuiteRunner_firstKoanFail() throws Exception { final KoanSuiteResult[] result = new KoanSuiteResult[]{null}; stubPresenter(new SuitePresenter(){ @@ -115,7 +115,7 @@ public void run(){ assertEquals(result[0].getFailingCase(), firstSuiteClassRan.substring(firstSuiteClassRan.lastIndexOf(".") + 1)); } - @Test /** Ensures that koans are ready for packaging & distribution */ + @Test public void testKoanSuiteRunner_allKoansFail() throws Exception { setRealPath(); final KoanSuiteResult[] result = new KoanSuiteResult[]{null}; @@ -142,7 +142,7 @@ public void run(){ } private void doAsIfInProd(Runnable runnable) { - DirectoryManager.setDirectorySet(new ProductionExecutedFromTestsDirectories()); + DirectoryManager.setDirectorySet(new ProductionDirectories()); resetClassLoader(); setRealPath(); runnable.run(); diff --git a/lib/koans-tests/test/com/sandwich/koan/runner/CommandLineTestCaseTest.java b/lib/src/test/java/com/sandwich/koan/runner/CommandLineTestCaseTest.java similarity index 100% rename from lib/koans-tests/test/com/sandwich/koan/runner/CommandLineTestCaseTest.java rename to lib/src/test/java/com/sandwich/koan/runner/CommandLineTestCaseTest.java diff --git a/lib/koans-tests/test/com/sandwich/koan/runner/ConsolePresenterTest.java b/lib/src/test/java/com/sandwich/koan/runner/ConsolePresenterTest.java similarity index 100% rename from lib/koans-tests/test/com/sandwich/koan/runner/ConsolePresenterTest.java rename to lib/src/test/java/com/sandwich/koan/runner/ConsolePresenterTest.java diff --git a/lib/koans-tests/test/com/sandwich/koan/runner/ui/AbstractSuitePresenterTest.java b/lib/src/test/java/com/sandwich/koan/runner/ui/AbstractSuitePresenterTest.java similarity index 100% rename from lib/koans-tests/test/com/sandwich/koan/runner/ui/AbstractSuitePresenterTest.java rename to lib/src/test/java/com/sandwich/koan/runner/ui/AbstractSuitePresenterTest.java diff --git a/lib/koans-tests/test/com/sandwich/koan/suite/BlowUpOnLineEleven.java b/lib/src/test/java/com/sandwich/koan/suite/BlowUpOnLineEleven.java similarity index 100% rename from lib/koans-tests/test/com/sandwich/koan/suite/BlowUpOnLineEleven.java rename to lib/src/test/java/com/sandwich/koan/suite/BlowUpOnLineEleven.java diff --git a/lib/koans-tests/test/com/sandwich/koan/suite/BlowUpOnLineTen.java b/lib/src/test/java/com/sandwich/koan/suite/BlowUpOnLineTen.java similarity index 100% rename from lib/koans-tests/test/com/sandwich/koan/suite/BlowUpOnLineTen.java rename to lib/src/test/java/com/sandwich/koan/suite/BlowUpOnLineTen.java diff --git a/lib/koans-tests/data/src/com/sandwich/koan/suite/OneFailingKoan.java b/lib/src/test/java/com/sandwich/koan/suite/OneFailingKoan.java old mode 100644 new mode 100755 similarity index 100% rename from lib/koans-tests/data/src/com/sandwich/koan/suite/OneFailingKoan.java rename to lib/src/test/java/com/sandwich/koan/suite/OneFailingKoan.java diff --git a/lib/koans-tests/data/src/com/sandwich/koan/suite/OneFailingKoanDifferentName.java b/lib/src/test/java/com/sandwich/koan/suite/OneFailingKoanDifferentName.java old mode 100644 new mode 100755 similarity index 100% rename from lib/koans-tests/data/src/com/sandwich/koan/suite/OneFailingKoanDifferentName.java rename to lib/src/test/java/com/sandwich/koan/suite/OneFailingKoanDifferentName.java diff --git a/lib/koans-tests/data/src/com/sandwich/koan/suite/OnePassingKoan.java b/lib/src/test/java/com/sandwich/koan/suite/OnePassingKoan.java old mode 100644 new mode 100755 similarity index 100% rename from lib/koans-tests/data/src/com/sandwich/koan/suite/OnePassingKoan.java rename to lib/src/test/java/com/sandwich/koan/suite/OnePassingKoan.java diff --git a/lib/koans-tests/test/com/sandwich/koan/suite/OnePassingKoanDifferentName.java b/lib/src/test/java/com/sandwich/koan/suite/OnePassingKoanDifferentName.java similarity index 100% rename from lib/koans-tests/test/com/sandwich/koan/suite/OnePassingKoanDifferentName.java rename to lib/src/test/java/com/sandwich/koan/suite/OnePassingKoanDifferentName.java diff --git a/lib/koans-tests/test/com/sandwich/koan/suite/TwoFailingKoans.java b/lib/src/test/java/com/sandwich/koan/suite/TwoFailingKoans.java similarity index 100% rename from lib/koans-tests/test/com/sandwich/koan/suite/TwoFailingKoans.java rename to lib/src/test/java/com/sandwich/koan/suite/TwoFailingKoans.java diff --git a/lib/koans-tests/test/com/sandwich/koan/suite/WrongExpectationOrderKoan.java b/lib/src/test/java/com/sandwich/koan/suite/WrongExpectationOrderKoan.java similarity index 100% rename from lib/koans-tests/test/com/sandwich/koan/suite/WrongExpectationOrderKoan.java rename to lib/src/test/java/com/sandwich/koan/suite/WrongExpectationOrderKoan.java diff --git a/lib/koans-tests/test/com/sandwich/util/KoanComparatorTest.java b/lib/src/test/java/com/sandwich/util/KoanComparatorTest.java similarity index 58% rename from lib/koans-tests/test/com/sandwich/util/KoanComparatorTest.java rename to lib/src/test/java/com/sandwich/util/KoanComparatorTest.java index ef16fb86..8b709d23 100755 --- a/lib/koans-tests/test/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(){ + @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)); + } } diff --git a/lib/koans-tests/test/com/sandwich/util/SimpleEntry.java b/lib/src/test/java/com/sandwich/util/SimpleEntry.java similarity index 94% rename from lib/koans-tests/test/com/sandwich/util/SimpleEntry.java rename to lib/src/test/java/com/sandwich/util/SimpleEntry.java index c27e16ab..816e0498 100755 --- a/lib/koans-tests/test/com/sandwich/util/SimpleEntry.java +++ b/lib/src/test/java/com/sandwich/util/SimpleEntry.java @@ -1,68 +1,68 @@ -package com.sandwich.util; - -import java.util.Map.Entry; - -/** - * Why on earth this wasn't around when JDK5 was released is just as bad as - * string.isEmpty()'s absence jeesh! - * - * @param - * @param - */ -public class SimpleEntry implements Entry{ - - private K k; - private V v; - - public SimpleEntry(K k, V v){ - this.k = k; - this.v = v; - } - - public K getKey() { - return k; - } - - public V getValue() { - return v; - } - - public V setValue(V value) { - V tmp = v; - v = value; - return tmp; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((k == null) ? 0 : k.hashCode()); - result = prime * result + ((v == null) ? 0 : v.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if(!Entry.class.isAssignableFrom(SimpleEntry.class)){ - return false; - } - Entry other = (Entry) obj; - if (k == null) { - if (other.getKey() != null) - return false; - } else if (!k.equals(other.getKey())) - return false; - if (v == null) { - if (other.getValue() != null) - return false; - } else if (!v.equals(other.getValue())) - return false; - return true; - } - -} +package com.sandwich.util; + +import java.util.Map.Entry; + +/** + * Why on earth this wasn't around when JDK5 was released is just as bad as + * string.isEmpty()'s absence jeesh! + * + * @param + * @param + */ +public class SimpleEntry implements Entry{ + + private K k; + private V v; + + public SimpleEntry(K k, V v){ + this.k = k; + this.v = v; + } + + public K getKey() { + return k; + } + + public V getValue() { + return v; + } + + public V setValue(V value) { + V tmp = v; + v = value; + return tmp; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((k == null) ? 0 : k.hashCode()); + result = prime * result + ((v == null) ? 0 : v.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if(!Entry.class.isAssignableFrom(SimpleEntry.class)){ + return false; + } + Entry other = (Entry) obj; + if (k == null) { + if (other.getKey() != null) + return false; + } else if (!k.equals(other.getKey())) + return false; + if (v == null) { + if (other.getValue() != null) + return false; + } else if (!v.equals(other.getValue())) + return false; + return true; + } + +} diff --git a/lib/koans-tests/test/com/sandwich/util/StringsTest.java b/lib/src/test/java/com/sandwich/util/StringsTest.java similarity index 100% rename from lib/koans-tests/test/com/sandwich/util/StringsTest.java rename to lib/src/test/java/com/sandwich/util/StringsTest.java diff --git a/lib/koans-tests/test/com/sandwich/util/io/DirectoryManagerTest.java b/lib/src/test/java/com/sandwich/util/io/DirectoryManagerTest.java similarity index 100% rename from lib/koans-tests/test/com/sandwich/util/io/DirectoryManagerTest.java rename to lib/src/test/java/com/sandwich/util/io/DirectoryManagerTest.java 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___"))); + } + +} diff --git a/lib/src/test/java/com/sandwich/util/io/directories/UnitTestDirectories.java b/lib/src/test/java/com/sandwich/util/io/directories/UnitTestDirectories.java new file mode 100644 index 00000000..11e15f3e --- /dev/null +++ b/lib/src/test/java/com/sandwich/util/io/directories/UnitTestDirectories.java @@ -0,0 +1,17 @@ +package com.sandwich.util.io.directories; + + + +public class UnitTestDirectories extends ProductionDirectories { + + public String getSourceDir() { + return "java"; + } + + public String getProjectDir() { + String sep = System.getProperty("file.separator"); + return super.getLibrariesDir() + sep + + "src" + sep + "test"; + } + +} diff --git a/lib/util/.classpath b/lib/util/.classpath deleted file mode 100644 index fb501163..00000000 --- a/lib/util/.classpath +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/lib/util/.project b/lib/util/.project deleted file mode 100644 index ee97704d..00000000 --- a/lib/util/.project +++ /dev/null @@ -1,17 +0,0 @@ - - - util - - - - - - org.eclipse.jdt.core.javabuilder - - - - - - org.eclipse.jdt.core.javanature - - diff --git a/lib/util/src/com/sandwich/util/io/FileOperation.java b/lib/util/src/com/sandwich/util/io/FileOperation.java deleted file mode 100644 index c6e2e167..00000000 --- a/lib/util/src/com/sandwich/util/io/FileOperation.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.sandwich.util.io; - -import java.io.File; -import java.io.IOException; - -public abstract class FileOperation implements FileAction { - - 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); - } - } - -}