diff --git a/README.md b/README.md index e75f4549..5466d09f 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,12 @@ # Java Exercise -This is a simple exercise to allow you to demostrate your software engineering skillset. It's completly up to you how long you give yourself, stop when you're happy with the quality of your work, but we don't expect it to take too long. - -## Instructions - 1. Please fork this repository and work on your fork. - _https://help.github.com/en/articles/fork-a-repo_ - 2. Commit changes frequently so that we can review your progression with you later. - _https://crealytics.com/blog/5-reasons-keeping-git-commits-small/_ - 3. You should use a recognised build tool, e.g. _gradle_, _maven_... - 4. We are currently using [open JDK 8u181](https://cdn.azul.com/zulu/bin/zulu8.31.0.1-jdk8.0.181-win_x64.msi). But please use the JDK you think is most appropriate to demonstrate your skillset. - 5. We don't expect 100% code coverage, we expect well tested code. - _https://medium.com/@nicklee1/why-test-code-coverage-targets-are-a-bad-idea-1b9b8ef711ef_ - 6. Any other tools or libraries used must be freely available. Any third-party jars must be accessible via [maven central](https://mvnrepository.com/repos/central). - 7. The specification is below. +This is a simple exercise done by Mehmet Sibar. The application can run via command line. It will ask a few questions to fill the shopping cart. At the end of it, the application should show your cart and the total price. + +It's best to run the test to see how the application performs. + +The command-line interface has not designed very well as the main focus is the code quality and logic. + + ## Specification @@ -35,12 +29,6 @@ Henry’s Grocery, currently only stocks four items and has two promotions. Thes | :--- | :---: | :---: | | Buy 2 tins of soup and get a loaf of bread half price | yesterday | for 7 days | | Apples have a 10% discount | from 3 days hence | until the end of the following month | - -### Inputs - All basket items added via the command prompt. - -### Outputs -All outputs must print to the command line. ### Tests - Price a basket containing: 3 tins of soup and 2 loaves of bread, bought today, diff --git a/build.gradle b/build.gradle new file mode 100644 index 00000000..030c01a3 --- /dev/null +++ b/build.gradle @@ -0,0 +1,17 @@ +plugins { + id 'java' +} + +group 'com.ford.exercise' +version '1.0-SNAPSHOT' + +sourceCompatibility = 1.8 + +repositories { + mavenCentral() +} + +dependencies { + testCompile group: 'org.hamcrest', name: 'java-hamcrest', version: '2.0.0.0' + testCompile group: 'junit', name: 'junit', version: '4.12' +} diff --git a/build/classes/java/main/cart/ShoppingCart.class b/build/classes/java/main/cart/ShoppingCart.class new file mode 100644 index 00000000..4ca6a3f6 Binary files /dev/null and b/build/classes/java/main/cart/ShoppingCart.class differ diff --git a/build/classes/java/main/item/Item.class b/build/classes/java/main/item/Item.class new file mode 100644 index 00000000..089d7dab Binary files /dev/null and b/build/classes/java/main/item/Item.class differ diff --git a/build/classes/java/main/item/PriceCalculator.class b/build/classes/java/main/item/PriceCalculator.class new file mode 100644 index 00000000..7f25f265 Binary files /dev/null and b/build/classes/java/main/item/PriceCalculator.class differ diff --git a/build/classes/java/main/item/Unit.class b/build/classes/java/main/item/Unit.class new file mode 100644 index 00000000..11c67545 Binary files /dev/null and b/build/classes/java/main/item/Unit.class differ diff --git a/build/classes/java/test/unit/GroceryTest.class b/build/classes/java/test/unit/GroceryTest.class new file mode 100644 index 00000000..ba45a96c Binary files /dev/null and b/build/classes/java/test/unit/GroceryTest.class differ diff --git a/build/reports/tests/test/classes/unit.GroceryTest.html b/build/reports/tests/test/classes/unit.GroceryTest.html new file mode 100644 index 00000000..0ff28d77 --- /dev/null +++ b/build/reports/tests/test/classes/unit.GroceryTest.html @@ -0,0 +1,387 @@ + + + + + +Test results - Class unit.GroceryTest + + + + + +
+

Class unit.GroceryTest

+ +
+ + + + + +
+
+ + + + + + + +
+
+
6
+

tests

+
+
+
+
4
+

failures

+
+
+
+
0
+

ignored

+
+
+
+
0.032s
+

duration

+
+
+
+
+
+
33%
+

successful

+
+
+
+
+ +
+

Failed tests

+
+ +

applyAllDiscountsWhenConditionAndDateValid

+ +
java.lang.NullPointerException
+	at cart.ShoppingCart.lambda$calculate$0(ShoppingCart.java:23)
+	at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
+	at java.util.HashMap$KeySpliterator.forEachRemaining(HashMap.java:1556)
+	at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:482)
+	at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:472)
+	at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
+	at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
+	at java.util.stream.ReferencePipeline.reduce(ReferencePipeline.java:474)
+	at cart.ShoppingCart.calculate(ShoppingCart.java:23)
+	at unit.GroceryTest.applyAllDiscountsWhenConditionAndDateValid(GroceryTest.java:56)
+	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
+	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
+	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
+	at java.lang.reflect.Method.invoke(Method.java:498)
+	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
+	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
+	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
+	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
+	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
+	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
+	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
+	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
+	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
+	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
+	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
+	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
+	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
+	at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.runTestClass(JUnitTestClassExecutor.java:106)
+	at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:58)
+	at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:38)
+	at org.gradle.api.internal.tasks.testing.junit.AbstractJUnitTestClassProcessor.processTestClass(AbstractJUnitTestClassProcessor.java:66)
+	at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:51)
+	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
+	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
+	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
+	at java.lang.reflect.Method.invoke(Method.java:498)
+	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
+	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
+	at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:32)
+	at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:93)
+	at com.sun.proxy.$Proxy2.processTestClass(Unknown Source)
+	at org.gradle.api.internal.tasks.testing.worker.TestWorker.processTestClass(TestWorker.java:117)
+	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
+	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
+	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
+	at java.lang.reflect.Method.invoke(Method.java:498)
+	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
+	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
+	at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:155)
+	at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:137)
+	at org.gradle.internal.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:404)
+	at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63)
+	at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:46)
+	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
+	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
+	at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:55)
+	at java.lang.Thread.run(Thread.java:748)
+
+
+
+
+ +

applyDiscountToApplesWhenDiscountDateValid

+ +
java.lang.NullPointerException
+	at cart.ShoppingCart.lambda$calculate$0(ShoppingCart.java:23)
+	at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
+	at java.util.HashMap$KeySpliterator.forEachRemaining(HashMap.java:1556)
+	at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:482)
+	at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:472)
+	at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
+	at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
+	at java.util.stream.ReferencePipeline.reduce(ReferencePipeline.java:474)
+	at cart.ShoppingCart.calculate(ShoppingCart.java:23)
+	at unit.GroceryTest.applyDiscountToApplesWhenDiscountDateValid(GroceryTest.java:43)
+	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
+	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
+	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
+	at java.lang.reflect.Method.invoke(Method.java:498)
+	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
+	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
+	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
+	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
+	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
+	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
+	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
+	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
+	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
+	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
+	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
+	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
+	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
+	at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.runTestClass(JUnitTestClassExecutor.java:106)
+	at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:58)
+	at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:38)
+	at org.gradle.api.internal.tasks.testing.junit.AbstractJUnitTestClassProcessor.processTestClass(AbstractJUnitTestClassProcessor.java:66)
+	at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:51)
+	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
+	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
+	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
+	at java.lang.reflect.Method.invoke(Method.java:498)
+	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
+	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
+	at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:32)
+	at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:93)
+	at com.sun.proxy.$Proxy2.processTestClass(Unknown Source)
+	at org.gradle.api.internal.tasks.testing.worker.TestWorker.processTestClass(TestWorker.java:117)
+	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
+	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
+	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
+	at java.lang.reflect.Method.invoke(Method.java:498)
+	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
+	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
+	at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:155)
+	at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:137)
+	at org.gradle.internal.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:404)
+	at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63)
+	at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:46)
+	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
+	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
+	at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:55)
+	at java.lang.Thread.run(Thread.java:748)
+
+
+
+
+ +

applyDiscountToOneBreadWhenThreeTinsOfSoupBought

+ +
java.lang.NullPointerException
+	at cart.ShoppingCart.lambda$calculate$0(ShoppingCart.java:23)
+	at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
+	at java.util.HashMap$KeySpliterator.forEachRemaining(HashMap.java:1556)
+	at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:482)
+	at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:472)
+	at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
+	at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
+	at java.util.stream.ReferencePipeline.reduce(ReferencePipeline.java:474)
+	at cart.ShoppingCart.calculate(ShoppingCart.java:23)
+	at unit.GroceryTest.applyDiscountToOneBreadWhenThreeTinsOfSoupBought(GroceryTest.java:21)
+	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
+	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
+	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
+	at java.lang.reflect.Method.invoke(Method.java:498)
+	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
+	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
+	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
+	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
+	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
+	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
+	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
+	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
+	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
+	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
+	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
+	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
+	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
+	at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.runTestClass(JUnitTestClassExecutor.java:106)
+	at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:58)
+	at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:38)
+	at org.gradle.api.internal.tasks.testing.junit.AbstractJUnitTestClassProcessor.processTestClass(AbstractJUnitTestClassProcessor.java:66)
+	at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:51)
+	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
+	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
+	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
+	at java.lang.reflect.Method.invoke(Method.java:498)
+	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
+	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
+	at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:32)
+	at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:93)
+	at com.sun.proxy.$Proxy2.processTestClass(Unknown Source)
+	at org.gradle.api.internal.tasks.testing.worker.TestWorker.processTestClass(TestWorker.java:117)
+	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
+	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
+	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
+	at java.lang.reflect.Method.invoke(Method.java:498)
+	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
+	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
+	at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:155)
+	at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:137)
+	at org.gradle.internal.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:404)
+	at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63)
+	at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:46)
+	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
+	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
+	at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:55)
+	at java.lang.Thread.run(Thread.java:748)
+
+
+
+
+ +

dontApplyDiscountWhenDiscountDateInvalid

+ +
java.lang.NullPointerException
+	at cart.ShoppingCart.lambda$calculate$0(ShoppingCart.java:23)
+	at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
+	at java.util.HashMap$KeySpliterator.forEachRemaining(HashMap.java:1556)
+	at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:482)
+	at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:472)
+	at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
+	at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
+	at java.util.stream.ReferencePipeline.reduce(ReferencePipeline.java:474)
+	at cart.ShoppingCart.calculate(ShoppingCart.java:23)
+	at unit.GroceryTest.dontApplyDiscountWhenDiscountDateInvalid(GroceryTest.java:32)
+	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
+	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
+	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
+	at java.lang.reflect.Method.invoke(Method.java:498)
+	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
+	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
+	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
+	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
+	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
+	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
+	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
+	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
+	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
+	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
+	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
+	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
+	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
+	at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.runTestClass(JUnitTestClassExecutor.java:106)
+	at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:58)
+	at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:38)
+	at org.gradle.api.internal.tasks.testing.junit.AbstractJUnitTestClassProcessor.processTestClass(AbstractJUnitTestClassProcessor.java:66)
+	at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:51)
+	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
+	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
+	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
+	at java.lang.reflect.Method.invoke(Method.java:498)
+	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
+	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
+	at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:32)
+	at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:93)
+	at com.sun.proxy.$Proxy2.processTestClass(Unknown Source)
+	at org.gradle.api.internal.tasks.testing.worker.TestWorker.processTestClass(TestWorker.java:117)
+	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
+	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
+	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
+	at java.lang.reflect.Method.invoke(Method.java:498)
+	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
+	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
+	at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:155)
+	at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:137)
+	at org.gradle.internal.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:404)
+	at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63)
+	at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:46)
+	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
+	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
+	at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:55)
+	at java.lang.Thread.run(Thread.java:748)
+
+
+
+
+
+

Tests

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TestDurationResult
applyAllDiscountsWhenConditionAndDateValid0.028sfailed
applyDiscountToApplesWhenDiscountDateValid0sfailed
applyDiscountToOneBreadWhenThreeTinsOfSoupBought0sfailed
dontApplyDiscountWhenDiscountDateInvalid0.001sfailed
shoppingCartShouldAddItems0spassed
shoppingCartShouldIncreaseTheTotalNumberOfItems0.003spassed
+
+
+ +
+ + diff --git a/build/reports/tests/test/css/base-style.css b/build/reports/tests/test/css/base-style.css new file mode 100644 index 00000000..4afa73e3 --- /dev/null +++ b/build/reports/tests/test/css/base-style.css @@ -0,0 +1,179 @@ + +body { + margin: 0; + padding: 0; + font-family: sans-serif; + font-size: 12pt; +} + +body, a, a:visited { + color: #303030; +} + +#content { + padding-left: 50px; + padding-right: 50px; + padding-top: 30px; + padding-bottom: 30px; +} + +#content h1 { + font-size: 160%; + margin-bottom: 10px; +} + +#footer { + margin-top: 100px; + font-size: 80%; + white-space: nowrap; +} + +#footer, #footer a { + color: #a0a0a0; +} + +#line-wrapping-toggle { + vertical-align: middle; +} + +#label-for-line-wrapping-toggle { + vertical-align: middle; +} + +ul { + margin-left: 0; +} + +h1, h2, h3 { + white-space: nowrap; +} + +h2 { + font-size: 120%; +} + +ul.tabLinks { + padding-left: 0; + padding-top: 10px; + padding-bottom: 10px; + overflow: auto; + min-width: 800px; + width: auto !important; + width: 800px; +} + +ul.tabLinks li { + float: left; + height: 100%; + list-style: none; + padding-left: 10px; + padding-right: 10px; + padding-top: 5px; + padding-bottom: 5px; + margin-bottom: 0; + -moz-border-radius: 7px; + border-radius: 7px; + margin-right: 25px; + border: solid 1px #d4d4d4; + background-color: #f0f0f0; +} + +ul.tabLinks li:hover { + background-color: #fafafa; +} + +ul.tabLinks li.selected { + background-color: #c5f0f5; + border-color: #c5f0f5; +} + +ul.tabLinks a { + font-size: 120%; + display: block; + outline: none; + text-decoration: none; + margin: 0; + padding: 0; +} + +ul.tabLinks li h2 { + margin: 0; + padding: 0; +} + +div.tab { +} + +div.selected { + display: block; +} + +div.deselected { + display: none; +} + +div.tab table { + min-width: 350px; + width: auto !important; + width: 350px; + border-collapse: collapse; +} + +div.tab th, div.tab table { + border-bottom: solid #d0d0d0 1px; +} + +div.tab th { + text-align: left; + white-space: nowrap; + padding-left: 6em; +} + +div.tab th:first-child { + padding-left: 0; +} + +div.tab td { + white-space: nowrap; + padding-left: 6em; + padding-top: 5px; + padding-bottom: 5px; +} + +div.tab td:first-child { + padding-left: 0; +} + +div.tab td.numeric, div.tab th.numeric { + text-align: right; +} + +span.code { + display: inline-block; + margin-top: 0em; + margin-bottom: 1em; +} + +span.code pre { + font-size: 11pt; + padding-top: 10px; + padding-bottom: 10px; + padding-left: 10px; + padding-right: 10px; + margin: 0; + background-color: #f7f7f7; + border: solid 1px #d0d0d0; + min-width: 700px; + width: auto !important; + width: 700px; +} + +span.wrapped pre { + word-wrap: break-word; + white-space: pre-wrap; + word-break: break-all; +} + +label.hidden { + display: none; +} \ No newline at end of file diff --git a/build/reports/tests/test/css/style.css b/build/reports/tests/test/css/style.css new file mode 100644 index 00000000..3dc4913e --- /dev/null +++ b/build/reports/tests/test/css/style.css @@ -0,0 +1,84 @@ + +#summary { + margin-top: 30px; + margin-bottom: 40px; +} + +#summary table { + border-collapse: collapse; +} + +#summary td { + vertical-align: top; +} + +.breadcrumbs, .breadcrumbs a { + color: #606060; +} + +.infoBox { + width: 110px; + padding-top: 15px; + padding-bottom: 15px; + text-align: center; +} + +.infoBox p { + margin: 0; +} + +.counter, .percent { + font-size: 120%; + font-weight: bold; + margin-bottom: 8px; +} + +#duration { + width: 125px; +} + +#successRate, .summaryGroup { + border: solid 2px #d0d0d0; + -moz-border-radius: 10px; + border-radius: 10px; +} + +#successRate { + width: 140px; + margin-left: 35px; +} + +#successRate .percent { + font-size: 180%; +} + +.success, .success a { + color: #008000; +} + +div.success, #successRate.success { + background-color: #bbd9bb; + border-color: #008000; +} + +.failures, .failures a { + color: #b60808; +} + +.skipped, .skipped a { + color: #c09853; +} + +div.failures, #successRate.failures { + background-color: #ecdada; + border-color: #b60808; +} + +ul.linkList { + padding-left: 0; +} + +ul.linkList li { + list-style: none; + margin-bottom: 5px; +} diff --git a/build/reports/tests/test/index.html b/build/reports/tests/test/index.html new file mode 100644 index 00000000..54284c82 --- /dev/null +++ b/build/reports/tests/test/index.html @@ -0,0 +1,156 @@ + + + + + +Test results - Test Summary + + + + + +
+

Test Summary

+
+ + + + + +
+
+ + + + + + + +
+
+
6
+

tests

+
+
+
+
4
+

failures

+
+
+
+
0
+

ignored

+
+
+
+
0.032s
+

duration

+
+
+
+
+
+
33%
+

successful

+
+
+
+
+ + +
+

Packages

+ + + + + + + + + + + + + + + + + + + + + +
PackageTestsFailuresIgnoredDurationSuccess rate
+unit +6400.032s33%
+
+
+

Classes

+ + + + + + + + + + + + + + + + + + + + +
ClassTestsFailuresIgnoredDurationSuccess rate
+unit.GroceryTest +6400.032s33%
+
+
+ +
+ + diff --git a/build/reports/tests/test/js/report.js b/build/reports/tests/test/js/report.js new file mode 100644 index 00000000..83bab4a1 --- /dev/null +++ b/build/reports/tests/test/js/report.js @@ -0,0 +1,194 @@ +(function (window, document) { + "use strict"; + + var tabs = {}; + + function changeElementClass(element, classValue) { + if (element.getAttribute("className")) { + element.setAttribute("className", classValue); + } else { + element.setAttribute("class", classValue); + } + } + + function getClassAttribute(element) { + if (element.getAttribute("className")) { + return element.getAttribute("className"); + } else { + return element.getAttribute("class"); + } + } + + function addClass(element, classValue) { + changeElementClass(element, getClassAttribute(element) + " " + classValue); + } + + function removeClass(element, classValue) { + changeElementClass(element, getClassAttribute(element).replace(classValue, "")); + } + + function initTabs() { + var container = document.getElementById("tabs"); + + tabs.tabs = findTabs(container); + tabs.titles = findTitles(tabs.tabs); + tabs.headers = findHeaders(container); + tabs.select = select; + tabs.deselectAll = deselectAll; + tabs.select(0); + + return true; + } + + function getCheckBox() { + return document.getElementById("line-wrapping-toggle"); + } + + function getLabelForCheckBox() { + return document.getElementById("label-for-line-wrapping-toggle"); + } + + function findCodeBlocks() { + var spans = document.getElementById("tabs").getElementsByTagName("span"); + var codeBlocks = []; + for (var i = 0; i < spans.length; ++i) { + if (spans[i].className.indexOf("code") >= 0) { + codeBlocks.push(spans[i]); + } + } + return codeBlocks; + } + + function forAllCodeBlocks(operation) { + var codeBlocks = findCodeBlocks(); + + for (var i = 0; i < codeBlocks.length; ++i) { + operation(codeBlocks[i], "wrapped"); + } + } + + function toggleLineWrapping() { + var checkBox = getCheckBox(); + + if (checkBox.checked) { + forAllCodeBlocks(addClass); + } else { + forAllCodeBlocks(removeClass); + } + } + + function initControls() { + if (findCodeBlocks().length > 0) { + var checkBox = getCheckBox(); + var label = getLabelForCheckBox(); + + checkBox.onclick = toggleLineWrapping; + checkBox.checked = false; + + removeClass(label, "hidden"); + } + } + + function switchTab() { + var id = this.id.substr(1); + + for (var i = 0; i < tabs.tabs.length; i++) { + if (tabs.tabs[i].id === id) { + tabs.select(i); + break; + } + } + + return false; + } + + function select(i) { + this.deselectAll(); + + changeElementClass(this.tabs[i], "tab selected"); + changeElementClass(this.headers[i], "selected"); + + while (this.headers[i].firstChild) { + this.headers[i].removeChild(this.headers[i].firstChild); + } + + var h2 = document.createElement("H2"); + + h2.appendChild(document.createTextNode(this.titles[i])); + this.headers[i].appendChild(h2); + } + + function deselectAll() { + for (var i = 0; i < this.tabs.length; i++) { + changeElementClass(this.tabs[i], "tab deselected"); + changeElementClass(this.headers[i], "deselected"); + + while (this.headers[i].firstChild) { + this.headers[i].removeChild(this.headers[i].firstChild); + } + + var a = document.createElement("A"); + + a.setAttribute("id", "ltab" + i); + a.setAttribute("href", "#tab" + i); + a.onclick = switchTab; + a.appendChild(document.createTextNode(this.titles[i])); + + this.headers[i].appendChild(a); + } + } + + function findTabs(container) { + return findChildElements(container, "DIV", "tab"); + } + + function findHeaders(container) { + var owner = findChildElements(container, "UL", "tabLinks"); + return findChildElements(owner[0], "LI", null); + } + + function findTitles(tabs) { + var titles = []; + + for (var i = 0; i < tabs.length; i++) { + var tab = tabs[i]; + var header = findChildElements(tab, "H2", null)[0]; + + header.parentNode.removeChild(header); + + if (header.innerText) { + titles.push(header.innerText); + } else { + titles.push(header.textContent); + } + } + + return titles; + } + + function findChildElements(container, name, targetClass) { + var elements = []; + var children = container.childNodes; + + for (var i = 0; i < children.length; i++) { + var child = children.item(i); + + if (child.nodeType === 1 && child.nodeName === name) { + if (targetClass && child.className.indexOf(targetClass) < 0) { + continue; + } + + elements.push(child); + } + } + + return elements; + } + + // Entry point. + + window.onload = function() { + initTabs(); + initControls(); + }; +} (window, window.document)); \ No newline at end of file diff --git a/build/reports/tests/test/packages/unit.html b/build/reports/tests/test/packages/unit.html new file mode 100644 index 00000000..a8d11912 --- /dev/null +++ b/build/reports/tests/test/packages/unit.html @@ -0,0 +1,127 @@ + + + + + +Test results - Package unit + + + + + +
+

Package unit

+ +
+ + + + + +
+
+ + + + + + + +
+
+
6
+

tests

+
+
+
+
4
+

failures

+
+
+
+
0
+

ignored

+
+
+
+
0.032s
+

duration

+
+
+
+
+
+
33%
+

successful

+
+
+
+
+ + +
+

Classes

+ + + + + + + + + + + + + + + + + + + +
ClassTestsFailuresIgnoredDurationSuccess rate
+GroceryTest +6400.032s33%
+
+
+ +
+ + diff --git a/build/test-results/test/TEST-unit.GroceryTest.xml b/build/test-results/test/TEST-unit.GroceryTest.xml new file mode 100644 index 00000000..e91d757f --- /dev/null +++ b/build/test-results/test/TEST-unit.GroceryTest.xml @@ -0,0 +1,252 @@ + + + + + + java.lang.NullPointerException + at cart.ShoppingCart.lambda$calculate$0(ShoppingCart.java:23) + at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193) + at java.util.HashMap$KeySpliterator.forEachRemaining(HashMap.java:1556) + at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:482) + at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:472) + at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708) + at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) + at java.util.stream.ReferencePipeline.reduce(ReferencePipeline.java:474) + at cart.ShoppingCart.calculate(ShoppingCart.java:23) + at unit.GroceryTest.applyAllDiscountsWhenConditionAndDateValid(GroceryTest.java:56) + at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) + at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) + at java.lang.reflect.Method.invoke(Method.java:498) + at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) + at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) + at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) + at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78) + at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.runTestClass(JUnitTestClassExecutor.java:106) + at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:58) + at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:38) + at org.gradle.api.internal.tasks.testing.junit.AbstractJUnitTestClassProcessor.processTestClass(AbstractJUnitTestClassProcessor.java:66) + at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:51) + at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) + at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) + at java.lang.reflect.Method.invoke(Method.java:498) + at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35) + at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24) + at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:32) + at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:93) + at com.sun.proxy.$Proxy2.processTestClass(Unknown Source) + at org.gradle.api.internal.tasks.testing.worker.TestWorker.processTestClass(TestWorker.java:117) + at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) + at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) + at java.lang.reflect.Method.invoke(Method.java:498) + at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35) + at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24) + at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:155) + at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:137) + at org.gradle.internal.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:404) + at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63) + at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:46) + at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) + at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) + at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:55) + at java.lang.Thread.run(Thread.java:748) + + + + java.lang.NullPointerException + at cart.ShoppingCart.lambda$calculate$0(ShoppingCart.java:23) + at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193) + at java.util.HashMap$KeySpliterator.forEachRemaining(HashMap.java:1556) + at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:482) + at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:472) + at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708) + at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) + at java.util.stream.ReferencePipeline.reduce(ReferencePipeline.java:474) + at cart.ShoppingCart.calculate(ShoppingCart.java:23) + at unit.GroceryTest.applyDiscountToApplesWhenDiscountDateValid(GroceryTest.java:43) + at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) + at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) + at java.lang.reflect.Method.invoke(Method.java:498) + at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) + at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) + at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) + at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78) + at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.runTestClass(JUnitTestClassExecutor.java:106) + at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:58) + at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:38) + at org.gradle.api.internal.tasks.testing.junit.AbstractJUnitTestClassProcessor.processTestClass(AbstractJUnitTestClassProcessor.java:66) + at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:51) + at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) + at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) + at java.lang.reflect.Method.invoke(Method.java:498) + at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35) + at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24) + at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:32) + at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:93) + at com.sun.proxy.$Proxy2.processTestClass(Unknown Source) + at org.gradle.api.internal.tasks.testing.worker.TestWorker.processTestClass(TestWorker.java:117) + at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) + at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) + at java.lang.reflect.Method.invoke(Method.java:498) + at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35) + at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24) + at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:155) + at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:137) + at org.gradle.internal.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:404) + at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63) + at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:46) + at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) + at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) + at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:55) + at java.lang.Thread.run(Thread.java:748) + + + + + java.lang.NullPointerException + at cart.ShoppingCart.lambda$calculate$0(ShoppingCart.java:23) + at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193) + at java.util.HashMap$KeySpliterator.forEachRemaining(HashMap.java:1556) + at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:482) + at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:472) + at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708) + at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) + at java.util.stream.ReferencePipeline.reduce(ReferencePipeline.java:474) + at cart.ShoppingCart.calculate(ShoppingCart.java:23) + at unit.GroceryTest.applyDiscountToOneBreadWhenThreeTinsOfSoupBought(GroceryTest.java:21) + at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) + at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) + at java.lang.reflect.Method.invoke(Method.java:498) + at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) + at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) + at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) + at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78) + at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.runTestClass(JUnitTestClassExecutor.java:106) + at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:58) + at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:38) + at org.gradle.api.internal.tasks.testing.junit.AbstractJUnitTestClassProcessor.processTestClass(AbstractJUnitTestClassProcessor.java:66) + at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:51) + at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) + at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) + at java.lang.reflect.Method.invoke(Method.java:498) + at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35) + at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24) + at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:32) + at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:93) + at com.sun.proxy.$Proxy2.processTestClass(Unknown Source) + at org.gradle.api.internal.tasks.testing.worker.TestWorker.processTestClass(TestWorker.java:117) + at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) + at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) + at java.lang.reflect.Method.invoke(Method.java:498) + at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35) + at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24) + at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:155) + at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:137) + at org.gradle.internal.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:404) + at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63) + at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:46) + at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) + at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) + at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:55) + at java.lang.Thread.run(Thread.java:748) + + + + java.lang.NullPointerException + at cart.ShoppingCart.lambda$calculate$0(ShoppingCart.java:23) + at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193) + at java.util.HashMap$KeySpliterator.forEachRemaining(HashMap.java:1556) + at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:482) + at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:472) + at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708) + at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) + at java.util.stream.ReferencePipeline.reduce(ReferencePipeline.java:474) + at cart.ShoppingCart.calculate(ShoppingCart.java:23) + at unit.GroceryTest.dontApplyDiscountWhenDiscountDateInvalid(GroceryTest.java:32) + at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) + at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) + at java.lang.reflect.Method.invoke(Method.java:498) + at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) + at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) + at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) + at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78) + at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.runTestClass(JUnitTestClassExecutor.java:106) + at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:58) + at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:38) + at org.gradle.api.internal.tasks.testing.junit.AbstractJUnitTestClassProcessor.processTestClass(AbstractJUnitTestClassProcessor.java:66) + at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:51) + at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) + at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) + at java.lang.reflect.Method.invoke(Method.java:498) + at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35) + at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24) + at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:32) + at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:93) + at com.sun.proxy.$Proxy2.processTestClass(Unknown Source) + at org.gradle.api.internal.tasks.testing.worker.TestWorker.processTestClass(TestWorker.java:117) + at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) + at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) + at java.lang.reflect.Method.invoke(Method.java:498) + at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35) + at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24) + at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:155) + at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:137) + at org.gradle.internal.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:404) + at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63) + at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:46) + at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) + at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) + at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:55) + at java.lang.Thread.run(Thread.java:748) + + + + + diff --git a/build/test-results/test/binary/output.bin b/build/test-results/test/binary/output.bin new file mode 100644 index 00000000..e69de29b diff --git a/build/test-results/test/binary/output.bin.idx b/build/test-results/test/binary/output.bin.idx new file mode 100644 index 00000000..f76dd238 Binary files /dev/null and b/build/test-results/test/binary/output.bin.idx differ diff --git a/build/test-results/test/binary/results.bin b/build/test-results/test/binary/results.bin new file mode 100644 index 00000000..c1bee836 Binary files /dev/null and b/build/test-results/test/binary/results.bin differ diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 00000000..94336fca Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000..290541c7 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.3-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew new file mode 100755 index 00000000..cccdd3d5 --- /dev/null +++ b/gradlew @@ -0,0 +1,172 @@ +#!/usr/bin/env sh + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# 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 + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +# 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 +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +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" -a "$nonstop" = "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 + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 00000000..e95643d6 --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,84 @@ +@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 + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@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= + +@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 Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_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=%* + +: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/settings.gradle b/settings.gradle new file mode 100644 index 00000000..18de637a --- /dev/null +++ b/settings.gradle @@ -0,0 +1,2 @@ +rootProject.name = 'grocery' + diff --git a/src/main/java/CommandLineApplication.java b/src/main/java/CommandLineApplication.java new file mode 100644 index 00000000..5d8eb96f --- /dev/null +++ b/src/main/java/CommandLineApplication.java @@ -0,0 +1,34 @@ +import cart.ShoppingCart; +import item.Item; + +import java.time.LocalDateTime; +import java.util.Scanner; + +public class CommandLineApplication { + + public static void main(String[] args) { + ShoppingCart shoppingCart = new ShoppingCart(); + + Scanner scan = new Scanner(System.in); + + System.out.println("Enter the number of apples: "); + shoppingCart.add(Item.APPLE, scan.nextInt()); + + System.out.println("Enter the number of milk: "); + shoppingCart.add(Item.MILK, scan.nextInt()); + + System.out.println("Enter the number of bread: "); + shoppingCart.add(Item.BREAD, scan.nextInt()); + + System.out.println("Enter the number of soup: "); + shoppingCart.add(Item.SOUP, scan.nextInt()); + + System.out.println("----Your shopping cart(after discounts applied and calculated for today)----"); + shoppingCart.getItems().forEach((item, number) -> showCartInfo(item, shoppingCart)); + System.out.printf("In total %f", shoppingCart.calculate(LocalDateTime.now())); + } + + private static void showCartInfo(Item item, ShoppingCart shoppingCart) { + System.out.printf("%d\t%s\t=\t%f\n", shoppingCart.getItems().get(item), item.name(), item.getCalculator().calculatePrice(shoppingCart.getItems(), item, LocalDateTime.now())); + } +} diff --git a/src/main/java/calculator/ApplePromotion.java b/src/main/java/calculator/ApplePromotion.java new file mode 100755 index 00000000..752babcc --- /dev/null +++ b/src/main/java/calculator/ApplePromotion.java @@ -0,0 +1,30 @@ +package calculator; + +import item.Item; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.time.temporal.TemporalAdjusters; +import java.util.Map; + +public class ApplePromotion implements PriceCalculator { + + private static final PromotionValidity promotionValidity = new PromotionValidity(LocalDateTime.now().plusDays(3), LocalDateTime.now().plusMonths(1).with(TemporalAdjusters.lastDayOfMonth())); + + @Override + public BigDecimal calculatePrice(Map items, Item item, LocalDateTime calculationTime) { + if (!items.containsKey(item)) { + return BigDecimal.ZERO; + } + BigDecimal factor = getFactorBasedOnTime(calculationTime); + return item.getPrice().multiply(BigDecimal.valueOf(items.get(item))).multiply(factor); + } + + private BigDecimal getFactorBasedOnTime(LocalDateTime calculationTime) { + if (promotionValidity.checkPromotionValid(calculationTime)) { + return BigDecimal.valueOf(0.9); + } + return BigDecimal.ONE; + } + +} diff --git a/src/main/java/calculator/BreadPromotion.java b/src/main/java/calculator/BreadPromotion.java new file mode 100755 index 00000000..d1e7ca7b --- /dev/null +++ b/src/main/java/calculator/BreadPromotion.java @@ -0,0 +1,37 @@ +package calculator; + +import item.Item; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.Map; +import java.util.Optional; + +public class BreadPromotion implements PriceCalculator { + + private static final BigDecimal TWO = BigDecimal.valueOf(2); + private static final PromotionValidity promotionValidity = new PromotionValidity(LocalDateTime.now().minusDays(1), LocalDateTime.now().plusDays(7)); + + @Override + public BigDecimal calculatePrice(Map items, Item item, LocalDateTime calculationTime) { + if (!items.containsKey(item)) { + return BigDecimal.ZERO; + } + if (promotionValidity.checkPromotionValid(calculationTime)) { + Integer discountedItems = getDiscountedItems(items, item); + BigDecimal discountedPrice = item.getPrice().divide(TWO).multiply(BigDecimal.valueOf(discountedItems)); + Integer undiscountedItemCount = items.get(item) - discountedItems; + if (undiscountedItemCount > 0) { + return discountedPrice.add(item.getPrice().multiply(BigDecimal.valueOf(undiscountedItemCount))); + } else { + return discountedPrice; + } + } + return item.getPrice().multiply(BigDecimal.valueOf(items.get(item))); + } + + private Integer getDiscountedItems(Map items, Item item) { + return Math.min(items.get(item), Optional.ofNullable(items.get(Item.SOUP)).orElse(0) / 2); + } + +} diff --git a/src/main/java/calculator/PriceCalculator.java b/src/main/java/calculator/PriceCalculator.java new file mode 100644 index 00000000..8e47ee08 --- /dev/null +++ b/src/main/java/calculator/PriceCalculator.java @@ -0,0 +1,14 @@ +package calculator; + +import item.Item; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.Map; + +public interface PriceCalculator { + + default BigDecimal calculatePrice(Map items, Item item, LocalDateTime calculationTime) { + return item.getPrice().multiply(BigDecimal.valueOf(items.get(item))); + } +} diff --git a/src/main/java/calculator/PromotionValidity.java b/src/main/java/calculator/PromotionValidity.java new file mode 100644 index 00000000..beb44cc2 --- /dev/null +++ b/src/main/java/calculator/PromotionValidity.java @@ -0,0 +1,17 @@ +package calculator; + +import java.time.LocalDateTime; + +public class PromotionValidity { + private LocalDateTime startDate; + private LocalDateTime endDate; + + public PromotionValidity(LocalDateTime startDate, LocalDateTime endDate) { + this.startDate = startDate; + this.endDate = endDate; + } + + public boolean checkPromotionValid(LocalDateTime promotionDate) { + return (promotionDate.isAfter(startDate) || promotionDate.isEqual(startDate)) && (promotionDate.isBefore(endDate) || promotionDate.isEqual(endDate)); + } +} diff --git a/src/main/java/cart/ShoppingCart.java b/src/main/java/cart/ShoppingCart.java new file mode 100755 index 00000000..a377f95b --- /dev/null +++ b/src/main/java/cart/ShoppingCart.java @@ -0,0 +1,29 @@ +package cart; + +import item.Item; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.HashMap; +import java.util.Map; + +public class ShoppingCart { + + private Map cart = new HashMap<>(); + + public void add(Item item, Integer amount) { + if (cart.containsKey(item)) { + cart.put(item, cart.get(item) + amount); + } else { + cart.put(item, amount); + } + } + + public BigDecimal calculate(LocalDateTime purchaseDate) { + return cart.keySet().stream().map(k -> k.getCalculator().calculatePrice(cart, k, purchaseDate)).reduce(BigDecimal.ZERO, BigDecimal::add); + } + + public Map getItems() { + return cart; + } +} diff --git a/src/main/java/item/Item.java b/src/main/java/item/Item.java new file mode 100755 index 00000000..949d41ea --- /dev/null +++ b/src/main/java/item/Item.java @@ -0,0 +1,32 @@ +package item; + +import calculator.ApplePromotion; +import calculator.BreadPromotion; +import calculator.PriceCalculator; + +import java.math.BigDecimal; + +public enum Item { + SOUP(BigDecimal.valueOf(0.65), new PriceCalculator() {}), + BREAD(BigDecimal.valueOf(0.8), new BreadPromotion()), + MILK(BigDecimal.valueOf(1.3), new PriceCalculator() {}), + APPLE(BigDecimal.valueOf(0.1), new ApplePromotion()); + + private final BigDecimal price; + private final PriceCalculator calculator; + + Item(BigDecimal price, PriceCalculator calculator) { + this.price = price; + this.calculator = calculator; + } + + public BigDecimal getPrice() { + return price; + } + + public PriceCalculator getCalculator() { + return calculator; + } + + +} diff --git a/src/test/java/unit/GroceryTest.java b/src/test/java/unit/GroceryTest.java new file mode 100755 index 00000000..adff6262 --- /dev/null +++ b/src/test/java/unit/GroceryTest.java @@ -0,0 +1,85 @@ +package unit; + +import cart.ShoppingCart; +import item.Item; +import org.junit.Test; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +import static org.junit.Assert.assertEquals; + +public class GroceryTest { + + @Test + //3 tins of soup and 2 loaves of bread, bought today, + public void applyDiscountToOneBreadWhenThreeTinsOfSoupBought() { + ShoppingCart shoppingCart = new ShoppingCart(); + shoppingCart.add(Item.SOUP, 3); + shoppingCart.add(Item.BREAD, 2); + + BigDecimal totalPrice = shoppingCart.calculate(LocalDateTime.now()); + assertEquals(BigDecimal.valueOf(3.15), totalPrice); + } + + @Test + // 6 apples and a bottle of milk, bought today + public void dontApplyDiscountWhenDiscountDateInvalid() { + ShoppingCart shoppingCart = new ShoppingCart(); + shoppingCart.add(Item.APPLE, 6); + shoppingCart.add(Item.MILK, 1); + + BigDecimal totalPrice = shoppingCart.calculate(LocalDateTime.now()); + assertEquals(BigDecimal.valueOf(1.9), totalPrice); + } + + @Test + //6 apples and a bottle of milk, bought in 5 days time, + public void applyDiscountToApplesWhenDiscountDateValid() { + ShoppingCart shoppingCart = new ShoppingCart(); + shoppingCart.add(Item.APPLE, 6); + shoppingCart.add(Item.MILK, 1); + + BigDecimal totalPrice = shoppingCart.calculate(LocalDateTime.now().plusDays(5)); + assertEquals(BigDecimal.valueOf(1.84), totalPrice); + } + + + @Test + //3 apples, 2 tins of soup and a loaf of bread, bought in 5 days time + public void applyAllDiscountsWhenConditionAndDateValid() { + ShoppingCart shoppingCart = new ShoppingCart(); + shoppingCart.add(Item.APPLE, 3); + shoppingCart.add(Item.SOUP, 2); + shoppingCart.add(Item.BREAD, 1); + + BigDecimal totalPrice = shoppingCart.calculate(LocalDateTime.now().plusDays(5)); + assertEquals(BigDecimal.valueOf(1.97), totalPrice); + } + + @Test + public void shoppingCartShouldAddItems() { + ShoppingCart shoppingCart = new ShoppingCart(); + shoppingCart.add(Item.APPLE, 3); + shoppingCart.add(Item.SOUP, 2); + + assertEquals(Integer.valueOf(3), shoppingCart.getItems().get(Item.APPLE)); + assertEquals(Integer.valueOf(2), shoppingCart.getItems().get(Item.SOUP)); + assertEquals(2, shoppingCart.getItems().keySet().size()); + } + + @Test + public void shoppingCartShouldIncreaseTheTotalNumberOfItems() { + ShoppingCart shoppingCart = new ShoppingCart(); + shoppingCart.add(Item.APPLE, 3); + shoppingCart.add(Item.APPLE, 2); + + assertEquals(Integer.valueOf(5), shoppingCart.getItems().get(Item.APPLE)); + } + + @Test + public void calculateZeroIFShoppingCartEmpty() { + ShoppingCart shoppingCart = new ShoppingCart(); + assertEquals(BigDecimal.ZERO, shoppingCart.calculate(LocalDateTime.now())); + } +} \ No newline at end of file diff --git a/src/test/java/unit/calculator/ApplePromotionTest.java b/src/test/java/unit/calculator/ApplePromotionTest.java new file mode 100644 index 00000000..92b53524 --- /dev/null +++ b/src/test/java/unit/calculator/ApplePromotionTest.java @@ -0,0 +1,71 @@ +package unit.calculator; + +import calculator.ApplePromotion; +import item.Item; +import org.hamcrest.Matchers; +import org.junit.Test; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.time.temporal.TemporalAdjusters; +import java.util.HashMap; +import java.util.Map; + +import static org.junit.Assert.assertThat; + +public class ApplePromotionTest { + + private final Item testItem = Item.APPLE; + + @Test + public void promotionNotActiveWhenDateOutRange() { + Map items = new HashMap<>(); + items.put(testItem, 10); + BigDecimal price = new ApplePromotion().calculatePrice(items, testItem, LocalDateTime.now()); + + assertThat(BigDecimal.valueOf(1), Matchers.comparesEqualTo(price)); + } + + @Test + public void applyPromotionWhenDateIsInRange() { + Map items = new HashMap<>(); + items.put(testItem, 10); + BigDecimal price = new ApplePromotion().calculatePrice(items, testItem, LocalDateTime.now().plusDays(5)); + + assertThat(BigDecimal.valueOf(0.9), Matchers.comparesEqualTo(price)); + } + + @Test + public void calculateZeroIfItemIsMissingInItemList() { + Map items = new HashMap<>(); + items.put(Item.BREAD, 1); + BigDecimal price = new ApplePromotion().calculatePrice(items, testItem, LocalDateTime.now().plusDays(5)); + + assertThat(BigDecimal.ZERO, Matchers.comparesEqualTo(price)); + } + + @Test + public void calculateCorrectDiscountWithManyItemsInList() { + Map items = new HashMap<>(); + items.put(testItem, 5); + items.put(Item.BREAD, 10); + items.put(Item.MILK, 10); + items.put(Item.SOUP, 10); + BigDecimal price = new ApplePromotion().calculatePrice(items, testItem, LocalDateTime.now().plusDays(5)); + + assertThat(BigDecimal.valueOf(0.45), Matchers.comparesEqualTo(price)); + } + + + @Test + public void promotionEndsAfterFollowingMonthEndDate() { + Map items = new HashMap<>(); + items.put(testItem, 10); + BigDecimal priceAfter = new ApplePromotion().calculatePrice(items, testItem, LocalDateTime.now().plusMonths(2).withDayOfMonth(1).plusSeconds(5)); + BigDecimal priceEndDate = new ApplePromotion().calculatePrice(items, testItem, LocalDateTime.now().plusMonths(1).with(TemporalAdjusters.lastDayOfMonth()).minusSeconds(5)); + + assertThat(BigDecimal.ONE, Matchers.comparesEqualTo(priceAfter)); + assertThat(BigDecimal.valueOf(0.9), Matchers.comparesEqualTo(priceEndDate)); + } + +} \ No newline at end of file diff --git a/src/test/java/unit/calculator/BreadPromotionTest.java b/src/test/java/unit/calculator/BreadPromotionTest.java new file mode 100644 index 00000000..a80b1714 --- /dev/null +++ b/src/test/java/unit/calculator/BreadPromotionTest.java @@ -0,0 +1,75 @@ +package unit.calculator; + +import calculator.BreadPromotion; +import item.Item; +import org.hamcrest.Matchers; +import org.junit.Test; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.HashMap; +import java.util.Map; + +import static org.junit.Assert.assertThat; + +public class BreadPromotionTest { + + private final Item testItem = Item.BREAD; + + @Test + public void noPromotionWhenhtereIsOnlyBread() { + Map items = new HashMap<>(); + items.put(testItem, 10); + BigDecimal price = new BreadPromotion().calculatePrice(items, testItem, LocalDateTime.now()); + + assertThat(BigDecimal.valueOf(8), Matchers.comparesEqualTo(price)); + } + + @Test + public void noPromotionWhenDateOutOfRange() { + Map items = new HashMap<>(); + items.put(testItem, 10); + BigDecimal price = new BreadPromotion().calculatePrice(items, testItem, LocalDateTime.now().plusMonths(5)); + + assertThat(BigDecimal.valueOf(8), Matchers.comparesEqualTo(price)); + } + + @Test + public void calculateZeroIfItemIsMissingInItemList() { + Map items = new HashMap<>(); + items.put(Item.SOUP, 10); + BigDecimal price = new BreadPromotion().calculatePrice(items, testItem, LocalDateTime.now()); + + assertThat(BigDecimal.ZERO, Matchers.comparesEqualTo(price)); + } + + @Test + public void calculateValidDiscountWhenSoupIsMoreThanBread() { + Map items = new HashMap<>(); + items.put(Item.SOUP, 10); + items.put(testItem, 1); + BigDecimal price = new BreadPromotion().calculatePrice(items, testItem, LocalDateTime.now()); + + assertThat(BigDecimal.valueOf(0.4), Matchers.comparesEqualTo(price)); + } + + @Test + public void calculateValidDiscountWhenSoupIsLessThanBread() { + Map items = new HashMap<>(); + items.put(Item.SOUP, 2); + items.put(testItem, 10); + BigDecimal price = new BreadPromotion().calculatePrice(items, testItem, LocalDateTime.now()); + + assertThat(BigDecimal.valueOf(7.6), Matchers.comparesEqualTo(price)); + } + + @Test + public void calculateValidDiscountWhenSoupIsNotEnoughForDiscount() { + Map items = new HashMap<>(); + items.put(Item.SOUP, 1); + items.put(testItem, 10); + BigDecimal price = new BreadPromotion().calculatePrice(items, testItem, LocalDateTime.now()); + + assertThat(BigDecimal.valueOf(8), Matchers.comparesEqualTo(price)); + } +} \ No newline at end of file diff --git a/src/test/java/unit/calculator/PriceCalculatorTest.java b/src/test/java/unit/calculator/PriceCalculatorTest.java new file mode 100644 index 00000000..ae4af136 --- /dev/null +++ b/src/test/java/unit/calculator/PriceCalculatorTest.java @@ -0,0 +1,37 @@ +package unit.calculator; + +import calculator.PriceCalculator; +import item.Item; +import org.hamcrest.Matchers; +import org.junit.Test; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.HashMap; +import java.util.Map; + +import static org.junit.Assert.assertThat; + +public class PriceCalculatorTest { + private final PriceCalculator priceCalculator = new PriceCalculator(){}; + + @Test + public void calculateCorrectPrice() { + Map items = new HashMap<>(); + items.put(Item.MILK, 10); + BigDecimal price = priceCalculator.calculatePrice(items, Item.MILK, LocalDateTime.now()); + + assertThat(BigDecimal.valueOf(13), Matchers.comparesEqualTo(price)); + } + + @Test + public void calculateDateIneffective() { + Map items = new HashMap<>(); + items.put(Item.MILK, 10); + BigDecimal price1 = priceCalculator.calculatePrice(items, Item.MILK, LocalDateTime.now().plusYears(10)); + BigDecimal price2 = priceCalculator.calculatePrice(items, Item.MILK, LocalDateTime.now().minusYears(10)); + + assertThat(price1, Matchers.comparesEqualTo(price2)); + } + +} \ No newline at end of file diff --git a/src/test/java/unit/calculator/PromotionValidityTest.java b/src/test/java/unit/calculator/PromotionValidityTest.java new file mode 100644 index 00000000..931fb6c2 --- /dev/null +++ b/src/test/java/unit/calculator/PromotionValidityTest.java @@ -0,0 +1,54 @@ +package unit.calculator; + +import calculator.PromotionValidity; +import org.junit.Test; + +import java.time.LocalDateTime; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class PromotionValidityTest { + + @Test + public void checkPromotionValidNow() { + PromotionValidity promotion = new PromotionValidity(LocalDateTime.now().minusDays(1), LocalDateTime.now().plusDays(1)); + assertTrue(promotion.checkPromotionValid(LocalDateTime.now())); + } + + @Test + public void checkPromotionValidForFutureDate() { + PromotionValidity promotion = new PromotionValidity(LocalDateTime.now().plusDays(1), LocalDateTime.now().plusDays(5)); + assertTrue(promotion.checkPromotionValid(LocalDateTime.now().plusDays(2))); + } + + @Test + public void checkPromotionValidForPastDate() { + PromotionValidity promotion = new PromotionValidity(LocalDateTime.now().minusDays(5), LocalDateTime.now().minusDays(3)); + assertTrue(promotion.checkPromotionValid(LocalDateTime.now().minusDays(4))); + } + + @Test + public void checkPromotionValidForTheSameDayItEnds() { + PromotionValidity promotion = new PromotionValidity(LocalDateTime.now().minusDays(5), LocalDateTime.now().plusDays(3)); + assertTrue(promotion.checkPromotionValid(LocalDateTime.now().plusDays(3).minusSeconds(5))); + } + + @Test + public void checkPromotionValidForTheSameDayItStarts() { + PromotionValidity promotion = new PromotionValidity(LocalDateTime.now().minusDays(5), LocalDateTime.now().plusDays(3)); + assertTrue(promotion.checkPromotionValid(LocalDateTime.now().minusDays(5).plusSeconds(5))); + } + + @Test + public void checkPromotionInvalidWhenDateBeforeStartTime() { + PromotionValidity promotion = new PromotionValidity(LocalDateTime.now().minusDays(1), LocalDateTime.now().plusDays(1)); + assertFalse(promotion.checkPromotionValid(LocalDateTime.now().minusDays(4))); + } + + @Test + public void checkPromotionInvalidWhenDateAfterEndTime() { + PromotionValidity promotion = new PromotionValidity(LocalDateTime.now().minusDays(1), LocalDateTime.now().plusDays(1)); + assertFalse(promotion.checkPromotionValid(LocalDateTime.now().plusDays(4))); + } +} \ No newline at end of file