diff --git a/src/main/cobol/GREETING.CBL b/src/main/cobol/GREETING.CBL index 419ad176..c18f16b8 100644 --- a/src/main/cobol/GREETING.CBL +++ b/src/main/cobol/GREETING.CBL @@ -16,7 +16,7 @@ 01 WS-FRIEND PIC X(10) VALUE SPACES. 01 WS-GREETING. 10 FILLER PIC X(07) VALUE 'Hello, '. - 10 WS-USER-NAME PIC X(06) VALUE SPACES. + 10 WS-USER-NAME PIC X(05) VALUE SPACES. 10 FILLER PIC X VALUE '!'. 01 WS-FAREWELL. 10 FILLER PIC X(15) VALUE 'See you later, '. diff --git a/src/main/java/org/openmainframeproject/cobolcheck/features/testSuiteParser/TestSuiteConcatenator.java b/src/main/java/org/openmainframeproject/cobolcheck/features/testSuiteParser/TestSuiteConcatenator.java index 580ba18e..6b1228ff 100644 --- a/src/main/java/org/openmainframeproject/cobolcheck/features/testSuiteParser/TestSuiteConcatenator.java +++ b/src/main/java/org/openmainframeproject/cobolcheck/features/testSuiteParser/TestSuiteConcatenator.java @@ -106,9 +106,12 @@ Reader concatenateTestSuites(String programTestSuiteSubdirectory) { for (String matchingFile : matchingFiles) { BufferedReader testFileReader = new BufferedReader(EncodingIO.getReaderWithCorrectEncoding(matchingFile)); String line = Constants.EMPTY_STRING; + // Line number is set to zero, to be used in Replace.replace() method + // So that replace is performed regardless of line number + int lineNumber = 0; concatenatedTestSuitesWriter.write(StringHelper.commentOutLine("From file: " + matchingFile) + Constants.NEWLINE); while((line = testFileReader.readLine()) != null) { - concatenatedTestSuitesWriter.write(Replace.replace(line) + Constants.NEWLINE); + concatenatedTestSuitesWriter.write(Replace.replace(line, lineNumber) + Constants.NEWLINE); } testFileReader.close(); } diff --git a/src/main/java/org/openmainframeproject/cobolcheck/features/testSuiteParser/TestSuiteParser.java b/src/main/java/org/openmainframeproject/cobolcheck/features/testSuiteParser/TestSuiteParser.java index cbd3d50e..b23cc078 100644 --- a/src/main/java/org/openmainframeproject/cobolcheck/features/testSuiteParser/TestSuiteParser.java +++ b/src/main/java/org/openmainframeproject/cobolcheck/features/testSuiteParser/TestSuiteParser.java @@ -882,7 +882,6 @@ private void handleEndOfMockStatement(BufferedReader testSuiteReader, String tes * * @param parsedTestSuiteLines The parsed lines, that the generated lines are * appended to - * @return - the next token from the testSuiteReader. * @throws VerifyReferencesNonexistentMockException if referenced mock, does not * exist */ diff --git a/src/main/java/org/openmainframeproject/cobolcheck/services/StringHelper.java b/src/main/java/org/openmainframeproject/cobolcheck/services/StringHelper.java index f7218093..0c7bf7b6 100644 --- a/src/main/java/org/openmainframeproject/cobolcheck/services/StringHelper.java +++ b/src/main/java/org/openmainframeproject/cobolcheck/services/StringHelper.java @@ -90,7 +90,7 @@ public static String changeFileExtension(String path, String extension){ /** * Trims only the end of the string. - * Ex.: " Hey \n" => " Hey" + * Ex.: " Hey \n" ~ " Hey" * * @param line - original string * @return - string trimmed at the end. @@ -123,7 +123,7 @@ public static boolean occursFirst (String text, char expectedFirst, char expecte /** * Swaps two characters in a given string. - * Example: swapChars("1.000.000,00", '.', ',') => "1,000,000.00" + * Example: swapChars("1.000.000,00", '.', ',') ~ "1,000,000.00" * @param c1 - One of the chars to swap * @param c2 - One of the chars to swap * @return - The given string with the given char values swapped diff --git a/src/main/java/org/openmainframeproject/cobolcheck/services/cobolLogic/replace/Replace.java b/src/main/java/org/openmainframeproject/cobolcheck/services/cobolLogic/replace/Replace.java index cc17b332..f1674429 100644 --- a/src/main/java/org/openmainframeproject/cobolcheck/services/cobolLogic/replace/Replace.java +++ b/src/main/java/org/openmainframeproject/cobolcheck/services/cobolLogic/replace/Replace.java @@ -4,8 +4,6 @@ import org.openmainframeproject.cobolcheck.services.log.LogLevel; import java.io.*; -import java.util.HashMap; -import java.util.Iterator; import java.util.LinkedList; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -60,9 +58,10 @@ public class Replace { * Looks in the source line for the replace-key and replaces is with the replace-to-value. * * @param source a line of cobol-check unit test code + * @param lineNumber the line number of the source line * @return the source line there the appropriate replacement has been made */ - public static String replace(String source) { + public static String replace(String source, int lineNumber) { if (!inspect_performed) { if (!inspect_performed_warned) { inspect_performed_warned = true; @@ -86,7 +85,7 @@ public static String replace(String source) { for (ReplaceSet replaceSet : replaceMap) { Log.trace("Replace.replace(): Key: <" + replaceSet.getFrom() + ">, Value: <" + replaceSet.getTo() + ">"); - replacesString = replaceSet.replaceInline(replacesString); + replacesString = replaceSet.replaceInline(replacesString, lineNumber); if ((Log.level() == LogLevel.TRACE) && (!replacesString.equals(source))) { Log.trace("Replace.replace(): Key: <" + replaceSet.getFrom() + ">, result: " + replacesString); } @@ -94,6 +93,10 @@ public static String replace(String source) { return replacesString; } + public static String replace(String source) { + return replace(source, 0); + } + public static void inspectProgram(File cobolProgram) { Log.trace("Replace.inspectProgram(): Inspecting the COBOL program file: " + cobolProgram); @@ -152,4 +155,34 @@ private static void reset() { inspect_performed = false; inspect_performed_warned = false; } + + public static String replaceInProgram(File program) { + // write the replaced program back to disk + + String newFileName = program+"_MOD"; + Log.warn("Replace.replaceInProgram(): Writing the COBOL program file: " + newFileName); + try { + BufferedWriter writer = new BufferedWriter(new FileWriter(newFileName)); + // read the program one line at the time + BufferedReader reader = new BufferedReader(new FileReader(program)); + //for every line in the program, replace and write to output file + String line; + int lineCount = 0; + while ((line = reader.readLine()) != null) { + writer.write(Replace.replace(line, lineCount++)); + writer.newLine(); + } + writer.close(); + reader.close(); + } catch (IOException e) { + Log.error("Replace.replaceInProgram(): Error writing the COBOL program file: " + program); + } + return newFileName; + } + + public static void showReplaceSets() { + for (ReplaceSet replaceSet : replaceMap) { + Log.info("Replace.showReplaceSets():" + replaceSet.toString()); + } + } } diff --git a/src/main/java/org/openmainframeproject/cobolcheck/services/cobolLogic/replace/ReplaceSet.java b/src/main/java/org/openmainframeproject/cobolcheck/services/cobolLogic/replace/ReplaceSet.java index 957c30ac..20c4bd5e 100644 --- a/src/main/java/org/openmainframeproject/cobolcheck/services/cobolLogic/replace/ReplaceSet.java +++ b/src/main/java/org/openmainframeproject/cobolcheck/services/cobolLogic/replace/ReplaceSet.java @@ -4,13 +4,21 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; +/** + * Class to handle the COBOL REPLACE statement keys on the test suite/test case source code. + *

+ * When fromSourceLine and untilSourceLine are set, the replace is only performed on the lines between these two lines. + * When the values are zero, the replace key set is applied to all lines. + */ public class ReplaceSet { private String from; private String to; private boolean trailing; private boolean leading; + private int fromSourceLine; + private int untilSourceLine; - public ReplaceSet(String from, String to, boolean trailing, boolean leading) { + public ReplaceSet(String from, String to, boolean trailing, boolean leading,int fromSourceLine, int untilSourceLine) { if (trailing && leading) { throw new IllegalArgumentException("Cannot have both trailing and leading set to true"); } @@ -19,6 +27,8 @@ public ReplaceSet(String from, String to, boolean trailing, boolean leading) { this.to = to; this.trailing = trailing; this.leading = leading; + this.fromSourceLine = fromSourceLine; + this.untilSourceLine = untilSourceLine; } public ReplaceSet() { @@ -26,10 +36,12 @@ public ReplaceSet() { this.to = ""; this.trailing = false; this.leading = false; + this.fromSourceLine = 0; + this.untilSourceLine = 0; } /** - * Perform 'Replace' in the string (line param). Correponding to the 'REPLACE' statement in COBOL program + * Perform 'Replace' in the string (line param). Corresponding to the 'REPLACE' statement in COBOL program * And the values parsed from the statements are used to replace the values in the line. * * @param line The line to replace in @@ -60,6 +72,28 @@ public String replaceInline(String line) { } } + /** + * Perform 'Replace' in the string (line param). Corresponding to the 'REPLACE' statement in COBOL program + * And the values parsed from the statements are used to replace the values in the line. + * @param line + * @param sourceLine + * @return + */ + public String replaceInline(String line, int sourceLine) { + // if the line is zero, the replace key set is applied + if (sourceLine == 0) return replaceInline(line); + + // when fromSourceLine and untilSourceLine are zero, the replace key set is applied to all lines. + if (fromSourceLine == 0 && untilSourceLine == 0) return replaceInline(line); + + // when the line number is between fromSourceLine and untilSourceLine, the replace is performed + if ((sourceLine >= fromSourceLine && sourceLine <= untilSourceLine) || + ((sourceLine >= fromSourceLine && untilSourceLine == 0))) return replaceInline(line); + + // Otherwise, return the line as is + return line; + } + public void setTrailing(boolean trailing) { if (trailing && this.leading) { throw new IllegalArgumentException("Cannot have both trailing and leading set to true"); @@ -97,4 +131,20 @@ public boolean isTrailing() { public boolean isLeading() { return leading; } + + public void setFromSourceLine(int sourceLineNumber) { + this.fromSourceLine = sourceLineNumber; + } + public void setUntilSourceLine(int sourceLineNumber) { + this.untilSourceLine = sourceLineNumber; + } + public int getFromSourceLine() { + return fromSourceLine; + } + public int getUntilSourceLine() { + return untilSourceLine; + } + public String toString() { + return "From: " + from + ", To: " + to + ", Trailing: " + trailing + ", Leading: " + leading + ", FromSourceLine: " + fromSourceLine + ", UntilSourceLine: " + untilSourceLine; + } } diff --git a/src/main/java/org/openmainframeproject/cobolcheck/services/cobolLogic/replace/ReplaceStatementLocator.java b/src/main/java/org/openmainframeproject/cobolcheck/services/cobolLogic/replace/ReplaceStatementLocator.java index 06d274fc..bd084683 100644 --- a/src/main/java/org/openmainframeproject/cobolcheck/services/cobolLogic/replace/ReplaceStatementLocator.java +++ b/src/main/java/org/openmainframeproject/cobolcheck/services/cobolLogic/replace/ReplaceStatementLocator.java @@ -1,5 +1,6 @@ package org.openmainframeproject.cobolcheck.services.cobolLogic.replace; +import org.jetbrains.annotations.NotNull; import org.openmainframeproject.cobolcheck.services.log.Log; import java.io.*; @@ -16,9 +17,11 @@ public class ReplaceStatementLocator { // because it can be split over multiple lines private final ReplaceTokenizer tokenizer = new ReplaceTokenizer(); protected StringBuilder currentStatement; + protected int statementLineNumber = 0; protected boolean we_are_parsing_a_replace_statement = false; protected int sourceLinesProcessed = 0; protected int commentLinesFound = 0; + private int currentSourcecodeLine = -1; public ReplaceStatementLocator() { Log.trace("ReplaceStatementLocator(): No file provided, only for testing purposes"); @@ -29,8 +32,9 @@ public ReplaceStatementLocator(File cobolFile) { //Iterate over the file and inspect each line try (BufferedReader reader = new BufferedReader(new FileReader(cobolFile))) { String line; + int lineCounter = 0; while ((line = reader.readLine()) != null) { - accumulateStatement(line); + accumulateStatement(line,++lineCounter); } } catch (FileNotFoundException e) { Log.error("ReplaceStatementLocator(): File not found: " + e.getMessage()); @@ -45,7 +49,7 @@ public LinkedList getReplaceSets() { return replaceSets; } - protected void accumulateStatement(String line) { + protected void accumulateStatement(String line, int sourceLineNumber) { // tokenize the line tokenizer.tokenize(line); @@ -66,25 +70,40 @@ protected void accumulateStatement(String line) { if (t.getType() == ReplaceTokenType.REPLACE) { // if we have a REPLACE token, start accumulating the statement currentStatement = new StringBuilder().append(t.getValue()); + this.statementLineNumber = sourceLineNumber; we_are_parsing_a_replace_statement = true; } else if (t.getType() == ReplaceTokenType.TERMINATOR && we_are_parsing_a_replace_statement) { // if we have a terminator token, process the statement - createStatements(currentStatement.toString()); + createStatements(currentStatement.toString(),this.statementLineNumber); we_are_parsing_a_replace_statement = false; } } } + /** + * Update the untilSourceLine in all ReplaceSet objects where the from is equal to the given value + * @param untilSourceLine the new value for untilSourceLine + */ + protected void updateUntilInReplaceSets(int fromSourceLine, int untilSourceLine) { + for (ReplaceSet replaceSet : replaceSets) { + if (replaceSet.getFromSourceLine() == fromSourceLine) replaceSet.setUntilSourceLine(untilSourceLine); + } + } + /** * process a complete REPLACE statement and create the ReplaceSet objects * @param statement string of tokens from replace to terminator (.) */ - protected void createStatements(String statement) { + protected void createStatements(String statement, int sourceLineNumber) { ReplaceTokenizer statementTokenizer = new ReplaceTokenizer(); statementTokenizer.tokenize(statement); - ReplaceSet replaceSet = new ReplaceSet(); + ReplaceSet replaceSet = getNewReplaceSet(sourceLineNumber); + // update the ReplaceSets that may have been created from the 'currentSourcecodeLine' location + // from and to values are corrected to avoid replacing the REPLACE statement itself + this.updateUntilInReplaceSets(this.currentSourcecodeLine + 1,sourceLineNumber - 1); + this.currentSourcecodeLine = sourceLineNumber; ReplaceToken t; boolean nextTokenIsTo = false; @@ -111,7 +130,7 @@ protected void createStatements(String statement) { replaceSet.setTo(t.getValue().replace("==", "")); nextTokenIsTo = false; replaceSets.add(replaceSet); - replaceSet = new ReplaceSet(); + replaceSet = getNewReplaceSet(sourceLineNumber); } else { replaceSet.setFrom(t.getValue().replace("==", "")); } @@ -119,4 +138,12 @@ protected void createStatements(String statement) { } } } + + private static @NotNull ReplaceSet getNewReplaceSet(int sourceLineNumber) { + ReplaceSet replaceSet = new ReplaceSet(); + // one is added to the sourceLineNumber because the REPLACE statement is on current line and the replace is done from the next line + // This way we won´t replace the REPLACE statement itself + replaceSet.setFromSourceLine(sourceLineNumber + 1); + return replaceSet; + } } diff --git a/src/main/java/org/openmainframeproject/cobolcheck/workers/Generator.java b/src/main/java/org/openmainframeproject/cobolcheck/workers/Generator.java index b55642f7..68469bbb 100644 --- a/src/main/java/org/openmainframeproject/cobolcheck/workers/Generator.java +++ b/src/main/java/org/openmainframeproject/cobolcheck/workers/Generator.java @@ -68,9 +68,12 @@ public Generator(InterpreterController interpreter, WriterController writerContr public void prepareAndRunMerge(String programName, String testFileNames) { RunInfo.setCurrentProgramName(new File(programName).getName()); RunInfo.setCurrentProgramPath(new File(programName).getAbsolutePath()); - Replace.inspectProgram(new File(PathHelper.appendMatchingFileSuffix(programName, Config.getApplicationFilenameSuffixes()))); + File originalSource = new File(PathHelper.appendMatchingFileSuffix(programName, Config.getApplicationFilenameSuffixes())); + Replace.inspectProgram(originalSource); matchingTestDirectories = PrepareMergeController.getMatchingTestDirectoriesForProgram(programName); + //replace in the program, return the program name with the corrected source code. + programName = Replace.replaceInProgram(originalSource); for (String matchingDirectory : matchingTestDirectories) { Reader sourceReader = PrepareMergeController.getSourceReader(programName); diff --git a/src/test/cobol/GREETING/GreetingByName.cut b/src/test/cobol/GREETING/GreetingByName.cut index 79816e06..f1a569f7 100644 --- a/src/test/cobol/GREETING/GreetingByName.cut +++ b/src/test/cobol/GREETING/GreetingByName.cut @@ -7,11 +7,11 @@ PERFORM 2000-SPEAK EXPECT WS-GREETING TO BE "Hello, James!" - TESTCASE "When message type is farewell it returns Goodbye, James!" + TESTCASE "When message type is farewell it returns Goodbye, James !" SET MESSAGE-IS-FAREWELL TO TRUE MOVE "James" TO WS-FRIEND PERFORM 2000-SPEAK - EXPECT WS-FAREWELL TO BE "Goodbye, James!" + EXPECT WS-FAREWELL TO BE "See you later, James !" TESTCASE "User name for greeting and farewell are consistent" SET MESSAGE-IS-GREETING TO TRUE diff --git a/src/test/cobol/GREETING/GreetingByType.cut b/src/test/cobol/GREETING/GreetingByType.cut index a75869c0..e4b44e39 100644 --- a/src/test/cobol/GREETING/GreetingByType.cut +++ b/src/test/cobol/GREETING/GreetingByType.cut @@ -2,6 +2,7 @@ "Greeting returns the appropriate message based on message type" TestCase "When message type is greeting it returns 'Hello, World!'" + move space to WS-FRIEND SET MESSAGE-IS-GREETING TO TRUE PERFORM 2000-SPEAK EXPECT WS-GREETING TO BE "Hello, World!" @@ -11,6 +12,7 @@ EXPECT WS-COUNT TO BE 1 TESTCASE "try 88 level compare" + set message-is-farewell to true EXPECT MESSAGE-IS-GREETING TO BE FALSE TESTCASE "When message type is farewell it returns See you later, alligator!" @@ -19,6 +21,6 @@ Expect WS-FAREWELL To Be "See you later, alligator!" TESTCASE "Message type greeting is not true" - SET MESSAGE-IS-GREETING TO TRUE + SET MESSAGE-IS-FAREWELL TO TRUE Expect MESSAGE-IS-GREETING NOT TO BE TRUE diff --git a/src/test/java/org/openmainframeproject/cobolcheck/services/cobolLogic/replace/ReplaceSetTest.java b/src/test/java/org/openmainframeproject/cobolcheck/services/cobolLogic/replace/ReplaceSetTest.java index 4accd7df..e021a460 100644 --- a/src/test/java/org/openmainframeproject/cobolcheck/services/cobolLogic/replace/ReplaceSetTest.java +++ b/src/test/java/org/openmainframeproject/cobolcheck/services/cobolLogic/replace/ReplaceSetTest.java @@ -10,19 +10,19 @@ public class ReplaceSetTest { public void testReplaceSet() { // Create a Replace set - ReplaceSet replaceSet = new ReplaceSet("REPLACE", "REPLACED", false, false); + ReplaceSet replaceSet = new ReplaceSet("REPLACE", "REPLACED", false, false,0,0); assertEquals("REPLACE", replaceSet.getFrom()); assertEquals("REPLACED", replaceSet.getTo()); assertFalse(replaceSet.isTrailing()); assertFalse(replaceSet.isLeading()); - replaceSet = new ReplaceSet("BRUCE", "CAITLYN", true, false); + replaceSet = new ReplaceSet("BRUCE", "CAITLYN", true, false,0,0); assertEquals("BRUCE", replaceSet.getFrom()); assertEquals("CAITLYN", replaceSet.getTo()); assertTrue(replaceSet.isTrailing()); assertFalse(replaceSet.isLeading()); - replaceSet = new ReplaceSet("JOHNNY", "JAY", false, true); + replaceSet = new ReplaceSet("JOHNNY", "JAY", false, true,0,0); assertEquals("JOHNNY", replaceSet.getFrom()); assertEquals("JAY", replaceSet.getTo()); assertFalse(replaceSet.isTrailing()); @@ -31,17 +31,17 @@ public void testReplaceSet() { // Having both trailing and leading set to true is not allowed // This should throw an exception // Not possible via constructor - assertThrows(IllegalArgumentException.class, () -> new ReplaceSet("JOHNNY", "JAY", true, true)); + assertThrows(IllegalArgumentException.class, () -> new ReplaceSet("JOHNNY", "JAY", true, true,0,0)); // not possible via setter - ReplaceSet replaceSetLeading = new ReplaceSet("REPLACE", "REPLACED", false, true); + ReplaceSet replaceSetLeading = new ReplaceSet("REPLACE", "REPLACED", false, true,0,0); assertThrows(IllegalArgumentException.class, () -> replaceSetLeading.setTrailing(true)); - ReplaceSet replaceSetTrailing = new ReplaceSet("REPLACE", "REPLACED", true, false); + ReplaceSet replaceSetTrailing = new ReplaceSet("REPLACE", "REPLACED", true, false,0,0); assertThrows(IllegalArgumentException.class, () -> replaceSetTrailing.setLeading(true)); } @Test public void testReplaceInline() { - ReplaceSet replaceSet = new ReplaceSet("JOHNNY", "JAY", false, false); + ReplaceSet replaceSet = new ReplaceSet("JOHNNY", "JAY", false, false,0,0); String from = "Johnny is behind the iconic late-night desk."; String expected = "JAY is behind the iconic late-night desk."; assertEquals(expected, replaceSet.replaceInline(from)); @@ -49,7 +49,7 @@ public void testReplaceInline() { @Test public void testReplaceInlineTrailing() { - ReplaceSet replaceSet = new ReplaceSet("night", "day", true, false); + ReplaceSet replaceSet = new ReplaceSet("night", "day", true, false,0,0); String from = "Johnny is behind the iconic late-night desk."; String expected = "Johnny is behind the iconic late-day desk."; assertEquals(expected, replaceSet.replaceInline(from)); @@ -61,13 +61,11 @@ public void testReplaceInlineTrailing() { from = "Johnny is working day and night behind the iconic desk."; expected = "Johnny is working day and night behind the iconic desk."; assertEquals(expected, replaceSet.replaceInline(from)); - - } @Test public void testReplaceInlineLeading() { - ReplaceSet replaceSet = new ReplaceSet("late", "early", false, true); + ReplaceSet replaceSet = new ReplaceSet("late", "early", false, true,0,0); String from = "Johnny is behind the iconic late-night desk."; String expected = "Johnny is behind the iconic early-night desk."; assertEquals(expected, replaceSet.replaceInline(from)); @@ -80,4 +78,26 @@ public void testReplaceInlineLeading() { expected = "Johnny is working early and late behind the iconic desk."; assertEquals(expected, replaceSet.replaceInline(from)); } + + @Test + public void testReplaceInlinewithlinenumbering() { + ReplaceSet replaceSet = new ReplaceSet("late", "early", false, true,10,100); + String from = "Johnny is behind the iconic late-night desk."; + String expected = "Johnny is behind the iconic early-night desk."; + // unchanged as line number is not in the range + assertEquals(from, replaceSet.replaceInline(from,5)); + // changed as line number is in the range + assertEquals(expected, replaceSet.replaceInline(from,15)); + } + + @Test + public void testReplaceinLineWithLinenumberingLastReplaceSetHasZeroAsUntilSourceLine() { + ReplaceSet replaceSet = new ReplaceSet("late", "early", false, true,10,0); + String from = "Johnny is behind the iconic late-night desk."; + String expected = "Johnny is behind the iconic early-night desk."; + // unchanged as line number is not in the range + assertEquals(from, replaceSet.replaceInline(from,5)); + // changed as line number is in the range + assertEquals(expected, replaceSet.replaceInline(from,15)); + } } diff --git a/src/test/java/org/openmainframeproject/cobolcheck/services/cobolLogic/replace/ReplaceStatementLocatorTest.java b/src/test/java/org/openmainframeproject/cobolcheck/services/cobolLogic/replace/ReplaceStatementLocatorTest.java index 0e79242a..c33c14de 100644 --- a/src/test/java/org/openmainframeproject/cobolcheck/services/cobolLogic/replace/ReplaceStatementLocatorTest.java +++ b/src/test/java/org/openmainframeproject/cobolcheck/services/cobolLogic/replace/ReplaceStatementLocatorTest.java @@ -42,37 +42,33 @@ public void testReplaceStatementLocator() { public void testAccumulateStatement() { ReplaceStatementLocator locator = new ReplaceStatementLocator(); - locator.accumulateStatement("123245 REPLACE ==REPLACE== BY ==REPLACED==."); + locator.accumulateStatement("123245 REPLACE ==REPLACE== BY ==REPLACED==.",0); assertEquals(1, locator.getReplaceSets().size()); assertEquals("REPLACE", locator.getReplaceSets().get(0).getFrom()); assertEquals("REPLACED", locator.getReplaceSets().get(0).getTo()); - - - } @Test public void testAccumulateStatementWithMultipleLines() { ReplaceStatementLocator locator = new ReplaceStatementLocator(); - locator.accumulateStatement("123245 REPLACE ==REPLACE== BY ==REPLACED== "); - locator.accumulateStatement("123456 ==PETER== BY ==PHIL==. "); + locator.accumulateStatement("123245 REPLACE ==REPLACE== BY ==REPLACED== ",0); + locator.accumulateStatement("123456 ==PETER== BY ==PHIL==. ",0); assertEquals(2, locator.getReplaceSets().size()); assertEquals("REPLACE", locator.getReplaceSets().get(0).getFrom()); assertEquals("REPLACED", locator.getReplaceSets().get(0).getTo()); assertEquals("PETER", locator.getReplaceSets().get(1).getFrom()); assertEquals("PHIL", locator.getReplaceSets().get(1).getTo()); - } @Test public void testAccumulateStatementWithMultipleLinesAndComments() { ReplaceStatementLocator locator = new ReplaceStatementLocator(); - locator.accumulateStatement("123456* REPLACE ==REPLACE== BY ==REPLACED== "); - locator.accumulateStatement("123456 REPLACE ==REPLACE== BY ==REPLACED== "); - locator.accumulateStatement("123456* REPLACE ==BEEF== BY ==SALAD== "); - locator.accumulateStatement("123456 ==PETER== BY ==PHIL==. "); + locator.accumulateStatement("123456* REPLACE ==REPLACE== BY ==REPLACED== ",0); + locator.accumulateStatement("123456 REPLACE ==REPLACE== BY ==REPLACED== ",0); + locator.accumulateStatement("123456* REPLACE ==BEEF== BY ==SALAD== ",0); + locator.accumulateStatement("123456 ==PETER== BY ==PHIL==. ",0); assertEquals(2, locator.getReplaceSets().size()); assertEquals("REPLACE", locator.getReplaceSets().get(0).getFrom()); assertEquals("REPLACED", locator.getReplaceSets().get(0).getTo()); @@ -81,10 +77,10 @@ public void testAccumulateStatementWithMultipleLinesAndComments() { locator = new ReplaceStatementLocator(); - locator.accumulateStatement("* REPLACE ==REPLACE== BY ==REPLACED== "); - locator.accumulateStatement(" REPLACE ==REPLACE== BY ==REPLACED== "); - locator.accumulateStatement(" * REPLACE ==BEEF== BY ==SALAD== "); - locator.accumulateStatement(" ==PETER== BY ==PHIL==. "); + locator.accumulateStatement("* REPLACE ==REPLACE== BY ==REPLACED== ",0); + locator.accumulateStatement(" REPLACE ==REPLACE== BY ==REPLACED== ",0); + locator.accumulateStatement(" * REPLACE ==BEEF== BY ==SALAD== ",0); + locator.accumulateStatement(" ==PETER== BY ==PHIL==. ",0); assertEquals(2, locator.getReplaceSets().size()); assertEquals("REPLACE", locator.getReplaceSets().get(0).getFrom()); assertEquals("REPLACED", locator.getReplaceSets().get(0).getTo()); @@ -97,14 +93,14 @@ public void testCreateStatements() { //one set of keywords ReplaceStatementLocator locator = new ReplaceStatementLocator(); - locator.createStatements("REPLACE ==REPLACE== BY ==REPLACED=="); + locator.createStatements("REPLACE ==REPLACE== BY ==REPLACED==",0); assertEquals(1, locator.getReplaceSets().size()); assertEquals("REPLACE", locator.getReplaceSets().get(0).getFrom()); assertEquals("REPLACED", locator.getReplaceSets().get(0).getTo()); //Two sets of keywords locator = new ReplaceStatementLocator(); - locator.createStatements("REPLACE ==REPLACE== BY ==REPLACED== ==PETER== BY ==PHIL=="); + locator.createStatements("REPLACE ==REPLACE== BY ==REPLACED== ==PETER== BY ==PHIL==",0); assertEquals(2, locator.getReplaceSets().size()); assertEquals("REPLACE", locator.getReplaceSets().get(0).getFrom()); assertEquals("REPLACED", locator.getReplaceSets().get(0).getTo()); @@ -113,7 +109,7 @@ public void testCreateStatements() { //Two sets of keywords with one leading and one trailing locator = new ReplaceStatementLocator(); - locator.createStatements("REPLACE TRAILING ==REPLACE== BY ==REPLACED== LEADING ==PETER== BY ==PHIL=="); + locator.createStatements("REPLACE TRAILING ==REPLACE== BY ==REPLACED== LEADING ==PETER== BY ==PHIL==",0); assertEquals(2, locator.getReplaceSets().size()); assertEquals("REPLACE", locator.getReplaceSets().get(0).getFrom()); assertEquals("REPLACED", locator.getReplaceSets().get(0).getTo()); @@ -122,4 +118,54 @@ public void testCreateStatements() { assertTrue(locator.getReplaceSets().get(0).isTrailing()); assertTrue(locator.getReplaceSets().get(1).isLeading()); } + + @Test + public void testSourcelinesAreAddedToReplaceSets() { + ReplaceStatementLocator locator = new ReplaceStatementLocator(); + locator.createStatements("REPLACE ==REPLACE== BY ==REPLACED==", 10); + assertEquals(1, locator.getReplaceSets().size()); + assertEquals(11, locator.getReplaceSets().get(0).getFromSourceLine()); + assertEquals(0, locator.getReplaceSets().get(0).getUntilSourceLine()); + + // add a second set of keywords, the previous set should have the untilSourceLine set + locator.createStatements("REPLACE ==MONDAY== BY ==TUESDAY==",100); + assertEquals(2, locator.getReplaceSets().size()); + assertEquals(11, locator.getReplaceSets().get(0).getFromSourceLine()); + assertEquals(99, locator.getReplaceSets().get(0).getUntilSourceLine()); + assertEquals(101, locator.getReplaceSets().get(1).getFromSourceLine()); + assertEquals(0, locator.getReplaceSets().get(1).getUntilSourceLine()); + + // add a third set of keywords, the previous set should have the untilSourceLine set + locator.createStatements("REPLACE ==THURSDAY== BY ==FRIDAY==",785); + assertEquals(3, locator.getReplaceSets().size()); + assertEquals(11, locator.getReplaceSets().get(0).getFromSourceLine()); + assertEquals(99, locator.getReplaceSets().get(0).getUntilSourceLine()); + assertEquals(101, locator.getReplaceSets().get(1).getFromSourceLine()); + assertEquals(784, locator.getReplaceSets().get(1).getUntilSourceLine()); + assertEquals(786, locator.getReplaceSets().get(2).getFromSourceLine()); + assertEquals(0, locator.getReplaceSets().get(2).getUntilSourceLine()); + + // add a fourth time - two sets, the previous set should have the untilSourceLine set + locator.createStatements("REPLACE TRAILING ==REPLACE== BY ==REPLACED== LEADING ==PETER== BY ==PHIL==",950); + assertEquals(5, locator.getReplaceSets().size()); + assertEquals(786, locator.getReplaceSets().get(2).getFromSourceLine()); + assertEquals(949, locator.getReplaceSets().get(2).getUntilSourceLine()); + assertEquals(951, locator.getReplaceSets().get(3).getFromSourceLine()); + assertEquals(0, locator.getReplaceSets().get(3).getUntilSourceLine()); + assertEquals(951, locator.getReplaceSets().get(4).getFromSourceLine()); + assertEquals(0, locator.getReplaceSets().get(4).getUntilSourceLine()); + + // add a fifth time - two sets, the previous sets should have the untilSourceLine set + locator.createStatements("REPLACE TRAILING ==REPLACE== BY ==NEW-WORD== LEADING ==PETER== BY ==Nicholas==",1000); + assertEquals(7, locator.getReplaceSets().size()); + assertEquals(951, locator.getReplaceSets().get(3).getFromSourceLine()); + assertEquals(999, locator.getReplaceSets().get(3).getUntilSourceLine()); + assertEquals(951, locator.getReplaceSets().get(4).getFromSourceLine()); + assertEquals(999, locator.getReplaceSets().get(4).getUntilSourceLine()); + assertEquals(1001, locator.getReplaceSets().get(5).getFromSourceLine()); + assertEquals(0, locator.getReplaceSets().get(5).getUntilSourceLine()); + assertEquals(1001, locator.getReplaceSets().get(6).getFromSourceLine()); + assertEquals(0, locator.getReplaceSets().get(6).getUntilSourceLine()); + } + } diff --git a/src/test/java/org/openmainframeproject/cobolcheck/services/cobolLogic/replace/ReplaceTest.java b/src/test/java/org/openmainframeproject/cobolcheck/services/cobolLogic/replace/ReplaceTest.java index 0305e01e..c1968ca5 100644 --- a/src/test/java/org/openmainframeproject/cobolcheck/services/cobolLogic/replace/ReplaceTest.java +++ b/src/test/java/org/openmainframeproject/cobolcheck/services/cobolLogic/replace/ReplaceTest.java @@ -1,6 +1,5 @@ package org.openmainframeproject.cobolcheck.services.cobolLogic.replace; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import java.io.File; @@ -26,40 +25,63 @@ public void test_General_setup() { Replace.inspectProgram(new File("./testfiles/REPLACE.CBL")); assertTrue(Replace.isReplaceOn()); assertEquals(5, Replace.getReplaceSetsSize()); - assertEquals("In Genesys, the lead singer is Phil",Replace.replace("In Genesys, the lead singer is Peter")); + assertEquals("In Genesys, the lead singer is Phil",Replace.replace("In Genesys, the lead singer is Peter", 62)); } @Test public void test_replace() { Replace.inspectProgram(new File("./testfiles/REPLACE.CBL")); - assertEquals("In Genesys, the lead singer is Phil",Replace.replace("In Genesys, the lead singer is Peter")); - assertEquals(" MOVE 'CAITLIN' TO WS-OMEGA",Replace.replace(" MOVE 'BRUCE' TO WS-OMEGA")); - assertEquals(" MOVE 'SOFT' TO WS-OMEGA",Replace.replace(" MOVE 'SOFT' TO WS-OMEGA")); + // line replaces in file: + // Replace.showReplaceSets(); + // 23 REPLACE TRAILING ==ACTUAL== BY ==EXPECTED==. + // 42 REPLACE TRAILING ==ALPHA== BY ==GAMMA==. + // 52 REPLACE LEADING ==:WS:== BY ==UT==. + // 61 REPLACE ==Bruce== BY ==CAITLIN== ==PETER== BY ==Phil==. + assertEquals("In Genesys, the lead singer is Peter",Replace.replace("In Genesys, the lead singer is Peter", 50)); + assertEquals("In Genesys, the lead singer is Phil",Replace.replace("In Genesys, the lead singer is Peter", 64)); + assertEquals(" MOVE 'CAITLIN' TO WS-OMEGA",Replace.replace(" MOVE 'BRUCE' TO WS-OMEGA", 65)); + assertEquals(" MOVE 'SOFT' TO WS-OMEGA",Replace.replace(" MOVE 'SOFT' TO WS-OMEGA", 310)); // When lines are comments, they should not be replaced - assertEquals(" * MOVE 'BRUCE' TO WS-OMEGA",Replace.replace(" * MOVE 'BRUCE' TO WS-OMEGA")); - assertEquals(" * MOVE 'SOFT' TO WS-OMEGA",Replace.replace(" * MOVE 'SOFT' TO WS-OMEGA")); + assertEquals(" * MOVE 'BRUCE' TO WS-OMEGA",Replace.replace(" * MOVE 'BRUCE' TO WS-OMEGA", 65)); + assertEquals(" * MOVE 'SOFT' TO WS-OMEGA",Replace.replace(" * MOVE 'SOFT' TO WS-OMEGA", 310)); } @Test public void test_replace_leading() { Replace.inspectProgram(new File("./testfiles/REPLACE.CBL")); - assertEquals(" * USING WS-NOT-USED WS-OMEGA", Replace.replace(" * USING WS-NOT-USED WS-OMEGA")); - assertEquals(" MOVE 'B' TO UT-EXPECTED",Replace.replace(" MOVE 'B' TO :WS:-EXPECTED")); - assertEquals(" MOVE 'Y' TO UT-OMEGA",Replace.replace(" MOVE 'Y' TO :WS:-OMEGA")); - assertEquals(" MOVE 'Y' TO WS-:WS:",Replace.replace(" MOVE 'Y' TO WS-:WS:")); + assertEquals(" * USING WS-NOT-USED WS-OMEGA", Replace.replace(" * USING WS-NOT-USED WS-OMEGA", 57)); + assertEquals(" MOVE 'B' TO UT-EXPECTED",Replace.replace(" MOVE 'B' TO :WS:-EXPECTED", 58)); + assertEquals(" MOVE 'Y' TO UT-OMEGA",Replace.replace(" MOVE 'Y' TO :WS:-OMEGA", 59)); + assertEquals(" MOVE 'Y' TO WS-:WS:",Replace.replace(" MOVE 'Y' TO WS-:WS:", 69)); } @Test public void test_replace_trailing() { Replace.inspectProgram(new File("./testfiles/REPLACE.CBL")); - assertEquals(" * USING WS-ALPHA WS-OMEGA", Replace.replace(" * USING WS-ALPHA WS-OMEGA")); - assertEquals(" MOVE 'B' TO UT-EXPECTED",Replace.replace(" MOVE 'B' TO UT-EXPECTED")); - assertEquals(" MOVE 'Y' TO UT-GAMMA",Replace.replace(" MOVE 'Y' TO UT-ALPHA")); - assertEquals(" MOVE 'Y' TO WS-EXPECTED",Replace.replace(" MOVE 'Y' TO WS-ACTUAL")); + assertEquals(" * USING WS-ALPHA WS-OMEGA", Replace.replace(" * USING WS-ALPHA WS-OMEGA", 43)); + assertEquals(" MOVE 'B' TO UT-EXPECTED",Replace.replace(" MOVE 'B' TO UT-EXPECTED", 32)); + assertEquals(" MOVE 'Y' TO UT-GAMMA",Replace.replace(" MOVE 'Y' TO UT-ALPHA", 46)); + assertEquals(" MOVE 'Y' TO WS-EXPECTED",Replace.replace(" MOVE 'Y' TO WS-ACTUAL", 27)); } + @Test + public void test_replace_FI01_only_when_the_line_is_correct() { + Replace.inspectProgram(new File("./testfiles/REPLACE2.CBL")); + Replace.showReplaceSets(); + assertEquals(" PERFORM INC-:XXXX:-SKRIV", Replace.replace(" PERFORM INC-:XXXX:-SKRIV", 69)); + assertEquals(" INC-FI01-SKRIV SECTION.", Replace.replace(" INC-:XXXX:-SKRIV SECTION.", 72)); + } + + @Test + public void test_for_linenumber_0_every_replace_is_performed() { + Replace.inspectProgram(new File("./testfiles/REPLACE.CBL")); + assertEquals(" MOVE 'B' TO UT-EXPECTED",Replace.replace(" MOVE 'B' TO :WS:-EXPECTED", 0)); + assertEquals(" MOVE 'Y' TO UT-OMEGA",Replace.replace(" MOVE 'Y' TO :WS:-OMEGA", 0)); + assertEquals(" MOVE 'Y' TO WS-EXPECTED",Replace.replace(" MOVE 'Y' TO WS-ACTUAL", 0)); + } + diff --git a/testfiles/REPLACE2.CBL b/testfiles/REPLACE2.CBL new file mode 100644 index 00000000..74e9ae6b --- /dev/null +++ b/testfiles/REPLACE2.CBL @@ -0,0 +1,77 @@ + ********************************************************************** + * AUTHOR: T. N. KRAMER + * DATE: 14 FEB 2025 + * PURPOSE: DEMONSTRATE REPLACE STATEMENT + ********************************************************************** + IDENTIFICATION DIVISION. + PROGRAM-ID. REPLDEMO. + ENVIRONMENT DIVISION. + DATA DIVISION. + WORKING-STORAGE SECTION. + 77 WS-OMEGA PIC X. + 77 WS-GAMMA PIC X. + 77 UT-OMEGA PIC X. + 77 UT-GAMMA PIC X. + 77 WS-SUBPROGRAM-NAME PIC X(08). + 77 UT-COMPARE-DEFAULT PIC X VALUE 'N'. + 77 UT-NORMAL-COMPARE PIC X VALUE 'N'. + 77 UT-ACTUAL PIC X. + 77 UT-EXPECTED PIC X. + 77 UT-TEST-CASE-COUNT PIC 9(4) VALUE 0. + 77 UT-TEST-CASE-COUNT PIC 9(4) VALUE 0. + + REPLACE TRAILING ==ACTUAL== BY ==EXPECTED==. + + PROCEDURE DIVISION. + + SET UT-COMPARE-DEFAULT TO TRUE + PERFORM UT-ASSERT-EQUAL + ADD 1 TO UT-TEST-CASE-COUNT + SET UT-NORMAL-COMPARE TO TRUE + MOVE WS-OMEGA TO UT-ACTUAL + MOVE 'Y' TO UT-EXPECTED + . + 3000-DYNAMIC-CALL. + MOVE 'A' TO WS-ALPHA + MOVE 'Z' TO WS-OMEGA + * CALL WS-SUBPROGRAM-NAME + * USING WS-ALPHA WS-OMEGA + MOVE "B" TO WS-ALPHA + MOVE "Y" TO WS-OMEGA + . + REPLACE TRAILING ==ALPHA== BY ==GAMMA==. + + + + 3001-DYNAMIC-CALL + MOVE 'A' TO WS-ALPHA + MOVE 'Z' TO WS-OMEGA + * CALL WS-SUBPROGRAM-NAME + * USING WS-ALPHA WS-OMEGA + MOVE "B" TO WS-ALPHA + MOVE "Y" TO WS-OMEGA + . + REPLACE LEADING ==:WS:== BY ==UT==. + 3002-DYNAMIC-CALL + MOVE 'A' TO WS-ALPHA + MOVE 'Z' TO WS-OMEGA + * CALL WS-SUBPROGRAM-NAME + * USING WS-ALPHA WS-OMEGA + MOVE "B" TO :WS:-EXPECTED + MOVE "Y" TO :WS:-OMEGA + . + REPLACE ==Bruce== BY ==CAITLIN== + ==PETER== BY ==Phil==. + 3002-DYNAMIC-CALL + MOVE 'PETER' TO WS-ALPHA + MOVE 'BRUCE' TO WS-OMEGA + + PERFORM INC-:XXXX:-SKRIV + + REPLACE ==:XXXX:== BY ==FI01==. + INC-:XXXX:-SKRIV SECTION. + ADD 1 TO UT-TEST-CASE-COUNT + * do some writing + . + 9999-END. + . \ No newline at end of file