Skip to content

Commit

Permalink
- Fixed bug where DECIMAL-POINT IS COMMA was not recognized nor dealt…
Browse files Browse the repository at this point in the history
… with.

- Added tests for DECIMAL-POINT IS COMMA
- Minor refactoring

Signed-off-by: David Kaan <dak@bankdata.dk>
  • Loading branch information
David Kaan committed Feb 11, 2022
1 parent 109be56 commit 531a51c
Show file tree
Hide file tree
Showing 16 changed files with 209 additions and 11 deletions.
10 changes: 10 additions & 0 deletions approval-test-expected.txt
Original file line number Diff line number Diff line change
Expand Up @@ -223,3 +223,13 @@ Mock Sections And Paragraphs
69 PASSED
2 FAILED
=================================================
TESTSUITE:
Verify Cobol Check handles decimal is comma properly
PASS: 1. simple expect for number
PASS: 2. simple expect for number
PASS: 3. VERIFY EXACT 1 ACCESS TO PARAGRAPH 100-ASSIGN

3 TEST CASES WERE EXECUTED
3 PASSED
0 FAILED
=================================================
1 change: 1 addition & 0 deletions approvaltest
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@
./cobolcheck -p GREETING >> approval-test-actual.txt
./cobolcheck -p FILECOPY >> approval-test-actual.txt
./cobolcheck -p MOCKTEST >> approval-test-actual.txt
./cobolcheck -p DPICNUMBERS >> approval-test-actual.txt
2 changes: 1 addition & 1 deletion approvaltestWin.cmd
Original file line number Diff line number Diff line change
@@ -1 +1 @@
./cobolcheck -p NUMBERS ALPHA GREETING FILECOPY MOCKTEST > approval-test-actual.txt
./cobolcheck -p NUMBERS ALPHA GREETING FILECOPY MOCKTEST DPICNUMBERS > approval-test-actual.txt
10 changes: 10 additions & 0 deletions config.properties
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,16 @@ config.loaded = production
#---------------------------------------------------------------------------------------------------------------------
cobolcheck.prefix = UT-

#---------------------------------------------------------------------------------------------------------------------
# Determines if cobolcheck should generate code, such that decimal point is comma.
# The default is "false". The value should be set to "true" if the compiler is set to
# read decimal points as commas. If the cobol source program sets DECIMAL-POINT IS COMMA,
# this configuration will be overwritten.
# Example: 1,385,481.00 (decimalPointIsComma = false)
# Example: 1.385.481,00 (decimalPointIsComma = true)
#---------------------------------------------------------------------------------------------------------------------
cobolcheck.decimalPointIsComma = false

#---------------------------------------------------------------------------------------------------------------------
# Suffix to append to the name of each program under test to produce the name of the corresponding
# test program that contains the merged test code.
Expand Down
25 changes: 25 additions & 0 deletions src/main/cobol/DPICNUMBERS.CBL
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
IDENTIFICATION DIVISION.
PROGRAM-ID. NUMBERS2.
*****************************************************************
* Program to exercise DECIMAL-POINT IS COMMA
*****************************************************************
ENVIRONMENT DIVISION.
CONFIGURATION SECTION.
SPECIAL-NAMES.
DECIMAL-POINT IS COMMA.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 FILLER.
05 VALUE-1 PIC Z.ZZ9,99.
05 VALUE-2 PIC ZZ.ZZZ,ZZ.

PROCEDURE DIVISION.

100-ASSIGN.
MOVE 10 TO VALUE-1
.

999-END.
GOBACK.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.neopragma.cobolcheck.exceptions.CobolSourceCouldNotBeReadException;
import com.neopragma.cobolcheck.exceptions.PossibleInternalLogicErrorException;
import com.neopragma.cobolcheck.services.Config;
import com.neopragma.cobolcheck.services.Messages;
import com.neopragma.cobolcheck.services.cobolLogic.*;
import com.neopragma.cobolcheck.services.Constants;
Expand Down Expand Up @@ -183,6 +184,10 @@ private void updateDependencies(CobolLine line) throws IOException {
reader.updateState();
updateLineRepository(line);

if (reader.isFlagSet(Constants.SPECIAL_NAMES_PARAGRAPH)){
updateDecimalPointIsComma(line);
}

if (reader.isFlagSet(Constants.DATA_DIVISION)){
updateNumericFields(line);
}
Expand All @@ -193,6 +198,15 @@ private void updateDependencies(CobolLine line) throws IOException {
}
}

private void updateDecimalPointIsComma(CobolLine line) {
List<String> orderedDecimalIsCommaKeywords = Arrays.asList(Constants.DECIMAL_POINT_KEYWORD,
Constants.IS_TOKEN, Constants.COMMA_KEYWORD);

if (line.containsAllTokensInConsecutiveOrder(orderedDecimalIsCommaKeywords)){
Config.setDecimalPointIsComma(true);
}
}

/**Updates possibleMockIdentifier, possibleMockType and possibleMockArgs
* if a specific part of the program was just entered.
* @param line - The line the update is based upon
Expand Down Expand Up @@ -261,10 +275,7 @@ private void updateNumericFields(CobolLine line){
for (String token : line.getTokens()) {
if (token.equalsIgnoreCase(Constants.PIC_VALUE)
|| (token.equalsIgnoreCase(Constants.PICTURE_VALUE))) {
Pattern pattern = Pattern.compile(Constants.NUMERIC_PICTURE_CLAUSE_PATTERN);
Matcher matcher = pattern.matcher(line.getToken(ix + 1));
boolean matched = matcher.find();
if (matched) {
if (Interpreter.isInNumericFormat(line.getToken(ix + 1))) {
numericFields.setDataTypeOf(line.getToken(1).toUpperCase(Locale.ROOT), DataType.DISPLAY_NUMERIC);
}
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ public State() {
flags.put(Constants.IDENTIFICATION_DIVISION, new Flag());
flags.put(Constants.ENVIRONMENT_DIVISION, new Flag());
flags.put(Constants.CONFIGURATION_SECTION, new Flag());
flags.put(Constants.SPECIAL_NAMES_PARAGRAPH, new Flag());
flags.put(Constants.INPUT_OUTPUT_SECTION, new Flag());
flags.put(Constants.FILE_CONTROL, new Flag());
flags.put(Constants.DATA_DIVISION, new Flag());
Expand Down Expand Up @@ -63,6 +64,9 @@ public State() {
//CONFIGURATION_SECTION
mutuallyExclusiveFlagsFor(Constants.CONFIGURATION_SECTION,
Constants.INPUT_OUTPUT_SECTION);
dependentFlagsFor(Constants.CONFIGURATION_SECTION,
Constants.SPECIAL_NAMES_PARAGRAPH);


//INPUT_OUTPUT_SECTION
mutuallyExclusiveFlagsFor(Constants.INPUT_OUTPUT_SECTION,
Expand Down Expand Up @@ -124,12 +128,13 @@ public State() {

// SECTION
mutuallyExclusiveFlagsFor(Constants.SECTION_TOKEN,
Constants.PARAGRAPH_TOKEN, Constants.CALL_TOKEN);

// CALL
mutuallyExclusiveFlagsFor(Constants.CALL_TOKEN,
Constants.PARAGRAPH_TOKEN, Constants.SECTION_TOKEN);
Constants.PARAGRAPH_TOKEN);
dependentFlagsFor(Constants.SECTION_TOKEN,
Constants.CALL_TOKEN);

// PARAGRAPH
dependentFlagsFor(Constants.PARAGRAPH_TOKEN,
Constants.CALL_TOKEN);
}

public Map<String, Flag> getFlags() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@
import com.neopragma.cobolcheck.services.Config;
import com.neopragma.cobolcheck.services.Constants;
import com.neopragma.cobolcheck.services.Messages;
import com.neopragma.cobolcheck.services.StringHelper;
import com.neopragma.cobolcheck.services.cobolLogic.NumericFields;
import com.neopragma.cobolcheck.services.log.Log;

import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

public class TestSuiteParserController {

Expand All @@ -31,6 +33,8 @@ public class TestSuiteParserController {
private static final String procedureDivisionResultCopybookFilename = "CCHECKRESULTPD.CPY";
private static final String procedureDivisionParagraphCopybookFilename = "CCHECKPARAGRAPHSPD.CPY";

private static final String[] copyBookTokensWithPeriodAsDecimalPoint = new String[]{"Z,ZZ9"};

private final String workingStorageHeader = (" WORKING-STORAGE SECTION.");

// Optionally replace identifier prefixes in cobol-check copybook lines and generated source lines,
Expand All @@ -47,7 +51,7 @@ public TestSuiteParserController(String testFileNames) {
beforeAfterRepo = new BeforeAfterRepo();
testSuiteParser = new TestSuiteParser(new KeywordExtractor(), mockRepository, beforeAfterRepo);
mockGenerator = new MockGenerator();
testCodePrefix = Config.getString(Constants.COBOLCHECK_PREFIX_CONFIG_KEY, Constants.DEFAULT_COBOLCHECK_PREFIX);
testCodePrefix = Config.getTestCodePrefix();
}

//Used for testing only
Expand Down Expand Up @@ -258,13 +262,23 @@ public void logUnusedMocks(){
*/
public List<String> getBoilerplateCodeFromCopybooks(String copybookFilename) throws IOException {
List<String> lines = new ArrayList<>();
boolean isComma = Config.isDecimalPointComma();
String path = Constants.COBOLCHECK_COPYBOOK_DIRECTORY + copybookFilename;
InputStream is = this.getClass().getResourceAsStream(path);
BufferedReader secondarySourceBufferedReader = new BufferedReader(new InputStreamReader(is));
String secondarySourceLine = Constants.EMPTY_STRING;
while ((secondarySourceLine = secondarySourceBufferedReader.readLine()) != null) {
secondarySourceLine = secondarySourceLine
.replaceAll(Constants.TEST_CODE_PREFIX_PLACEHOLDER, testCodePrefix);
if (Config.isDecimalPointComma()){
for (String token : copyBookTokensWithPeriodAsDecimalPoint){
if (secondarySourceLine.toUpperCase(Locale.ROOT).contains(token.toUpperCase(Locale.ROOT))){
String replacement = StringHelper.swapChars(token, ',', '.');
secondarySourceLine = secondarySourceLine.replaceAll(token, replacement);
}

}
}
lines.add(secondarySourceLine);
}
secondarySourceBufferedReader.close();
Expand All @@ -278,4 +292,8 @@ public void closeTestSuiteReader(){
throw new TestSuiteCouldNotBeReadException(e);
}
}

public void prepareNextParse() {
Config.setDecimalPointIsCommaFromFile();
}
}
17 changes: 17 additions & 0 deletions src/main/java/com/neopragma/cobolcheck/services/Config.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
*/
public class Config {

public static final String DECIMAL_POINT_IS_COMMA_CONFIG_KEY = "cobolcheck.decimalPointIsComma";
public static final String LOCALE_LANGUAGE_CONFIG_KEY = "locale.language";
public static final String LOCALE_COUNTRY_CONFIG_KEY = "locale.country";
public static final String LOCALE_VARIANT_CONFIG_KEY = "locale.variant";
Expand Down Expand Up @@ -73,6 +74,7 @@ public static void load(String configResourceName) {
"configResourceName", "Config.load(configResourceName)"),
npe);
}
setDecimalPointIsCommaFromFile();
setDefaultLocaleOverride();
Log.info(Messages.get("INF002", configResourceName));

Expand Down Expand Up @@ -109,6 +111,21 @@ public static String getTestCodePrefix() {
return testCodePrefix;
}

static boolean decimalPointIsComma = false;
public static void setDecimalPointIsCommaFromFile() {
String value = adjustPathString(settings.getProperty(DECIMAL_POINT_IS_COMMA_CONFIG_KEY,
Constants.CURRENT_DIRECTORY));
decimalPointIsComma = Boolean.parseBoolean(value.trim());
}

public static boolean isDecimalPointComma() {
return decimalPointIsComma;
}

public static void setDecimalPointIsComma(boolean value) {
decimalPointIsComma = value;
}

public static String getTestSuiteDirectoryPathString() {
return adjustPathString(settings.getProperty(TEST_SUITE_DIRECTORY_CONFIG_KEY,
Constants.CURRENT_DIRECTORY));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ private Constants() {
public static final String IDENTIFICATION_DIVISION = "IDENTIFICATION DIVISION";
public static final String ENVIRONMENT_DIVISION = "ENVIRONMENT DIVISION";
public static final String CONFIGURATION_SECTION = "CONFIGURATION SECTION";
public static final String SPECIAL_NAMES_PARAGRAPH = "SPECIAL-NAMES";
public static final String INPUT_OUTPUT_SECTION = "INPUT-OUTPUT SECTION";
public static final String FILE_CONTROL = "FILE-CONTROL";
public static final String DATA_DIVISION = "DATA DIVISION";
Expand All @@ -118,6 +119,8 @@ private Constants() {
public static final String SELECT_TOKEN = "SELECT";
public static final String FILE_STATUS_TOKEN = "FILE STATUS";
public static final String IS_TOKEN = "IS";
public static final String DECIMAL_POINT_KEYWORD = "DECIMAL-POINT";
public static final String COMMA_KEYWORD = "COMMA";
public static final String FD_TOKEN = "FD";
public static final String LEVEL_01_TOKEN = "01";
public static final String COPY_TOKEN = "COPY";
Expand Down
18 changes: 18 additions & 0 deletions src/main/java/com/neopragma/cobolcheck/services/StringHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,24 @@ public static boolean occursFirst (String text, char expectedFirst, char expecte
return false;
}

/**
* Swaps two characters in a given string.
* 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
*/
public static String swapChars(String text, char c1, char c2){
char[] textArray = text.toCharArray();
for (int i = 0; i < text.length(); i++){
if (textArray[i] == c1)
textArray[i] = c2;
else if(textArray[i] == c2)
textArray[i] = c1;
}
return new String(textArray);
}


public static String commentOutLine(String line){
if (line.startsWith(" ")){
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.neopragma.cobolcheck.services.StringHelper;
import com.neopragma.cobolcheck.services.cobolLogic.TokenExtractor;

import java.util.Collection;
import java.util.List;
import java.util.Locale;

Expand Down Expand Up @@ -42,6 +43,42 @@ public boolean containsToken(String tokenValue) {
return tokens.size() > 0 && tokens.contains(tokenValue.toUpperCase(Locale.ROOT));
}

/**
* Checks if this line contains all the specified strings - not case-sensitive. Each string
* has to be a single token.
*
* @param tokenValues - The string tokens, to look for.
*
* @return (boolean) true if this line contains all the given token values
*/
public boolean containsAllTokens(Collection<String> tokenValues) {
for (String token : tokenValues){
if (!containsToken(token))
return false;
}
return true;
}

/**
* Checks if this line contains all the specified strings - not case-sensitive. Each string
* has to be a single token.
*
* @param tokenValues - The string tokens, to look for.
*
* @return (boolean) true if this line contains all the given token values
*/
public boolean containsAllTokensInConsecutiveOrder(Collection<String> tokenValues) {
int tokenIndex = 0;
int lastTokenIndex = 0;
for (String token : tokenValues){
tokenIndex = getTokenIndexOf(token);
if (tokenIndex != 0 && tokenIndex != lastTokenIndex + 1)
return false;
lastTokenIndex = tokenIndex;
}
return true;
}

/**
* Looks through the list of tokens for the specified string and finds the index. - not case-sensitive. The string
* has to be a single token.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ public static String setFlagsForCurrentLine(CobolLine line, CobolLine nextLine,
state.setFlagFor(Constants.CONFIGURATION_SECTION);
partOfProgram = Constants.CONFIGURATION_SECTION;
}
if (line.containsToken(Constants.SPECIAL_NAMES_PARAGRAPH)) {
state.setFlagFor(Constants.SPECIAL_NAMES_PARAGRAPH);
partOfProgram = Constants.SPECIAL_NAMES_PARAGRAPH;
}
if (line.containsToken(Constants.INPUT_OUTPUT_SECTION)) {
state.setFlagFor(Constants.INPUT_OUTPUT_SECTION);
partOfProgram = Constants.INPUT_OUTPUT_SECTION;
Expand Down Expand Up @@ -391,6 +395,12 @@ public static Area getBeginningArea(CobolLine line, boolean ignoreSequenceArea){
return Area.NONE;
}

public static boolean isInNumericFormat(String token){
List<Character> numberCharacters = Arrays.asList('9', 'Z', 'V', 'S', '*', '$');
char firstLetter = token.toCharArray()[0];
return numberCharacters.contains(Character.toUpperCase(firstLetter));
}

/**
* Checks if this line is ending the current component (SECTION, CALL, etc.)
* This should be called from inside the component, as it only checks, if
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ private void mergeTestSuite() {
processingAfterEchoingSourceLineToOutput();
}
testSuiteParserController.logUnusedMocks();
testSuiteParserController.prepareNextParse();
} catch (IOException ioEx) {
throw new CobolSourceCouldNotBeReadException(ioEx);
}
Expand Down
13 changes: 13 additions & 0 deletions src/test/cobol/DPICNUMBERS/NumbersExpect
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
TestSuite "Verify Cobol Check handles decimal is comma properly"

TestCase "simple expect for number"
Move 25,74 to VALUE-1
Expect VALUE-1 = 25,74

TestCase "simple expect for number"
MOCK PARAGRAPH 100-ASSIGN
MOVE 105 TO VALUE-1
END-MOCK
PERFORM 100-ASSIGN
EXPECT VALUE-1 = 00105
VERIFY PARAGRAPH 100-ASSIGN HAPPENED ONCE
Loading

0 comments on commit 531a51c

Please sign in to comment.