diff --git a/src/main/kotlin/org/domaindrivenarchitecture/provs/framework/core/Prov.kt b/src/main/kotlin/org/domaindrivenarchitecture/provs/framework/core/Prov.kt index 63a5e5b..95c1588 100644 --- a/src/main/kotlin/org/domaindrivenarchitecture/provs/framework/core/Prov.kt +++ b/src/main/kotlin/org/domaindrivenarchitecture/provs/framework/core/Prov.kt @@ -72,11 +72,11 @@ open class Prov protected constructor( * A session is the top-level execution unit in provs. A session can contain tasks. * Returns success if no sub-tasks are called or if all subtasks finish with success. */ - fun session(taskLambda: Prov.() -> Unit) = task("session") { - if (level > 1) { + fun session(taskLambda: Prov.() -> ProvResult): ProvResult { + if (level > 0) { throw IllegalStateException("A session can only be created on the top-level and may not be included in another session or task.") } - taskLambda() + return evaluate(ResultMode.ALL, "session") { taskLambda() } } /** @@ -84,6 +84,7 @@ open class Prov protected constructor( * Returns success if no sub-tasks are called or if all subtasks finish with success. */ fun task(name: String? = null, taskLambda: Prov.() -> Unit): ProvResult { + printDeprecationWarningIfLevel0("task") return evaluate(ResultMode.ALL, name) { taskLambda(); ProvResult(true) } } @@ -92,6 +93,7 @@ open class Prov protected constructor( * The returned result is included in the evaluation. */ fun taskWithResult(name: String? = null, taskLambda: Prov.() -> ProvResult): ProvResult { + printDeprecationWarningIfLevel0("taskWithResult") return evaluate(ResultMode.ALL, name) { taskLambda() } } @@ -99,6 +101,7 @@ open class Prov protected constructor( * defines a task, which returns the returned result, the results of sub-tasks are not considered */ fun requireLast(name: String? = null, a: Prov.() -> ProvResult): ProvResult { + printDeprecationWarningIfLevel0("requireLast") return evaluate(ResultMode.LAST, name) { a() } } @@ -106,6 +109,7 @@ open class Prov protected constructor( * defines a task, which always returns success */ fun optional(name: String? = null, a: Prov.() -> ProvResult): ProvResult { + printDeprecationWarningIfLevel0("optional") return evaluate(ResultMode.OPTIONAL, name) { a() } } @@ -113,6 +117,7 @@ open class Prov protected constructor( * defines a task, which exits the overall execution on failure */ fun exitOnFailure(a: Prov.() -> ProvResult): ProvResult { + printDeprecationWarningIfLevel0("exitOnFailure") return evaluate(ResultMode.FAILEXIT) { a() } } @@ -120,6 +125,7 @@ open class Prov protected constructor( * Runs the provided task in the specified (running) container */ fun taskInContainer(containerName: String, taskLambda: Prov.() -> ProvResult): ProvResult { + printDeprecationWarningIfLevel0("taskInContainer") runInContainerWithName = containerName val res = evaluate(ResultMode.ALL) { taskLambda() } runInContainerWithName = null @@ -456,6 +462,11 @@ open class Prov protected constructor( } } + fun printDeprecationWarningIfLevel0(methodName: String) { + if (level == 0) { + println("WARNING: method $methodName should not be used at top-level, use method instead.") + } + } } diff --git a/src/test/kotlin/org/domaindrivenarchitecture/provs/framework/core/ProvTest.kt b/src/test/kotlin/org/domaindrivenarchitecture/provs/framework/core/ProvTest.kt index c06eadf..d04f1c2 100644 --- a/src/test/kotlin/org/domaindrivenarchitecture/provs/framework/core/ProvTest.kt +++ b/src/test/kotlin/org/domaindrivenarchitecture/provs/framework/core/ProvTest.kt @@ -301,7 +301,9 @@ internal class ProvTest { // when Prov.newInstance(name = "test instance with no progress info", progressType = ProgressType.NONE) - .testMethodForOutputTest_with_mode_requireLast() + .session { + testMethodForOutputTest_with_mode_requireLast() + } // then System.setOut(originalOut) @@ -311,13 +313,14 @@ internal class ProvTest { val expectedOutput = "============================================== SUMMARY (test instance with no progress info) =============================================\n" + - "> \u001B[92mSuccess\u001B[0m -- testMethodForOutputTest_with_mode_requireLast (requireLast) \n" + - "---> \u001B[93mFAILED\u001B[0m -- checkPrereq_evaluateToFailure (requireLast) -- Error: This is a test error.\n" + - "---> \u001B[92mSuccess\u001B[0m -- sh \n" + - "------> \u001B[92mSuccess\u001B[0m -- cmd [/bin/bash, -c, echo -Start test-]\n" + - "------> \u001B[92mSuccess\u001B[0m -- cmd [/bin/bash, -c, echo Some output]\n" + - "---> \u001B[92mSuccess\u001B[0m -- sh \n" + - "------> \u001B[92mSuccess\u001B[0m -- cmd [/bin/bash, -c, echo -End test-]\n" + + "> \u001B[92mSuccess\u001B[0m -- session \n" + + "---> \u001B[92mSuccess\u001B[0m -- testMethodForOutputTest_with_mode_requireLast (requireLast) \n" + + "------> \u001B[93mFAILED\u001B[0m -- checkPrereq_evaluateToFailure (requireLast) -- Error: This is a test error.\n" + + "------> \u001B[92mSuccess\u001B[0m -- sh \n" + + "---------> \u001B[92mSuccess\u001B[0m -- cmd [/bin/bash, -c, echo -Start test-]\n" + + "---------> \u001B[92mSuccess\u001B[0m -- cmd [/bin/bash, -c, echo Some output]\n" + + "------> \u001B[92mSuccess\u001B[0m -- sh \n" + + "---------> \u001B[92mSuccess\u001B[0m -- cmd [/bin/bash, -c, echo -End test-]\n" + "----------------------------------------------------------------------------------------------------\n" + "Overall > \u001B[92mSuccess\u001B[0m\n" + "============================================ SUMMARY END ===========================================\n" + @@ -342,8 +345,9 @@ internal class ProvTest { System.setErr(PrintStream(errContent)) // when - Prov.newInstance(name = "test instance with no progress info", progressType = ProgressType.NONE) - .testMethodForOutputTest_nested_with_failure() + Prov.newInstance(name = "test instance with no progress info", progressType = ProgressType.NONE).session { + testMethodForOutputTest_nested_with_failure() + } // then System.setOut(originalOut) @@ -353,11 +357,12 @@ internal class ProvTest { val expectedOutput = "============================================== SUMMARY (test instance with no progress info) =============================================\n" + - "> \u001B[91mFAILED\u001B[0m -- testMethodForOutputTest_nested_with_failure \n" + - "---> \u001B[91mFAILED\u001B[0m -- sub1 \n" + - "------> \u001B[92mSuccess\u001B[0m -- testMethodForOutputTest_nested_with_failure \n" + - "------> \u001B[91mFAILED\u001B[0m -- <> -- Error: Iamanerrormessage\n" + - "---> \u001B[92mSuccess\u001B[0m -- cmd [/bin/bash, -c, echo -End test-]\n" + + "> \u001B[91mFAILED\u001B[0m -- session \n" + + "---> \u001B[91mFAILED\u001B[0m -- testMethodForOutputTest_nested_with_failure \n" + + "------> \u001B[91mFAILED\u001B[0m -- sub1 \n" + + "---------> \u001B[92mSuccess\u001B[0m -- testMethodForOutputTest_nested_with_failure \n" + + "---------> \u001B[91mFAILED\u001B[0m -- <> -- Error: Iamanerrormessage\n" + + "------> \u001B[92mSuccess\u001B[0m -- cmd [/bin/bash, -c, echo -End test-]\n" + "----------------------------------------------------------------------------------------------------\n" + "Overall > \u001B[91mFAILED\u001B[0m \n" + "============================================ SUMMARY END ===========================================\n" + @@ -399,7 +404,8 @@ internal class ProvTest { println(outContent.toString()) val expectedOutput = - "============================================== SUMMARY (test instance with no progress info) =============================================\n" + + "WARNING: method task should not be used at top-level, use method instead.\n" + + "============================================== SUMMARY (test instance with no progress info) =============================================\n" + "> \u001B[92mSuccess\u001B[0m -- taskA \n" + "---> \u001B[92mSuccess\u001B[0m -- prov_marks_failed_output_yellow_if_optional (optional) \n" + "------> \u001B[93mFAILED\u001B[0m -- taskB \n" + @@ -469,7 +475,8 @@ internal class ProvTest { println(outContent.toString()) val expectedOutput = - "============================================== SUMMARY (test instance) =============================================\n" + + "WARNING: method task should not be used at top-level, use method instead.\n" + + "============================================== SUMMARY (test instance) =============================================\n" + "> \u001B[92mSuccess\u001B[0m -- TaskB \n" + "---> \u001B[92mSuccess\u001B[0m -- taskC \n" + "----------------------------------------------------------------------------------------------------\n" + @@ -621,9 +628,10 @@ internal class ProvTest { val prov = Prov.newInstance(name = "test instance with no progress info", progressType = ProgressType.NONE) // when - prov.task { + prov.session { addInfoText("Text1") addInfoText("Text2\nwith newline") + ProvResult(true) } // then @@ -634,7 +642,7 @@ internal class ProvTest { val expectedOutput = "============================================== SUMMARY (test instance with no progress info) =============================================\n" + - "> \u001B[92mSuccess\u001B[0m -- infoText_is_printed_correctly \n" + + "> \u001B[92mSuccess\u001B[0m -- session \n" + "+++++++++++++++++++++++++++++++++++ \u001B[94mAdditional information\u001B[0m +++++++++++++++++++++++++++++++++++++++\n" + "Text1\n" + "Text2\n" + @@ -714,7 +722,8 @@ internal class ProvTest { println(outContent.toString()) val expectedOutput = - "============================================== SUMMARY (test instance with no progress info) =============================================\n" + + "WARNING: method taskWithResult should not be used at top-level, use method instead.\n" + + "============================================== SUMMARY (test instance with no progress info) =============================================\n" + "> \u001B[91mFAILED\u001B[0m -- testMethodForOutputTest_with_returned_results \n" + "---> \u001B[91mFAILED\u001B[0m -- sub1 \n" + "------> \u001B[92mSuccess\u001B[0m -- sub2a \n" + @@ -755,6 +764,57 @@ internal class ProvTest { } } // then - assertEquals("A session can only be created on the top-level and may not be included in another session or task.", exception.message) + assertEquals( + "A session can only be created on the top-level and may not be included in another session or task.", + exception.message + ) + } + + // method for task_warning_for_task_on_top_level_is_in_output + // must be declared outside test task_warning_for_task_on_top_level_is_in_output in order to avoid strange naming in result output + fun Prov.tst_task() = task { + task_returningTrue() + task_returningFalse() + } + + @Test + fun task_warning_for_task_on_top_level_is_in_output() { + // given + setRootLoggingLevel(Level.OFF) + + val outContent = ByteArrayOutputStream() + val errContent = ByteArrayOutputStream() + val originalOut = System.out + val originalErr = System.err + + System.setOut(PrintStream(outContent)) + System.setErr(PrintStream(errContent)) + + // when + Prov.newInstance(name = "test instance with no progress info", progressType = ProgressType.NONE) + .tst_task().success + Prov.newInstance(name = "test instance with no progress info", progressType = ProgressType.NONE) + .tst_task().success // test that also second run gets warning + + // then + System.setOut(originalOut) + System.setErr(originalErr) + + println(outContent.toString()) + + val expectedOutputOneRun = + "WARNING: method task should not be used at top-level, use method instead.\n" + + "============================================== SUMMARY (test instance with no progress info) =============================================\n" + + "> \u001B[91mFAILED\u001B[0m -- tst_task \n" + + "---> \u001B[92mSuccess\u001B[0m -- task_returningTrue \n" + + "---> \u001B[91mFAILED\u001B[0m -- task_returningFalse \n" + + "----------------------------------------------------------------------------------------------------\n" + + "Overall > \u001B[91mFAILED\u001B[0m \n" + + "============================================ SUMMARY END ===========================================\n" + + "\n" + + val expectedOutputDoubleRun = expectedOutputOneRun + expectedOutputOneRun + + assertEquals(expectedOutputDoubleRun, outContent.toString().replace("\r", "")) } }