diff --git a/src/core/operations/Fork.mjs b/src/core/operations/Fork.mjs index 6e961990..3d4c596a 100644 --- a/src/core/operations/Fork.mjs +++ b/src/core/operations/Fork.mjs @@ -65,12 +65,21 @@ class Fork extends Operation { if (input) inputs = input.split(splitDelim); + // Set to 1 as if we are here, then there is one, the current one. + let numOp = 1; // Create subOpList for each tranche to operate on - // (all remaining operations unless we encounter a Merge) + // all remaining operations unless we encounter a Merge for (i = state.progress + 1; i < opList.length; i++) { if (opList[i].name === "Merge" && !opList[i].disabled) { - break; + numOp--; + if (numOp === 0 || opList[i].ingValues[0]) + break; + else + // Not this Fork's Merge. + subOpList.push(opList[i]); } else { + if (opList[i].name === "Fork" || opList[i].name === "Subsection") + numOp++; subOpList.push(opList[i]); } } diff --git a/src/core/operations/Merge.mjs b/src/core/operations/Merge.mjs index 07123aee..573e62e0 100644 --- a/src/core/operations/Merge.mjs +++ b/src/core/operations/Merge.mjs @@ -20,10 +20,16 @@ class Merge extends Operation { this.name = "Merge"; this.flowControl = true; this.module = "Default"; - this.description = "Consolidate all branches back into a single trunk. The opposite of Fork."; + this.description = "Consolidate all branches back into a single trunk. The opposite of Fork. Unticking the Merge All checkbox will only consolidate all branches up to the nearest Fork/Subsection."; this.inputType = "string"; this.outputType = "string"; - this.args = []; + this.args = [ + { + name: "Merge All", + type: "boolean", + value: true, + } + ]; } /** diff --git a/src/core/operations/Subsection.mjs b/src/core/operations/Subsection.mjs index 86980e40..1093917b 100644 --- a/src/core/operations/Subsection.mjs +++ b/src/core/operations/Subsection.mjs @@ -67,12 +67,21 @@ class Subsection extends Operation { subOpList = []; if (input && section !== "") { + // Set to 1 as if we are here, then there is one, the current one. + let numOp = 1; // Create subOpList for each tranche to operate on // all remaining operations unless we encounter a Merge for (let i = state.progress + 1; i < opList.length; i++) { if (opList[i].name === "Merge" && !opList[i].disabled) { - break; + numOp--; + if (numOp === 0 || opList[i].ingValues[0]) + break; + else + // Not this subsection's Merge. + subOpList.push(opList[i]); } else { + if (opList[i].name === "Fork" || opList[i].name === "Subsection") + numOp++; subOpList.push(opList[i]); } } diff --git a/tests/operations/index.mjs b/tests/operations/index.mjs index b6beb081..1e9dbbb1 100644 --- a/tests/operations/index.mjs +++ b/tests/operations/index.mjs @@ -114,6 +114,7 @@ import "./tests/HASSH.mjs"; import "./tests/GetAllCasings.mjs"; import "./tests/SIGABA.mjs"; import "./tests/ELFInfo.mjs"; +import "./tests/Subsection.mjs"; // Cannot test operations that use the File type yet diff --git a/tests/operations/tests/Fork.mjs b/tests/operations/tests/Fork.mjs index d7ee918c..05fde17e 100644 --- a/tests/operations/tests/Fork.mjs +++ b/tests/operations/tests/Fork.mjs @@ -31,7 +31,7 @@ TestRegister.addTests([ }, { op: "Merge", - args: [], + args: [true], }, ], }, @@ -50,7 +50,7 @@ TestRegister.addTests([ }, { op: "Merge", - args: [], + args: [true], }, ], }, @@ -66,5 +66,16 @@ TestRegister.addTests([ {"op": "Label", "args": ["skipReturn"]}, {"op": "To Base64", "args": ["A-Za-z0-9+/="]} ] - } + }, + { + name: "Fork, Partial Merge", + input: "Hello World", + expectedOutput: "48656c6c6f 576f726c64", + recipeConfig: [ + { "op": "Fork", "args": [" ", " ", false] }, + { "op": "Fork", "args": ["l", "l", false] }, + { "op": "Merge", "args": [false] }, + { "op": "To Hex", "args": ["None", 0] }, + ] + }, ]); diff --git a/tests/operations/tests/Subsection.mjs b/tests/operations/tests/Subsection.mjs new file mode 100644 index 00000000..6a181985 --- /dev/null +++ b/tests/operations/tests/Subsection.mjs @@ -0,0 +1,102 @@ +/** + * Subsection Tests. + * + * @author n1073645 [n1073645@gmail.com] + * @copyright Crown Copyright 2022 + * @license Apache-2.0 + */ +import TestRegister from "../../lib/TestRegister.mjs"; + +TestRegister.addTests([ + { + name: "Subsection: nothing", + input: "", + expectedOutput: "", + recipeConfig: [ + { + "op": "Subsection", + "args": ["", true, true, false], + }, + ], + }, + { + name: "Subsection, Full Merge: nothing", + input: "", + expectedOutput: "", + recipeConfig: [ + { + "op": "Subsection", + "args": ["", true, true, false], + }, + { + "op": "Merge", + "args": [true], + }, + ], + }, + { + name: "Subsection, Partial Merge: nothing", + input: "", + expectedOutput: "", + recipeConfig: [ + { + "op": "Subsection", + "args": ["", true, true, false], + }, + { + "op": "Merge", + "args": [false], + }, + ], + }, + { + name: "Subsection, Full Merge: Base64 with Hex", + input: "SGVsbG38675629ybGQ=", + expectedOutput: "Hello World", + recipeConfig: [ + { + "op": "Subsection", + "args": ["386756", true, true, false], + }, + { + "op": "From Hex", + "args": ["Auto"], + }, + { + "op": "Merge", + "args": [true], + }, + { + "op": "From Base64", + "args": ["A-Za-z0-9+/=", true, false], + }, + ], + }, + { + name: "Subsection, Partial Merge: Base64 with Hex surrounded by binary data.", + input: "000000000SGVsbG38675629ybGQ=0000000000", + expectedOutput: "000000000Hello World0000000000", + recipeConfig: [ + { + "op": "Subsection", + "args": ["SGVsbG38675629ybGQ=", true, true, false], + }, + { + "op": "Subsection", + "args": ["386756", true, true, false], + }, + { + "op": "From Hex", + "args": ["Auto"], + }, + { + "op": "Merge", + "args": [false], + }, + { + "op": "From Base64", + "args": ["A-Za-z0-9+/=", true, false], + }, + ], + }, +]);