diff --git a/src/test/resources/testnextflowvdsl3/src/test_wfs/fromstate_tostate/config.vsh.yaml b/src/test/resources/testnextflowvdsl3/src/test_wfs/fromstate_tostate/config.vsh.yaml new file mode 100644 index 000000000..712058169 --- /dev/null +++ b/src/test/resources/testnextflowvdsl3/src/test_wfs/fromstate_tostate/config.vsh.yaml @@ -0,0 +1,15 @@ +functionality: + name: fromstate_tostate + namespace: test_wfs + resources: + - type: nextflow_script + path: main.nf + entrypoint: base + # TODO: make absolute when the ns build uses the right CWD + - path: ../../../resources + dependencies: + - name: step1 + - name: step2 + - name: step3 +platforms: + - type: nextflow \ No newline at end of file diff --git a/src/test/resources/testnextflowvdsl3/src/test_wfs/fromstate_tostate/main.nf b/src/test/resources/testnextflowvdsl3/src/test_wfs/fromstate_tostate/main.nf new file mode 100644 index 000000000..795c51b0b --- /dev/null +++ b/src/test/resources/testnextflowvdsl3/src/test_wfs/fromstate_tostate/main.nf @@ -0,0 +1,89 @@ +lines3 = meta.resources_dir.resolve("resources/lines3.txt") +lines5 = meta.resources_dir.resolve("resources/lines5.txt") + +workflow base { + take: input_ch + main: + + Channel.fromList([ + ["one", [input: [lines3, lines5], other: lines3]], + ["two", [input: [lines3, lines5], other: lines5]] + ]) + | view{ "DEBUG1: $it" } + + // test fromstate and tostate with list[string] + | step1.run( + fromState: ["input"], + toState: ["output"] + ) + | view{ "DEBUG2: $it" } + + // test fromstate and tostate with map[string, string] + | step2.run( + fromState: ["input1": "output", "input2": "other"], + toState: ["step2_output1": "output1", "step2_output2": "output2"] + ) + | view{ "DEBUG3: $it" } + + // test fromstate and tostate with closure + | step3.run( + fromState: { id, state -> + [ "input": [state.step2_output1, state.step2_output2] ] + }, + toState: { id, output, state -> + state + [ "step3_output": output.output ] + } + ) + /* TESTING */ + | toSortedList{ a, b -> a[0] <=> b[0] } + | view { tups -> + assert tups.size() == 2 : "Output channel should contain 2 event. Expected: output_list.size() == 2. Actual: output_list.size() == ${output_list.size()}" + + // check tuples + def tup0 = tups[0] + def tup1 = tups[1] + assert tup0.size() == 2 : "Outputs should contain two elements; [id, output]. Expected: tup0.size() == 2. Actual: tup0.size() == ${tup0.size()}" + assert tup1.size() == 2 : "Outputs should contain two elements; [id, output]. Expected: tup1.size() == 2. Actual: tup1.size() == ${tup1.size()}" + + // check id + assert tup0[0] == "one" : "Id should be 'one'. Expected: tup0[0] == 'one'. Actual: tup0[0] == '${tup0[0]}'." + assert tup1[0] == "two" : "Id should be 'two'. Expected: tup1[0] == 'two'. Actual: tup1[0] == '${tup1[0]}'." + + // check data + def expectedKeys = ["input", "other", "output", "step2_output1", "step2_output2", "step3_output"] + + // check tup0 data + assert tup0[1] instanceof Map : "Output should be a Map. Expected: tup0[1] instanceof Map. Actual: tup0[1] instanceof ${tup0[1].getClass()}." + assert tup0[1].keySet().containsAll(expectedKeys) : "Output should contain keys $expectedKeys. Actual: tup0[1].keySet() == ${tup0[1].keySet()}." + def unexpectedKeys = tup0[1].keySet() - expectedKeys + assert unexpectedKeys.size() == 0 : "Output should not contain keys $unexpectedKeys. Actual: tup0[1].keySet() == ${tup0[1].keySet()}." + for (key in expectedKeys) { + assert tup0[1][key] != null : "Output should contain key $key. Actual: tup0[1].keySet() == ${tup0[1].keySet()}." + if (key == "input") { + assert tup0[1][key] instanceof List : "data.input should be a List. Expected: tup0[1].input instanceof List. Actual: tup0[1].input instanceof ${tup0[1].input.getClass()}." + } else { + assert tup0[1][key] instanceof Path : "data.$key should be a Path. Expected: tup0[1].$key instanceof Path. Actual: tup0[1].$key instanceof ${tup0[1][key].getClass()}." + } + } + + // check tup1 data + assert tup1[1] instanceof Map : "Output should be a Map. Expected: tup1[1] instanceof Map. Actual: tup1[1] instanceof ${tup1[1].getClass()}." + assert tup1[1].keySet().containsAll(expectedKeys) : "Output should contain keys $expectedKeys. Actual: tup1[1].keySet() == ${tup1[1].keySet()}." + unexpectedKeys = tup1[1].keySet() - expectedKeys + assert unexpectedKeys.size() == 0 : "Output should not contain keys $unexpectedKeys. Actual: tup1[1].keySet() == ${tup1[1].keySet()}." + for (key in expectedKeys) { + assert tup1[1][key] != null : "Output should contain key $key. Actual: tup1[1].keySet() == ${tup1[1].keySet()}." + if (key == "input") { + assert tup1[1][key] instanceof List : "data.input should be a List. Expected: tup1[1].input instanceof List. Actual: tup1[1].input instanceof ${tup1[1].input.getClass()}." + } else { + assert tup1[1][key] instanceof Path : "data.$key should be a Path. Expected: tup1[1].$key instanceof Path. Actual: tup1[1].$key instanceof ${tup1[1][key].getClass()}." + } + } + + // return something to print + "DEBUG4: $tups" + } + + emit: + Channel.empty() +} diff --git a/src/test/resources/testnextflowvdsl3/workflows/pipeline1/main.nf b/src/test/resources/testnextflowvdsl3/workflows/pipeline1/main.nf index 10c560b55..55bb7d816 100644 --- a/src/test/resources/testnextflowvdsl3/workflows/pipeline1/main.nf +++ b/src/test/resources/testnextflowvdsl3/workflows/pipeline1/main.nf @@ -108,113 +108,3 @@ workflow test_map_mapdata_mapid_arguments { } } - -workflow test_fromstate_tostate_arguments { - Channel.fromList([ - [ - // id - "foo", - // data - [ - "input": file("${params.rootDir}/resources/lines*.txt"), - "lines3": file("${params.rootDir}/resources/lines3.txt") - ] - ] - ]) - | view{ "DEBUG1: $it" } - - // test fromstate and tostate with list[string] - | step1.run( - fromState: ["input"], - toState: ["output"], - auto: [simplifyOutput: false] - ) - | view{ "DEBUG2: $it" } - - // test fromstate and tostate with map[string, string] - | step2.run( - fromState: ["input1": "output", "input2": "lines3"], - toState: ["step2_output1": "output1", "step2_output2": "output2"], - auto: [simplifyOutput: false] - ) - | view{ "DEBUG3: $it" } - - // test fromstate and tostate with closure - | step3.run( - fromState: { id, state -> - [ "input": [state.step2_output1, state.step2_output2] ] - }, - toState: { id, output, state -> - state + [ "step3_output": output.output ] - }, - auto: [simplifyOutput: false] - ) - /* TESTING */ - | toList() - | view { output_list -> - assert output_list.size() == 1 : "output channel should contain 1 event" - - def output = output_list[0] - assert output.size() == 2 : "outputs should contain two elements; [id, state]" - def id = output[0] - def state = output[1] - - // check id - assert id == "foo" : "id should be foo" - - // check state - for (key in ["input", "lines3", "output", "step2_output1", "step2_output2", "step3_output"]) { - assert state.containsKey(key) : "state should contain key $key" - def value = state[key] - if (key == "input") { - assert value instanceof List : "state[input] should be a List" - } else { - assert value instanceof Path : "state[$key] should be a Path" - } - } - - // check final output file - def output_str = state["step3_output"].readLines().join("\n") - assert output_str.matches('^11 .*$') : 'output should match ^11 .*$' - - // return something to print - "DEBUG4: $output" - } -} - - -workflow test_filter_runif_arguments { - Channel.fromList([ - ["one", [input: [lines3]]], - ["two", [input: [lines3, lines5]]], - ["three", [input: [lines5]]] - ]) - | step1.run( - filter: { id, data -> id != "three" }, - runIf: { id, data -> data.input.size() == 2 } - ) - | toSortedList( { a, b -> a[0] <=> b[0] } ) - | view { tups -> - assert tups.size() == 2 : "output channel should contain 1 event" - - def tup0 = tups[0] - def tup1 = tups[1] - assert tup0.size() == 2 : "outputs should contain two elements; [id, output]" - assert tup1.size() == 2 : "outputs should contain two elements; [id, output]" - - // check id - assert tup0[0] == "one" : "id should be one" - assert tup1[0] == "two" : "id should be two" - - // check data - assert tup0[1].containsKey("input") : "data should contain key input" - assert tup0[1].input.size() == 1 : "data should contain 1 file" - assert tup0[1].input[0].name == "lines3.txt" : "data should contain lines3.txt. Found: ${tup0[1]}" - - assert tup1[1].containsKey("output") : "data should contain key output" - assert tup1[1].output instanceof Path : "data should contain 1 file" - assert tup1[1].output.name == "two.step1.output.txt" : "data should contain two.step1.output.txt. Found: ${tup1[1]}" - - "" - } -} \ No newline at end of file diff --git a/src/test/scala/io/viash/platforms/nextflow/NextflowScriptTest.scala b/src/test/scala/io/viash/platforms/nextflow/NextflowScriptTest.scala index ad9264bc5..ccedae480 100644 --- a/src/test/scala/io/viash/platforms/nextflow/NextflowScriptTest.scala +++ b/src/test/scala/io/viash/platforms/nextflow/NextflowScriptTest.scala @@ -76,6 +76,18 @@ class NextflowScriptTest extends AnyFunSuite with BeforeAndAfterAll { assert(exitCode == 0, s"\nexit code was $exitCode\nStd output:\n$stdOut\nStd error:\n$stdErr") } + test("Test fromState/toState", DockerTest, NextflowTest) { + val (exitCode, stdOut, stdErr) = NextflowTestHelper.run( + mainScript = "target/nextflow/test_wfs/fromstate_tostate/main.nf", + args = List( + "--publish_dir", "output" + ), + cwd = tempFolFile + ) + + assert(exitCode == 0, s"\nexit code was $exitCode\nStd output:\n$stdOut\nStd error:\n$stdErr") + } + test("Test filter/runIf", DockerTest, NextflowTest) { val (exitCode, stdOut, stdErr) = NextflowTestHelper.run( mainScript = "target/nextflow/test_wfs/filter_runif/main.nf", diff --git a/src/test/scala/io/viash/platforms/nextflow/Vdsl3ModuleTest.scala b/src/test/scala/io/viash/platforms/nextflow/Vdsl3ModuleTest.scala index c63ba3d05..3b9b49707 100644 --- a/src/test/scala/io/viash/platforms/nextflow/Vdsl3ModuleTest.scala +++ b/src/test/scala/io/viash/platforms/nextflow/Vdsl3ModuleTest.scala @@ -74,17 +74,6 @@ class Vdsl3ModuleTest extends AnyFunSuite with BeforeAndAfterAll { assert(exitCode == 0, s"\nexit code was $exitCode\nStd output:\n$stdOut\nStd error:\n$stdErr") } - test("Test fromState/toState arguments", DockerTest, NextflowTest) { - - val (exitCode, stdOut, stdErr) = NextflowTestHelper.run( - mainScript = "workflows/pipeline1/main.nf", - entry = Some("test_fromstate_tostate_arguments"), - args = List("--publish_dir", "output"), - cwd = tempFolFile - ) - - assert(exitCode == 0, s"\nexit code was $exitCode\nStd output:\n$stdOut\nStd error:\n$stdErr") - } test("Check whether --help is same as Viash's --help", NextflowTest) { // except that WorkflowHelper.nf will not print alternatives, and