From cef8d0867cbeebf3bb9adb3498bc31500d0fc48c Mon Sep 17 00:00:00 2001 From: TR017966 Date: Thu, 13 Dec 2018 15:41:53 -0600 Subject: [PATCH 1/7] Initial import of CCL Unit Mocking. --- CONTRIBUTORS.md | 2 + cclunit-framework-source/doc/CCLUTMOCKING.md | 268 +++ cclunit-framework-source/pom.xml | 2 +- .../src/main/resources/cclut_compile_subs.inc | 2 + .../resources/cclut_execute_test_logic.inc | 1 + .../src/main/resources/cclutmock.inc | 192 +++ .../src/main/resources/cclutmock_table.inc | 728 +++++++++ ...cclut_execute_program_with_mocks_happy.prg | 84 + .../test/ccl/ut_cclut_execute_test_case.inc | 132 +- .../ccl/ut_cclut_execute_test_case_file.inc | 132 +- .../src/test/ccl/ut_cclut_mock.inc | 409 +++++ .../src/test/ccl/ut_cclut_mock_table.inc | 1449 +++++++++++++++++ cclunit-framework-tests/pom.xml | 2 +- .../spring/applicationContext-cclutTests.xml | 6 +- pom.xml | 2 +- 15 files changed, 3273 insertions(+), 138 deletions(-) create mode 100644 cclunit-framework-source/doc/CCLUTMOCKING.md create mode 100644 cclunit-framework-source/src/main/resources/cclutmock.inc create mode 100644 cclunit-framework-source/src/main/resources/cclutmock_table.inc create mode 100644 cclunit-framework-source/src/test/ccl/cclut_execute_program_with_mocks_happy.prg create mode 100644 cclunit-framework-source/src/test/ccl/ut_cclut_mock.inc create mode 100644 cclunit-framework-source/src/test/ccl/ut_cclut_mock_table.inc diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index d3b7f14..8630871 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -1,6 +1,8 @@ * Cerner Corporation * Fred Ecketson [@feckerston][fred-eckertson] * Bill Pennington [@bpennington][bill-pennington] +* Trevor Rials [@cernertrevor][trevor-rials] [fred-eckertson]: https://github.com/feckertson [bill-pennington]: https://github.com/bill.pennington +[trevor-rials]: https://github.com/cernertrevor diff --git a/cclunit-framework-source/doc/CCLUTMOCKING.md b/cclunit-framework-source/doc/CCLUTMOCKING.md new file mode 100644 index 0000000..2a24166 --- /dev/null +++ b/cclunit-framework-source/doc/CCLUTMOCKING.md @@ -0,0 +1,268 @@ + +# CCL Unit Mocking +**\*CAUTION\*** **The CCL Unit Mocking framework should only be used in non-production environments. Table mocking creates new tables against an Oracle instance for the lifetime of the test. Because the DDL is generated in a dynamic way, it is possible through inappropriate use of the framework to affect the actual table. Please only use the documented API.** + +## API + +**cclutDefineMockTable(tableName = vc, fieldNames = vc, fieldTypes = vc)** + +Defines a mock table structure that can be created for use within a program. This is the first function to be called in the process of mocking a table. It must be called before cclutAddMockIndex(), cclutAddMockConstraint(), and +cclutCreateMockTable() can be called. The table will not be mocked in cclutExecuteProgramWithMocks() unless +cclutCreateMockTable() is called. tableName, columnNames, and columnTypes are required. columnNames and columnTypes are expected to be pipe-delimited strings. The columnTypes should have the same count as columnNames and be in the same order. + +@param tableName +    The table to be mocked. +@param columnNames +    A pipe-delimited list of columns to be mocked on the table +@param columnTypes +    A pipe-delimited list of types for each column +@returns +    The name of the mock table (This can be used to select data for testing) + +Example: +call cclutDefineMockTable("person", "person_id|name_last|name_first|birth_dt_tm", "f8|vc|vc|dq8") + +**cclutAddMockConstraint(tableName = vc, columnName = vc, columnConstraint = vc)** + +Adds a constraint to a mock table. The table must already be defined through cclutDefineMockTable(), otherwise an error will be thrown. This function may not be called after cclutCreateMockTable(). tableName and columnName are required. If the columnName is not valid for the table specified, an error will be thrown. All constraints for a column should be present in the columnConstraint field. If a constraint already exists, this function will overwrite it with the new value. If columnConstraint is blank, the constraint will be removed for the column. The supported constraints can be seen here: +https://wiki.cerner.com/display/public/1101discernHP/SELECT+INTO+TABLE+Table_Name+Using+Discern+Explorer + +@param tableName +    The table to which the constraint will be added. +@param columnName +    The column to which the constraint will be applied. +@param columnConstraint +    A string of all constraints to be applied to the column. + +Example: +call cclutAddMockConstraint("person", "name_last", "not null unique") + +**cclutAddMockIndex(tableName = vc, columnNames = vc, isUnique = i4)** + +Adds an index to a mock table. The table must already be defined through cclutDefineMockTable(), otherwise an error will be thrown. This function may not be called after cclutCreateMockTable(). tableName, columnNames, and isUnique are required. columnNames may be a single column name or a pipe-delimited list of columns for a composite index (the order of the columns will be the order of the index). If isUnique is 1, then a unique index will be created. If isUnique is 0, then a non-unique index will be created. + +@param tableName +    The table to which the index will be added. +@param columnNames +    A pipe-delimited string of column names for the index. +@param isUnique +    1 to create a unique index; 0 to create a non-unique index + +Example: +call cclutAddMockIndex("person", "person_id", 1) +call cclutAddMockIndex("person", "name_last|name_first", 0) + +**cclutCreateMockTable(tableName = vc)** + +Creates the mock table. The table must already be defined through cclutDefineMockTable(), otherwise an error will be thrown. If the table has already been created, the function will return silently. tableName is required. + +@param tableName +    The table to be mocked. + +Example: +call cclutCreateMockTable("person") + +**cclutRemoveMockTable(tableName = vc)** + +Removes the mock table. If the table was already created, it will also be dropped. If the table is not currently +mocked, it will return silently. tableName is required. + +@param tableName +    The table that is mocked. + +Example: +call cclutRemoveMockTable("person") + +**cclutRemoveAllMockTables(null)** + +Removes all mock tables. Any tables that have already been created will also be dropped. + +Example: +call cclutRemoveAllMockTables(null) + +**cclutAddMockData(tableName = vc, rowData = vc)** + +Add a row of mock data to a table. tableName and rowData are required. tableName must have already been created through cclutCreateMockTable() or an error will be thrown. rowData is a pipe-delimited string for each column in the same order that was used in cclutDefineMockTable(). For character fields, the backslash (\\) will serve as an escape character. For date fields, the value in rowData will be supplied to the cnvtdatetime() function. All other values will be passed as-is. + +Supported escape values +\\| = | (to represent a pipe in character fields) +\\\\ = \ (to represent a backslash in character fields) +\null = null (no value will be inserted into the column) + +@param tableName +    The table to which the data will be added. +@param rowData +    A pipe-delimited string of data to be inserted into the table. + +Example: +call cclutDefineMockTable("person", "person_id|name_last|name_first|birth_dt_tm", "f8|vc|vc|dq8") +call cclutCreateMockTable("person") +call cclutAddMockData("person", "1.0|Washington|George|01-JAN-1970 00:00") ;Will add George Washington +call cclutAddMockData("person", "2.0|A\\|d\\\\ams|John|02-FEB-1971 11:11") ;Will add John A|d\ams +call cclutAddMockData("person", "3.0|Jefferson|\null|03-MAR-1972 22:22") ;Will add Jefferson (no first name) +call cclutAddMockData("person", "4.0|Madison||04-APR-1973 10:33") ;Will add Madison (empty string for first name) + +**cclutClearMockData(tableName = vc)** + +Clears all data from the mock table. This is functionally similar to a truncate. tableName is required. The table +must have been created through cclutCreateMockTable() or else an error will be thrown. + +@param tableName +    The table to be cleared. + +Example: +call cclutClearMockData("person") + +**cclutAddMockImplementation(originalName = vc, replaceName = vc)** + +Adds a mock implementation to be utilized by cclutExecuteProgramWithMocks. This can include record structures, subroutines, or other programs. originalName and replaceName are required. If originalName is already being mocked, the mock will be overwritten with the new replaceName. + +@param originalName +    The object to be mocked. +@param replaceName +    The mocked object. + +Example: +call cclutAddMockImplementation("uar_get_code_by", "mock_uar_get_code_by") + +**cclutRemoveMockImplementation(originalName = vc)** + +Removes a mock implementation. + +@param originalName +    The object that is mocked. + +Example: +call cclutRemoveMockImplementation("uar_get_code_by") + +**cclutRemoveAllMockImplementations(null)** + +Removes all mock implementations. + +Example: +call cclutRemoveAllMockImplementations(null) + +**cclutExecuteProgramWithMocks(programName = vc, params = vc, namespace = vc)** + +Executes a program with all mocks currently added through cclutAddMockImplementation() and cclutCreateMockTable(). programName is required. params is a string parameter to be sent directly to the program, so all commas and string delimiters must be specified. If namespace is omitted, it will default to the PUBLIC namespace. + +Example: +call cclutExecuteProgramWithMocks("ccl_my_program", "\^MINE^, 1.0, ^string parameter^", "MYNAMESPACE") + +**cclutRemoveAllMocks** + +Removes all mock implementations and mock tables that have been added through the cclutAddMockImplementation() and cclutCreateMockTable() APIs. This should be called at the completion of a test suite to clean up all mocks. + +Example: +call cclutRemoveAllMocks(null) + +## Implementation Notes +1. cclutRemoveAllMocks should be called as part of the teardown for all tests. The framework will attempt to clean up any outstanding mocks, but it is good practice to explicitly remove any mocks to ensure that no mocked tables remain in the Oracle instance. + +2. The mocked items created through cclutCreateMockTable() and cclutAddMockImplementation will not be applied to children script called from the script-under-test. Some alternatives would be to mock the child script to return the appropriate data or to mock the child script to execute the real script applying the mocked tables and implementations. + +3. The mocked items created through cclutCreateMockTable() and cclutAddMockImplementation will not be applied to statements executed through "call parser()" commands. An alternative would be to mock the parser() call to validate the correct information is supplied, then perform the appropriate mock versions of the actions the statement would normally perform. + +4. The mocking API calls cannot be used from reportwriter sections. Alternatives would be dependent on the use-case, but take, for example, a dummyt used with a record structure and a call to cclutAddMockData within the detail section in order to add data based on a record structure. Instead, a FOR loop construct could be leveraged outside the context of a reportwriter section to iterate over the record structure. + +5. Mocking record structures with a call to tdbexecute is unsupported under certain conditions, specifically if a call to free the record structure is made just prior to calling tdbexecute. If the scenario is truly necessary for a test, the best alternative is to separate the freeing of the record structure and the call to tdbexecute in different subroutines and test the subroutines independently of each other. + +## Example +Below is an example of some of the APIs available in the CCL Unit Mocking framework along with some simple notes. + +Script-under-test: + + drop program cclut_get_persons:dba go + create program cclut_get_persons:dba + + declare newSize = i4 with protect, noconstant(0) + + select into "nl:" + from person p + plan p + order by p.person_id + detail + newSize = newSize + 1 + stat = alterlist(reply->persons, newSize) + reply->persons[newSize].person_id = p.person_id + reply->persons[newSize].name_last = p.name_last + reply->persons[newSize].name_first = p.name_first + reply->persons[newSize].birth_dt_tm = p.birth_dt_tm + with nocounter + + end + go + +Test Code: + + declare mockTable = vc with protect, noconstant("") + + ; Defining a mock person table. The return value is the name of the mockTable. + ; This can be useful to perform a select on the table after the script-under-test is complete + ; to verify (among other things) that an insert or a delete worked correctly. + set mockTable = cclutDefineMockTable("person", "person_id|name_last|name_first|birth_dt_tm", + "f8|vc|vc|dq8") + + ; Add a constraint that the person_id cannot be null + call cclutAddMockConstraint("person", "person_id", "not null") + + ; Add a non-unique index to name_last + call cclutAddMockIndex("person", "name_last", 0) + + ; Creates the mock table. After this, it is available for DML statements. + call cclutCreateMockTable("person") + + ; Create data for the table. + call cclutAddMockData("person", "1.0|Washington|George|01-JAN-1970 00:00") ;Will add George Washington + call cclutAddMockData("person", "2.0|Adams|John|02-FEB-1971 11:11") ;Will add John Adams + call cclutAddMockData("person", "3.0|Jefferson|\null|03-MAR-1972 22:22") ;Will add Jefferson (no first name) + call cclutAddMockData("person", "4.0|Madison||04-APR-1973 10:33") ;Will add Madison (empty string for first name) + + record mock_reply ( + 1 persons[*] + 2 person_id = f8 + 2 name_last = vc + 2 name_first = vc + 2 birth_dt_tm = dq8 + ) with protect + + ; Replace the reply references with mock_reply + call cclutAddMockImplementation("REPLY", "MOCK_REPLY") + + ; Execute the script-under-test + call cclutExecuteProgramWithMocks("cclut_get_persons", "") + + ; Do validation + call cclutAssertf8Equal(CURREF, "test_get_people_happy", mock_reply->persons[1].person_id, 1.0) + call cclutAssertvcEqual(CURREF, "test_get_people_happy", mock_reply->persons[1].name_last, + "Washington") + call cclutAssertvcEqual(CURREF, "test_get_people_happy", mock_reply->persons[1].name_first, + "George") + call cclutAssertf8Equal(CURREF, "test_get_people_happy", mock_reply->persons[1].birth_dt_tm, + cnvtdatetime("01-JAN-1970 00:00")) + + call cclutAssertf8Equal(CURREF, "test_get_people_happy", mock_reply->persons[2].person_id, 2.0) + call cclutAssertvcEqual(CURREF, "test_get_people_happy", mock_reply->persons[2].name_last, + "Adams") + call cclutAssertvcEqual(CURREF, "test_get_people_happy", mock_reply->persons[2].name_first, + "John") + call cclutAssertf8Equal(CURREF, "test_get_people_happy", mock_reply->persons[2].birth_dt_tm, + cnvtdatetime("02-FEB-1971 11:11")) + + call cclutAssertf8Equal(CURREF, "test_get_people_happy", mock_reply->persons[3].person_id, 3.0) + call cclutAssertvcEqual(CURREF, "test_get_people_happy", mock_reply->persons[3].name_last, + "Jefferson") + call cclutAssertvcEqual(CURREF, "test_get_people_happy", mock_reply->persons[3].name_first, + "") + call cclutAssertf8Equal(CURREF, "test_get_people_happy", mock_reply->persons[3].birth_dt_tm, + cnvtdatetime("03-MAR-1972 22:22")) + + call cclutAssertf8Equal(CURREF, "test_get_people_happy", mock_reply->persons[4].person_id, 4.0) + call cclutAssertvcEqual(CURREF, "test_get_people_happy", mock_reply->persons[4].name_last, + "Madison") + call cclutAssertvcEqual(CURREF, "test_get_people_happy", mock_reply->persons[4].name_first, + "") + call cclutAssertf8Equal(CURREF, "test_get_people_happy", mock_reply->persons[4].birth_dt_tm, + cnvtdatetime("04-APR-1973 10:33")) + + call cclutRemoveAllMocks(null) \ No newline at end of file diff --git a/cclunit-framework-source/pom.xml b/cclunit-framework-source/pom.xml index 26bfa62..5bc930f 100644 --- a/cclunit-framework-source/pom.xml +++ b/cclunit-framework-source/pom.xml @@ -3,7 +3,7 @@ com.cerner.ccl cclunit-framework-parent - 3.0 + 3.1-SNAPSHOT .. diff --git a/cclunit-framework-source/src/main/resources/cclut_compile_subs.inc b/cclunit-framework-source/src/main/resources/cclut_compile_subs.inc index c878a8d..2fc6aef 100644 --- a/cclunit-framework-source/src/main/resources/cclut_compile_subs.inc +++ b/cclunit-framework-source/src/main/resources/cclut_compile_subs.inc @@ -88,6 +88,8 @@ subroutine cclut::generateTestCaseProgram( col 0 value row+1 value = "%i cclsource:cclut_reflection_subs.inc" col 0 value row+1 + value = "%i cclsource:cclutmock.inc" + col 0 value row+1 detail col 0 ";;;CCLUT_START_TEST_INC_FILE" row+1 value = concat("%i ", cclutDirectoryLogical, ":", cclutFileNameLower) diff --git a/cclunit-framework-source/src/main/resources/cclut_execute_test_logic.inc b/cclunit-framework-source/src/main/resources/cclut_execute_test_logic.inc index e50cabd..76a5e1f 100644 --- a/cclunit-framework-source/src/main/resources/cclut_execute_test_logic.inc +++ b/cclunit-framework-source/src/main/resources/cclut_execute_test_logic.inc @@ -294,6 +294,7 @@ set cclutReply->status_data.status = "S" call cclut::executeTestLogic(null) #exit_script +call cclutRemoveAllMocks(null) ;Record any dangling errors and asserts in case the last executed unit test called go to exit_script. set cclutReply->resultInd = band(cclutReply->resultInd, cclut::evaluateTestResults(size(cclutReply->tests, 5), cclutReply, cclut_runResult, cclut_timerList)) diff --git a/cclunit-framework-source/src/main/resources/cclutmock.inc b/cclunit-framework-source/src/main/resources/cclutmock.inc new file mode 100644 index 0000000..e8004c1 --- /dev/null +++ b/cclunit-framework-source/src/main/resources/cclutmock.inc @@ -0,0 +1,192 @@ +%#ifndef CCLUTMOCK_INC +%#def CCLUTMOCK_INC +;********************************************************************************************************************************** +; +; Provides support functions that can be leveraged by consumers to construct mock objects and use those mocks in the script under +; test. +; +;********************************************************************************************************************************** + +%i cclsource:cclutmock_table.inc + +declare cclutAddMockImplementation(originalName = vc(val), replaceName = vc(val)) = null with protect +declare cclutRemoveMockImplementation(originalName = vc(val)) = null with protect +declare cclutRemoveAllMockImplementations(null) = null with protect +declare cclutExecuteProgramWithMocks(programName = vc(val), params = vc(val), + namespace = vc(val, "PUBLIC")) = null with protect +declare cclutRemoveAllMocks(null) = null with protect + +record cclut_mockImplementations ( + 1 implementations[*] + 2 originalName = vc + 2 replaceName = vc +) with protect + +/** +Adds a mock implementation to be utilized by cclutExecuteProgramWithMocks. This can include record structures, +subroutines, or other programs. originalName and replaceName are required. If originalName is already being mocked, +the mock will be overwritten with the new replaceName. + +@param originalName + The object to be mocked. +@param replaceName + The mocked object. + +Example: +call cclutAddMockImplementation("uar_get_code_by", "mock_uar_get_code_by") +**/ +subroutine cclutAddMockImplementation(originalName, replaceName) + ;Declare local variables + declare CCLUT_ORIGINAL_NAME = vc with protect, constant(trim(cnvtupper(originalName), 3)) + declare CCLUT_REPLACE_NAME = vc with protect, constant(trim(cnvtupper(replaceName), 3)) + declare cclutMockImplementationLength = + i4 with protect, noconstant(size(cclut_mockImplementations->implementations, 5)) + declare cclutMockImplementationPos = i4 with protect, noconstant(0) + declare cclutMockImplementationIndex = i4 with protect, noconstant(0) + + ;Validate inbound parameters + if (CCLUT_ORIGINAL_NAME <= " ") + call cclexception(100, "E", "cclutAddMockImplementation() - originalName is a required field") + return + endif + if (CCLUT_REPLACE_NAME <= " ") + call cclexception(100, "E", "cclutAddMockImplementation() - replaceName is a required field") + return + endif + + ;Validate that the implementation exists + set cclutMockImplementationPos = + locateval(cclutMockImplementationIndex, 1, cclutMockImplementationLength, + CCLUT_ORIGINAL_NAME, cclut_mockImplementations->implementations[cclutMockImplementationIndex].originalName) + if (cclutMockImplementationPos < 1) + set cclutMockImplementationPos = cclutMockImplementationLength + 1 + set stat = alterlist(cclut_mockImplementations->implementations, cclutMockImplementationPos) + set cclut_mockImplementations->implementations[cclutMockImplementationPos].originalName = CCLUT_ORIGINAL_NAME + endif + + set cclut_mockImplementations->implementations[cclutMockImplementationPos].replaceName = CCLUT_REPLACE_NAME +end ;cclutAddMockImplementation + +/** +Removes a mock implementation. + +@param originalName + The object that is mocked. + +Example: +call cclutRemoveMockImplementation("uar_get_code_by") +**/ +subroutine cclutRemoveMockImplementation(originalName) + ;Declare local variables + declare CCLUT_ORIGINAL_NAME = vc with protect, constant(trim(cnvtupper(originalName), 3)) + declare cclutMockImplementationLength = + i4 with protect, noconstant(size(cclut_mockImplementations->implementations, 5)) + declare cclutMockImplementationPos = i4 with protect, noconstant(0) + declare cclutMockImplementationIndex = i4 with protect, noconstant(0) + + ;Validate inbound parameters + if (CCLUT_ORIGINAL_NAME <= " ") + call cclexception(100, "E", "cclutRemoveMockImplementation() - originalName is a required field") + return + endif + + ;Validate that the implementation exists + set cclutMockImplementationPos = + locateval(cclutMockImplementationIndex, 1, cclutMockImplementationLength, + CCLUT_ORIGINAL_NAME, cclut_mockImplementations->implementations[cclutMockImplementationIndex].originalName) + if (cclutMockImplementationPos > 0) + set stat = alterlist(cclut_mockImplementations->implementations, cclutMockImplementationLength - 1, + cclutMockImplementationPos - 1) + endif +end ;cclutRemoveMockImplementation + +/** +Removes all mock implementations. + +Example: +call cclutRemoveAllMockImplementations(null) +**/ +subroutine cclutRemoveAllMockImplementations(null) + while (size(cclut_mockImplementations->implementations, 5) > 0) + call cclutRemoveMockImplementation(cclut_mockImplementations->implementations[1].originalName) + endwhile +end ;cclutRemoveAllMockImplementations + +/** +Executes a program with all mocks currently added through cclutAddMockImplementation() and cclutCreateMockTable(). +programName is required. params is a string parameter to be sent directly to the program, so all commas and string +delimiters must be specified. If namespace is omitted, it will default to the PUBLIC namespace. + +Example: +call cclutExecuteProgramWithMocks("ccl_my_program", "^MINE^, 1.0, ^string parameter^", "MYNAMESPACE") +**/ +subroutine cclutExecuteProgramWithMocks(programName, params, namespace) + ;Declare local variables + declare CCLUT_PROGRAM_NAME = vc with protect, constant(trim(cnvtupper(programName), 3)) + declare CCLUT_PARAMS = vc with protect, constant(params) + declare CCLUT_NAMESPACE = vc with protect, constant(namespace) + declare cclutMockImplementationLength = + i4 with protect, noconstant(size(cclut_mockImplementations->implementations, 5)) + declare cclutMockImplementationIndex = i4 with protect, noconstant(0) + declare cclutMockTableLength = i4 with protect, noconstant(size(cclut_mockTables->tables, 5)) + declare cclutMockTableIndex = i4 with protect, noconstant(0) + declare cclutHasComma = i4 with protect, noconstant(0) + declare cclutParserText = vc with protect, noconstant("") + + ;Validate inbound parameters + if (CCLUT_PROGRAM_NAME <= " ") + call cclexception(100, "E", "cclutExecuteProgramWithMocks() - programName is a required field") + return + endif + + set cclutParserText = concat(" execute ", CCLUT_PROGRAM_NAME, " ") + if (params > " ") + set cclutParserText = concat(cclutParserText, " ", params) + endif + set cclutParserText = concat(cclutParserText, " with ") + + ;Add mock implementations + for (cclutMockImplementationIndex = 1 to cclutMockImplementationLength) + if (cclutHasComma) + set cclutParserText = concat(cclutParserText, ", ") + endif + set cclutParserText = concat(cclutParserText, ^ replace("^, + cclut_mockImplementations->implementations[cclutMockImplementationIndex].originalName, ^", ^, + cclut_mockImplementations->implementations[cclutMockImplementationIndex].replaceName, ^) ^) + set cclutHasComma = 1 + endfor + + ;Add mock tables + for (cclutMockTableIndex = 1 to cclutMockTableLength) + if (cclut_mockTables->tables[cclutMockTableIndex].isFinalized = TRUE) + if (cclutHasComma) + set cclutParserText = concat(cclutParserText, ", ") + endif + set cclutParserText = + concat(cclutParserText, ^ replace("^, cclut_mockTables->tables[cclutMockTableIndex].originalName, ^", ^, + cclut_mockTables->tables[cclutMockTableIndex].replaceName, ^) ^) + set cclutHasComma = 1 + endif + endfor + + ;Add namespace + if (cclutHasComma) + set cclutParserText = concat(cclutParserText, ", ") + endif + set cclutParserText = concat(cclutParserText, ^ curnamespace = "^, CCLUT_NAMESPACE, ^" go ^) + call parser(cclutParserText) +end ;cclutExecuteProgramWithMocks + +/** +Removes all mock implementations and mock tables that have been added through the cclutAddMockImplementation() and +cclutCreateMockTable() APIs. This should be called at the completion of a test suite to clean up all mocks. + +Example: +call cclutRemoveAllMocks(null) +**/ +subroutine cclutRemoveAllMocks(null) + call cclutRemoveAllMockImplementations(null) + call cclutRemoveAllMockTables(null) +end ;cclutRemoveAllMocks + +%#endif CCLUTMOCK_INC \ No newline at end of file diff --git a/cclunit-framework-source/src/main/resources/cclutmock_table.inc b/cclunit-framework-source/src/main/resources/cclutmock_table.inc new file mode 100644 index 0000000..b3b2725 --- /dev/null +++ b/cclunit-framework-source/src/main/resources/cclutmock_table.inc @@ -0,0 +1,728 @@ +%#ifndef CCLUTMOCK_TABLE_INC +%#def CCLUTMOCK_TABLE_INC +;********************************************************************************************************************************** +; +; Provides support functions that can be leveraged by consumers to construct mock tables and add data to them to be used in the +; script under test. +; +;********************************************************************************************************************************** + +declare cclutDefineMockTable(tableName = vc(val), fieldNames = vc(val), fieldTypes = vc(val)) = vc with protect +declare cclutAddMockConstraint(tableName = vc(val), columnName = vc(val), + columnConstraint = vc(val)) = null with protect +declare cclutAddMockIndex(tableName = vc(val), columnNames = vc(val), isUnique = i4(val)) = null with protect +declare cclutCreateMockTable(tableName = vc(val)) = null with protect +declare cclutRemoveMockTable(tableName = vc(val)) = null with protect +declare cclutRemoveAllMockTables(null) = null with protect +declare cclutAddMockData(tableName = vc(val), rowData = vc(val)) = null with protect +declare cclutClearMockData(tableName = vc(val)) = null with protect + +declare cclut::cclutParseColumn(tableIndex = i4(val), columnIndex = i4(val), dataBuffer = vc(val)) = vc with protect + +record cclut_mockTables ( + 1 startTime = i4 + 1 tables[*] + 2 originalName = vc + 2 replaceName = vc + 2 columns[*] + 3 columnName = vc + 3 columnType = vc + 3 columnConstraint = vc + 2 indexes[*] + 3 indexColumns = vc + 3 isUnique = i4 + 2 isFinalized = i4 +) with protect + +set cclut_mockTables->startTime = cnvtint(curtime3) + +/** +Defines a mock table structure that can be created for use within a program. This is the first function to be called in +the process of mocking a table. It must be called before cclutAddMockIndex(), cclutAddMockConstraint(), and +cclutCreateMockTable() can be called. The table will not be mocked in cclutExecuteProgramWithMocks() unless +cclutCreateMockTable() is called. tableName, columnNames, and columnTypes are required. columnNames and columnTypes +are expected to be pipe-delimited strings. The columnTypes should have the same count as columnNames and be in the same +order. + +@param tableName + The table to be mocked. +@param columnNames + A pipe-delimited list of columns to be mocked on the table +@param columnTypes + A pipe-delimited list of types for each column +@returns + The name of the mock table (This can be used to select data for testing) + +Example: +call cclutDefineMockTable("person", "person_id|name_last|name_first|birth_dt_tm", "f8|vc|vc|dq8") +**/ +subroutine cclutDefineMockTable(tableName, columnNames, columnTypes) + ;Declare local variables + declare CCLUT_TABLE_NAME = vc with protect, constant(trim(cnvtupper(tableName), 3)) + declare CCLUT_COLUMN_NAMES = vc with protect, constant(trim(cnvtupper(columnNames), 3)) + declare CCLUT_COLUMN_TYPES = vc with protect, constant(trim(cnvtupper(columnTypes), 3)) + declare cclutMockTableLength = i4 with protect, noconstant(size(cclut_mockTables->tables, 5)) + declare cclutMockTablePos = i4 with protect, noconstant(0) + declare cclutMockTableIndex = i4 with protect, noconstant(0) + declare cclutColumnCount = i4 with protect, noconstant(0) + declare cclutColumnIndex = i4 with protect, noconstant(0) + declare cclutTypeCount = i4 with protect, noconstant(0) + declare cclutTypeIndex = i4 with protect, noconstant(0) + declare cclutColumnName = vc with protect, noconstant("") + record cclutColumnRec( + 1 qual[*] + 2 str = vc + ) with protect + record cclutTypeRec( + 1 qual[*] + 2 str = vc + ) with protect + + ;Validate inbound parameters + if (CCLUT_TABLE_NAME <= " ") + call cclexception(100, "E", "cclutDefineMockTable() - tableName is a required field") + return("") + endif + if (CCLUT_COLUMN_NAMES <= " ") + call cclexception(100, "E", "cclutDefineMockTable() - columnNames is a required field") + return("") + endif + if (CCLUT_COLUMN_TYPES <= " ") + call cclexception(100, "E", "cclutDefineMockTable() - columnTypes is a required field") + return("") + endif + + ;Validate the column count matches the type count + set cclutColumnCount = + arraysplit(cclutColumnRec->qual[cclutColumnIndex].str, cclutColumnIndex, CCLUT_COLUMN_NAMES, "|") + set cclutTypeCount = arraysplit(cclutTypeRec->qual[cclutTypeIndex].str, cclutTypeIndex, CCLUT_COLUMN_TYPES, "|") + + if (cclutColumnCount != cclutTypeCount) + call cclexception(100, "E", concat("cclutDefineMockTable() - columnTypes must match number of columnNames. ", + "columnNames Count: ", cnvtstring(cclutColumnCount), " columnTypes Count: ", cnvtstring(cclutTypeCount))) + return("") + endif + + ;Validate that every column and type is populated and that there are no duplicate columns + for (cclutColumnIndex = 1 to cclutColumnCount) + set cclutColumnName = cclutColumnRec->qual[cclutColumnIndex].str + if (cclutColumnName <= " ") + call cclexception(100, "E", concat("cclutDefineMockTable() - Empty columnName found in columnNames. ", + "columnNames: ", CCLUT_COLUMN_NAMES)) + return("") + endif + if (cclutTypeRec->qual[cclutColumnIndex].str <= " ") + call cclexception(100, "E", concat("cclutDefineMockTable() - Empty columnType found in columnTypes. ", + "columnTypes: ", CCLUT_COLUMN_TYPES)) + return("") + endif + if (findstring(cclutColumnName, CCLUT_COLUMN_NAMES, 1, 0) != + findstring(cclutColumnName, CCLUT_COLUMN_NAMES, 1, 1)) + call cclexception(100, "E", concat("cclutDefineMockTable() - Duplicate columnName found. ", + "columnName: ", cclutColumnName)) + return("") + endif + endfor + + ;Check if table is already mocked + set cclutMockTablePos = locateval(cclutMockTableIndex, 1, cclutMockTableLength, CCLUT_TABLE_NAME, + cclut_mockTables->tables[cclutMockTableIndex].originalName) + + if (cclutMockTablePos > 0) + ;If table was already defined, remove it and re-add it + call cclutRemoveMockTable(CCLUT_TABLE_NAME) + set stat = alterlist(cclut_mockTables->tables, cclutMockTableLength, cclutMockTablePos - 1) + else + ;If table is new, add a new element to the end of the array + set cclutMockTablePos = cclutMockTableLength + 1 + set stat = alterlist(cclut_mockTables->tables, cclutMockTablePos) + endif + + ;Create the mock name and fill out the columns + set cclut_mockTables->tables[cclutMockTablePos].originalName = CCLUT_TABLE_NAME + set cclut_mockTables->tables[cclutMockTablePos].replaceName = cnvtupper(trim(substring(1, 30, concat("CUST_CCLUT_", + trim(cnvtstring(cclutMockTablePos), 3), trim(cnvtstring(cclut_mockTables->startTime), 3), curuser)), 3)) + set cclut_mockTables->tables[cclutMockTablePos].isFinalized = FALSE + + set stat = alterlist(cclut_mockTables->tables[cclutMockTablePos].columns, cclutColumnCount) + for (cclutColumnIndex = 1 to cclutColumnCount) + set cclut_mockTables->tables[cclutMockTablePos].columns[cclutColumnIndex].columnName = + cclutColumnRec->qual[cclutColumnIndex].str + set cclut_mockTables->tables[cclutMockTablePos].columns[cclutColumnIndex].columnType = + cclutTypeRec->qual[cclutColumnIndex].str + endfor + + return(cclut_mockTables->tables[cclutMockTablePos].replaceName) +end ;cclutDefineMockTable + +/** +Adds a constraint to a mock table. The table must already be defined through cclutDefineMockTable(), otherwise an error +will be thrown. This function may not be called after cclutCreateMockTable(). tableName and columnName are required. +If the columnName is not valid for the table specified, an error will be thrown. All constraints for a column should be +present in the columnConstraint field. If a constraint already exists, this function will overwrite it with the new +value. If columnConstraint is blank, the constraint will be removed for the column. The supported constraints can be +seen here: +https://wiki.cerner.com/display/public/1101discernHP/SELECT+INTO+TABLE+Table_Name+Using+Discern+Explorer + +@param tableName + The table to which the constraint will be added. +@param columnName + The column to which the constraint will be applied. +@param columnConstraint + A string of all constraints to be applied to the column. + +Example: +call cclutAddMockConstraint("person", "name_last", "not null unique") +**/ +subroutine cclutAddMockConstraint(tableName, columnName, columnConstraint) + ;Declare local variables + declare CCLUT_TABLE_NAME = vc with protect, constant(trim(cnvtupper(tableName), 3)) + declare CCLUT_COLUMN_NAME = vc with protect, constant(trim(cnvtupper(columnName), 3)) + declare CCLUT_COLUMN_CONSTRAINT = vc with protect, constant(trim(cnvtupper(columnConstraint), 3)) + declare cclutMockTablePos = i4 with protect, noconstant(0) + declare cclutMockTableIndex = i4 with protect, noconstant(0) + declare cclutMockColumnPos = i4 with protect, noconstant(0) + declare cclutMockColumnIndex = i4 with protect, noconstant(0) + + ;Validate inbound parameters + if (CCLUT_TABLE_NAME <= " ") + call cclexception(100, "E", "cclutAddMockConstraint() - tableName is a required field") + return + endif + if (CCLUT_COLUMN_NAME <= " ") + call cclexception(100, "E", "cclutAddMockConstraint() - columnName is a required field") + return + endif + + ;Validate that the table exists and has not been created + set cclutMockTablePos = locateval(cclutMockTableIndex, 1, size(cclut_mockTables->tables, 5), CCLUT_TABLE_NAME, + cclut_mockTables->tables[cclutMockTableIndex].originalName) + if (cclutMockTablePos < 1) + call cclexception(100, "E", concat("cclutAddMockConstraint() - tableName has not been mocked. tableName: ", + CCLUT_TABLE_NAME)) + return + endif + if (cclut_mockTables->tables[cclutMockTableIndex].isFinalized = TRUE) + call cclexception(100, "E", concat("cclutAddMockConstraint() - tableName has already been created. ", + "Constraints cannot be modified. tableName: ", CCLUT_TABLE_NAME)) + return + endif + + ;Validate that the column exists on the table. + set cclutMockColumnPos = + locateval(cclutMockColumnIndex, 1, size(cclut_mockTables->tables[cclutMockTablePos].columns, 5), + CCLUT_COLUMN_NAME, cclut_mockTables->tables[cclutMockTablePos].columns[cclutMockColumnIndex].columnName) + if (cclutMockColumnPos < 1) + call cclexception(100, "E", concat("cclutAddMockConstraint() - columnName is not mocked on table. ", + "columnName: ", CCLUT_COLUMN_NAME, " tableName: ", CCLUT_TABLE_NAME)) + endif + + ;Set the constraint + set cclut_mockTables->tables[cclutMockTablePos].columns[cclutMockColumnPos].columnConstraint = + CCLUT_COLUMN_CONSTRAINT +end ;cclutAddMockConstraint + +/** +Adds an index to a mock table. The table must already be defined through cclutDefineMockTable(), otherwise an error +will be thrown. This function may not be called after cclutCreateMockTable(). tableName, columnNames, and isUnique are +required. columnNames may be a single column name or a pipe-delimited list of columns for a composite index (the order +of the columns will be the order of the index). If isUnique is 1, then a unique index will be created. If isUnique is +0, then a non-unique index will be created. + +@param tableName + The table to which the index will be added. +@param columnNames + A pipe-delimited string of column names for the index. +@param isUnique + 1 to create a unique index; 0 to create a non-unique index + +Example: +call cclutAddMockIndex("person", "person_id", 1) +call cclutAddMockIndex("person", "name_last|name_first", 0) +**/ +subroutine cclutAddMockIndex(tableName, columnNames, isUnique) + ;Declare local variables + declare CCLUT_TABLE_NAME = vc with protect, constant(trim(cnvtupper(tableName), 3)) + declare CCLUT_COLUMN_NAMES = vc with protect, constant(trim(cnvtupper(columnNames), 3)) + declare CCLUT_IS_UNIQUE = i4 with protect, constant(isUnique) + declare cclutMockTablePos = i4 with protect, noconstant(0) + declare cclutMockTableIndex = i4 with protect, noconstant(0) + declare cclutMockColumnPos = i4 with protect, noconstant(0) + declare cclutMockColumnIndex = i4 with protect, noconstant(0) + declare cclutMockIndexPos = i4 with protect, noconstant(0) + declare cclutMockIndexIndex = i4 with protect, noconstant(0) + declare cclutMockIndexLength = i4 with protect, noconstant(0) + declare cclutColumnCount = i4 with protect, noconstant(0) + declare cclutColumnIndex = i4 with protect, noconstant(0) + declare cclutColumnName = vc with protect, noconstant("") + record cclutColumnRec( + 1 qual[*] + 2 str = vc + ) with protect + + ;Validate inbound parameters + if (CCLUT_TABLE_NAME <= " ") + call cclexception(100, "E", "cclutAddMockIndex() - tableName is a required field") + return + endif + if (CCLUT_COLUMN_NAMES <= " ") + call cclexception(100, "E", "cclutAddMockIndex() - columnNames is a required field") + return + endif + + ;Validate that the table exists and has not been created + set cclutMockTablePos = locateval(cclutMockTableIndex, 1, size(cclut_mockTables->tables, 5), CCLUT_TABLE_NAME, + cclut_mockTables->tables[cclutMockTableIndex].originalName) + if (cclutMockTablePos < 1) + call cclexception(100, "E", concat("cclutAddMockIndex() - tableName has not been mocked. tableName: ", + CCLUT_TABLE_NAME)) + return + endif + if (cclut_mockTables->tables[cclutMockTableIndex].isFinalized = TRUE) + call cclexception(100, "E", concat("cclutAddMockIndex() - tableName has already been created. ", + "Indexes cannot be modified. tableName: ", CCLUT_TABLE_NAME)) + return + endif + + ;Validate that each column in the index is valid and that there are no duplicates + set cclutColumnCount = + arraysplit(cclutColumnRec->qual[cclutColumnIndex].str, cclutColumnIndex, CCLUT_COLUMN_NAMES, "|") + for (cclutColumnIndex = 1 to cclutColumnCount) + set cclutColumnName = cclutColumnRec->qual[cclutColumnIndex].str + set cclutMockColumnPos = locateval(cclutMockColumnIndex, 1, + size(cclut_mockTables->tables[cclutMockTablePos].columns, 5), cclutColumnName, + cclut_mockTables->tables[cclutMockTablePos].columns[cclutMockColumnIndex].columnName) + if (cclutMockColumnPos < 1) + call cclexception(100, "E", concat("cclutAddMockIndex() - columnName is not mocked on table. columnName: ", + cclutColumnName, " tableName: ", CCLUT_TABLE_NAME)) + return + endif + if (findstring(cclutColumnName, CCLUT_COLUMN_NAMES, 1, 0) != + findstring(cclutColumnName, CCLUT_COLUMN_NAMES, 1, 1)) + call cclexception(100, "E", concat("cclutAddMockIndex() - Duplicate columnName found. ", + "columnName: ", cclutColumnName)) + return + endif + endfor + + ;Set the index + set cclutMockIndexLength = size(cclut_mockTables->tables[cclutMockTablePos].indexes, 5) + set cclutMockIndexPos = locateval(cclutMockIndexIndex, 1, cclutMockIndexLength, + CCLUT_COLUMN_NAMES, cclut_mockTables->tables[cclutMockTablePos].indexes[cclutMockIndexIndex].indexColumns) + if (cclutMockIndexPos < 1) + set cclutMockIndexPos = cclutMockIndexLength + 1 + set stat = alterlist(cclut_mockTables->tables[cclutMockTablePos].indexes, cclutMockIndexPos) + set cclut_mockTables->tables[cclutMockTablePos].indexes[cclutMockIndexPos].indexColumns = CCLUT_COLUMN_NAMES + endif + set cclut_mockTables->tables[cclutMockTablePos].indexes[cclutMockIndexPos].isUnique = + evaluate(CCLUT_IS_UNIQUE, 0, 0, 1) +end ;cclutAddMockIndex + +/** +Creates the mock table. The table must already be defined through cclutDefineMockTable(), otherwise an error will be +thrown. If the table has already been created, the function will return silently. tableName is required. + +@param tableName + The table to be mocked. + +Example: +call cclutCreateMockTable("person") +**/ +subroutine cclutCreateMockTable(tableName) + ;Declare local variables + declare CCLUT_TABLE_NAME = vc with protect, constant(trim(cnvtupper(tableName), 3)) + declare cclutMockTablePos = i4 with protect, noconstant(0) + declare cclutMockTableIndex = i4 with protect, noconstant(0) + declare cclutMockColumnCount = i4 with protect, noconstant(0) + declare cclutMockColumnIndex = i4 with protect, noconstant(0) + declare cclutMockIndexIndex = i4 with protect, noconstant(0) + declare cclutParserText = vc with protect, noconstant("") + declare cclutColumnName = vc with protect, noconstant("") + declare cclutConstraint = vc with protect, noconstant("") + declare cclutParserConstraint = vc with protect, noconstant(" ") + + ;Validate inbound parameter + if (CCLUT_TABLE_NAME <= " ") + call cclexception(100, "E", "cclutCreateMockTable() - tableName is a required field") + return + endif + + ;Validate that the table exists and has not been created + set cclutMockTablePos = locateval(cclutMockTableIndex, 1, size(cclut_mockTables->tables, 5), CCLUT_TABLE_NAME, + cclut_mockTables->tables[cclutMockTableIndex].originalName) + if (cclutMockTablePos < 1) + call cclexception(100, "E", concat("cclutCreateMockTable() - tableName has not been mocked. tableName: ", + CCLUT_TABLE_NAME)) + return + endif + if (cclut_mockTables->tables[cclutMockTableIndex].isFinalized = TRUE) + return + endif + + ;Create the table + set cclutParserText = concat(" select into table ", cclut_mockTables->tables[cclutMockTablePos].replaceName) + for (cclutMockColumnIndex = 1 to size(cclut_mockTables->tables[cclutMockTablePos].columns, 5)) + if (cclutMockColumnIndex > 1) + set cclutParserText = concat(cclutParserText, " , ") + endif + set cclutColumnName = cclut_mockTables->tables[cclutMockTablePos].columns[cclutMockColumnIndex].columnName + set cclutConstraint = cclut_mockTables->tables[cclutMockTablePos].columns[cclutMockColumnIndex].columnConstraint + set cclutParserText = + concat(cclutParserText, ^ ^, cclutColumnName, + ^ = type("^, cclut_mockTables->tables[cclutMockTablePos].columns[cclutMockColumnIndex].columnType, ^")^) + if (cclutConstraint > " ") + set cclutParserConstraint = + concat(cclutParserConstraint, ^ , constraint(^, cclutColumnName, ^,"^, cclutConstraint, ^")^) + endif + endfor + set cclutParserText = concat(cclutParserText, ^ with organization="P" ^) + if (cclutParserConstraint > " ") + set cclutParserText = concat(cclutParserText, cclutParserConstraint) + endif + for (cclutMockIndexIndex = 1 to size(cclut_mockTables->tables[cclutMockTablePos].indexes, 5)) + set cclutParserText = concat(cclutParserText, + evaluate(cclut_mockTables->tables[cclutMockTablePos].indexes[cclutMockIndexIndex].isUnique, 1, + " , indexunique(", " , index("), + replace(cclut_mockTables->tables[cclutMockTablePos].indexes[cclutMockIndexIndex].indexColumns, "|", ","), + ")") + endfor + + set cclutParserText = concat(cclutParserText, " go ") + call parser(cclutParserText) + + set cclut_mockTables->tables[cclutMockTablePos].isFinalized = TRUE +end ;cclutCreateMockTable + +/** +Removes the mock table. If the table was already created, it will also be dropped. If the table is not currently +mocked, it will return silently. tableName is required. + +@param tableName + The table that is mocked. + +Example: +call cclutRemoveMockTable("person") +**/ +subroutine cclutRemoveMockTable(tableName) + ;Declare local variables + declare CCLUT_TABLE_NAME = vc with protect, constant(trim(cnvtupper(tableName), 3)) + declare cclutMockTableLength = i4 with protect, noconstant(size(cclut_mockTables->tables, 5)) + declare cclutMockTablePos = i4 with protect, noconstant(0) + declare cclutMockTableIndex = i4 with protect, noconstant(0) + declare cclutParserText = vc with protect, noconstant("") + + ;Validate inbound parameter + if (CCLUT_TABLE_NAME <= " ") + call cclexception(100, "E", "cclutRemoveMockTable() - tableName is a required field") + return + endif + + set cclutMockTablePos = locateval(cclutMockTableIndex, 1, cclutMockTableLength, CCLUT_TABLE_NAME, + cclut_mockTables->tables[cclutMockTableIndex].originalName) + if (cclutMockTablePos > 0) + if (cclut_mockTables->tables[cclutMockTableIndex].isFinalized) + ;Drop the table if it was already added + set cclutParserText = + concat(" drop table ", cclut_mockTables->tables[cclutMockTablePos].replaceName, " go ") + call parser(cclutParserText) + set cclutParserText = + concat(" rdb drop table ", cclut_mockTables->tables[cclutMockTablePos].replaceName, " end go ") + call parser(cclutParserText) + endif + ;Remove it from the mocked list + set stat = alterlist(cclut_mockTables->tables, cclutMockTableLength - 1, cclutMockTablePos - 1) + endif +end ;cclutRemoveMockTable + +/** +Removes all mock tables. Any tables that have already been created will also be dropped. + +Example: +call cclutRemoveAllMockTables(null) +**/ +subroutine cclutRemoveAllMockTables(null) + while (size(cclut_mockTables->tables, 5) > 0) + call cclutRemoveMockTable(cclut_mockTables->tables[1].originalName) + endwhile +end ;cclutRemoveAllMockTables + +/** +Add a row of mock data to a table. tableName and rowData are required. tableName must have already been created +through cclutCreateMockTable() or an error will be thrown. rowData is a pipe-delimited string for each column in the +same order that was used in cclutDefineMockTable(). For character fields, the backslash (\) will serve as an escape +character. For date fields, the value in rowData will be supplied to the cnvtdatetime() function. All other values +will be passed as-is. + +Supported escape values +\| = | (to represent a pipe in character fields) +\\ = \ (to represent a backslash in character fields) +\null = null (no value will be inserted into the column) + +@param tableName + The table to which the data will be added. +@param rowData + A pipe-delimited string of data to be inserted into the table. + +Example: +call cclutDefineMockTable("person", "person_id|name_last|name_first|birth_dt_tm", "f8|vc|vc|dq8") +call cclutCreateMockTable("person") +call cclutAddMockData("person", "1.0|Washington|George|01-JAN-1970 00:00") ;Will add George Washington +call cclutAddMockData("person", "2.0|A\|d\\ams|John|02-FEB-1971 11:11") ;Will add John A|d\ams +call cclutAddMockData("person", "3.0|Jefferson|\null|03-MAR-1972 22:22") ;Will add Jefferson (no first name) +call cclutAddMockData("person", "4.0|Madison||04-APR-1973 10:33") ;Will add Madison (empty string for first name) +**/ +subroutine cclutAddMockData(tableName, rowData) + ;Declare local variables + declare CCLUT_TABLE_NAME = vc with protect, constant(trim(cnvtupper(tableName), 3)) + declare CCLUT_ROW_DATA = vc with protect, constant(rowData) + declare cclutMockTablePos = i4 with protect, noconstant(0) + declare cclutMockTableIndex = i4 with protect, noconstant(0) + declare cclutMockDataLength = i4 with protect, noconstant(size(CCLUT_ROW_DATA)) + declare cclutMockDataIndex = i4 with protect, noconstant(0) + declare cclutMockColumnLength = i4 with protect, + noconstant(size(cclut_mockTables->tables[cclutMockTablePos].columns, 5)) + declare cclutMockColumnIndex = i4 with protect, noconstant(1) + declare cclutHasComma = i4 with protect, noconstant(0) + declare cclutNullColumn = i4 with protect, noconstant(0) + declare cclutDataBuffer = vc with protect, noconstant(" ") + declare cclutEscapeBuffer = vc with protect, noconstant("") + declare cclutDataCharacter = vc with protect, noconstant("") + declare cclutParserText = vc with protect, noconstant("") + + ;Validate inbound parameters + if (CCLUT_TABLE_NAME <= " ") + call cclexception(100, "E", "cclutAddMockData() - tableName is a required field") + return + endif + + ;Validate that the table exists and has been created + set cclutMockTablePos = locateval(cclutMockTableIndex, 1, size(cclut_mockTables->tables, 5), CCLUT_TABLE_NAME, + cclut_mockTables->tables[cclutMockTableIndex].originalName) + if (cclutMockTablePos < 1) + call cclexception(100, "E", concat("cclutAddMockData() - tableName has not been mocked. tableName: ", + CCLUT_TABLE_NAME)) + return + elseif (cclut_mockTables->tables[cclutMockTablePos].isFinalized = FALSE) + call cclexception(100, "E", concat("cclutAddMockData() - tableName has not been created. tableName: ", + CCLUT_TABLE_NAME)) + return + endif + + ;Initialize insert statement + set cclutParserText = concat(" insert into ", cclut_mockTables->tables[cclutMockTablePos].replaceName, " set ") + call parser(cclutParserText) + + ;Special case if rowData is empty for single-column tables + if (cclutMockDataLength = 0 or (cclutMockDataLength = 1 and ichar(substring(1, 1, CCLUT_ROW_DATA)) = 0)) + set cclutDataBuffer = cclut::cclutParseColumn(cclutMockTablePos, 1, " ") + if (cclutDataBuffer > " ") + call parser(cclutDataBuffer) + set cclutMockColumnIndex = cclutMockColumnIndex + 1 + else + ;Error occurred in cclutParseColumn, return + return + endif + else + ;Iterate over every character in rowData + for (cclutMockDataIndex = 1 to cclutMockDataLength) + set cclutParserText = " " + ;Grab the next character + set cclutDataCharacter = notrim(substring(cclutMockDataIndex, 1, CCLUT_ROW_DATA)) + ;If the character is a pipe or the end of the string + if (cclutDataCharacter = "|" or cclutMockDataIndex = cclutMockDataLength) + if (cclutNullColumn = FALSE) + ;Check if the comma is needed + if (cclutHasComma) + set cclutParserText = concat(cclutParserText, " , ") + endif + + ;Add the last character if the end of the string is reached and it is not a pipe + if (cclutMockDataIndex = cclutMockDataLength and cclutDataCharacter != "|") + set cclutDataBuffer = notrim(concat(cclutDataBuffer, cclutDataCharacter)) + endif + + ;Construct the column insertion + set cclutDataBuffer = + cclut::cclutParseColumn(cclutMockTablePos, cclutMockColumnIndex, cclutDataBuffer) + if (cclutDataBuffer > " ") + set cclutParserText = concat(cclutParserText, " ", cclutDataBuffer) + else + ;Error occurred in cclutParseColumn, return + return + endif + + ;Add one final empty string if the pipe is the last character + if (cclutMockDataIndex = cclutMockDataLength and cclutDataCharacter = "|") + set cclutDataBuffer = cclut::cclutParseColumn(cclutMockTablePos, cclutMockColumnIndex + 1, " ") + if (cclutDataBuffer > " ") + set cclutParserText = concat(cclutParserText, " , ", cclutDataBuffer) + set cclutMockColumnIndex = cclutMockColumnIndex + 1 + else + ;Error occurred in cclutParseColumn, return + return + endif + endif + + set cclutHasComma = 1 + call parser(cclutParserText) + set cclutDataBuffer = " " + set cclutMockColumnIndex = cclutMockColumnIndex + 1 + else + set cclutNullColumn = FALSE + endif + ;If the character is an escape character + elseif (cclutDataCharacter = "\") + ;Evaluate escape conditions + set cclutEscapeBuffer = substring(cclutMockDataIndex + 1, 1, CCLUT_ROW_DATA) + if (cclutEscapeBuffer = "|" or cclutEscapeBuffer = "\") + set cclutDataBuffer = notrim(concat(cclutDataBuffer, cclutEscapeBuffer)) + if (cclutMockDataLength = cclutMockDataIndex + 1) + ;End of string was reached, save off last column + if (cclutHasComma) + set cclutParserText = concat(cclutParserText, " , ") + endif + set cclutDataBuffer = + cclut::cclutParseColumn(cclutMockTablePos, cclutMockColumnIndex, cclutDataBuffer) + if (cclutDataBuffer > " ") + set cclutParserText = concat(cclutParserText, " ", cclutDataBuffer) + else + ;Error occurred in cclutParseColumn, return + return + endif + set cclutHasComma = 1 + call parser(cclutParserText) + set cclutDataBuffer = " " + set cclutMockColumnIndex = cclutMockColumnIndex + 1 + endif + set cclutMockDataIndex = cclutMockDataIndex + 1 + else + set cclutEscapeBuffer = substring(cclutMockDataIndex + 1, 4, CCLUT_ROW_DATA) + if (cclutEscapeBuffer = "null") + ;Validate that null is by itself in the column + if ((cclutMockDataIndex = 1 or + (substring(cclutMockDataIndex - 1, 1, CCLUT_ROW_DATA) = "|" and + (cclutMockDataIndex = 2 or substring(cclutMockDataIndex - 2, 1, CCLUT_ROW_DATA) != "\"))) + and + (cclutMockDataIndex + 4 = cclutMockDataLength or + substring(cclutMockDataIndex + 5, 1, CCLUT_ROW_DATA) = "|")) + set cclutMockColumnIndex = cclutMockColumnIndex + 1 + if (cclutMockDataLength != cclutMockDataIndex + 4) + set cclutMockDataIndex = cclutMockDataIndex + 4 + endif + set cclutNullColumn = TRUE + else + ;\null must be by itself + call cclexception(100, "E", + concat("cclutAddMockData() - \null column must have no other characters. rowData: ", + CCLUT_ROW_DATA)) + call parser(" reset ") + call parser(" set modify system go ") + return + endif + else + ;Invalid escape character + call cclexception(100, "E", concat("cclutAddMockData() - Invalid escape sequence. rowData: ", + CCLUT_ROW_DATA)) + call parser(" reset ") + call parser(" set modify system go ") + return + endif + endif + ;All other characters + else + set cclutDataBuffer = notrim(concat(cclutDataBuffer, cclutDataCharacter)) + endif + endfor + endif + + if (cclutMockColumnIndex <= cclutMockColumnLength) + call cclexception(100, "E", concat("cclutAddMockData() - Too few columns of data. rowData: ", CCLUT_ROW_DATA)) + call parser(" reset ") + call parser(" set modify system go ") + return + endif + + ;No columns have been added meaning all are null + if (cclutHasComma = 0) + call parser(" reset ") + call parser(concat(" rdb insert into ", cclut_mockTables->tables[cclutMockTablePos].replaceName, " values (")) + for (cclutMockColumnIndex = 1 to cclutMockColumnLength) + call parser(evaluate(cclutMockColumnIndex, 1, "NULL", ",NULL")) + endfor + call parser(") end ") + endif + + call parser(" go ") +end ;cclutAddMockData + +/** +Helper function to parse out a column for a mock insertion. +**/ +subroutine cclut::cclutParseColumn(tableIndex, columnIndex, dataBuffer) + declare CCLUT_COLUMN_COUNT = i4 with protect, constant(size(cclut_mockTables->tables[tableIndex].columns, 5)) + declare cclutMockColumnType = vc with protect, noconstant("") + declare cclutMockColumnName = vc with protect, noconstant("") + + if (columnIndex > CCLUT_COLUMN_COUNT) + call cclexception(100, "E", concat("cclutParseColumn() - Too many columns of data added to table. tableName: ", + cclut_mockTables->tables[tableIndex].originalName)) + call parser(" reset ") + call parser(" set modify system go ") + return("") + endif + + set cclutMockColumnType = cclut_mockTables->tables[tableIndex].columns[columnIndex].columnType + set cclutMockColumnName = cclut_mockTables->tables[tableIndex].columns[columnIndex].columnName + + ;Use the @ delimiter for string columns + if (findstring("C", cclutMockColumnType) > 0) + return(concat(cclutMockColumnName, " = @", + trim(cnvtstring(size(dataBuffer)), 3), ":", dataBuffer, "@ ")) + ;Use cnvtdatetime for date columns + elseif (findstring("D", cclutMockColumnType) > 0) + return(concat(cclutMockColumnName, ^ = cnvtdatetime("^, dataBuffer, ^") ^)) + ;Everything else is set directly + else + return(concat(cclutMockColumnName, " = ", dataBuffer)) + endif +end ;cclut::cclutParseColumn + +/** +Clears all data from the mock table. This is functionally similar to a truncate. tableName is required. The table +must have been created through cclutCreateMockTable() or else an error will be thrown. + +@param tableName + The table to be cleared. + +Example: +call cclutClearMockData("person") +**/ +subroutine cclutClearMockData(tableName) + ;Declare local variables + declare CCLUT_TABLE_NAME = vc with protect, constant(trim(cnvtupper(tableName), 3)) + declare cclutMockTablePos = i4 with protect, noconstant(0) + declare cclutMockTableIndex = i4 with protect, noconstant(0) + + ;Validate inbound parameters + if (CCLUT_TABLE_NAME <= " ") + call cclexception(100, "E", "cclutClearMockData() - tableName is a required field") + return + endif + + ;Validate that the table exists and has been created + set cclutMockTablePos = locateval(cclutMockTableIndex, 1, size(cclut_mockTables->tables, 5), CCLUT_TABLE_NAME, + cclut_mockTables->tables[cclutMockTableIndex].originalName) + if (cclutMockTablePos < 1) + call cclexception(100, "E", concat("cclutClearMockData() - tableName has not been mocked. tableName: ", + CCLUT_TABLE_NAME)) + return + elseif (cclut_mockTables->tables[cclutMockTablePos].isFinalized = FALSE) + call cclexception(100, "E", concat("cclutClearMockData() - tableName has not been created. tableName: ", + CCLUT_TABLE_NAME)) + return + endif + + call parser(concat(" delete from ", cclut_mockTables->tables[cclutMockTablePos].replaceName, " where seq = 1 go ")) +end ;cclutClearMockData + +%#endif CCLUTMOCK_TABLE_INC \ No newline at end of file diff --git a/cclunit-framework-source/src/test/ccl/cclut_execute_program_with_mocks_happy.prg b/cclunit-framework-source/src/test/ccl/cclut_execute_program_with_mocks_happy.prg new file mode 100644 index 0000000..953d202 --- /dev/null +++ b/cclunit-framework-source/src/test/ccl/cclut_execute_program_with_mocks_happy.prg @@ -0,0 +1,84 @@ +;****************************************************************************** +; This program is for unit testing happy path of cclutExecuteProgramWithMocks * +;****************************************************************************** +drop program cclut_execute_mocks_happy:dba go +create program cclut_execute_mocks_happy:dba + +/* Expected reply structure +record reply ( + 1 number_parameter = i4 + 1 string_parameter = vc + 1 public_subroutine = i4 + 1 test_subroutine = i4 + 1 mock_subroutine = i4 + 1 regular_join[*] + 2 person_id = f8 + 2 encounter_id = f8 + 2 encounter_alias = vc + 1 left_join[*] + 2 person_id = f8 + 2 encounter_id = f8 + 2 encounter_alias = vc + 1 rdb_join[*] + 2 columns = vc + 2 data = vc +) +*/ + +declare PUBLIC::InternalSubroutine(null) = null with protect + +subroutine (PUBLIC::InternalSubroutine(null) = null with protect) + set reply->public_subroutine = 1 +end + +call InternalSubroutine(null) + +set reply->number_parameter = $1 +set reply->string_parameter = $2 + +declare newSize = i4 with protect, noconstant(0) + +select into "nl:" +from sample_person sp + ,sample_encounter se + ,sample_encounter_alias sea +plan sp +join se + where se.person_id = sp.person_id +join sea + where sea.encounter_id = se.encounter_id +detail + newSize = size(reply->regular_join, 5) + 1 + stat = alterlist(reply->regular_join, newSize) + reply->regular_join[newSize].person_id = sp.person_id + reply->regular_join[newSize].encounter_id = se.encounter_id + reply->regular_join[newSize].encounter_alias = sea.encounter_alias +with nocounter + +select into "nl:" +from sample_person sp + ,(left join sample_encounter se on se.person_id = sp.person_id) + ,(left join sample_encounter_alias sea on sea.encounter_id = se.encounter_id) +plan sp +join se +join sea +order by sp.person_id +detail + newSize = size(reply->left_join, 5) + 1 + stat = alterlist(reply->left_join, newSize) + reply->left_join[newSize].person_id = sp.person_id + reply->left_join[newSize].encounter_id = se.encounter_id + reply->left_join[newSize].encounter_alias = sea.encounter_alias +with nocounter + +rdb set output "ccluserdir:cclut_happy.dat" end +rdb + select * + from sample_person sp + ,sample_encounter se + ,sample_encounter_alias sea + where se.person_id = sp.person_id + and sea.encounter_id = se.encounter_id +end + +end go \ No newline at end of file diff --git a/cclunit-framework-source/src/test/ccl/ut_cclut_execute_test_case.inc b/cclunit-framework-source/src/test/ccl/ut_cclut_execute_test_case.inc index d0120e2..267385c 100644 --- a/cclunit-framework-source/src/test/ccl/ut_cclut_execute_test_case.inc +++ b/cclunit-framework-source/src/test/ccl/ut_cclut_execute_test_case.inc @@ -191,67 +191,67 @@ subroutine validateListingXml(xml) ; call echo(build2("listingXml = ", xml)) call cclutAssertEndsWith(CURREF, "validate listingXml", -~916917918919920921922923924925926927928\ -929930931932933934935936937<\ -TEXT>938939\ -94094194294394494594694794894\ -9950951952953954\ -955956957<\ -/NBR>958959960961\ -962963964965966967968969970971972973\ -97497597697797897\ -9980981982983984985986987988989990991992993994\ -995\ -996997<\ -NBR>9989991000100110\ -021003<\ -/LISTING>~, xml) +~183018311832<\ +NBR>1833183418351836<\ +![CDATA[*/]]>18371838\ +1839184018411842184318441845\ +184618471848\ +18491850\ +185118521853185418551856185718581859186018611862186318641865\ +1866\ +1867186818691870\ +1871187218731874187518761877<\ +/LINE>18781879<\ +/LINE>18801881<\ +/TEXT>1882188318841885<\ +/LINE>188618871888<\ +NBR>18891890189\ +11892189318941895189618971898<\ +![CDATA[ endif]]>1899190019011902\ +19031904190519061907\ +19081909<\ +/LINE>1910191119121913191419151916<\ +/LINE>1917~, xml) end ;;;validateListingXml @@ -299,7 +299,7 @@ subroutine validateResultsXml(xml) call cclutAssertI4Equal(CURREF, "validate assert found 1.1", foundInd, TRUE) set lineNbr = cclut::retrieveXmlContent(xmlAssert, "lineNumber", 1, foundInd) call cclutAssertI4Equal(CURREF, "validate line number found 1.1", foundInd, TRUE) - call cclutAssertVCEqual(CURREF, "validate line number 1.1", lineNbr, "938") + call cclutAssertVCEqual(CURREF, "validate line number 1.1", lineNbr, "1852") set assertContext = cclut::retrieveXmlContent(xmlAssert, "context", 1, foundInd) call cclutAssertI4Equal(CURREF, "validate assert context found 1.1", foundInd, TRUE) call cclutAssertVCEqual(CURREF, "validate assert context 1.1", assertContext, "setupOnce executed") @@ -328,7 +328,7 @@ subroutine validateResultsXml(xml) call cclutAssertI4Equal(CURREF, "validate assert found 2.1", foundInd, TRUE) set lineNbr = cclut::retrieveXmlContent(xmlAssert, "lineNumber", 1, foundInd) call cclutAssertI4Equal(CURREF, "validate line number found 2.1", foundInd, TRUE) - call cclutAssertVCEqual(CURREF, "validate line number 2.1", lineNbr, "958") + call cclutAssertVCEqual(CURREF, "validate line number 2.1", lineNbr, "1872") set assertContext = cclut::retrieveXmlContent(xmlAssert, "context", 1, foundInd) call cclutAssertI4Equal(CURREF, "validate assert context found 2.1", foundInd, TRUE) call cclutAssertVCEqual(CURREF, "validate assert context 2.1", assertContext, "setup executed") @@ -344,7 +344,7 @@ subroutine validateResultsXml(xml) call cclutAssertI4Equal(CURREF, "validate assert found 2.2", foundInd, TRUE) set lineNbr = cclut::retrieveXmlContent(xmlAssert, "lineNumber", 1, foundInd) call cclutAssertI4Equal(CURREF, "validate line number found 2.2", foundInd, TRUE) - call cclutAssertVCEqual(CURREF, "validate line number 2.2", lineNbr, "978") + call cclutAssertVCEqual(CURREF, "validate line number 2.2", lineNbr, "1892") set assertContext = cclut::retrieveXmlContent(xmlAssert, "context", 1, foundInd) call cclutAssertI4Equal(CURREF, "validate assert context found 2.2", foundInd, TRUE) call cclutAssertVCEqual(CURREF, "validate assert context 2.2", assertContext, "testOne executed") @@ -361,7 +361,7 @@ subroutine validateResultsXml(xml) call cclutAssertI4Equal(CURREF, "validate assert found 2.3", foundInd, TRUE) set lineNbr = cclut::retrieveXmlContent(xmlAssert, "lineNumber", 1, foundInd) call cclutAssertI4Equal(CURREF, "validate line number found 2.3", foundInd, TRUE) - call cclutAssertVCEqual(CURREF, "validate line number 2.3", lineNbr, "968") + call cclutAssertVCEqual(CURREF, "validate line number 2.3", lineNbr, "1882") set assertContext = cclut::retrieveXmlContent(xmlAssert, "context", 1, foundInd) call cclutAssertI4Equal(CURREF, "validate assert context found 2.3", foundInd, TRUE) call cclutAssertVCEqual(CURREF, "validate assert context 2.3", assertContext, "teardown executed") @@ -407,7 +407,7 @@ subroutine validateResultsXml(xml) call cclutAssertI4Equal(CURREF, "validate assert found 5.1", foundInd, TRUE) set lineNbr = cclut::retrieveXmlContent(xmlAssert, "lineNumber", 1, foundInd) call cclutAssertI4Equal(CURREF, "validate line number found 5.1", foundInd, TRUE) - call cclutAssertVCEqual(CURREF, "validate line number 5.1", lineNbr, "948") + call cclutAssertVCEqual(CURREF, "validate line number 5.1", lineNbr, "1862") set assertContext = cclut::retrieveXmlContent(xmlAssert, "context", 1, foundInd) call cclutAssertI4Equal(CURREF, "validate assert context found 5.1", foundInd, TRUE) call cclutAssertVCEqual(CURREF, "validate assert context 5.1", assertContext, "teardownOnce executed") diff --git a/cclunit-framework-source/src/test/ccl/ut_cclut_execute_test_case_file.inc b/cclunit-framework-source/src/test/ccl/ut_cclut_execute_test_case_file.inc index 563cd66..7111c44 100644 --- a/cclunit-framework-source/src/test/ccl/ut_cclut_execute_test_case_file.inc +++ b/cclunit-framework-source/src/test/ccl/ut_cclut_execute_test_case_file.inc @@ -214,67 +214,67 @@ subroutine validateListingXml(xml) ; call echo(build2("listingXml = ", xml)) call cclutAssertEndsWith(CURREF, "validate listingXml", -~916917918919920921922923924925926927928\ -929930931932933934935936937<\ -TEXT>938939\ -94094194294394494594694794894\ -9950951952953954\ -955956957<\ -/NBR>958959960961\ -962963964965966967968969970971972973\ -97497597697797897\ -9980981982983984985986987988989990991992993994\ -995\ -996997<\ -NBR>9989991000100110\ -021003<\ -/LISTING>~, xml) +~183018311832<\ +NBR>1833183418351836<\ +![CDATA[*/]]>18371838\ +1839184018411842184318441845\ +184618471848\ +18491850\ +185118521853185418551856185718581859186018611862186318641865\ +1866\ +1867186818691870\ +1871187218731874187518761877<\ +/LINE>18781879<\ +/LINE>18801881<\ +/TEXT>1882188318841885<\ +/LINE>188618871888<\ +NBR>18891890189\ +11892189318941895189618971898<\ +![CDATA[ endif]]>1899190019011902\ +19031904190519061907\ +19081909<\ +/LINE>1910191119121913191419151916<\ +/LINE>1917~, xml) end ;;;validateListingXml @@ -319,7 +319,7 @@ subroutine validateResultsXml(xml, legacyFormat) call cclutAssertI4Equal(CURREF, "validate assert found 1.1", foundInd, TRUE) set lineNbr = cclut::retrieveXmlContent(xmlAssert, "lineNumber", 1, foundInd) call cclutAssertI4Equal(CURREF, "validate line number found 1.1", foundInd, TRUE) - call cclutAssertVCEqual(CURREF, "validate line number 1.1", lineNbr, "938") + call cclutAssertVCEqual(CURREF, "validate line number 1.1", lineNbr, "1852") set assertContext = cclut::retrieveXmlContent(xmlAssert, "context", 1, foundInd) call cclutAssertI4Equal(CURREF, "validate assert context found 1.1", foundInd, TRUE) call cclutAssertVCEqual(CURREF, "validate assert context 1.1", assertContext, "setupOnce executed") @@ -352,7 +352,7 @@ subroutine validateResultsXml(xml, legacyFormat) call cclutAssertI4Equal(CURREF, "validate assert found 2.1", foundInd, TRUE) set lineNbr = cclut::retrieveXmlContent(xmlAssert, "lineNumber", 1, foundInd) call cclutAssertI4Equal(CURREF, "validate line number found 2.1", foundInd, TRUE) - call cclutAssertVCEqual(CURREF, "validate line number 2.1", lineNbr, "958") + call cclutAssertVCEqual(CURREF, "validate line number 2.1", lineNbr, "1872") set assertContext = cclut::retrieveXmlContent(xmlAssert, "context", 1, foundInd) call cclutAssertI4Equal(CURREF, "validate assert context found 2.1", foundInd, TRUE) call cclutAssertVCEqual(CURREF, "validate assert context 2.1", assertContext, "setup executed") @@ -372,7 +372,7 @@ subroutine validateResultsXml(xml, legacyFormat) call cclutAssertI4Equal(CURREF, "validate assert found 2.2", foundInd, TRUE) set lineNbr = cclut::retrieveXmlContent(xmlAssert, "lineNumber", 1, foundInd) call cclutAssertI4Equal(CURREF, "validate line number found 2.2", foundInd, TRUE) - call cclutAssertVCEqual(CURREF, "validate line number 2.2", lineNbr, "978") + call cclutAssertVCEqual(CURREF, "validate line number 2.2", lineNbr, "1892") set assertContext = cclut::retrieveXmlContent(xmlAssert, "context", 1, foundInd) call cclutAssertI4Equal(CURREF, "validate assert context found 2.2", foundInd, TRUE) call cclutAssertVCEqual(CURREF, "validate assert context 2.2", assertContext, "testOne executed") @@ -393,7 +393,7 @@ subroutine validateResultsXml(xml, legacyFormat) call cclutAssertI4Equal(CURREF, "validate assert found 2.3", foundInd, TRUE) set lineNbr = cclut::retrieveXmlContent(xmlAssert, "lineNumber", 1, foundInd) call cclutAssertI4Equal(CURREF, "validate line number found 2.3", foundInd, TRUE) - call cclutAssertVCEqual(CURREF, "validate line number 2.3", lineNbr, "968") + call cclutAssertVCEqual(CURREF, "validate line number 2.3", lineNbr, "1882") set assertContext = cclut::retrieveXmlContent(xmlAssert, "context", 1, foundInd) call cclutAssertI4Equal(CURREF, "validate assert context found 2.3", foundInd, TRUE) call cclutAssertVCEqual(CURREF, "validate assert context 2.3", assertContext, "teardown executed") @@ -443,7 +443,7 @@ subroutine validateResultsXml(xml, legacyFormat) call cclutAssertI4Equal(CURREF, "validate assert found 5.1", foundInd, TRUE) set lineNbr = cclut::retrieveXmlContent(xmlAssert, "lineNumber", 1, foundInd) call cclutAssertI4Equal(CURREF, "validate line number found 5.1", foundInd, TRUE) - call cclutAssertVCEqual(CURREF, "validate line number 5.1", lineNbr, "948") + call cclutAssertVCEqual(CURREF, "validate line number 5.1", lineNbr, "1862") set assertContext = cclut::retrieveXmlContent(xmlAssert, "context", 1, foundInd) call cclutAssertI4Equal(CURREF, "validate assert context found 5.1", foundInd, TRUE) call cclutAssertVCEqual(CURREF, "validate assert context 5.1", assertContext, "teardownOnce executed") diff --git a/cclunit-framework-source/src/test/ccl/ut_cclut_mock.inc b/cclunit-framework-source/src/test/ccl/ut_cclut_mock.inc new file mode 100644 index 0000000..a018356 --- /dev/null +++ b/cclunit-framework-source/src/test/ccl/ut_cclut_mock.inc @@ -0,0 +1,409 @@ +declare setup(dummyVar = i2) = null +declare tearDown(dummyVar = i2) = null + +subroutine setup(dummyVar) + null +end ;setup + +subroutine tearDown(dummyVar) + call cclutRemoveAllMocks(null) + rollback +end ;tearDown + +;********************************************************************************************************************************** +;** cclutAddMockImplementation +;********************************************************************************************************************************** +/* test_cclutAddMockImplementation_happy ******************************************************************** +* Scenario: Adds a mock implementation that can be used with cclutExecuteProgramWithMocks * +************************************************************************************************************/ +subroutine test_cclutAddMockImplementation_happy(null) + call echo("~~~***~~~***test_cclutAddMockImplementation_happy***~~~***~~~") + + call cclutAddMockImplementation("sample_subroutine", "mock_subroutine") + + call cclutAsserti4Equal(CURREF, "test_cclutAddMockImplementation_happy", + size(cclut_mockImplementations->implementations, 5), 1) + call cclutAssertvcEqual(CURREF, "test_cclutAddMockImplementation_happy", + cclut_mockImplementations->implementations[1].originalName, "SAMPLE_SUBROUTINE") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockImplementation_happy", + cclut_mockImplementations->implementations[1].replaceName, "MOCK_SUBROUTINE") +end ;test_cclutAddMockImplementation_happy + +/* test_cclutAddMockImplementation_existing_implementation ************************************************** +* Scenario: Replaces the mock name of an implementation if it was already added * +************************************************************************************************************/ +subroutine test_cclutAddMockImplementation_existing_implementation(null) + call echo("~~~***~~~***test_cclutAddMockImplementation_existing_implementation***~~~***~~~") + + call cclutAddMockImplementation("sample_subroutine", "mock_subroutine") + + call cclutAsserti4Equal(CURREF, "test_cclutAddMockImplementation_happy", + size(cclut_mockImplementations->implementations, 5), 1) + call cclutAssertvcEqual(CURREF, "test_cclutAddMockImplementation_happy", + cclut_mockImplementations->implementations[1].originalName, "SAMPLE_SUBROUTINE") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockImplementation_happy", + cclut_mockImplementations->implementations[1].replaceName, "MOCK_SUBROUTINE") + + call cclutAddMockImplementation("sample_subroutine", "new_subroutine") + + call cclutAsserti4Equal(CURREF, "test_cclutAddMockImplementation_happy", + size(cclut_mockImplementations->implementations, 5), 1) + call cclutAssertvcEqual(CURREF, "test_cclutAddMockImplementation_happy", + cclut_mockImplementations->implementations[1].originalName, "SAMPLE_SUBROUTINE") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockImplementation_happy", + cclut_mockImplementations->implementations[1].replaceName, "NEW_SUBROUTINE") +end ;test_cclutAddMockImplementation_happy + +/* test_cclutAddMockImplementation_missing_originalName ***************************************************** +* Scenario: Throws an error when an empty originalName is supplied to the function (after trimming) * +************************************************************************************************************/ +subroutine test_cclutAddMockImplementation_missing_originalName(null) + call echo("~~~***~~~***test_cclutAddMockImplementation_missing_originalName***~~~***~~~") + + declare errorMessage = vc with protect, noconstant("") + declare errorCode = i4 with protect, noconstant(0) + call cclutAddMockImplementation(" ", "mock_subroutine") + + set errorCode = error(errorMessage, 0) + + call cclutAssertVcOperator(CURREF, "test_cclutAddMockImplementation_missing_originalName", trim(errorMessage, 3), + "regexplike", concat("%CCL-E-392-PRG_[0-9]+_[0-9]+\([^)]+\)[0-9]+:[0-9]+\{CCLEXCEPTION\(\)\}Exception\(100\):", + " cclutAddMockImplementation\(\) - originalName is a required field.")) +end ;test_cclutAddMockImplementation_missing_originalName + +/* test_cclutAddMockImplementation_missing_replaceName ****************************************************** +* Scenario: Throws an error when an empty replaceName is supplied to the function (after trimming) * +************************************************************************************************************/ +subroutine test_cclutAddMockImplementation_missing_replaceName(null) + call echo("~~~***~~~***test_cclutAddMockImplementation_missing_replaceName***~~~***~~~") + + declare errorMessage = vc with protect, noconstant("") + declare errorCode = i4 with protect, noconstant(0) + call cclutAddMockImplementation("sample_subroutine", " ") + + set errorCode = error(errorMessage, 0) + + call cclutAssertVcOperator(CURREF, "test_cclutAddMockImplementation_missing_replaceName", trim(errorMessage, 3), + "regexplike", concat("%CCL-E-392-PRG_[0-9]+_[0-9]+\([^)]+\)[0-9]+:[0-9]+\{CCLEXCEPTION\(\)\}Exception\(100\):", + " cclutAddMockImplementation\(\) - replaceName is a required field.")) +end ;test_cclutAddMockImplementation_missing_replaceName + +;********************************************************************************************************************************** +;** cclutRemoveMockImplementation +;********************************************************************************************************************************** +/* test_cclutRemoveMockImplementation_happy ***************************************************************** +* Scenario: Removes a mock implementation so that the original can be used * +************************************************************************************************************/ +subroutine test_cclutRemoveMockImplementation_happy(null) + call echo("~~~***~~~***test_cclutRemoveMockImplementation_happy***~~~***~~~") + + call cclutAddMockImplementation("sample_subroutine", "mock_subroutine") + + call cclutAsserti4Equal(CURREF, "test_cclutRemoveMockImplementation_happy", + size(cclut_mockImplementations->implementations, 5), 1) + call cclutAssertvcEqual(CURREF, "test_cclutRemoveMockImplementation_happy", + cclut_mockImplementations->implementations[1].originalName, "SAMPLE_SUBROUTINE") + call cclutAssertvcEqual(CURREF, "test_cclutRemoveMockImplementation_happy", + cclut_mockImplementations->implementations[1].replaceName, "MOCK_SUBROUTINE") + + call cclutRemoveMockImplementation("sample_subroutine") + + call cclutAsserti4Equal(CURREF, "test_cclutRemoveMockImplementation_happy", + size(cclut_mockImplementations->implementations, 5), 0) +end ;test_cclutRemoveMockImplementation_happy + +/* test_cclutRemoveMockImplementation_missing_originalName ***************************************************** +* Scenario: Throws an error when an empty originalName is supplied to the function (after trimming) * +************************************************************************************************************/ +subroutine test_cclutRemoveMockImplementation_missing_originalName(null) + call echo("~~~***~~~***test_cclutRemoveMockImplementation_missing_originalName***~~~***~~~") + + declare errorMessage = vc with protect, noconstant("") + declare errorCode = i4 with protect, noconstant(0) + call cclutRemoveMockImplementation(" ") + + set errorCode = error(errorMessage, 0) + + call cclutAssertVcOperator(CURREF, "test_cclutRemoveMockImplementation_missing_originalName", trim(errorMessage, 3), + "regexplike", concat("%CCL-E-392-PRG_[0-9]+_[0-9]+\([^)]+\)[0-9]+:[0-9]+\{CCLEXCEPTION\(\)\}Exception\(100\):", + " cclutRemoveMockImplementation\(\) - originalName is a required field.")) +end ;test_cclutRemoveMockImplementation_missing_originalName + +;********************************************************************************************************************************** +;** cclutRemoveAllMockImplementations +;********************************************************************************************************************************** +/* test_cclutRemoveAllMockImplementations_happy ************************************************************* +* Scenario: Removes all mock implementations so that the originals can be used * +************************************************************************************************************/ +subroutine test_cclutRemoveAllMockImplementations_happy(null) + call echo("~~~***~~~***test_cclutRemoveAllMockImplementations_happy***~~~***~~~") + + call cclutAddMockImplementation("sample_subroutine", "mock_subroutine") + call cclutAddMockImplementation("sample_subroutine_2", "mock_subroutine_2") + call cclutAddMockImplementation("sample_subroutine_3", "mock_subroutine_3") + + call cclutAsserti4Equal(CURREF, "test_cclutRemoveAllMockImplementations_happy", + size(cclut_mockImplementations->implementations, 5), 3) + + call cclutRemoveAllMockImplementations(null) + + call cclutAsserti4Equal(CURREF, "test_cclutRemoveAllMockImplementations_happy", + size(cclut_mockImplementations->implementations, 5), 0) +end ;test_cclutRemoveAllMockImplementations_happy + +;********************************************************************************************************************************** +;** cclutExecuteProgramWithMocks +;********************************************************************************************************************************** +/* test_cclutExecuteProgramWithMocks_happy ****************************************************************** +* Scenario: Executes the program using mock tables and implementations that have been set up * +************************************************************************************************************/ +subroutine test_cclutExecuteProgramWithMocks_happy(null) + call echo("~~~***~~~***test_cclutExecuteProgramWithMocks_happy***~~~***~~~") + + record executeReply ( + 1 number_parameter = i4 + 1 string_parameter = vc + 1 public_subroutine = i4 + 1 test_subroutine = i4 + 1 mock_subroutine = i4 + 1 regular_join[*] + 2 person_id = f8 + 2 encounter_id = f8 + 2 encounter_alias = vc + 1 left_join[*] + 2 person_id = f8 + 2 encounter_id = f8 + 2 encounter_alias = vc + 1 rdb_join[*] + 2 columns = vc + 2 data = vc + ) with protect + + call cclutDefineMockTable("sample_person", "person_id", "f8") + call cclutDefineMockTable("sample_encounter", "encounter_id|person_id", "f8|f8") + call cclutDefineMockTable("sample_encounter_alias", "encounter_id|encounter_alias", "f8|vc") + call cclutCreateMockTable("sample_person") + call cclutCreateMockTable("sample_encounter") + call cclutCreateMockTable("sample_encounter_alias") + + call cclutAddMockData("sample_person", "1.0") + call cclutAddMockData("sample_person", "2.0") + call cclutAddMockData("sample_person", "3.0") + call cclutAddMockData("sample_encounter", "4.0|1.0") + call cclutAddMockData("sample_encounter", "5.0|2.0") + call cclutAddMockData("sample_encounter_alias", "4.0|test alias") + + call cclutAddMockImplementation("REPLY", "EXECUTEREPLY") + + call cclutExecuteProgramWithMocks("cclut_execute_mocks_happy", "10,^test param^") + + call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy", executeReply->number_parameter, 10) + call cclutAssertvcEqual(CURREF, "test_cclutExecuteProgramWithMocks_happy", executeReply->string_parameter, + "test param") + call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy", executeReply->public_subroutine, 1) + call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy", executeReply->test_subroutine, 0) + call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy", executeReply->mock_subroutine, 0) + + call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy", size(executeReply->regular_join, 5), 1) + call cclutAssertf8Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy", executeReply->regular_join[1].person_id, + 1.0) + call cclutAssertf8Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy", + executeReply->regular_join[1].encounter_id, 4.0) + call cclutAssertvcEqual(CURREF, "test_cclutExecuteProgramWithMocks_happy", + executeReply->regular_join[1].encounter_alias, "test alias") + + call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy", size(executeReply->left_join, 5), 3) + call cclutAssertf8Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy", executeReply->left_join[1].person_id, + 1.0) + call cclutAssertf8Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy", + executeReply->left_join[1].encounter_id, 4.0) + call cclutAssertvcEqual(CURREF, "test_cclutExecuteProgramWithMocks_happy", + executeReply->left_join[1].encounter_alias, "test alias") + call cclutAssertf8Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy", executeReply->left_join[2].person_id, + 2.0) + call cclutAssertf8Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy", + executeReply->left_join[2].encounter_id, 5.0) + call cclutAssertvcEqual(CURREF, "test_cclutExecuteProgramWithMocks_happy", + executeReply->left_join[2].encounter_alias, "") + call cclutAssertf8Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy", executeReply->left_join[3].person_id, + 3.0) + call cclutAssertf8Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy", + executeReply->left_join[3].encounter_id, 0.0) + call cclutAssertvcEqual(CURREF, "test_cclutExecuteProgramWithMocks_happy", + executeReply->left_join[3].encounter_alias, "") + + set stat = alterlist(executeReply->rdb_join, 1) + free define rtl2 + define rtl2 is "ccluserdir:cclut_happy.dat" + select into "nl:" + from rtl2t r + head report + executeReply->rdb_join[1].columns = r.line + foot report + executeReply->rdb_join[1].data = r.line + with nocounter + + call cclutAssertVcOperator(CURREF, "test_cclutExecuteProgramWithMocks_happy", executeReply->rdb_join[1].columns, + "regexplike", "PERSON_ID.*ENCOUNTER_ID.*PERSON_ID.*ENCOUNTER_ID.*ENCOUNTER_ALIAS") + call cclutAssertVcOperator(CURREF, "test_cclutExecuteProgramWithMocks_happy", executeReply->rdb_join[1].data, + "regexplike", "1.*4.*1.*4.*test alias") +end ;test_cclutExecuteProgramWithMocks_happy + +declare CCLUT::InternalSubroutine(null) = null with protect + +subroutine (CCLUT::InternalSubroutine(null) = null with protect) + set executeReply->test_subroutine = 1 +end + +/* test_cclutExecuteProgramWithMocks_namespace ************************************************************** +* Scenario: Executes the program using the supplied namespace * +************************************************************************************************************/ +subroutine test_cclutExecuteProgramWithMocks_namespace(null) + call echo("~~~***~~~***test_cclutExecuteProgramWithMocks_namespace***~~~***~~~") + + record executeReply ( + 1 number_parameter = i4 + 1 string_parameter = vc + 1 public_subroutine = i4 + 1 test_subroutine = i4 + 1 mock_subroutine = i4 + 1 regular_join[*] + 2 person_id = f8 + 2 encounter_id = f8 + 2 encounter_alias = vc + 1 left_join[*] + 2 person_id = f8 + 2 encounter_id = f8 + 2 encounter_alias = vc + 1 rdb_join[*] + 2 columns = vc + 2 data = vc + ) with protect + + call cclutDefineMockTable("sample_person", "person_id", "f8") + call cclutDefineMockTable("sample_encounter", "encounter_id|person_id", "f8|f8") + call cclutDefineMockTable("sample_encounter_alias", "encounter_id|encounter_alias", "f8|vc") + call cclutCreateMockTable("sample_person") + call cclutCreateMockTable("sample_encounter") + call cclutCreateMockTable("sample_encounter_alias") + + call cclutAddMockData("sample_person", "1.0") + call cclutAddMockData("sample_person", "2.0") + call cclutAddMockData("sample_person", "3.0") + call cclutAddMockData("sample_encounter", "4.0|1.0") + call cclutAddMockData("sample_encounter", "5.0|2.0") + call cclutAddMockData("sample_encounter_alias", "4.0|test alias") + + call cclutAddMockImplementation("REPLY", "EXECUTEREPLY") + + call cclutExecuteProgramWithMocks("cclut_execute_mocks_happy", "10,^test param^", "CCLUT") + + call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_namespace", executeReply->public_subroutine, 0) + call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_namespace", executeReply->test_subroutine, 1) + call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_namespace", executeReply->mock_subroutine, 0) +end ;test_cclutExecuteProgramWithMocks_namespace + +declare CCLUT::MockSubroutine(null) = null with protect + +subroutine (CCLUT::MockSubroutine(null) = null with protect) + set executeReply->mock_subroutine = 1 +end + +/* test_cclutExecuteProgramWithMocks_mock_subroutine ******************************************************** +* Scenario: Executes the program while replacing a subroutine with a mocked version * +************************************************************************************************************/ +subroutine test_cclutExecuteProgramWithMocks_mock_subroutine(null) + call echo("~~~***~~~***test_cclutExecuteProgramWithMocks_mock_subroutine***~~~***~~~") + + record executeReply ( + 1 number_parameter = i4 + 1 string_parameter = vc + 1 public_subroutine = i4 + 1 test_subroutine = i4 + 1 mock_subroutine = i4 + 1 regular_join[*] + 2 person_id = f8 + 2 encounter_id = f8 + 2 encounter_alias = vc + 1 left_join[*] + 2 person_id = f8 + 2 encounter_id = f8 + 2 encounter_alias = vc + 1 rdb_join[*] + 2 columns = vc + 2 data = vc + ) with protect + + call cclutDefineMockTable("sample_person", "person_id", "f8") + call cclutDefineMockTable("sample_encounter", "encounter_id|person_id", "f8|f8") + call cclutDefineMockTable("sample_encounter_alias", "encounter_id|encounter_alias", "f8|vc") + call cclutCreateMockTable("sample_person") + call cclutCreateMockTable("sample_encounter") + call cclutCreateMockTable("sample_encounter_alias") + + call cclutAddMockData("sample_person", "1.0") + call cclutAddMockData("sample_person", "2.0") + call cclutAddMockData("sample_person", "3.0") + call cclutAddMockData("sample_encounter", "4.0|1.0") + call cclutAddMockData("sample_encounter", "5.0|2.0") + call cclutAddMockData("sample_encounter_alias", "4.0|test alias") + + call cclutAddMockImplementation("REPLY", "EXECUTEREPLY") + call cclutAddMockImplementation("InternalSubroutine", "MockSubroutine") + + call cclutExecuteProgramWithMocks("cclut_execute_mocks_happy", "10,^test param^", "CCLUT") + + call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_mock_subroutine", executeReply->public_subroutine, 0) + call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_mock_subroutine", executeReply->test_subroutine, 0) + call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_mock_subroutine", executeReply->mock_subroutine, 1) +end ;test_cclutExecuteProgramWithMocks_mock_subroutine + +/* test_cclutExecuteProgramWithMocks_missing_programName **************************************************** +* Scenario: Throws an error when an empty programName is supplied to the function (after trimming) * +************************************************************************************************************/ +subroutine test_cclutExecuteProgramWithMocks_missing_programName(null) + call echo("~~~***~~~***test_cclutExecuteProgramWithMocks_missing_programName***~~~***~~~") + + declare errorMessage = vc with protect, noconstant("") + declare errorCode = i4 with protect, noconstant(0) + call cclutExecuteProgramWithMocks(" ", "") + + set errorCode = error(errorMessage, 0) + + call cclutAssertVcOperator(CURREF, "test_cclutExecuteProgramWithMocks_missing_programName", trim(errorMessage, 3), + "regexplike", concat("%CCL-E-392-PRG_[0-9]+_[0-9]+\([^)]+\)[0-9]+:[0-9]+\{CCLEXCEPTION\(\)\}Exception\(100\):", + " cclutExecuteProgramWithMocks\(\) - programName is a required field.")) +end ;test_cclutExecuteProgramWithMocks_missing_programName + +;********************************************************************************************************************************** +;** cclutRemoveAllMocks +;********************************************************************************************************************************** +/* test_cclutRemoveAllMocks_happy *************************************************************************** +* Scenario: Removes all mock tables and implementations so that the originals can be used * +************************************************************************************************************/ +subroutine test_cclutRemoveAllMocks_happy(null) + call echo("~~~***~~~***test_cclutRemoveAllMocks_happy***~~~***~~~") + + call cclutDefineMockTable("sample_table", "sample_table_id|sample_table_text|sample_table_date", "f8|vc|dq8") + call cclutDefineMockTable("sample_table_2", "sample_table_2_id|sample_table_2_text|sample_table_2_date", + "f8|vc|dq8") + call cclutDefineMockTable("sample_table_3", "sample_table_3_id|sample_table_3_text|sample_table_3_date", + "f8|vc|dq8") + + call cclutCreateMockTable("sample_table") + + call cclutAddMockImplementation("sample_subroutine", "mock_subroutine") + call cclutAddMockImplementation("sample_subroutine_2", "mock_subroutine_2") + call cclutAddMockImplementation("sample_subroutine_3", "mock_subroutine_3") + + call cclutAsserti4Equal(CURREF, "test_cclutRemoveAllMocks_happy", + size(cclut_mockTables->tables, 5), 3) + call cclutAsserti4Equal(CURREF, "test_cclutRemoveAllMocks_happy", + size(cclut_mockImplementations->implementations, 5), 3) + + call cclutRemoveAllMocks(null) + + call cclutAsserti4Equal(CURREF, "test_cclutRemoveAllMocks_happy", size(cclut_mockTables->tables, 5), 0) + call cclutAsserti4Equal(CURREF, "test_cclutRemoveAllMocks_happy", + size(cclut_mockImplementations->implementations, 5), 0) +end ;test_cclutRemoveAllMocks_happy \ No newline at end of file diff --git a/cclunit-framework-source/src/test/ccl/ut_cclut_mock_table.inc b/cclunit-framework-source/src/test/ccl/ut_cclut_mock_table.inc new file mode 100644 index 0000000..31420c9 --- /dev/null +++ b/cclunit-framework-source/src/test/ccl/ut_cclut_mock_table.inc @@ -0,0 +1,1449 @@ +declare setup(dummyVar = i2) = null +declare tearDown(dummyVar = i2) = null + +subroutine setup(dummyVar) + null +end ;setup + +subroutine tearDown(dummyVar) + call cclutRemoveAllMocks(null) + rollback +end ;tearDown + +;********************************************************************************************************************************** +;** cclutDefineMockTable +;********************************************************************************************************************************** +/* test_cclutDefineMockTable_happy ************************************************************************** +* Scenario: Defines a table with columns of various types that has not been mocked or defined previously. * +************************************************************************************************************/ +subroutine test_cclutDefineMockTable_happy(null) + call echo("~~~***~~~***test_cclutDefineMockTable_happy***~~~***~~~") + + declare mockTable = vc with protect, noconstant("") + set mockTable = + cclutDefineMockTable("sample_table", "sample_table_id|sample_table_text|sample_table_date", "f8|vc|dq8") + + call cclutAssertStartsWith(CURREF, "test_cclutDefineMockTable_happy", "CUST_CCLUT", mockTable) + + call cclutAsserti4Equal(CURREF, "test_cclutDefineMockTable_happy", size(cclut_mockTables->tables, 5), 1) + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_happy", cclut_mockTables->tables[1].originalName, + "SAMPLE_TABLE") + call cclutAssertStartsWith(CURREF, "test_cclutDefineMockTable_happy", "CUST_CCLUT", + cclut_mockTables->tables[1].replaceName) + call cclutAsserti4Equal(CURREF, "test_cclutDefineMockTable_happy", size(cclut_mockTables->tables[1].columns, 5), 3) + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_happy", + cclut_mockTables->tables[1].columns[1].columnName, "SAMPLE_TABLE_ID") + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_happy", + cclut_mockTables->tables[1].columns[1].columnType, "F8") + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_happy", + cclut_mockTables->tables[1].columns[1].columnConstraint, "") + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_happy", + cclut_mockTables->tables[1].columns[2].columnName, "SAMPLE_TABLE_TEXT") + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_happy", + cclut_mockTables->tables[1].columns[2].columnType, "VC") + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_happy", + cclut_mockTables->tables[1].columns[2].columnConstraint, "") + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_happy", + cclut_mockTables->tables[1].columns[3].columnName, "SAMPLE_TABLE_DATE") + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_happy", + cclut_mockTables->tables[1].columns[3].columnType, "DQ8") + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_happy", + cclut_mockTables->tables[1].columns[3].columnConstraint, "") + call cclutAsserti4Equal(CURREF, "test_cclutDefineMockTable_happy", size(cclut_mockTables->tables[1].indexes, 5), 0) + call cclutAsserti4Equal(CURREF, "test_cclutDefineMockTable_happy", cclut_mockTables->tables[1].isFinalized, FALSE) +end ;test_cclutDefineMockTable_happy + +/* test_cclutDefineMockTable_existing_mock ****************************************************************** +* Scenario: Removes the existing mock and adds a new one when cclutDefineMockTable is called again * +************************************************************************************************************/ +subroutine test_cclutDefineMockTable_existing_mock(null) + call echo("~~~***~~~***test_cclutDefineMockTable_existing_mock***~~~***~~~") + + declare mockTable = vc with protect, noconstant("") + set mockTable = + cclutDefineMockTable("sample_table", "sample_table_id|sample_table_text|sample_table_date", "f8|vc|dq8") + + call cclutAssertStartsWith(CURREF, "test_cclutDefineMockTable_existing_mock", "CUST_CCLUT", mockTable) + + call cclutAsserti4Equal(CURREF, "test_cclutDefineMockTable_existing_mock", size(cclut_mockTables->tables, 5), 1) + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_existing_mock", cclut_mockTables->tables[1].originalName, + "SAMPLE_TABLE") + call cclutAssertStartsWith(CURREF, "test_cclutDefineMockTable_existing_mock", "CUST_CCLUT", + cclut_mockTables->tables[1].replaceName) + call cclutAsserti4Equal(CURREF, "test_cclutDefineMockTable_existing_mock", + size(cclut_mockTables->tables[1].columns, 5), 3) + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_existing_mock", + cclut_mockTables->tables[1].columns[1].columnName, "SAMPLE_TABLE_ID") + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_existing_mock", + cclut_mockTables->tables[1].columns[1].columnType, "F8") + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_existing_mock", + cclut_mockTables->tables[1].columns[1].columnConstraint, "") + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_existing_mock", + cclut_mockTables->tables[1].columns[2].columnName, "SAMPLE_TABLE_TEXT") + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_existing_mock", + cclut_mockTables->tables[1].columns[2].columnType, "VC") + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_existing_mock", + cclut_mockTables->tables[1].columns[2].columnConstraint, "") + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_existing_mock", + cclut_mockTables->tables[1].columns[3].columnName, "SAMPLE_TABLE_DATE") + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_existing_mock", + cclut_mockTables->tables[1].columns[3].columnType, "DQ8") + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_existing_mock", + cclut_mockTables->tables[1].columns[3].columnConstraint, "") + call cclutAsserti4Equal(CURREF, "test_cclutDefineMockTable_existing_mock", + size(cclut_mockTables->tables[1].indexes, 5), 0) + call cclutAsserti4Equal(CURREF, "test_cclutDefineMockTable_existing_mock", cclut_mockTables->tables[1].isFinalized, + FALSE) + + set mockTable = cclutDefineMockTable("sample_table", "new_table_id|new_table_text|new_table_date", "i4|c100|dm12") + + call cclutAssertStartsWith(CURREF, "test_cclutDefineMockTable_existing_mock", "CUST_CCLUT", mockTable) + + call cclutAsserti4Equal(CURREF, "test_cclutDefineMockTable_existing_mock", size(cclut_mockTables->tables, 5), 1) + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_existing_mock", cclut_mockTables->tables[1].originalName, + "SAMPLE_TABLE") + call cclutAssertStartsWith(CURREF, "test_cclutDefineMockTable_existing_mock", "CUST_CCLUT", + cclut_mockTables->tables[1].replaceName) + call cclutAsserti4Equal(CURREF, "test_cclutDefineMockTable_existing_mock", + size(cclut_mockTables->tables[1].columns, 5), 3) + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_existing_mock", + cclut_mockTables->tables[1].columns[1].columnName, "NEW_TABLE_ID") + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_existing_mock", + cclut_mockTables->tables[1].columns[1].columnType, "I4") + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_existing_mock", + cclut_mockTables->tables[1].columns[1].columnConstraint, "") + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_existing_mock", + cclut_mockTables->tables[1].columns[2].columnName, "NEW_TABLE_TEXT") + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_existing_mock", + cclut_mockTables->tables[1].columns[2].columnType, "C100") + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_existing_mock", + cclut_mockTables->tables[1].columns[2].columnConstraint, "") + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_existing_mock", + cclut_mockTables->tables[1].columns[3].columnName, "NEW_TABLE_DATE") + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_existing_mock", + cclut_mockTables->tables[1].columns[3].columnType, "DM12") + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_existing_mock", + cclut_mockTables->tables[1].columns[3].columnConstraint, "") + call cclutAsserti4Equal(CURREF, "test_cclutDefineMockTable_existing_mock", + size(cclut_mockTables->tables[1].indexes, 5), 0) + call cclutAsserti4Equal(CURREF, "test_cclutDefineMockTable_existing_mock", cclut_mockTables->tables[1].isFinalized, + FALSE) +end ;test_cclutDefineMockTable_existing_mock + +/* test_cclutDefineMockTable_missing_tableName ************************************************************** +* Scenario: Throws an error when an empty tableName is supplied to the function (after trimming) * +************************************************************************************************************/ +subroutine test_cclutDefineMockTable_missing_tableName(null) + call echo("~~~***~~~***test_cclutDefineMockTable_missing_tableName***~~~***~~~") + + declare mockTable = vc with protect, noconstant("") + declare errorMessage = vc with protect, noconstant("") + declare errorCode = i4 with protect, noconstant(0) + set mockTable = + cclutDefineMockTable(" ", "sample_table_id|sample_table_text|sample_table_date", "f8|vc|dq8") + + set errorCode = error(errorMessage, 0) + + call cclutAssertVcOperator(CURREF, "test_cclutDefineMockTable_missing_tableName", trim(errorMessage, 3), + "regexplike", concat("%CCL-E-392-PRG_[0-9]+_[0-9]+\([^)]+\)[0-9]+:[0-9]+\{CCLEXCEPTION\(\)\}Exception\(100\):", + " cclutDefineMockTable\(\) - tableName is a required field.")) + + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_missing_tableName", mockTable, "") +end ;test_cclutDefineMockTable_missing_tableName + +/* test_cclutDefineMockTable_missing_columnNames ************************************************************ +* Scenario: Throws an error when an empty columnNames is supplied to the function (after trimming) * +************************************************************************************************************/ +subroutine test_cclutDefineMockTable_missing_columnNames(null) + call echo("~~~***~~~***test_cclutDefineMockTable_missing_columnNames***~~~***~~~") + + declare mockTable = vc with protect, noconstant("") + declare errorMessage = vc with protect, noconstant("") + declare errorCode = i4 with protect, noconstant(0) + set mockTable = + cclutDefineMockTable("sample_table", " ", "f8|vc|dq8") + + set errorCode = error(errorMessage, 0) + + call cclutAssertVcOperator(CURREF, "test_cclutDefineMockTable_missing_columnNames", trim(errorMessage, 3), + "regexplike", concat("%CCL-E-392-PRG_[0-9]+_[0-9]+\([^)]+\)[0-9]+:[0-9]+\{CCLEXCEPTION\(\)\}Exception\(100\):", + " cclutDefineMockTable\(\) - columnNames is a required field.")) + + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_missing_columnNames", mockTable, "") +end ;test_cclutDefineMockTable_missing_columnNames + +/* test_cclutDefineMockTable_missing_columnTypes ************************************************************ +* Scenario: Throws an error when an empty columnTypes is supplied to the function (after trimming) * +************************************************************************************************************/ +subroutine test_cclutDefineMockTable_missing_columnTypes(null) + call echo("~~~***~~~***test_cclutDefineMockTable_missing_columnTypes***~~~***~~~") + + declare mockTable = vc with protect, noconstant("") + declare errorMessage = vc with protect, noconstant("") + declare errorCode = i4 with protect, noconstant(0) + set mockTable = + cclutDefineMockTable("sample_table", "sample_table_id|sample_table_text|sample_table_date", " ") + + set errorCode = error(errorMessage, 0) + + call cclutAssertVcOperator(CURREF, "test_cclutDefineMockTable_missing_columnTypes", trim(errorMessage, 3), + "regexplike", concat("%CCL-E-392-PRG_[0-9]+_[0-9]+\([^)]+\)[0-9]+:[0-9]+\{CCLEXCEPTION\(\)\}Exception\(100\):", + " cclutDefineMockTable\(\) - columnTypes is a required field.")) + + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_missing_columnTypes", mockTable, "") +end ;test_cclutDefineMockTable_missing_columnTypes + +/* test_cclutDefineMockTable_mismatch_column_count ********************************************************** +* Scenario: Throws an error when the number of column names is different than the number of column types * +************************************************************************************************************/ +subroutine test_cclutDefineMockTable_mismatch_column_count(null) + call echo("~~~***~~~***test_cclutDefineMockTable_mismatch_column_count***~~~***~~~") + + declare mockTable = vc with protect, noconstant("") + declare errorMessage = vc with protect, noconstant("") + declare errorCode = i4 with protect, noconstant(0) + set mockTable = + cclutDefineMockTable("sample_table", "sample_table_id|sample_table_text|sample_table_date", "f8|vc") + + set errorCode = error(errorMessage, 0) + + call cclutAssertVcOperator(CURREF, "test_cclutDefineMockTable_mismatch_column_count", trim(errorMessage, 3), + "regexplike", concat("%CCL-E-392-PRG_[0-9]+_[0-9]+\([^)]+\)[0-9]+:[0-9]+\{CCLEXCEPTION\(\)\}Exception\(100\):", + " cclutDefineMockTable\(\) - columnTypes must match number of columnNames. columnNames Count: 3.*", + "columnTypes Count: 2.*.")) + + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_mismatch_column_count", mockTable, "") +end ;test_cclutDefineMockTable_mismatch_column_count + +/* test_cclutDefineMockTable_missing_column_name ************************************************************ +* Scenario: Throws an error if any of the individual column names are empty (after trimming) * +************************************************************************************************************/ +subroutine test_cclutDefineMockTable_missing_column_name(null) + call echo("~~~***~~~***test_cclutDefineMockTable_missing_column_name***~~~***~~~") + + declare mockTable = vc with protect, noconstant("") + declare errorMessage = vc with protect, noconstant("") + declare errorCode = i4 with protect, noconstant(0) + set mockTable = + cclutDefineMockTable("sample_table", "sample_table_id| |sample_table_date", "f8|vc|dq8") + + set errorCode = error(errorMessage, 0) + + call cclutAssertVcOperator(CURREF, "test_cclutDefineMockTable_missing_column_name", trim(errorMessage, 3), + "regexplike", concat("%CCL-E-392-PRG_[0-9]+_[0-9]+\([^)]+\)[0-9]+:[0-9]+\{CCLEXCEPTION\(\)\}Exception\(100\):", + " cclutDefineMockTable\(\) - Empty columnName found in columnNames. columnNames: ", + "SAMPLE_TABLE_ID| |SAMPLE_TABLE_DATE.")) + + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_missing_column_name", mockTable, "") +end ;test_cclutDefineMockTable_missing_column_name + +/* test_cclutDefineMockTable_missing_column_type ************************************************************ +* Scenario: Throws an error if any of the individual column types are empty (after trimming) * +************************************************************************************************************/ +subroutine test_cclutDefineMockTable_missing_column_type(null) + call echo("~~~***~~~***test_cclutDefineMockTable_missing_column_type***~~~***~~~") + + declare mockTable = vc with protect, noconstant("") + declare errorMessage = vc with protect, noconstant("") + declare errorCode = i4 with protect, noconstant(0) + set mockTable = + cclutDefineMockTable("sample_table", "sample_table_id|sample_table_text|sample_table_date", "f8| |dq8") + + set errorCode = error(errorMessage, 0) + + call cclutAssertVcOperator(CURREF, "test_cclutDefineMockTable_missing_column_type", trim(errorMessage, 3), + "regexplike", concat("%CCL-E-392-PRG_[0-9]+_[0-9]+\([^)]+\)[0-9]+:[0-9]+\{CCLEXCEPTION\(\)\}Exception\(100\):", + " cclutDefineMockTable\(\) - Empty columnType found in columnTypes. columnTypes: ", + "F8| |DQ8.")) + + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_missing_column_type", mockTable, "") +end ;test_cclutDefineMockTable_missing_column_type + +/* test_cclutDefineMockTable_duplicate_column_name ********************************************************** +* Scenario: Throws an error if any of the column names are duplicated (names are case-insensitive) * +************************************************************************************************************/ +subroutine test_cclutDefineMockTable_duplicate_column_name(null) + call echo("~~~***~~~***test_cclutDefineMockTable_duplicate_column_name***~~~***~~~") + + declare mockTable = vc with protect, noconstant("") + declare errorMessage = vc with protect, noconstant("") + declare errorCode = i4 with protect, noconstant(0) + set mockTable = + cclutDefineMockTable("sample_table", "sample_table_id|sample_table_text|sample_table_date|SAMPLE_table_text", + "f8|vc|dq8|vc") + + set errorCode = error(errorMessage, 0) + + call cclutAssertVcOperator(CURREF, "test_cclutDefineMockTable_duplicate_column_name", trim(errorMessage, 3), + "regexplike", concat("%CCL-E-392-PRG_[0-9]+_[0-9]+\([^)]+\)[0-9]+:[0-9]+\{CCLEXCEPTION\(\)\}Exception\(100\):", + " cclutDefineMockTable\(\) - Duplicate columnName found. columnName: SAMPLE_TABLE_TEXT")) + + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_duplicate_column_name", mockTable, "") +end ;test_cclutDefineMockTable_duplicate_column_name + +;********************************************************************************************************************************** +;** cclutAddMockConstraint +;********************************************************************************************************************************** +/* test_cclutAddMockConstraint_happy ************************************************************************ +* Scenario: Adds a mock constraint to a table that has already been defined with cclutDefineMockTable * +************************************************************************************************************/ +subroutine test_cclutAddMockConstraint_happy(null) + call echo("~~~***~~~***test_cclutAddMockConstraint_happy***~~~***~~~") + + call cclutDefineMockTable("sample_table", "sample_table_id|sample_table_text|sample_table_date", "f8|vc|dq8") + call cclutDefineMockTable("sample_table_2", "sample_table_2_id|sample_table_2_text|sample_table_2_date", + "f8|vc|dq8") + call cclutDefineMockTable("sample_table_3", "sample_table_3_id|sample_table_3_text|sample_table_3_date", + "f8|vc|dq8") + + call cclutAddMockConstraint("sample_table_2", "sample_table_2_text", "not null unique") + + call cclutAssertvcEqual(CURREF, "test_cclutAddMockConstraint_happy", + cclut_mockTables->tables[2].columns[2].columnConstraint, "NOT NULL UNIQUE") +end ;test_cclutAddMockConstraint_happy + +/* test_cclutAddMockConstraint_missing_tableName ************************************************************ +* Scenario: Throws an error when an empty tableName is supplied to the function (after trimming) * +************************************************************************************************************/ +subroutine test_cclutAddMockConstraint_missing_tableName(null) + call echo("~~~***~~~***test_cclutAddMockConstraint_missing_tableName***~~~***~~~") + + declare errorMessage = vc with protect, noconstant("") + declare errorCode = i4 with protect, noconstant(0) + call cclutAddMockConstraint(" ", "sample_table_text", "not null unique") + + set errorCode = error(errorMessage, 0) + + call cclutAssertVcOperator(CURREF, "test_cclutAddMockConstraint_missing_tableName", trim(errorMessage, 3), + "regexplike", concat("%CCL-E-392-PRG_[0-9]+_[0-9]+\([^)]+\)[0-9]+:[0-9]+\{CCLEXCEPTION\(\)\}Exception\(100\):", + " cclutAddMockConstraint\(\) - tableName is a required field.")) +end ;test_cclutAddMockConstraint_missing_tableName + +/* test_cclutAddMockConstraint_missing_columnName *********************************************************** +* Scenario: Throws an error when an empty columnName is supplied to the function (after trimming) * +************************************************************************************************************/ +subroutine test_cclutAddMockConstraint_missing_columnName(null) + call echo("~~~***~~~***test_cclutAddMockConstraint_missing_columnName***~~~***~~~") + + declare errorMessage = vc with protect, noconstant("") + declare errorCode = i4 with protect, noconstant(0) + call cclutAddMockConstraint("sample_table", " ", "not null unique") + + set errorCode = error(errorMessage, 0) + + call cclutAssertVcOperator(CURREF, "test_cclutAddMockConstraint_missing_columnName", trim(errorMessage, 3), + "regexplike", concat("%CCL-E-392-PRG_[0-9]+_[0-9]+\([^)]+\)[0-9]+:[0-9]+\{CCLEXCEPTION\(\)\}Exception\(100\):", + " cclutAddMockConstraint\(\) - columnName is a required field.")) +end ;test_cclutAddMockConstraint_missing_columnName + +/* test_cclutAddMockConstraint_unmocked_table *************************************************************** +* Scenario: Throws an error when the tableName specified has not been mocked through cclutDefineMockTable * +************************************************************************************************************/ +subroutine test_cclutAddMockConstraint_unmocked_table(null) + call echo("~~~***~~~***test_cclutAddMockConstraint_unmocked_table***~~~***~~~") + + declare errorMessage = vc with protect, noconstant("") + declare errorCode = i4 with protect, noconstant(0) + call cclutAddMockConstraint("sample_table", "sample_table_text", "not null unique") + + set errorCode = error(errorMessage, 0) + + call cclutAssertVcOperator(CURREF, "test_cclutAddMockConstraint_unmocked_table", trim(errorMessage, 3), + "regexplike", concat("%CCL-E-392-PRG_[0-9]+_[0-9]+\([^)]+\)[0-9]+:[0-9]+\{CCLEXCEPTION\(\)\}Exception\(100\):", + " cclutAddMockConstraint\(\) - tableName has not been mocked. tableName: SAMPLE_TABLE.")) +end ;test_cclutAddMockConstraint_unmocked_table + +/* test_cclutAddMockConstraint_created_table **************************************************************** +* Scenario: Throws an error when the tableName specified has already been created * +************************************************************************************************************/ +subroutine test_cclutAddMockConstraint_created_table(null) + call echo("~~~***~~~***test_cclutAddMockConstraint_created_table***~~~***~~~") + + call cclutDefineMockTable("sample_table", "sample_table_id|sample_table_text|sample_table_date", "f8|vc|dq8") + call cclutCreateMockTable("sample_table") + + declare errorMessage = vc with protect, noconstant("") + declare errorCode = i4 with protect, noconstant(0) + call cclutAddMockConstraint("sample_table", "sample_table_text", "not null unique") + + set errorCode = error(errorMessage, 0) + + call cclutAssertVcOperator(CURREF, "test_cclutAddMockConstraint_created_table", trim(errorMessage, 3), + "regexplike", concat("%CCL-E-392-PRG_[0-9]+_[0-9]+\([^)]+\)[0-9]+:[0-9]+\{CCLEXCEPTION\(\)\}Exception\(100\):", + " cclutAddMockConstraint\(\) - tableName has already been created. Constraints cannot be modified. ", + "tableName: SAMPLE_TABLE.")) +end ;test_cclutAddMockConstraint_created_table + +/* test_cclutAddMockConstraint_invalid_column *************************************************************** +* Scenario: Throws an error when the column is not a valid column on the mocked table * +************************************************************************************************************/ +subroutine test_cclutAddMockConstraint_invalid_column(null) + call echo("~~~***~~~***test_cclutAddMockConstraint_invalid_column***~~~***~~~") + + call cclutDefineMockTable("sample_table", "sample_table_id|sample_table_text|sample_table_date", "f8|vc|dq8") + + declare errorMessage = vc with protect, noconstant("") + declare errorCode = i4 with protect, noconstant(0) + call cclutAddMockConstraint("sample_table", "wrong_column", "not null unique") + + set errorCode = error(errorMessage, 0) + + call cclutAssertVcOperator(CURREF, "test_cclutAddMockConstraint_invalid_column", trim(errorMessage, 3), + "regexplike", concat("%CCL-E-392-PRG_[0-9]+_[0-9]+\([^)]+\)[0-9]+:[0-9]+\{CCLEXCEPTION\(\)\}Exception\(100\):", + " cclutAddMockConstraint\(\) - columnName is not mocked on table. columnName: WRONG_COLUMN ", + "tableName: SAMPLE_TABLE.")) +end ;test_cclutAddMockConstraint_invalid_column + +;********************************************************************************************************************************** +;** cclutAddMockIndex +;********************************************************************************************************************************** +/* test_cclutAddMockIndex_happy ***************************************************************************** +* Scenario: Adds a mock index to a table that has already been defined with cclutDefineMockTable * +************************************************************************************************************/ +subroutine test_cclutAddMockIndex_happy(null) + call echo("~~~***~~~***test_cclutAddMockIndex_happy***~~~***~~~") + + call cclutDefineMockTable("sample_table", "sample_table_id|sample_table_text|sample_table_date", "f8|vc|dq8") + call cclutDefineMockTable("sample_table_2", "sample_table_2_id|sample_table_2_text|sample_table_2_date", + "f8|vc|dq8") + call cclutDefineMockTable("sample_table_3", "sample_table_3_id|sample_table_3_text|sample_table_3_date", + "f8|vc|dq8") + + call cclutAddMockIndex("sample_table_2", "sample_table_2_id", 1) + call cclutAddMockIndex("sample_table_2", "sample_table_2_text|sample_table_2_id", 0) + + call cclutAsserti4Equal(CURREF, "test_cclutAddMockIndex_happy", size(cclut_mockTables->tables[2].indexes, 5), 2) + call cclutAssertvcEqual(CURREF, "test_cclutAddMockIndex_happy", cclut_mockTables->tables[2].indexes[1].indexColumns, + "SAMPLE_TABLE_2_ID") + call cclutAsserti4Equal(CURREF, "test_cclutAddMockIndex_happy", cclut_mockTables->tables[2].indexes[1].isUnique, 1) + call cclutAssertvcEqual(CURREF, "test_cclutAddMockIndex_happy", cclut_mockTables->tables[2].indexes[2].indexColumns, + "SAMPLE_TABLE_2_TEXT|SAMPLE_TABLE_2_ID") + call cclutAsserti4Equal(CURREF, "test_cclutAddMockIndex_happy", cclut_mockTables->tables[2].indexes[2].isUnique, 0) +end ;test_cclutAddMockIndex_happy + +/* test_cclutAddMockIndex_missing_tableName ***************************************************************** +* Scenario: Throws an error when an empty tableName is supplied to the function (after trimming) * +************************************************************************************************************/ +subroutine test_cclutAddMockIndex_missing_tableName(null) + call echo("~~~***~~~***test_cclutAddMockIndex_missing_tableName***~~~***~~~") + + declare errorMessage = vc with protect, noconstant("") + declare errorCode = i4 with protect, noconstant(0) + call cclutAddMockIndex(" ", "sample_table_id", 1) + + set errorCode = error(errorMessage, 0) + + call cclutAssertVcOperator(CURREF, "test_cclutAddMockIndex_missing_tableName", trim(errorMessage, 3), + "regexplike", concat("%CCL-E-392-PRG_[0-9]+_[0-9]+\([^)]+\)[0-9]+:[0-9]+\{CCLEXCEPTION\(\)\}Exception\(100\):", + " cclutAddMockIndex\(\) - tableName is a required field.")) +end ;test_cclutAddMockIndex_missing_tableName + +/* test_cclutAddMockIndex_missing_columnNames *************************************************************** +* Scenario: Throws an error when an empty columnNames is supplied to the function (after trimming) * +************************************************************************************************************/ +subroutine test_cclutAddMockIndex_missing_columnNames(null) + call echo("~~~***~~~***test_cclutAddMockIndex_missing_columnNames***~~~***~~~") + + declare errorMessage = vc with protect, noconstant("") + declare errorCode = i4 with protect, noconstant(0) + call cclutAddMockIndex("sample_table", " ", 1) + + set errorCode = error(errorMessage, 0) + + call cclutAssertVcOperator(CURREF, "test_cclutAddMockIndex_missing_columnNames", trim(errorMessage, 3), + "regexplike", concat("%CCL-E-392-PRG_[0-9]+_[0-9]+\([^)]+\)[0-9]+:[0-9]+\{CCLEXCEPTION\(\)\}Exception\(100\):", + " cclutAddMockIndex\(\) - columnNames is a required field.")) +end ;test_cclutAddMockIndex_missing_columnNames + +/* test_cclutAddMockIndex_unmocked_table ******************************************************************** +* Scenario: Throws an error when the tableName specified has not been mocked through cclutDefineMockTable * +************************************************************************************************************/ +subroutine test_cclutAddMockIndex_unmocked_table(null) + call echo("~~~***~~~***test_cclutAddMockIndex_unmocked_table***~~~***~~~") + + declare errorMessage = vc with protect, noconstant("") + declare errorCode = i4 with protect, noconstant(0) + call cclutAddMockIndex("sample_table", "sample_table_id", 1) + + set errorCode = error(errorMessage, 0) + + call cclutAssertVcOperator(CURREF, "test_cclutAddMockIndex_unmocked_table", trim(errorMessage, 3), + "regexplike", concat("%CCL-E-392-PRG_[0-9]+_[0-9]+\([^)]+\)[0-9]+:[0-9]+\{CCLEXCEPTION\(\)\}Exception\(100\):", + " cclutAddMockIndex\(\) - tableName has not been mocked. tableName: SAMPLE_TABLE.")) +end ;test_cclutAddMockIndex_unmocked_table + +/* test_cclutAddMockIndex_created_table ********************************************************************* +* Scenario: Throws an error when the tableName specified has already been created * +************************************************************************************************************/ +subroutine test_cclutAddMockIndex_created_table(null) + call echo("~~~***~~~***test_cclutAddMockIndex_created_table***~~~***~~~") + + call cclutDefineMockTable("sample_table", "sample_table_id|sample_table_text|sample_table_date", "f8|vc|dq8") + call cclutCreateMockTable("sample_table") + + declare errorMessage = vc with protect, noconstant("") + declare errorCode = i4 with protect, noconstant(0) + call cclutAddMockIndex("sample_table", "sample_table_id", 1) + + set errorCode = error(errorMessage, 0) + + call cclutAssertVcOperator(CURREF, "test_cclutAddMockIndex_created_table", trim(errorMessage, 3), + "regexplike", concat("%CCL-E-392-PRG_[0-9]+_[0-9]+\([^)]+\)[0-9]+:[0-9]+\{CCLEXCEPTION\(\)\}Exception\(100\):", + " cclutAddMockIndex\(\) - tableName has already been created. Indexes cannot be modified. ", + "tableName: SAMPLE_TABLE.")) +end ;test_cclutAddMockIndex_created_table + +/* test_cclutAddMockIndex_invalid_column ******************************************************************** +* Scenario: Throws an error when the column is not a valid column on the mocked table * +************************************************************************************************************/ +subroutine test_cclutAddMockIndex_invalid_column(null) + call echo("~~~***~~~***test_cclutAddMockIndex_invalid_column***~~~***~~~") + + call cclutDefineMockTable("sample_table", "sample_table_id|sample_table_text|sample_table_date", "f8|vc|dq8") + + declare errorMessage = vc with protect, noconstant("") + declare errorCode = i4 with protect, noconstant(0) + call cclutAddMockIndex("sample_table", "wrong_column", 1) + + set errorCode = error(errorMessage, 0) + + call cclutAssertVcOperator(CURREF, "test_cclutAddMockIndex_invalid_column", trim(errorMessage, 3), + "regexplike", concat("%CCL-E-392-PRG_[0-9]+_[0-9]+\([^)]+\)[0-9]+:[0-9]+\{CCLEXCEPTION\(\)\}Exception\(100\):", + " cclutAddMockIndex\(\) - columnName is not mocked on table. columnName: WRONG_COLUMN ", + "tableName: SAMPLE_TABLE.")) +end ;test_cclutAddMockIndex_invalid_column + +/* test_cclutAddMockIndex_duplicate_column_name ************************************************************* +* Scenario: Throws an error if any of the column names are duplicated (names are case-insensitive) * +************************************************************************************************************/ +subroutine test_cclutAddMockIndex_duplicate_column_name(null) + call echo("~~~***~~~***test_cclutAddMockIndex_duplicate_column_name***~~~***~~~") + + call cclutDefineMockTable("sample_table", "sample_table_id|sample_table_text|sample_table_date", "f8|vc|dq8") + + declare errorMessage = vc with protect, noconstant("") + declare errorCode = i4 with protect, noconstant(0) + call cclutAddMockIndex("sample_table", "sample_table_text|sample_table_id|sample_table_text", 1) + + set errorCode = error(errorMessage, 0) + + call cclutAssertVcOperator(CURREF, "test_cclutAddMockIndex_duplicate_column_name", trim(errorMessage, 3), + "regexplike", concat("%CCL-E-392-PRG_[0-9]+_[0-9]+\([^)]+\)[0-9]+:[0-9]+\{CCLEXCEPTION\(\)\}Exception\(100\):", + " cclutAddMockIndex\(\) - Duplicate columnName found. columnName: SAMPLE_TABLE_TEXT.")) +end ;test_cclutAddMockIndex_duplicate_column_name + +;********************************************************************************************************************************** +;** cclutCreateMockTable +;********************************************************************************************************************************** +/* test_cclutCreateMockTable_happy ************************************************************************** +* Scenario: Adds a mock table to the RDBMS with the values defined in cclutDefineMockTable * +************************************************************************************************************/ +subroutine test_cclutCreateMockTable_happy(null) + call echo("~~~***~~~***test_cclutCreateMockTable_happy***~~~***~~~") + + declare mockTable = vc with protect, noconstant("") + set mockTable = + cclutDefineMockTable("sample_table", "sample_table_id|sample_table_text|sample_table_date", "f8|vc|dq8") + call cclutCreateMockTable("sample_table") + call cclutAddMockData("sample_table", "1.0|test text|27-NOV-2018 08:00") + + declare mockId = f8 with protect, noconstant(0.0) + declare mockText = vc with protect, noconstant("") + declare mockDate = dq8 with protect, noconstant(0) + select into "nl:" + from (value(mockTable) m) + detail + mockId = m.SAMPLE_TABLE_ID + mockText = m.SAMPLE_TABLE_TEXT + mockDate = m.SAMPLE_TABLE_DATE + with nocounter + + call cclutAssertf8Equal(CURREF, "test_cclutCreateMockTable_happy", mockId, 1.0) + call cclutAssertvcEqual(CURREF, "test_cclutCreateMockTable_happy", mockText, "test text") + call cclutAssertf8Equal(CURREF, "test_cclutCreateMockTable_happy", mockDate, cnvtdatetime("27-NOV-2018 08:00")) +end ;test_cclutCreateMockTable_happy + +/* test_cclutCreateMockTable_missing_tableName ************************************************************** +* Scenario: Throws an error when an empty tableName is supplied to the function (after trimming) * +************************************************************************************************************/ +subroutine test_cclutCreateMockTable_missing_tableName(null) + call echo("~~~***~~~***test_cclutCreateMockTable_missing_tableName***~~~***~~~") + + declare errorMessage = vc with protect, noconstant("") + declare errorCode = i4 with protect, noconstant(0) + call cclutCreateMockTable(" ") + + set errorCode = error(errorMessage, 0) + + call cclutAssertVcOperator(CURREF, "test_cclutCreateMockTable_missing_tableName", trim(errorMessage, 3), + "regexplike", concat("%CCL-E-392-PRG_[0-9]+_[0-9]+\([^)]+\)[0-9]+:[0-9]+\{CCLEXCEPTION\(\)\}Exception\(100\):", + " cclutCreateMockTable\(\) - tableName is a required field.")) +end ;test_cclutCreateMockTable_missing_tableName + +/* test_cclutCreateMockTable_unmocked_table ***************************************************************** +* Scenario: Throws an error when the tableName specified has not been mocked through cclutDefineMockTable * +************************************************************************************************************/ +subroutine test_cclutCreateMockTable_unmocked_table(null) + call echo("~~~***~~~***test_cclutCreateMockTable_unmocked_table***~~~***~~~") + + declare errorMessage = vc with protect, noconstant("") + declare errorCode = i4 with protect, noconstant(0) + call cclutCreateMockTable("sample_table") + + set errorCode = error(errorMessage, 0) + + call cclutAssertVcOperator(CURREF, "test_cclutCreateMockTable_unmocked_table", trim(errorMessage, 3), + "regexplike", concat("%CCL-E-392-PRG_[0-9]+_[0-9]+\([^)]+\)[0-9]+:[0-9]+\{CCLEXCEPTION\(\)\}Exception\(100\):", + " cclutCreateMockTable\(\) - tableName has not been mocked. tableName: SAMPLE_TABLE.")) +end ;test_cclutCreateMockTable_unmocked_table + +/* test_cclutCreateMockTable_created_table ****************************************************************** +* Scenario: Does nothing if the table has already been created * +************************************************************************************************************/ +subroutine test_cclutCreateMockTable_created_table(null) + call echo("~~~***~~~***test_cclutCreateMockTable_created_table***~~~***~~~") + + declare mockTable = vc with protect, noconstant("") + set mockTable = + cclutDefineMockTable("sample_table", "sample_table_id|sample_table_text|sample_table_date", "f8|vc|dq8") + call cclutCreateMockTable("sample_table") + call cclutAddMockData("sample_table", "1.0|test text|27-NOV-2018 08:00") + + call cclutCreateMockTable("sample_table") + + declare mockId = f8 with protect, noconstant(0.0) + declare mockText = vc with protect, noconstant("") + declare mockDate = dq8 with protect, noconstant(0) + select into "nl:" + from (value(mockTable) m) + detail + mockId = m.SAMPLE_TABLE_ID + mockText = m.SAMPLE_TABLE_TEXT + mockDate = m.SAMPLE_TABLE_DATE + with nocounter + + call cclutAssertf8Equal(CURREF, "test_cclutCreateMockTable_happy", mockId, 1.0) + call cclutAssertvcEqual(CURREF, "test_cclutCreateMockTable_happy", mockText, "test text") + call cclutAssertf8Equal(CURREF, "test_cclutCreateMockTable_happy", mockDate, cnvtdatetime("27-NOV-2018 08:00")) +end ;test_cclutCreateMockTable_created_table + +;********************************************************************************************************************************** +;** cclutRemoveMockTable +;********************************************************************************************************************************** +/* test_cclutRemoveMockTable_happy ************************************************************************** +* Scenario: Removes a mock table that has not been created yet * +************************************************************************************************************/ +subroutine test_cclutRemoveMockTable_happy(null) + call echo("~~~***~~~***test_cclutRemoveMockTable_happy***~~~***~~~") + + declare mockTable = vc with protect, noconstant("") + set mockTable = + cclutDefineMockTable("sample_table", "sample_table_id|sample_table_text|sample_table_date", "f8|vc|dq8") + call cclutRemoveMockTable("sample_table") + + call cclutAsserti4Equal(CURREF, "test_cclutRemoveMockTable_happy", size(cclut_mockTables->tables, 5), 0) +end ;test_cclutRemoveMockTable_happy + +/* test_cclutRemoveMockTable_created_table ****************************************************************** +* Scenario: Removes a mock table that has been created yet and drops it from the RDBMS * +************************************************************************************************************/ +subroutine test_cclutRemoveMockTable_created_table(null) + call echo("~~~***~~~***test_cclutRemoveMockTable_created_table***~~~***~~~") + + declare mockTable = vc with protect, noconstant("") + set mockTable = + cclutDefineMockTable("sample_table", "sample_table_id|sample_table_text|sample_table_date", "f8|vc|dq8") + call cclutCreateMockTable("sample_table") + call cclutAddMockData("sample_table", "1.0|test text|27-NOV-2018 08:00") + + declare mockId = f8 with protect, noconstant(0.0) + declare mockText = vc with protect, noconstant("") + declare mockDate = dq8 with protect, noconstant(0) + select into "nl:" + from (value(mockTable) m) + detail + mockId = m.SAMPLE_TABLE_ID + mockText = m.SAMPLE_TABLE_TEXT + mockDate = m.SAMPLE_TABLE_DATE + with nocounter + + call cclutAssertf8Equal(CURREF, "test_cclutRemoveMockTable_created_table", mockId, 1.0) + call cclutAssertvcEqual(CURREF, "test_cclutRemoveMockTable_created_table", mockText, "test text") + call cclutAssertf8Equal(CURREF, "test_cclutRemoveMockTable_created_table", mockDate, + cnvtdatetime("27-NOV-2018 08:00")) + + call cclutRemoveMockTable("sample_table") + + select into "nl:" + from (value(mockTable) m) + detail + mockId = m.SAMPLE_TABLE_ID + mockText = m.SAMPLE_TABLE_TEXT + mockDate = m.SAMPLE_TABLE_DATE + with nocounter + + declare errorMessage = vc with protect, noconstant("") + declare errorCode = i4 with protect, noconstant(0) + set errorCode = error(errorMessage, 0) + + call cclutAssertVcOperator(CURREF, "test_cclutRemoveMockTable_created_table", trim(errorMessage, 3), + "regexplike", concat("%CCL-E-18-PRG_[0-9]+_[0-9]+\([^)]+\)[0-9]+:[0-9]+\{\}Unable to add range, definition for", + " table \(CUST_CCLUT_[^)]*\) not found in dictionary.")) + + call cclutAsserti4Equal(CURREF, "test_cclutRemoveMockTable_created_table", size(cclut_mockTables->tables, 5), 0) +end ;test_cclutRemoveMockTable_created_table + +/* test_cclutRemoveMockTable_missing_tableName ************************************************************** +* Scenario: Throws an error when an empty tableName is supplied to the function (after trimming) * +************************************************************************************************************/ +subroutine test_cclutRemoveMockTable_missing_tableName(null) + call echo("~~~***~~~***test_cclutRemoveMockTable_missing_tableName***~~~***~~~") + + declare errorMessage = vc with protect, noconstant("") + declare errorCode = i4 with protect, noconstant(0) + call cclutRemoveMockTable(" ") + + set errorCode = error(errorMessage, 0) + + call cclutAssertVcOperator(CURREF, "test_cclutRemoveMockTable_missing_tableName", trim(errorMessage, 3), + "regexplike", concat("%CCL-E-392-PRG_[0-9]+_[0-9]+\([^)]+\)[0-9]+:[0-9]+\{CCLEXCEPTION\(\)\}Exception\(100\):", + " cclutRemoveMockTable\(\) - tableName is a required field.")) +end ;test_cclutRemoveMockTable_missing_tableName + +;********************************************************************************************************************************** +;** cclutRemoveAllMockTables +;********************************************************************************************************************************** +/* test_cclutRemoveAllMockTables_happy ********************************************************************** +* Scenario: Removes all mock tables that have been mocked regardless of whether they have been created * +************************************************************************************************************/ +subroutine test_cclutRemoveAllMockTables_happy(null) + call echo("~~~***~~~***test_cclutRemoveAllMockTables_happy***~~~***~~~") + + call cclutDefineMockTable("sample_table", "sample_table_id|sample_table_text|sample_table_date", "f8|vc|dq8") + call cclutDefineMockTable("sample_table_2", "sample_table_2_id|sample_table_2_text|sample_table_2_date", + "f8|vc|dq8") + call cclutDefineMockTable("sample_table_3", "sample_table_3_id|sample_table_3_text|sample_table_3_date", + "f8|vc|dq8") + + call cclutAsserti4Equal(CURREF, "test_cclutRemoveAllMockTables_happy", size(cclut_mockTables->tables, 5), 3) + + call cclutRemoveAllMockTables(null) + + call cclutAsserti4Equal(CURREF, "test_cclutRemoveAllMockTables_happy", size(cclut_mockTables->tables, 5), 0) +end ;test_cclutRemoveAllMockTables_happy + +;********************************************************************************************************************************** +;** cclutAddMockData +;********************************************************************************************************************************** +/* test_cclutAddMockData_happy ****************************************************************************** +* Scenario: Adds the appropriate mock data to the table when the data has no escape characters or nulls * +************************************************************************************************************/ +subroutine test_cclutAddMockData_happy(null) + call echo("~~~***~~~***test_cclutAddMockData_happy***~~~***~~~") + + declare mockTable = vc with protect, noconstant("") + set mockTable = + cclutDefineMockTable("sample_table", "sample_table_id|sample_table_text|sample_table_date", "f8|vc|dq8") + call cclutCreateMockTable("sample_table") + call cclutAddMockData("sample_table", "1.0|test text|27-NOV-2018 08:00") + call cclutAddMockData("sample_table", "2.0|test \|text\\ 2|28-NOV-2018 09:00") + call cclutAddMockData("sample_table", "3.0|test text 3|29-NOV-2018 10:00") + + declare mockId = f8 with protect, noconstant(0.0) + declare mockText = vc with protect, noconstant("") + declare mockDate = dq8 with protect, noconstant(0) + select into "nl:" + from (value(mockTable) m) + where m.SAMPLE_TABLE_ID = 1.0 + detail + mockId = m.SAMPLE_TABLE_ID + mockText = m.SAMPLE_TABLE_TEXT + mockDate = m.SAMPLE_TABLE_DATE + with nocounter + + call cclutAssertf8Equal(CURREF, "test_cclutAddMockData_happy", mockId, 1.0) + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_happy", mockText, "test text") + call cclutAssertf8Equal(CURREF, "test_cclutAddMockData_happy", mockDate, cnvtdatetime("27-NOV-2018 08:00")) + + select into "nl:" + from (value(mockTable) m) + where m.SAMPLE_TABLE_ID = 2.0 + detail + mockId = m.SAMPLE_TABLE_ID + mockText = m.SAMPLE_TABLE_TEXT + mockDate = m.SAMPLE_TABLE_DATE + with nocounter + + call cclutAssertf8Equal(CURREF, "test_cclutAddMockData_happy", mockId, 2.0) + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_happy", mockText, "test |text\ 2") + call cclutAssertf8Equal(CURREF, "test_cclutAddMockData_happy", mockDate, cnvtdatetime("28-NOV-2018 09:00")) + + select into "nl:" + from (value(mockTable) m) + where m.SAMPLE_TABLE_ID = 3.0 + detail + mockId = m.SAMPLE_TABLE_ID + mockText = m.SAMPLE_TABLE_TEXT + mockDate = m.SAMPLE_TABLE_DATE + with nocounter + + call cclutAssertf8Equal(CURREF, "test_cclutAddMockData_happy", mockId, 3.0) + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_happy", mockText, "test text 3") + call cclutAssertf8Equal(CURREF, "test_cclutAddMockData_happy", mockDate, cnvtdatetime("29-NOV-2018 10:00")) +end ;test_cclutAddMockData_happy + +/* test_cclutAddMockData_empty_single_column **************************************************************** +* Scenario: Correctly handles adding an empty string to a table with a single column when rowData is empty * +************************************************************************************************************/ +subroutine test_cclutAddMockData_empty_single_column(null) + call echo("~~~***~~~***test_cclutAddMockData_empty_single_column***~~~***~~~") + + declare mockTable = vc with protect, noconstant("") + set mockTable = + cclutDefineMockTable("sample_table", "sample_table_text", "vc") + call cclutCreateMockTable("sample_table") + call cclutAddMockData("sample_table", "") + + declare mockText = vc with protect, noconstant("") + select into "nl:" + from (value(mockTable) m) + detail + mockText = m.SAMPLE_TABLE_TEXT + with nocounter + + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_empty_single_column", mockText, "") + + call cclutClearMockData("sample_table") + call cclutAddMockData("sample_table", " ") + + select into "nl:" + from (value(mockTable) m) + detail + mockText = m.SAMPLE_TABLE_TEXT + with nocounter + + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_empty_single_column", mockText, " ") +end ;test_cclutAddMockData_empty_single_column + +/* test_cclutAddMockData_empty_string_tests ***************************************************************** +* Scenario: Correctly handles empty strings regardless of where they are in the rowData parameter * +************************************************************************************************************/ +subroutine test_cclutAddMockData_empty_string_tests(null) + call echo("~~~***~~~***test_cclutAddMockData_empty_string_tests***~~~***~~~") + + declare mockTable = vc with protect, noconstant("") + set mockTable = + cclutDefineMockTable("sample_table", "sample_table_text_1|sample_table_text_2|sample_table_text_3", "vc|vc|vc") + call cclutCreateMockTable("sample_table") + call cclutAddMockData("sample_table", "|test|test 2") + + declare mockText1 = vc with protect, noconstant("") + declare mockText2 = vc with protect, noconstant("") + declare mockText3 = vc with protect, noconstant("") + select into "nl:" + from (value(mockTable) m) + detail + mockText1 = m.SAMPLE_TABLE_TEXT_1 + mockText2 = m.SAMPLE_TABLE_TEXT_2 + mockText3 = m.SAMPLE_TABLE_TEXT_3 + with nocounter + + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_empty_string_tests", mockText1, "") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_empty_string_tests", mockText2, "test") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_empty_string_tests", mockText3, "test 2") + + call cclutClearMockData("sample_table") + call cclutAddMockData("sample_table", "test||test 2") + + select into "nl:" + from (value(mockTable) m) + detail + mockText1 = m.SAMPLE_TABLE_TEXT_1 + mockText2 = m.SAMPLE_TABLE_TEXT_2 + mockText3 = m.SAMPLE_TABLE_TEXT_3 + with nocounter + + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_empty_string_tests", mockText1, "test") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_empty_string_tests", mockText2, "") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_empty_string_tests", mockText3, "test 2") + + call cclutClearMockData("sample_table") + call cclutAddMockData("sample_table", "test|test 2|") + + select into "nl:" + from (value(mockTable) m) + detail + mockText1 = m.SAMPLE_TABLE_TEXT_1 + mockText2 = m.SAMPLE_TABLE_TEXT_2 + mockText3 = m.SAMPLE_TABLE_TEXT_3 + with nocounter + + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_empty_string_tests", mockText1, "test") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_empty_string_tests", mockText2, "test 2") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_empty_string_tests", mockText3, "") + + call cclutClearMockData("sample_table") + call cclutAddMockData("sample_table", "||test") + + select into "nl:" + from (value(mockTable) m) + detail + mockText1 = m.SAMPLE_TABLE_TEXT_1 + mockText2 = m.SAMPLE_TABLE_TEXT_2 + mockText3 = m.SAMPLE_TABLE_TEXT_3 + with nocounter + + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_empty_string_tests", mockText1, "") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_empty_string_tests", mockText2, "") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_empty_string_tests", mockText3, "test") + + call cclutClearMockData("sample_table") + call cclutAddMockData("sample_table", "|test|") + + select into "nl:" + from (value(mockTable) m) + detail + mockText1 = m.SAMPLE_TABLE_TEXT_1 + mockText2 = m.SAMPLE_TABLE_TEXT_2 + mockText3 = m.SAMPLE_TABLE_TEXT_3 + with nocounter + + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_empty_string_tests", mockText1, "") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_empty_string_tests", mockText2, "test") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_empty_string_tests", mockText3, "") + + call cclutClearMockData("sample_table") + call cclutAddMockData("sample_table", "test||") + + select into "nl:" + from (value(mockTable) m) + detail + mockText1 = m.SAMPLE_TABLE_TEXT_1 + mockText2 = m.SAMPLE_TABLE_TEXT_2 + mockText3 = m.SAMPLE_TABLE_TEXT_3 + with nocounter + + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_empty_string_tests", mockText1, "test") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_empty_string_tests", mockText2, "") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_empty_string_tests", mockText3, "") + + call cclutClearMockData("sample_table") + call cclutAddMockData("sample_table", "||") + + select into "nl:" + from (value(mockTable) m) + detail + mockText1 = m.SAMPLE_TABLE_TEXT_1 + mockText2 = m.SAMPLE_TABLE_TEXT_2 + mockText3 = m.SAMPLE_TABLE_TEXT_3 + with nocounter + + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_empty_string_tests", mockText1, "") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_empty_string_tests", mockText2, "") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_empty_string_tests", mockText3, "") +end ;test_cclutAddMockData_empty_string_tests + +/* test_cclutAddMockData_backslash_tests ******************************************************************** +* Scenario: Correctly handles strings with backslashes * +************************************************************************************************************/ +subroutine test_cclutAddMockData_backslash_tests(null) + call echo("~~~***~~~***test_cclutAddMockData_backslash_tests***~~~***~~~") + + declare mockTable = vc with protect, noconstant("") + set mockTable = + cclutDefineMockTable("sample_table", "sample_table_text_1|sample_table_text_2|sample_table_text_3", "vc|vc|vc") + call cclutCreateMockTable("sample_table") + call cclutAddMockData("sample_table", "\\\\\\|test|test 2") + + declare mockText1 = vc with protect, noconstant("") + declare mockText2 = vc with protect, noconstant("") + declare mockText3 = vc with protect, noconstant("") + select into "nl:" + from (value(mockTable) m) + detail + mockText1 = m.SAMPLE_TABLE_TEXT_1 + mockText2 = m.SAMPLE_TABLE_TEXT_2 + mockText3 = m.SAMPLE_TABLE_TEXT_3 + with nocounter + + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_backslash_tests", mockText1, "\\\") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_backslash_tests", mockText2, "test") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_backslash_tests", mockText3, "test 2") + + call cclutClearMockData("sample_table") + call cclutAddMockData("sample_table", "test|\\\\\\|test 2") + + select into "nl:" + from (value(mockTable) m) + detail + mockText1 = m.SAMPLE_TABLE_TEXT_1 + mockText2 = m.SAMPLE_TABLE_TEXT_2 + mockText3 = m.SAMPLE_TABLE_TEXT_3 + with nocounter + + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_backslash_tests", mockText1, "test") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_backslash_tests", mockText2, "\\\") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_backslash_tests", mockText3, "test 2") + + call cclutClearMockData("sample_table") + call cclutAddMockData("sample_table", "test|test 2|\\\\\\") + + select into "nl:" + from (value(mockTable) m) + detail + mockText1 = m.SAMPLE_TABLE_TEXT_1 + mockText2 = m.SAMPLE_TABLE_TEXT_2 + mockText3 = m.SAMPLE_TABLE_TEXT_3 + with nocounter + + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_backslash_tests", mockText1, "test") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_backslash_tests", mockText2, "test 2") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_backslash_tests", mockText3, "\\\") + + call cclutClearMockData("sample_table") + call cclutAddMockData("sample_table", "\\\\\\|\\\\\\|test") + + select into "nl:" + from (value(mockTable) m) + detail + mockText1 = m.SAMPLE_TABLE_TEXT_1 + mockText2 = m.SAMPLE_TABLE_TEXT_2 + mockText3 = m.SAMPLE_TABLE_TEXT_3 + with nocounter + + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_backslash_tests", mockText1, "\\\") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_backslash_tests", mockText2, "\\\") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_backslash_tests", mockText3, "test") + + call cclutClearMockData("sample_table") + call cclutAddMockData("sample_table", "\\\\\\|test|\\\\\\") + + select into "nl:" + from (value(mockTable) m) + detail + mockText1 = m.SAMPLE_TABLE_TEXT_1 + mockText2 = m.SAMPLE_TABLE_TEXT_2 + mockText3 = m.SAMPLE_TABLE_TEXT_3 + with nocounter + + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_backslash_tests", mockText1, "\\\") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_backslash_tests", mockText2, "test") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_backslash_tests", mockText3, "\\\") + + call cclutClearMockData("sample_table") + call cclutAddMockData("sample_table", "test|\\\\\\|\\\\\\") + + select into "nl:" + from (value(mockTable) m) + detail + mockText1 = m.SAMPLE_TABLE_TEXT_1 + mockText2 = m.SAMPLE_TABLE_TEXT_2 + mockText3 = m.SAMPLE_TABLE_TEXT_3 + with nocounter + + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_backslash_tests", mockText1, "test") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_backslash_tests", mockText2, "\\\") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_backslash_tests", mockText3, "\\\") + + call cclutClearMockData("sample_table") + call cclutAddMockData("sample_table", "\\\\\\|\\\\\\|\\\\\\") + + select into "nl:" + from (value(mockTable) m) + detail + mockText1 = m.SAMPLE_TABLE_TEXT_1 + mockText2 = m.SAMPLE_TABLE_TEXT_2 + mockText3 = m.SAMPLE_TABLE_TEXT_3 + with nocounter + + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_backslash_tests", mockText1, "\\\") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_backslash_tests", mockText2, "\\\") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_backslash_tests", mockText3, "\\\") +end ;test_cclutAddMockData_backslash_tests + +/* test_cclutAddMockData_null_tests ************************************************************************* +* Scenario: Correctly handles strings with nulls * +************************************************************************************************************/ +subroutine test_cclutAddMockData_null_tests(null) + call echo("~~~***~~~***test_cclutAddMockData_null_tests***~~~***~~~") + + declare mockTable = vc with protect, noconstant("") + set mockTable = + cclutDefineMockTable("sample_table", "sample_table_text_1|sample_table_text_2|sample_table_text_3", "vc|vc|vc") + call cclutCreateMockTable("sample_table") + call cclutAddMockData("sample_table", "\null|test|test 2") + + declare mockNull1 = i4 with protect, noconstant(0) + declare mockNull2 = i4 with protect, noconstant(0) + declare mockNull3 = i4 with protect, noconstant(0) + declare mockText1 = vc with protect, noconstant("") + declare mockText2 = vc with protect, noconstant("") + declare mockText3 = vc with protect, noconstant("") + select into "nl:" + sampleTableText1Null = nullind(m.SAMPLE_TABLE_TEXT_1), + sampleTableText2Null = nullind(m.SAMPLE_TABLE_TEXT_2), + sampleTableText3Null = nullind(m.SAMPLE_TABLE_TEXT_3) + from (value(mockTable) m) + detail + mockNull1 = sampleTableText1Null + mockNull2 = sampleTableText2Null + mockNull3 = sampleTableText3Null + mockText2 = m.SAMPLE_TABLE_TEXT_2 + mockText3 = m.SAMPLE_TABLE_TEXT_3 + with nocounter + + call cclutAsserti4Equal(CURREF, "test_cclutAddMockData_null_tests", mockNull1, 1) + call cclutAsserti4Equal(CURREF, "test_cclutAddMockData_null_tests", mockNull2, 0) + call cclutAsserti4Equal(CURREF, "test_cclutAddMockData_null_tests", mockNull3, 0) + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_null_tests", mockText2, "test") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_null_tests", mockText3, "test 2") + + call cclutClearMockData("sample_table") + call cclutAddMockData("sample_table", "test|\null|test 2") + + select into "nl:" + sampleTableText1Null = nullind(m.SAMPLE_TABLE_TEXT_1), + sampleTableText2Null = nullind(m.SAMPLE_TABLE_TEXT_2), + sampleTableText3Null = nullind(m.SAMPLE_TABLE_TEXT_3) + from (value(mockTable) m) + detail + mockNull1 = sampleTableText1Null + mockNull2 = sampleTableText2Null + mockNull3 = sampleTableText3Null + mockText1 = m.SAMPLE_TABLE_TEXT_1 + mockText3 = m.SAMPLE_TABLE_TEXT_3 + with nocounter + + call cclutAsserti4Equal(CURREF, "test_cclutAddMockData_null_tests", mockNull1, 0) + call cclutAsserti4Equal(CURREF, "test_cclutAddMockData_null_tests", mockNull2, 1) + call cclutAsserti4Equal(CURREF, "test_cclutAddMockData_null_tests", mockNull3, 0) + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_null_tests", mockText1, "test") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_null_tests", mockText3, "test 2") + + call cclutClearMockData("sample_table") + call cclutAddMockData("sample_table", "test|test 2|\null") + + select into "nl:" + sampleTableText1Null = nullind(m.SAMPLE_TABLE_TEXT_1), + sampleTableText2Null = nullind(m.SAMPLE_TABLE_TEXT_2), + sampleTableText3Null = nullind(m.SAMPLE_TABLE_TEXT_3) + from (value(mockTable) m) + detail + mockNull1 = sampleTableText1Null + mockNull2 = sampleTableText2Null + mockNull3 = sampleTableText3Null + mockText1 = m.SAMPLE_TABLE_TEXT_1 + mockText2 = m.SAMPLE_TABLE_TEXT_2 + with nocounter + + call cclutAsserti4Equal(CURREF, "test_cclutAddMockData_null_tests", mockNull1, 0) + call cclutAsserti4Equal(CURREF, "test_cclutAddMockData_null_tests", mockNull2, 0) + call cclutAsserti4Equal(CURREF, "test_cclutAddMockData_null_tests", mockNull3, 1) + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_null_tests", mockText1, "test") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_null_tests", mockText2, "test 2") + + call cclutClearMockData("sample_table") + call cclutAddMockData("sample_table", "\null|\null|test") + + select into "nl:" + sampleTableText1Null = nullind(m.SAMPLE_TABLE_TEXT_1), + sampleTableText2Null = nullind(m.SAMPLE_TABLE_TEXT_2), + sampleTableText3Null = nullind(m.SAMPLE_TABLE_TEXT_3) + from (value(mockTable) m) + detail + mockNull1 = sampleTableText1Null + mockNull2 = sampleTableText2Null + mockNull3 = sampleTableText3Null + mockText3 = m.SAMPLE_TABLE_TEXT_3 + with nocounter + + call cclutAsserti4Equal(CURREF, "test_cclutAddMockData_null_tests", mockNull1, 1) + call cclutAsserti4Equal(CURREF, "test_cclutAddMockData_null_tests", mockNull2, 1) + call cclutAsserti4Equal(CURREF, "test_cclutAddMockData_null_tests", mockNull3, 0) + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_null_tests", mockText3, "test") + + call cclutClearMockData("sample_table") + call cclutAddMockData("sample_table", "\null|test|\null") + + select into "nl:" + sampleTableText1Null = nullind(m.SAMPLE_TABLE_TEXT_1), + sampleTableText2Null = nullind(m.SAMPLE_TABLE_TEXT_2), + sampleTableText3Null = nullind(m.SAMPLE_TABLE_TEXT_3) + from (value(mockTable) m) + detail + mockNull1 = sampleTableText1Null + mockNull2 = sampleTableText2Null + mockNull3 = sampleTableText3Null + mockText2 = m.SAMPLE_TABLE_TEXT_2 + with nocounter + + call cclutAsserti4Equal(CURREF, "test_cclutAddMockData_null_tests", mockNull1, 1) + call cclutAsserti4Equal(CURREF, "test_cclutAddMockData_null_tests", mockNull2, 0) + call cclutAsserti4Equal(CURREF, "test_cclutAddMockData_null_tests", mockNull3, 1) + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_null_tests", mockText2, "test") + + call cclutClearMockData("sample_table") + call cclutAddMockData("sample_table", "test|\null|\null") + + select into "nl:" + sampleTableText1Null = nullind(m.SAMPLE_TABLE_TEXT_1), + sampleTableText2Null = nullind(m.SAMPLE_TABLE_TEXT_2), + sampleTableText3Null = nullind(m.SAMPLE_TABLE_TEXT_3) + from (value(mockTable) m) + detail + mockNull1 = sampleTableText1Null + mockNull2 = sampleTableText2Null + mockNull3 = sampleTableText3Null + mockText1 = m.SAMPLE_TABLE_TEXT_1 + with nocounter + + call cclutAsserti4Equal(CURREF, "test_cclutAddMockData_null_tests", mockNull1, 0) + call cclutAsserti4Equal(CURREF, "test_cclutAddMockData_null_tests", mockNull2, 1) + call cclutAsserti4Equal(CURREF, "test_cclutAddMockData_null_tests", mockNull3, 1) + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_null_tests", mockText1, "test") + + call cclutClearMockData("sample_table") + call cclutAddMockData("sample_table", "\null|\null|\null") + + select into "nl:" + sampleTableText1Null = nullind(m.SAMPLE_TABLE_TEXT_1), + sampleTableText2Null = nullind(m.SAMPLE_TABLE_TEXT_2), + sampleTableText3Null = nullind(m.SAMPLE_TABLE_TEXT_3) + from (value(mockTable) m) + detail + mockNull1 = sampleTableText1Null + mockNull2 = sampleTableText2Null + mockNull3 = sampleTableText3Null + with nocounter + + call cclutAsserti4Equal(CURREF, "test_cclutAddMockData_null_tests", mockNull1, 1) + call cclutAsserti4Equal(CURREF, "test_cclutAddMockData_null_tests", mockNull2, 1) + call cclutAsserti4Equal(CURREF, "test_cclutAddMockData_null_tests", mockNull3, 1) +end ;test_cclutAddMockData_null_tests + +/* test_cclutAddMockData_missing_tableName ****************************************************************** +* Scenario: Throws an error when an empty tableName is supplied to the function (after trimming) * +************************************************************************************************************/ +subroutine test_cclutAddMockData_missing_tableName(null) + call echo("~~~***~~~***test_cclutAddMockData_missing_tableName***~~~***~~~") + + declare errorMessage = vc with protect, noconstant("") + declare errorCode = i4 with protect, noconstant(0) + call cclutAddMockData(" ", "1.0|test text|27-NOV-2018 08:00") + + set errorCode = error(errorMessage, 0) + + call cclutAssertVcOperator(CURREF, "test_cclutAddMockData_missing_tableName", trim(errorMessage, 3), + "regexplike", concat("%CCL-E-392-PRG_[0-9]+_[0-9]+\([^)]+\)[0-9]+:[0-9]+\{CCLEXCEPTION\(\)\}Exception\(100\):", + " cclutAddMockData\(\) - tableName is a required field.")) +end ;test_cclutAddMockData_missing_tableName + +/* test_cclutAddMockData_unmocked_table ********************************************************************* +* Scenario: Throws an error when the tableName specified has not been mocked through cclutDefineMockTable * +************************************************************************************************************/ +subroutine test_cclutAddMockData_unmocked_table(null) + call echo("~~~***~~~***test_cclutAddMockData_unmocked_table***~~~***~~~") + + declare errorMessage = vc with protect, noconstant("") + declare errorCode = i4 with protect, noconstant(0) + call cclutAddMockData("sample_table", "1.0|test text|27-NOV-2018 08:00") + + set errorCode = error(errorMessage, 0) + + call cclutAssertVcOperator(CURREF, "test_cclutAddMockData_unmocked_table", trim(errorMessage, 3), + "regexplike", concat("%CCL-E-392-PRG_[0-9]+_[0-9]+\([^)]+\)[0-9]+:[0-9]+\{CCLEXCEPTION\(\)\}Exception\(100\):", + " cclutAddMockData\(\) - tableName has not been mocked. tableName: SAMPLE_TABLE.")) +end ;test_cclutAddMockData_unmocked_table + +/* test_cclutAddMockData_uncreated_table ******************************************************************** +* Scenario: Throws an error when the tableName specified has not been created through cclutCreateMockTable * +************************************************************************************************************/ +subroutine test_cclutAddMockData_uncreated_table(null) + call echo("~~~***~~~***test_cclutAddMockData_uncreated_table***~~~***~~~") + + call cclutDefineMockTable("sample_table", "sample_table_id|sample_table_text|sample_table_date", "f8|vc|dq8") + + declare errorMessage = vc with protect, noconstant("") + declare errorCode = i4 with protect, noconstant(0) + call cclutAddMockData("sample_table", "1.0|test text|27-NOV-2018 08:00") + + set errorCode = error(errorMessage, 0) + + call cclutAssertVcOperator(CURREF, "test_cclutAddMockData_uncreated_table", trim(errorMessage, 3), + "regexplike", concat("%CCL-E-392-PRG_[0-9]+_[0-9]+\([^)]+\)[0-9]+:[0-9]+\{CCLEXCEPTION\(\)\}Exception\(100\):", + " cclutAddMockData\(\) - tableName has not been created. tableName: SAMPLE_TABLE.")) +end ;test_cclutAddMockData_uncreated_table + +/* test_cclutAddMockData_too_many_columns ******************************************************************* +* Scenario: Throws an error when there are more columns in the rowData than are defined for the table * +************************************************************************************************************/ +subroutine test_cclutAddMockData_too_many_columns(null) + call echo("~~~***~~~***test_cclutAddMockData_too_many_columns***~~~***~~~") + + call cclutDefineMockTable("sample_table", "sample_table_id|sample_table_text|sample_table_date", "f8|vc|dq8") + call cclutCreateMockTable("sample_table") + + declare errorMessage = vc with protect, noconstant("") + declare errorCode = i4 with protect, noconstant(0) + call cclutAddMockData("sample_table", "1.0|test text|27-NOV-2018 08:00|extra") + + set errorCode = error(errorMessage, 0) + + call cclutAssertVcOperator(CURREF, "test_cclutAddMockData_too_many_columns", trim(errorMessage, 3), + "regexplike", concat("%CCL-E-392-PRG_[0-9]+_[0-9]+\([^)]+\)[0-9]+:[0-9]+\{CCLEXCEPTION\(\)\}Exception\(100\):", + " cclutParseColumn\(\) - Too many columns of data added to table. tableName: SAMPLE_TABLE.")) +end ;test_cclutAddMockData_too_many_columns + +/* test_cclutAddMockData_too_few_columns ******************************************************************** +* Scenario: Throws an error when there are fewer columns in the rowData than are defined for the table * +************************************************************************************************************/ +subroutine test_cclutAddMockData_too_few_columns(null) + call echo("~~~***~~~***test_cclutAddMockData_too_few_columns***~~~***~~~") + + call cclutDefineMockTable("sample_table", "sample_table_id|sample_table_text|sample_table_date", "f8|vc|dq8") + call cclutCreateMockTable("sample_table") + + declare errorMessage = vc with protect, noconstant("") + declare errorCode = i4 with protect, noconstant(0) + call cclutAddMockData("sample_table", "1.0|test text") + + set errorCode = error(errorMessage, 0) + + call cclutAssertVcOperator(CURREF, "test_cclutAddMockData_too_few_columns", trim(errorMessage, 3), + "regexplike", concat("%CCL-E-392-PRG_[0-9]+_[0-9]+\([^)]+\)[0-9]+:[0-9]+\{CCLEXCEPTION\(\)\}Exception\(100\):", + " cclutParseColumn\(\) - Too few columns of data. rowData: 1.0|test text.")) +end ;test_cclutAddMockData_too_many_columns + +/* test_cclutAddMockData_invalid_escape_sequence ************************************************************ +* Scenario: Throws an error when the sequence after the escape character is not valid per the API * +************************************************************************************************************/ +subroutine test_cclutAddMockData_invalid_escape_sequence(null) + call echo("~~~***~~~***test_cclutAddMockData_invalid_escape_sequence***~~~***~~~") + + call cclutDefineMockTable("sample_table", "sample_table_id|sample_table_text|sample_table_date", "f8|vc|dq8") + call cclutCreateMockTable("sample_table") + + declare errorMessage = vc with protect, noconstant("") + declare errorCode = i4 with protect, noconstant(0) + call cclutAddMockData("sample_table", "1.0|\a|27-NOV-2018 08:00") + + set errorCode = error(errorMessage, 0) + + call cclutAssertVcOperator(CURREF, "test_cclutAddMockData_invalid_escape_sequence", trim(errorMessage, 3), + "regexplike", concat("%CCL-E-392-PRG_[0-9]+_[0-9]+\([^)]+\)[0-9]+:[0-9]+\{CCLEXCEPTION\(\)\}Exception\(100\):", + " cclutAddMockData\(\) - Invalid escape sequence. rowData: 1.0|\a|27-NOV-2018 08:00.")) +end ;test_cclutAddMockData_invalid_escape_sequence + +/* test_cclutAddMockData_invalid_null *********************************************************************** +* Scenario: Throws an error if the null escape sequence is not by itself in a column * +************************************************************************************************************/ +subroutine test_cclutAddMockData_invalid_null(null) + call echo("~~~***~~~***test_cclutAddMockData_invalid_null***~~~***~~~") + + call cclutDefineMockTable("sample_table", "sample_table_id|sample_table_text|sample_table_date", "f8|vc|dq8") + call cclutCreateMockTable("sample_table") + + declare errorMessage = vc with protect, noconstant("") + declare errorCode = i4 with protect, noconstant(0) + call cclutAddMockData("sample_table", "1.0|\nulla|27-NOV-2018 08:00") + + set errorCode = error(errorMessage, 0) + + call cclutAssertVcOperator(CURREF, "test_cclutAddMockData_invalid_null", trim(errorMessage, 3), + "regexplike", concat("%CCL-E-392-PRG_[0-9]+_[0-9]+\([^)]+\)[0-9]+:[0-9]+\{CCLEXCEPTION\(\)\}Exception\(100\):", + " cclutAddMockData\(\) - \null column must have no other characters.", + " rowData: 1.0|\nulla|27-NOV-2018 08:00.")) +end ;test_cclutAddMockData_invalid_null + +;********************************************************************************************************************************** +;** cclutClearMockData +;********************************************************************************************************************************** +/* test_cclutClearMockData_happy **************************************************************************** +* Scenario: Clears all data from the mock table but does not drop the table (essentially a truncate) * +************************************************************************************************************/ +subroutine test_cclutClearMockData_happy(null) + call echo("~~~***~~~***test_cclutClearMockData_happy***~~~***~~~") + + declare mockTable = vc with protect, noconstant("") + set mockTable = + cclutDefineMockTable("sample_table", "sample_table_id|sample_table_text|sample_table_date", "f8|vc|dq8") + call cclutCreateMockTable("sample_table") + call cclutAddMockData("sample_table", "1.0|test text|27-NOV-2018 08:00") + call cclutAddMockData("sample_table", "2.0|test text 2|28-NOV-2018 09:00") + call cclutAddMockData("sample_table", "3.0|test text 3|29-NOV-2018 10:00") + + declare tableCount = i4 with protect, noconstant(0) + + select into "nl:" + totalCount = count(*) + from (value(mockTable) m) + head report + tableCount = totalCount + with nocounter + + call cclutAsserti4Equal(CURREF, "test_cclutClearMockData_happy", tableCount, 3) + + call cclutClearMockData("sample_table") + + select into "nl:" + totalCount = count(*) + from (value(mockTable) m) + head report + tableCount = totalCount + with nocounter + + call cclutAsserti4Equal(CURREF, "test_cclutClearMockData_happy", tableCount, 0) +end ;test_cclutClearMockData_happy + +/* test_cclutClearMockData_missing_tableName **************************************************************** +* Scenario: Throws an error when an empty tableName is supplied to the function (after trimming) * +************************************************************************************************************/ +subroutine test_cclutClearMockData_missing_tableName(null) + call echo("~~~***~~~***test_cclutClearMockData_missing_tableName***~~~***~~~") + + declare errorMessage = vc with protect, noconstant("") + declare errorCode = i4 with protect, noconstant(0) + call cclutClearMockData(" ") + + set errorCode = error(errorMessage, 0) + + call cclutAssertVcOperator(CURREF, "test_cclutClearMockData_missing_tableName", trim(errorMessage, 3), + "regexplike", concat("%CCL-E-392-PRG_[0-9]+_[0-9]+\([^)]+\)[0-9]+:[0-9]+\{CCLEXCEPTION\(\)\}Exception\(100\):", + " cclutClearMockData\(\) - tableName is a required field.")) +end ;test_cclutClearMockData_missing_tableName + +/* test_cclutClearMockData_unmocked_table ******************************************************************* +* Scenario: Throws an error when the tableName specified has not been mocked through cclutDefineMockTable * +************************************************************************************************************/ +subroutine test_cclutClearMockData_unmocked_table(null) + call echo("~~~***~~~***test_cclutClearMockData_unmocked_table***~~~***~~~") + + declare errorMessage = vc with protect, noconstant("") + declare errorCode = i4 with protect, noconstant(0) + call cclutClearMockData("sample_table") + + set errorCode = error(errorMessage, 0) + + call cclutAssertVcOperator(CURREF, "test_cclutClearMockData_unmocked_table", trim(errorMessage, 3), + "regexplike", concat("%CCL-E-392-PRG_[0-9]+_[0-9]+\([^)]+\)[0-9]+:[0-9]+\{CCLEXCEPTION\(\)\}Exception\(100\):", + " cclutClearMockData\(\) - tableName has not been mocked. tableName: SAMPLE_TABLE.")) +end ;test_cclutClearMockData_unmocked_table + +/* test_cclutClearMockData_uncreated_table ****************************************************************** +* Scenario: Throws an error when the tableName specified has not been created through cclutCreateMockTable * +************************************************************************************************************/ +subroutine test_cclutClearMockData_uncreated_table(null) + call echo("~~~***~~~***test_cclutClearMockData_uncreated_table***~~~***~~~") + + call cclutDefineMockTable("sample_table", "sample_table_id|sample_table_text|sample_table_date", "f8|vc|dq8") + + declare errorMessage = vc with protect, noconstant("") + declare errorCode = i4 with protect, noconstant(0) + call cclutClearMockData("sample_table") + + set errorCode = error(errorMessage, 0) + + call cclutAssertVcOperator(CURREF, "test_cclutClearMockData_uncreated_table", trim(errorMessage, 3), + "regexplike", concat("%CCL-E-392-PRG_[0-9]+_[0-9]+\([^)]+\)[0-9]+:[0-9]+\{CCLEXCEPTION\(\)\}Exception\(100\):", + " cclutClearMockData\(\) - tableName has not been created. tableName: SAMPLE_TABLE.")) +end ;test_cclutClearMockData_uncreated_table \ No newline at end of file diff --git a/cclunit-framework-tests/pom.xml b/cclunit-framework-tests/pom.xml index a139b35..1c1dac7 100644 --- a/cclunit-framework-tests/pom.xml +++ b/cclunit-framework-tests/pom.xml @@ -3,7 +3,7 @@ com.cerner.ccl cclunit-framework-parent - 3.0 + 3.1-SNAPSHOT .. cclunit-framework-tests diff --git a/cclunit-framework-tests/src/test/resources/META-INF/spring/applicationContext-cclutTests.xml b/cclunit-framework-tests/src/test/resources/META-INF/spring/applicationContext-cclutTests.xml index 8736b39..88b714a 100644 --- a/cclunit-framework-tests/src/test/resources/META-INF/spring/applicationContext-cclutTests.xml +++ b/cclunit-framework-tests/src/test/resources/META-INF/spring/applicationContext-cclutTests.xml @@ -8,7 +8,7 @@ http://www.springframework.org/schema/context http://www.springframework.org/sch - + @@ -20,7 +20,7 @@ http://www.springframework.org/schema/context http://www.springframework.org/sch - + @@ -32,7 +32,7 @@ http://www.springframework.org/schema/context http://www.springframework.org/sch - + diff --git a/pom.xml b/pom.xml index 5c6d55b..e4099eb 100644 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ 4.0.0 com.cerner.ccl cclunit-framework-parent - 3.0 + 3.1-SNAPSHOT CCL Testing Framework Reactor Build Reactor build for the CCL Testing Framework pom From 68c67498f51fe8ab24072579890d8ce75083af4d Mon Sep 17 00:00:00 2001 From: cernertrevor Date: Tue, 29 Jan 2019 12:04:02 -0600 Subject: [PATCH 2/7] First batch of changes based on code review comments. --- cclunit-framework-source/doc/CCLUTGUIDANCE.md | 338 ++++++ cclunit-framework-source/doc/CCLUTMOCKING.md | 125 +- .../src/main/resources/cclut_compile_subs.inc | 2 + .../src/main/resources/cclut_utils.inc | 30 + .../src/main/resources/cclutmock.inc | 82 +- .../src/main/resources/cclutmock_table.inc | 774 +++++++------ ...cclut_execute_program_with_mocks_happy.prg | 84 -- ...cclut_execute_program_with_mocks_happy.prg | 81 ++ .../test/ccl/ut_cclut_execute_test_case.inc | 130 +-- .../ccl/ut_cclut_execute_test_case_file.inc | 130 +-- .../src/test/ccl/ut_cclut_mock.inc | 439 +++---- .../src/test/ccl/ut_cclut_mock_table.inc | 1008 +++++++++-------- .../src/test/ccl/ut_cclut_utils.inc | 32 + .../spring/applicationContext-cclutTests.xml | 6 +- 14 files changed, 1869 insertions(+), 1392 deletions(-) create mode 100644 cclunit-framework-source/doc/CCLUTGUIDANCE.md create mode 100644 cclunit-framework-source/src/main/resources/cclut_utils.inc delete mode 100644 cclunit-framework-source/src/test/ccl/cclut_execute_program_with_mocks_happy.prg create mode 100644 cclunit-framework-source/src/test/ccl/ut_cclut_execute_program_with_mocks_happy.prg create mode 100644 cclunit-framework-source/src/test/ccl/ut_cclut_utils.inc diff --git a/cclunit-framework-source/doc/CCLUTGUIDANCE.md b/cclunit-framework-source/doc/CCLUTGUIDANCE.md new file mode 100644 index 0000000..5ef0133 --- /dev/null +++ b/cclunit-framework-source/doc/CCLUTGUIDANCE.md @@ -0,0 +1,338 @@ +# CCL Unit Guidance + +## Building Unit Tests + +Before there can be unit testing, there must be units. The ultimate goal is to have small, testable, modular units and to test each of them individually. The goal of this guidance is to describe a way to structure a CCL script that supports testing its units individually. It will not discuss how to create units or unit testable code as there are many other sources that go into that detail. + +Say our CCL script contains a testable unit "functionX" that we want to test in some particular scenario, "scenarioY". Then we will create and execute a unit test named something like "testFunctionXForScenarioY". We want our test to execute functionX and the descendants of functionX. We do not want it to execute any other functions in our script. Here is how to go about it. + +First off, namespace every subroutine with the PUBLIC namespace. Then put all (most all) of the executable code for the script into a main function, say public::main(null) = null +Use a unique namespace to define an override for the main subroutine within the test suite, say testFunctionXForScenarioY::main(null) = null, and have the override first set up the conditions for scenarioY and then have it call functionX directly. + +The key point here is that the script does not contain a lot of loose code that gets executed every time the script executes. It all gets bundled into the main subroutine which is what allows a unit test to dictate exactly how much of the script's code will be executed. + +Here is an illustration of the concept: +``` +;; this is the test +;;; testFunctionB::main is the workhorse. It will be called instead of public::main because of the curnamespace + +/** +* Confirms that functionB returns "functionBTest" when it is passed "Test" +* and "functionBSubroutine" when it is passed "Subroutine". +*/ +subroutine (testFunctionB(null) = null) + + execute the_script:dba with curnamespace = "testFunctionB" + +end + +subroutine (testFunctionB::main(null) = null) + declare b_string = vc with protect, noconstant("") + + set b_string = functionB("Test") + set stat = cclutAssertVCEquals(CURREF, "testFunctionB Test", b_string, "functionBTest") + + set b_string = functionB("Subroutine") + set stat = cclutAssertVCEquals(CURREF, "testFunctionB Subroutine", b_string, "functionBSubroutine") +end;;;testFunctionB + +;; this is the script to be tested + +drop program the_script:dba go +create program the_script:dba + + record reply ( +%i cclsource:status_block.inc + ) + + subroutine (PUBLIC::functionA(id = f8) = vc) + call echo("functionA") + ;;; do stuff + return("functionA") + end + + subroutine (PUBLIC::functionB(name = vc) = vc) + call echo("functionB") + ;;; do stuff + return(concat("functionB", name)) + end + + subroutine (PUBLIC::functionC(null) = null) + call echo("functionC") + ;;; do stuff + call functionD(null) + end + + subroutine (PUBLIC::functionD(null) = null) + call echo("functionD") + end + + ;;; observe that subroutine main deserves to be tested in its own right with all other functions mocked. + subroutine(PUBLIC::main(null) = null) + declare a_string = vc with protect, noconstant("") + declare b_string = vc with protect, noconstant("") + set a_string = functionA(1.0) + set b_string = functionB(a_string) + call functionC(null) + end + + call main(null) + +#exit_script + ;; script finalizer code can go here + ;; a PUBLIC::exitScript(null) subroutine that encapsulates this work could be created and called + ;; if it does something that should occur for some unit tests. +end go + +``` + +Be careful! There is a small problem if you structure all of your scripts using this pattern and you test a function in one script that calls another script that isn't mocked by your test. Try the following example to understand what can go wrong: + +``` +drop program callstackA go +create program callstackA +subroutine (public::main(null) = null with private) + call echo("callstackA's main") +end + call main(null) + execute callstackB +end go + +drop program callstackB go +create program callstackB +subroutine (public::main(null) = null with private) + call echo("callstackB's main") +end + call main(null) + execute callstackC +end go + +drop program callstackC go +create program callstackC +subroutine (public::main(null) = null with private) + call echo("callstackC's main") +end + call main(null) +end go + +drop program callstack go +create program callstack + subroutine (callstack::main(null) = null with protect) + call echo("callstack's main") + end + + execute callstackA with curnamespace = 'callstack' +end go +``` + +If you execute callstackA directly, each program calls the correct main function. That's because each program gravitates to the copy of main that is in the closest scope, i.e., the one it declared for itself. + +If you execute call stack, each program calls the override. That is because when the namespace is forced, there is only one copy of callstack::main to choose from and since the forced namespace propagates to descendants, all the programs are forced to chose it. + +There are many ways to circumvent it. One is to always mock any descendant programs. Another is to use unique function names rather than generic ones. The script script_X could name its main function public::script_x_main, for example. Since script names are limited to 32 characters and subroutine names can be resolved to at least 40 characters, this will work, but another option still is to use "with replace". An example can be seen below: + +``` +drop program callstackA go +create program callstackA +subroutine (public::main(null) = null with private) + call echo("callstackA's main") +end + call main(null) + execute callstackB +end go + +drop program callstackB go +create program callstackB +subroutine (public::main(null) = null with private) + call echo("callstackB's main") +end + call main(null) + execute callstackC +end go + +drop program callstackC go +create program callstackC +subroutine (public::main(null) = null with private) + call echo("callstackC's main") +end + call main(null) +end go + +drop program callstack go +create program callstack + subroutine (public::callstackmain(null) = null with protect) + call echo("callstack's main") + end + + execute callstackA with replace("MAIN", callstackmain) +end go +``` + +This works because "with replace" does not propagate to descendant scripts by default (though an option is available to do so). Additionally, the CCL Unit Testing framework contains a mocking API that abstracts the "with replace" logic. See the documentation for cclutAddMockImplementation at [CCLUTMOCKING.md](../CCLUTMOCKING.md) + +## CCL Mocks + +In general, there are two ways to mock objects in CCL unit tests: + +1. Use "with replace" +2. Use "with curnamespace" + + 2a. Add the PUBLIC namespace to the real thing. Use an alternate namespace to define an override. Execute the script using 'with curnamespace = "\"' + + 2b. In practice, it is convenient to use the name of the test case for the alternate namespace. + +Generally speaking, use "with replace" to mock things that are defined outside the script (CCL subroutines, UARs, other scripts), and use "with curnamespace" to mock things defined within the script. + +The CCL Unit Testing framework also supports an abstraction for creating mocks. The purpose is to help make it easier to define mock tables and other mock objects to be used when executing a script. Details on the API can be found at [CCLUTMOCKING.md](../CCLUTMOCKING.md) + +Below are some examples using the CCL Unit Testing framework's mocking API. These examples assume the script under test is called "the_script" and executes a program called "other_script". They test for scenarios where other_script returns 0 items, more than 5 items, and a failed ("F") status. + +``` +;;; put the following script definition in a .prg file in src/test/ccl + + +drop program mock_other_script go +create program mock_other_script + free record reply + set stat = copyrec(mock_other_script_reply, reply, 1) +end go + +;;; put the following functions in a test suite (.inc) in src/test/ccl + +/** +* Test myFunction when other_script returns zero items +*/ +subroutine (testMyFunctionOtherScriptZero(null) = null) + record mock_other_script_reply ( + 1 qual [*] + 2 id = f8 +%i cclsource:status_block.inc + ) with protect + + set mock_other_script_reply->status_data->status = "Z" + + call cclutAddMockImplementation("OTHER_SCRIPT", "mock_other_script") + call cclutExecuteProgramWithMocks("the_script", "") + + ;assert things here +end ;;;testMyFunctionZero + +/** +* Test myFunction when other_script returns more than five items +*/ +subroutine (testMyFunctionOtherScriptMoreThanTen(null) = null) + record mock_other_script_reply ( + 1 qual [*] + 2 id = f8 +%i cclsource:status_block.inc + ) with protect + + set mock_other_script_reply->status_data->status = "S" + set stat = alterlist(mock_other_script_reply->qual, 6) + + declare idx = i4 with protect, noconstant(0) + for (idx = 1 to 6) + set mock_other_script_reply->qual[idx].id = idx + endfor + + call cclutAddMockImplementation("OTHER_SCRIPT", "mock_other_script") + call cclutExecuteProgramWithMocks("the_script", "") + + ;assert things here +end ;;;testMyFunctionMoreThanTen + +/** +* Test myFunction when other_script fails +*/ +subroutine (testMyFunctionOtherScriptFail(null) = null) + record mock_other_script_reply ( + 1 qual [*] + 2 id = f8 +%i cclsource:status_block.inc + ) with protect + + set mock_other_script_reply->status_data->status = "F" + + call cclutAddMockImplementation("OTHER_SCRIPT", "mock_other_script") + call cclutExecuteProgramWithMocks("the_script", "") + + ;assert things here +end ;;;testMyFunctionOtherScriptFail +``` + +There are other variations on this. For example, you could put asserts within mock_other_script itself. Additionally, other_script might generate its own reply structure, so you would want to do the same in mock_other_script. + +Below is an example where the mock script calls a validation subroutine defined from the testing subroutine. It tests that other_script is called exactly 3 times with the correct parameters each time. + +``` +;;; here is the script + +drop program the_script go +create program the_script + execute other_script 4, 5 + execute other_script 3, 2 + execute other_script 0, 1 +end go + + +;;; put this definition in a .prg file in src/test/ccl + +drop program mock_other_script go +create program mock_other_script + prompt "param 1", "param 2" with param1, param2 + + set otherScriptCallCount = otherScriptCallCount + 1 + call validateOtherScriptParams($param1, $param2) +end go + +;;; put this functions in a test suite (.inc) in src/test/ccl + +/** +* confirms that the script executes other_script exactly three times passing in (4, 5) then (3, 2) then (0, 1) +*/ +subroutine (testOtherScriptCalledThreeTimes(null) = null) + declare otherScriptCallCount = i4 with protect, noconstant(0) + + call cclutAddMockImplementation("OTHER_SCRIPT", "mock_other_script") + call cclutExecuteProgramWithMocks("the_script", "") + + set stat = cclutAssertI4Equal(CURREF, "testMyFunction_6_9 a", otherScriptCallCount, 3) +end ;;;testMyFunctionZero + +subroutine (validateOtherScriptParams(p1 = i4, p2 = i4) = null) + case (otherScriptCallCount) + of 1: + set stat = cclutAssertI4Equal(CURREF, "validateOtherScriptParams 1 a", p1, 4) + set stat = cclutAssertI4Equal(CURREF, "validateOtherScriptParams 1 b", p2, 5) + of 2: + set stat = cclutAssertI4Equal(CURREF, "validateOtherScriptParams 2 a", p1, 3) + set stat = cclutAssertI4Equal(CURREF, "validateOtherScriptParams 2 b", p2, 2) + of 3: + set stat = cclutAssertI4Equal(CURREF, "validateOtherScriptParams 3 a", p1, 0) + set stat = cclutAssertI4Equal(CURREF, "validateOtherScriptParams 3 b", p2, 1) + endcase +end ;;;validateOtherScriptParams +``` + +Finally, a namespace example where getPersonName will always return the same value. + +``` +/** +* Executes a test knowing that every call to getPersonName(id) will return "Bob Marley". +*/ +subroutine (testGetNameReturnsBobMarley(null) = null) + declare otherScriptCallCount = i4 with protect, noconstant(0) + + call cclutExecuteProgramWithMocks("the_script", "", "testGetNameReturnsBobMarley") + + ; assert stuff here +end +subroutine (testGetNameReturnsBobMarley::getPersonName(id = f8) = vc) + return ("Bob Marley") +end ;;;testGetNameReturnsBobMarley +``` + +## Commit/Rollback Guidance + +"commit" and "rollback" are keywords within CCL that apply the respective commands to the RDBMS. This can be particularly annoying when dealing with real tables, especially if one is testing insert/update/delete functionality. The table mocking API helps mitigate this by using separate custom tables, but it may still be advantageous to separate any usages of commit/rollback into their own subroutines and test them independently of the other tests. + diff --git a/cclunit-framework-source/doc/CCLUTMOCKING.md b/cclunit-framework-source/doc/CCLUTMOCKING.md index 2a24166..5b1624c 100644 --- a/cclunit-framework-source/doc/CCLUTMOCKING.md +++ b/cclunit-framework-source/doc/CCLUTMOCKING.md @@ -4,11 +4,28 @@ ## API +**cclutExecuteProgramWithMocks(programName = vc, params = vc, namespace = vc)** + +Executes a CCL program applying an indicated namespace and all mocks that have been specified using the functions +described below. programName is required. params is a stringified representation of the parameters to be passed to the +program, so all commas and string delimiters must be specified. If namespace is omitted, it will default to the PUBLIC +namespace. Additionally, to execute the program with specific "with replace()" functionality (e.g. record structures), +call cclutAddMockImplementation with the Name_From as originalName and Name_To as replaceName prior to calling +cclutExecuteProgramWithMocks. + +@param programName +    The program to be executed with mocks. +@param params +    The parameters to be sent to the program. +@param namespace +    The namespace under which to execute the program. + +Example: +call cclutExecuteProgramWithMocks("ccl_my_program", "\^MINE^, 1.0, ^string parameter^", "MYNAMESPACE") + **cclutDefineMockTable(tableName = vc, fieldNames = vc, fieldTypes = vc)** -Defines a mock table structure that can be created for use within a program. This is the first function to be called in the process of mocking a table. It must be called before cclutAddMockIndex(), cclutAddMockConstraint(), and -cclutCreateMockTable() can be called. The table will not be mocked in cclutExecuteProgramWithMocks() unless -cclutCreateMockTable() is called. tableName, columnNames, and columnTypes are required. columnNames and columnTypes are expected to be pipe-delimited strings. The columnTypes should have the same count as columnNames and be in the same order. +Defines a mock table structure that can be created for use within a program. This is the first function to be called in the process of mocking a table. It must be called before cclutAddMockIndex(), cclutAddMockConstraint(), and cclutCreateMockTable() can be called. The table will not be mocked in cclutExecuteProgramWithMocks() unless cclutCreateMockTable() is called. This function can be called for the same table after cclutCreateMockTable() in order to redefine it; however, the existing mocked table will be dropped and cclutCreateMockTable() will need to be called again to recreate it with the new defintion. tableName, columnNames, and columnTypes are required. columnNames and columnTypes are expected to be pipe-delimited strings. The columnTypes should have the same count as columnNames and be in the same order. @param tableName     The table to be mocked. @@ -28,7 +45,7 @@ Adds a constraint to a mock table. The table must already be defined through cc https://wiki.cerner.com/display/public/1101discernHP/SELECT+INTO+TABLE+Table_Name+Using+Discern+Explorer @param tableName -    The table to which the constraint will be added. +    The name of the source table for the mock table to which the constraint will be added. @param columnName     The column to which the constraint will be applied. @param columnConstraint @@ -39,36 +56,36 @@ call cclutAddMockConstraint("person", "name_last", "not null unique") **cclutAddMockIndex(tableName = vc, columnNames = vc, isUnique = i4)** -Adds an index to a mock table. The table must already be defined through cclutDefineMockTable(), otherwise an error will be thrown. This function may not be called after cclutCreateMockTable(). tableName, columnNames, and isUnique are required. columnNames may be a single column name or a pipe-delimited list of columns for a composite index (the order of the columns will be the order of the index). If isUnique is 1, then a unique index will be created. If isUnique is 0, then a non-unique index will be created. +Adds an index to a mock table. The table must already be defined through cclutDefineMockTable(), otherwise an error will be thrown. This function may not be called after cclutCreateMockTable(). tableName, columnNames, and isUnique are required. columnNames may be a single column name or a pipe-delimited list of columns for a composite index (the order of the columns will be the order of the index). If isUnique is TRUE, then a unique index will be created. If isUnique is FALSE, then a non-unique index will be created. @param tableName -    The table to which the index will be added. +    The name of the source table for the mock table to which the index will be added. @param columnNames     A pipe-delimited string of column names for the index. @param isUnique -    1 to create a unique index; 0 to create a non-unique index +    TRUE to create a unique index; FALSE to create a non-unique index Example: -call cclutAddMockIndex("person", "person_id", 1) -call cclutAddMockIndex("person", "name_last|name_first", 0) +call cclutAddMockIndex("person", "person_id", TRUE) +call cclutAddMockIndex("person", "name_last|name_first", FALSE) **cclutCreateMockTable(tableName = vc)** -Creates the mock table. The table must already be defined through cclutDefineMockTable(), otherwise an error will be thrown. If the table has already been created, the function will return silently. tableName is required. +Creates a mock table. The table must already be defined through cclutDefineMockTable(), otherwise an error will be thrown. If the table has already been created, the function will return silently. tableName is required. @param tableName -    The table to be mocked. +    The name of the source table to be mocked. Example: call cclutCreateMockTable("person") **cclutRemoveMockTable(tableName = vc)** -Removes the mock table. If the table was already created, it will also be dropped. If the table is not currently +Removes a mock table. If the table was already created, it will also be dropped. If the table is not currently mocked, it will return silently. tableName is required. @param tableName -    The table that is mocked. +    The name of the source table that is mocked. Example: call cclutRemoveMockTable("person") @@ -90,9 +107,9 @@ Supported escape values \null = null (no value will be inserted into the column) @param tableName -    The table to which the data will be added. +    The name of the source table for the mock table to which the data will be added. @param rowData -    A pipe-delimited string of data to be inserted into the table. +    A pipe-delimited string of data to be inserted into the mock table. Example: call cclutDefineMockTable("person", "person_id|name_last|name_first|birth_dt_tm", "f8|vc|vc|dq8") @@ -108,7 +125,7 @@ Clears all data from the mock table. This is functionally similar to a truncate must have been created through cclutCreateMockTable() or else an error will be thrown. @param tableName -    The table to be cleared. +    The name of the source table for the mock table to be cleared. Example: call cclutClearMockData("person") @@ -142,13 +159,6 @@ Removes all mock implementations. Example: call cclutRemoveAllMockImplementations(null) -**cclutExecuteProgramWithMocks(programName = vc, params = vc, namespace = vc)** - -Executes a program with all mocks currently added through cclutAddMockImplementation() and cclutCreateMockTable(). programName is required. params is a string parameter to be sent directly to the program, so all commas and string delimiters must be specified. If namespace is omitted, it will default to the PUBLIC namespace. - -Example: -call cclutExecuteProgramWithMocks("ccl_my_program", "\^MINE^, 1.0, ^string parameter^", "MYNAMESPACE") - **cclutRemoveAllMocks** Removes all mock implementations and mock tables that have been added through the cclutAddMockImplementation() and cclutCreateMockTable() APIs. This should be called at the completion of a test suite to clean up all mocks. @@ -157,23 +167,27 @@ Example: call cclutRemoveAllMocks(null) ## Implementation Notes -1. cclutRemoveAllMocks should be called as part of the teardown for all tests. The framework will attempt to clean up any outstanding mocks, but it is good practice to explicitly remove any mocks to ensure that no mocked tables remain in the Oracle instance. +1. For consistency, all mocking functions normalize names (tables, subroutines, records, etc.) to be uppercase. This matches with CCL and Oracle. + +2. cclutRemoveAllMocks should be called as part of the teardown for all tests. The framework will attempt to clean up any outstanding mocks, but it is good practice to explicitly remove any mocks to ensure that no mocked tables remain in the Oracle instance. -2. The mocked items created through cclutCreateMockTable() and cclutAddMockImplementation will not be applied to children script called from the script-under-test. Some alternatives would be to mock the child script to return the appropriate data or to mock the child script to execute the real script applying the mocked tables and implementations. +3. Tables can be mocked even if the table does not exist in the domain where the test is run. The mocked version will be used when executing programs with executeProgramWithMocks. This can be useful to test tables that do not formally exist yet. -3. The mocked items created through cclutCreateMockTable() and cclutAddMockImplementation will not be applied to statements executed through "call parser()" commands. An alternative would be to mock the parser() call to validate the correct information is supplied, then perform the appropriate mock versions of the actions the statement would normally perform. +4. The mocked items created through cclutCreateMockTable() and cclutAddMockImplementation will not be applied to child scripts called from the script-under-test. Some alternatives would be to mock the child script to return the appropriate data or to mock the child script to execute the real script applying the mocked tables and implementations. -4. The mocking API calls cannot be used from reportwriter sections. Alternatives would be dependent on the use-case, but take, for example, a dummyt used with a record structure and a call to cclutAddMockData within the detail section in order to add data based on a record structure. Instead, a FOR loop construct could be leveraged outside the context of a reportwriter section to iterate over the record structure. +5. The mocked items created through cclutCreateMockTable() and cclutAddMockImplementation will not be applied to statements executed through "call parser()" commands. One alternative would be to separate the parser string generation into separate subroutines and mock the subroutines to return parser strings using the mocked entity names. Another alternative would be to mock the parser() call to validate the correct information is supplied, then perform the appropriate mock versions of the actions the statement would normally perform. -5. Mocking record structures with a call to tdbexecute is unsupported under certain conditions, specifically if a call to free the record structure is made just prior to calling tdbexecute. If the scenario is truly necessary for a test, the best alternative is to separate the freeing of the record structure and the call to tdbexecute in different subroutines and test the subroutines independently of each other. +6. The table mocking APIs are not supported when called from within a reportwriter section. It might be tempting to use a dummyt query to set up mock data from a record structure, but various mocking calls such as cclutCreateMockTable, cclutRemoveMockTable and cclutAddMockData cannot be executed within the context of a query (because the implementations execute queries). Use a for loop instead. + +7. Mocking the tdbexecute "reply_to" entity is unsupported under certain conditions, specifically if a call to free the "reply_to" entity is made just prior to calling tdbexecute. If the scenario is truly necessary for a test, the best alternative is to define and use a subroutine for freeing the "reply_to" entity within the script and use a mock for that subroutine which does not actually perform the freeing of the "reply_to" entity. ## Example Below is an example of some of the APIs available in the CCL Unit Mocking framework along with some simple notes. Script-under-test: - drop program cclut_get_persons:dba go - create program cclut_get_persons:dba + drop program 1abc_mo_get_persons:dba go + create program 1abc_mo_get_persons:dba declare newSize = i4 with protect, noconstant(0) @@ -195,19 +209,19 @@ Script-under-test: Test Code: - declare mockTable = vc with protect, noconstant("") + declare mock_table_person = vc with protect, noconstant("") - ; Defining a mock person table. The return value is the name of the mockTable. + ; Defining a mock person table. The return value is the name of the mocked table. ; This can be useful to perform a select on the table after the script-under-test is complete ; to verify (among other things) that an insert or a delete worked correctly. - set mockTable = cclutDefineMockTable("person", "person_id|name_last|name_first|birth_dt_tm", + set mock_table_person = cclutDefineMockTable("person", "person_id|name_last|name_first|birth_dt_tm", "f8|vc|vc|dq8") ; Add a constraint that the person_id cannot be null call cclutAddMockConstraint("person", "person_id", "not null") ; Add a non-unique index to name_last - call cclutAddMockIndex("person", "name_last", 0) + call cclutAddMockIndex("person", "name_last", FALSE) ; Creates the mock table. After this, it is available for DML statements. call cclutCreateMockTable("person") @@ -218,7 +232,7 @@ Test Code: call cclutAddMockData("person", "3.0|Jefferson|\null|03-MAR-1972 22:22") ;Will add Jefferson (no first name) call cclutAddMockData("person", "4.0|Madison||04-APR-1973 10:33") ;Will add Madison (empty string for first name) - record mock_reply ( + record agp_reply ( 1 persons[*] 2 person_id = f8 2 name_last = vc @@ -226,43 +240,44 @@ Test Code: 2 birth_dt_tm = dq8 ) with protect - ; Replace the reply references with mock_reply - call cclutAddMockImplementation("REPLY", "MOCK_REPLY") + ; Have with replace("REPLY", AGP_REPLY) be applied when executing 1abc_mo_get_persons. + call cclutAddMockImplementation("REPLY", "AGP_REPLY") ; Execute the script-under-test - call cclutExecuteProgramWithMocks("cclut_get_persons", "") + call cclutExecuteProgramWithMocks("1abc_mo_get_persons", "") ; Do validation - call cclutAssertf8Equal(CURREF, "test_get_people_happy", mock_reply->persons[1].person_id, 1.0) - call cclutAssertvcEqual(CURREF, "test_get_people_happy", mock_reply->persons[1].name_last, + call cclutAssertf8Equal(CURREF, "test_get_people_happy 001", agp_reply->persons[1].person_id, 1.0) + call cclutAssertvcEqual(CURREF, "test_get_people_happy 002", agp_reply->persons[1].name_last, "Washington") - call cclutAssertvcEqual(CURREF, "test_get_people_happy", mock_reply->persons[1].name_first, + call cclutAssertvcEqual(CURREF, "test_get_people_happy 003", agp_reply->persons[1].name_first, "George") - call cclutAssertf8Equal(CURREF, "test_get_people_happy", mock_reply->persons[1].birth_dt_tm, + call cclutAssertf8Equal(CURREF, "test_get_people_happy 004", agp_reply->persons[1].birth_dt_tm, cnvtdatetime("01-JAN-1970 00:00")) - call cclutAssertf8Equal(CURREF, "test_get_people_happy", mock_reply->persons[2].person_id, 2.0) - call cclutAssertvcEqual(CURREF, "test_get_people_happy", mock_reply->persons[2].name_last, + call cclutAssertf8Equal(CURREF, "test_get_people_happy 005", agp_reply->persons[2].person_id, 2.0) + call cclutAssertvcEqual(CURREF, "test_get_people_happy 006", agp_reply->persons[2].name_last, "Adams") - call cclutAssertvcEqual(CURREF, "test_get_people_happy", mock_reply->persons[2].name_first, + call cclutAssertvcEqual(CURREF, "test_get_people_happy 007", agp_reply->persons[2].name_first, "John") - call cclutAssertf8Equal(CURREF, "test_get_people_happy", mock_reply->persons[2].birth_dt_tm, + call cclutAssertf8Equal(CURREF, "test_get_people_happy 008", agp_reply->persons[2].birth_dt_tm, cnvtdatetime("02-FEB-1971 11:11")) - call cclutAssertf8Equal(CURREF, "test_get_people_happy", mock_reply->persons[3].person_id, 3.0) - call cclutAssertvcEqual(CURREF, "test_get_people_happy", mock_reply->persons[3].name_last, + call cclutAssertf8Equal(CURREF, "test_get_people_happy 009", agp_reply->persons[3].person_id, 3.0) + call cclutAssertvcEqual(CURREF, "test_get_people_happy 010", agp_reply->persons[3].name_last, "Jefferson") - call cclutAssertvcEqual(CURREF, "test_get_people_happy", mock_reply->persons[3].name_first, + call cclutAssertvcEqual(CURREF, "test_get_people_happy 011", agp_reply->persons[3].name_first, "") - call cclutAssertf8Equal(CURREF, "test_get_people_happy", mock_reply->persons[3].birth_dt_tm, + call cclutAssertf8Equal(CURREF, "test_get_people_happy 012", agp_reply->persons[3].birth_dt_tm, cnvtdatetime("03-MAR-1972 22:22")) - call cclutAssertf8Equal(CURREF, "test_get_people_happy", mock_reply->persons[4].person_id, 4.0) - call cclutAssertvcEqual(CURREF, "test_get_people_happy", mock_reply->persons[4].name_last, + call cclutAssertf8Equal(CURREF, "test_get_people_happy 013", agp_reply->persons[4].person_id, 4.0) + call cclutAssertvcEqual(CURREF, "test_get_people_happy 014", agp_reply->persons[4].name_last, "Madison") - call cclutAssertvcEqual(CURREF, "test_get_people_happy", mock_reply->persons[4].name_first, + call cclutAssertvcEqual(CURREF, "test_get_people_happy 015", agp_reply->persons[4].name_first, "") - call cclutAssertf8Equal(CURREF, "test_get_people_happy", mock_reply->persons[4].birth_dt_tm, + call cclutAssertf8Equal(CURREF, "test_get_people_happy 016", agp_reply->persons[4].birth_dt_tm, cnvtdatetime("04-APR-1973 10:33")) - call cclutRemoveAllMocks(null) \ No newline at end of file + call cclutRemoveAllMocks(null) + \ No newline at end of file diff --git a/cclunit-framework-source/src/main/resources/cclut_compile_subs.inc b/cclunit-framework-source/src/main/resources/cclut_compile_subs.inc index 2fc6aef..4d330e9 100644 --- a/cclunit-framework-source/src/main/resources/cclut_compile_subs.inc +++ b/cclunit-framework-source/src/main/resources/cclut_compile_subs.inc @@ -80,6 +80,8 @@ subroutine cclut::generateTestCaseProgram( col 0 value row+1 value = concat("create program ", cclutProgramName) col 0 value row+1 + value = "%i cclsource:cclut_utils.inc" + col 0 value row+1 value = "%i cclsource:cclutassert_impl_nff.inc" col 0 value row+1 value = "%i cclsource:cclut_error_handling.inc" diff --git a/cclunit-framework-source/src/main/resources/cclut_utils.inc b/cclunit-framework-source/src/main/resources/cclut_utils.inc new file mode 100644 index 0000000..d34d1e4 --- /dev/null +++ b/cclunit-framework-source/src/main/resources/cclut_utils.inc @@ -0,0 +1,30 @@ +%#ifndef CCLUT_UTILS_INC +%#def CCLUT_UTILS_INC +;********************************************************************************************************************************** +; +; Provides utility functions that can be leveraged by the rest of the CCL Unit Testing framework in order to perform common +; operations. +; +;********************************************************************************************************************************** + +declare cclut::cclutIsEmpty(cclutText = vc) = i2 with protect + +/** +Checks a vc value to determine if it is an empty string or only contains whitespace/control characters. Returns TRUE if +the string meets the criteria or FALSE if it does not. + +@param cclutText + A vc value to be checked. +@returns + TRUE if the string is empty or only contains whitespace/control characters; otherwise, FALSE. + +Example: +call cclut::cclutIsEmpty("test") ; returns FALSE +call cclut::cclutIsEmpty("") ; returns TRUE +call cclut::cclutIsEmpty(" ") ; returns TRUE +**/ +subroutine cclut::cclutIsEmpty(cclutText) + return (evaluate(textlen(trim(cclutText, 3)), 0, TRUE, FALSE)) +end ;cclutIsEmpty + +%#endif CCLUT_UTILS_INC diff --git a/cclunit-framework-source/src/main/resources/cclutmock.inc b/cclunit-framework-source/src/main/resources/cclutmock.inc index e8004c1..44fac68 100644 --- a/cclunit-framework-source/src/main/resources/cclutmock.inc +++ b/cclunit-framework-source/src/main/resources/cclutmock.inc @@ -9,11 +9,11 @@ %i cclsource:cclutmock_table.inc -declare cclutAddMockImplementation(originalName = vc(val), replaceName = vc(val)) = null with protect -declare cclutRemoveMockImplementation(originalName = vc(val)) = null with protect +declare cclutAddMockImplementation(cclutOriginalName = vc(val), cclutReplaceName = vc(val)) = null with protect +declare cclutRemoveMockImplementation(cclutOriginalName = vc(val)) = null with protect declare cclutRemoveAllMockImplementations(null) = null with protect -declare cclutExecuteProgramWithMocks(programName = vc(val), params = vc(val), - namespace = vc(val, "PUBLIC")) = null with protect +declare cclutExecuteProgramWithMocks(cclutProgramName = vc(val), cclutParams = vc(val), + cclutNamespace = vc(val, "PUBLIC")) = null with protect declare cclutRemoveAllMocks(null) = null with protect record cclut_mockImplementations ( @@ -35,22 +35,22 @@ the mock will be overwritten with the new replaceName. Example: call cclutAddMockImplementation("uar_get_code_by", "mock_uar_get_code_by") **/ -subroutine cclutAddMockImplementation(originalName, replaceName) - ;Declare local variables - declare CCLUT_ORIGINAL_NAME = vc with protect, constant(trim(cnvtupper(originalName), 3)) - declare CCLUT_REPLACE_NAME = vc with protect, constant(trim(cnvtupper(replaceName), 3)) +subroutine cclutAddMockImplementation(cclutOriginalName, cclutReplaceName) + declare CCLUT_ORIGINAL_NAME = vc with protect, constant(cnvtupper(cclutOriginalName)) + declare CCLUT_REPLACE_NAME = vc with protect, constant(cnvtupper(cclutReplaceName)) declare cclutMockImplementationLength = i4 with protect, noconstant(size(cclut_mockImplementations->implementations, 5)) declare cclutMockImplementationPos = i4 with protect, noconstant(0) declare cclutMockImplementationIndex = i4 with protect, noconstant(0) ;Validate inbound parameters - if (CCLUT_ORIGINAL_NAME <= " ") + if (cclut::cclutIsEmpty(CCLUT_ORIGINAL_NAME)) call cclexception(100, "E", "cclutAddMockImplementation() - originalName is a required field") return endif - if (CCLUT_REPLACE_NAME <= " ") - call cclexception(100, "E", "cclutAddMockImplementation() - replaceName is a required field") + if (cclut::cclutIsEmpty(CCLUT_REPLACE_NAME)) + call cclexception(100, "E", concat("cclutAddMockImplementation(", CCLUT_ORIGINAL_NAME, + ") - replaceName is a required field")) return endif @@ -76,16 +76,15 @@ Removes a mock implementation. Example: call cclutRemoveMockImplementation("uar_get_code_by") **/ -subroutine cclutRemoveMockImplementation(originalName) - ;Declare local variables - declare CCLUT_ORIGINAL_NAME = vc with protect, constant(trim(cnvtupper(originalName), 3)) +subroutine cclutRemoveMockImplementation(cclutOriginalName) + declare CCLUT_ORIGINAL_NAME = vc with protect, constant(cnvtupper(cclutOriginalName)) declare cclutMockImplementationLength = i4 with protect, noconstant(size(cclut_mockImplementations->implementations, 5)) declare cclutMockImplementationPos = i4 with protect, noconstant(0) declare cclutMockImplementationIndex = i4 with protect, noconstant(0) ;Validate inbound parameters - if (CCLUT_ORIGINAL_NAME <= " ") + if (cclut::cclutIsEmpty(CCLUT_ORIGINAL_NAME)) call cclexception(100, "E", "cclutRemoveMockImplementation() - originalName is a required field") return endif @@ -113,67 +112,62 @@ subroutine cclutRemoveAllMockImplementations(null) end ;cclutRemoveAllMockImplementations /** -Executes a program with all mocks currently added through cclutAddMockImplementation() and cclutCreateMockTable(). -programName is required. params is a string parameter to be sent directly to the program, so all commas and string -delimiters must be specified. If namespace is omitted, it will default to the PUBLIC namespace. +Executes a CCL program applying an indicated namespace and all mocks that have been specified using the functions +described below. programName is required. params is a stringified representation of the parameters to be passed to the +program, so all commas and string delimiters must be specified. If namespace is omitted, it will default to the PUBLIC +namespace. + +@param programName + The program to be executed with mocks. +@param params + The parameters to be sent to the program. +@param namespace + The namespace under which to execute the program. Example: call cclutExecuteProgramWithMocks("ccl_my_program", "^MINE^, 1.0, ^string parameter^", "MYNAMESPACE") **/ -subroutine cclutExecuteProgramWithMocks(programName, params, namespace) - ;Declare local variables - declare CCLUT_PROGRAM_NAME = vc with protect, constant(trim(cnvtupper(programName), 3)) - declare CCLUT_PARAMS = vc with protect, constant(params) - declare CCLUT_NAMESPACE = vc with protect, constant(namespace) +subroutine cclutExecuteProgramWithMocks(cclutProgramName, cclutParams, cclutNamespace) + declare CCLUT_PROGRAM_NAME = vc with protect, constant(cnvtupper(cclutProgramName)) + declare CCLUT_PARAMS = vc with protect, constant(cclutParams) + declare CCLUT_NAMESPACE = vc with protect, constant(cclutNamespace) declare cclutMockImplementationLength = i4 with protect, noconstant(size(cclut_mockImplementations->implementations, 5)) declare cclutMockImplementationIndex = i4 with protect, noconstant(0) declare cclutMockTableLength = i4 with protect, noconstant(size(cclut_mockTables->tables, 5)) declare cclutMockTableIndex = i4 with protect, noconstant(0) - declare cclutHasComma = i4 with protect, noconstant(0) declare cclutParserText = vc with protect, noconstant("") ;Validate inbound parameters - if (CCLUT_PROGRAM_NAME <= " ") + if (cclut::cclutIsEmpty(CCLUT_PROGRAM_NAME)) call cclexception(100, "E", "cclutExecuteProgramWithMocks() - programName is a required field") return endif - set cclutParserText = concat(" execute ", CCLUT_PROGRAM_NAME, " ") - if (params > " ") - set cclutParserText = concat(cclutParserText, " ", params) + set cclutParserText = concat(" execute ", CCLUT_PROGRAM_NAME) + if (cclut::cclutIsEmpty(CCLUT_PARAMS) = FALSE) + set cclutParserText = concat(cclutParserText, " ", CCLUT_PARAMS) endif - set cclutParserText = concat(cclutParserText, " with ") + set cclutParserText = concat(cclutParserText, " with") ;Add mock implementations for (cclutMockImplementationIndex = 1 to cclutMockImplementationLength) - if (cclutHasComma) - set cclutParserText = concat(cclutParserText, ", ") - endif set cclutParserText = concat(cclutParserText, ^ replace("^, cclut_mockImplementations->implementations[cclutMockImplementationIndex].originalName, ^", ^, - cclut_mockImplementations->implementations[cclutMockImplementationIndex].replaceName, ^) ^) - set cclutHasComma = 1 + cclut_mockImplementations->implementations[cclutMockImplementationIndex].replaceName, ^),^) endfor ;Add mock tables for (cclutMockTableIndex = 1 to cclutMockTableLength) if (cclut_mockTables->tables[cclutMockTableIndex].isFinalized = TRUE) - if (cclutHasComma) - set cclutParserText = concat(cclutParserText, ", ") - endif set cclutParserText = concat(cclutParserText, ^ replace("^, cclut_mockTables->tables[cclutMockTableIndex].originalName, ^", ^, - cclut_mockTables->tables[cclutMockTableIndex].replaceName, ^) ^) - set cclutHasComma = 1 + cclut_mockTables->tables[cclutMockTableIndex].replaceName, ^),^) endif endfor ;Add namespace - if (cclutHasComma) - set cclutParserText = concat(cclutParserText, ", ") - endif - set cclutParserText = concat(cclutParserText, ^ curnamespace = "^, CCLUT_NAMESPACE, ^" go ^) + set cclutParserText = concat(cclutParserText, ^ curnamespace = "^, CCLUT_NAMESPACE, ^" go^) call parser(cclutParserText) end ;cclutExecuteProgramWithMocks @@ -189,4 +183,4 @@ subroutine cclutRemoveAllMocks(null) call cclutRemoveAllMockTables(null) end ;cclutRemoveAllMocks -%#endif CCLUTMOCK_INC \ No newline at end of file +%#endif CCLUTMOCK_INC diff --git a/cclunit-framework-source/src/main/resources/cclutmock_table.inc b/cclunit-framework-source/src/main/resources/cclutmock_table.inc index b3b2725..9ccec20 100644 --- a/cclunit-framework-source/src/main/resources/cclutmock_table.inc +++ b/cclunit-framework-source/src/main/resources/cclutmock_table.inc @@ -7,20 +7,40 @@ ; ;********************************************************************************************************************************** -declare cclutDefineMockTable(tableName = vc(val), fieldNames = vc(val), fieldTypes = vc(val)) = vc with protect -declare cclutAddMockConstraint(tableName = vc(val), columnName = vc(val), - columnConstraint = vc(val)) = null with protect -declare cclutAddMockIndex(tableName = vc(val), columnNames = vc(val), isUnique = i4(val)) = null with protect -declare cclutCreateMockTable(tableName = vc(val)) = null with protect -declare cclutRemoveMockTable(tableName = vc(val)) = null with protect +declare CCLUT_BACKSLASH = vc with protect, constant("\") +declare CCLUT_ESCAPED_BACKSLASH = vc with protect, constant("\\") +declare CCLUT_PIPE = vc with protect, constant("|") +declare CCLUT_ESCAPED_PIPE = vc with protect, constant("\|") +declare CCLUT_ESCAPED_NULL = vc with protect, constant("\null") + +declare cclutDefineMockTable(cclutTableName = vc(val), cclutFieldNames = vc(val), + cclutFieldTypes = vc(val)) = vc with protect +declare cclutAddMockConstraint(cclutTableName = vc(val), cclutColumnName = vc(val), + cclutColumnConstraint = vc(val)) = null with protect +declare cclutAddMockIndex(cclutTableName = vc(val), cclutColumnNames = vc(val), + cclutIsUnique = i4(val)) = null with protect +declare cclutCreateMockTable(cclutTableName = vc(val)) = null with protect +declare cclutRemoveMockTable(cclutTableName = vc(val)) = null with protect declare cclutRemoveAllMockTables(null) = null with protect -declare cclutAddMockData(tableName = vc(val), rowData = vc(val)) = null with protect -declare cclutClearMockData(tableName = vc(val)) = null with protect - -declare cclut::cclutParseColumn(tableIndex = i4(val), columnIndex = i4(val), dataBuffer = vc(val)) = vc with protect +declare cclutAddMockData(cclutTableName = vc(val), cclutRowData = vc(val)) = null with protect +declare cclutClearMockData(cclutTableName = vc(val)) = null with protect + +declare cclut::cclutGetMockTableIndex(cclutTableName = vc(val)) = i4 with protect +declare cclut::cclutGetMockColumnIndex(cclutTableName = vc(val), cclutColumnName = vc(val)) = i4 with protect +declare cclut::cclutValidateMockTableIsDefined(cclutTableName = vc(val)) = i4 with protect +declare cclut::cclutValidateMockTableIsCreated(cclutTableName = vc(val)) = i4 with protect +declare cclut::cclutValidateMockTableIsNotCreated(cclutTableName = vc(val)) = i4 with protect +declare cclut::cclutValidateParameterIsNotEmpty(cclutParameter = vc(val), + cclutParameterName = vc(val)) = i4 with protect +declare cclut::cclutValidateEscapeSequences(cclutMockValues = vc(val)) = i4 with protect +declare cclut::cclutValidateNoNulls(cclutMockValue = vc(val)) = i4 with protect +declare cclut::cclutNormalizeEscapes(cclutEscapedData = vc(val)) = vc with protect +declare cclut::cclutConstructDBSetStatement(cclutTableIndex = i4(val), cclutColumnIndex = i4(val), + cclutDataBuffer = vc(val)) = vc with protect +declare cclut::cclutNextPipeValue(cclutPipeString = vc(ref)) = vc with protect record cclut_mockTables ( - 1 startTime = i4 + 1 markerTime = i4 1 tables[*] 2 originalName = vc 2 replaceName = vc @@ -30,11 +50,11 @@ record cclut_mockTables ( 3 columnConstraint = vc 2 indexes[*] 3 indexColumns = vc - 3 isUnique = i4 - 2 isFinalized = i4 + 3 isUnique = i2 + 2 isFinalized = i2 ) with protect -set cclut_mockTables->startTime = cnvtint(curtime3) +set cclut_mockTables->markerTime = cnvtint(curtime3) /** Defines a mock table structure that can be created for use within a program. This is the first function to be called in @@ -56,14 +76,11 @@ order. Example: call cclutDefineMockTable("person", "person_id|name_last|name_first|birth_dt_tm", "f8|vc|vc|dq8") **/ -subroutine cclutDefineMockTable(tableName, columnNames, columnTypes) - ;Declare local variables - declare CCLUT_TABLE_NAME = vc with protect, constant(trim(cnvtupper(tableName), 3)) - declare CCLUT_COLUMN_NAMES = vc with protect, constant(trim(cnvtupper(columnNames), 3)) - declare CCLUT_COLUMN_TYPES = vc with protect, constant(trim(cnvtupper(columnTypes), 3)) - declare cclutMockTableLength = i4 with protect, noconstant(size(cclut_mockTables->tables, 5)) +subroutine cclutDefineMockTable(cclutTableName, cclutColumnNames, cclutColumnTypes) + declare CCLUT_TABLE_NAME = vc with protect, constant(cnvtupper(cclutTableName)) + declare CCLUT_COLUMN_NAMES = vc with protect, constant(cnvtupper(cclutColumnNames)) + declare CCLUT_COLUMN_TYPES = vc with protect, constant(cnvtupper(cclutColumnTypes)) declare cclutMockTablePos = i4 with protect, noconstant(0) - declare cclutMockTableIndex = i4 with protect, noconstant(0) declare cclutColumnCount = i4 with protect, noconstant(0) declare cclutColumnIndex = i4 with protect, noconstant(0) declare cclutTypeCount = i4 with protect, noconstant(0) @@ -79,69 +96,60 @@ subroutine cclutDefineMockTable(tableName, columnNames, columnTypes) ) with protect ;Validate inbound parameters - if (CCLUT_TABLE_NAME <= " ") - call cclexception(100, "E", "cclutDefineMockTable() - tableName is a required field") + if (cclut::cclutValidateParameterIsNotEmpty(CCLUT_TABLE_NAME, "tableName") = FALSE) return("") endif - if (CCLUT_COLUMN_NAMES <= " ") - call cclexception(100, "E", "cclutDefineMockTable() - columnNames is a required field") + if (cclut::cclutValidateParameterIsNotEmpty(CCLUT_COLUMN_NAMES, "columnNames") = FALSE) return("") endif - if (CCLUT_COLUMN_TYPES <= " ") - call cclexception(100, "E", "cclutDefineMockTable() - columnTypes is a required field") + if (cclut::cclutValidateParameterIsNotEmpty(CCLUT_COLUMN_TYPES, "columnTypes") = FALSE) return("") endif ;Validate the column count matches the type count set cclutColumnCount = - arraysplit(cclutColumnRec->qual[cclutColumnIndex].str, cclutColumnIndex, CCLUT_COLUMN_NAMES, "|") - set cclutTypeCount = arraysplit(cclutTypeRec->qual[cclutTypeIndex].str, cclutTypeIndex, CCLUT_COLUMN_TYPES, "|") + arraysplit(cclutColumnRec->qual[cclutColumnIndex].str, cclutColumnIndex, CCLUT_COLUMN_NAMES, CCLUT_PIPE) + set cclutTypeCount = + arraysplit(cclutTypeRec->qual[cclutTypeIndex].str, cclutTypeIndex, CCLUT_COLUMN_TYPES, CCLUT_PIPE) if (cclutColumnCount != cclutTypeCount) - call cclexception(100, "E", concat("cclutDefineMockTable() - columnTypes must match number of columnNames. ", - "columnNames Count: ", cnvtstring(cclutColumnCount), " columnTypes Count: ", cnvtstring(cclutTypeCount))) + call cclexception(100, "E", concat("cclutDefineMockTable(", CCLUT_TABLE_NAME, ") - Size mismatch. ", + trim(cnvtstring(cclutColumnCount)), " columnNames vs. ", trim(cnvtstring(cclutTypeCount)), " columnTypes")) return("") endif ;Validate that every column and type is populated and that there are no duplicate columns for (cclutColumnIndex = 1 to cclutColumnCount) set cclutColumnName = cclutColumnRec->qual[cclutColumnIndex].str - if (cclutColumnName <= " ") - call cclexception(100, "E", concat("cclutDefineMockTable() - Empty columnName found in columnNames. ", - "columnNames: ", CCLUT_COLUMN_NAMES)) + if (cclut::cclutIsEmpty(cclutColumnName)) + call cclexception(100, "E", concat("cclutDefineMockTable(", CCLUT_TABLE_NAME, + ") - Empty columnName found in columnNames. columnNames: ", CCLUT_COLUMN_NAMES)) return("") endif - if (cclutTypeRec->qual[cclutColumnIndex].str <= " ") - call cclexception(100, "E", concat("cclutDefineMockTable() - Empty columnType found in columnTypes. ", - "columnTypes: ", CCLUT_COLUMN_TYPES)) + if (cclut::cclutIsEmpty(cclutTypeRec->qual[cclutColumnIndex].str)) + call cclexception(100, "E", concat("cclutDefineMockTable(", CCLUT_TABLE_NAME, + ") - Empty columnType found in columnTypes. columnTypes: ", CCLUT_COLUMN_TYPES)) return("") endif - if (findstring(cclutColumnName, CCLUT_COLUMN_NAMES, 1, 0) != - findstring(cclutColumnName, CCLUT_COLUMN_NAMES, 1, 1)) - call cclexception(100, "E", concat("cclutDefineMockTable() - Duplicate columnName found. ", - "columnName: ", cclutColumnName)) - return("") + if (findstring(concat(CCLUT_PIPE, cclutColumnName, CCLUT_PIPE), + concat(CCLUT_PIPE, CCLUT_COLUMN_NAMES, CCLUT_PIPE), 1, 0) != + findstring(concat(CCLUT_PIPE, cclutColumnName, CCLUT_PIPE), + concat(CCLUT_PIPE, CCLUT_COLUMN_NAMES, CCLUT_PIPE), 1, 1)) + call cclexception(100, "E", concat("cclutDefineMockTable(", CCLUT_TABLE_NAME, + ") - Duplicate columnName found. columnName: ", cclutColumnName)) + return("") endif endfor - ;Check if table is already mocked - set cclutMockTablePos = locateval(cclutMockTableIndex, 1, cclutMockTableLength, CCLUT_TABLE_NAME, - cclut_mockTables->tables[cclutMockTableIndex].originalName) - - if (cclutMockTablePos > 0) - ;If table was already defined, remove it and re-add it - call cclutRemoveMockTable(CCLUT_TABLE_NAME) - set stat = alterlist(cclut_mockTables->tables, cclutMockTableLength, cclutMockTablePos - 1) - else - ;If table is new, add a new element to the end of the array - set cclutMockTablePos = cclutMockTableLength + 1 - set stat = alterlist(cclut_mockTables->tables, cclutMockTablePos) - endif + ;Remove table if it exists, and add a new element to the end of the array + call cclutRemoveMockTable(CCLUT_TABLE_NAME) + set cclutMockTablePos = size(cclut_mockTables->tables, 5) + 1 + set stat = alterlist(cclut_mockTables->tables, cclutMockTablePos) ;Create the mock name and fill out the columns set cclut_mockTables->tables[cclutMockTablePos].originalName = CCLUT_TABLE_NAME set cclut_mockTables->tables[cclutMockTablePos].replaceName = cnvtupper(trim(substring(1, 30, concat("CUST_CCLUT_", - trim(cnvtstring(cclutMockTablePos), 3), trim(cnvtstring(cclut_mockTables->startTime), 3), curuser)), 3)) + trim(cnvtstring(cclutMockTablePos), 3), trim(cnvtstring(cclut_mockTables->markerTime), 3), curuser)), 3)) set cclut_mockTables->tables[cclutMockTablePos].isFinalized = FALSE set stat = alterlist(cclut_mockTables->tables[cclutMockTablePos].columns, cclutColumnCount) @@ -155,6 +163,20 @@ subroutine cclutDefineMockTable(tableName, columnNames, columnTypes) return(cclut_mockTables->tables[cclutMockTablePos].replaceName) end ;cclutDefineMockTable +/** +Helper function to validate if the supplied cclutParameter is not empty. cclutParameter is the vc value to be checked. +cclutParameterName is the name of the parameter to be used in any error handling. The subroutine returns TRUE if the +parameter is not empty or FALSE if it is empty. The subroutine creates an exception if it returns FALSE. +**/ +subroutine cclut::cclutValidateParameterIsNotEmpty(cclutParameter, cclutParameterName) + if (cclut::cclutIsEmpty(cclutParameter)) + call cclexception(100, "E", concat("cclutValidateParameterIsNotEmpty() - ", cclutParameterName, + " is a required field")) + return(FALSE) + endif + return(TRUE) +end ;cclut::cclutValidateParameterIsNotEmpty + /** Adds a constraint to a mock table. The table must already be defined through cclutDefineMockTable(), otherwise an error will be thrown. This function may not be called after cclutCreateMockTable(). tableName and columnName are required. @@ -165,7 +187,7 @@ seen here: https://wiki.cerner.com/display/public/1101discernHP/SELECT+INTO+TABLE+Table_Name+Using+Discern+Explorer @param tableName - The table to which the constraint will be added. + The name of the source table for the mock table to which the constraint will be added. @param columnName The column to which the constraint will be applied. @param columnConstraint @@ -174,81 +196,147 @@ https://wiki.cerner.com/display/public/1101discernHP/SELECT+INTO+TABLE+Table_Nam Example: call cclutAddMockConstraint("person", "name_last", "not null unique") **/ -subroutine cclutAddMockConstraint(tableName, columnName, columnConstraint) - ;Declare local variables - declare CCLUT_TABLE_NAME = vc with protect, constant(trim(cnvtupper(tableName), 3)) - declare CCLUT_COLUMN_NAME = vc with protect, constant(trim(cnvtupper(columnName), 3)) - declare CCLUT_COLUMN_CONSTRAINT = vc with protect, constant(trim(cnvtupper(columnConstraint), 3)) +subroutine cclutAddMockConstraint(cclutTableName, cclutColumnName, cclutColumnConstraint) + declare CCLUT_TABLE_NAME = vc with protect, constant(cnvtupper(cclutTableName)) + declare CCLUT_COLUMN_NAME = vc with protect, constant(cnvtupper(cclutColumnName)) + declare CCLUT_COLUMN_CONSTRAINT = vc with protect, constant(cnvtupper(cclutColumnConstraint)) declare cclutMockTablePos = i4 with protect, noconstant(0) - declare cclutMockTableIndex = i4 with protect, noconstant(0) declare cclutMockColumnPos = i4 with protect, noconstant(0) - declare cclutMockColumnIndex = i4 with protect, noconstant(0) ;Validate inbound parameters - if (CCLUT_TABLE_NAME <= " ") - call cclexception(100, "E", "cclutAddMockConstraint() - tableName is a required field") + if (cclut::cclutValidateParameterIsNotEmpty(CCLUT_TABLE_NAME, "tableName") = FALSE) return endif - if (CCLUT_COLUMN_NAME <= " ") - call cclexception(100, "E", "cclutAddMockConstraint() - columnName is a required field") + if (cclut::cclutValidateParameterIsNotEmpty(CCLUT_COLUMN_NAME, "columnName") = FALSE) return endif ;Validate that the table exists and has not been created - set cclutMockTablePos = locateval(cclutMockTableIndex, 1, size(cclut_mockTables->tables, 5), CCLUT_TABLE_NAME, - cclut_mockTables->tables[cclutMockTableIndex].originalName) + set cclutMockTablePos = cclut::cclutValidateMockTableIsDefined(CCLUT_TABLE_NAME) + if (cclutMockTablePos > 0 and cclut::cclutValidateMockTableIsNotCreated(CCLUT_TABLE_NAME)) + ;Validate that the column exists on the table. + set cclutMockColumnPos = cclut::cclutGetMockColumnIndex(CCLUT_TABLE_NAME, CCLUT_COLUMN_NAME) + if (cclutMockColumnPos < 1) + call cclexception(100, "E", concat("cclutAddMockConstraint(", CCLUT_TABLE_NAME, ") - ", CCLUT_COLUMN_NAME, + " is not mocked on table.")) + return + endif + + ;Set the constraint + set cclut_mockTables->tables[cclutMockTablePos].columns[cclutMockColumnPos].columnConstraint = + CCLUT_COLUMN_CONSTRAINT + endif +end ;cclutAddMockConstraint + +/** +Helper function to validate if the supplied cclutTableName has been defined as a mock in cclut_mockTables. +cclutTableName is the name of the table to validate. The subroutine returns the index within the array if it is defined +or 0 if it is not defined. +**/ +subroutine cclut::cclutValidateMockTableIsDefined(cclutTableName) + declare cclutMockTablePos = i4 with protect, noconstant(0) + + set cclutMockTablePos = cclut::cclutGetMockTableIndex(cclutTableName) if (cclutMockTablePos < 1) - call cclexception(100, "E", concat("cclutAddMockConstraint() - tableName has not been mocked. tableName: ", - CCLUT_TABLE_NAME)) - return + call cclexception(100, "E", concat("cclutValidateMockTableIsDefined(", cclutTableName, + ") - Table has not been mocked.")) + return(0) endif - if (cclut_mockTables->tables[cclutMockTableIndex].isFinalized = TRUE) - call cclexception(100, "E", concat("cclutAddMockConstraint() - tableName has already been created. ", - "Constraints cannot be modified. tableName: ", CCLUT_TABLE_NAME)) - return + return(cclutMockTablePos) +end ;cclut::cclutValidateMockTableIsDefined + +/** +Helper function to validate if the supplied cclutTableName has been created as a mock in the RDBMS. cclutTableName is +the name of the table to validate. The subroutine returns TRUE if it has been created or FALSE if it has not been +created. The subroutine creates an exception if it returns FALSE. +**/ +subroutine cclut::cclutValidateMockTableIsCreated(cclutTableName) + declare cclutMockTablePos = i4 with protect, noconstant(0) + + set cclutMockTablePos = cclut::cclutGetMockTableIndex(cclutTableName) + if (cclutMockTablePos > 0) + if (cclut_mockTables->tables[cclutMockTablePos].isFinalized = TRUE) + return(TRUE) + endif endif + call cclexception(100, "E", concat("cclutValidateMockTableIsCreated(", cclutTableName, + ") - Table has not been created.")) + return(FALSE) +end ;cclut::cclutValidateMockTableIsCreated + +/** +Helper function to validate if the supplied cclutTableName has not been created as a mock in the RDBMS. cclutTableName +is the name of the table to validate. The subroutine returns TRUE if it has been not been created or FALSE if it has +been created. The subroutine creates an exception if it returns FALSE. +**/ +subroutine cclut::cclutValidateMockTableIsNotCreated(cclutTableName) + declare cclutMockTablePos = i4 with protect, noconstant(0) - ;Validate that the column exists on the table. - set cclutMockColumnPos = - locateval(cclutMockColumnIndex, 1, size(cclut_mockTables->tables[cclutMockTablePos].columns, 5), - CCLUT_COLUMN_NAME, cclut_mockTables->tables[cclutMockTablePos].columns[cclutMockColumnIndex].columnName) - if (cclutMockColumnPos < 1) - call cclexception(100, "E", concat("cclutAddMockConstraint() - columnName is not mocked on table. ", - "columnName: ", CCLUT_COLUMN_NAME, " tableName: ", CCLUT_TABLE_NAME)) + set cclutMockTablePos = cclut::cclutGetMockTableIndex(cclutTableName) + if (cclutMockTablePos > 0) + if (cclut_mockTables->tables[cclutMockTablePos].isFinalized = TRUE) + call cclexception(100, "E", concat("cclutValidateMockTableIsNotCreated(", cclutTableName, + ") - Table has already been created.")) + return(FALSE) + endif endif + return(TRUE) +end ;cclut::cclutValidateMockTableIsNotCreated - ;Set the constraint - set cclut_mockTables->tables[cclutMockTablePos].columns[cclutMockColumnPos].columnConstraint = - CCLUT_COLUMN_CONSTRAINT -end ;cclutAddMockConstraint +/** +Helper function to retrieve the index of the supplied cclutTableName within the cclut_mockTables->tables array. +cclutTableName is the name of the table for which to search. The subroutine returns the index as an integer if it is +found or 0 if it is not found. +**/ +subroutine cclut::cclutGetMockTableIndex(cclutTableName) + declare cclutMockTableIndex = i4 with protect, noconstant(0) + + return(locateval(cclutMockTableIndex, 1, size(cclut_mockTables->tables, 5), cclutTableName, + cclut_mockTables->tables[cclutMockTableIndex].originalName)) +end ;cclut::cclutGetMockTableIndex + +/** +Helper function to retrieve the index of the supplied cclutColumnName for the supplied cclutTableName within the +cclut_mockTables record structure. cclutTableName is the name of the table for which to search. cclutColumnName is the +name of the column for which to search. The subroutine returns the index as an integer if it is found or 0 if it is not +found. +**/ +subroutine cclut::cclutGetMockColumnIndex(cclutTableName, cclutColumnName) + declare cclutMockTableIndex = i4 with protect, noconstant(0) + declare cclutMockTablePos = i4 with protect, noconstant(0) + declare cclutMockColumnIndex = i4 with protect, noconstant(0) + + set cclutMockTablePos = locateval(cclutMockTableIndex, 1, size(cclut_mockTables->tables, 5), cclutTableName, + cclut_mockTables->tables[cclutMockTableIndex].originalName) + return(locateval(cclutMockColumnIndex, 1, + size(cclut_mockTables->tables[cclutMockTablePos].columns, 5), cclutColumnName, + cclut_mockTables->tables[cclutMockTablePos].columns[cclutMockColumnIndex].columnName)) +end ;cclut::cclutGetMockColumnIndex /** Adds an index to a mock table. The table must already be defined through cclutDefineMockTable(), otherwise an error will be thrown. This function may not be called after cclutCreateMockTable(). tableName, columnNames, and isUnique are required. columnNames may be a single column name or a pipe-delimited list of columns for a composite index (the order -of the columns will be the order of the index). If isUnique is 1, then a unique index will be created. If isUnique is -0, then a non-unique index will be created. +of the columns will be the order of the index). If isUnique is TRUE, then a unique index will be created. If isUnique +is FALSE, then a non-unique index will be created. @param tableName - The table to which the index will be added. + The name of the source table for the mock table to which the index will be added. @param columnNames A pipe-delimited string of column names for the index. @param isUnique - 1 to create a unique index; 0 to create a non-unique index + TRUE to create a unique index; FALSE to create a non-unique index Example: -call cclutAddMockIndex("person", "person_id", 1) -call cclutAddMockIndex("person", "name_last|name_first", 0) +call cclutAddMockIndex("person", "person_id", TRUE) +call cclutAddMockIndex("person", "name_last|name_first", FALSE) **/ -subroutine cclutAddMockIndex(tableName, columnNames, isUnique) - ;Declare local variables - declare CCLUT_TABLE_NAME = vc with protect, constant(trim(cnvtupper(tableName), 3)) - declare CCLUT_COLUMN_NAMES = vc with protect, constant(trim(cnvtupper(columnNames), 3)) - declare CCLUT_IS_UNIQUE = i4 with protect, constant(isUnique) +subroutine cclutAddMockIndex(cclutTableName, cclutColumnNames, cclutIsUnique) + declare CCLUT_TABLE_NAME = vc with protect, constant(cnvtupper(cclutTableName)) + declare CCLUT_COLUMN_NAMES = vc with protect, constant(cnvtupper(cclutColumnNames)) + declare CCLUT_IS_UNIQUE = i4 with protect, constant(cclutIsUnique) declare cclutMockTablePos = i4 with protect, noconstant(0) - declare cclutMockTableIndex = i4 with protect, noconstant(0) declare cclutMockColumnPos = i4 with protect, noconstant(0) - declare cclutMockColumnIndex = i4 with protect, noconstant(0) declare cclutMockIndexPos = i4 with protect, noconstant(0) declare cclutMockIndexIndex = i4 with protect, noconstant(0) declare cclutMockIndexLength = i4 with protect, noconstant(0) @@ -261,78 +349,64 @@ subroutine cclutAddMockIndex(tableName, columnNames, isUnique) ) with protect ;Validate inbound parameters - if (CCLUT_TABLE_NAME <= " ") - call cclexception(100, "E", "cclutAddMockIndex() - tableName is a required field") + if (cclut::cclutValidateParameterIsNotEmpty(CCLUT_TABLE_NAME, "tableName") = FALSE) return endif - if (CCLUT_COLUMN_NAMES <= " ") - call cclexception(100, "E", "cclutAddMockIndex() - columnNames is a required field") + if (cclut::cclutValidateParameterIsNotEmpty(CCLUT_COLUMN_NAMES, "columnNames") = FALSE) return endif ;Validate that the table exists and has not been created - set cclutMockTablePos = locateval(cclutMockTableIndex, 1, size(cclut_mockTables->tables, 5), CCLUT_TABLE_NAME, - cclut_mockTables->tables[cclutMockTableIndex].originalName) - if (cclutMockTablePos < 1) - call cclexception(100, "E", concat("cclutAddMockIndex() - tableName has not been mocked. tableName: ", - CCLUT_TABLE_NAME)) - return - endif - if (cclut_mockTables->tables[cclutMockTableIndex].isFinalized = TRUE) - call cclexception(100, "E", concat("cclutAddMockIndex() - tableName has already been created. ", - "Indexes cannot be modified. tableName: ", CCLUT_TABLE_NAME)) - return - endif - - ;Validate that each column in the index is valid and that there are no duplicates - set cclutColumnCount = - arraysplit(cclutColumnRec->qual[cclutColumnIndex].str, cclutColumnIndex, CCLUT_COLUMN_NAMES, "|") - for (cclutColumnIndex = 1 to cclutColumnCount) - set cclutColumnName = cclutColumnRec->qual[cclutColumnIndex].str - set cclutMockColumnPos = locateval(cclutMockColumnIndex, 1, - size(cclut_mockTables->tables[cclutMockTablePos].columns, 5), cclutColumnName, - cclut_mockTables->tables[cclutMockTablePos].columns[cclutMockColumnIndex].columnName) - if (cclutMockColumnPos < 1) - call cclexception(100, "E", concat("cclutAddMockIndex() - columnName is not mocked on table. columnName: ", - cclutColumnName, " tableName: ", CCLUT_TABLE_NAME)) - return - endif - if (findstring(cclutColumnName, CCLUT_COLUMN_NAMES, 1, 0) != - findstring(cclutColumnName, CCLUT_COLUMN_NAMES, 1, 1)) - call cclexception(100, "E", concat("cclutAddMockIndex() - Duplicate columnName found. ", - "columnName: ", cclutColumnName)) + set cclutMockTablePos = cclut::cclutValidateMockTableIsDefined(CCLUT_TABLE_NAME) + if (cclutMockTablePos > 0 and cclut::cclutValidateMockTableIsNotCreated(CCLUT_TABLE_NAME)) + ;Validate that each column in the index is valid and that there are no duplicates + set cclutColumnCount = + arraysplit(cclutColumnRec->qual[cclutColumnIndex].str, cclutColumnIndex, CCLUT_COLUMN_NAMES, CCLUT_PIPE) + for (cclutColumnIndex = 1 to cclutColumnCount) + set cclutColumnName = cclutColumnRec->qual[cclutColumnIndex].str + set cclutMockColumnPos = cclut::cclutGetMockColumnIndex(CCLUT_TABLE_NAME, cclutColumnName) + if (cclutMockColumnPos < 1) + call cclexception(100, "E", concat("cclutAddMockIndex(", CCLUT_TABLE_NAME, + ") - ", cclutColumnName, " is not mocked on table.")) return - endif - endfor + endif + if (findstring(concat(CCLUT_PIPE, cclutColumnName, CCLUT_PIPE), + concat(CCLUT_PIPE, CCLUT_COLUMN_NAMES, CCLUT_PIPE), 1, 0) != + findstring(concat(CCLUT_PIPE, cclutColumnName, CCLUT_PIPE), + concat(CCLUT_PIPE, CCLUT_COLUMN_NAMES, CCLUT_PIPE), 1, 1)) + call cclexception(100, "E", concat("cclutAddMockIndex(", CCLUT_TABLE_NAME, + ") - Duplicate columnName found. columnName: ", cclutColumnName)) + return + endif + endfor - ;Set the index - set cclutMockIndexLength = size(cclut_mockTables->tables[cclutMockTablePos].indexes, 5) - set cclutMockIndexPos = locateval(cclutMockIndexIndex, 1, cclutMockIndexLength, - CCLUT_COLUMN_NAMES, cclut_mockTables->tables[cclutMockTablePos].indexes[cclutMockIndexIndex].indexColumns) - if (cclutMockIndexPos < 1) - set cclutMockIndexPos = cclutMockIndexLength + 1 - set stat = alterlist(cclut_mockTables->tables[cclutMockTablePos].indexes, cclutMockIndexPos) - set cclut_mockTables->tables[cclutMockTablePos].indexes[cclutMockIndexPos].indexColumns = CCLUT_COLUMN_NAMES - endif - set cclut_mockTables->tables[cclutMockTablePos].indexes[cclutMockIndexPos].isUnique = - evaluate(CCLUT_IS_UNIQUE, 0, 0, 1) + ;Set the index + set cclutMockIndexLength = size(cclut_mockTables->tables[cclutMockTablePos].indexes, 5) + set cclutMockIndexPos = locateval(cclutMockIndexIndex, 1, cclutMockIndexLength, + CCLUT_COLUMN_NAMES, cclut_mockTables->tables[cclutMockTablePos].indexes[cclutMockIndexIndex].indexColumns) + if (cclutMockIndexPos < 1) + set cclutMockIndexPos = cclutMockIndexLength + 1 + set stat = alterlist(cclut_mockTables->tables[cclutMockTablePos].indexes, cclutMockIndexPos) + set cclut_mockTables->tables[cclutMockTablePos].indexes[cclutMockIndexPos].indexColumns = CCLUT_COLUMN_NAMES + endif + set cclut_mockTables->tables[cclutMockTablePos].indexes[cclutMockIndexPos].isUnique = + evaluate(CCLUT_IS_UNIQUE, FALSE, FALSE, TRUE) + endif end ;cclutAddMockIndex /** -Creates the mock table. The table must already be defined through cclutDefineMockTable(), otherwise an error will be +Creates a mock table. The table must already be defined through cclutDefineMockTable(), otherwise an error will be thrown. If the table has already been created, the function will return silently. tableName is required. @param tableName - The table to be mocked. + The name of the source table to be mocked. Example: call cclutCreateMockTable("person") **/ -subroutine cclutCreateMockTable(tableName) - ;Declare local variables - declare CCLUT_TABLE_NAME = vc with protect, constant(trim(cnvtupper(tableName), 3)) +subroutine cclutCreateMockTable(cclutTableName) + declare CCLUT_TABLE_NAME = vc with protect, constant(cnvtupper(cclutTableName)) declare cclutMockTablePos = i4 with protect, noconstant(0) - declare cclutMockTableIndex = i4 with protect, noconstant(0) declare cclutMockColumnCount = i4 with protect, noconstant(0) declare cclutMockColumnIndex = i4 with protect, noconstant(0) declare cclutMockIndexIndex = i4 with protect, noconstant(0) @@ -342,20 +416,16 @@ subroutine cclutCreateMockTable(tableName) declare cclutParserConstraint = vc with protect, noconstant(" ") ;Validate inbound parameter - if (CCLUT_TABLE_NAME <= " ") - call cclexception(100, "E", "cclutCreateMockTable() - tableName is a required field") + if (cclut::cclutValidateParameterIsNotEmpty(CCLUT_TABLE_NAME, "tableName") = FALSE) return endif ;Validate that the table exists and has not been created - set cclutMockTablePos = locateval(cclutMockTableIndex, 1, size(cclut_mockTables->tables, 5), CCLUT_TABLE_NAME, - cclut_mockTables->tables[cclutMockTableIndex].originalName) + set cclutMockTablePos = cclut::cclutValidateMockTableIsDefined(CCLUT_TABLE_NAME) if (cclutMockTablePos < 1) - call cclexception(100, "E", concat("cclutCreateMockTable() - tableName has not been mocked. tableName: ", - CCLUT_TABLE_NAME)) return endif - if (cclut_mockTables->tables[cclutMockTableIndex].isFinalized = TRUE) + if (cclut_mockTables->tables[cclutMockTablePos].isFinalized = TRUE) return endif @@ -363,74 +433,70 @@ subroutine cclutCreateMockTable(tableName) set cclutParserText = concat(" select into table ", cclut_mockTables->tables[cclutMockTablePos].replaceName) for (cclutMockColumnIndex = 1 to size(cclut_mockTables->tables[cclutMockTablePos].columns, 5)) if (cclutMockColumnIndex > 1) - set cclutParserText = concat(cclutParserText, " , ") + set cclutParserText = concat(cclutParserText, " ,") endif set cclutColumnName = cclut_mockTables->tables[cclutMockTablePos].columns[cclutMockColumnIndex].columnName set cclutConstraint = cclut_mockTables->tables[cclutMockTablePos].columns[cclutMockColumnIndex].columnConstraint set cclutParserText = concat(cclutParserText, ^ ^, cclutColumnName, ^ = type("^, cclut_mockTables->tables[cclutMockTablePos].columns[cclutMockColumnIndex].columnType, ^")^) - if (cclutConstraint > " ") + if (cclut::cclutIsEmpty(cclutConstraint) = FALSE) set cclutParserConstraint = concat(cclutParserConstraint, ^ , constraint(^, cclutColumnName, ^,"^, cclutConstraint, ^")^) endif endfor - set cclutParserText = concat(cclutParserText, ^ with organization="P" ^) + set cclutParserText = concat(cclutParserText, ^ with organization="P"^) if (cclutParserConstraint > " ") set cclutParserText = concat(cclutParserText, cclutParserConstraint) endif for (cclutMockIndexIndex = 1 to size(cclut_mockTables->tables[cclutMockTablePos].indexes, 5)) set cclutParserText = concat(cclutParserText, - evaluate(cclut_mockTables->tables[cclutMockTablePos].indexes[cclutMockIndexIndex].isUnique, 1, + evaluate(cclut_mockTables->tables[cclutMockTablePos].indexes[cclutMockIndexIndex].isUnique, TRUE, " , indexunique(", " , index("), - replace(cclut_mockTables->tables[cclutMockTablePos].indexes[cclutMockIndexIndex].indexColumns, "|", ","), - ")") + replace(cclut_mockTables->tables[cclutMockTablePos].indexes[cclutMockIndexIndex].indexColumns, CCLUT_PIPE, + ","), ")") endfor - set cclutParserText = concat(cclutParserText, " go ") + set cclutParserText = concat(cclutParserText, " go") call parser(cclutParserText) set cclut_mockTables->tables[cclutMockTablePos].isFinalized = TRUE end ;cclutCreateMockTable /** -Removes the mock table. If the table was already created, it will also be dropped. If the table is not currently +Removes a mock table. If the table was already created, it will also be dropped. If the table is not currently mocked, it will return silently. tableName is required. @param tableName - The table that is mocked. + The name of the source table that is mocked. Example: call cclutRemoveMockTable("person") **/ -subroutine cclutRemoveMockTable(tableName) - ;Declare local variables - declare CCLUT_TABLE_NAME = vc with protect, constant(trim(cnvtupper(tableName), 3)) - declare cclutMockTableLength = i4 with protect, noconstant(size(cclut_mockTables->tables, 5)) +subroutine cclutRemoveMockTable(cclutTableName) + declare CCLUT_TABLE_NAME = vc with protect, constant(cnvtupper(cclutTableName)) + declare cclutMockTableCount = i4 with protect, noconstant(size(cclut_mockTables->tables, 5)) declare cclutMockTablePos = i4 with protect, noconstant(0) - declare cclutMockTableIndex = i4 with protect, noconstant(0) declare cclutParserText = vc with protect, noconstant("") ;Validate inbound parameter - if (CCLUT_TABLE_NAME <= " ") - call cclexception(100, "E", "cclutRemoveMockTable() - tableName is a required field") + if (cclut::cclutValidateParameterIsNotEmpty(CCLUT_TABLE_NAME, "tableName") = FALSE) return endif - set cclutMockTablePos = locateval(cclutMockTableIndex, 1, cclutMockTableLength, CCLUT_TABLE_NAME, - cclut_mockTables->tables[cclutMockTableIndex].originalName) + set cclutMockTablePos = cclut::cclutGetMockTableIndex(CCLUT_TABLE_NAME) if (cclutMockTablePos > 0) - if (cclut_mockTables->tables[cclutMockTableIndex].isFinalized) + if (cclut_mockTables->tables[cclutMockTablePos].isFinalized) ;Drop the table if it was already added set cclutParserText = - concat(" drop table ", cclut_mockTables->tables[cclutMockTablePos].replaceName, " go ") + concat(" drop table ", cclut_mockTables->tables[cclutMockTablePos].replaceName, " go") call parser(cclutParserText) set cclutParserText = - concat(" rdb drop table ", cclut_mockTables->tables[cclutMockTablePos].replaceName, " end go ") + concat(" rdb drop table ", cclut_mockTables->tables[cclutMockTablePos].replaceName, " end go") call parser(cclutParserText) endif ;Remove it from the mocked list - set stat = alterlist(cclut_mockTables->tables, cclutMockTableLength - 1, cclutMockTablePos - 1) + set stat = alterlist(cclut_mockTables->tables, cclutMockTableCount - 1, cclutMockTablePos - 1) endif end ;cclutRemoveMockTable @@ -447,7 +513,7 @@ subroutine cclutRemoveAllMockTables(null) end ;cclutRemoveAllMockTables /** -Add a row of mock data to a table. tableName and rowData are required. tableName must have already been created +Adds a row of mock data to a table. tableName and rowData are required. tableName must have already been created through cclutCreateMockTable() or an error will be thrown. rowData is a pipe-delimited string for each column in the same order that was used in cclutDefineMockTable(). For character fields, the backslash (\) will serve as an escape character. For date fields, the value in rowData will be supplied to the cnvtdatetime() function. All other values @@ -459,9 +525,9 @@ Supported escape values \null = null (no value will be inserted into the column) @param tableName - The table to which the data will be added. + The name of the source table for the mock table to which the data will be added. @param rowData - A pipe-delimited string of data to be inserted into the table. + A pipe-delimited string of data to be inserted into the mock table. Example: call cclutDefineMockTable("person", "person_id|name_last|name_first|birth_dt_tm", "f8|vc|vc|dq8") @@ -471,258 +537,220 @@ call cclutAddMockData("person", "2.0|A\|d\\ams|John|02-FEB-1971 11:11") ;Will ad call cclutAddMockData("person", "3.0|Jefferson|\null|03-MAR-1972 22:22") ;Will add Jefferson (no first name) call cclutAddMockData("person", "4.0|Madison||04-APR-1973 10:33") ;Will add Madison (empty string for first name) **/ -subroutine cclutAddMockData(tableName, rowData) - ;Declare local variables - declare CCLUT_TABLE_NAME = vc with protect, constant(trim(cnvtupper(tableName), 3)) - declare CCLUT_ROW_DATA = vc with protect, constant(rowData) +subroutine cclutAddMockData(cclutTableName, cclutRowData) + declare CCLUT_TABLE_NAME = vc with protect, constant(cnvtupper(cclutTableName)) + ;Appending a single pipe on the end so that the string is empty once all values are popped. + declare cclutMockValues = vc with protect, noconstant(concat(notrim(cclutRowData), CCLUT_PIPE)) + declare cclutMockValue = vc with protect, noconstant("") declare cclutMockTablePos = i4 with protect, noconstant(0) - declare cclutMockTableIndex = i4 with protect, noconstant(0) - declare cclutMockDataLength = i4 with protect, noconstant(size(CCLUT_ROW_DATA)) - declare cclutMockDataIndex = i4 with protect, noconstant(0) - declare cclutMockColumnLength = i4 with protect, - noconstant(size(cclut_mockTables->tables[cclutMockTablePos].columns, 5)) - declare cclutMockColumnIndex = i4 with protect, noconstant(1) - declare cclutHasComma = i4 with protect, noconstant(0) - declare cclutNullColumn = i4 with protect, noconstant(0) - declare cclutDataBuffer = vc with protect, noconstant(" ") - declare cclutEscapeBuffer = vc with protect, noconstant("") - declare cclutDataCharacter = vc with protect, noconstant("") - declare cclutParserText = vc with protect, noconstant("") + declare cclutMockColumnLength = i4 with protect, noconstant(0) + declare cclutMockColumnIndex = i4 with protect, noconstant(0) + declare cclutNeedsAComma = i2 with protect, noconstant(FALSE) ;Validate inbound parameters - if (CCLUT_TABLE_NAME <= " ") - call cclexception(100, "E", "cclutAddMockData() - tableName is a required field") + if (cclut::cclutValidateParameterIsNotEmpty(CCLUT_TABLE_NAME, "tableName") = FALSE) return endif ;Validate that the table exists and has been created - set cclutMockTablePos = locateval(cclutMockTableIndex, 1, size(cclut_mockTables->tables, 5), CCLUT_TABLE_NAME, - cclut_mockTables->tables[cclutMockTableIndex].originalName) + set cclutMockTablePos = cclut::cclutValidateMockTableIsDefined(CCLUT_TABLE_NAME) if (cclutMockTablePos < 1) - call cclexception(100, "E", concat("cclutAddMockData() - tableName has not been mocked. tableName: ", - CCLUT_TABLE_NAME)) return - elseif (cclut_mockTables->tables[cclutMockTablePos].isFinalized = FALSE) - call cclexception(100, "E", concat("cclutAddMockData() - tableName has not been created. tableName: ", - CCLUT_TABLE_NAME)) + endif + if (cclut::cclutValidateMockTableIsCreated(CCLUT_TABLE_NAME) = FALSE) + return + endif + set cclutMockColumnLength = size(cclut_mockTables->tables[cclutMockTablePos].columns, 5) + + ;Validate that there are no unsupported escape sequences + if (cclut::cclutValidateEscapeSequences(cclutMockValues) = FALSE) return endif ;Initialize insert statement - set cclutParserText = concat(" insert into ", cclut_mockTables->tables[cclutMockTablePos].replaceName, " set ") - call parser(cclutParserText) + call parser(concat(" insert into ", cclut_mockTables->tables[cclutMockTablePos].replaceName, " set")) - ;Special case if rowData is empty for single-column tables - if (cclutMockDataLength = 0 or (cclutMockDataLength = 1 and ichar(substring(1, 1, CCLUT_ROW_DATA)) = 0)) - set cclutDataBuffer = cclut::cclutParseColumn(cclutMockTablePos, 1, " ") - if (cclutDataBuffer > " ") - call parser(cclutDataBuffer) - set cclutMockColumnIndex = cclutMockColumnIndex + 1 - else - ;Error occurred in cclutParseColumn, return - return - endif - else - ;Iterate over every character in rowData - for (cclutMockDataIndex = 1 to cclutMockDataLength) - set cclutParserText = " " - ;Grab the next character - set cclutDataCharacter = notrim(substring(cclutMockDataIndex, 1, CCLUT_ROW_DATA)) - ;If the character is a pipe or the end of the string - if (cclutDataCharacter = "|" or cclutMockDataIndex = cclutMockDataLength) - if (cclutNullColumn = FALSE) - ;Check if the comma is needed - if (cclutHasComma) - set cclutParserText = concat(cclutParserText, " , ") - endif - - ;Add the last character if the end of the string is reached and it is not a pipe - if (cclutMockDataIndex = cclutMockDataLength and cclutDataCharacter != "|") - set cclutDataBuffer = notrim(concat(cclutDataBuffer, cclutDataCharacter)) - endif - - ;Construct the column insertion - set cclutDataBuffer = - cclut::cclutParseColumn(cclutMockTablePos, cclutMockColumnIndex, cclutDataBuffer) - if (cclutDataBuffer > " ") - set cclutParserText = concat(cclutParserText, " ", cclutDataBuffer) - else - ;Error occurred in cclutParseColumn, return - return - endif - - ;Add one final empty string if the pipe is the last character - if (cclutMockDataIndex = cclutMockDataLength and cclutDataCharacter = "|") - set cclutDataBuffer = cclut::cclutParseColumn(cclutMockTablePos, cclutMockColumnIndex + 1, " ") - if (cclutDataBuffer > " ") - set cclutParserText = concat(cclutParserText, " , ", cclutDataBuffer) - set cclutMockColumnIndex = cclutMockColumnIndex + 1 - else - ;Error occurred in cclutParseColumn, return - return - endif - endif - - set cclutHasComma = 1 - call parser(cclutParserText) - set cclutDataBuffer = " " - set cclutMockColumnIndex = cclutMockColumnIndex + 1 - else - set cclutNullColumn = FALSE - endif - ;If the character is an escape character - elseif (cclutDataCharacter = "\") - ;Evaluate escape conditions - set cclutEscapeBuffer = substring(cclutMockDataIndex + 1, 1, CCLUT_ROW_DATA) - if (cclutEscapeBuffer = "|" or cclutEscapeBuffer = "\") - set cclutDataBuffer = notrim(concat(cclutDataBuffer, cclutEscapeBuffer)) - if (cclutMockDataLength = cclutMockDataIndex + 1) - ;End of string was reached, save off last column - if (cclutHasComma) - set cclutParserText = concat(cclutParserText, " , ") - endif - set cclutDataBuffer = - cclut::cclutParseColumn(cclutMockTablePos, cclutMockColumnIndex, cclutDataBuffer) - if (cclutDataBuffer > " ") - set cclutParserText = concat(cclutParserText, " ", cclutDataBuffer) - else - ;Error occurred in cclutParseColumn, return - return - endif - set cclutHasComma = 1 - call parser(cclutParserText) - set cclutDataBuffer = " " - set cclutMockColumnIndex = cclutMockColumnIndex + 1 - endif - set cclutMockDataIndex = cclutMockDataIndex + 1 - else - set cclutEscapeBuffer = substring(cclutMockDataIndex + 1, 4, CCLUT_ROW_DATA) - if (cclutEscapeBuffer = "null") - ;Validate that null is by itself in the column - if ((cclutMockDataIndex = 1 or - (substring(cclutMockDataIndex - 1, 1, CCLUT_ROW_DATA) = "|" and - (cclutMockDataIndex = 2 or substring(cclutMockDataIndex - 2, 1, CCLUT_ROW_DATA) != "\"))) - and - (cclutMockDataIndex + 4 = cclutMockDataLength or - substring(cclutMockDataIndex + 5, 1, CCLUT_ROW_DATA) = "|")) - set cclutMockColumnIndex = cclutMockColumnIndex + 1 - if (cclutMockDataLength != cclutMockDataIndex + 4) - set cclutMockDataIndex = cclutMockDataIndex + 4 - endif - set cclutNullColumn = TRUE - else - ;\null must be by itself - call cclexception(100, "E", - concat("cclutAddMockData() - \null column must have no other characters. rowData: ", - CCLUT_ROW_DATA)) - call parser(" reset ") - call parser(" set modify system go ") - return - endif - else - ;Invalid escape character - call cclexception(100, "E", concat("cclutAddMockData() - Invalid escape sequence. rowData: ", - CCLUT_ROW_DATA)) - call parser(" reset ") - call parser(" set modify system go ") - return - endif - endif - ;All other characters + while (textlen(cclutMockValues) > 0) + set cclutMockColumnIndex = cclutMockColumnIndex + 1 + set cclutMockValue = notrim(cclut::cclutNextPipeValue(cclutMockValues)) + if (cclutMockValue != CCLUT_ESCAPED_NULL) + if (cclut::cclutValidateNoNulls(cclutMockValue) = FALSE) + return + endif + set cclutMockValue = notrim(cclut::cclutNormalizeEscapes(notrim(cclutMockValue))) + set cclutMockValue = notrim(cclut::cclutConstructDBSetStatement(cclutMockTablePos, cclutMockColumnIndex, + notrim(cclutMockValue))) + if (cclut::cclutIsEmpty(cclutMockValue) = FALSE) + call parser(concat(evaluate(cclutNeedsAComma, TRUE, ", ", " "), cclutMockValue)) + set cclutNeedsAComma = TRUE else - set cclutDataBuffer = notrim(concat(cclutDataBuffer, cclutDataCharacter)) + ;Error occurred in cclutConstructDBSetStatement, return + return endif - endfor - endif + endif + endwhile - if (cclutMockColumnIndex <= cclutMockColumnLength) - call cclexception(100, "E", concat("cclutAddMockData() - Too few columns of data. rowData: ", CCLUT_ROW_DATA)) - call parser(" reset ") - call parser(" set modify system go ") + if (cclutMockColumnIndex < cclutMockColumnLength) + call cclexception(100, "E", concat("cclutAddMockData(", CCLUT_TABLE_NAME, + ") - Too few columns of data. rowData: ", cclutRowData)) + call parser(" reset") + call parser(" generate null go") return endif ;No columns have been added meaning all are null - if (cclutHasComma = 0) - call parser(" reset ") + if (cclutNeedsAComma = FALSE) + call parser(" reset") call parser(concat(" rdb insert into ", cclut_mockTables->tables[cclutMockTablePos].replaceName, " values (")) for (cclutMockColumnIndex = 1 to cclutMockColumnLength) call parser(evaluate(cclutMockColumnIndex, 1, "NULL", ",NULL")) endfor - call parser(") end ") + call parser(") end") endif - call parser(" go ") + call parser(" go") end ;cclutAddMockData /** -Helper function to parse out a column for a mock insertion. +Helper function to replace escaped character sequences with their unescaped value. This function expects +cclutEscapedData to not have any pipes besides escaped ones (i.e. cclutEscapedData should represent a single value to be +added to a single column for cclutAddMockData). The subroutine returns TRUE if all escape sequences are valid or FALSE +if there are any invalid escape sequences. The subroutine creates an exception if it returns FALSE. +**/ +subroutine cclut::cclutValidateEscapeSequences(cclutMockValues) + if (findstring(CCLUT_BACKSLASH, replace(replace(replace(cclutMockValues, CCLUT_ESCAPED_BACKSLASH, ""), + CCLUT_ESCAPED_PIPE, ""), CCLUT_ESCAPED_NULL, "")) > 0) + call cclexception(100, "E", + concat("cclutValidateEscapeSequences() - Invalid escape sequence. rowData: ", cclutMockValues)) + return(FALSE) + endif + return(TRUE) +end ;cclut::cclutValidateEscapeSequences + +/** +Helper function to validate that there are no escaped nulls in a mocked value. Escaped nulls should be the only +characters in a given column as it indicates that the column should be null. The subroutine returns TRUE if there are +no escaped nulls or FALSE if there are any escaped nulls. The subroutine creates an exception if it returns FALSE. +**/ +subroutine cclut::cclutValidateNoNulls(cclutMockValue) + if (findstring(CCLUT_ESCAPED_NULL, replace(replace(cclutMockValue, CCLUT_ESCAPED_BACKSLASH, ""), + CCLUT_ESCAPED_PIPE, "")) > 0) + call cclexception(100, "E", + concat("cclutValidateNotNulls() - \null column must have no other characters. rowData: ", + cclutMockValue)) + call parser(" reset") + call parser(" generate null go") + return(FALSE) + endif + return(TRUE) +end ;cclut::cclutValidateNoNulls + +/** +Helper function to replace escaped character sequences with their unescaped value. This function expects +cclutEscapedData to not have any pipes besides escaped ones (i.e. cclutEscapedData should represent a single value to be +added to a single column for cclutAddMockData). +**/ +subroutine cclut::cclutNormalizeEscapes(cclutEscapedData) + return (replace(replace(cclutEscapedData, CCLUT_ESCAPED_PIPE, CCLUT_PIPE), + CCLUT_ESCAPED_BACKSLASH, CCLUT_BACKSLASH)) +end ;cclut::cclutNormalizeEscapes + +/** +Helper function to pop the next value out of a piped string for the cclutAddMockData function. The cclutPipeString +value is passed by reference and will be modified to remove the next value similar to popping an array. The returned +value will be the value that was popped. **/ -subroutine cclut::cclutParseColumn(tableIndex, columnIndex, dataBuffer) - declare CCLUT_COLUMN_COUNT = i4 with protect, constant(size(cclut_mockTables->tables[tableIndex].columns, 5)) +subroutine cclut::cclutNextPipeValue(cclutPipeString) + declare cclutPipePos = i4 with protect, noconstant(findString(CCLUT_PIPE, cclutPipeString)) + declare cclutPipeValue = vc with protect, noconstant("") + while (cclutPipePos > 0) + set cclutPipeValue = notrim(substring(1, cclutPipePos - 1, cclutPipeString)) + ;Check if the pipe is a delimiter pipe or an escaped pipe. An escaped pipe will have an odd number of + ;backslashes at the end (to account for situations like "\\" representing an escaped backslash). + if(operator(cclutPipeValue,"regexplike","(^|[^\\])(\\\\)*$")) + ;Delimiter pipe found, so update cclutPipeString to pop off the next value and return cclutPipeValue. + set cclutPipeString = + notrim(substring(cclutPipePos + 1, textlen(cclutPipeString) - cclutPipePos, cclutPipeString)) + return (cclutPipeValue) + endif + ;Escaped pipe, keep searching + set cclutPipePos = findstring(CCLUT_PIPE, cclutPipeString, cclutPipePos + 1) + endwhile + ;Found no delimiter pipes, so the string is complete + set cclutPipeValue = notrim(cclutPipeString) + set cclutPipeString = trim("") + return (cclutPipeValue) +end ;cclut::cclutNextPipeValue + + +/** +Helper function to construct a column for a mock insertion. cclutTableIndex is the index of the table within the +cclut_mockTables->tables array. cclutColumnIndex is the index of the column within the +cclut_mockTables->tables->columns array. cclutDataBuffer is the data that will be inserted into the column. The +subroutine will return a string in the form of " = " with appropriate wrapping of data for certain data +types. +**/ +subroutine cclut::cclutConstructDBSetStatement(cclutTableIndex, cclutColumnIndex, cclutDataBuffer) + declare CCLUT_COLUMN_COUNT = i4 with protect, constant(size(cclut_mockTables->tables[cclutTableIndex].columns, 5)) declare cclutMockColumnType = vc with protect, noconstant("") declare cclutMockColumnName = vc with protect, noconstant("") - if (columnIndex > CCLUT_COLUMN_COUNT) - call cclexception(100, "E", concat("cclutParseColumn() - Too many columns of data added to table. tableName: ", - cclut_mockTables->tables[tableIndex].originalName)) - call parser(" reset ") - call parser(" set modify system go ") + if (cclutColumnIndex > CCLUT_COLUMN_COUNT) + call cclexception(100, "E", concat("cclutConstructDBSetStatement(", + cclut_mockTables->tables[cclutTableIndex].originalName, ") - Too many columns of data added to table.")) + call parser(" reset") + call parser(" generate null go") return("") endif - set cclutMockColumnType = cclut_mockTables->tables[tableIndex].columns[columnIndex].columnType - set cclutMockColumnName = cclut_mockTables->tables[tableIndex].columns[columnIndex].columnName + set cclutMockColumnType = cclut_mockTables->tables[cclutTableIndex].columns[cclutColumnIndex].columnType + set cclutMockColumnName = cclut_mockTables->tables[cclutTableIndex].columns[cclutColumnIndex].columnName ;Use the @ delimiter for string columns if (findstring("C", cclutMockColumnType) > 0) + if (textlen(cclutDataBuffer) = 0) + return(concat(cclutMockColumnName, ' = trim("")')) + endif return(concat(cclutMockColumnName, " = @", - trim(cnvtstring(size(dataBuffer)), 3), ":", dataBuffer, "@ ")) + trim(cnvtstring(textlen(cclutDataBuffer)), 3), ":", cclutDataBuffer, "@")) ;Use cnvtdatetime for date columns elseif (findstring("D", cclutMockColumnType) > 0) - return(concat(cclutMockColumnName, ^ = cnvtdatetime("^, dataBuffer, ^") ^)) + return(concat(cclutMockColumnName, ^ = cnvtdatetime("^, cclutDataBuffer, ^")^)) ;Everything else is set directly else - return(concat(cclutMockColumnName, " = ", dataBuffer)) + return(concat(cclutMockColumnName, " = ", cclutDataBuffer)) endif -end ;cclut::cclutParseColumn +end ;cclut::cclutConstructDBSetStatement /** -Clears all data from the mock table. This is functionally similar to a truncate. tableName is required. The table -must have been created through cclutCreateMockTable() or else an error will be thrown. +Clears all data from a specified mock table. This is functionally similar to a truncate. tableName is required. The +mock table must have been created through cclutCreateMockTable() or else an error will be thrown. @param tableName - The table to be cleared. + The name of the source table for the mock table to be cleared. Example: call cclutClearMockData("person") **/ -subroutine cclutClearMockData(tableName) - ;Declare local variables - declare CCLUT_TABLE_NAME = vc with protect, constant(trim(cnvtupper(tableName), 3)) +subroutine cclutClearMockData(cclutTableName) + declare CCLUT_TABLE_NAME = vc with protect, constant(cnvtupper(cclutTableName)) declare cclutMockTablePos = i4 with protect, noconstant(0) - declare cclutMockTableIndex = i4 with protect, noconstant(0) ;Validate inbound parameters - if (CCLUT_TABLE_NAME <= " ") - call cclexception(100, "E", "cclutClearMockData() - tableName is a required field") + if (cclut::cclutValidateParameterIsNotEmpty(CCLUT_TABLE_NAME, "tableName") = FALSE) return endif ;Validate that the table exists and has been created - set cclutMockTablePos = locateval(cclutMockTableIndex, 1, size(cclut_mockTables->tables, 5), CCLUT_TABLE_NAME, - cclut_mockTables->tables[cclutMockTableIndex].originalName) + set cclutMockTablePos = cclut::cclutValidateMockTableIsDefined(CCLUT_TABLE_NAME) if (cclutMockTablePos < 1) - call cclexception(100, "E", concat("cclutClearMockData() - tableName has not been mocked. tableName: ", - CCLUT_TABLE_NAME)) return - elseif (cclut_mockTables->tables[cclutMockTablePos].isFinalized = FALSE) - call cclexception(100, "E", concat("cclutClearMockData() - tableName has not been created. tableName: ", - CCLUT_TABLE_NAME)) + endif + if (cclut::cclutValidateMockTableIsCreated(CCLUT_TABLE_NAME) = FALSE) return endif - call parser(concat(" delete from ", cclut_mockTables->tables[cclutMockTablePos].replaceName, " where seq = 1 go ")) + call parser(concat(" delete from ", cclut_mockTables->tables[cclutMockTablePos].replaceName, " where seq = 1 go")) end ;cclutClearMockData -%#endif CCLUTMOCK_TABLE_INC \ No newline at end of file +%#endif CCLUTMOCK_TABLE_INC diff --git a/cclunit-framework-source/src/test/ccl/cclut_execute_program_with_mocks_happy.prg b/cclunit-framework-source/src/test/ccl/cclut_execute_program_with_mocks_happy.prg deleted file mode 100644 index 953d202..0000000 --- a/cclunit-framework-source/src/test/ccl/cclut_execute_program_with_mocks_happy.prg +++ /dev/null @@ -1,84 +0,0 @@ -;****************************************************************************** -; This program is for unit testing happy path of cclutExecuteProgramWithMocks * -;****************************************************************************** -drop program cclut_execute_mocks_happy:dba go -create program cclut_execute_mocks_happy:dba - -/* Expected reply structure -record reply ( - 1 number_parameter = i4 - 1 string_parameter = vc - 1 public_subroutine = i4 - 1 test_subroutine = i4 - 1 mock_subroutine = i4 - 1 regular_join[*] - 2 person_id = f8 - 2 encounter_id = f8 - 2 encounter_alias = vc - 1 left_join[*] - 2 person_id = f8 - 2 encounter_id = f8 - 2 encounter_alias = vc - 1 rdb_join[*] - 2 columns = vc - 2 data = vc -) -*/ - -declare PUBLIC::InternalSubroutine(null) = null with protect - -subroutine (PUBLIC::InternalSubroutine(null) = null with protect) - set reply->public_subroutine = 1 -end - -call InternalSubroutine(null) - -set reply->number_parameter = $1 -set reply->string_parameter = $2 - -declare newSize = i4 with protect, noconstant(0) - -select into "nl:" -from sample_person sp - ,sample_encounter se - ,sample_encounter_alias sea -plan sp -join se - where se.person_id = sp.person_id -join sea - where sea.encounter_id = se.encounter_id -detail - newSize = size(reply->regular_join, 5) + 1 - stat = alterlist(reply->regular_join, newSize) - reply->regular_join[newSize].person_id = sp.person_id - reply->regular_join[newSize].encounter_id = se.encounter_id - reply->regular_join[newSize].encounter_alias = sea.encounter_alias -with nocounter - -select into "nl:" -from sample_person sp - ,(left join sample_encounter se on se.person_id = sp.person_id) - ,(left join sample_encounter_alias sea on sea.encounter_id = se.encounter_id) -plan sp -join se -join sea -order by sp.person_id -detail - newSize = size(reply->left_join, 5) + 1 - stat = alterlist(reply->left_join, newSize) - reply->left_join[newSize].person_id = sp.person_id - reply->left_join[newSize].encounter_id = se.encounter_id - reply->left_join[newSize].encounter_alias = sea.encounter_alias -with nocounter - -rdb set output "ccluserdir:cclut_happy.dat" end -rdb - select * - from sample_person sp - ,sample_encounter se - ,sample_encounter_alias sea - where se.person_id = sp.person_id - and sea.encounter_id = se.encounter_id -end - -end go \ No newline at end of file diff --git a/cclunit-framework-source/src/test/ccl/ut_cclut_execute_program_with_mocks_happy.prg b/cclunit-framework-source/src/test/ccl/ut_cclut_execute_program_with_mocks_happy.prg new file mode 100644 index 0000000..bd65778 --- /dev/null +++ b/cclunit-framework-source/src/test/ccl/ut_cclut_execute_program_with_mocks_happy.prg @@ -0,0 +1,81 @@ +;****************************************************************************** +; This program is for unit testing happy path of cclutExecuteProgramWithMocks * +;****************************************************************************** +drop program ut_cclut_execute_mocks_happy:dba go +create program ut_cclut_execute_mocks_happy:dba + +/* Expected reply structure +record reply ( + 1 number_parameter = i4 + 1 string_parameter = vc + 1 regular_join[*] + 2 person_id = f8 + 2 encounter_id = f8 + 2 encounter_alias = vc + 1 left_join[*] + 2 person_id = f8 + 2 encounter_id = f8 + 2 encounter_alias = vc + 1 rdb_join[*] + 2 columns = vc + 2 data = vc +) +*/ + +declare public::internalSubroutine(null) = null with protect + +subroutine (public::internalSubroutine(null) = null with protect) + set public_subroutine = 1 + + set reply->number_parameter = $1 + set reply->string_parameter = $2 + + declare newSize = i4 with protect, noconstant(0) + + select into "nl:" + from sample_person sp + ,sample_encounter se + ,sample_encounter_alias sea + plan sp + join se + where se.person_id = sp.person_id + join sea + where sea.encounter_id = se.encounter_id + detail + newSize = size(reply->regular_join, 5) + 1 + stat = alterlist(reply->regular_join, newSize) + reply->regular_join[newSize].person_id = sp.person_id + reply->regular_join[newSize].encounter_id = se.encounter_id + reply->regular_join[newSize].encounter_alias = sea.encounter_alias + with nocounter + + select into "nl:" + from sample_person sp + ,(left join sample_encounter se on se.person_id = sp.person_id) + ,(left join sample_encounter_alias sea on sea.encounter_id = se.encounter_id) + plan sp + join se + join sea + order by sp.person_id + detail + newSize = size(reply->left_join, 5) + 1 + stat = alterlist(reply->left_join, newSize) + reply->left_join[newSize].person_id = sp.person_id + reply->left_join[newSize].encounter_id = se.encounter_id + reply->left_join[newSize].encounter_alias = sea.encounter_alias + with nocounter + + rdb set output "ccluserdir:cclut_happy.dat" end + rdb + select * + from sample_person sp + ,sample_encounter se + ,sample_encounter_alias sea + where se.person_id = sp.person_id + and sea.encounter_id = se.encounter_id + end +end + +call internalSubroutine(null) + +end go diff --git a/cclunit-framework-source/src/test/ccl/ut_cclut_execute_test_case.inc b/cclunit-framework-source/src/test/ccl/ut_cclut_execute_test_case.inc index 267385c..0271da4 100644 --- a/cclunit-framework-source/src/test/ccl/ut_cclut_execute_test_case.inc +++ b/cclunit-framework-source/src/test/ccl/ut_cclut_execute_test_case.inc @@ -191,67 +191,67 @@ subroutine validateListingXml(xml) ; call echo(build2("listingXml = ", xml)) call cclutAssertEndsWith(CURREF, "validate listingXml", -~183018311832187918801881<\ -NBR>1833183418351836<\ -![CDATA[*/]]>18371838\ -1839184018411842184318441845\ -184618471848\ -18491850\ -185118521853185418551856185718581859186018611862186318641865\ -1866\ -1867186818691870\ -1871187218731874187518761877<\ -/LINE>18781879<\ -/LINE>18801881<\ -/TEXT>1882188318841885<\ -/LINE>188618871888<\ -NBR>18891890189\ -11892189318941895189618971898<\ -![CDATA[ endif]]>1899190019011902\ -19031904190519061907\ -19081909<\ -/LINE>1910191119121913191419151916<\ -/LINE>1917~, xml) +NBR>1882188318841885<\ +![CDATA[*/]]>18861887\ +1888188918901891189218931894\ +189518961897\ +18981899\ +190019011902190319041905190619071908190919101911191219131914\ +1915\ +1916191719181919\ +1920192119221923192419251926<\ +/LINE>19271928<\ +/LINE>19291930<\ +/TEXT>1931193219331934<\ +/LINE>193519361937<\ +NBR>19381939194\ +01941194219431944194519461947<\ +![CDATA[ endif]]>1948194919501951\ +19521953195419551956\ +19571958<\ +/LINE>1959196019611962196319641965<\ +/LINE>1966~, xml) end ;;;validateListingXml @@ -299,7 +299,7 @@ subroutine validateResultsXml(xml) call cclutAssertI4Equal(CURREF, "validate assert found 1.1", foundInd, TRUE) set lineNbr = cclut::retrieveXmlContent(xmlAssert, "lineNumber", 1, foundInd) call cclutAssertI4Equal(CURREF, "validate line number found 1.1", foundInd, TRUE) - call cclutAssertVCEqual(CURREF, "validate line number 1.1", lineNbr, "1852") + call cclutAssertVCEqual(CURREF, "validate line number 1.1", lineNbr, "1901") set assertContext = cclut::retrieveXmlContent(xmlAssert, "context", 1, foundInd) call cclutAssertI4Equal(CURREF, "validate assert context found 1.1", foundInd, TRUE) call cclutAssertVCEqual(CURREF, "validate assert context 1.1", assertContext, "setupOnce executed") @@ -328,7 +328,7 @@ subroutine validateResultsXml(xml) call cclutAssertI4Equal(CURREF, "validate assert found 2.1", foundInd, TRUE) set lineNbr = cclut::retrieveXmlContent(xmlAssert, "lineNumber", 1, foundInd) call cclutAssertI4Equal(CURREF, "validate line number found 2.1", foundInd, TRUE) - call cclutAssertVCEqual(CURREF, "validate line number 2.1", lineNbr, "1872") + call cclutAssertVCEqual(CURREF, "validate line number 2.1", lineNbr, "1921") set assertContext = cclut::retrieveXmlContent(xmlAssert, "context", 1, foundInd) call cclutAssertI4Equal(CURREF, "validate assert context found 2.1", foundInd, TRUE) call cclutAssertVCEqual(CURREF, "validate assert context 2.1", assertContext, "setup executed") @@ -344,7 +344,7 @@ subroutine validateResultsXml(xml) call cclutAssertI4Equal(CURREF, "validate assert found 2.2", foundInd, TRUE) set lineNbr = cclut::retrieveXmlContent(xmlAssert, "lineNumber", 1, foundInd) call cclutAssertI4Equal(CURREF, "validate line number found 2.2", foundInd, TRUE) - call cclutAssertVCEqual(CURREF, "validate line number 2.2", lineNbr, "1892") + call cclutAssertVCEqual(CURREF, "validate line number 2.2", lineNbr, "1941") set assertContext = cclut::retrieveXmlContent(xmlAssert, "context", 1, foundInd) call cclutAssertI4Equal(CURREF, "validate assert context found 2.2", foundInd, TRUE) call cclutAssertVCEqual(CURREF, "validate assert context 2.2", assertContext, "testOne executed") @@ -361,7 +361,7 @@ subroutine validateResultsXml(xml) call cclutAssertI4Equal(CURREF, "validate assert found 2.3", foundInd, TRUE) set lineNbr = cclut::retrieveXmlContent(xmlAssert, "lineNumber", 1, foundInd) call cclutAssertI4Equal(CURREF, "validate line number found 2.3", foundInd, TRUE) - call cclutAssertVCEqual(CURREF, "validate line number 2.3", lineNbr, "1882") + call cclutAssertVCEqual(CURREF, "validate line number 2.3", lineNbr, "1931") set assertContext = cclut::retrieveXmlContent(xmlAssert, "context", 1, foundInd) call cclutAssertI4Equal(CURREF, "validate assert context found 2.3", foundInd, TRUE) call cclutAssertVCEqual(CURREF, "validate assert context 2.3", assertContext, "teardown executed") @@ -407,7 +407,7 @@ subroutine validateResultsXml(xml) call cclutAssertI4Equal(CURREF, "validate assert found 5.1", foundInd, TRUE) set lineNbr = cclut::retrieveXmlContent(xmlAssert, "lineNumber", 1, foundInd) call cclutAssertI4Equal(CURREF, "validate line number found 5.1", foundInd, TRUE) - call cclutAssertVCEqual(CURREF, "validate line number 5.1", lineNbr, "1862") + call cclutAssertVCEqual(CURREF, "validate line number 5.1", lineNbr, "1911") set assertContext = cclut::retrieveXmlContent(xmlAssert, "context", 1, foundInd) call cclutAssertI4Equal(CURREF, "validate assert context found 5.1", foundInd, TRUE) call cclutAssertVCEqual(CURREF, "validate assert context 5.1", assertContext, "teardownOnce executed") diff --git a/cclunit-framework-source/src/test/ccl/ut_cclut_execute_test_case_file.inc b/cclunit-framework-source/src/test/ccl/ut_cclut_execute_test_case_file.inc index 7111c44..fefd6ed 100644 --- a/cclunit-framework-source/src/test/ccl/ut_cclut_execute_test_case_file.inc +++ b/cclunit-framework-source/src/test/ccl/ut_cclut_execute_test_case_file.inc @@ -214,67 +214,67 @@ subroutine validateListingXml(xml) ; call echo(build2("listingXml = ", xml)) call cclutAssertEndsWith(CURREF, "validate listingXml", -~183018311832187918801881<\ -NBR>1833183418351836<\ -![CDATA[*/]]>18371838\ -1839184018411842184318441845\ -184618471848\ -18491850\ -185118521853185418551856185718581859186018611862186318641865\ -1866\ -1867186818691870\ -1871187218731874187518761877<\ -/LINE>18781879<\ -/LINE>18801881<\ -/TEXT>1882188318841885<\ -/LINE>188618871888<\ -NBR>18891890189\ -11892189318941895189618971898<\ -![CDATA[ endif]]>1899190019011902\ -19031904190519061907\ -19081909<\ -/LINE>1910191119121913191419151916<\ -/LINE>1917~, xml) +NBR>1882188318841885<\ +![CDATA[*/]]>18861887\ +1888188918901891189218931894\ +189518961897\ +18981899\ +190019011902190319041905190619071908190919101911191219131914\ +1915\ +1916191719181919\ +1920192119221923192419251926<\ +/LINE>19271928<\ +/LINE>19291930<\ +/TEXT>1931193219331934<\ +/LINE>193519361937<\ +NBR>19381939194\ +01941194219431944194519461947<\ +![CDATA[ endif]]>1948194919501951\ +19521953195419551956\ +19571958<\ +/LINE>1959196019611962196319641965<\ +/LINE>1966~, xml) end ;;;validateListingXml @@ -319,7 +319,7 @@ subroutine validateResultsXml(xml, legacyFormat) call cclutAssertI4Equal(CURREF, "validate assert found 1.1", foundInd, TRUE) set lineNbr = cclut::retrieveXmlContent(xmlAssert, "lineNumber", 1, foundInd) call cclutAssertI4Equal(CURREF, "validate line number found 1.1", foundInd, TRUE) - call cclutAssertVCEqual(CURREF, "validate line number 1.1", lineNbr, "1852") + call cclutAssertVCEqual(CURREF, "validate line number 1.1", lineNbr, "1901") set assertContext = cclut::retrieveXmlContent(xmlAssert, "context", 1, foundInd) call cclutAssertI4Equal(CURREF, "validate assert context found 1.1", foundInd, TRUE) call cclutAssertVCEqual(CURREF, "validate assert context 1.1", assertContext, "setupOnce executed") @@ -352,7 +352,7 @@ subroutine validateResultsXml(xml, legacyFormat) call cclutAssertI4Equal(CURREF, "validate assert found 2.1", foundInd, TRUE) set lineNbr = cclut::retrieveXmlContent(xmlAssert, "lineNumber", 1, foundInd) call cclutAssertI4Equal(CURREF, "validate line number found 2.1", foundInd, TRUE) - call cclutAssertVCEqual(CURREF, "validate line number 2.1", lineNbr, "1872") + call cclutAssertVCEqual(CURREF, "validate line number 2.1", lineNbr, "1921") set assertContext = cclut::retrieveXmlContent(xmlAssert, "context", 1, foundInd) call cclutAssertI4Equal(CURREF, "validate assert context found 2.1", foundInd, TRUE) call cclutAssertVCEqual(CURREF, "validate assert context 2.1", assertContext, "setup executed") @@ -372,7 +372,7 @@ subroutine validateResultsXml(xml, legacyFormat) call cclutAssertI4Equal(CURREF, "validate assert found 2.2", foundInd, TRUE) set lineNbr = cclut::retrieveXmlContent(xmlAssert, "lineNumber", 1, foundInd) call cclutAssertI4Equal(CURREF, "validate line number found 2.2", foundInd, TRUE) - call cclutAssertVCEqual(CURREF, "validate line number 2.2", lineNbr, "1892") + call cclutAssertVCEqual(CURREF, "validate line number 2.2", lineNbr, "1941") set assertContext = cclut::retrieveXmlContent(xmlAssert, "context", 1, foundInd) call cclutAssertI4Equal(CURREF, "validate assert context found 2.2", foundInd, TRUE) call cclutAssertVCEqual(CURREF, "validate assert context 2.2", assertContext, "testOne executed") @@ -393,7 +393,7 @@ subroutine validateResultsXml(xml, legacyFormat) call cclutAssertI4Equal(CURREF, "validate assert found 2.3", foundInd, TRUE) set lineNbr = cclut::retrieveXmlContent(xmlAssert, "lineNumber", 1, foundInd) call cclutAssertI4Equal(CURREF, "validate line number found 2.3", foundInd, TRUE) - call cclutAssertVCEqual(CURREF, "validate line number 2.3", lineNbr, "1882") + call cclutAssertVCEqual(CURREF, "validate line number 2.3", lineNbr, "1931") set assertContext = cclut::retrieveXmlContent(xmlAssert, "context", 1, foundInd) call cclutAssertI4Equal(CURREF, "validate assert context found 2.3", foundInd, TRUE) call cclutAssertVCEqual(CURREF, "validate assert context 2.3", assertContext, "teardown executed") @@ -443,7 +443,7 @@ subroutine validateResultsXml(xml, legacyFormat) call cclutAssertI4Equal(CURREF, "validate assert found 5.1", foundInd, TRUE) set lineNbr = cclut::retrieveXmlContent(xmlAssert, "lineNumber", 1, foundInd) call cclutAssertI4Equal(CURREF, "validate line number found 5.1", foundInd, TRUE) - call cclutAssertVCEqual(CURREF, "validate line number 5.1", lineNbr, "1862") + call cclutAssertVCEqual(CURREF, "validate line number 5.1", lineNbr, "1911") set assertContext = cclut::retrieveXmlContent(xmlAssert, "context", 1, foundInd) call cclutAssertI4Equal(CURREF, "validate assert context found 5.1", foundInd, TRUE) call cclutAssertVCEqual(CURREF, "validate assert context 5.1", assertContext, "teardownOnce executed") diff --git a/cclunit-framework-source/src/test/ccl/ut_cclut_mock.inc b/cclunit-framework-source/src/test/ccl/ut_cclut_mock.inc index a018356..f8e207f 100644 --- a/cclunit-framework-source/src/test/ccl/ut_cclut_mock.inc +++ b/cclunit-framework-source/src/test/ccl/ut_cclut_mock.inc @@ -1,73 +1,122 @@ declare setup(dummyVar = i2) = null declare tearDown(dummyVar = i2) = null -subroutine setup(dummyVar) - null -end ;setup - subroutine tearDown(dummyVar) call cclutRemoveAllMocks(null) - rollback + rollback end ;tearDown ;********************************************************************************************************************************** ;** cclutAddMockImplementation ;********************************************************************************************************************************** /* test_cclutAddMockImplementation_happy ******************************************************************** -* Scenario: Adds a mock implementation that can be used with cclutExecuteProgramWithMocks * +* Scenario: Adds mock implementations that can be used with cclutExecuteProgramWithMocks * ************************************************************************************************************/ subroutine test_cclutAddMockImplementation_happy(null) - call echo("~~~***~~~***test_cclutAddMockImplementation_happy***~~~***~~~") - - call cclutAddMockImplementation("sample_subroutine", "mock_subroutine") + call cclutAddMockImplementation("sample_subroutine", "mock_subroutine") - call cclutAsserti4Equal(CURREF, "test_cclutAddMockImplementation_happy", + call cclutAsserti4Equal(CURREF, "test_cclutAddMockImplementation_happy 001", size(cclut_mockImplementations->implementations, 5), 1) - call cclutAssertvcEqual(CURREF, "test_cclutAddMockImplementation_happy", + call cclutAssertvcEqual(CURREF, "test_cclutAddMockImplementation_happy 002", + cclut_mockImplementations->implementations[1].originalName, "SAMPLE_SUBROUTINE") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockImplementation_happy 003", + cclut_mockImplementations->implementations[1].replaceName, "MOCK_SUBROUTINE") + + call cclutAddMockImplementation("second_subroutine", "new_subroutine") + + call cclutAsserti4Equal(CURREF, "test_cclutAddMockImplementation_happy 004", + size(cclut_mockImplementations->implementations, 5), 2) + call cclutAssertvcEqual(CURREF, "test_cclutAddMockImplementation_happy 005", cclut_mockImplementations->implementations[1].originalName, "SAMPLE_SUBROUTINE") - call cclutAssertvcEqual(CURREF, "test_cclutAddMockImplementation_happy", + call cclutAssertvcEqual(CURREF, "test_cclutAddMockImplementation_happy 006", cclut_mockImplementations->implementations[1].replaceName, "MOCK_SUBROUTINE") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockImplementation_happy 007", + cclut_mockImplementations->implementations[2].originalName, "SECOND_SUBROUTINE") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockImplementation_happy 008", + cclut_mockImplementations->implementations[2].replaceName, "NEW_SUBROUTINE") end ;test_cclutAddMockImplementation_happy +/* test_cclutAddMockImplementation_different_cases ********************************************************** +* Scenario: Adds mock implementations with different cases * +************************************************************************************************************/ +subroutine test_cclutAddMockImplementation_different_cases(null) + call cclutAddMockImplementation("sAmpLE_subROUtine", "MoCK_suBROutiNE") + + call cclutAsserti4Equal(CURREF, "test_cclutAddMockImplementation_different_cases 001", + size(cclut_mockImplementations->implementations, 5), 1) + call cclutAssertvcEqual(CURREF, "test_cclutAddMockImplementation_different_cases 002", + cclut_mockImplementations->implementations[1].originalName, "SAMPLE_SUBROUTINE") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockImplementation_different_cases 003", + cclut_mockImplementations->implementations[1].replaceName, "MOCK_SUBROUTINE") + + call cclutAddMockImplementation("sEcOnD_sUbRoUtInE", "NeW_sUbRoUtInE") + + call cclutAsserti4Equal(CURREF, "test_cclutAddMockImplementation_different_cases 004", + size(cclut_mockImplementations->implementations, 5), 2) + call cclutAssertvcEqual(CURREF, "test_cclutAddMockImplementation_different_cases 005", + cclut_mockImplementations->implementations[1].originalName, "SAMPLE_SUBROUTINE") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockImplementation_different_cases 006", + cclut_mockImplementations->implementations[1].replaceName, "MOCK_SUBROUTINE") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockImplementation_different_cases 007", + cclut_mockImplementations->implementations[2].originalName, "SECOND_SUBROUTINE") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockImplementation_different_cases 008", + cclut_mockImplementations->implementations[2].replaceName, "NEW_SUBROUTINE") +end ;test_cclutAddMockImplementation_different_cases + /* test_cclutAddMockImplementation_existing_implementation ************************************************** * Scenario: Replaces the mock name of an implementation if it was already added * ************************************************************************************************************/ subroutine test_cclutAddMockImplementation_existing_implementation(null) - call echo("~~~***~~~***test_cclutAddMockImplementation_existing_implementation***~~~***~~~") - call cclutAddMockImplementation("sample_subroutine", "mock_subroutine") - call cclutAsserti4Equal(CURREF, "test_cclutAddMockImplementation_happy", + call cclutAsserti4Equal(CURREF, "test_cclutAddMockImplementation_existing_implementation 001", size(cclut_mockImplementations->implementations, 5), 1) - call cclutAssertvcEqual(CURREF, "test_cclutAddMockImplementation_happy", + call cclutAssertvcEqual(CURREF, "test_cclutAddMockImplementation_existing_implementation 002", cclut_mockImplementations->implementations[1].originalName, "SAMPLE_SUBROUTINE") - call cclutAssertvcEqual(CURREF, "test_cclutAddMockImplementation_happy", + call cclutAssertvcEqual(CURREF, "test_cclutAddMockImplementation_existing_implementation 003", cclut_mockImplementations->implementations[1].replaceName, "MOCK_SUBROUTINE") - call cclutAddMockImplementation("sample_subroutine", "new_subroutine") + call cclutAddMockImplementation("second_subroutine", "new_subroutine") - call cclutAsserti4Equal(CURREF, "test_cclutAddMockImplementation_happy", - size(cclut_mockImplementations->implementations, 5), 1) - call cclutAssertvcEqual(CURREF, "test_cclutAddMockImplementation_happy", + call cclutAsserti4Equal(CURREF, "test_cclutAddMockImplementation_existing_implementation 004", + size(cclut_mockImplementations->implementations, 5), 2) + call cclutAssertvcEqual(CURREF, "test_cclutAddMockImplementation_existing_implementation 005", + cclut_mockImplementations->implementations[1].originalName, "SAMPLE_SUBROUTINE") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockImplementation_existing_implementation 006", + cclut_mockImplementations->implementations[1].replaceName, "MOCK_SUBROUTINE") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockImplementation_existing_implementation 007", + cclut_mockImplementations->implementations[2].originalName, "SECOND_SUBROUTINE") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockImplementation_existing_implementation 008", + cclut_mockImplementations->implementations[2].replaceName, "NEW_SUBROUTINE") + + call cclutAddMockImplementation("sample_subroutine", "replace_subroutine") + call cclutAddMockImplementation("second_subroutine", "test_subroutine") + + call cclutAsserti4Equal(CURREF, "test_cclutAddMockImplementation_existing_implementation 009", + size(cclut_mockImplementations->implementations, 5), 2) + call cclutAssertvcEqual(CURREF, "test_cclutAddMockImplementation_existing_implementation 010", cclut_mockImplementations->implementations[1].originalName, "SAMPLE_SUBROUTINE") - call cclutAssertvcEqual(CURREF, "test_cclutAddMockImplementation_happy", - cclut_mockImplementations->implementations[1].replaceName, "NEW_SUBROUTINE") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockImplementation_existing_implementation 011", + cclut_mockImplementations->implementations[1].replaceName, "REPLACE_SUBROUTINE") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockImplementation_existing_implementation 012", + cclut_mockImplementations->implementations[2].originalName, "SECOND_SUBROUTINE") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockImplementation_existing_implementation 013", + cclut_mockImplementations->implementations[2].replaceName, "TEST_SUBROUTINE") end ;test_cclutAddMockImplementation_happy /* test_cclutAddMockImplementation_missing_originalName ***************************************************** * Scenario: Throws an error when an empty originalName is supplied to the function (after trimming) * ************************************************************************************************************/ subroutine test_cclutAddMockImplementation_missing_originalName(null) - call echo("~~~***~~~***test_cclutAddMockImplementation_missing_originalName***~~~***~~~") - - declare errorMessage = vc with protect, noconstant("") + declare errorMessage = vc with protect, noconstant("") declare errorCode = i4 with protect, noconstant(0) - call cclutAddMockImplementation(" ", "mock_subroutine") + call cclutAddMockImplementation(" ", "mock_subroutine") - set errorCode = error(errorMessage, 0) + set errorCode = error(errorMessage, 0) - call cclutAssertVcOperator(CURREF, "test_cclutAddMockImplementation_missing_originalName", trim(errorMessage, 3), - "regexplike", concat("%CCL-E-392-PRG_[0-9]+_[0-9]+\([^)]+\)[0-9]+:[0-9]+\{CCLEXCEPTION\(\)\}Exception\(100\):", + call cclutAssertVcOperator(CURREF, "test_cclutAddMockImplementation_missing_originalName 001", + trim(errorMessage, 3), "regexplike", + concat("%CCL-E-392-PRG_[0-9]+_[0-9]+\([^)]+\)[0-9]+:[0-9]+\{CCLEXCEPTION\(\)\}Exception\(100\):", " cclutAddMockImplementation\(\) - originalName is a required field.")) end ;test_cclutAddMockImplementation_missing_originalName @@ -75,57 +124,82 @@ end ;test_cclutAddMockImplementation_missing_originalName * Scenario: Throws an error when an empty replaceName is supplied to the function (after trimming) * ************************************************************************************************************/ subroutine test_cclutAddMockImplementation_missing_replaceName(null) - call echo("~~~***~~~***test_cclutAddMockImplementation_missing_replaceName***~~~***~~~") - - declare errorMessage = vc with protect, noconstant("") + declare errorMessage = vc with protect, noconstant("") declare errorCode = i4 with protect, noconstant(0) - call cclutAddMockImplementation("sample_subroutine", " ") + call cclutAddMockImplementation("sample_subroutine", " ") - set errorCode = error(errorMessage, 0) + set errorCode = error(errorMessage, 0) - call cclutAssertVcOperator(CURREF, "test_cclutAddMockImplementation_missing_replaceName", trim(errorMessage, 3), + call cclutAssertVcOperator(CURREF, "test_cclutAddMockImplementation_missing_replaceName 001", trim(errorMessage, 3), "regexplike", concat("%CCL-E-392-PRG_[0-9]+_[0-9]+\([^)]+\)[0-9]+:[0-9]+\{CCLEXCEPTION\(\)\}Exception\(100\):", - " cclutAddMockImplementation\(\) - replaceName is a required field.")) + " cclutAddMockImplementation\(SAMPLE_SUBROUTINE\) - replaceName is a required field.")) end ;test_cclutAddMockImplementation_missing_replaceName ;********************************************************************************************************************************** ;** cclutRemoveMockImplementation ;********************************************************************************************************************************** /* test_cclutRemoveMockImplementation_happy ***************************************************************** -* Scenario: Removes a mock implementation so that the original can be used * +* Scenario: Removes a mock implementation * ************************************************************************************************************/ subroutine test_cclutRemoveMockImplementation_happy(null) - call echo("~~~***~~~***test_cclutRemoveMockImplementation_happy***~~~***~~~") - - call cclutAddMockImplementation("sample_subroutine", "mock_subroutine") - - call cclutAsserti4Equal(CURREF, "test_cclutRemoveMockImplementation_happy", - size(cclut_mockImplementations->implementations, 5), 1) - call cclutAssertvcEqual(CURREF, "test_cclutRemoveMockImplementation_happy", - cclut_mockImplementations->implementations[1].originalName, "SAMPLE_SUBROUTINE") - call cclutAssertvcEqual(CURREF, "test_cclutRemoveMockImplementation_happy", - cclut_mockImplementations->implementations[1].replaceName, "MOCK_SUBROUTINE") - - call cclutRemoveMockImplementation("sample_subroutine") - - call cclutAsserti4Equal(CURREF, "test_cclutRemoveMockImplementation_happy", - size(cclut_mockImplementations->implementations, 5), 0) + call cclutAddMockImplementation("one_subroutine", "mock_one_subroutine") + call cclutAddMockImplementation("two_subroutine", "mock_two_subroutine") + call cclutAddMockImplementation("three_subroutine", "mock_three_subroutine") + call cclutAddMockImplementation("four_subroutine", "mock_four_subroutine") + call cclutAddMockImplementation("five_subroutine", "mock_five_subroutine") + + call cclutAsserti4Equal(CURREF, "test_cclutRemoveMockImplementation_happy 001", + size(cclut_mockImplementations->implementations, 5), 5) + call cclutAssertvcEqual(CURREF, "test_cclutRemoveMockImplementation_happy 002", + cclut_mockImplementations->implementations[1].originalName, "ONE_SUBROUTINE") + call cclutAssertvcEqual(CURREF, "test_cclutRemoveMockImplementation_happy 003", + cclut_mockImplementations->implementations[1].replaceName, "MOCK_ONE_SUBROUTINE") + call cclutAssertvcEqual(CURREF, "test_cclutRemoveMockImplementation_happy 004", + cclut_mockImplementations->implementations[2].originalName, "TWO_SUBROUTINE") + call cclutAssertvcEqual(CURREF, "test_cclutRemoveMockImplementation_happy 005", + cclut_mockImplementations->implementations[2].replaceName, "MOCK_TWO_SUBROUTINE") + call cclutAssertvcEqual(CURREF, "test_cclutRemoveMockImplementation_happy 006", + cclut_mockImplementations->implementations[3].originalName, "THREE_SUBROUTINE") + call cclutAssertvcEqual(CURREF, "test_cclutRemoveMockImplementation_happy 007", + cclut_mockImplementations->implementations[3].replaceName, "MOCK_THREE_SUBROUTINE") + call cclutAssertvcEqual(CURREF, "test_cclutRemoveMockImplementation_happy 008", + cclut_mockImplementations->implementations[4].originalName, "FOUR_SUBROUTINE") + call cclutAssertvcEqual(CURREF, "test_cclutRemoveMockImplementation_happy 009", + cclut_mockImplementations->implementations[4].replaceName, "MOCK_FOUR_SUBROUTINE") + call cclutAssertvcEqual(CURREF, "test_cclutRemoveMockImplementation_happy 010", + cclut_mockImplementations->implementations[5].originalName, "FIVE_SUBROUTINE") + call cclutAssertvcEqual(CURREF, "test_cclutRemoveMockImplementation_happy 011", + cclut_mockImplementations->implementations[5].replaceName, "MOCK_FIVE_SUBROUTINE") + + call cclutRemoveMockImplementation("one_subroutine") + call cclutRemoveMockImplementation("three_subroutine") + call cclutRemoveMockImplementation("five_subroutine") + + call cclutAsserti4Equal(CURREF, "test_cclutRemoveMockImplementation_happy 012", + size(cclut_mockImplementations->implementations, 5), 2) + call cclutAssertvcEqual(CURREF, "test_cclutRemoveMockImplementation_happy 013", + cclut_mockImplementations->implementations[1].originalName, "TWO_SUBROUTINE") + call cclutAssertvcEqual(CURREF, "test_cclutRemoveMockImplementation_happy 014", + cclut_mockImplementations->implementations[1].replaceName, "MOCK_TWO_SUBROUTINE") + call cclutAssertvcEqual(CURREF, "test_cclutRemoveMockImplementation_happy 015", + cclut_mockImplementations->implementations[2].originalName, "FOUR_SUBROUTINE") + call cclutAssertvcEqual(CURREF, "test_cclutRemoveMockImplementation_happy 016", + cclut_mockImplementations->implementations[2].replaceName, "MOCK_FOUR_SUBROUTINE") end ;test_cclutRemoveMockImplementation_happy -/* test_cclutRemoveMockImplementation_missing_originalName ***************************************************** +/* test_cclutRemoveMockImplementation_missing_originalName ************************************************** * Scenario: Throws an error when an empty originalName is supplied to the function (after trimming) * ************************************************************************************************************/ subroutine test_cclutRemoveMockImplementation_missing_originalName(null) - call echo("~~~***~~~***test_cclutRemoveMockImplementation_missing_originalName***~~~***~~~") - - declare errorMessage = vc with protect, noconstant("") + declare errorMessage = vc with protect, noconstant("") declare errorCode = i4 with protect, noconstant(0) - call cclutRemoveMockImplementation(" ") + call cclutRemoveMockImplementation(" ") - set errorCode = error(errorMessage, 0) + set errorCode = error(errorMessage, 0) - call cclutAssertVcOperator(CURREF, "test_cclutRemoveMockImplementation_missing_originalName", trim(errorMessage, 3), - "regexplike", concat("%CCL-E-392-PRG_[0-9]+_[0-9]+\([^)]+\)[0-9]+:[0-9]+\{CCLEXCEPTION\(\)\}Exception\(100\):", + call cclutAssertVcOperator(CURREF, "test_cclutRemoveMockImplementation_missing_originalName 001", + trim(errorMessage, 3), "regexplike", + concat("%CCL-E-392-PRG_[0-9]+_[0-9]+\([^)]+\)[0-9]+:[0-9]+\{CCLEXCEPTION\(\)\}Exception\(100\):", " cclutRemoveMockImplementation\(\) - originalName is a required field.")) end ;test_cclutRemoveMockImplementation_missing_originalName @@ -133,21 +207,19 @@ end ;test_cclutRemoveMockImplementation_missing_originalName ;** cclutRemoveAllMockImplementations ;********************************************************************************************************************************** /* test_cclutRemoveAllMockImplementations_happy ************************************************************* -* Scenario: Removes all mock implementations so that the originals can be used * +* Scenario: Removes all mock implementations * ************************************************************************************************************/ subroutine test_cclutRemoveAllMockImplementations_happy(null) - call echo("~~~***~~~***test_cclutRemoveAllMockImplementations_happy***~~~***~~~") + call cclutAddMockImplementation("sample_subroutine", "mock_subroutine") + call cclutAddMockImplementation("sample_subroutine_2", "mock_subroutine_2") + call cclutAddMockImplementation("sample_subroutine_3", "mock_subroutine_3") - call cclutAddMockImplementation("sample_subroutine", "mock_subroutine") - call cclutAddMockImplementation("sample_subroutine_2", "mock_subroutine_2") - call cclutAddMockImplementation("sample_subroutine_3", "mock_subroutine_3") - - call cclutAsserti4Equal(CURREF, "test_cclutRemoveAllMockImplementations_happy", + call cclutAsserti4Equal(CURREF, "test_cclutRemoveAllMockImplementations_happy 001", size(cclut_mockImplementations->implementations, 5), 3) call cclutRemoveAllMockImplementations(null) - call cclutAsserti4Equal(CURREF, "test_cclutRemoveAllMockImplementations_happy", + call cclutAsserti4Equal(CURREF, "test_cclutRemoveAllMockImplementations_happy 002", size(cclut_mockImplementations->implementations, 5), 0) end ;test_cclutRemoveAllMockImplementations_happy @@ -155,17 +227,16 @@ end ;test_cclutRemoveAllMockImplementations_happy ;** cclutExecuteProgramWithMocks ;********************************************************************************************************************************** /* test_cclutExecuteProgramWithMocks_happy ****************************************************************** -* Scenario: Executes the program using mock tables and implementations that have been set up * +* Scenario: Executes a program using mock tables and implementations that have been set up * ************************************************************************************************************/ subroutine test_cclutExecuteProgramWithMocks_happy(null) - call echo("~~~***~~~***test_cclutExecuteProgramWithMocks_happy***~~~***~~~") + declare public_subroutine = i4 with protect, noconstant(0) + declare mock_subroutine = i4 with protect, noconstant(0) + declare test_subroutine = i4 with protect, noconstant(0) - record executeReply ( + record executeReply ( 1 number_parameter = i4 1 string_parameter = vc - 1 public_subroutine = i4 - 1 test_subroutine = i4 - 1 mock_subroutine = i4 1 regular_join[*] 2 person_id = f8 2 encounter_id = f8 @@ -179,59 +250,63 @@ subroutine test_cclutExecuteProgramWithMocks_happy(null) 2 data = vc ) with protect - call cclutDefineMockTable("sample_person", "person_id", "f8") - call cclutDefineMockTable("sample_encounter", "encounter_id|person_id", "f8|f8") - call cclutDefineMockTable("sample_encounter_alias", "encounter_id|encounter_alias", "f8|vc") - call cclutCreateMockTable("sample_person") - call cclutCreateMockTable("sample_encounter") - call cclutCreateMockTable("sample_encounter_alias") + call cclutDefineMockTable("sample_person", "person_id", "f8") + call cclutDefineMockTable("sample_encounter", "encounter_id|person_id", "f8|f8") + call cclutDefineMockTable("sample_encounter_alias", "encounter_id|encounter_alias", "f8|vc") + call cclutCreateMockTable("sample_person") + call cclutCreateMockTable("sample_encounter") + call cclutCreateMockTable("sample_encounter_alias") + + call cclutAddMockData("sample_person", "1.0") + call cclutAddMockData("sample_person", "2.0") + call cclutAddMockData("sample_person", "3.0") + call cclutAddMockData("sample_encounter", "4.0|1.0") + call cclutAddMockData("sample_encounter", "5.0|2.0") + call cclutAddMockData("sample_encounter_alias", "4.0|test alias") - call cclutAddMockData("sample_person", "1.0") - call cclutAddMockData("sample_person", "2.0") - call cclutAddMockData("sample_person", "3.0") - call cclutAddMockData("sample_encounter", "4.0|1.0") - call cclutAddMockData("sample_encounter", "5.0|2.0") - call cclutAddMockData("sample_encounter_alias", "4.0|test alias") + call cclutAddMockImplementation("REPLY", "EXECUTEREPLY") - call cclutAddMockImplementation("REPLY", "EXECUTEREPLY") + call cclutExecuteProgramWithMocks("ut_cclut_execute_mocks_happy", "10,^test param^") - call cclutExecuteProgramWithMocks("cclut_execute_mocks_happy", "10,^test param^") + call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy 001", public_subroutine, 1) + call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy 002", test_subroutine, 0) + call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy 003", mock_subroutine, 0) - call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy", executeReply->number_parameter, 10) - call cclutAssertvcEqual(CURREF, "test_cclutExecuteProgramWithMocks_happy", executeReply->string_parameter, + call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy 004", executeReply->number_parameter, 10) + call cclutAssertvcEqual(CURREF, "test_cclutExecuteProgramWithMocks_happy 005", executeReply->string_parameter, "test param") - call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy", executeReply->public_subroutine, 1) - call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy", executeReply->test_subroutine, 0) - call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy", executeReply->mock_subroutine, 0) - call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy", size(executeReply->regular_join, 5), 1) - call cclutAssertf8Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy", executeReply->regular_join[1].person_id, + call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy 006", size(executeReply->regular_join, 5), + 1) + call cclutAssertf8Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy 007", executeReply->regular_join[1].person_id, 1.0) - call cclutAssertf8Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy", + call cclutAssertf8Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy 008", executeReply->regular_join[1].encounter_id, 4.0) - call cclutAssertvcEqual(CURREF, "test_cclutExecuteProgramWithMocks_happy", + call cclutAssertvcEqual(CURREF, "test_cclutExecuteProgramWithMocks_happy 009", executeReply->regular_join[1].encounter_alias, "test alias") - call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy", size(executeReply->left_join, 5), 3) - call cclutAssertf8Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy", executeReply->left_join[1].person_id, + call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy 010", size(executeReply->left_join, 5), 3) + call cclutAssertf8Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy 011", executeReply->left_join[1].person_id, 1.0) - call cclutAssertf8Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy", + call cclutAssertf8Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy 012", executeReply->left_join[1].encounter_id, 4.0) - call cclutAssertvcEqual(CURREF, "test_cclutExecuteProgramWithMocks_happy", + call cclutAssertvcEqual(CURREF, "test_cclutExecuteProgramWithMocks_happy 013", executeReply->left_join[1].encounter_alias, "test alias") - call cclutAssertf8Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy", executeReply->left_join[2].person_id, + call cclutAssertf8Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy 014", executeReply->left_join[2].person_id, 2.0) - call cclutAssertf8Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy", + call cclutAssertf8Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy 015", executeReply->left_join[2].encounter_id, 5.0) - call cclutAssertvcEqual(CURREF, "test_cclutExecuteProgramWithMocks_happy", + call cclutAssertvcEqual(CURREF, "test_cclutExecuteProgramWithMocks_happy 016", executeReply->left_join[2].encounter_alias, "") - call cclutAssertf8Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy", executeReply->left_join[3].person_id, + call cclutAssertf8Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy 017", executeReply->left_join[3].person_id, 3.0) - call cclutAssertf8Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy", + call cclutAssertf8Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy 018", executeReply->left_join[3].encounter_id, 0.0) - call cclutAssertvcEqual(CURREF, "test_cclutExecuteProgramWithMocks_happy", + call cclutAssertvcEqual(CURREF, "test_cclutExecuteProgramWithMocks_happy 019", executeReply->left_join[3].encounter_alias, "") + ;The program ut_cclut_execute_mocks_happy performs an inner join for the rdb test and writes the data to the + ;cclut_happy.dat file. set stat = alterlist(executeReply->rdb_join, 1) free define rtl2 define rtl2 is "ccluserdir:cclut_happy.dat" @@ -243,135 +318,69 @@ subroutine test_cclutExecuteProgramWithMocks_happy(null) executeReply->rdb_join[1].data = r.line with nocounter - call cclutAssertVcOperator(CURREF, "test_cclutExecuteProgramWithMocks_happy", executeReply->rdb_join[1].columns, + call cclutAssertVcOperator(CURREF, "test_cclutExecuteProgramWithMocks_happy 020", executeReply->rdb_join[1].columns, "regexplike", "PERSON_ID.*ENCOUNTER_ID.*PERSON_ID.*ENCOUNTER_ID.*ENCOUNTER_ALIAS") - call cclutAssertVcOperator(CURREF, "test_cclutExecuteProgramWithMocks_happy", executeReply->rdb_join[1].data, + call cclutAssertVcOperator(CURREF, "test_cclutExecuteProgramWithMocks_happy 021", executeReply->rdb_join[1].data, "regexplike", "1.*4.*1.*4.*test alias") end ;test_cclutExecuteProgramWithMocks_happy -declare CCLUT::InternalSubroutine(null) = null with protect - -subroutine (CCLUT::InternalSubroutine(null) = null with protect) - set executeReply->test_subroutine = 1 -end - /* test_cclutExecuteProgramWithMocks_namespace ************************************************************** * Scenario: Executes the program using the supplied namespace * ************************************************************************************************************/ subroutine test_cclutExecuteProgramWithMocks_namespace(null) - call echo("~~~***~~~***test_cclutExecuteProgramWithMocks_namespace***~~~***~~~") - - record executeReply ( - 1 number_parameter = i4 - 1 string_parameter = vc - 1 public_subroutine = i4 - 1 test_subroutine = i4 - 1 mock_subroutine = i4 - 1 regular_join[*] - 2 person_id = f8 - 2 encounter_id = f8 - 2 encounter_alias = vc - 1 left_join[*] - 2 person_id = f8 - 2 encounter_id = f8 - 2 encounter_alias = vc - 1 rdb_join[*] - 2 columns = vc - 2 data = vc - ) with protect - - call cclutDefineMockTable("sample_person", "person_id", "f8") - call cclutDefineMockTable("sample_encounter", "encounter_id|person_id", "f8|f8") - call cclutDefineMockTable("sample_encounter_alias", "encounter_id|encounter_alias", "f8|vc") - call cclutCreateMockTable("sample_person") - call cclutCreateMockTable("sample_encounter") - call cclutCreateMockTable("sample_encounter_alias") + declare public_subroutine = i4 with protect, noconstant(0) + declare mock_subroutine = i4 with protect, noconstant(0) + declare test_subroutine = i4 with protect, noconstant(0) - call cclutAddMockData("sample_person", "1.0") - call cclutAddMockData("sample_person", "2.0") - call cclutAddMockData("sample_person", "3.0") - call cclutAddMockData("sample_encounter", "4.0|1.0") - call cclutAddMockData("sample_encounter", "5.0|2.0") - call cclutAddMockData("sample_encounter_alias", "4.0|test alias") + declare cclut::internalSubroutine(null) = null with protect - call cclutAddMockImplementation("REPLY", "EXECUTEREPLY") + subroutine (cclut::internalSubroutine(null) = null with protect) + set test_subroutine = 1 + end - call cclutExecuteProgramWithMocks("cclut_execute_mocks_happy", "10,^test param^", "CCLUT") + call cclutExecuteProgramWithMocks("ut_cclut_execute_mocks_happy", "10,^test param^", "CCLUT") - call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_namespace", executeReply->public_subroutine, 0) - call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_namespace", executeReply->test_subroutine, 1) - call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_namespace", executeReply->mock_subroutine, 0) + call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_namespace 001", public_subroutine, 0) + call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_namespace 002", test_subroutine, 1) + call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_namespace 003", mock_subroutine, 0) end ;test_cclutExecuteProgramWithMocks_namespace -declare CCLUT::MockSubroutine(null) = null with protect - -subroutine (CCLUT::MockSubroutine(null) = null with protect) - set executeReply->mock_subroutine = 1 -end - /* test_cclutExecuteProgramWithMocks_mock_subroutine ******************************************************** * Scenario: Executes the program while replacing a subroutine with a mocked version * ************************************************************************************************************/ subroutine test_cclutExecuteProgramWithMocks_mock_subroutine(null) - call echo("~~~***~~~***test_cclutExecuteProgramWithMocks_mock_subroutine***~~~***~~~") + declare public_subroutine = i4 with protect, noconstant(0) + declare mock_subroutine = i4 with protect, noconstant(0) + declare test_subroutine = i4 with protect, noconstant(0) - record executeReply ( - 1 number_parameter = i4 - 1 string_parameter = vc - 1 public_subroutine = i4 - 1 test_subroutine = i4 - 1 mock_subroutine = i4 - 1 regular_join[*] - 2 person_id = f8 - 2 encounter_id = f8 - 2 encounter_alias = vc - 1 left_join[*] - 2 person_id = f8 - 2 encounter_id = f8 - 2 encounter_alias = vc - 1 rdb_join[*] - 2 columns = vc - 2 data = vc - ) with protect - - call cclutDefineMockTable("sample_person", "person_id", "f8") - call cclutDefineMockTable("sample_encounter", "encounter_id|person_id", "f8|f8") - call cclutDefineMockTable("sample_encounter_alias", "encounter_id|encounter_alias", "f8|vc") - call cclutCreateMockTable("sample_person") - call cclutCreateMockTable("sample_encounter") - call cclutCreateMockTable("sample_encounter_alias") + declare cclut::mockSubroutine(null) = null with protect - call cclutAddMockData("sample_person", "1.0") - call cclutAddMockData("sample_person", "2.0") - call cclutAddMockData("sample_person", "3.0") - call cclutAddMockData("sample_encounter", "4.0|1.0") - call cclutAddMockData("sample_encounter", "5.0|2.0") - call cclutAddMockData("sample_encounter_alias", "4.0|test alias") + subroutine (cclut::mockSubroutine(null) = null with protect) + set mock_subroutine = 1 + end - call cclutAddMockImplementation("REPLY", "EXECUTEREPLY") - call cclutAddMockImplementation("InternalSubroutine", "MockSubroutine") + call cclutAddMockImplementation("internalSubroutine", "mockSubroutine") - call cclutExecuteProgramWithMocks("cclut_execute_mocks_happy", "10,^test param^", "CCLUT") + call cclutExecuteProgramWithMocks("ut_cclut_execute_mocks_happy", "10,^test param^", "CCLUT") - call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_mock_subroutine", executeReply->public_subroutine, 0) - call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_mock_subroutine", executeReply->test_subroutine, 0) - call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_mock_subroutine", executeReply->mock_subroutine, 1) + call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_mock_subroutine 001", public_subroutine, 0) + call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_mock_subroutine 002", test_subroutine, 0) + call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_mock_subroutine 003", mock_subroutine, 1) end ;test_cclutExecuteProgramWithMocks_mock_subroutine /* test_cclutExecuteProgramWithMocks_missing_programName **************************************************** * Scenario: Throws an error when an empty programName is supplied to the function (after trimming) * ************************************************************************************************************/ subroutine test_cclutExecuteProgramWithMocks_missing_programName(null) - call echo("~~~***~~~***test_cclutExecuteProgramWithMocks_missing_programName***~~~***~~~") - - declare errorMessage = vc with protect, noconstant("") + declare errorMessage = vc with protect, noconstant("") declare errorCode = i4 with protect, noconstant(0) - call cclutExecuteProgramWithMocks(" ", "") + call cclutExecuteProgramWithMocks(" ", "") - set errorCode = error(errorMessage, 0) + set errorCode = error(errorMessage, 0) - call cclutAssertVcOperator(CURREF, "test_cclutExecuteProgramWithMocks_missing_programName", trim(errorMessage, 3), - "regexplike", concat("%CCL-E-392-PRG_[0-9]+_[0-9]+\([^)]+\)[0-9]+:[0-9]+\{CCLEXCEPTION\(\)\}Exception\(100\):", + call cclutAssertVcOperator(CURREF, "test_cclutExecuteProgramWithMocks_missing_programName 001", + trim(errorMessage, 3), "regexplike", + concat("%CCL-E-392-PRG_[0-9]+_[0-9]+\([^)]+\)[0-9]+:[0-9]+\{CCLEXCEPTION\(\)\}Exception\(100\):", " cclutExecuteProgramWithMocks\(\) - programName is a required field.")) end ;test_cclutExecuteProgramWithMocks_missing_programName @@ -382,9 +391,7 @@ end ;test_cclutExecuteProgramWithMocks_missing_programName * Scenario: Removes all mock tables and implementations so that the originals can be used * ************************************************************************************************************/ subroutine test_cclutRemoveAllMocks_happy(null) - call echo("~~~***~~~***test_cclutRemoveAllMocks_happy***~~~***~~~") - - call cclutDefineMockTable("sample_table", "sample_table_id|sample_table_text|sample_table_date", "f8|vc|dq8") + call cclutDefineMockTable("sample_table", "sample_table_id|sample_table_text|sample_table_date", "f8|vc|dq8") call cclutDefineMockTable("sample_table_2", "sample_table_2_id|sample_table_2_text|sample_table_2_date", "f8|vc|dq8") call cclutDefineMockTable("sample_table_3", "sample_table_3_id|sample_table_3_text|sample_table_3_date", @@ -392,18 +399,18 @@ subroutine test_cclutRemoveAllMocks_happy(null) call cclutCreateMockTable("sample_table") - call cclutAddMockImplementation("sample_subroutine", "mock_subroutine") - call cclutAddMockImplementation("sample_subroutine_2", "mock_subroutine_2") - call cclutAddMockImplementation("sample_subroutine_3", "mock_subroutine_3") + call cclutAddMockImplementation("sample_subroutine", "mock_subroutine") + call cclutAddMockImplementation("sample_subroutine_2", "mock_subroutine_2") + call cclutAddMockImplementation("sample_subroutine_3", "mock_subroutine_3") - call cclutAsserti4Equal(CURREF, "test_cclutRemoveAllMocks_happy", + call cclutAsserti4Equal(CURREF, "test_cclutRemoveAllMocks_happy 001", size(cclut_mockTables->tables, 5), 3) - call cclutAsserti4Equal(CURREF, "test_cclutRemoveAllMocks_happy", + call cclutAsserti4Equal(CURREF, "test_cclutRemoveAllMocks_happy 002", size(cclut_mockImplementations->implementations, 5), 3) call cclutRemoveAllMocks(null) - call cclutAsserti4Equal(CURREF, "test_cclutRemoveAllMocks_happy", size(cclut_mockTables->tables, 5), 0) - call cclutAsserti4Equal(CURREF, "test_cclutRemoveAllMocks_happy", + call cclutAsserti4Equal(CURREF, "test_cclutRemoveAllMocks_happy 003", size(cclut_mockTables->tables, 5), 0) + call cclutAsserti4Equal(CURREF, "test_cclutRemoveAllMocks_happy 004", size(cclut_mockImplementations->implementations, 5), 0) -end ;test_cclutRemoveAllMocks_happy \ No newline at end of file +end ;test_cclutRemoveAllMocks_happy diff --git a/cclunit-framework-source/src/test/ccl/ut_cclut_mock_table.inc b/cclunit-framework-source/src/test/ccl/ut_cclut_mock_table.inc index 31420c9..371943d 100644 --- a/cclunit-framework-source/src/test/ccl/ut_cclut_mock_table.inc +++ b/cclunit-framework-source/src/test/ccl/ut_cclut_mock_table.inc @@ -1,13 +1,9 @@ declare setup(dummyVar = i2) = null declare tearDown(dummyVar = i2) = null -subroutine setup(dummyVar) - null -end ;setup - subroutine tearDown(dummyVar) call cclutRemoveAllMocks(null) - rollback + rollback end ;tearDown ;********************************************************************************************************************************** @@ -17,268 +13,338 @@ end ;tearDown * Scenario: Defines a table with columns of various types that has not been mocked or defined previously. * ************************************************************************************************************/ subroutine test_cclutDefineMockTable_happy(null) - call echo("~~~***~~~***test_cclutDefineMockTable_happy***~~~***~~~") - - declare mockTable = vc with protect, noconstant("") - set mockTable = - cclutDefineMockTable("sample_table", "sample_table_id|sample_table_text|sample_table_date", "f8|vc|dq8") + declare mockTable = vc with protect, noconstant("") + set mockTable = + cclutDefineMockTable("sample_table", "sample_table_id|sample_table_text|sample_table_date", "f8|vc|dq8") - call cclutAssertStartsWith(CURREF, "test_cclutDefineMockTable_happy", "CUST_CCLUT", mockTable) + call cclutAssertStartsWith(CURREF, "test_cclutDefineMockTable_happy 001", "CUST_CCLUT", mockTable) - call cclutAsserti4Equal(CURREF, "test_cclutDefineMockTable_happy", size(cclut_mockTables->tables, 5), 1) - call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_happy", cclut_mockTables->tables[1].originalName, + call cclutAsserti4Equal(CURREF, "test_cclutDefineMockTable_happy 002", size(cclut_mockTables->tables, 5), 1) + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_happy 003", cclut_mockTables->tables[1].originalName, "SAMPLE_TABLE") - call cclutAssertStartsWith(CURREF, "test_cclutDefineMockTable_happy", "CUST_CCLUT", + call cclutAssertStartsWith(CURREF, "test_cclutDefineMockTable_happy 004", "CUST_CCLUT", cclut_mockTables->tables[1].replaceName) - call cclutAsserti4Equal(CURREF, "test_cclutDefineMockTable_happy", size(cclut_mockTables->tables[1].columns, 5), 3) - call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_happy", + call cclutAsserti4Equal(CURREF, "test_cclutDefineMockTable_happy 005", size(cclut_mockTables->tables[1].columns, 5), + 3) + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_happy 006", cclut_mockTables->tables[1].columns[1].columnName, "SAMPLE_TABLE_ID") - call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_happy", + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_happy 007", cclut_mockTables->tables[1].columns[1].columnType, "F8") - call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_happy", + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_happy 008", cclut_mockTables->tables[1].columns[1].columnConstraint, "") - call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_happy", + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_happy 009", cclut_mockTables->tables[1].columns[2].columnName, "SAMPLE_TABLE_TEXT") - call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_happy", + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_happy 010", cclut_mockTables->tables[1].columns[2].columnType, "VC") - call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_happy", + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_happy 011", cclut_mockTables->tables[1].columns[2].columnConstraint, "") - call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_happy", + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_happy 012", cclut_mockTables->tables[1].columns[3].columnName, "SAMPLE_TABLE_DATE") - call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_happy", + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_happy 013", cclut_mockTables->tables[1].columns[3].columnType, "DQ8") - call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_happy", + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_happy 014", cclut_mockTables->tables[1].columns[3].columnConstraint, "") - call cclutAsserti4Equal(CURREF, "test_cclutDefineMockTable_happy", size(cclut_mockTables->tables[1].indexes, 5), 0) - call cclutAsserti4Equal(CURREF, "test_cclutDefineMockTable_happy", cclut_mockTables->tables[1].isFinalized, FALSE) + call cclutAsserti4Equal(CURREF, "test_cclutDefineMockTable_happy 015", size(cclut_mockTables->tables[1].indexes, 5), + 0) + call cclutAsserti4Equal(CURREF, "test_cclutDefineMockTable_happy 016", cclut_mockTables->tables[1].isFinalized, FALSE) end ;test_cclutDefineMockTable_happy -/* test_cclutDefineMockTable_existing_mock ****************************************************************** -* Scenario: Removes the existing mock and adds a new one when cclutDefineMockTable is called again * +/* test_cclutDefineMockTable_different_cases **************************************************************** +* Scenario: Defines a table with columns of various types that has different cases within each word * ************************************************************************************************************/ -subroutine test_cclutDefineMockTable_existing_mock(null) - call echo("~~~***~~~***test_cclutDefineMockTable_existing_mock***~~~***~~~") - - declare mockTable = vc with protect, noconstant("") - set mockTable = - cclutDefineMockTable("sample_table", "sample_table_id|sample_table_text|sample_table_date", "f8|vc|dq8") +subroutine test_cclutDefineMockTable_different_cases(null) + declare mockTable = vc with protect, noconstant("") + set mockTable = + cclutDefineMockTable("sAmpLE_tabLE", "SaMPle_TABle_iD|sAmPlE_tAbLe_TeXt|SaMpLe_TaBlE_dAtE", "f8|VC|dQ8") - call cclutAssertStartsWith(CURREF, "test_cclutDefineMockTable_existing_mock", "CUST_CCLUT", mockTable) + call cclutAssertStartsWith(CURREF, "test_cclutDefineMockTable_different_cases 001", "CUST_CCLUT", mockTable) - call cclutAsserti4Equal(CURREF, "test_cclutDefineMockTable_existing_mock", size(cclut_mockTables->tables, 5), 1) - call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_existing_mock", cclut_mockTables->tables[1].originalName, - "SAMPLE_TABLE") - call cclutAssertStartsWith(CURREF, "test_cclutDefineMockTable_existing_mock", "CUST_CCLUT", + call cclutAsserti4Equal(CURREF, "test_cclutDefineMockTable_different_cases 002", size(cclut_mockTables->tables, 5), + 1) + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_different_cases 003", + cclut_mockTables->tables[1].originalName, "SAMPLE_TABLE") + call cclutAssertStartsWith(CURREF, "test_cclutDefineMockTable_different_cases 004", "CUST_CCLUT", cclut_mockTables->tables[1].replaceName) - call cclutAsserti4Equal(CURREF, "test_cclutDefineMockTable_existing_mock", + call cclutAsserti4Equal(CURREF, "test_cclutDefineMockTable_different_cases 005", size(cclut_mockTables->tables[1].columns, 5), 3) - call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_existing_mock", + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_different_cases 006", cclut_mockTables->tables[1].columns[1].columnName, "SAMPLE_TABLE_ID") - call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_existing_mock", + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_different_cases 007", cclut_mockTables->tables[1].columns[1].columnType, "F8") - call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_existing_mock", + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_different_cases 008", cclut_mockTables->tables[1].columns[1].columnConstraint, "") - call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_existing_mock", + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_different_cases 009", cclut_mockTables->tables[1].columns[2].columnName, "SAMPLE_TABLE_TEXT") - call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_existing_mock", + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_different_cases 010", cclut_mockTables->tables[1].columns[2].columnType, "VC") - call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_existing_mock", + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_different_cases 011", cclut_mockTables->tables[1].columns[2].columnConstraint, "") - call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_existing_mock", + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_different_cases 012", cclut_mockTables->tables[1].columns[3].columnName, "SAMPLE_TABLE_DATE") - call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_existing_mock", + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_different_cases 013", cclut_mockTables->tables[1].columns[3].columnType, "DQ8") - call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_existing_mock", + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_different_cases 014", cclut_mockTables->tables[1].columns[3].columnConstraint, "") - call cclutAsserti4Equal(CURREF, "test_cclutDefineMockTable_existing_mock", + call cclutAsserti4Equal(CURREF, "test_cclutDefineMockTable_different_cases 015", size(cclut_mockTables->tables[1].indexes, 5), 0) - call cclutAsserti4Equal(CURREF, "test_cclutDefineMockTable_existing_mock", cclut_mockTables->tables[1].isFinalized, - FALSE) + call cclutAsserti4Equal(CURREF, "test_cclutDefineMockTable_different_cases 016", + cclut_mockTables->tables[1].isFinalized, FALSE) +end ;test_cclutDefineMockTable_different_cases +/* test_cclutDefineMockTable_existing_mock ****************************************************************** +* Scenario: Removes the existing mock and adds a new one when cclutDefineMockTable is called again * +************************************************************************************************************/ +subroutine test_cclutDefineMockTable_existing_mock(null) + declare mockTable = vc with protect, noconstant("") + set mockTable = + cclutDefineMockTable("sample_table", "sample_table_id|sample_table_text|sample_table_date", "f8|vc|dq8") set mockTable = cclutDefineMockTable("sample_table", "new_table_id|new_table_text|new_table_date", "i4|c100|dm12") - call cclutAssertStartsWith(CURREF, "test_cclutDefineMockTable_existing_mock", "CUST_CCLUT", mockTable) + call cclutAssertStartsWith(CURREF, "test_cclutDefineMockTable_existing_mock 001", "CUST_CCLUT", mockTable) - call cclutAsserti4Equal(CURREF, "test_cclutDefineMockTable_existing_mock", size(cclut_mockTables->tables, 5), 1) - call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_existing_mock", cclut_mockTables->tables[1].originalName, - "SAMPLE_TABLE") - call cclutAssertStartsWith(CURREF, "test_cclutDefineMockTable_existing_mock", "CUST_CCLUT", + call cclutAsserti4Equal(CURREF, "test_cclutDefineMockTable_existing_mock 002", size(cclut_mockTables->tables, 5), 1) + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_existing_mock 003", + cclut_mockTables->tables[1].originalName, "SAMPLE_TABLE") + call cclutAssertStartsWith(CURREF, "test_cclutDefineMockTable_existing_mock 004", "CUST_CCLUT", cclut_mockTables->tables[1].replaceName) - call cclutAsserti4Equal(CURREF, "test_cclutDefineMockTable_existing_mock", + call cclutAsserti4Equal(CURREF, "test_cclutDefineMockTable_existing_mock 005", size(cclut_mockTables->tables[1].columns, 5), 3) - call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_existing_mock", + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_existing_mock 006", cclut_mockTables->tables[1].columns[1].columnName, "NEW_TABLE_ID") - call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_existing_mock", + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_existing_mock 007", cclut_mockTables->tables[1].columns[1].columnType, "I4") - call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_existing_mock", + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_existing_mock 008", cclut_mockTables->tables[1].columns[1].columnConstraint, "") - call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_existing_mock", + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_existing_mock 009", cclut_mockTables->tables[1].columns[2].columnName, "NEW_TABLE_TEXT") - call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_existing_mock", + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_existing_mock 010", cclut_mockTables->tables[1].columns[2].columnType, "C100") - call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_existing_mock", + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_existing_mock 011", cclut_mockTables->tables[1].columns[2].columnConstraint, "") - call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_existing_mock", + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_existing_mock 012", cclut_mockTables->tables[1].columns[3].columnName, "NEW_TABLE_DATE") - call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_existing_mock", + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_existing_mock 013", cclut_mockTables->tables[1].columns[3].columnType, "DM12") - call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_existing_mock", + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_existing_mock 014", cclut_mockTables->tables[1].columns[3].columnConstraint, "") - call cclutAsserti4Equal(CURREF, "test_cclutDefineMockTable_existing_mock", + call cclutAsserti4Equal(CURREF, "test_cclutDefineMockTable_existing_mock 015", size(cclut_mockTables->tables[1].indexes, 5), 0) - call cclutAsserti4Equal(CURREF, "test_cclutDefineMockTable_existing_mock", cclut_mockTables->tables[1].isFinalized, - FALSE) + call cclutAsserti4Equal(CURREF, "test_cclutDefineMockTable_existing_mock 016", + cclut_mockTables->tables[1].isFinalized, FALSE) end ;test_cclutDefineMockTable_existing_mock +/* test_cclutDefineMockTable_existing_created_mock ********************************************************** +* Scenario: Drops the existing created mock and adds a new one when cclutDefineMockTable is called again * +************************************************************************************************************/ +subroutine test_cclutDefineMockTable_existing_created_mock(null) + declare mockTable = vc with protect, noconstant("") + set mockTable = + cclutDefineMockTable("sample_table", "sample_table_id|sample_table_text|sample_table_date", "f8|vc|dq8") + call cclutCreateMockTable("sample_table") + call cclutAddMockData("sample_table", "1.0|test text|27-NOV-2018 08:00") + + declare mockId = f8 with protect, noconstant(0.0) + declare mockText = vc with protect, noconstant("") + declare mockDate = dq8 with protect, noconstant(0) + select into "nl:" + from (value(mockTable) m) + detail + mockId = m.SAMPLE_TABLE_ID + mockText = m.SAMPLE_TABLE_TEXT + mockDate = m.SAMPLE_TABLE_DATE + with nocounter + + call cclutAssertf8Equal(CURREF, "test_cclutDefineMockTable_existing_created_mock 001", mockId, 1.0) + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_existing_created_mock 002", mockText, "test text") + call cclutAssertf8Equal(CURREF, "test_cclutDefineMockTable_existing_created_mock 003", mockDate, + cnvtdatetime("27-NOV-2018 08:00")) + + set mockTable = cclutDefineMockTable("sample_table", "new_table_id|new_table_text|new_table_date", "i4|c100|dm12") + + select into "nl:" + from (value(mockTable) m) + detail + mockId = m.SAMPLE_TABLE_ID + mockText = m.SAMPLE_TABLE_TEXT + mockDate = m.SAMPLE_TABLE_DATE + with nocounter + + declare errorMessage = vc with protect, noconstant("") + declare errorCode = i4 with protect, noconstant(0) + set errorCode = error(errorMessage, 0) + + call cclutAssertVcOperator(CURREF, "test_cclutDefineMockTable_existing_created_mock 004", trim(errorMessage, 3), + "regexplike", concat("%CCL-E-18-PRG_[0-9]+_[0-9]+\([^)]+\)[0-9]+:[0-9]+\{\}Unable to add range, definition for", + " table \(CUST_CCLUT_[^)]*\) not found in dictionary.")) + + call cclutAssertStartsWith(CURREF, "test_cclutDefineMockTable_existing_created_mock 005", "CUST_CCLUT", mockTable) + + call cclutAsserti4Equal(CURREF, "test_cclutDefineMockTable_existing_created_mock 006", + size(cclut_mockTables->tables, 5), 1) + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_existing_created_mock 007", + cclut_mockTables->tables[1].originalName, "SAMPLE_TABLE") + call cclutAssertStartsWith(CURREF, "test_cclutDefineMockTable_existing_created_mock 008", "CUST_CCLUT", + cclut_mockTables->tables[1].replaceName) + call cclutAsserti4Equal(CURREF, "test_cclutDefineMockTable_existing_created_mock 009", + size(cclut_mockTables->tables[1].columns, 5), 3) + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_existing_created_mock 010", + cclut_mockTables->tables[1].columns[1].columnName, "NEW_TABLE_ID") + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_existing_created_mock 011", + cclut_mockTables->tables[1].columns[1].columnType, "I4") + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_existing_created_mock 012", + cclut_mockTables->tables[1].columns[1].columnConstraint, "") + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_existing_created_mock 013", + cclut_mockTables->tables[1].columns[2].columnName, "NEW_TABLE_TEXT") + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_existing_created_mock 014", + cclut_mockTables->tables[1].columns[2].columnType, "C100") + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_existing_created_mock 015", + cclut_mockTables->tables[1].columns[2].columnConstraint, "") + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_existing_created_mock 016", + cclut_mockTables->tables[1].columns[3].columnName, "NEW_TABLE_DATE") + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_existing_created_mock 017", + cclut_mockTables->tables[1].columns[3].columnType, "DM12") + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_existing_created_mock 018", + cclut_mockTables->tables[1].columns[3].columnConstraint, "") + call cclutAsserti4Equal(CURREF, "test_cclutDefineMockTable_existing_created_mock 019", + size(cclut_mockTables->tables[1].indexes, 5), 0) + call cclutAsserti4Equal(CURREF, "test_cclutDefineMockTable_existing_created_mock 020", + cclut_mockTables->tables[1].isFinalized, FALSE) +end ;test_cclutDefineMockTable_existing_created_mock + /* test_cclutDefineMockTable_missing_tableName ************************************************************** * Scenario: Throws an error when an empty tableName is supplied to the function (after trimming) * ************************************************************************************************************/ subroutine test_cclutDefineMockTable_missing_tableName(null) - call echo("~~~***~~~***test_cclutDefineMockTable_missing_tableName***~~~***~~~") - - declare mockTable = vc with protect, noconstant("") - declare errorMessage = vc with protect, noconstant("") + declare mockTable = vc with protect, noconstant("") + declare errorMessage = vc with protect, noconstant("") declare errorCode = i4 with protect, noconstant(0) - set mockTable = - cclutDefineMockTable(" ", "sample_table_id|sample_table_text|sample_table_date", "f8|vc|dq8") + set mockTable = + cclutDefineMockTable(" ", "sample_table_id|sample_table_text|sample_table_date", "f8|vc|dq8") - set errorCode = error(errorMessage, 0) + set errorCode = error(errorMessage, 0) - call cclutAssertVcOperator(CURREF, "test_cclutDefineMockTable_missing_tableName", trim(errorMessage, 3), + call cclutAssertVcOperator(CURREF, "test_cclutDefineMockTable_missing_tableName 001", trim(errorMessage, 3), "regexplike", concat("%CCL-E-392-PRG_[0-9]+_[0-9]+\([^)]+\)[0-9]+:[0-9]+\{CCLEXCEPTION\(\)\}Exception\(100\):", - " cclutDefineMockTable\(\) - tableName is a required field.")) + " cclutValidateParameterIsNotEmpty\(\) - tableName is a required field.")) - call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_missing_tableName", mockTable, "") + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_missing_tableName 002", mockTable, "") end ;test_cclutDefineMockTable_missing_tableName /* test_cclutDefineMockTable_missing_columnNames ************************************************************ * Scenario: Throws an error when an empty columnNames is supplied to the function (after trimming) * ************************************************************************************************************/ subroutine test_cclutDefineMockTable_missing_columnNames(null) - call echo("~~~***~~~***test_cclutDefineMockTable_missing_columnNames***~~~***~~~") - - declare mockTable = vc with protect, noconstant("") - declare errorMessage = vc with protect, noconstant("") + declare mockTable = vc with protect, noconstant("") + declare errorMessage = vc with protect, noconstant("") declare errorCode = i4 with protect, noconstant(0) - set mockTable = - cclutDefineMockTable("sample_table", " ", "f8|vc|dq8") + set mockTable = + cclutDefineMockTable("sample_table", " ", "f8|vc|dq8") - set errorCode = error(errorMessage, 0) + set errorCode = error(errorMessage, 0) - call cclutAssertVcOperator(CURREF, "test_cclutDefineMockTable_missing_columnNames", trim(errorMessage, 3), + call cclutAssertVcOperator(CURREF, "test_cclutDefineMockTable_missing_columnNames 001", trim(errorMessage, 3), "regexplike", concat("%CCL-E-392-PRG_[0-9]+_[0-9]+\([^)]+\)[0-9]+:[0-9]+\{CCLEXCEPTION\(\)\}Exception\(100\):", - " cclutDefineMockTable\(\) - columnNames is a required field.")) + " cclutValidateParameterIsNotEmpty\(\) - columnNames is a required field.")) - call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_missing_columnNames", mockTable, "") + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_missing_columnNames 002", mockTable, "") end ;test_cclutDefineMockTable_missing_columnNames /* test_cclutDefineMockTable_missing_columnTypes ************************************************************ * Scenario: Throws an error when an empty columnTypes is supplied to the function (after trimming) * ************************************************************************************************************/ subroutine test_cclutDefineMockTable_missing_columnTypes(null) - call echo("~~~***~~~***test_cclutDefineMockTable_missing_columnTypes***~~~***~~~") - - declare mockTable = vc with protect, noconstant("") - declare errorMessage = vc with protect, noconstant("") + declare mockTable = vc with protect, noconstant("") + declare errorMessage = vc with protect, noconstant("") declare errorCode = i4 with protect, noconstant(0) - set mockTable = - cclutDefineMockTable("sample_table", "sample_table_id|sample_table_text|sample_table_date", " ") + set mockTable = + cclutDefineMockTable("sample_table", "sample_table_id|sample_table_text|sample_table_date", " ") - set errorCode = error(errorMessage, 0) + set errorCode = error(errorMessage, 0) - call cclutAssertVcOperator(CURREF, "test_cclutDefineMockTable_missing_columnTypes", trim(errorMessage, 3), + call cclutAssertVcOperator(CURREF, "test_cclutDefineMockTable_missing_columnTypes 001", trim(errorMessage, 3), "regexplike", concat("%CCL-E-392-PRG_[0-9]+_[0-9]+\([^)]+\)[0-9]+:[0-9]+\{CCLEXCEPTION\(\)\}Exception\(100\):", - " cclutDefineMockTable\(\) - columnTypes is a required field.")) + " cclutValidateParameterIsNotEmpty\(\) - columnTypes is a required field.")) - call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_missing_columnTypes", mockTable, "") + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_missing_columnTypes 002", mockTable, "") end ;test_cclutDefineMockTable_missing_columnTypes /* test_cclutDefineMockTable_mismatch_column_count ********************************************************** * Scenario: Throws an error when the number of column names is different than the number of column types * ************************************************************************************************************/ subroutine test_cclutDefineMockTable_mismatch_column_count(null) - call echo("~~~***~~~***test_cclutDefineMockTable_mismatch_column_count***~~~***~~~") - - declare mockTable = vc with protect, noconstant("") - declare errorMessage = vc with protect, noconstant("") + declare mockTable = vc with protect, noconstant("") + declare errorMessage = vc with protect, noconstant("") declare errorCode = i4 with protect, noconstant(0) - set mockTable = - cclutDefineMockTable("sample_table", "sample_table_id|sample_table_text|sample_table_date", "f8|vc") + set mockTable = + cclutDefineMockTable("sample_table", "sample_table_id|sample_table_text|sample_table_date", "f8|vc") - set errorCode = error(errorMessage, 0) + set errorCode = error(errorMessage, 0) - call cclutAssertVcOperator(CURREF, "test_cclutDefineMockTable_mismatch_column_count", trim(errorMessage, 3), + call cclutAssertVcOperator(CURREF, "test_cclutDefineMockTable_mismatch_column_count 001", trim(errorMessage, 3), "regexplike", concat("%CCL-E-392-PRG_[0-9]+_[0-9]+\([^)]+\)[0-9]+:[0-9]+\{CCLEXCEPTION\(\)\}Exception\(100\):", - " cclutDefineMockTable\(\) - columnTypes must match number of columnNames. columnNames Count: 3.*", - "columnTypes Count: 2.*.")) + " cclutDefineMockTable\(SAMPLE_TABLE\) - Size mismatch. 3 columnNames vs. 2 columnTypes")) - call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_mismatch_column_count", mockTable, "") + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_mismatch_column_count 002", mockTable, "") end ;test_cclutDefineMockTable_mismatch_column_count /* test_cclutDefineMockTable_missing_column_name ************************************************************ * Scenario: Throws an error if any of the individual column names are empty (after trimming) * ************************************************************************************************************/ subroutine test_cclutDefineMockTable_missing_column_name(null) - call echo("~~~***~~~***test_cclutDefineMockTable_missing_column_name***~~~***~~~") - - declare mockTable = vc with protect, noconstant("") - declare errorMessage = vc with protect, noconstant("") + declare mockTable = vc with protect, noconstant("") + declare errorMessage = vc with protect, noconstant("") declare errorCode = i4 with protect, noconstant(0) - set mockTable = - cclutDefineMockTable("sample_table", "sample_table_id| |sample_table_date", "f8|vc|dq8") + set mockTable = + cclutDefineMockTable("sample_table", "sample_table_id| |sample_table_date", "f8|vc|dq8") - set errorCode = error(errorMessage, 0) + set errorCode = error(errorMessage, 0) - call cclutAssertVcOperator(CURREF, "test_cclutDefineMockTable_missing_column_name", trim(errorMessage, 3), + call cclutAssertVcOperator(CURREF, "test_cclutDefineMockTable_missing_column_name 001", trim(errorMessage, 3), "regexplike", concat("%CCL-E-392-PRG_[0-9]+_[0-9]+\([^)]+\)[0-9]+:[0-9]+\{CCLEXCEPTION\(\)\}Exception\(100\):", " cclutDefineMockTable\(\) - Empty columnName found in columnNames. columnNames: ", "SAMPLE_TABLE_ID| |SAMPLE_TABLE_DATE.")) - call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_missing_column_name", mockTable, "") + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_missing_column_name 002", mockTable, "") end ;test_cclutDefineMockTable_missing_column_name /* test_cclutDefineMockTable_missing_column_type ************************************************************ * Scenario: Throws an error if any of the individual column types are empty (after trimming) * ************************************************************************************************************/ subroutine test_cclutDefineMockTable_missing_column_type(null) - call echo("~~~***~~~***test_cclutDefineMockTable_missing_column_type***~~~***~~~") - - declare mockTable = vc with protect, noconstant("") - declare errorMessage = vc with protect, noconstant("") + declare mockTable = vc with protect, noconstant("") + declare errorMessage = vc with protect, noconstant("") declare errorCode = i4 with protect, noconstant(0) - set mockTable = - cclutDefineMockTable("sample_table", "sample_table_id|sample_table_text|sample_table_date", "f8| |dq8") + set mockTable = + cclutDefineMockTable("sample_table", "sample_table_id|sample_table_text|sample_table_date", "f8| |dq8") - set errorCode = error(errorMessage, 0) + set errorCode = error(errorMessage, 0) - call cclutAssertVcOperator(CURREF, "test_cclutDefineMockTable_missing_column_type", trim(errorMessage, 3), + call cclutAssertVcOperator(CURREF, "test_cclutDefineMockTable_missing_column_type 001", trim(errorMessage, 3), "regexplike", concat("%CCL-E-392-PRG_[0-9]+_[0-9]+\([^)]+\)[0-9]+:[0-9]+\{CCLEXCEPTION\(\)\}Exception\(100\):", " cclutDefineMockTable\(\) - Empty columnType found in columnTypes. columnTypes: ", "F8| |DQ8.")) - call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_missing_column_type", mockTable, "") + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_missing_column_type 002", mockTable, "") end ;test_cclutDefineMockTable_missing_column_type /* test_cclutDefineMockTable_duplicate_column_name ********************************************************** * Scenario: Throws an error if any of the column names are duplicated (names are case-insensitive) * ************************************************************************************************************/ subroutine test_cclutDefineMockTable_duplicate_column_name(null) - call echo("~~~***~~~***test_cclutDefineMockTable_duplicate_column_name***~~~***~~~") - - declare mockTable = vc with protect, noconstant("") - declare errorMessage = vc with protect, noconstant("") + declare mockTable = vc with protect, noconstant("") + declare errorMessage = vc with protect, noconstant("") declare errorCode = i4 with protect, noconstant(0) - set mockTable = - cclutDefineMockTable("sample_table", "sample_table_id|sample_table_text|sample_table_date|SAMPLE_table_text", - "f8|vc|dq8|vc") + set mockTable = + cclutDefineMockTable("sample_table", "sample_table_id|sample_table_text|sample_table_date|SAMPLE_table_text", + "f8|vc|dq8|vc") - set errorCode = error(errorMessage, 0) + set errorCode = error(errorMessage, 0) - call cclutAssertVcOperator(CURREF, "test_cclutDefineMockTable_duplicate_column_name", trim(errorMessage, 3), + call cclutAssertVcOperator(CURREF, "test_cclutDefineMockTable_duplicate_column_name 001", trim(errorMessage, 3), "regexplike", concat("%CCL-E-392-PRG_[0-9]+_[0-9]+\([^)]+\)[0-9]+:[0-9]+\{CCLEXCEPTION\(\)\}Exception\(100\):", - " cclutDefineMockTable\(\) - Duplicate columnName found. columnName: SAMPLE_TABLE_TEXT")) + " cclutDefineMockTable\(SAMPLE_TABLE\) - Duplicate columnName found. columnName: SAMPLE_TABLE_TEXT")) - call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_duplicate_column_name", mockTable, "") + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_duplicate_column_name 002", mockTable, "") end ;test_cclutDefineMockTable_duplicate_column_name ;********************************************************************************************************************************** @@ -288,110 +354,96 @@ end ;test_cclutDefineMockTable_duplicate_column_name * Scenario: Adds a mock constraint to a table that has already been defined with cclutDefineMockTable * ************************************************************************************************************/ subroutine test_cclutAddMockConstraint_happy(null) - call echo("~~~***~~~***test_cclutAddMockConstraint_happy***~~~***~~~") - - call cclutDefineMockTable("sample_table", "sample_table_id|sample_table_text|sample_table_date", "f8|vc|dq8") - call cclutDefineMockTable("sample_table_2", "sample_table_2_id|sample_table_2_text|sample_table_2_date", - "f8|vc|dq8") - call cclutDefineMockTable("sample_table_3", "sample_table_3_id|sample_table_3_text|sample_table_3_date", - "f8|vc|dq8") + call cclutDefineMockTable("sample_table", "sample_table_id|sample_table_text|sample_table_date", "f8|vc|dq8") + call cclutDefineMockTable("sample_table_2", "sample_table_2_id|sample_table_2_text|sample_table_2_date", + "f8|vc|dq8") + call cclutDefineMockTable("sample_table_3", "sample_table_3_id|sample_table_3_text|sample_table_3_date", + "f8|vc|dq8") - call cclutAddMockConstraint("sample_table_2", "sample_table_2_text", "not null unique") + call cclutAddMockConstraint("sample_table_2", "sample_table_2_text", "not null unique") - call cclutAssertvcEqual(CURREF, "test_cclutAddMockConstraint_happy", - cclut_mockTables->tables[2].columns[2].columnConstraint, "NOT NULL UNIQUE") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockConstraint_happy 001", + cclut_mockTables->tables[2].columns[2].columnConstraint, "NOT NULL UNIQUE") end ;test_cclutAddMockConstraint_happy /* test_cclutAddMockConstraint_missing_tableName ************************************************************ * Scenario: Throws an error when an empty tableName is supplied to the function (after trimming) * ************************************************************************************************************/ subroutine test_cclutAddMockConstraint_missing_tableName(null) - call echo("~~~***~~~***test_cclutAddMockConstraint_missing_tableName***~~~***~~~") - - declare errorMessage = vc with protect, noconstant("") + declare errorMessage = vc with protect, noconstant("") declare errorCode = i4 with protect, noconstant(0) - call cclutAddMockConstraint(" ", "sample_table_text", "not null unique") + call cclutAddMockConstraint(" ", "sample_table_text", "not null unique") - set errorCode = error(errorMessage, 0) + set errorCode = error(errorMessage, 0) - call cclutAssertVcOperator(CURREF, "test_cclutAddMockConstraint_missing_tableName", trim(errorMessage, 3), + call cclutAssertVcOperator(CURREF, "test_cclutAddMockConstraint_missing_tableName 001", trim(errorMessage, 3), "regexplike", concat("%CCL-E-392-PRG_[0-9]+_[0-9]+\([^)]+\)[0-9]+:[0-9]+\{CCLEXCEPTION\(\)\}Exception\(100\):", - " cclutAddMockConstraint\(\) - tableName is a required field.")) + " cclutValidateParameterIsNotEmpty\(\) - tableName is a required field.")) end ;test_cclutAddMockConstraint_missing_tableName /* test_cclutAddMockConstraint_missing_columnName *********************************************************** * Scenario: Throws an error when an empty columnName is supplied to the function (after trimming) * ************************************************************************************************************/ subroutine test_cclutAddMockConstraint_missing_columnName(null) - call echo("~~~***~~~***test_cclutAddMockConstraint_missing_columnName***~~~***~~~") - - declare errorMessage = vc with protect, noconstant("") + declare errorMessage = vc with protect, noconstant("") declare errorCode = i4 with protect, noconstant(0) - call cclutAddMockConstraint("sample_table", " ", "not null unique") + call cclutAddMockConstraint("sample_table", " ", "not null unique") - set errorCode = error(errorMessage, 0) + set errorCode = error(errorMessage, 0) - call cclutAssertVcOperator(CURREF, "test_cclutAddMockConstraint_missing_columnName", trim(errorMessage, 3), + call cclutAssertVcOperator(CURREF, "test_cclutAddMockConstraint_missing_columnName 001", trim(errorMessage, 3), "regexplike", concat("%CCL-E-392-PRG_[0-9]+_[0-9]+\([^)]+\)[0-9]+:[0-9]+\{CCLEXCEPTION\(\)\}Exception\(100\):", - " cclutAddMockConstraint\(\) - columnName is a required field.")) + " cclutValidateParameterIsNotEmpty\(\) - columnName is a required field.")) end ;test_cclutAddMockConstraint_missing_columnName /* test_cclutAddMockConstraint_unmocked_table *************************************************************** * Scenario: Throws an error when the tableName specified has not been mocked through cclutDefineMockTable * ************************************************************************************************************/ subroutine test_cclutAddMockConstraint_unmocked_table(null) - call echo("~~~***~~~***test_cclutAddMockConstraint_unmocked_table***~~~***~~~") - - declare errorMessage = vc with protect, noconstant("") + declare errorMessage = vc with protect, noconstant("") declare errorCode = i4 with protect, noconstant(0) - call cclutAddMockConstraint("sample_table", "sample_table_text", "not null unique") + call cclutAddMockConstraint("sample_table", "sample_table_text", "not null unique") - set errorCode = error(errorMessage, 0) + set errorCode = error(errorMessage, 0) - call cclutAssertVcOperator(CURREF, "test_cclutAddMockConstraint_unmocked_table", trim(errorMessage, 3), + call cclutAssertVcOperator(CURREF, "test_cclutAddMockConstraint_unmocked_table 001", trim(errorMessage, 3), "regexplike", concat("%CCL-E-392-PRG_[0-9]+_[0-9]+\([^)]+\)[0-9]+:[0-9]+\{CCLEXCEPTION\(\)\}Exception\(100\):", - " cclutAddMockConstraint\(\) - tableName has not been mocked. tableName: SAMPLE_TABLE.")) + " cclutValidateMockTableIsDefined\(SAMPLE_TABLE\) - Table has not been mocked.")) end ;test_cclutAddMockConstraint_unmocked_table /* test_cclutAddMockConstraint_created_table **************************************************************** * Scenario: Throws an error when the tableName specified has already been created * ************************************************************************************************************/ subroutine test_cclutAddMockConstraint_created_table(null) - call echo("~~~***~~~***test_cclutAddMockConstraint_created_table***~~~***~~~") - call cclutDefineMockTable("sample_table", "sample_table_id|sample_table_text|sample_table_date", "f8|vc|dq8") call cclutCreateMockTable("sample_table") - declare errorMessage = vc with protect, noconstant("") + declare errorMessage = vc with protect, noconstant("") declare errorCode = i4 with protect, noconstant(0) - call cclutAddMockConstraint("sample_table", "sample_table_text", "not null unique") + call cclutAddMockConstraint("sample_table", "sample_table_text", "not null unique") - set errorCode = error(errorMessage, 0) + set errorCode = error(errorMessage, 0) - call cclutAssertVcOperator(CURREF, "test_cclutAddMockConstraint_created_table", trim(errorMessage, 3), - "regexplike", concat("%CCL-E-392-PRG_[0-9]+_[0-9]+\([^)]+\)[0-9]+:[0-9]+\{CCLEXCEPTION\(\)\}Exception\(100\):", - " cclutAddMockConstraint\(\) - tableName has already been created. Constraints cannot be modified. ", - "tableName: SAMPLE_TABLE.")) + call cclutAssertVcOperator(CURREF, "test_cclutAddMockConstraint_created_table 001", trim(errorMessage, 3), + "regexplike", concat("%CCL-E-392-PRG_[0-9]+_[0-9]+\([^)]+\)[0-9]+:[0-9]+\{CCLEXCEPTION\(\)\}Exception\(100\): ", + "cclutValidateMockTableIsNotCreated\(SAMPLE_TABLE\) - Table has already been created.")) end ;test_cclutAddMockConstraint_created_table /* test_cclutAddMockConstraint_invalid_column *************************************************************** * Scenario: Throws an error when the column is not a valid column on the mocked table * ************************************************************************************************************/ subroutine test_cclutAddMockConstraint_invalid_column(null) - call echo("~~~***~~~***test_cclutAddMockConstraint_invalid_column***~~~***~~~") - call cclutDefineMockTable("sample_table", "sample_table_id|sample_table_text|sample_table_date", "f8|vc|dq8") - declare errorMessage = vc with protect, noconstant("") + declare errorMessage = vc with protect, noconstant("") declare errorCode = i4 with protect, noconstant(0) - call cclutAddMockConstraint("sample_table", "wrong_column", "not null unique") + call cclutAddMockConstraint("sample_table", "wrong_column", "not null unique") - set errorCode = error(errorMessage, 0) + set errorCode = error(errorMessage, 0) - call cclutAssertVcOperator(CURREF, "test_cclutAddMockConstraint_invalid_column", trim(errorMessage, 3), + call cclutAssertVcOperator(CURREF, "test_cclutAddMockConstraint_invalid_column 001", trim(errorMessage, 3), "regexplike", concat("%CCL-E-392-PRG_[0-9]+_[0-9]+\([^)]+\)[0-9]+:[0-9]+\{CCLEXCEPTION\(\)\}Exception\(100\):", - " cclutAddMockConstraint\(\) - columnName is not mocked on table. columnName: WRONG_COLUMN ", - "tableName: SAMPLE_TABLE.")) + " cclutAddMockConstraint\(SAMPLE_TABLE\) - WRONG_COLUMN is not mocked on table.")) end ;test_cclutAddMockConstraint_invalid_column ;********************************************************************************************************************************** @@ -401,135 +453,119 @@ end ;test_cclutAddMockConstraint_invalid_column * Scenario: Adds a mock index to a table that has already been defined with cclutDefineMockTable * ************************************************************************************************************/ subroutine test_cclutAddMockIndex_happy(null) - call echo("~~~***~~~***test_cclutAddMockIndex_happy***~~~***~~~") - - call cclutDefineMockTable("sample_table", "sample_table_id|sample_table_text|sample_table_date", "f8|vc|dq8") - call cclutDefineMockTable("sample_table_2", "sample_table_2_id|sample_table_2_text|sample_table_2_date", - "f8|vc|dq8") - call cclutDefineMockTable("sample_table_3", "sample_table_3_id|sample_table_3_text|sample_table_3_date", - "f8|vc|dq8") - - call cclutAddMockIndex("sample_table_2", "sample_table_2_id", 1) - call cclutAddMockIndex("sample_table_2", "sample_table_2_text|sample_table_2_id", 0) - - call cclutAsserti4Equal(CURREF, "test_cclutAddMockIndex_happy", size(cclut_mockTables->tables[2].indexes, 5), 2) - call cclutAssertvcEqual(CURREF, "test_cclutAddMockIndex_happy", cclut_mockTables->tables[2].indexes[1].indexColumns, - "SAMPLE_TABLE_2_ID") - call cclutAsserti4Equal(CURREF, "test_cclutAddMockIndex_happy", cclut_mockTables->tables[2].indexes[1].isUnique, 1) - call cclutAssertvcEqual(CURREF, "test_cclutAddMockIndex_happy", cclut_mockTables->tables[2].indexes[2].indexColumns, - "SAMPLE_TABLE_2_TEXT|SAMPLE_TABLE_2_ID") - call cclutAsserti4Equal(CURREF, "test_cclutAddMockIndex_happy", cclut_mockTables->tables[2].indexes[2].isUnique, 0) + call cclutDefineMockTable("sample_table", "sample_table_id|sample_table_text|sample_table_date", "f8|vc|dq8") + call cclutDefineMockTable("sample_table_2", "sample_table_2_id|sample_table_2_text|sample_table_2_date", + "f8|vc|dq8") + call cclutDefineMockTable("sample_table_3", "sample_table_3_id|sample_table_3_text|sample_table_3_date", + "f8|vc|dq8") + + call cclutAddMockIndex("sample_table_2", "sample_table_2_id", 1) + call cclutAddMockIndex("sample_table_2", "sample_table_2_text|sample_table_2_id", 0) + + call cclutAsserti4Equal(CURREF, "test_cclutAddMockIndex_happy 001", size(cclut_mockTables->tables[2].indexes, 5), 2) + call cclutAssertvcEqual(CURREF, "test_cclutAddMockIndex_happy 002", cclut_mockTables->tables[2].indexes[1].indexColumns, + "SAMPLE_TABLE_2_ID") + call cclutAsserti4Equal(CURREF, "test_cclutAddMockIndex_happy 003", cclut_mockTables->tables[2].indexes[1].isUnique, 1) + call cclutAssertvcEqual(CURREF, "test_cclutAddMockIndex_happy 004", cclut_mockTables->tables[2].indexes[2].indexColumns, + "SAMPLE_TABLE_2_TEXT|SAMPLE_TABLE_2_ID") + call cclutAsserti4Equal(CURREF, "test_cclutAddMockIndex_happy 005", cclut_mockTables->tables[2].indexes[2].isUnique, 0) end ;test_cclutAddMockIndex_happy /* test_cclutAddMockIndex_missing_tableName ***************************************************************** * Scenario: Throws an error when an empty tableName is supplied to the function (after trimming) * ************************************************************************************************************/ subroutine test_cclutAddMockIndex_missing_tableName(null) - call echo("~~~***~~~***test_cclutAddMockIndex_missing_tableName***~~~***~~~") - - declare errorMessage = vc with protect, noconstant("") + declare errorMessage = vc with protect, noconstant("") declare errorCode = i4 with protect, noconstant(0) - call cclutAddMockIndex(" ", "sample_table_id", 1) + call cclutAddMockIndex(" ", "sample_table_id", 1) - set errorCode = error(errorMessage, 0) + set errorCode = error(errorMessage, 0) - call cclutAssertVcOperator(CURREF, "test_cclutAddMockIndex_missing_tableName", trim(errorMessage, 3), + call cclutAssertVcOperator(CURREF, "test_cclutAddMockIndex_missing_tableName 001", trim(errorMessage, 3), "regexplike", concat("%CCL-E-392-PRG_[0-9]+_[0-9]+\([^)]+\)[0-9]+:[0-9]+\{CCLEXCEPTION\(\)\}Exception\(100\):", - " cclutAddMockIndex\(\) - tableName is a required field.")) + " cclutValidateParameterIsNotEmpty\(\) - tableName is a required field.")) end ;test_cclutAddMockIndex_missing_tableName /* test_cclutAddMockIndex_missing_columnNames *************************************************************** * Scenario: Throws an error when an empty columnNames is supplied to the function (after trimming) * ************************************************************************************************************/ subroutine test_cclutAddMockIndex_missing_columnNames(null) - call echo("~~~***~~~***test_cclutAddMockIndex_missing_columnNames***~~~***~~~") - - declare errorMessage = vc with protect, noconstant("") + declare errorMessage = vc with protect, noconstant("") declare errorCode = i4 with protect, noconstant(0) - call cclutAddMockIndex("sample_table", " ", 1) + call cclutAddMockIndex("sample_table", " ", 1) - set errorCode = error(errorMessage, 0) + set errorCode = error(errorMessage, 0) - call cclutAssertVcOperator(CURREF, "test_cclutAddMockIndex_missing_columnNames", trim(errorMessage, 3), + call cclutAssertVcOperator(CURREF, "test_cclutAddMockIndex_missing_columnNames 001", trim(errorMessage, 3), "regexplike", concat("%CCL-E-392-PRG_[0-9]+_[0-9]+\([^)]+\)[0-9]+:[0-9]+\{CCLEXCEPTION\(\)\}Exception\(100\):", - " cclutAddMockIndex\(\) - columnNames is a required field.")) + " cclutValidateParameterIsNotEmpty\(\) - columnNames is a required field.")) end ;test_cclutAddMockIndex_missing_columnNames /* test_cclutAddMockIndex_unmocked_table ******************************************************************** * Scenario: Throws an error when the tableName specified has not been mocked through cclutDefineMockTable * ************************************************************************************************************/ subroutine test_cclutAddMockIndex_unmocked_table(null) - call echo("~~~***~~~***test_cclutAddMockIndex_unmocked_table***~~~***~~~") - - declare errorMessage = vc with protect, noconstant("") + declare errorMessage = vc with protect, noconstant("") declare errorCode = i4 with protect, noconstant(0) - call cclutAddMockIndex("sample_table", "sample_table_id", 1) + call cclutAddMockIndex("sample_table", "sample_table_id", 1) - set errorCode = error(errorMessage, 0) + set errorCode = error(errorMessage, 0) - call cclutAssertVcOperator(CURREF, "test_cclutAddMockIndex_unmocked_table", trim(errorMessage, 3), + call cclutAssertVcOperator(CURREF, "test_cclutAddMockIndex_unmocked_table 001", trim(errorMessage, 3), "regexplike", concat("%CCL-E-392-PRG_[0-9]+_[0-9]+\([^)]+\)[0-9]+:[0-9]+\{CCLEXCEPTION\(\)\}Exception\(100\):", - " cclutAddMockIndex\(\) - tableName has not been mocked. tableName: SAMPLE_TABLE.")) + " cclutValidateMockTableIsDefined\(SAMPLE_TABLE\) - Table has not been mocked.")) end ;test_cclutAddMockIndex_unmocked_table /* test_cclutAddMockIndex_created_table ********************************************************************* * Scenario: Throws an error when the tableName specified has already been created * ************************************************************************************************************/ subroutine test_cclutAddMockIndex_created_table(null) - call echo("~~~***~~~***test_cclutAddMockIndex_created_table***~~~***~~~") - call cclutDefineMockTable("sample_table", "sample_table_id|sample_table_text|sample_table_date", "f8|vc|dq8") call cclutCreateMockTable("sample_table") - declare errorMessage = vc with protect, noconstant("") + declare errorMessage = vc with protect, noconstant("") declare errorCode = i4 with protect, noconstant(0) - call cclutAddMockIndex("sample_table", "sample_table_id", 1) + call cclutAddMockIndex("sample_table", "sample_table_id", 1) - set errorCode = error(errorMessage, 0) + set errorCode = error(errorMessage, 0) - call cclutAssertVcOperator(CURREF, "test_cclutAddMockIndex_created_table", trim(errorMessage, 3), + call cclutAssertVcOperator(CURREF, "test_cclutAddMockIndex_created_table 001", trim(errorMessage, 3), "regexplike", concat("%CCL-E-392-PRG_[0-9]+_[0-9]+\([^)]+\)[0-9]+:[0-9]+\{CCLEXCEPTION\(\)\}Exception\(100\):", - " cclutAddMockIndex\(\) - tableName has already been created. Indexes cannot be modified. ", - "tableName: SAMPLE_TABLE.")) + " cclutValidateMockTableIsNotCreated\(SAMPLE_TABLE\) - Table has already been created.")) end ;test_cclutAddMockIndex_created_table /* test_cclutAddMockIndex_invalid_column ******************************************************************** * Scenario: Throws an error when the column is not a valid column on the mocked table * ************************************************************************************************************/ subroutine test_cclutAddMockIndex_invalid_column(null) - call echo("~~~***~~~***test_cclutAddMockIndex_invalid_column***~~~***~~~") - call cclutDefineMockTable("sample_table", "sample_table_id|sample_table_text|sample_table_date", "f8|vc|dq8") - declare errorMessage = vc with protect, noconstant("") + declare errorMessage = vc with protect, noconstant("") declare errorCode = i4 with protect, noconstant(0) - call cclutAddMockIndex("sample_table", "wrong_column", 1) + call cclutAddMockIndex("sample_table", "wrong_column", 1) - set errorCode = error(errorMessage, 0) + set errorCode = error(errorMessage, 0) - call cclutAssertVcOperator(CURREF, "test_cclutAddMockIndex_invalid_column", trim(errorMessage, 3), + call cclutAssertVcOperator(CURREF, "test_cclutAddMockIndex_invalid_column 001", trim(errorMessage, 3), "regexplike", concat("%CCL-E-392-PRG_[0-9]+_[0-9]+\([^)]+\)[0-9]+:[0-9]+\{CCLEXCEPTION\(\)\}Exception\(100\):", - " cclutAddMockIndex\(\) - columnName is not mocked on table. columnName: WRONG_COLUMN ", - "tableName: SAMPLE_TABLE.")) + " cclutAddMockIndex\(SAMPLE_TABLE\) - WRONG_COLUMN is not mocked on table.")) end ;test_cclutAddMockIndex_invalid_column /* test_cclutAddMockIndex_duplicate_column_name ************************************************************* * Scenario: Throws an error if any of the column names are duplicated (names are case-insensitive) * ************************************************************************************************************/ subroutine test_cclutAddMockIndex_duplicate_column_name(null) - call echo("~~~***~~~***test_cclutAddMockIndex_duplicate_column_name***~~~***~~~") - call cclutDefineMockTable("sample_table", "sample_table_id|sample_table_text|sample_table_date", "f8|vc|dq8") - declare errorMessage = vc with protect, noconstant("") + declare errorMessage = vc with protect, noconstant("") declare errorCode = i4 with protect, noconstant(0) - call cclutAddMockIndex("sample_table", "sample_table_text|sample_table_id|sample_table_text", 1) + call cclutAddMockIndex("sample_table", "sample_table_text|sample_table_id|sample_table_text", 1) - set errorCode = error(errorMessage, 0) + set errorCode = error(errorMessage, 0) - call cclutAssertVcOperator(CURREF, "test_cclutAddMockIndex_duplicate_column_name", trim(errorMessage, 3), + call cclutAssertVcOperator(CURREF, "test_cclutAddMockIndex_duplicate_column_name 001", trim(errorMessage, 3), "regexplike", concat("%CCL-E-392-PRG_[0-9]+_[0-9]+\([^)]+\)[0-9]+:[0-9]+\{CCLEXCEPTION\(\)\}Exception\(100\):", - " cclutAddMockIndex\(\) - Duplicate columnName found. columnName: SAMPLE_TABLE_TEXT.")) + " cclutAddMockIndex\(SAMPLE_TABLE\) - Duplicate columnName found. columnName: SAMPLE_TABLE_TEXT.")) end ;test_cclutAddMockIndex_duplicate_column_name ;********************************************************************************************************************************** @@ -539,71 +575,63 @@ end ;test_cclutAddMockIndex_duplicate_column_name * Scenario: Adds a mock table to the RDBMS with the values defined in cclutDefineMockTable * ************************************************************************************************************/ subroutine test_cclutCreateMockTable_happy(null) - call echo("~~~***~~~***test_cclutCreateMockTable_happy***~~~***~~~") - declare mockTable = vc with protect, noconstant("") set mockTable = cclutDefineMockTable("sample_table", "sample_table_id|sample_table_text|sample_table_date", "f8|vc|dq8") call cclutCreateMockTable("sample_table") call cclutAddMockData("sample_table", "1.0|test text|27-NOV-2018 08:00") - declare mockId = f8 with protect, noconstant(0.0) - declare mockText = vc with protect, noconstant("") - declare mockDate = dq8 with protect, noconstant(0) - select into "nl:" - from (value(mockTable) m) - detail - mockId = m.SAMPLE_TABLE_ID - mockText = m.SAMPLE_TABLE_TEXT - mockDate = m.SAMPLE_TABLE_DATE - with nocounter - - call cclutAssertf8Equal(CURREF, "test_cclutCreateMockTable_happy", mockId, 1.0) - call cclutAssertvcEqual(CURREF, "test_cclutCreateMockTable_happy", mockText, "test text") - call cclutAssertf8Equal(CURREF, "test_cclutCreateMockTable_happy", mockDate, cnvtdatetime("27-NOV-2018 08:00")) + declare mockId = f8 with protect, noconstant(0.0) + declare mockText = vc with protect, noconstant("") + declare mockDate = dq8 with protect, noconstant(0) + select into "nl:" + from (value(mockTable) m) + detail + mockId = m.SAMPLE_TABLE_ID + mockText = m.SAMPLE_TABLE_TEXT + mockDate = m.SAMPLE_TABLE_DATE + with nocounter + + call cclutAssertf8Equal(CURREF, "test_cclutCreateMockTable_happy 001", mockId, 1.0) + call cclutAssertvcEqual(CURREF, "test_cclutCreateMockTable_happy 002", mockText, "test text") + call cclutAssertf8Equal(CURREF, "test_cclutCreateMockTable_happy 003", mockDate, cnvtdatetime("27-NOV-2018 08:00")) end ;test_cclutCreateMockTable_happy /* test_cclutCreateMockTable_missing_tableName ************************************************************** * Scenario: Throws an error when an empty tableName is supplied to the function (after trimming) * ************************************************************************************************************/ subroutine test_cclutCreateMockTable_missing_tableName(null) - call echo("~~~***~~~***test_cclutCreateMockTable_missing_tableName***~~~***~~~") - - declare errorMessage = vc with protect, noconstant("") + declare errorMessage = vc with protect, noconstant("") declare errorCode = i4 with protect, noconstant(0) - call cclutCreateMockTable(" ") + call cclutCreateMockTable(" ") - set errorCode = error(errorMessage, 0) + set errorCode = error(errorMessage, 0) - call cclutAssertVcOperator(CURREF, "test_cclutCreateMockTable_missing_tableName", trim(errorMessage, 3), + call cclutAssertVcOperator(CURREF, "test_cclutCreateMockTable_missing_tableName 001", trim(errorMessage, 3), "regexplike", concat("%CCL-E-392-PRG_[0-9]+_[0-9]+\([^)]+\)[0-9]+:[0-9]+\{CCLEXCEPTION\(\)\}Exception\(100\):", - " cclutCreateMockTable\(\) - tableName is a required field.")) + " cclutValidateParameterIsNotEmpty\(\) - tableName is a required field.")) end ;test_cclutCreateMockTable_missing_tableName /* test_cclutCreateMockTable_unmocked_table ***************************************************************** * Scenario: Throws an error when the tableName specified has not been mocked through cclutDefineMockTable * ************************************************************************************************************/ subroutine test_cclutCreateMockTable_unmocked_table(null) - call echo("~~~***~~~***test_cclutCreateMockTable_unmocked_table***~~~***~~~") - - declare errorMessage = vc with protect, noconstant("") + declare errorMessage = vc with protect, noconstant("") declare errorCode = i4 with protect, noconstant(0) - call cclutCreateMockTable("sample_table") + call cclutCreateMockTable("sample_table") - set errorCode = error(errorMessage, 0) + set errorCode = error(errorMessage, 0) - call cclutAssertVcOperator(CURREF, "test_cclutCreateMockTable_unmocked_table", trim(errorMessage, 3), + call cclutAssertVcOperator(CURREF, "test_cclutCreateMockTable_unmocked_table 001", trim(errorMessage, 3), "regexplike", concat("%CCL-E-392-PRG_[0-9]+_[0-9]+\([^)]+\)[0-9]+:[0-9]+\{CCLEXCEPTION\(\)\}Exception\(100\):", - " cclutCreateMockTable\(\) - tableName has not been mocked. tableName: SAMPLE_TABLE.")) + " cclutValidateMockTableIsDefined\(SAMPLE_TABLE\) - Table has not been mocked.")) end ;test_cclutCreateMockTable_unmocked_table /* test_cclutCreateMockTable_created_table ****************************************************************** * Scenario: Does nothing if the table has already been created * ************************************************************************************************************/ subroutine test_cclutCreateMockTable_created_table(null) - call echo("~~~***~~~***test_cclutCreateMockTable_created_table***~~~***~~~") - - declare mockTable = vc with protect, noconstant("") + declare mockTable = vc with protect, noconstant("") set mockTable = cclutDefineMockTable("sample_table", "sample_table_id|sample_table_text|sample_table_date", "f8|vc|dq8") call cclutCreateMockTable("sample_table") @@ -622,9 +650,9 @@ subroutine test_cclutCreateMockTable_created_table(null) mockDate = m.SAMPLE_TABLE_DATE with nocounter - call cclutAssertf8Equal(CURREF, "test_cclutCreateMockTable_happy", mockId, 1.0) - call cclutAssertvcEqual(CURREF, "test_cclutCreateMockTable_happy", mockText, "test text") - call cclutAssertf8Equal(CURREF, "test_cclutCreateMockTable_happy", mockDate, cnvtdatetime("27-NOV-2018 08:00")) + call cclutAssertf8Equal(CURREF, "test_cclutCreateMockTable_happy 001", mockId, 1.0) + call cclutAssertvcEqual(CURREF, "test_cclutCreateMockTable_happy 002", mockText, "test text") + call cclutAssertf8Equal(CURREF, "test_cclutCreateMockTable_happy 003", mockDate, cnvtdatetime("27-NOV-2018 08:00")) end ;test_cclutCreateMockTable_created_table ;********************************************************************************************************************************** @@ -634,22 +662,18 @@ end ;test_cclutCreateMockTable_created_table * Scenario: Removes a mock table that has not been created yet * ************************************************************************************************************/ subroutine test_cclutRemoveMockTable_happy(null) - call echo("~~~***~~~***test_cclutRemoveMockTable_happy***~~~***~~~") - declare mockTable = vc with protect, noconstant("") set mockTable = cclutDefineMockTable("sample_table", "sample_table_id|sample_table_text|sample_table_date", "f8|vc|dq8") call cclutRemoveMockTable("sample_table") - call cclutAsserti4Equal(CURREF, "test_cclutRemoveMockTable_happy", size(cclut_mockTables->tables, 5), 0) + call cclutAsserti4Equal(CURREF, "test_cclutRemoveMockTable_happy 001", size(cclut_mockTables->tables, 5), 0) end ;test_cclutRemoveMockTable_happy /* test_cclutRemoveMockTable_created_table ****************************************************************** * Scenario: Removes a mock table that has been created yet and drops it from the RDBMS * ************************************************************************************************************/ subroutine test_cclutRemoveMockTable_created_table(null) - call echo("~~~***~~~***test_cclutRemoveMockTable_created_table***~~~***~~~") - declare mockTable = vc with protect, noconstant("") set mockTable = cclutDefineMockTable("sample_table", "sample_table_id|sample_table_text|sample_table_date", "f8|vc|dq8") @@ -667,9 +691,9 @@ subroutine test_cclutRemoveMockTable_created_table(null) mockDate = m.SAMPLE_TABLE_DATE with nocounter - call cclutAssertf8Equal(CURREF, "test_cclutRemoveMockTable_created_table", mockId, 1.0) - call cclutAssertvcEqual(CURREF, "test_cclutRemoveMockTable_created_table", mockText, "test text") - call cclutAssertf8Equal(CURREF, "test_cclutRemoveMockTable_created_table", mockDate, + call cclutAssertf8Equal(CURREF, "test_cclutRemoveMockTable_created_table 001", mockId, 1.0) + call cclutAssertvcEqual(CURREF, "test_cclutRemoveMockTable_created_table 002", mockText, "test text") + call cclutAssertf8Equal(CURREF, "test_cclutRemoveMockTable_created_table 003", mockDate, cnvtdatetime("27-NOV-2018 08:00")) call cclutRemoveMockTable("sample_table") @@ -686,28 +710,26 @@ subroutine test_cclutRemoveMockTable_created_table(null) declare errorCode = i4 with protect, noconstant(0) set errorCode = error(errorMessage, 0) - call cclutAssertVcOperator(CURREF, "test_cclutRemoveMockTable_created_table", trim(errorMessage, 3), + call cclutAssertVcOperator(CURREF, "test_cclutRemoveMockTable_created_table 004", trim(errorMessage, 3), "regexplike", concat("%CCL-E-18-PRG_[0-9]+_[0-9]+\([^)]+\)[0-9]+:[0-9]+\{\}Unable to add range, definition for", " table \(CUST_CCLUT_[^)]*\) not found in dictionary.")) - call cclutAsserti4Equal(CURREF, "test_cclutRemoveMockTable_created_table", size(cclut_mockTables->tables, 5), 0) + call cclutAsserti4Equal(CURREF, "test_cclutRemoveMockTable_created_table 005", size(cclut_mockTables->tables, 5), 0) end ;test_cclutRemoveMockTable_created_table /* test_cclutRemoveMockTable_missing_tableName ************************************************************** * Scenario: Throws an error when an empty tableName is supplied to the function (after trimming) * ************************************************************************************************************/ subroutine test_cclutRemoveMockTable_missing_tableName(null) - call echo("~~~***~~~***test_cclutRemoveMockTable_missing_tableName***~~~***~~~") - - declare errorMessage = vc with protect, noconstant("") + declare errorMessage = vc with protect, noconstant("") declare errorCode = i4 with protect, noconstant(0) - call cclutRemoveMockTable(" ") + call cclutRemoveMockTable(" ") - set errorCode = error(errorMessage, 0) + set errorCode = error(errorMessage, 0) - call cclutAssertVcOperator(CURREF, "test_cclutRemoveMockTable_missing_tableName", trim(errorMessage, 3), + call cclutAssertVcOperator(CURREF, "test_cclutRemoveMockTable_missing_tableName 001", trim(errorMessage, 3), "regexplike", concat("%CCL-E-392-PRG_[0-9]+_[0-9]+\([^)]+\)[0-9]+:[0-9]+\{CCLEXCEPTION\(\)\}Exception\(100\):", - " cclutRemoveMockTable\(\) - tableName is a required field.")) + " cclutValidateParameterIsNotEmpty\(\) - tableName is a required field.")) end ;test_cclutRemoveMockTable_missing_tableName ;********************************************************************************************************************************** @@ -717,19 +739,17 @@ end ;test_cclutRemoveMockTable_missing_tableName * Scenario: Removes all mock tables that have been mocked regardless of whether they have been created * ************************************************************************************************************/ subroutine test_cclutRemoveAllMockTables_happy(null) - call echo("~~~***~~~***test_cclutRemoveAllMockTables_happy***~~~***~~~") - call cclutDefineMockTable("sample_table", "sample_table_id|sample_table_text|sample_table_date", "f8|vc|dq8") call cclutDefineMockTable("sample_table_2", "sample_table_2_id|sample_table_2_text|sample_table_2_date", "f8|vc|dq8") call cclutDefineMockTable("sample_table_3", "sample_table_3_id|sample_table_3_text|sample_table_3_date", "f8|vc|dq8") - call cclutAsserti4Equal(CURREF, "test_cclutRemoveAllMockTables_happy", size(cclut_mockTables->tables, 5), 3) + call cclutAsserti4Equal(CURREF, "test_cclutRemoveAllMockTables_happy 001", size(cclut_mockTables->tables, 5), 3) call cclutRemoveAllMockTables(null) - call cclutAsserti4Equal(CURREF, "test_cclutRemoveAllMockTables_happy", size(cclut_mockTables->tables, 5), 0) + call cclutAsserti4Equal(CURREF, "test_cclutRemoveAllMockTables_happy 002", size(cclut_mockTables->tables, 5), 0) end ;test_cclutRemoveAllMockTables_happy ;********************************************************************************************************************************** @@ -739,8 +759,6 @@ end ;test_cclutRemoveAllMockTables_happy * Scenario: Adds the appropriate mock data to the table when the data has no escape characters or nulls * ************************************************************************************************************/ subroutine test_cclutAddMockData_happy(null) - call echo("~~~***~~~***test_cclutAddMockData_happy***~~~***~~~") - declare mockTable = vc with protect, noconstant("") set mockTable = cclutDefineMockTable("sample_table", "sample_table_id|sample_table_text|sample_table_date", "f8|vc|dq8") @@ -761,9 +779,9 @@ subroutine test_cclutAddMockData_happy(null) mockDate = m.SAMPLE_TABLE_DATE with nocounter - call cclutAssertf8Equal(CURREF, "test_cclutAddMockData_happy", mockId, 1.0) - call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_happy", mockText, "test text") - call cclutAssertf8Equal(CURREF, "test_cclutAddMockData_happy", mockDate, cnvtdatetime("27-NOV-2018 08:00")) + call cclutAssertf8Equal(CURREF, "test_cclutAddMockData_happy 001", mockId, 1.0) + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_happy 002", mockText, "test text") + call cclutAssertf8Equal(CURREF, "test_cclutAddMockData_happy 003", mockDate, cnvtdatetime("27-NOV-2018 08:00")) select into "nl:" from (value(mockTable) m) @@ -774,9 +792,9 @@ subroutine test_cclutAddMockData_happy(null) mockDate = m.SAMPLE_TABLE_DATE with nocounter - call cclutAssertf8Equal(CURREF, "test_cclutAddMockData_happy", mockId, 2.0) - call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_happy", mockText, "test |text\ 2") - call cclutAssertf8Equal(CURREF, "test_cclutAddMockData_happy", mockDate, cnvtdatetime("28-NOV-2018 09:00")) + call cclutAssertf8Equal(CURREF, "test_cclutAddMockData_happy 004", mockId, 2.0) + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_happy 005", mockText, "test |text\ 2") + call cclutAssertf8Equal(CURREF, "test_cclutAddMockData_happy 006", mockDate, cnvtdatetime("28-NOV-2018 09:00")) select into "nl:" from (value(mockTable) m) @@ -787,50 +805,92 @@ subroutine test_cclutAddMockData_happy(null) mockDate = m.SAMPLE_TABLE_DATE with nocounter - call cclutAssertf8Equal(CURREF, "test_cclutAddMockData_happy", mockId, 3.0) - call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_happy", mockText, "test text 3") - call cclutAssertf8Equal(CURREF, "test_cclutAddMockData_happy", mockDate, cnvtdatetime("29-NOV-2018 10:00")) + call cclutAssertf8Equal(CURREF, "test_cclutAddMockData_happy 007", mockId, 3.0) + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_happy 008", mockText, "test text 3") + call cclutAssertf8Equal(CURREF, "test_cclutAddMockData_happy 009", mockDate, cnvtdatetime("29-NOV-2018 10:00")) end ;test_cclutAddMockData_happy /* test_cclutAddMockData_empty_single_column **************************************************************** * Scenario: Correctly handles adding an empty string to a table with a single column when rowData is empty * ************************************************************************************************************/ subroutine test_cclutAddMockData_empty_single_column(null) - call echo("~~~***~~~***test_cclutAddMockData_empty_single_column***~~~***~~~") - declare mockTable = vc with protect, noconstant("") set mockTable = cclutDefineMockTable("sample_table", "sample_table_text", "vc") + call cclutCreateMockTable("sample_table") + call cclutAddMockData("sample_table", char(0)) + + declare mockLength = i4 with protect, noconstant(0) + declare mockIChar = i4 with protect, noconstant(0) + select into "nl:" + from (value(mockTable) m) + detail + mockLength = textlen(m.SAMPLE_TABLE_TEXT) + mockIChar = ichar(m.SAMPLE_TABLE_TEXT) + with nocounter + + call cclutAsserti4Equal(CURREF, "test_cclutAddMockData_empty_single_column 001", mockLength, 1) + call cclutAsserti4Equal(CURREF, "test_cclutAddMockData_empty_single_column 002", mockIChar, 0) + call cclutCreateMockTable("sample_table") call cclutAddMockData("sample_table", "") - declare mockText = vc with protect, noconstant("") + declare mockLength = i4 with protect, noconstant(0) + declare mockIChar = i4 with protect, noconstant(0) select into "nl:" from (value(mockTable) m) detail - mockText = m.SAMPLE_TABLE_TEXT + mockLength = textlen(m.SAMPLE_TABLE_TEXT) + mockIChar = ichar(m.SAMPLE_TABLE_TEXT) with nocounter - call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_empty_single_column", mockText, "") + call cclutAsserti4Equal(CURREF, "test_cclutAddMockData_empty_single_column 003", mockLength, 1) + call cclutAsserti4Equal(CURREF, "test_cclutAddMockData_empty_single_column 004", mockIChar, 0) call cclutClearMockData("sample_table") - call cclutAddMockData("sample_table", " ") + call cclutAddMockData("sample_table", notrim(" ")) select into "nl:" from (value(mockTable) m) detail - mockText = m.SAMPLE_TABLE_TEXT + mockLength = textlen(m.SAMPLE_TABLE_TEXT) + mockIChar = ichar(m.SAMPLE_TABLE_TEXT) with nocounter - call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_empty_single_column", mockText, " ") + call cclutAsserti4Equal(CURREF, "test_cclutAddMockData_empty_single_column 005", mockLength, 1) + call cclutAsserti4Equal(CURREF, "test_cclutAddMockData_empty_single_column 006", mockIChar, 32) + + call cclutClearMockData("sample_table") + call cclutAddMockData("sample_table", trim("")) + + select into "nl:" + from (value(mockTable) m) + detail + mockLength = textlen(m.SAMPLE_TABLE_TEXT) + mockIChar = ichar(m.SAMPLE_TABLE_TEXT) + with nocounter + + call cclutAsserti4Equal(CURREF, "test_cclutAddMockData_empty_single_column 007", mockLength, 0) + call cclutAsserti4Equal(CURREF, "test_cclutAddMockData_empty_single_column 008", mockIChar, 32) + + call cclutClearMockData("sample_table") + call cclutAddMockData("sample_table", trim(" ")) + + select into "nl:" + from (value(mockTable) m) + detail + mockLength = textlen(m.SAMPLE_TABLE_TEXT) + mockIChar = ichar(m.SAMPLE_TABLE_TEXT) + with nocounter + + call cclutAsserti4Equal(CURREF, "test_cclutAddMockData_empty_single_column 009", mockLength, 0) + call cclutAsserti4Equal(CURREF, "test_cclutAddMockData_empty_single_column 010", mockIChar, 32) end ;test_cclutAddMockData_empty_single_column /* test_cclutAddMockData_empty_string_tests ***************************************************************** * Scenario: Correctly handles empty strings regardless of where they are in the rowData parameter * ************************************************************************************************************/ subroutine test_cclutAddMockData_empty_string_tests(null) - call echo("~~~***~~~***test_cclutAddMockData_empty_string_tests***~~~***~~~") - declare mockTable = vc with protect, noconstant("") set mockTable = cclutDefineMockTable("sample_table", "sample_table_text_1|sample_table_text_2|sample_table_text_3", "vc|vc|vc") @@ -848,9 +908,9 @@ subroutine test_cclutAddMockData_empty_string_tests(null) mockText3 = m.SAMPLE_TABLE_TEXT_3 with nocounter - call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_empty_string_tests", mockText1, "") - call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_empty_string_tests", mockText2, "test") - call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_empty_string_tests", mockText3, "test 2") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_empty_string_tests 001", mockText1, "") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_empty_string_tests 002", mockText2, "test") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_empty_string_tests 003", mockText3, "test 2") call cclutClearMockData("sample_table") call cclutAddMockData("sample_table", "test||test 2") @@ -863,9 +923,9 @@ subroutine test_cclutAddMockData_empty_string_tests(null) mockText3 = m.SAMPLE_TABLE_TEXT_3 with nocounter - call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_empty_string_tests", mockText1, "test") - call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_empty_string_tests", mockText2, "") - call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_empty_string_tests", mockText3, "test 2") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_empty_string_tests 004", mockText1, "test") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_empty_string_tests 005", mockText2, "") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_empty_string_tests 006", mockText3, "test 2") call cclutClearMockData("sample_table") call cclutAddMockData("sample_table", "test|test 2|") @@ -878,9 +938,9 @@ subroutine test_cclutAddMockData_empty_string_tests(null) mockText3 = m.SAMPLE_TABLE_TEXT_3 with nocounter - call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_empty_string_tests", mockText1, "test") - call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_empty_string_tests", mockText2, "test 2") - call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_empty_string_tests", mockText3, "") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_empty_string_tests 007", mockText1, "test") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_empty_string_tests 008", mockText2, "test 2") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_empty_string_tests 009", mockText3, "") call cclutClearMockData("sample_table") call cclutAddMockData("sample_table", "||test") @@ -893,9 +953,9 @@ subroutine test_cclutAddMockData_empty_string_tests(null) mockText3 = m.SAMPLE_TABLE_TEXT_3 with nocounter - call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_empty_string_tests", mockText1, "") - call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_empty_string_tests", mockText2, "") - call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_empty_string_tests", mockText3, "test") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_empty_string_tests 010", mockText1, "") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_empty_string_tests 011", mockText2, "") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_empty_string_tests 012", mockText3, "test") call cclutClearMockData("sample_table") call cclutAddMockData("sample_table", "|test|") @@ -908,9 +968,9 @@ subroutine test_cclutAddMockData_empty_string_tests(null) mockText3 = m.SAMPLE_TABLE_TEXT_3 with nocounter - call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_empty_string_tests", mockText1, "") - call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_empty_string_tests", mockText2, "test") - call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_empty_string_tests", mockText3, "") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_empty_string_tests 013", mockText1, "") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_empty_string_tests 014", mockText2, "test") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_empty_string_tests 015", mockText3, "") call cclutClearMockData("sample_table") call cclutAddMockData("sample_table", "test||") @@ -923,9 +983,9 @@ subroutine test_cclutAddMockData_empty_string_tests(null) mockText3 = m.SAMPLE_TABLE_TEXT_3 with nocounter - call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_empty_string_tests", mockText1, "test") - call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_empty_string_tests", mockText2, "") - call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_empty_string_tests", mockText3, "") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_empty_string_tests 016", mockText1, "test") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_empty_string_tests 017", mockText2, "") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_empty_string_tests 018", mockText3, "") call cclutClearMockData("sample_table") call cclutAddMockData("sample_table", "||") @@ -938,17 +998,15 @@ subroutine test_cclutAddMockData_empty_string_tests(null) mockText3 = m.SAMPLE_TABLE_TEXT_3 with nocounter - call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_empty_string_tests", mockText1, "") - call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_empty_string_tests", mockText2, "") - call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_empty_string_tests", mockText3, "") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_empty_string_tests 019", mockText1, "") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_empty_string_tests 020", mockText2, "") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_empty_string_tests 021", mockText3, "") end ;test_cclutAddMockData_empty_string_tests /* test_cclutAddMockData_backslash_tests ******************************************************************** * Scenario: Correctly handles strings with backslashes * ************************************************************************************************************/ subroutine test_cclutAddMockData_backslash_tests(null) - call echo("~~~***~~~***test_cclutAddMockData_backslash_tests***~~~***~~~") - declare mockTable = vc with protect, noconstant("") set mockTable = cclutDefineMockTable("sample_table", "sample_table_text_1|sample_table_text_2|sample_table_text_3", "vc|vc|vc") @@ -966,9 +1024,9 @@ subroutine test_cclutAddMockData_backslash_tests(null) mockText3 = m.SAMPLE_TABLE_TEXT_3 with nocounter - call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_backslash_tests", mockText1, "\\\") - call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_backslash_tests", mockText2, "test") - call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_backslash_tests", mockText3, "test 2") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_backslash_tests 001", mockText1, "\\\") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_backslash_tests 002", mockText2, "test") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_backslash_tests 003", mockText3, "test 2") call cclutClearMockData("sample_table") call cclutAddMockData("sample_table", "test|\\\\\\|test 2") @@ -981,9 +1039,9 @@ subroutine test_cclutAddMockData_backslash_tests(null) mockText3 = m.SAMPLE_TABLE_TEXT_3 with nocounter - call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_backslash_tests", mockText1, "test") - call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_backslash_tests", mockText2, "\\\") - call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_backslash_tests", mockText3, "test 2") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_backslash_tests 004", mockText1, "test") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_backslash_tests 005", mockText2, "\\\") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_backslash_tests 006", mockText3, "test 2") call cclutClearMockData("sample_table") call cclutAddMockData("sample_table", "test|test 2|\\\\\\") @@ -996,9 +1054,9 @@ subroutine test_cclutAddMockData_backslash_tests(null) mockText3 = m.SAMPLE_TABLE_TEXT_3 with nocounter - call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_backslash_tests", mockText1, "test") - call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_backslash_tests", mockText2, "test 2") - call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_backslash_tests", mockText3, "\\\") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_backslash_tests 007", mockText1, "test") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_backslash_tests 008", mockText2, "test 2") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_backslash_tests 009", mockText3, "\\\") call cclutClearMockData("sample_table") call cclutAddMockData("sample_table", "\\\\\\|\\\\\\|test") @@ -1011,9 +1069,9 @@ subroutine test_cclutAddMockData_backslash_tests(null) mockText3 = m.SAMPLE_TABLE_TEXT_3 with nocounter - call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_backslash_tests", mockText1, "\\\") - call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_backslash_tests", mockText2, "\\\") - call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_backslash_tests", mockText3, "test") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_backslash_tests 010", mockText1, "\\\") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_backslash_tests 011", mockText2, "\\\") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_backslash_tests 012", mockText3, "test") call cclutClearMockData("sample_table") call cclutAddMockData("sample_table", "\\\\\\|test|\\\\\\") @@ -1026,9 +1084,9 @@ subroutine test_cclutAddMockData_backslash_tests(null) mockText3 = m.SAMPLE_TABLE_TEXT_3 with nocounter - call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_backslash_tests", mockText1, "\\\") - call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_backslash_tests", mockText2, "test") - call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_backslash_tests", mockText3, "\\\") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_backslash_tests 013", mockText1, "\\\") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_backslash_tests 014", mockText2, "test") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_backslash_tests 015", mockText3, "\\\") call cclutClearMockData("sample_table") call cclutAddMockData("sample_table", "test|\\\\\\|\\\\\\") @@ -1041,9 +1099,9 @@ subroutine test_cclutAddMockData_backslash_tests(null) mockText3 = m.SAMPLE_TABLE_TEXT_3 with nocounter - call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_backslash_tests", mockText1, "test") - call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_backslash_tests", mockText2, "\\\") - call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_backslash_tests", mockText3, "\\\") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_backslash_tests 016", mockText1, "test") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_backslash_tests 017", mockText2, "\\\") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_backslash_tests 018", mockText3, "\\\") call cclutClearMockData("sample_table") call cclutAddMockData("sample_table", "\\\\\\|\\\\\\|\\\\\\") @@ -1056,17 +1114,15 @@ subroutine test_cclutAddMockData_backslash_tests(null) mockText3 = m.SAMPLE_TABLE_TEXT_3 with nocounter - call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_backslash_tests", mockText1, "\\\") - call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_backslash_tests", mockText2, "\\\") - call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_backslash_tests", mockText3, "\\\") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_backslash_tests 019", mockText1, "\\\") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_backslash_tests 020", mockText2, "\\\") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_backslash_tests 021", mockText3, "\\\") end ;test_cclutAddMockData_backslash_tests /* test_cclutAddMockData_null_tests ************************************************************************* * Scenario: Correctly handles strings with nulls * ************************************************************************************************************/ subroutine test_cclutAddMockData_null_tests(null) - call echo("~~~***~~~***test_cclutAddMockData_null_tests***~~~***~~~") - declare mockTable = vc with protect, noconstant("") set mockTable = cclutDefineMockTable("sample_table", "sample_table_text_1|sample_table_text_2|sample_table_text_3", "vc|vc|vc") @@ -1092,11 +1148,11 @@ subroutine test_cclutAddMockData_null_tests(null) mockText3 = m.SAMPLE_TABLE_TEXT_3 with nocounter - call cclutAsserti4Equal(CURREF, "test_cclutAddMockData_null_tests", mockNull1, 1) - call cclutAsserti4Equal(CURREF, "test_cclutAddMockData_null_tests", mockNull2, 0) - call cclutAsserti4Equal(CURREF, "test_cclutAddMockData_null_tests", mockNull3, 0) - call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_null_tests", mockText2, "test") - call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_null_tests", mockText3, "test 2") + call cclutAsserti4Equal(CURREF, "test_cclutAddMockData_null_tests 001", mockNull1, 1) + call cclutAsserti4Equal(CURREF, "test_cclutAddMockData_null_tests 002", mockNull2, 0) + call cclutAsserti4Equal(CURREF, "test_cclutAddMockData_null_tests 003", mockNull3, 0) + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_null_tests 004", mockText2, "test") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_null_tests 005", mockText3, "test 2") call cclutClearMockData("sample_table") call cclutAddMockData("sample_table", "test|\null|test 2") @@ -1114,11 +1170,11 @@ subroutine test_cclutAddMockData_null_tests(null) mockText3 = m.SAMPLE_TABLE_TEXT_3 with nocounter - call cclutAsserti4Equal(CURREF, "test_cclutAddMockData_null_tests", mockNull1, 0) - call cclutAsserti4Equal(CURREF, "test_cclutAddMockData_null_tests", mockNull2, 1) - call cclutAsserti4Equal(CURREF, "test_cclutAddMockData_null_tests", mockNull3, 0) - call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_null_tests", mockText1, "test") - call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_null_tests", mockText3, "test 2") + call cclutAsserti4Equal(CURREF, "test_cclutAddMockData_null_tests 006", mockNull1, 0) + call cclutAsserti4Equal(CURREF, "test_cclutAddMockData_null_tests 007", mockNull2, 1) + call cclutAsserti4Equal(CURREF, "test_cclutAddMockData_null_tests 008", mockNull3, 0) + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_null_tests 009", mockText1, "test") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_null_tests 010", mockText3, "test 2") call cclutClearMockData("sample_table") call cclutAddMockData("sample_table", "test|test 2|\null") @@ -1136,11 +1192,11 @@ subroutine test_cclutAddMockData_null_tests(null) mockText2 = m.SAMPLE_TABLE_TEXT_2 with nocounter - call cclutAsserti4Equal(CURREF, "test_cclutAddMockData_null_tests", mockNull1, 0) - call cclutAsserti4Equal(CURREF, "test_cclutAddMockData_null_tests", mockNull2, 0) - call cclutAsserti4Equal(CURREF, "test_cclutAddMockData_null_tests", mockNull3, 1) - call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_null_tests", mockText1, "test") - call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_null_tests", mockText2, "test 2") + call cclutAsserti4Equal(CURREF, "test_cclutAddMockData_null_tests 011", mockNull1, 0) + call cclutAsserti4Equal(CURREF, "test_cclutAddMockData_null_tests 012", mockNull2, 0) + call cclutAsserti4Equal(CURREF, "test_cclutAddMockData_null_tests 013", mockNull3, 1) + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_null_tests 014", mockText1, "test") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_null_tests 015", mockText2, "test 2") call cclutClearMockData("sample_table") call cclutAddMockData("sample_table", "\null|\null|test") @@ -1157,10 +1213,10 @@ subroutine test_cclutAddMockData_null_tests(null) mockText3 = m.SAMPLE_TABLE_TEXT_3 with nocounter - call cclutAsserti4Equal(CURREF, "test_cclutAddMockData_null_tests", mockNull1, 1) - call cclutAsserti4Equal(CURREF, "test_cclutAddMockData_null_tests", mockNull2, 1) - call cclutAsserti4Equal(CURREF, "test_cclutAddMockData_null_tests", mockNull3, 0) - call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_null_tests", mockText3, "test") + call cclutAsserti4Equal(CURREF, "test_cclutAddMockData_null_tests 016", mockNull1, 1) + call cclutAsserti4Equal(CURREF, "test_cclutAddMockData_null_tests 017", mockNull2, 1) + call cclutAsserti4Equal(CURREF, "test_cclutAddMockData_null_tests 018", mockNull3, 0) + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_null_tests 019", mockText3, "test") call cclutClearMockData("sample_table") call cclutAddMockData("sample_table", "\null|test|\null") @@ -1177,10 +1233,10 @@ subroutine test_cclutAddMockData_null_tests(null) mockText2 = m.SAMPLE_TABLE_TEXT_2 with nocounter - call cclutAsserti4Equal(CURREF, "test_cclutAddMockData_null_tests", mockNull1, 1) - call cclutAsserti4Equal(CURREF, "test_cclutAddMockData_null_tests", mockNull2, 0) - call cclutAsserti4Equal(CURREF, "test_cclutAddMockData_null_tests", mockNull3, 1) - call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_null_tests", mockText2, "test") + call cclutAsserti4Equal(CURREF, "test_cclutAddMockData_null_tests 020", mockNull1, 1) + call cclutAsserti4Equal(CURREF, "test_cclutAddMockData_null_tests 021", mockNull2, 0) + call cclutAsserti4Equal(CURREF, "test_cclutAddMockData_null_tests 022", mockNull3, 1) + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_null_tests 023", mockText2, "test") call cclutClearMockData("sample_table") call cclutAddMockData("sample_table", "test|\null|\null") @@ -1197,10 +1253,10 @@ subroutine test_cclutAddMockData_null_tests(null) mockText1 = m.SAMPLE_TABLE_TEXT_1 with nocounter - call cclutAsserti4Equal(CURREF, "test_cclutAddMockData_null_tests", mockNull1, 0) - call cclutAsserti4Equal(CURREF, "test_cclutAddMockData_null_tests", mockNull2, 1) - call cclutAsserti4Equal(CURREF, "test_cclutAddMockData_null_tests", mockNull3, 1) - call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_null_tests", mockText1, "test") + call cclutAsserti4Equal(CURREF, "test_cclutAddMockData_null_tests 024", mockNull1, 0) + call cclutAsserti4Equal(CURREF, "test_cclutAddMockData_null_tests 025", mockNull2, 1) + call cclutAsserti4Equal(CURREF, "test_cclutAddMockData_null_tests 026", mockNull3, 1) + call cclutAssertvcEqual(CURREF, "test_cclutAddMockData_null_tests 027", mockText1, "test") call cclutClearMockData("sample_table") call cclutAddMockData("sample_table", "\null|\null|\null") @@ -1216,120 +1272,108 @@ subroutine test_cclutAddMockData_null_tests(null) mockNull3 = sampleTableText3Null with nocounter - call cclutAsserti4Equal(CURREF, "test_cclutAddMockData_null_tests", mockNull1, 1) - call cclutAsserti4Equal(CURREF, "test_cclutAddMockData_null_tests", mockNull2, 1) - call cclutAsserti4Equal(CURREF, "test_cclutAddMockData_null_tests", mockNull3, 1) + call cclutAsserti4Equal(CURREF, "test_cclutAddMockData_null_tests 028", mockNull1, 1) + call cclutAsserti4Equal(CURREF, "test_cclutAddMockData_null_tests 029", mockNull2, 1) + call cclutAsserti4Equal(CURREF, "test_cclutAddMockData_null_tests 030", mockNull3, 1) end ;test_cclutAddMockData_null_tests /* test_cclutAddMockData_missing_tableName ****************************************************************** * Scenario: Throws an error when an empty tableName is supplied to the function (after trimming) * ************************************************************************************************************/ subroutine test_cclutAddMockData_missing_tableName(null) - call echo("~~~***~~~***test_cclutAddMockData_missing_tableName***~~~***~~~") - - declare errorMessage = vc with protect, noconstant("") + declare errorMessage = vc with protect, noconstant("") declare errorCode = i4 with protect, noconstant(0) - call cclutAddMockData(" ", "1.0|test text|27-NOV-2018 08:00") + call cclutAddMockData(" ", "1.0|test text|27-NOV-2018 08:00") - set errorCode = error(errorMessage, 0) + set errorCode = error(errorMessage, 0) - call cclutAssertVcOperator(CURREF, "test_cclutAddMockData_missing_tableName", trim(errorMessage, 3), + call cclutAssertVcOperator(CURREF, "test_cclutAddMockData_missing_tableName 001", trim(errorMessage, 3), "regexplike", concat("%CCL-E-392-PRG_[0-9]+_[0-9]+\([^)]+\)[0-9]+:[0-9]+\{CCLEXCEPTION\(\)\}Exception\(100\):", - " cclutAddMockData\(\) - tableName is a required field.")) + " cclutValidateParameterIsNotEmpty\(\) - tableName is a required field.")) end ;test_cclutAddMockData_missing_tableName /* test_cclutAddMockData_unmocked_table ********************************************************************* * Scenario: Throws an error when the tableName specified has not been mocked through cclutDefineMockTable * ************************************************************************************************************/ subroutine test_cclutAddMockData_unmocked_table(null) - call echo("~~~***~~~***test_cclutAddMockData_unmocked_table***~~~***~~~") - - declare errorMessage = vc with protect, noconstant("") + declare errorMessage = vc with protect, noconstant("") declare errorCode = i4 with protect, noconstant(0) - call cclutAddMockData("sample_table", "1.0|test text|27-NOV-2018 08:00") + call cclutAddMockData("sample_table", "1.0|test text|27-NOV-2018 08:00") - set errorCode = error(errorMessage, 0) + set errorCode = error(errorMessage, 0) - call cclutAssertVcOperator(CURREF, "test_cclutAddMockData_unmocked_table", trim(errorMessage, 3), + call cclutAssertVcOperator(CURREF, "test_cclutAddMockData_unmocked_table 001", trim(errorMessage, 3), "regexplike", concat("%CCL-E-392-PRG_[0-9]+_[0-9]+\([^)]+\)[0-9]+:[0-9]+\{CCLEXCEPTION\(\)\}Exception\(100\):", - " cclutAddMockData\(\) - tableName has not been mocked. tableName: SAMPLE_TABLE.")) + " cclutValidateMockTableIsDefined\(SAMPLE_TABLE\) - Table has not been mocked.")) end ;test_cclutAddMockData_unmocked_table /* test_cclutAddMockData_uncreated_table ******************************************************************** * Scenario: Throws an error when the tableName specified has not been created through cclutCreateMockTable * ************************************************************************************************************/ subroutine test_cclutAddMockData_uncreated_table(null) - call echo("~~~***~~~***test_cclutAddMockData_uncreated_table***~~~***~~~") - - call cclutDefineMockTable("sample_table", "sample_table_id|sample_table_text|sample_table_date", "f8|vc|dq8") + call cclutDefineMockTable("sample_table", "sample_table_id|sample_table_text|sample_table_date", "f8|vc|dq8") - declare errorMessage = vc with protect, noconstant("") + declare errorMessage = vc with protect, noconstant("") declare errorCode = i4 with protect, noconstant(0) - call cclutAddMockData("sample_table", "1.0|test text|27-NOV-2018 08:00") + call cclutAddMockData("sample_table", "1.0|test text|27-NOV-2018 08:00") - set errorCode = error(errorMessage, 0) + set errorCode = error(errorMessage, 0) - call cclutAssertVcOperator(CURREF, "test_cclutAddMockData_uncreated_table", trim(errorMessage, 3), + call cclutAssertVcOperator(CURREF, "test_cclutAddMockData_uncreated_table 001", trim(errorMessage, 3), "regexplike", concat("%CCL-E-392-PRG_[0-9]+_[0-9]+\([^)]+\)[0-9]+:[0-9]+\{CCLEXCEPTION\(\)\}Exception\(100\):", - " cclutAddMockData\(\) - tableName has not been created. tableName: SAMPLE_TABLE.")) + " cclutValidateMockTableIsCreated\(SAMPLE_TABLE\) - Table has not been created.")) end ;test_cclutAddMockData_uncreated_table /* test_cclutAddMockData_too_many_columns ******************************************************************* * Scenario: Throws an error when there are more columns in the rowData than are defined for the table * ************************************************************************************************************/ subroutine test_cclutAddMockData_too_many_columns(null) - call echo("~~~***~~~***test_cclutAddMockData_too_many_columns***~~~***~~~") - - call cclutDefineMockTable("sample_table", "sample_table_id|sample_table_text|sample_table_date", "f8|vc|dq8") - call cclutCreateMockTable("sample_table") + call cclutDefineMockTable("sample_table", "sample_table_id|sample_table_text|sample_table_date", "f8|vc|dq8") + call cclutCreateMockTable("sample_table") - declare errorMessage = vc with protect, noconstant("") + declare errorMessage = vc with protect, noconstant("") declare errorCode = i4 with protect, noconstant(0) - call cclutAddMockData("sample_table", "1.0|test text|27-NOV-2018 08:00|extra") + call cclutAddMockData("sample_table", "1.0|test text|27-NOV-2018 08:00|extra") - set errorCode = error(errorMessage, 0) + set errorCode = error(errorMessage, 0) - call cclutAssertVcOperator(CURREF, "test_cclutAddMockData_too_many_columns", trim(errorMessage, 3), + call cclutAssertVcOperator(CURREF, "test_cclutAddMockData_too_many_columns 001", trim(errorMessage, 3), "regexplike", concat("%CCL-E-392-PRG_[0-9]+_[0-9]+\([^)]+\)[0-9]+:[0-9]+\{CCLEXCEPTION\(\)\}Exception\(100\):", - " cclutParseColumn\(\) - Too many columns of data added to table. tableName: SAMPLE_TABLE.")) + " cclutConstructDBSetStatement\(SAMPLE_TABLE\) - Too many columns of data added to table.")) end ;test_cclutAddMockData_too_many_columns /* test_cclutAddMockData_too_few_columns ******************************************************************** * Scenario: Throws an error when there are fewer columns in the rowData than are defined for the table * ************************************************************************************************************/ subroutine test_cclutAddMockData_too_few_columns(null) - call echo("~~~***~~~***test_cclutAddMockData_too_few_columns***~~~***~~~") - - call cclutDefineMockTable("sample_table", "sample_table_id|sample_table_text|sample_table_date", "f8|vc|dq8") - call cclutCreateMockTable("sample_table") + call cclutDefineMockTable("sample_table", "sample_table_id|sample_table_text|sample_table_date", "f8|vc|dq8") + call cclutCreateMockTable("sample_table") - declare errorMessage = vc with protect, noconstant("") + declare errorMessage = vc with protect, noconstant("") declare errorCode = i4 with protect, noconstant(0) - call cclutAddMockData("sample_table", "1.0|test text") + call cclutAddMockData("sample_table", "1.0|test text") - set errorCode = error(errorMessage, 0) + set errorCode = error(errorMessage, 0) - call cclutAssertVcOperator(CURREF, "test_cclutAddMockData_too_few_columns", trim(errorMessage, 3), + call cclutAssertVcOperator(CURREF, "test_cclutAddMockData_too_few_columns 001", trim(errorMessage, 3), "regexplike", concat("%CCL-E-392-PRG_[0-9]+_[0-9]+\([^)]+\)[0-9]+:[0-9]+\{CCLEXCEPTION\(\)\}Exception\(100\):", " cclutParseColumn\(\) - Too few columns of data. rowData: 1.0|test text.")) -end ;test_cclutAddMockData_too_many_columns +end ;test_cclutAddMockData_too_few_columns /* test_cclutAddMockData_invalid_escape_sequence ************************************************************ * Scenario: Throws an error when the sequence after the escape character is not valid per the API * ************************************************************************************************************/ subroutine test_cclutAddMockData_invalid_escape_sequence(null) - call echo("~~~***~~~***test_cclutAddMockData_invalid_escape_sequence***~~~***~~~") - - call cclutDefineMockTable("sample_table", "sample_table_id|sample_table_text|sample_table_date", "f8|vc|dq8") - call cclutCreateMockTable("sample_table") + call cclutDefineMockTable("sample_table", "sample_table_id|sample_table_text|sample_table_date", "f8|vc|dq8") + call cclutCreateMockTable("sample_table") - declare errorMessage = vc with protect, noconstant("") + declare errorMessage = vc with protect, noconstant("") declare errorCode = i4 with protect, noconstant(0) - call cclutAddMockData("sample_table", "1.0|\a|27-NOV-2018 08:00") + call cclutAddMockData("sample_table", "1.0|\a|27-NOV-2018 08:00") - set errorCode = error(errorMessage, 0) + set errorCode = error(errorMessage, 0) - call cclutAssertVcOperator(CURREF, "test_cclutAddMockData_invalid_escape_sequence", trim(errorMessage, 3), + call cclutAssertVcOperator(CURREF, "test_cclutAddMockData_invalid_escape_sequence 001", trim(errorMessage, 3), "regexplike", concat("%CCL-E-392-PRG_[0-9]+_[0-9]+\([^)]+\)[0-9]+:[0-9]+\{CCLEXCEPTION\(\)\}Exception\(100\):", " cclutAddMockData\(\) - Invalid escape sequence. rowData: 1.0|\a|27-NOV-2018 08:00.")) end ;test_cclutAddMockData_invalid_escape_sequence @@ -1338,18 +1382,16 @@ end ;test_cclutAddMockData_invalid_escape_sequence * Scenario: Throws an error if the null escape sequence is not by itself in a column * ************************************************************************************************************/ subroutine test_cclutAddMockData_invalid_null(null) - call echo("~~~***~~~***test_cclutAddMockData_invalid_null***~~~***~~~") - - call cclutDefineMockTable("sample_table", "sample_table_id|sample_table_text|sample_table_date", "f8|vc|dq8") - call cclutCreateMockTable("sample_table") + call cclutDefineMockTable("sample_table", "sample_table_id|sample_table_text|sample_table_date", "f8|vc|dq8") + call cclutCreateMockTable("sample_table") - declare errorMessage = vc with protect, noconstant("") + declare errorMessage = vc with protect, noconstant("") declare errorCode = i4 with protect, noconstant(0) - call cclutAddMockData("sample_table", "1.0|\nulla|27-NOV-2018 08:00") + call cclutAddMockData("sample_table", "1.0|\nulla|27-NOV-2018 08:00") - set errorCode = error(errorMessage, 0) + set errorCode = error(errorMessage, 0) - call cclutAssertVcOperator(CURREF, "test_cclutAddMockData_invalid_null", trim(errorMessage, 3), + call cclutAssertVcOperator(CURREF, "test_cclutAddMockData_invalid_null 001", trim(errorMessage, 3), "regexplike", concat("%CCL-E-392-PRG_[0-9]+_[0-9]+\([^)]+\)[0-9]+:[0-9]+\{CCLEXCEPTION\(\)\}Exception\(100\):", " cclutAddMockData\(\) - \null column must have no other characters.", " rowData: 1.0|\nulla|27-NOV-2018 08:00.")) @@ -1362,8 +1404,6 @@ end ;test_cclutAddMockData_invalid_null * Scenario: Clears all data from the mock table but does not drop the table (essentially a truncate) * ************************************************************************************************************/ subroutine test_cclutClearMockData_happy(null) - call echo("~~~***~~~***test_cclutClearMockData_happy***~~~***~~~") - declare mockTable = vc with protect, noconstant("") set mockTable = cclutDefineMockTable("sample_table", "sample_table_id|sample_table_text|sample_table_date", "f8|vc|dq8") @@ -1381,7 +1421,7 @@ subroutine test_cclutClearMockData_happy(null) tableCount = totalCount with nocounter - call cclutAsserti4Equal(CURREF, "test_cclutClearMockData_happy", tableCount, 3) + call cclutAsserti4Equal(CURREF, "test_cclutClearMockData_happy 001", tableCount, 3) call cclutClearMockData("sample_table") @@ -1392,58 +1432,52 @@ subroutine test_cclutClearMockData_happy(null) tableCount = totalCount with nocounter - call cclutAsserti4Equal(CURREF, "test_cclutClearMockData_happy", tableCount, 0) + call cclutAsserti4Equal(CURREF, "test_cclutClearMockData_happy 002", tableCount, 0) end ;test_cclutClearMockData_happy /* test_cclutClearMockData_missing_tableName **************************************************************** * Scenario: Throws an error when an empty tableName is supplied to the function (after trimming) * ************************************************************************************************************/ subroutine test_cclutClearMockData_missing_tableName(null) - call echo("~~~***~~~***test_cclutClearMockData_missing_tableName***~~~***~~~") - - declare errorMessage = vc with protect, noconstant("") + declare errorMessage = vc with protect, noconstant("") declare errorCode = i4 with protect, noconstant(0) - call cclutClearMockData(" ") + call cclutClearMockData(" ") - set errorCode = error(errorMessage, 0) + set errorCode = error(errorMessage, 0) - call cclutAssertVcOperator(CURREF, "test_cclutClearMockData_missing_tableName", trim(errorMessage, 3), + call cclutAssertVcOperator(CURREF, "test_cclutClearMockData_missing_tableName 001", trim(errorMessage, 3), "regexplike", concat("%CCL-E-392-PRG_[0-9]+_[0-9]+\([^)]+\)[0-9]+:[0-9]+\{CCLEXCEPTION\(\)\}Exception\(100\):", - " cclutClearMockData\(\) - tableName is a required field.")) + " cclutValidateParameterIsNotEmpty\(\) - tableName is a required field.")) end ;test_cclutClearMockData_missing_tableName /* test_cclutClearMockData_unmocked_table ******************************************************************* * Scenario: Throws an error when the tableName specified has not been mocked through cclutDefineMockTable * ************************************************************************************************************/ subroutine test_cclutClearMockData_unmocked_table(null) - call echo("~~~***~~~***test_cclutClearMockData_unmocked_table***~~~***~~~") - - declare errorMessage = vc with protect, noconstant("") + declare errorMessage = vc with protect, noconstant("") declare errorCode = i4 with protect, noconstant(0) - call cclutClearMockData("sample_table") + call cclutClearMockData("sample_table") - set errorCode = error(errorMessage, 0) + set errorCode = error(errorMessage, 0) - call cclutAssertVcOperator(CURREF, "test_cclutClearMockData_unmocked_table", trim(errorMessage, 3), + call cclutAssertVcOperator(CURREF, "test_cclutClearMockData_unmocked_table 001", trim(errorMessage, 3), "regexplike", concat("%CCL-E-392-PRG_[0-9]+_[0-9]+\([^)]+\)[0-9]+:[0-9]+\{CCLEXCEPTION\(\)\}Exception\(100\):", - " cclutClearMockData\(\) - tableName has not been mocked. tableName: SAMPLE_TABLE.")) + " cclutValidateMockTableIsDefined\(SAMPLE_TABLE\) - Table has not been mocked.")) end ;test_cclutClearMockData_unmocked_table /* test_cclutClearMockData_uncreated_table ****************************************************************** * Scenario: Throws an error when the tableName specified has not been created through cclutCreateMockTable * ************************************************************************************************************/ subroutine test_cclutClearMockData_uncreated_table(null) - call echo("~~~***~~~***test_cclutClearMockData_uncreated_table***~~~***~~~") - - call cclutDefineMockTable("sample_table", "sample_table_id|sample_table_text|sample_table_date", "f8|vc|dq8") + call cclutDefineMockTable("sample_table", "sample_table_id|sample_table_text|sample_table_date", "f8|vc|dq8") - declare errorMessage = vc with protect, noconstant("") + declare errorMessage = vc with protect, noconstant("") declare errorCode = i4 with protect, noconstant(0) - call cclutClearMockData("sample_table") + call cclutClearMockData("sample_table") - set errorCode = error(errorMessage, 0) + set errorCode = error(errorMessage, 0) - call cclutAssertVcOperator(CURREF, "test_cclutClearMockData_uncreated_table", trim(errorMessage, 3), + call cclutAssertVcOperator(CURREF, "test_cclutClearMockData_uncreated_table 001", trim(errorMessage, 3), "regexplike", concat("%CCL-E-392-PRG_[0-9]+_[0-9]+\([^)]+\)[0-9]+:[0-9]+\{CCLEXCEPTION\(\)\}Exception\(100\):", - " cclutClearMockData\(\) - tableName has not been created. tableName: SAMPLE_TABLE.")) -end ;test_cclutClearMockData_uncreated_table \ No newline at end of file + " cclutValidateMockTableIsCreated\(SAMPLE_TABLE\) - Table has not been created.")) +end ;test_cclutClearMockData_uncreated_table diff --git a/cclunit-framework-source/src/test/ccl/ut_cclut_utils.inc b/cclunit-framework-source/src/test/ccl/ut_cclut_utils.inc new file mode 100644 index 0000000..cec2fc6 --- /dev/null +++ b/cclunit-framework-source/src/test/ccl/ut_cclut_utils.inc @@ -0,0 +1,32 @@ +declare setup(dummyVar = i2) = null +declare tearDown(dummyVar = i2) = null + +subroutine tearDown(dummyVar) + rollback +end ;tearDown + +;********************************************************************************************************************************** +;** cclutIsEmpty +;********************************************************************************************************************************** +/* test_cclutIsEmpty_true *********************************************************************************** +* Scenario: Validates that TRUE is returned whenever the string is empty or only has whitespace characters * +************************************************************************************************************/ +subroutine test_cclutIsEmpty_true(null) + call cclutAsserti4Equal(CURREF, "test_cclutIsEmpty_true 001", cclut::cclutIsEmpty(""), TRUE) + call cclutAsserti4Equal(CURREF, "test_cclutIsEmpty_true 002", cclut::cclutIsEmpty(" "), TRUE) + call cclutAsserti4Equal(CURREF, "test_cclutIsEmpty_true 003", + cclut::cclutIsEmpty(concat(char(10), char(20), char(30))), TRUE) +end ;test_cclutIsEmpty_true + +;********************************************************************************************************************************** +;** cclutIsEmpty +;********************************************************************************************************************************** +/* test_cclutIsEmpty_false ********************************************************************************** +* Scenario: Validates that FALSE is returned whenever the string has non-whitespace characters * +************************************************************************************************************/ +subroutine test_cclutIsEmpty_false(null) + call cclutAsserti4Equal(CURREF, "test_cclutIsEmpty_false 001", cclut::cclutIsEmpty("aaaaa"), FALSE) + call cclutAsserti4Equal(CURREF, "test_cclutIsEmpty_false 002", cclut::cclutIsEmpty(" aaaaa "), FALSE) + call cclutAsserti4Equal(CURREF, "test_cclutIsEmpty_false 003", + cclut::cclutIsEmpty(concat(char(10), "aaaaa", char(30))), FALSE) +end ;test_cclutIsEmpty_false diff --git a/cclunit-framework-tests/src/test/resources/META-INF/spring/applicationContext-cclutTests.xml b/cclunit-framework-tests/src/test/resources/META-INF/spring/applicationContext-cclutTests.xml index 88b714a..8736b39 100644 --- a/cclunit-framework-tests/src/test/resources/META-INF/spring/applicationContext-cclutTests.xml +++ b/cclunit-framework-tests/src/test/resources/META-INF/spring/applicationContext-cclutTests.xml @@ -8,7 +8,7 @@ http://www.springframework.org/schema/context http://www.springframework.org/sch - + @@ -20,7 +20,7 @@ http://www.springframework.org/schema/context http://www.springframework.org/sch - + @@ -32,7 +32,7 @@ http://www.springframework.org/schema/context http://www.springframework.org/sch - + From c94684cd37268257484a04c69a912cc5de84e780 Mon Sep 17 00:00:00 2001 From: cernertrevor Date: Fri, 1 Feb 2019 08:19:34 -0600 Subject: [PATCH 3/7] Second batch of changes based on code review comments. --- cclunit-framework-source/doc/CCLUTGUIDANCE.md | 328 +----------------- cclunit-framework-source/doc/CCLUTMOCKING.md | 22 +- .../doc/examples/basic_example.inc | 69 ++++ .../doc/examples/mocking_api.inc | 70 ++++ .../doc/examples/using_namespaces.inc | 13 + .../doc/examples/validation_subroutine.inc | 47 +++ .../src/main/ccl/cclut_ff.prg | 2 + .../resources/cclut_execute_test_logic.inc | 1 + .../main/resources/cclut_test_runner_end.inc | 3 + ...cclut_execute_program_with_mocks_happy.prg | 3 + .../test/ccl/ut_cclut_execute_test_case.inc | 35 ++ .../ccl/ut_cclut_execute_test_case_file.inc | 37 +- .../src/test/ccl/ut_cclut_ff.inc | 30 ++ .../src/test/ccl/ut_cclut_mock.inc | 84 +++-- .../test/ccl/ut_cclut_mock_carry_forward.inc | 46 +++ ...t_cclut_mock_table_misbehaving_cleanup.inc | 75 ++++ 16 files changed, 517 insertions(+), 348 deletions(-) create mode 100644 cclunit-framework-source/doc/examples/basic_example.inc create mode 100644 cclunit-framework-source/doc/examples/mocking_api.inc create mode 100644 cclunit-framework-source/doc/examples/using_namespaces.inc create mode 100644 cclunit-framework-source/doc/examples/validation_subroutine.inc create mode 100644 cclunit-framework-source/src/test/ccl/ut_cclut_mock_carry_forward.inc create mode 100644 cclunit-framework-source/src/test/ccl/ut_cclut_mock_table_misbehaving_cleanup.inc diff --git a/cclunit-framework-source/doc/CCLUTGUIDANCE.md b/cclunit-framework-source/doc/CCLUTGUIDANCE.md index 5ef0133..5cef4be 100644 --- a/cclunit-framework-source/doc/CCLUTGUIDANCE.md +++ b/cclunit-framework-source/doc/CCLUTGUIDANCE.md @@ -2,337 +2,35 @@ ## Building Unit Tests -Before there can be unit testing, there must be units. The ultimate goal is to have small, testable, modular units and to test each of them individually. The goal of this guidance is to describe a way to structure a CCL script that supports testing its units individually. It will not discuss how to create units or unit testable code as there are many other sources that go into that detail. +Before there can be unit testing, there must be units. The ultimate goal is to have small, testable, modular units and to test each of them individually. The goal of this guidance is to describe a way to structure a CCL script that supports testing its units individually. It will not discuss how to create units as there are many other sources that go into that detail. -Say our CCL script contains a testable unit "functionX" that we want to test in some particular scenario, "scenarioY". Then we will create and execute a unit test named something like "testFunctionXForScenarioY". We want our test to execute functionX and the descendants of functionX. We do not want it to execute any other functions in our script. Here is how to go about it. +Suppose the body of the script under test has been decomposed into a series of calls to testable subroutines (e.g. "call subroutineA(null)", "call subroutineB(null)", etc.). -First off, namespace every subroutine with the PUBLIC namespace. Then put all (most all) of the executable code for the script into a main function, say public::main(null) = null -Use a unique namespace to define an override for the main subroutine within the test suite, say testFunctionXForScenarioY::main(null) = null, and have the override first set up the conditions for scenarioY and then have it call functionX directly. +First off, enclose the body of the script under test in a separate subroutine, say "main(null)". Next, namespace every subroutine declaration/implementation with the PUBLIC namespace. -The key point here is that the script does not contain a lot of loose code that gets executed every time the script executes. It all gets bundled into the main subroutine which is what allows a unit test to dictate exactly how much of the script's code will be executed. - -Here is an illustration of the concept: -``` -;; this is the test -;;; testFunctionB::main is the workhorse. It will be called instead of public::main because of the curnamespace - -/** -* Confirms that functionB returns "functionBTest" when it is passed "Test" -* and "functionBSubroutine" when it is passed "Subroutine". -*/ -subroutine (testFunctionB(null) = null) - - execute the_script:dba with curnamespace = "testFunctionB" - -end - -subroutine (testFunctionB::main(null) = null) - declare b_string = vc with protect, noconstant("") - - set b_string = functionB("Test") - set stat = cclutAssertVCEquals(CURREF, "testFunctionB Test", b_string, "functionBTest") +Let's say we want to test subroutineB in isolation. Then we will create and execute a unit test named something like "testSubroutineBForScenarioX". We want our test to execute subroutineB and the descendants of subroutineB. We do not want it to execute any other functions in our script. Here is how to go about it. - set b_string = functionB("Subroutine") - set stat = cclutAssertVCEquals(CURREF, "testFunctionB Subroutine", b_string, "functionBSubroutine") -end;;;testFunctionB - -;; this is the script to be tested - -drop program the_script:dba go -create program the_script:dba - - record reply ( -%i cclsource:status_block.inc - ) - - subroutine (PUBLIC::functionA(id = f8) = vc) - call echo("functionA") - ;;; do stuff - return("functionA") - end - - subroutine (PUBLIC::functionB(name = vc) = vc) - call echo("functionB") - ;;; do stuff - return(concat("functionB", name)) - end - - subroutine (PUBLIC::functionC(null) = null) - call echo("functionC") - ;;; do stuff - call functionD(null) - end - - subroutine (PUBLIC::functionD(null) = null) - call echo("functionD") - end +Use a unique name to define an override for the main subroutine within the test suite, say mainForSubroutineBForScenarioX(null) = null, and have the override first set up the conditions for scenarioX and then have it call subroutineB directly. Note that the main function also deserves to be tested with all of the functions it calls mocked to ensure that the real implementation for main behaves correctly. - ;;; observe that subroutine main deserves to be tested in its own right with all other functions mocked. - subroutine(PUBLIC::main(null) = null) - declare a_string = vc with protect, noconstant("") - declare b_string = vc with protect, noconstant("") - set a_string = functionA(1.0) - set b_string = functionB(a_string) - call functionC(null) - end - - call main(null) - -#exit_script - ;; script finalizer code can go here - ;; a PUBLIC::exitScript(null) subroutine that encapsulates this work could be created and called - ;; if it does something that should occur for some unit tests. -end go - -``` - -Be careful! There is a small problem if you structure all of your scripts using this pattern and you test a function in one script that calls another script that isn't mocked by your test. Try the following example to understand what can go wrong: - -``` -drop program callstackA go -create program callstackA -subroutine (public::main(null) = null with private) - call echo("callstackA's main") -end - call main(null) - execute callstackB -end go - -drop program callstackB go -create program callstackB -subroutine (public::main(null) = null with private) - call echo("callstackB's main") -end - call main(null) - execute callstackC -end go - -drop program callstackC go -create program callstackC -subroutine (public::main(null) = null with private) - call echo("callstackC's main") -end - call main(null) -end go - -drop program callstack go -create program callstack - subroutine (callstack::main(null) = null with protect) - call echo("callstack's main") - end - - execute callstackA with curnamespace = 'callstack' -end go -``` - -If you execute callstackA directly, each program calls the correct main function. That's because each program gravitates to the copy of main that is in the closest scope, i.e., the one it declared for itself. - -If you execute call stack, each program calls the override. That is because when the namespace is forced, there is only one copy of callstack::main to choose from and since the forced namespace propagates to descendants, all the programs are forced to chose it. - -There are many ways to circumvent it. One is to always mock any descendant programs. Another is to use unique function names rather than generic ones. The script script_X could name its main function public::script_x_main, for example. Since script names are limited to 32 characters and subroutine names can be resolved to at least 40 characters, this will work, but another option still is to use "with replace". An example can be seen below: - -``` -drop program callstackA go -create program callstackA -subroutine (public::main(null) = null with private) - call echo("callstackA's main") -end - call main(null) - execute callstackB -end go - -drop program callstackB go -create program callstackB -subroutine (public::main(null) = null with private) - call echo("callstackB's main") -end - call main(null) - execute callstackC -end go - -drop program callstackC go -create program callstackC -subroutine (public::main(null) = null with private) - call echo("callstackC's main") -end - call main(null) -end go - -drop program callstack go -create program callstack - subroutine (public::callstackmain(null) = null with protect) - call echo("callstack's main") - end - - execute callstackA with replace("MAIN", callstackmain) -end go -``` +The key point here is that the script does not contain a lot of loose code that gets executed every time the script executes. It all gets bundled into the main subroutine which is what allows a unit test to dictate exactly how much of the script's code will be executed. -This works because "with replace" does not propagate to descendant scripts by default (though an option is available to do so). Additionally, the CCL Unit Testing framework contains a mocking API that abstracts the "with replace" logic. See the documentation for cclutAddMockImplementation at [CCLUTMOCKING.md](../CCLUTMOCKING.md) +An illustration of the concept can be seen [here](./examples/basic_example.inc) ## CCL Mocks -In general, there are two ways to mock objects in CCL unit tests: - -1. Use "with replace" -2. Use "with curnamespace" - - 2a. Add the PUBLIC namespace to the real thing. Use an alternate namespace to define an override. Execute the script using 'with curnamespace = "\"' +In general, there are two ways to mock objects in CCL unit tests. Generally speaking, use "with replace" to mock things that are defined outside the script or called directly by the script (CCL subroutines, UARs, other scripts), and use "with curnamespace" to mock subroutines executed by the subroutine being tested. When using "with curnamespace", add the PUBLIC namespace to the real thing and use an alternate namespace to define an override. Execute the script using 'with curnamespace = "\"'. In practice, it is convenient to use the name of the test case for the alternate namespace. - 2b. In practice, it is convenient to use the name of the test case for the alternate namespace. - -Generally speaking, use "with replace" to mock things that are defined outside the script (CCL subroutines, UARs, other scripts), and use "with curnamespace" to mock things defined within the script. - -The CCL Unit Testing framework also supports an abstraction for creating mocks. The purpose is to help make it easier to define mock tables and other mock objects to be used when executing a script. Details on the API can be found at [CCLUTMOCKING.md](../CCLUTMOCKING.md) +The CCL Unit Testing framework provides an abstraction for creating mocks. The purpose is to help make it easier to define mock tables and other mock objects to be used when executing a script. Details on the API can be found at [CCLUTMOCKING.md](../CCLUTMOCKING.md) -Below are some examples using the CCL Unit Testing framework's mocking API. These examples assume the script under test is called "the_script" and executes a program called "other_script". They test for scenarios where other_script returns 0 items, more than 5 items, and a failed ("F") status. - -``` -;;; put the following script definition in a .prg file in src/test/ccl - - -drop program mock_other_script go -create program mock_other_script - free record reply - set stat = copyrec(mock_other_script_reply, reply, 1) -end go - -;;; put the following functions in a test suite (.inc) in src/test/ccl - -/** -* Test myFunction when other_script returns zero items -*/ -subroutine (testMyFunctionOtherScriptZero(null) = null) - record mock_other_script_reply ( - 1 qual [*] - 2 id = f8 -%i cclsource:status_block.inc - ) with protect - - set mock_other_script_reply->status_data->status = "Z" - - call cclutAddMockImplementation("OTHER_SCRIPT", "mock_other_script") - call cclutExecuteProgramWithMocks("the_script", "") - - ;assert things here -end ;;;testMyFunctionZero - -/** -* Test myFunction when other_script returns more than five items -*/ -subroutine (testMyFunctionOtherScriptMoreThanTen(null) = null) - record mock_other_script_reply ( - 1 qual [*] - 2 id = f8 -%i cclsource:status_block.inc - ) with protect - - set mock_other_script_reply->status_data->status = "S" - set stat = alterlist(mock_other_script_reply->qual, 6) - - declare idx = i4 with protect, noconstant(0) - for (idx = 1 to 6) - set mock_other_script_reply->qual[idx].id = idx - endfor - - call cclutAddMockImplementation("OTHER_SCRIPT", "mock_other_script") - call cclutExecuteProgramWithMocks("the_script", "") - - ;assert things here -end ;;;testMyFunctionMoreThanTen - -/** -* Test myFunction when other_script fails -*/ -subroutine (testMyFunctionOtherScriptFail(null) = null) - record mock_other_script_reply ( - 1 qual [*] - 2 id = f8 -%i cclsource:status_block.inc - ) with protect - - set mock_other_script_reply->status_data->status = "F" - - call cclutAddMockImplementation("OTHER_SCRIPT", "mock_other_script") - call cclutExecuteProgramWithMocks("the_script", "") - - ;assert things here -end ;;;testMyFunctionOtherScriptFail -``` +[These examples](./examples/mocking_api.inc) demonstrates the CCL Unit Testing framework's mocking API. They assume the script under test is called "the_script" and executes a program called "other_script". They test for scenarios where other_script returns 0 items, more than 5 items, and a failed ("F") status. There are other variations on this. For example, you could put asserts within mock_other_script itself. Additionally, other_script might generate its own reply structure, so you would want to do the same in mock_other_script. -Below is an example where the mock script calls a validation subroutine defined from the testing subroutine. It tests that other_script is called exactly 3 times with the correct parameters each time. - -``` -;;; here is the script - -drop program the_script go -create program the_script - execute other_script 4, 5 - execute other_script 3, 2 - execute other_script 0, 1 -end go - - -;;; put this definition in a .prg file in src/test/ccl - -drop program mock_other_script go -create program mock_other_script - prompt "param 1", "param 2" with param1, param2 - - set otherScriptCallCount = otherScriptCallCount + 1 - call validateOtherScriptParams($param1, $param2) -end go - -;;; put this functions in a test suite (.inc) in src/test/ccl - -/** -* confirms that the script executes other_script exactly three times passing in (4, 5) then (3, 2) then (0, 1) -*/ -subroutine (testOtherScriptCalledThreeTimes(null) = null) - declare otherScriptCallCount = i4 with protect, noconstant(0) - - call cclutAddMockImplementation("OTHER_SCRIPT", "mock_other_script") - call cclutExecuteProgramWithMocks("the_script", "") - - set stat = cclutAssertI4Equal(CURREF, "testMyFunction_6_9 a", otherScriptCallCount, 3) -end ;;;testMyFunctionZero - -subroutine (validateOtherScriptParams(p1 = i4, p2 = i4) = null) - case (otherScriptCallCount) - of 1: - set stat = cclutAssertI4Equal(CURREF, "validateOtherScriptParams 1 a", p1, 4) - set stat = cclutAssertI4Equal(CURREF, "validateOtherScriptParams 1 b", p2, 5) - of 2: - set stat = cclutAssertI4Equal(CURREF, "validateOtherScriptParams 2 a", p1, 3) - set stat = cclutAssertI4Equal(CURREF, "validateOtherScriptParams 2 b", p2, 2) - of 3: - set stat = cclutAssertI4Equal(CURREF, "validateOtherScriptParams 3 a", p1, 0) - set stat = cclutAssertI4Equal(CURREF, "validateOtherScriptParams 3 b", p2, 1) - endcase -end ;;;validateOtherScriptParams -``` - -Finally, a namespace example where getPersonName will always return the same value. +[Here](./examples/validation_subroutine.inc) is an example where the mock script calls a validation subroutine defined from the testing subroutine. It tests that other_script is called exactly 3 times with the correct parameters each time. -``` -/** -* Executes a test knowing that every call to getPersonName(id) will return "Bob Marley". -*/ -subroutine (testGetNameReturnsBobMarley(null) = null) - declare otherScriptCallCount = i4 with protect, noconstant(0) - - call cclutExecuteProgramWithMocks("the_script", "", "testGetNameReturnsBobMarley") - - ; assert stuff here -end -subroutine (testGetNameReturnsBobMarley::getPersonName(id = f8) = vc) - return ("Bob Marley") -end ;;;testGetNameReturnsBobMarley -``` +Finally, a [namespace example](./examples/using_namespaces.inc) where getPersonName will always return the same value. ## Commit/Rollback Guidance -"commit" and "rollback" are keywords within CCL that apply the respective commands to the RDBMS. This can be particularly annoying when dealing with real tables, especially if one is testing insert/update/delete functionality. The table mocking API helps mitigate this by using separate custom tables, but it may still be advantageous to separate any usages of commit/rollback into their own subroutines and test them independently of the other tests. +"commit" and "rollback" are keywords within CCL that apply the respective commands to the RDBMS. This can be particularly annoying when dealing with real tables, especially if one is testing insert/update/delete functionality. The table mocking API helps mitigate this by using separate custom tables, but it may still be advantageous to separate any usages of commit/rollback into their own subroutines which can be mocked with no-op subroutines. diff --git a/cclunit-framework-source/doc/CCLUTMOCKING.md b/cclunit-framework-source/doc/CCLUTMOCKING.md index 5b1624c..abfde8b 100644 --- a/cclunit-framework-source/doc/CCLUTMOCKING.md +++ b/cclunit-framework-source/doc/CCLUTMOCKING.md @@ -171,15 +171,27 @@ call cclutRemoveAllMocks(null) 2. cclutRemoveAllMocks should be called as part of the teardown for all tests. The framework will attempt to clean up any outstanding mocks, but it is good practice to explicitly remove any mocks to ensure that no mocked tables remain in the Oracle instance. -3. Tables can be mocked even if the table does not exist in the domain where the test is run. The mocked version will be used when executing programs with executeProgramWithMocks. This can be useful to test tables that do not formally exist yet. +3. Namespaces are not supported when using cclutAddMockImplementation. An example of this would be: -4. The mocked items created through cclutCreateMockTable() and cclutAddMockImplementation will not be applied to child scripts called from the script-under-test. Some alternatives would be to mock the child script to return the appropriate data or to mock the child script to execute the real script applying the mocked tables and implementations. + ``` + call cclutAddMockImplementation("public::testSubroutine", "myNamespace::mockSubroutine") + ``` -5. The mocked items created through cclutCreateMockTable() and cclutAddMockImplementation will not be applied to statements executed through "call parser()" commands. One alternative would be to separate the parser string generation into separate subroutines and mock the subroutines to return parser strings using the mocked entity names. Another alternative would be to mock the parser() call to validate the correct information is supplied, then perform the appropriate mock versions of the actions the statement would normally perform. + Alternatives will depend on the specifics of the script-under-test, but one alternative for the example above would be to define the mock implementation under the namespace that the program uses (i.e. public::mockSubroutine) and exclude the namespaces when adding the mock: + + ``` + call cclutAddMockImplementation("testSubroutine", "mockSubroutine") + ``` -6. The table mocking APIs are not supported when called from within a reportwriter section. It might be tempting to use a dummyt query to set up mock data from a record structure, but various mocking calls such as cclutCreateMockTable, cclutRemoveMockTable and cclutAddMockData cannot be executed within the context of a query (because the implementations execute queries). Use a for loop instead. +4. Tables can be mocked even if the table does not exist in the domain where the test is run. The mocked version will be used when executing programs with executeProgramWithMocks. This can be useful to test tables that do not formally exist yet. + +5. The mocked items created through cclutCreateMockTable() and cclutAddMockImplementation will not be applied to child scripts called from the script-under-test. Some alternatives would be to mock the child script to return the appropriate data or to mock the child script to execute the real script applying the mocked tables and implementations. + +6. The mocked items created through cclutCreateMockTable() and cclutAddMockImplementation will not be applied to statements executed through "call parser()" commands. One alternative would be to separate the parser string generation into separate subroutines and mock the subroutines to return parser strings using the mocked entity names. Another alternative would be to mock the parser() call to validate the correct information is supplied, then perform the appropriate mock versions of the actions the statement would normally perform. + +7. The table mocking APIs are not supported when called from within a reportwriter section. It might be tempting to use a dummyt query to set up mock data from a record structure, but various mocking calls such as cclutCreateMockTable, cclutRemoveMockTable and cclutAddMockData cannot be executed within the context of a query (because the implementations execute queries). Use a for loop instead. -7. Mocking the tdbexecute "reply_to" entity is unsupported under certain conditions, specifically if a call to free the "reply_to" entity is made just prior to calling tdbexecute. If the scenario is truly necessary for a test, the best alternative is to define and use a subroutine for freeing the "reply_to" entity within the script and use a mock for that subroutine which does not actually perform the freeing of the "reply_to" entity. +8. Mocking the tdbexecute "reply_to" entity is unsupported under certain conditions, specifically if a call to free the "reply_to" entity is made just prior to calling tdbexecute. If the scenario is truly necessary for a test, the best alternative is to define and use a subroutine for freeing the "reply_to" entity within the script and use a mock for that subroutine which does not actually perform the freeing of the "reply_to" entity. ## Example Below is an example of some of the APIs available in the CCL Unit Mocking framework along with some simple notes. diff --git a/cclunit-framework-source/doc/examples/basic_example.inc b/cclunit-framework-source/doc/examples/basic_example.inc new file mode 100644 index 0000000..edaf178 --- /dev/null +++ b/cclunit-framework-source/doc/examples/basic_example.inc @@ -0,0 +1,69 @@ +;; this is the test +;;; public::mainForSubroutineB is the workhorse. It will be called instead of public::main because of "with replace" + +/** +* Confirms that subroutineB returns "subroutineBTest" when it is passed "Test" +* and "subroutineBSubroutine" when it is passed "Subroutine". +*/ +subroutine (testSubroutineB(null) = null) + + execute the_script:dba with replace("MAIN", MAINFORSUBROUTINEB) + +end + +subroutine (public::mainForSubroutineB(null) = null) + declare b_string = vc with protect, noconstant("") + + set b_string = subroutineB("Test") + set stat = cclutAssertVCEqual(CURREF, "testSubroutineB Test", b_string, "subroutineBTest") + + set b_string = subroutineB("Subroutine") + set stat = cclutAssertVCEqual(CURREF, "testSubroutineB Subroutine", b_string, "subroutineBSubroutine") +end;;;mainForSubroutineB + +;; this is the script to be tested + +drop program the_script:dba go +create program the_script:dba + + record reply ( +%i cclsource:status_block.inc + ) + + subroutine (PUBLIC::subroutineA(id = f8) = vc) + call echo("subroutineA") + ;;; do stuff + return("subroutineA") + end + + subroutine (PUBLIC::subroutineB(name = vc) = vc) + call echo("subroutineB") + ;;; do stuff + return(concat("subroutineB", name)) + end + + subroutine (PUBLIC::subroutineC(null) = null) + call echo("subroutineC") + ;;; do stuff + call subroutineD(null) + end + + subroutine (PUBLIC::subroutineD(null) = null) + call echo("subroutineD") + end + + subroutine(PUBLIC::main(null) = null) + declare a_string = vc with protect, noconstant("") + declare b_string = vc with protect, noconstant("") + set a_string = subroutineA(1.0) + set b_string = subroutineB(a_string) + call subroutineC(null) + end + + call main(null) + +#exit_script + ;; script finalizer code can go here + ;; a PUBLIC::exitScript(null) subroutine that encapsulates this work could be created and called + ;; if it does something that should occur for some unit tests. +end go diff --git a/cclunit-framework-source/doc/examples/mocking_api.inc b/cclunit-framework-source/doc/examples/mocking_api.inc new file mode 100644 index 0000000..fd50b3c --- /dev/null +++ b/cclunit-framework-source/doc/examples/mocking_api.inc @@ -0,0 +1,70 @@ +;;; put the following script definition in a .prg file and compile it + + +drop program mock_other_script go +create program mock_other_script + free record reply + set stat = copyrec(mock_other_script_reply, reply, 1) +end go + +;;; put the following functions in a test case (.inc) + +/** +* Test myFunction when other_script returns zero items +*/ +subroutine (testMyFunctionOtherScriptZero(null) = null) + record mock_other_script_reply ( + 1 qual [*] + 2 id = f8 +%i cclsource:status_block.inc + ) with protect + + set mock_other_script_reply->status_data->status = "Z" + + call cclutAddMockImplementation("OTHER_SCRIPT", "mock_other_script") + call cclutExecuteProgramWithMocks("the_script", "") + + ;assert things here +end ;;;testMyFunctionZero + +/** +* Test myFunction when other_script returns more than five items +*/ +subroutine (testMyFunctionOtherScriptMoreThanTen(null) = null) + record mock_other_script_reply ( + 1 qual [*] + 2 id = f8 +%i cclsource:status_block.inc + ) with protect + + set mock_other_script_reply->status_data->status = "S" + set stat = alterlist(mock_other_script_reply->qual, 6) + + declare idx = i4 with protect, noconstant(0) + for (idx = 1 to 6) + set mock_other_script_reply->qual[idx].id = idx + endfor + + call cclutAddMockImplementation("OTHER_SCRIPT", "mock_other_script") + call cclutExecuteProgramWithMocks("the_script", "") + + ;assert things here +end ;;;testMyFunctionMoreThanTen + +/** +* Test myFunction when other_script fails +*/ +subroutine (testMyFunctionOtherScriptFail(null) = null) + record mock_other_script_reply ( + 1 qual [*] + 2 id = f8 +%i cclsource:status_block.inc + ) with protect + + set mock_other_script_reply->status_data->status = "F" + + call cclutAddMockImplementation("OTHER_SCRIPT", "mock_other_script") + call cclutExecuteProgramWithMocks("the_script", "") + + ;assert things here +end ;;;testMyFunctionOtherScriptFail diff --git a/cclunit-framework-source/doc/examples/using_namespaces.inc b/cclunit-framework-source/doc/examples/using_namespaces.inc new file mode 100644 index 0000000..a6c614f --- /dev/null +++ b/cclunit-framework-source/doc/examples/using_namespaces.inc @@ -0,0 +1,13 @@ +/** +* Executes a test knowing that every call to getPersonName(id) will return "Bob Marley". +*/ +subroutine (testGetNameReturnsBobMarley(null) = null) + declare otherScriptCallCount = i4 with protect, noconstant(0) + + call cclutExecuteProgramWithMocks("the_script", "", "testGetNameReturnsBobMarley") + + ; assert stuff here +end +subroutine (testGetNameReturnsBobMarley::getPersonName(id = f8) = vc) + return ("Bob Marley") +end ;;;testGetNameReturnsBobMarley diff --git a/cclunit-framework-source/doc/examples/validation_subroutine.inc b/cclunit-framework-source/doc/examples/validation_subroutine.inc new file mode 100644 index 0000000..176e8db --- /dev/null +++ b/cclunit-framework-source/doc/examples/validation_subroutine.inc @@ -0,0 +1,47 @@ +;;; here is the script + +drop program the_script go +create program the_script + execute other_script 4, 5 + execute other_script 3, 2 + execute other_script 0, 1 +end go + + +;;; put this definition in a .prg file and compile it + +drop program mock_other_script go +create program mock_other_script + prompt "param 1", "param 2" with param1, param2 + + set otherScriptCallCount = otherScriptCallCount + 1 + call validateOtherScriptParams($param1, $param2) +end go + +;;; put this functions in a test case (.inc) + +/** +* confirms that the script executes other_script exactly three times passing in (4, 5) then (3, 2) then (0, 1) +*/ +subroutine (testOtherScriptCalledThreeTimes(null) = null) + declare otherScriptCallCount = i4 with protect, noconstant(0) + + call cclutAddMockImplementation("OTHER_SCRIPT", "mock_other_script") + call cclutExecuteProgramWithMocks("the_script", "") + + set stat = cclutAssertI4Equal(CURREF, "testMyFunction_6_9 a", otherScriptCallCount, 3) +end ;;;testMyFunctionZero + +subroutine (validateOtherScriptParams(p1 = i4, p2 = i4) = null) + case (otherScriptCallCount) + of 1: + set stat = cclutAssertI4Equal(CURREF, "validateOtherScriptParams 1 a", p1, 4) + set stat = cclutAssertI4Equal(CURREF, "validateOtherScriptParams 1 b", p2, 5) + of 2: + set stat = cclutAssertI4Equal(CURREF, "validateOtherScriptParams 2 a", p1, 3) + set stat = cclutAssertI4Equal(CURREF, "validateOtherScriptParams 2 b", p2, 2) + of 3: + set stat = cclutAssertI4Equal(CURREF, "validateOtherScriptParams 3 a", p1, 0) + set stat = cclutAssertI4Equal(CURREF, "validateOtherScriptParams 3 b", p2, 1) + endcase +end ;;;validateOtherScriptParams diff --git a/cclunit-framework-source/src/main/ccl/cclut_ff.prg b/cclunit-framework-source/src/main/ccl/cclut_ff.prg index 87e1b66..19e9e11 100644 --- a/cclunit-framework-source/src/main/ccl/cclut_ff.prg +++ b/cclunit-framework-source/src/main/ccl/cclut_ff.prg @@ -110,6 +110,8 @@ with outdev, testCaseDirectory, testCaseFileName, testNamePattern, optimizerMode cclut_ff::outputLine row+1 cclut_ff::outputLine = "%i cclsource:cclut_test_runner.inc" cclut_ff::outputLine row+1 + cclut_ff::outputLine = "%i cclsource:cclutmock.inc" + cclut_ff::outputLine row+1 cclut_ff::outputLine = concat("%i ", cclut_ff::testCaseFileLocation) cclut_ff::outputLine row+1 cclut_ff::outputLine = \ diff --git a/cclunit-framework-source/src/main/resources/cclut_execute_test_logic.inc b/cclunit-framework-source/src/main/resources/cclut_execute_test_logic.inc index 76a5e1f..e7493f6 100644 --- a/cclunit-framework-source/src/main/resources/cclut_execute_test_logic.inc +++ b/cclunit-framework-source/src/main/resources/cclut_execute_test_logic.inc @@ -294,6 +294,7 @@ set cclutReply->status_data.status = "S" call cclut::executeTestLogic(null) #exit_script +;Clean up any mocks that were not cleaned up by the tests. call cclutRemoveAllMocks(null) ;Record any dangling errors and asserts in case the last executed unit test called go to exit_script. set cclutReply->resultInd = band(cclutReply->resultInd, diff --git a/cclunit-framework-source/src/main/resources/cclut_test_runner_end.inc b/cclunit-framework-source/src/main/resources/cclut_test_runner_end.inc index 6859e6e..7c99d65 100644 --- a/cclunit-framework-source/src/main/resources/cclut_test_runner_end.inc +++ b/cclunit-framework-source/src/main/resources/cclut_test_runner_end.inc @@ -48,6 +48,9 @@ if (checkfun("TEARDOWNONCE") = cclut_test_runner::FUN_TYPE_SUBROUTINE) endif endif +;Clean up any mocks that were not cleaned up by the tests. +call cclutRemoveAllMocks(null) + call parser(concat("drop program ", cclut_ff::testProgramName, " go")) if (cclut_test_runner::assertSuccess = TRUE AND cclut_test_runner::testRunnerSuccessInd = TRUE) diff --git a/cclunit-framework-source/src/test/ccl/ut_cclut_execute_program_with_mocks_happy.prg b/cclunit-framework-source/src/test/ccl/ut_cclut_execute_program_with_mocks_happy.prg index bd65778..20c8e40 100644 --- a/cclunit-framework-source/src/test/ccl/ut_cclut_execute_program_with_mocks_happy.prg +++ b/cclunit-framework-source/src/test/ccl/ut_cclut_execute_program_with_mocks_happy.prg @@ -78,4 +78,7 @@ end call internalSubroutine(null) +set internalVariable = 1 +set internalRecord->item = 1 + end go diff --git a/cclunit-framework-source/src/test/ccl/ut_cclut_execute_test_case.inc b/cclunit-framework-source/src/test/ccl/ut_cclut_execute_test_case.inc index 0271da4..fdd5cf4 100644 --- a/cclunit-framework-source/src/test/ccl/ut_cclut_execute_test_case.inc +++ b/cclunit-framework-source/src/test/ccl/ut_cclut_execute_test_case.inc @@ -1076,3 +1076,38 @@ subroutine testSetupErrors(null) call cclutAssertI4Equal(CURREF, "assert value", ucetc_testCaseResults->tests[5].asserts[1].resultInd, TRUE) end ;;;testSetupErrors + +/** + Test that the framework removes any mock tables that test cases fail to do when calling cclut_execute_test_case. +*/ +subroutine testMockTableCleanup(null) + declare cclutMockTableName = vc with protect, noconstant("") + + set ucetc_request->testINCName = "ut_cclut_mock_table_misbehaving_cleanup" + + execute cclut_execute_test_case with + replace("CCLUTREQUEST", ucetc_request), + replace("CCLUTREPLY", ucetc_reply), + replace("CCLUTTESTCASERESULTS", ucetc_testCaseResults) + + call cclutAssertStartsWith(CURREF, "testMockTableCleanup 001", "CUST_CCLUT", cclutMockTableName) + + declare mockId = f8 with protect, noconstant(0.0) + declare mockText = vc with protect, noconstant("") + declare mockDate = dq8 with protect, noconstant(0) + select into "nl:" + from (value(cclutMockTableName) m) + detail + mockId = m.SAMPLE_TABLE_ID + mockText = m.SAMPLE_TABLE_TEXT + mockDate = m.SAMPLE_TABLE_DATE + with nocounter + + declare errorMessage = vc with protect, noconstant("") + declare errorCode = i4 with protect, noconstant(0) + set errorCode = error(errorMessage, 0) + + call cclutAssertVcOperator(CURREF, "testMockTableCleanup 002", trim(errorMessage, 3), + "regexplike", concat("%CCL-E-18-PRG_[0-9]+_[0-9]+\([^)]+\)[0-9]+:[0-9]+\{\}Unable to add range, definition for", + " table \(CUST_CCLUT_[^)]*\) not found in dictionary.")) +end ;;;testMockTableCleanup diff --git a/cclunit-framework-source/src/test/ccl/ut_cclut_execute_test_case_file.inc b/cclunit-framework-source/src/test/ccl/ut_cclut_execute_test_case_file.inc index fefd6ed..3a66548 100644 --- a/cclunit-framework-source/src/test/ccl/ut_cclut_execute_test_case_file.inc +++ b/cclunit-framework-source/src/test/ccl/ut_cclut_execute_test_case_file.inc @@ -1577,4 +1577,39 @@ subroutine testCoverageExcludes(null) replace("CCLUTTESTCASERESULTS", tce_testCaseResults) call cclutAssertVcEqual(CURREF, "expected empty listingXml", tce_reply->programs[1].listingXml, "") call cclutAssertVcEqual(CURREF, "expected same coverageXml", tce_reply->programs[1].coverageXml, coverageXml) -end ;;;testCoverageExcludes \ No newline at end of file +end ;;;testCoverageExcludes + +/** + Test that the framework removes any mock tables that test cases fail to do when calling cclut_execute_test_case_file. +*/ +subroutine testMockTableCleanup(null) + declare cclutMockTableName = vc with protect, noconstant("") + + set ucets_request->testCaseFileName = "ut_cclut_mock_table_misbehaving_cleanup" + + execute cclut_execute_test_case_file with + replace("CCLUTREQUEST", ucets_request), + replace("CCLUTREPLY", ucets_reply), + replace("CCLUTTESTCASERESULTS", ucets_testCaseResults) + + call cclutAssertStartsWith(CURREF, "testMockTableCleanup 001", "CUST_CCLUT", cclutMockTableName) + + declare mockId = f8 with protect, noconstant(0.0) + declare mockText = vc with protect, noconstant("") + declare mockDate = dq8 with protect, noconstant(0) + select into "nl:" + from (value(cclutMockTableName) m) + detail + mockId = m.SAMPLE_TABLE_ID + mockText = m.SAMPLE_TABLE_TEXT + mockDate = m.SAMPLE_TABLE_DATE + with nocounter + + declare errorMessage = vc with protect, noconstant("") + declare errorCode = i4 with protect, noconstant(0) + set errorCode = error(errorMessage, 0) + + call cclutAssertVcOperator(CURREF, "testMockTableCleanup 002", trim(errorMessage, 3), + "regexplike", concat("%CCL-E-18-PRG_[0-9]+_[0-9]+\([^)]+\)[0-9]+:[0-9]+\{\}Unable to add range, definition for", + " table \(CUST_CCLUT_[^)]*\) not found in dictionary.")) +end ;;;testMockTableCleanup diff --git a/cclunit-framework-source/src/test/ccl/ut_cclut_ff.inc b/cclunit-framework-source/src/test/ccl/ut_cclut_ff.inc index 3739774..745d0ba 100644 --- a/cclunit-framework-source/src/test/ccl/ut_cclut_ff.inc +++ b/cclunit-framework-source/src/test/ccl/ut_cclut_ff.inc @@ -718,3 +718,33 @@ subroutine testFailedCompile(null) call testing::checkMessages(null) call testing::checkMRS(_memory_reply_string) end ;;;testFailedCompile + +/** + Test that the framework removes any mock tables that test cases fail to do when calling cclut_ff. +*/ +subroutine testMockTableCleanup(null) + declare cclutMockTableName = vc with protect, noconstant("") + + execute cclut_ff "ut_cclut_output", "cclsource", "ut_cclut_mock_table_misbehaving_cleanup" + + call cclutAssertStartsWith(CURREF, "testMockTableCleanup 001", "CUST_CCLUT", cclutMockTableName) + + declare mockId = f8 with protect, noconstant(0.0) + declare mockText = vc with protect, noconstant("") + declare mockDate = dq8 with protect, noconstant(0) + select into "nl:" + from (value(cclutMockTableName) m) + detail + mockId = m.SAMPLE_TABLE_ID + mockText = m.SAMPLE_TABLE_TEXT + mockDate = m.SAMPLE_TABLE_DATE + with nocounter + + declare errorMessage = vc with protect, noconstant("") + declare errorCode = i4 with protect, noconstant(0) + set errorCode = error(errorMessage, 0) + + call cclutAssertVcOperator(CURREF, "testMockTableCleanup 002", trim(errorMessage, 3), + "regexplike", concat("%CCL-E-18-PRG_[0-9]+_[0-9]+\([^)]+\)[0-9]+:[0-9]+\{\}Unable to add range, definition for", + " table \(CUST_CCLUT_[^)]*\) not found in dictionary.")) +end ;;;testMockTableCleanup diff --git a/cclunit-framework-source/src/test/ccl/ut_cclut_mock.inc b/cclunit-framework-source/src/test/ccl/ut_cclut_mock.inc index f8e207f..0089889 100644 --- a/cclunit-framework-source/src/test/ccl/ut_cclut_mock.inc +++ b/cclunit-framework-source/src/test/ccl/ut_cclut_mock.inc @@ -226,13 +226,17 @@ end ;test_cclutRemoveAllMockImplementations_happy ;********************************************************************************************************************************** ;** cclutExecuteProgramWithMocks ;********************************************************************************************************************************** -/* test_cclutExecuteProgramWithMocks_happy ****************************************************************** -* Scenario: Executes a program using mock tables and implementations that have been set up * -************************************************************************************************************/ +/* test_cclutExecuteProgramWithMocks_happy ******************************************************************************* +* Scenario: Demonstrates a program is successfully executed using mock tables and implementations that have been set up * +*************************************************************************************************************************/ subroutine test_cclutExecuteProgramWithMocks_happy(null) declare public_subroutine = i4 with protect, noconstant(0) declare mock_subroutine = i4 with protect, noconstant(0) declare test_subroutine = i4 with protect, noconstant(0) + declare public::internalVariable = i4 with protect, noconstant(0) + record public::internalRecord ( + 1 item = i4 + ) with protect record executeReply ( 1 number_parameter = i4 @@ -272,37 +276,40 @@ subroutine test_cclutExecuteProgramWithMocks_happy(null) call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy 002", test_subroutine, 0) call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy 003", mock_subroutine, 0) - call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy 004", executeReply->number_parameter, 10) - call cclutAssertvcEqual(CURREF, "test_cclutExecuteProgramWithMocks_happy 005", executeReply->string_parameter, + call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy 004", public::internalVariable, 1) + call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy 005", public::internalRecord->item, 1) + + call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy 006", executeReply->number_parameter, 10) + call cclutAssertvcEqual(CURREF, "test_cclutExecuteProgramWithMocks_happy 007", executeReply->string_parameter, "test param") - call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy 006", size(executeReply->regular_join, 5), + call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy 008", size(executeReply->regular_join, 5), 1) - call cclutAssertf8Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy 007", executeReply->regular_join[1].person_id, + call cclutAssertf8Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy 009", executeReply->regular_join[1].person_id, 1.0) - call cclutAssertf8Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy 008", + call cclutAssertf8Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy 010", executeReply->regular_join[1].encounter_id, 4.0) - call cclutAssertvcEqual(CURREF, "test_cclutExecuteProgramWithMocks_happy 009", + call cclutAssertvcEqual(CURREF, "test_cclutExecuteProgramWithMocks_happy 011", executeReply->regular_join[1].encounter_alias, "test alias") - call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy 010", size(executeReply->left_join, 5), 3) - call cclutAssertf8Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy 011", executeReply->left_join[1].person_id, + call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy 012", size(executeReply->left_join, 5), 3) + call cclutAssertf8Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy 013", executeReply->left_join[1].person_id, 1.0) - call cclutAssertf8Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy 012", + call cclutAssertf8Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy 014", executeReply->left_join[1].encounter_id, 4.0) - call cclutAssertvcEqual(CURREF, "test_cclutExecuteProgramWithMocks_happy 013", + call cclutAssertvcEqual(CURREF, "test_cclutExecuteProgramWithMocks_happy 015", executeReply->left_join[1].encounter_alias, "test alias") - call cclutAssertf8Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy 014", executeReply->left_join[2].person_id, + call cclutAssertf8Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy 016", executeReply->left_join[2].person_id, 2.0) - call cclutAssertf8Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy 015", + call cclutAssertf8Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy 017", executeReply->left_join[2].encounter_id, 5.0) - call cclutAssertvcEqual(CURREF, "test_cclutExecuteProgramWithMocks_happy 016", + call cclutAssertvcEqual(CURREF, "test_cclutExecuteProgramWithMocks_happy 018", executeReply->left_join[2].encounter_alias, "") - call cclutAssertf8Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy 017", executeReply->left_join[3].person_id, + call cclutAssertf8Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy 019", executeReply->left_join[3].person_id, 3.0) - call cclutAssertf8Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy 018", + call cclutAssertf8Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy 020", executeReply->left_join[3].encounter_id, 0.0) - call cclutAssertvcEqual(CURREF, "test_cclutExecuteProgramWithMocks_happy 019", + call cclutAssertvcEqual(CURREF, "test_cclutExecuteProgramWithMocks_happy 021", executeReply->left_join[3].encounter_alias, "") ;The program ut_cclut_execute_mocks_happy performs an inner join for the rdb test and writes the data to the @@ -318,9 +325,9 @@ subroutine test_cclutExecuteProgramWithMocks_happy(null) executeReply->rdb_join[1].data = r.line with nocounter - call cclutAssertVcOperator(CURREF, "test_cclutExecuteProgramWithMocks_happy 020", executeReply->rdb_join[1].columns, + call cclutAssertVcOperator(CURREF, "test_cclutExecuteProgramWithMocks_happy 022", executeReply->rdb_join[1].columns, "regexplike", "PERSON_ID.*ENCOUNTER_ID.*PERSON_ID.*ENCOUNTER_ID.*ENCOUNTER_ALIAS") - call cclutAssertVcOperator(CURREF, "test_cclutExecuteProgramWithMocks_happy 021", executeReply->rdb_join[1].data, + call cclutAssertVcOperator(CURREF, "test_cclutExecuteProgramWithMocks_happy 023", executeReply->rdb_join[1].data, "regexplike", "1.*4.*1.*4.*test alias") end ;test_cclutExecuteProgramWithMocks_happy @@ -328,21 +335,29 @@ end ;test_cclutExecuteProgramWithMocks_happy * Scenario: Executes the program using the supplied namespace * ************************************************************************************************************/ subroutine test_cclutExecuteProgramWithMocks_namespace(null) - declare public_subroutine = i4 with protect, noconstant(0) - declare mock_subroutine = i4 with protect, noconstant(0) declare test_subroutine = i4 with protect, noconstant(0) + declare public::internalVariable = i4 with protect, noconstant(0) + record public::internalRecord ( + 1 item = i4 + ) with protect declare cclut::internalSubroutine(null) = null with protect + declare cclut::internalVariable = i4 with protect, noconstant(0) + record cclut::internalRecord ( + 1 item = i4 + ) with protect subroutine (cclut::internalSubroutine(null) = null with protect) set test_subroutine = 1 end - call cclutExecuteProgramWithMocks("ut_cclut_execute_mocks_happy", "10,^test param^", "CCLUT") + call cclutExecuteProgramWithMocks("ut_cclut_execute_mocks_happy", "", "CCLUT") - call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_namespace 001", public_subroutine, 0) - call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_namespace 002", test_subroutine, 1) - call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_namespace 003", mock_subroutine, 0) + call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_namespace 001", test_subroutine, 1) + call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_namespace 002", public::internalVariable, 0) + call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_namespace 003", cclut::internalVariable, 1) + call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_namespace 004", public::internalRecord->item, 0) + call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_namespace 005", cclut::internalRecord->item, 1) end ;test_cclutExecuteProgramWithMocks_namespace /* test_cclutExecuteProgramWithMocks_mock_subroutine ******************************************************** @@ -352,6 +367,14 @@ subroutine test_cclutExecuteProgramWithMocks_mock_subroutine(null) declare public_subroutine = i4 with protect, noconstant(0) declare mock_subroutine = i4 with protect, noconstant(0) declare test_subroutine = i4 with protect, noconstant(0) + declare public::internalVariable = i4 with protect, noconstant(0) + record public::internalRecord ( + 1 item = i4 + ) with protect + declare cclut::internalVariable = i4 with protect, noconstant(0) + record cclut::internalRecord ( + 1 item = i4 + ) with protect declare cclut::mockSubroutine(null) = null with protect @@ -366,6 +389,13 @@ subroutine test_cclutExecuteProgramWithMocks_mock_subroutine(null) call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_mock_subroutine 001", public_subroutine, 0) call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_mock_subroutine 002", test_subroutine, 0) call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_mock_subroutine 003", mock_subroutine, 1) + call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_mock_subroutine 004", public::internalVariable, + 0) + call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_mock_subroutine 005", cclut::internalVariable, 1) + call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_mock_subroutine 006", + public::internalRecord->item, 0) + call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_mock_subroutine 007", + cclut::internalRecord->item, 1) end ;test_cclutExecuteProgramWithMocks_mock_subroutine /* test_cclutExecuteProgramWithMocks_missing_programName **************************************************** diff --git a/cclunit-framework-source/src/test/ccl/ut_cclut_mock_carry_forward.inc b/cclunit-framework-source/src/test/ccl/ut_cclut_mock_carry_forward.inc new file mode 100644 index 0000000..f9ba0f4 --- /dev/null +++ b/cclunit-framework-source/src/test/ccl/ut_cclut_mock_carry_forward.inc @@ -0,0 +1,46 @@ +;********************************************************************************************************************************** +;** This is a special test case that is specifically designed to test that mocks carry forward from test to test until they are +;** explicitly removed. The framework removes all mocks at the end of every test case. +;********************************************************************************************************************************** +/* test_cclutAddMockImplementation_happy ******************************************************************** +* Scenario: Adds mock implementations that can be used with cclutExecuteProgramWithMocks * +************************************************************************************************************/ +subroutine test_cclutAddMockImplementation_happy(null) + call cclutAddMockImplementation("sample_subroutine", "mock_subroutine") + + call cclutAsserti4Equal(CURREF, "test_cclutAddMockImplementation_happy 001", + size(cclut_mockImplementations->implementations, 5), 1) + call cclutAssertvcEqual(CURREF, "test_cclutAddMockImplementation_happy 002", + cclut_mockImplementations->implementations[1].originalName, "SAMPLE_SUBROUTINE") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockImplementation_happy 003", + cclut_mockImplementations->implementations[1].replaceName, "MOCK_SUBROUTINE") + + call cclutAddMockImplementation("second_subroutine", "new_subroutine") + + call cclutAsserti4Equal(CURREF, "test_cclutAddMockImplementation_happy 004", + size(cclut_mockImplementations->implementations, 5), 2) + call cclutAssertvcEqual(CURREF, "test_cclutAddMockImplementation_happy 005", + cclut_mockImplementations->implementations[1].originalName, "SAMPLE_SUBROUTINE") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockImplementation_happy 006", + cclut_mockImplementations->implementations[1].replaceName, "MOCK_SUBROUTINE") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockImplementation_happy 007", + cclut_mockImplementations->implementations[2].originalName, "SECOND_SUBROUTINE") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockImplementation_happy 008", + cclut_mockImplementations->implementations[2].replaceName, "NEW_SUBROUTINE") +end ;test_cclutAddMockImplementation_happy + +/* test_cclutAddMockImplementation_not_cleared ************************************************************** +* Scenario: Demonstrates that the mocks from the previous test still exist since they have not been cleared* +************************************************************************************************************/ +subroutine test_cclutAddMockImplementation_not_cleared(null) + call cclutAsserti4Equal(CURREF, "test_cclutAddMockImplementation_not_cleared 001", + size(cclut_mockImplementations->implementations, 5), 2) + call cclutAssertvcEqual(CURREF, "test_cclutAddMockImplementation_not_cleared 002", + cclut_mockImplementations->implementations[1].originalName, "SAMPLE_SUBROUTINE") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockImplementation_not_cleared 003", + cclut_mockImplementations->implementations[1].replaceName, "MOCK_SUBROUTINE") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockImplementation_not_cleared 004", + cclut_mockImplementations->implementations[2].originalName, "SECOND_SUBROUTINE") + call cclutAssertvcEqual(CURREF, "test_cclutAddMockImplementation_not_cleared 005", + cclut_mockImplementations->implementations[2].replaceName, "NEW_SUBROUTINE") +end ;test_cclutAddMockImplementation_happy \ No newline at end of file diff --git a/cclunit-framework-source/src/test/ccl/ut_cclut_mock_table_misbehaving_cleanup.inc b/cclunit-framework-source/src/test/ccl/ut_cclut_mock_table_misbehaving_cleanup.inc new file mode 100644 index 0000000..f174e48 --- /dev/null +++ b/cclunit-framework-source/src/test/ccl/ut_cclut_mock_table_misbehaving_cleanup.inc @@ -0,0 +1,75 @@ +;********************************************************************************************************************************** +;** This is a special test case that is specifically designed to test that when mock tables are not cleaned up, they are still +;** available at the "tearDown" and "tearDownOnce" stage. This .inc is used by other tests in ut_cclut_ff and +;** ut_cclut_execute_test_case(_file) to confirm that the framework removes the mock tables afterward. +;********************************************************************************************************************************** + +if (validate(cclutMockTableName) = 0) + declare cclutMockTableName = vc with protect, noconstant("") +endif + +declare tearDown(dummyVar = i2) = null +declare tearDownOnce(dummyVar = i2) = null + +subroutine tearDown(dummyVar) + declare mockId = f8 with protect, noconstant(0.0) + declare mockText = vc with protect, noconstant("") + declare mockDate = dq8 with protect, noconstant(0) + select into "nl:" + from (value(cclutMockTableName) m) + detail + mockId = m.SAMPLE_TABLE_ID + mockText = m.SAMPLE_TABLE_TEXT + mockDate = m.SAMPLE_TABLE_DATE + with nocounter + + call cclutAssertf8Equal(CURREF, "test_cclut_mock_table_misbehaving_cleanup_teardown 001", mockId, 1.0) + call cclutAssertvcEqual(CURREF, "test_cclut_mock_table_misbehaving_cleanup_teardown 002", mockText, "test text") + call cclutAssertf8Equal(CURREF, "test_cclut_mock_table_misbehaving_cleanup_teardown 003", mockDate, + cnvtdatetime("27-NOV-2018 08:00")) +end ;tearDown + +subroutine tearDownOnce(dummyVar) + declare mockId = f8 with protect, noconstant(0.0) + declare mockText = vc with protect, noconstant("") + declare mockDate = dq8 with protect, noconstant(0) + select into "nl:" + from (value(cclutMockTableName) m) + detail + mockId = m.SAMPLE_TABLE_ID + mockText = m.SAMPLE_TABLE_TEXT + mockDate = m.SAMPLE_TABLE_DATE + with nocounter + + call cclutAssertf8Equal(CURREF, "test_cclut_mock_table_misbehaving_cleanup_teardown_once 001", mockId, 1.0) + call cclutAssertvcEqual(CURREF, "test_cclut_mock_table_misbehaving_cleanup_teardown_once 002", mockText, "test text") + call cclutAssertf8Equal(CURREF, "test_cclut_mock_table_misbehaving_cleanup_teardown_once 003", mockDate, + cnvtdatetime("27-NOV-2018 08:00")) +end ;tearDownOnce + +/* test_cclut_mock_table_misbehaving_cleanup **************************************************************** +* Scenario: Creates a mock table and does not clean it up within tearDown or tearDownOnce * +************************************************************************************************************/ +subroutine test_cclut_mock_table_misbehaving_cleanup(null) + set cclutMockTableName = + cclutDefineMockTable("sample_table", "sample_table_id|sample_table_text|sample_table_date", "f8|vc|dq8") + call cclutCreateMockTable("sample_table") + call cclutAddMockData("sample_table", "1.0|test text|27-NOV-2018 08:00") + call cclutAddMockImplementation("sample_subroutine", "mock_subroutine") + + declare mockId = f8 with protect, noconstant(0.0) + declare mockText = vc with protect, noconstant("") + declare mockDate = dq8 with protect, noconstant(0) + select into "nl:" + from (value(cclutMockTableName) m) + detail + mockId = m.SAMPLE_TABLE_ID + mockText = m.SAMPLE_TABLE_TEXT + mockDate = m.SAMPLE_TABLE_DATE + with nocounter + + call cclutAssertf8Equal(CURREF, "test_cclut_mock_table_misbehaving_cleanup 001", mockId, 1.0) + call cclutAssertvcEqual(CURREF, "test_cclut_mock_table_misbehaving_cleanup 002", mockText, "test text") + call cclutAssertf8Equal(CURREF, "test_cclut_mock_table_misbehaving_cleanup 003", mockDate, + cnvtdatetime("27-NOV-2018 08:00")) +end ;test_cclut_mock_table_misbehaving_cleanup \ No newline at end of file From 2000026252b24dd02f70f66f25d946cd0d7b3544 Mon Sep 17 00:00:00 2001 From: cernertrevor Date: Tue, 5 Feb 2019 08:06:29 -0600 Subject: [PATCH 4/7] Third batch of changes based on code review comments. --- cclunit-framework-source/doc/CCLUTGUIDANCE.md | 2 +- cclunit-framework-source/doc/CCLUTMOCKING.md | 7 ++ .../doc/examples/basic_example.inc | 4 +- .../doc/examples/mocking_api.inc | 13 ++- .../doc/examples/validation_subroutine.inc | 6 +- ...cclut_execute_program_with_mocks_happy.prg | 11 +++ .../src/test/ccl/ut_cclut_mock.inc | 58 ++++-------- .../test/ccl/ut_cclut_mock_carry_forward.inc | 88 +++++++++++-------- 8 files changed, 107 insertions(+), 82 deletions(-) diff --git a/cclunit-framework-source/doc/CCLUTGUIDANCE.md b/cclunit-framework-source/doc/CCLUTGUIDANCE.md index 5cef4be..c88addc 100644 --- a/cclunit-framework-source/doc/CCLUTGUIDANCE.md +++ b/cclunit-framework-source/doc/CCLUTGUIDANCE.md @@ -22,7 +22,7 @@ In general, there are two ways to mock objects in CCL unit tests. Generally spe The CCL Unit Testing framework provides an abstraction for creating mocks. The purpose is to help make it easier to define mock tables and other mock objects to be used when executing a script. Details on the API can be found at [CCLUTMOCKING.md](../CCLUTMOCKING.md) -[These examples](./examples/mocking_api.inc) demonstrates the CCL Unit Testing framework's mocking API. They assume the script under test is called "the_script" and executes a program called "other_script". They test for scenarios where other_script returns 0 items, more than 5 items, and a failed ("F") status. +[These unit tests](./examples/mocking_api.inc) demonstrate how to accomplish a basic "with replace" while using the CCL Unit Testing framework's mocking API. They test a script named "the_script" and executes a program called "other_script". They test for scenarios where other_script returns 0 items, more than 5 items, and a failed ("F") status. There are other variations on this. For example, you could put asserts within mock_other_script itself. Additionally, other_script might generate its own reply structure, so you would want to do the same in mock_other_script. diff --git a/cclunit-framework-source/doc/CCLUTMOCKING.md b/cclunit-framework-source/doc/CCLUTMOCKING.md index abfde8b..c0bf669 100644 --- a/cclunit-framework-source/doc/CCLUTMOCKING.md +++ b/cclunit-framework-source/doc/CCLUTMOCKING.md @@ -1,7 +1,14 @@ # CCL Unit Mocking +The CCL Unit Test framework's mocking API is available for consumers to mock certain objects to better isolate unit tests from outside variability and provide more control over the scenarios under which unit tests are run. The API provides ways to mock tables, variables, subroutines, scripts, etc. + **\*CAUTION\*** **The CCL Unit Mocking framework should only be used in non-production environments. Table mocking creates new tables against an Oracle instance for the lifetime of the test. Because the DDL is generated in a dynamic way, it is possible through inappropriate use of the framework to affect the actual table. Please only use the documented API.** +## Table of Contents +[API](#api) +[Implementation Notes](#implementation-notes) +[Example](#example) + ## API **cclutExecuteProgramWithMocks(programName = vc, params = vc, namespace = vc)** diff --git a/cclunit-framework-source/doc/examples/basic_example.inc b/cclunit-framework-source/doc/examples/basic_example.inc index edaf178..80b5c67 100644 --- a/cclunit-framework-source/doc/examples/basic_example.inc +++ b/cclunit-framework-source/doc/examples/basic_example.inc @@ -1,9 +1,9 @@ ;; this is the test -;;; public::mainForSubroutineB is the workhorse. It will be called instead of public::main because of "with replace" /** * Confirms that subroutineB returns "subroutineBTest" when it is passed "Test" -* and "subroutineBSubroutine" when it is passed "Subroutine". +* and "subroutineBSubroutine" when it is passed "Subroutine". public::mainForSubroutineB is the workhorse. It will be +* called instead of public::main because of "with replace" */ subroutine (testSubroutineB(null) = null) diff --git a/cclunit-framework-source/doc/examples/mocking_api.inc b/cclunit-framework-source/doc/examples/mocking_api.inc index fd50b3c..4dc25c7 100644 --- a/cclunit-framework-source/doc/examples/mocking_api.inc +++ b/cclunit-framework-source/doc/examples/mocking_api.inc @@ -1,6 +1,8 @@ ;;; put the following script definition in a .prg file and compile it - +/** +Mock implementation for other_script which sets reply equal to a copy of mock_other_script_reply. +*/ drop program mock_other_script go create program mock_other_script free record reply @@ -68,3 +70,12 @@ subroutine (testMyFunctionOtherScriptFail(null) = null) ;assert things here end ;;;testMyFunctionOtherScriptFail + +;; this is the script to be tested + +drop program the_script:dba go +create program the_script:dba + + execute other_script + +end go diff --git a/cclunit-framework-source/doc/examples/validation_subroutine.inc b/cclunit-framework-source/doc/examples/validation_subroutine.inc index 176e8db..57daee3 100644 --- a/cclunit-framework-source/doc/examples/validation_subroutine.inc +++ b/cclunit-framework-source/doc/examples/validation_subroutine.inc @@ -8,8 +8,10 @@ create program the_script end go -;;; put this definition in a .prg file and compile it - +/** +Mock implementation for other_script which calls validateOtherScriptParams to validate the two input parameters +and increments a counter for the number of calls to other_script. +*/ drop program mock_other_script go create program mock_other_script prompt "param 1", "param 2" with param1, param2 diff --git a/cclunit-framework-source/src/test/ccl/ut_cclut_execute_program_with_mocks_happy.prg b/cclunit-framework-source/src/test/ccl/ut_cclut_execute_program_with_mocks_happy.prg index 20c8e40..014979f 100644 --- a/cclunit-framework-source/src/test/ccl/ut_cclut_execute_program_with_mocks_happy.prg +++ b/cclunit-framework-source/src/test/ccl/ut_cclut_execute_program_with_mocks_happy.prg @@ -22,6 +22,15 @@ record reply ( ) */ +record public::persistRecord ( + 1 item = i4 +) with persistscript + +declare public::internalVariable = i4 with protect, noconstant(0) +record public::internalRecord ( + 1 item = i4 +) with protect + declare public::internalSubroutine(null) = null with protect subroutine (public::internalSubroutine(null) = null with protect) @@ -81,4 +90,6 @@ call internalSubroutine(null) set internalVariable = 1 set internalRecord->item = 1 +set persistRecord->item = 1 + end go diff --git a/cclunit-framework-source/src/test/ccl/ut_cclut_mock.inc b/cclunit-framework-source/src/test/ccl/ut_cclut_mock.inc index 0089889..4d14f20 100644 --- a/cclunit-framework-source/src/test/ccl/ut_cclut_mock.inc +++ b/cclunit-framework-source/src/test/ccl/ut_cclut_mock.inc @@ -233,10 +233,6 @@ subroutine test_cclutExecuteProgramWithMocks_happy(null) declare public_subroutine = i4 with protect, noconstant(0) declare mock_subroutine = i4 with protect, noconstant(0) declare test_subroutine = i4 with protect, noconstant(0) - declare public::internalVariable = i4 with protect, noconstant(0) - record public::internalRecord ( - 1 item = i4 - ) with protect record executeReply ( 1 number_parameter = i4 @@ -276,40 +272,39 @@ subroutine test_cclutExecuteProgramWithMocks_happy(null) call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy 002", test_subroutine, 0) call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy 003", mock_subroutine, 0) - call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy 004", public::internalVariable, 1) - call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy 005", public::internalRecord->item, 1) + call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy 004", public::persistRecord->item, 1) - call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy 006", executeReply->number_parameter, 10) - call cclutAssertvcEqual(CURREF, "test_cclutExecuteProgramWithMocks_happy 007", executeReply->string_parameter, + call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy 005", executeReply->number_parameter, 10) + call cclutAssertvcEqual(CURREF, "test_cclutExecuteProgramWithMocks_happy 006", executeReply->string_parameter, "test param") - call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy 008", size(executeReply->regular_join, 5), + call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy 007", size(executeReply->regular_join, 5), 1) - call cclutAssertf8Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy 009", executeReply->regular_join[1].person_id, + call cclutAssertf8Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy 008", executeReply->regular_join[1].person_id, 1.0) - call cclutAssertf8Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy 010", + call cclutAssertf8Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy 009", executeReply->regular_join[1].encounter_id, 4.0) - call cclutAssertvcEqual(CURREF, "test_cclutExecuteProgramWithMocks_happy 011", + call cclutAssertvcEqual(CURREF, "test_cclutExecuteProgramWithMocks_happy 010", executeReply->regular_join[1].encounter_alias, "test alias") - call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy 012", size(executeReply->left_join, 5), 3) - call cclutAssertf8Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy 013", executeReply->left_join[1].person_id, + call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy 011", size(executeReply->left_join, 5), 3) + call cclutAssertf8Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy 012", executeReply->left_join[1].person_id, 1.0) - call cclutAssertf8Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy 014", + call cclutAssertf8Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy 013", executeReply->left_join[1].encounter_id, 4.0) - call cclutAssertvcEqual(CURREF, "test_cclutExecuteProgramWithMocks_happy 015", + call cclutAssertvcEqual(CURREF, "test_cclutExecuteProgramWithMocks_happy 014", executeReply->left_join[1].encounter_alias, "test alias") - call cclutAssertf8Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy 016", executeReply->left_join[2].person_id, + call cclutAssertf8Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy 015", executeReply->left_join[2].person_id, 2.0) - call cclutAssertf8Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy 017", + call cclutAssertf8Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy 016", executeReply->left_join[2].encounter_id, 5.0) - call cclutAssertvcEqual(CURREF, "test_cclutExecuteProgramWithMocks_happy 018", + call cclutAssertvcEqual(CURREF, "test_cclutExecuteProgramWithMocks_happy 017", executeReply->left_join[2].encounter_alias, "") - call cclutAssertf8Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy 019", executeReply->left_join[3].person_id, + call cclutAssertf8Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy 018", executeReply->left_join[3].person_id, 3.0) - call cclutAssertf8Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy 020", + call cclutAssertf8Equal(CURREF, "test_cclutExecuteProgramWithMocks_happy 019", executeReply->left_join[3].encounter_id, 0.0) - call cclutAssertvcEqual(CURREF, "test_cclutExecuteProgramWithMocks_happy 021", + call cclutAssertvcEqual(CURREF, "test_cclutExecuteProgramWithMocks_happy 020", executeReply->left_join[3].encounter_alias, "") ;The program ut_cclut_execute_mocks_happy performs an inner join for the rdb test and writes the data to the @@ -325,9 +320,9 @@ subroutine test_cclutExecuteProgramWithMocks_happy(null) executeReply->rdb_join[1].data = r.line with nocounter - call cclutAssertVcOperator(CURREF, "test_cclutExecuteProgramWithMocks_happy 022", executeReply->rdb_join[1].columns, + call cclutAssertVcOperator(CURREF, "test_cclutExecuteProgramWithMocks_happy 021", executeReply->rdb_join[1].columns, "regexplike", "PERSON_ID.*ENCOUNTER_ID.*PERSON_ID.*ENCOUNTER_ID.*ENCOUNTER_ALIAS") - call cclutAssertVcOperator(CURREF, "test_cclutExecuteProgramWithMocks_happy 023", executeReply->rdb_join[1].data, + call cclutAssertVcOperator(CURREF, "test_cclutExecuteProgramWithMocks_happy 022", executeReply->rdb_join[1].data, "regexplike", "1.*4.*1.*4.*test alias") end ;test_cclutExecuteProgramWithMocks_happy @@ -336,11 +331,6 @@ end ;test_cclutExecuteProgramWithMocks_happy ************************************************************************************************************/ subroutine test_cclutExecuteProgramWithMocks_namespace(null) declare test_subroutine = i4 with protect, noconstant(0) - declare public::internalVariable = i4 with protect, noconstant(0) - record public::internalRecord ( - 1 item = i4 - ) with protect - declare cclut::internalSubroutine(null) = null with protect declare cclut::internalVariable = i4 with protect, noconstant(0) record cclut::internalRecord ( @@ -354,9 +344,7 @@ subroutine test_cclutExecuteProgramWithMocks_namespace(null) call cclutExecuteProgramWithMocks("ut_cclut_execute_mocks_happy", "", "CCLUT") call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_namespace 001", test_subroutine, 1) - call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_namespace 002", public::internalVariable, 0) call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_namespace 003", cclut::internalVariable, 1) - call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_namespace 004", public::internalRecord->item, 0) call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_namespace 005", cclut::internalRecord->item, 1) end ;test_cclutExecuteProgramWithMocks_namespace @@ -367,10 +355,6 @@ subroutine test_cclutExecuteProgramWithMocks_mock_subroutine(null) declare public_subroutine = i4 with protect, noconstant(0) declare mock_subroutine = i4 with protect, noconstant(0) declare test_subroutine = i4 with protect, noconstant(0) - declare public::internalVariable = i4 with protect, noconstant(0) - record public::internalRecord ( - 1 item = i4 - ) with protect declare cclut::internalVariable = i4 with protect, noconstant(0) record cclut::internalRecord ( 1 item = i4 @@ -389,11 +373,7 @@ subroutine test_cclutExecuteProgramWithMocks_mock_subroutine(null) call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_mock_subroutine 001", public_subroutine, 0) call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_mock_subroutine 002", test_subroutine, 0) call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_mock_subroutine 003", mock_subroutine, 1) - call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_mock_subroutine 004", public::internalVariable, - 0) call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_mock_subroutine 005", cclut::internalVariable, 1) - call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_mock_subroutine 006", - public::internalRecord->item, 0) call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_mock_subroutine 007", cclut::internalRecord->item, 1) end ;test_cclutExecuteProgramWithMocks_mock_subroutine diff --git a/cclunit-framework-source/src/test/ccl/ut_cclut_mock_carry_forward.inc b/cclunit-framework-source/src/test/ccl/ut_cclut_mock_carry_forward.inc index f9ba0f4..90829b1 100644 --- a/cclunit-framework-source/src/test/ccl/ut_cclut_mock_carry_forward.inc +++ b/cclunit-framework-source/src/test/ccl/ut_cclut_mock_carry_forward.inc @@ -2,45 +2,59 @@ ;** This is a special test case that is specifically designed to test that mocks carry forward from test to test until they are ;** explicitly removed. The framework removes all mocks at the end of every test case. ;********************************************************************************************************************************** -/* test_cclutAddMockImplementation_happy ******************************************************************** -* Scenario: Adds mock implementations that can be used with cclutExecuteProgramWithMocks * -************************************************************************************************************/ -subroutine test_cclutAddMockImplementation_happy(null) - call cclutAddMockImplementation("sample_subroutine", "mock_subroutine") - - call cclutAsserti4Equal(CURREF, "test_cclutAddMockImplementation_happy 001", - size(cclut_mockImplementations->implementations, 5), 1) - call cclutAssertvcEqual(CURREF, "test_cclutAddMockImplementation_happy 002", - cclut_mockImplementations->implementations[1].originalName, "SAMPLE_SUBROUTINE") - call cclutAssertvcEqual(CURREF, "test_cclutAddMockImplementation_happy 003", - cclut_mockImplementations->implementations[1].replaceName, "MOCK_SUBROUTINE") - - call cclutAddMockImplementation("second_subroutine", "new_subroutine") - - call cclutAsserti4Equal(CURREF, "test_cclutAddMockImplementation_happy 004", - size(cclut_mockImplementations->implementations, 5), 2) - call cclutAssertvcEqual(CURREF, "test_cclutAddMockImplementation_happy 005", - cclut_mockImplementations->implementations[1].originalName, "SAMPLE_SUBROUTINE") - call cclutAssertvcEqual(CURREF, "test_cclutAddMockImplementation_happy 006", - cclut_mockImplementations->implementations[1].replaceName, "MOCK_SUBROUTINE") - call cclutAssertvcEqual(CURREF, "test_cclutAddMockImplementation_happy 007", - cclut_mockImplementations->implementations[2].originalName, "SECOND_SUBROUTINE") - call cclutAssertvcEqual(CURREF, "test_cclutAddMockImplementation_happy 008", - cclut_mockImplementations->implementations[2].replaceName, "NEW_SUBROUTINE") -end ;test_cclutAddMockImplementation_happy - -/* test_cclutAddMockImplementation_not_cleared ************************************************************** -* Scenario: Demonstrates that the mocks from the previous test still exist since they have not been cleared* -************************************************************************************************************/ -subroutine test_cclutAddMockImplementation_not_cleared(null) + +declare setupOnce(dummyVar = i2) = null +declare tearDownOnce(dummyVar = i2) = null + +subroutine setupOnce(dummyVar) + call cclutAddMockImplementation("setup_once_subroutine", "mock_setup_once_subroutine") +end ;setupOnce + +subroutine tearDownOnce(dummyVar) + declare mockIndex = i4 with protect, noconstant(0) + declare mockPos = i4 with protect, noconstant(0) + call cclutAsserti4Equal(CURREF, "test_cclutAddMockImplementation_not_cleared 001", - size(cclut_mockImplementations->implementations, 5), 2) + size(cclut_mockImplementations->implementations, 5), 4) + + set mockPos = locateVal(mockIndex, 1, 4, "SETUP_ONCE_SUBROUTINE", + cclut_mockImplementations->implementations[mockIndex].originalName) call cclutAssertvcEqual(CURREF, "test_cclutAddMockImplementation_not_cleared 002", - cclut_mockImplementations->implementations[1].originalName, "SAMPLE_SUBROUTINE") + cclut_mockImplementations->implementations[mockPos].replaceName, "MOCK_SETUP_ONCE_SUBROUTINE") + + set mockPos = locateVal(mockIndex, 1, 4, "ONE_SUBROUTINE", + cclut_mockImplementations->implementations[mockIndex].originalName) call cclutAssertvcEqual(CURREF, "test_cclutAddMockImplementation_not_cleared 003", - cclut_mockImplementations->implementations[1].replaceName, "MOCK_SUBROUTINE") + cclut_mockImplementations->implementations[mockPos].replaceName, "MOCK_ONE_SUBROUTINE") + + set mockPos = locateVal(mockIndex, 1, 4, "TWO_SUBROUTINE", + cclut_mockImplementations->implementations[mockIndex].originalName) call cclutAssertvcEqual(CURREF, "test_cclutAddMockImplementation_not_cleared 004", - cclut_mockImplementations->implementations[2].originalName, "SECOND_SUBROUTINE") + cclut_mockImplementations->implementations[mockPos].replaceName, "MOCK_TWO_SUBROUTINE") + + set mockPos = locateVal(mockIndex, 1, 4, "THREE_SUBROUTINE", + cclut_mockImplementations->implementations[mockIndex].originalName) call cclutAssertvcEqual(CURREF, "test_cclutAddMockImplementation_not_cleared 005", - cclut_mockImplementations->implementations[2].replaceName, "NEW_SUBROUTINE") -end ;test_cclutAddMockImplementation_happy \ No newline at end of file + cclut_mockImplementations->implementations[mockPos].replaceName, "MOCK_THREE_SUBROUTINE") +end ;tearDownOnce + +/* test_cclutAddMockImplementation_one ********************************************************************** +* Scenario: Adds a mock implementation that can be used with cclutExecuteProgramWithMocks * +************************************************************************************************************/ +subroutine test_cclutAddMockImplementation_one(null) + call cclutAddMockImplementation("one_subroutine", "mock_one_subroutine") +end ;test_cclutAddMockImplementation_one + +/* test_cclutAddMockImplementation_two ********************************************************************** +* Scenario: Adds a mock implementation that can be used with cclutExecuteProgramWithMocks * +************************************************************************************************************/ +subroutine test_cclutAddMockImplementation_two(null) + call cclutAddMockImplementation("two_subroutine", "mock_two_subroutine") +end ;test_cclutAddMockImplementation_two + +/* test_cclutAddMockImplementation_three ******************************************************************** +* Scenario: Adds a mock implementation that can be used with cclutExecuteProgramWithMocks * +************************************************************************************************************/ +subroutine test_cclutAddMockImplementation_three(null) + call cclutAddMockImplementation("three_subroutine", "mock_three_subroutine") +end ;test_cclutAddMockImplementation_three \ No newline at end of file From 0978f413814799f1fd4065951a9c8b7bfe4454a6 Mon Sep 17 00:00:00 2001 From: cernertrevor Date: Fri, 8 Feb 2019 16:08:07 -0600 Subject: [PATCH 5/7] Removal of cclutAddConstraint API for initial version. Will be added as an enhancement on Github after this PR is merged. --- cclunit-framework-source/doc/CCLUTMOCKING.md | 20 +-- .../src/main/resources/cclutmock_table.inc | 73 +------- .../test/ccl/ut_cclut_execute_test_case.inc | 130 +++++++------- .../ccl/ut_cclut_execute_test_case_file.inc | 130 +++++++------- .../src/test/ccl/ut_cclut_mock_table.inc | 163 +++--------------- 5 files changed, 155 insertions(+), 361 deletions(-) diff --git a/cclunit-framework-source/doc/CCLUTMOCKING.md b/cclunit-framework-source/doc/CCLUTMOCKING.md index c0bf669..bde5c6e 100644 --- a/cclunit-framework-source/doc/CCLUTMOCKING.md +++ b/cclunit-framework-source/doc/CCLUTMOCKING.md @@ -32,7 +32,7 @@ call cclutExecuteProgramWithMocks("ccl_my_program", "\^MINE^, 1.0, ^string param **cclutDefineMockTable(tableName = vc, fieldNames = vc, fieldTypes = vc)** -Defines a mock table structure that can be created for use within a program. This is the first function to be called in the process of mocking a table. It must be called before cclutAddMockIndex(), cclutAddMockConstraint(), and cclutCreateMockTable() can be called. The table will not be mocked in cclutExecuteProgramWithMocks() unless cclutCreateMockTable() is called. This function can be called for the same table after cclutCreateMockTable() in order to redefine it; however, the existing mocked table will be dropped and cclutCreateMockTable() will need to be called again to recreate it with the new defintion. tableName, columnNames, and columnTypes are required. columnNames and columnTypes are expected to be pipe-delimited strings. The columnTypes should have the same count as columnNames and be in the same order. +Defines a mock table structure that can be created for use within a program. This is the first function to be called in the process of mocking a table. It must be called before cclutAddMockIndex() and cclutCreateMockTable() can be called. The table will not be mocked in cclutExecuteProgramWithMocks() unless cclutCreateMockTable() is called. This function can be called for the same table after cclutCreateMockTable() in order to redefine it; however, the existing mocked table will be dropped and cclutCreateMockTable() will need to be called again to recreate it with the new defintion. tableName, columnNames, and columnTypes are required. columnNames and columnTypes are expected to be pipe-delimited strings. The columnTypes should have the same count as columnNames and be in the same order. @param tableName     The table to be mocked. @@ -46,21 +46,6 @@ Defines a mock table structure that can be created for use within a program. Th Example: call cclutDefineMockTable("person", "person_id|name_last|name_first|birth_dt_tm", "f8|vc|vc|dq8") -**cclutAddMockConstraint(tableName = vc, columnName = vc, columnConstraint = vc)** - -Adds a constraint to a mock table. The table must already be defined through cclutDefineMockTable(), otherwise an error will be thrown. This function may not be called after cclutCreateMockTable(). tableName and columnName are required. If the columnName is not valid for the table specified, an error will be thrown. All constraints for a column should be present in the columnConstraint field. If a constraint already exists, this function will overwrite it with the new value. If columnConstraint is blank, the constraint will be removed for the column. The supported constraints can be seen here: -https://wiki.cerner.com/display/public/1101discernHP/SELECT+INTO+TABLE+Table_Name+Using+Discern+Explorer - -@param tableName -    The name of the source table for the mock table to which the constraint will be added. -@param columnName -    The column to which the constraint will be applied. -@param columnConstraint -    A string of all constraints to be applied to the column. - -Example: -call cclutAddMockConstraint("person", "name_last", "not null unique") - **cclutAddMockIndex(tableName = vc, columnNames = vc, isUnique = i4)** Adds an index to a mock table. The table must already be defined through cclutDefineMockTable(), otherwise an error will be thrown. This function may not be called after cclutCreateMockTable(). tableName, columnNames, and isUnique are required. columnNames may be a single column name or a pipe-delimited list of columns for a composite index (the order of the columns will be the order of the index). If isUnique is TRUE, then a unique index will be created. If isUnique is FALSE, then a non-unique index will be created. @@ -236,9 +221,6 @@ Test Code: set mock_table_person = cclutDefineMockTable("person", "person_id|name_last|name_first|birth_dt_tm", "f8|vc|vc|dq8") - ; Add a constraint that the person_id cannot be null - call cclutAddMockConstraint("person", "person_id", "not null") - ; Add a non-unique index to name_last call cclutAddMockIndex("person", "name_last", FALSE) diff --git a/cclunit-framework-source/src/main/resources/cclutmock_table.inc b/cclunit-framework-source/src/main/resources/cclutmock_table.inc index 9ccec20..9c66ceb 100644 --- a/cclunit-framework-source/src/main/resources/cclutmock_table.inc +++ b/cclunit-framework-source/src/main/resources/cclutmock_table.inc @@ -15,8 +15,6 @@ declare CCLUT_ESCAPED_NULL = vc with protect, constant("\null") declare cclutDefineMockTable(cclutTableName = vc(val), cclutFieldNames = vc(val), cclutFieldTypes = vc(val)) = vc with protect -declare cclutAddMockConstraint(cclutTableName = vc(val), cclutColumnName = vc(val), - cclutColumnConstraint = vc(val)) = null with protect declare cclutAddMockIndex(cclutTableName = vc(val), cclutColumnNames = vc(val), cclutIsUnique = i4(val)) = null with protect declare cclutCreateMockTable(cclutTableName = vc(val)) = null with protect @@ -47,7 +45,6 @@ record cclut_mockTables ( 2 columns[*] 3 columnName = vc 3 columnType = vc - 3 columnConstraint = vc 2 indexes[*] 3 indexColumns = vc 3 isUnique = i2 @@ -58,11 +55,10 @@ set cclut_mockTables->markerTime = cnvtint(curtime3) /** Defines a mock table structure that can be created for use within a program. This is the first function to be called in -the process of mocking a table. It must be called before cclutAddMockIndex(), cclutAddMockConstraint(), and -cclutCreateMockTable() can be called. The table will not be mocked in cclutExecuteProgramWithMocks() unless -cclutCreateMockTable() is called. tableName, columnNames, and columnTypes are required. columnNames and columnTypes -are expected to be pipe-delimited strings. The columnTypes should have the same count as columnNames and be in the same -order. +the process of mocking a table. It must be called before cclutAddMockIndex() and cclutCreateMockTable() can be called. +The table will not be mocked in cclutExecuteProgramWithMocks() unless cclutCreateMockTable() is called. tableName, +columnNames, and columnTypes are required. columnNames and columnTypes are expected to be pipe-delimited strings. The +columnTypes should have the same count as columnNames and be in the same order. @param tableName The table to be mocked. @@ -177,57 +173,6 @@ subroutine cclut::cclutValidateParameterIsNotEmpty(cclutParameter, cclutParamete return(TRUE) end ;cclut::cclutValidateParameterIsNotEmpty -/** -Adds a constraint to a mock table. The table must already be defined through cclutDefineMockTable(), otherwise an error -will be thrown. This function may not be called after cclutCreateMockTable(). tableName and columnName are required. -If the columnName is not valid for the table specified, an error will be thrown. All constraints for a column should be -present in the columnConstraint field. If a constraint already exists, this function will overwrite it with the new -value. If columnConstraint is blank, the constraint will be removed for the column. The supported constraints can be -seen here: -https://wiki.cerner.com/display/public/1101discernHP/SELECT+INTO+TABLE+Table_Name+Using+Discern+Explorer - -@param tableName - The name of the source table for the mock table to which the constraint will be added. -@param columnName - The column to which the constraint will be applied. -@param columnConstraint - A string of all constraints to be applied to the column. - -Example: -call cclutAddMockConstraint("person", "name_last", "not null unique") -**/ -subroutine cclutAddMockConstraint(cclutTableName, cclutColumnName, cclutColumnConstraint) - declare CCLUT_TABLE_NAME = vc with protect, constant(cnvtupper(cclutTableName)) - declare CCLUT_COLUMN_NAME = vc with protect, constant(cnvtupper(cclutColumnName)) - declare CCLUT_COLUMN_CONSTRAINT = vc with protect, constant(cnvtupper(cclutColumnConstraint)) - declare cclutMockTablePos = i4 with protect, noconstant(0) - declare cclutMockColumnPos = i4 with protect, noconstant(0) - - ;Validate inbound parameters - if (cclut::cclutValidateParameterIsNotEmpty(CCLUT_TABLE_NAME, "tableName") = FALSE) - return - endif - if (cclut::cclutValidateParameterIsNotEmpty(CCLUT_COLUMN_NAME, "columnName") = FALSE) - return - endif - - ;Validate that the table exists and has not been created - set cclutMockTablePos = cclut::cclutValidateMockTableIsDefined(CCLUT_TABLE_NAME) - if (cclutMockTablePos > 0 and cclut::cclutValidateMockTableIsNotCreated(CCLUT_TABLE_NAME)) - ;Validate that the column exists on the table. - set cclutMockColumnPos = cclut::cclutGetMockColumnIndex(CCLUT_TABLE_NAME, CCLUT_COLUMN_NAME) - if (cclutMockColumnPos < 1) - call cclexception(100, "E", concat("cclutAddMockConstraint(", CCLUT_TABLE_NAME, ") - ", CCLUT_COLUMN_NAME, - " is not mocked on table.")) - return - endif - - ;Set the constraint - set cclut_mockTables->tables[cclutMockTablePos].columns[cclutMockColumnPos].columnConstraint = - CCLUT_COLUMN_CONSTRAINT - endif -end ;cclutAddMockConstraint - /** Helper function to validate if the supplied cclutTableName has been defined as a mock in cclut_mockTables. cclutTableName is the name of the table to validate. The subroutine returns the index within the array if it is defined @@ -412,8 +357,6 @@ subroutine cclutCreateMockTable(cclutTableName) declare cclutMockIndexIndex = i4 with protect, noconstant(0) declare cclutParserText = vc with protect, noconstant("") declare cclutColumnName = vc with protect, noconstant("") - declare cclutConstraint = vc with protect, noconstant("") - declare cclutParserConstraint = vc with protect, noconstant(" ") ;Validate inbound parameter if (cclut::cclutValidateParameterIsNotEmpty(CCLUT_TABLE_NAME, "tableName") = FALSE) @@ -436,19 +379,11 @@ subroutine cclutCreateMockTable(cclutTableName) set cclutParserText = concat(cclutParserText, " ,") endif set cclutColumnName = cclut_mockTables->tables[cclutMockTablePos].columns[cclutMockColumnIndex].columnName - set cclutConstraint = cclut_mockTables->tables[cclutMockTablePos].columns[cclutMockColumnIndex].columnConstraint set cclutParserText = concat(cclutParserText, ^ ^, cclutColumnName, ^ = type("^, cclut_mockTables->tables[cclutMockTablePos].columns[cclutMockColumnIndex].columnType, ^")^) - if (cclut::cclutIsEmpty(cclutConstraint) = FALSE) - set cclutParserConstraint = - concat(cclutParserConstraint, ^ , constraint(^, cclutColumnName, ^,"^, cclutConstraint, ^")^) - endif endfor set cclutParserText = concat(cclutParserText, ^ with organization="P"^) - if (cclutParserConstraint > " ") - set cclutParserText = concat(cclutParserText, cclutParserConstraint) - endif for (cclutMockIndexIndex = 1 to size(cclut_mockTables->tables[cclutMockTablePos].indexes, 5)) set cclutParserText = concat(cclutParserText, evaluate(cclut_mockTables->tables[cclutMockTablePos].indexes[cclutMockIndexIndex].isUnique, TRUE, diff --git a/cclunit-framework-source/src/test/ccl/ut_cclut_execute_test_case.inc b/cclunit-framework-source/src/test/ccl/ut_cclut_execute_test_case.inc index fdd5cf4..9ffb2d0 100644 --- a/cclunit-framework-source/src/test/ccl/ut_cclut_execute_test_case.inc +++ b/cclunit-framework-source/src/test/ccl/ut_cclut_execute_test_case.inc @@ -191,67 +191,67 @@ subroutine validateListingXml(xml) ; call echo(build2("listingXml = ", xml)) call cclutAssertEndsWith(CURREF, "validate listingXml", -~187918801881181418151816<\ -NBR>1882188318841885<\ -![CDATA[*/]]>18861887\ -1888188918901891189218931894\ -189518961897\ -18981899\ -190019011902190319041905190619071908190919101911191219131914\ -1915\ -1916191719181919\ -1920192119221923192419251926<\ -/LINE>19271928<\ -/LINE>19291930<\ -/TEXT>1931193219331934<\ -/LINE>193519361937<\ -NBR>19381939194\ -01941194219431944194519461947<\ -![CDATA[ endif]]>1948194919501951\ -19521953195419551956\ -19571958<\ -/LINE>1959196019611962196319641965<\ -/LINE>1966~, xml) +NBR>1817181818191820<\ +![CDATA[*/]]>18211822\ +1823182418251826182718281829\ +183018311832\ +18331834\ +183518361837183818391840184118421843184418451846184718481849\ +1850\ +1851185218531854\ +1855185618571858185918601861<\ +/LINE>18621863<\ +/LINE>18641865<\ +/TEXT>1866186718681869<\ +/LINE>187018711872<\ +NBR>18731874187\ +51876187718781879188018811882<\ +![CDATA[ endif]]>1883188418851886\ +18871888188918901891\ +18921893<\ +/LINE>1894189518961897189818991900<\ +/LINE>1901~, xml) end ;;;validateListingXml @@ -299,7 +299,7 @@ subroutine validateResultsXml(xml) call cclutAssertI4Equal(CURREF, "validate assert found 1.1", foundInd, TRUE) set lineNbr = cclut::retrieveXmlContent(xmlAssert, "lineNumber", 1, foundInd) call cclutAssertI4Equal(CURREF, "validate line number found 1.1", foundInd, TRUE) - call cclutAssertVCEqual(CURREF, "validate line number 1.1", lineNbr, "1901") + call cclutAssertVCEqual(CURREF, "validate line number 1.1", lineNbr, "1836") set assertContext = cclut::retrieveXmlContent(xmlAssert, "context", 1, foundInd) call cclutAssertI4Equal(CURREF, "validate assert context found 1.1", foundInd, TRUE) call cclutAssertVCEqual(CURREF, "validate assert context 1.1", assertContext, "setupOnce executed") @@ -328,7 +328,7 @@ subroutine validateResultsXml(xml) call cclutAssertI4Equal(CURREF, "validate assert found 2.1", foundInd, TRUE) set lineNbr = cclut::retrieveXmlContent(xmlAssert, "lineNumber", 1, foundInd) call cclutAssertI4Equal(CURREF, "validate line number found 2.1", foundInd, TRUE) - call cclutAssertVCEqual(CURREF, "validate line number 2.1", lineNbr, "1921") + call cclutAssertVCEqual(CURREF, "validate line number 2.1", lineNbr, "1856") set assertContext = cclut::retrieveXmlContent(xmlAssert, "context", 1, foundInd) call cclutAssertI4Equal(CURREF, "validate assert context found 2.1", foundInd, TRUE) call cclutAssertVCEqual(CURREF, "validate assert context 2.1", assertContext, "setup executed") @@ -344,7 +344,7 @@ subroutine validateResultsXml(xml) call cclutAssertI4Equal(CURREF, "validate assert found 2.2", foundInd, TRUE) set lineNbr = cclut::retrieveXmlContent(xmlAssert, "lineNumber", 1, foundInd) call cclutAssertI4Equal(CURREF, "validate line number found 2.2", foundInd, TRUE) - call cclutAssertVCEqual(CURREF, "validate line number 2.2", lineNbr, "1941") + call cclutAssertVCEqual(CURREF, "validate line number 2.2", lineNbr, "1876") set assertContext = cclut::retrieveXmlContent(xmlAssert, "context", 1, foundInd) call cclutAssertI4Equal(CURREF, "validate assert context found 2.2", foundInd, TRUE) call cclutAssertVCEqual(CURREF, "validate assert context 2.2", assertContext, "testOne executed") @@ -361,7 +361,7 @@ subroutine validateResultsXml(xml) call cclutAssertI4Equal(CURREF, "validate assert found 2.3", foundInd, TRUE) set lineNbr = cclut::retrieveXmlContent(xmlAssert, "lineNumber", 1, foundInd) call cclutAssertI4Equal(CURREF, "validate line number found 2.3", foundInd, TRUE) - call cclutAssertVCEqual(CURREF, "validate line number 2.3", lineNbr, "1931") + call cclutAssertVCEqual(CURREF, "validate line number 2.3", lineNbr, "1866") set assertContext = cclut::retrieveXmlContent(xmlAssert, "context", 1, foundInd) call cclutAssertI4Equal(CURREF, "validate assert context found 2.3", foundInd, TRUE) call cclutAssertVCEqual(CURREF, "validate assert context 2.3", assertContext, "teardown executed") @@ -407,7 +407,7 @@ subroutine validateResultsXml(xml) call cclutAssertI4Equal(CURREF, "validate assert found 5.1", foundInd, TRUE) set lineNbr = cclut::retrieveXmlContent(xmlAssert, "lineNumber", 1, foundInd) call cclutAssertI4Equal(CURREF, "validate line number found 5.1", foundInd, TRUE) - call cclutAssertVCEqual(CURREF, "validate line number 5.1", lineNbr, "1911") + call cclutAssertVCEqual(CURREF, "validate line number 5.1", lineNbr, "1846") set assertContext = cclut::retrieveXmlContent(xmlAssert, "context", 1, foundInd) call cclutAssertI4Equal(CURREF, "validate assert context found 5.1", foundInd, TRUE) call cclutAssertVCEqual(CURREF, "validate assert context 5.1", assertContext, "teardownOnce executed") diff --git a/cclunit-framework-source/src/test/ccl/ut_cclut_execute_test_case_file.inc b/cclunit-framework-source/src/test/ccl/ut_cclut_execute_test_case_file.inc index 3a66548..856453c 100644 --- a/cclunit-framework-source/src/test/ccl/ut_cclut_execute_test_case_file.inc +++ b/cclunit-framework-source/src/test/ccl/ut_cclut_execute_test_case_file.inc @@ -214,67 +214,67 @@ subroutine validateListingXml(xml) ; call echo(build2("listingXml = ", xml)) call cclutAssertEndsWith(CURREF, "validate listingXml", -~187918801881181418151816<\ -NBR>1882188318841885<\ -![CDATA[*/]]>18861887\ -1888188918901891189218931894\ -189518961897\ -18981899\ -190019011902190319041905190619071908190919101911191219131914\ -1915\ -1916191719181919\ -1920192119221923192419251926<\ -/LINE>19271928<\ -/LINE>19291930<\ -/TEXT>1931193219331934<\ -/LINE>193519361937<\ -NBR>19381939194\ -01941194219431944194519461947<\ -![CDATA[ endif]]>1948194919501951\ -19521953195419551956\ -19571958<\ -/LINE>1959196019611962196319641965<\ -/LINE>1966~, xml) +NBR>1817181818191820<\ +![CDATA[*/]]>18211822\ +1823182418251826182718281829\ +183018311832\ +18331834\ +183518361837183818391840184118421843184418451846184718481849\ +1850\ +1851185218531854\ +1855185618571858185918601861<\ +/LINE>18621863<\ +/LINE>18641865<\ +/TEXT>1866186718681869<\ +/LINE>187018711872<\ +NBR>18731874187\ +51876187718781879188018811882<\ +![CDATA[ endif]]>1883188418851886\ +18871888188918901891\ +18921893<\ +/LINE>1894189518961897189818991900<\ +/LINE>1901~, xml) end ;;;validateListingXml @@ -319,7 +319,7 @@ subroutine validateResultsXml(xml, legacyFormat) call cclutAssertI4Equal(CURREF, "validate assert found 1.1", foundInd, TRUE) set lineNbr = cclut::retrieveXmlContent(xmlAssert, "lineNumber", 1, foundInd) call cclutAssertI4Equal(CURREF, "validate line number found 1.1", foundInd, TRUE) - call cclutAssertVCEqual(CURREF, "validate line number 1.1", lineNbr, "1901") + call cclutAssertVCEqual(CURREF, "validate line number 1.1", lineNbr, "1836") set assertContext = cclut::retrieveXmlContent(xmlAssert, "context", 1, foundInd) call cclutAssertI4Equal(CURREF, "validate assert context found 1.1", foundInd, TRUE) call cclutAssertVCEqual(CURREF, "validate assert context 1.1", assertContext, "setupOnce executed") @@ -352,7 +352,7 @@ subroutine validateResultsXml(xml, legacyFormat) call cclutAssertI4Equal(CURREF, "validate assert found 2.1", foundInd, TRUE) set lineNbr = cclut::retrieveXmlContent(xmlAssert, "lineNumber", 1, foundInd) call cclutAssertI4Equal(CURREF, "validate line number found 2.1", foundInd, TRUE) - call cclutAssertVCEqual(CURREF, "validate line number 2.1", lineNbr, "1921") + call cclutAssertVCEqual(CURREF, "validate line number 2.1", lineNbr, "1856") set assertContext = cclut::retrieveXmlContent(xmlAssert, "context", 1, foundInd) call cclutAssertI4Equal(CURREF, "validate assert context found 2.1", foundInd, TRUE) call cclutAssertVCEqual(CURREF, "validate assert context 2.1", assertContext, "setup executed") @@ -372,7 +372,7 @@ subroutine validateResultsXml(xml, legacyFormat) call cclutAssertI4Equal(CURREF, "validate assert found 2.2", foundInd, TRUE) set lineNbr = cclut::retrieveXmlContent(xmlAssert, "lineNumber", 1, foundInd) call cclutAssertI4Equal(CURREF, "validate line number found 2.2", foundInd, TRUE) - call cclutAssertVCEqual(CURREF, "validate line number 2.2", lineNbr, "1941") + call cclutAssertVCEqual(CURREF, "validate line number 2.2", lineNbr, "1876") set assertContext = cclut::retrieveXmlContent(xmlAssert, "context", 1, foundInd) call cclutAssertI4Equal(CURREF, "validate assert context found 2.2", foundInd, TRUE) call cclutAssertVCEqual(CURREF, "validate assert context 2.2", assertContext, "testOne executed") @@ -393,7 +393,7 @@ subroutine validateResultsXml(xml, legacyFormat) call cclutAssertI4Equal(CURREF, "validate assert found 2.3", foundInd, TRUE) set lineNbr = cclut::retrieveXmlContent(xmlAssert, "lineNumber", 1, foundInd) call cclutAssertI4Equal(CURREF, "validate line number found 2.3", foundInd, TRUE) - call cclutAssertVCEqual(CURREF, "validate line number 2.3", lineNbr, "1931") + call cclutAssertVCEqual(CURREF, "validate line number 2.3", lineNbr, "1866") set assertContext = cclut::retrieveXmlContent(xmlAssert, "context", 1, foundInd) call cclutAssertI4Equal(CURREF, "validate assert context found 2.3", foundInd, TRUE) call cclutAssertVCEqual(CURREF, "validate assert context 2.3", assertContext, "teardown executed") @@ -443,7 +443,7 @@ subroutine validateResultsXml(xml, legacyFormat) call cclutAssertI4Equal(CURREF, "validate assert found 5.1", foundInd, TRUE) set lineNbr = cclut::retrieveXmlContent(xmlAssert, "lineNumber", 1, foundInd) call cclutAssertI4Equal(CURREF, "validate line number found 5.1", foundInd, TRUE) - call cclutAssertVCEqual(CURREF, "validate line number 5.1", lineNbr, "1911") + call cclutAssertVCEqual(CURREF, "validate line number 5.1", lineNbr, "1846") set assertContext = cclut::retrieveXmlContent(xmlAssert, "context", 1, foundInd) call cclutAssertI4Equal(CURREF, "validate assert context found 5.1", foundInd, TRUE) call cclutAssertVCEqual(CURREF, "validate assert context 5.1", assertContext, "teardownOnce executed") diff --git a/cclunit-framework-source/src/test/ccl/ut_cclut_mock_table.inc b/cclunit-framework-source/src/test/ccl/ut_cclut_mock_table.inc index 371943d..b8591e6 100644 --- a/cclunit-framework-source/src/test/ccl/ut_cclut_mock_table.inc +++ b/cclunit-framework-source/src/test/ccl/ut_cclut_mock_table.inc @@ -31,22 +31,16 @@ subroutine test_cclutDefineMockTable_happy(null) call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_happy 007", cclut_mockTables->tables[1].columns[1].columnType, "F8") call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_happy 008", - cclut_mockTables->tables[1].columns[1].columnConstraint, "") - call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_happy 009", cclut_mockTables->tables[1].columns[2].columnName, "SAMPLE_TABLE_TEXT") - call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_happy 010", + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_happy 009", cclut_mockTables->tables[1].columns[2].columnType, "VC") - call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_happy 011", - cclut_mockTables->tables[1].columns[2].columnConstraint, "") - call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_happy 012", + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_happy 010", cclut_mockTables->tables[1].columns[3].columnName, "SAMPLE_TABLE_DATE") - call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_happy 013", + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_happy 011", cclut_mockTables->tables[1].columns[3].columnType, "DQ8") - call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_happy 014", - cclut_mockTables->tables[1].columns[3].columnConstraint, "") - call cclutAsserti4Equal(CURREF, "test_cclutDefineMockTable_happy 015", size(cclut_mockTables->tables[1].indexes, 5), + call cclutAsserti4Equal(CURREF, "test_cclutDefineMockTable_happy 012", size(cclut_mockTables->tables[1].indexes, 5), 0) - call cclutAsserti4Equal(CURREF, "test_cclutDefineMockTable_happy 016", cclut_mockTables->tables[1].isFinalized, FALSE) + call cclutAsserti4Equal(CURREF, "test_cclutDefineMockTable_happy 013", cclut_mockTables->tables[1].isFinalized, FALSE) end ;test_cclutDefineMockTable_happy /* test_cclutDefineMockTable_different_cases **************************************************************** @@ -72,22 +66,16 @@ subroutine test_cclutDefineMockTable_different_cases(null) call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_different_cases 007", cclut_mockTables->tables[1].columns[1].columnType, "F8") call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_different_cases 008", - cclut_mockTables->tables[1].columns[1].columnConstraint, "") - call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_different_cases 009", cclut_mockTables->tables[1].columns[2].columnName, "SAMPLE_TABLE_TEXT") - call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_different_cases 010", + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_different_cases 009", cclut_mockTables->tables[1].columns[2].columnType, "VC") - call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_different_cases 011", - cclut_mockTables->tables[1].columns[2].columnConstraint, "") - call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_different_cases 012", + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_different_cases 010", cclut_mockTables->tables[1].columns[3].columnName, "SAMPLE_TABLE_DATE") - call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_different_cases 013", + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_different_cases 011", cclut_mockTables->tables[1].columns[3].columnType, "DQ8") - call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_different_cases 014", - cclut_mockTables->tables[1].columns[3].columnConstraint, "") - call cclutAsserti4Equal(CURREF, "test_cclutDefineMockTable_different_cases 015", + call cclutAsserti4Equal(CURREF, "test_cclutDefineMockTable_different_cases 012", size(cclut_mockTables->tables[1].indexes, 5), 0) - call cclutAsserti4Equal(CURREF, "test_cclutDefineMockTable_different_cases 016", + call cclutAsserti4Equal(CURREF, "test_cclutDefineMockTable_different_cases 013", cclut_mockTables->tables[1].isFinalized, FALSE) end ;test_cclutDefineMockTable_different_cases @@ -114,22 +102,16 @@ subroutine test_cclutDefineMockTable_existing_mock(null) call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_existing_mock 007", cclut_mockTables->tables[1].columns[1].columnType, "I4") call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_existing_mock 008", - cclut_mockTables->tables[1].columns[1].columnConstraint, "") - call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_existing_mock 009", cclut_mockTables->tables[1].columns[2].columnName, "NEW_TABLE_TEXT") - call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_existing_mock 010", + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_existing_mock 009", cclut_mockTables->tables[1].columns[2].columnType, "C100") - call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_existing_mock 011", - cclut_mockTables->tables[1].columns[2].columnConstraint, "") - call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_existing_mock 012", + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_existing_mock 010", cclut_mockTables->tables[1].columns[3].columnName, "NEW_TABLE_DATE") - call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_existing_mock 013", + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_existing_mock 011", cclut_mockTables->tables[1].columns[3].columnType, "DM12") - call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_existing_mock 014", - cclut_mockTables->tables[1].columns[3].columnConstraint, "") - call cclutAsserti4Equal(CURREF, "test_cclutDefineMockTable_existing_mock 015", + call cclutAsserti4Equal(CURREF, "test_cclutDefineMockTable_existing_mock 012", size(cclut_mockTables->tables[1].indexes, 5), 0) - call cclutAsserti4Equal(CURREF, "test_cclutDefineMockTable_existing_mock 016", + call cclutAsserti4Equal(CURREF, "test_cclutDefineMockTable_existing_mock 013", cclut_mockTables->tables[1].isFinalized, FALSE) end ;test_cclutDefineMockTable_existing_mock @@ -192,22 +174,16 @@ subroutine test_cclutDefineMockTable_existing_created_mock(null) call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_existing_created_mock 011", cclut_mockTables->tables[1].columns[1].columnType, "I4") call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_existing_created_mock 012", - cclut_mockTables->tables[1].columns[1].columnConstraint, "") - call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_existing_created_mock 013", cclut_mockTables->tables[1].columns[2].columnName, "NEW_TABLE_TEXT") - call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_existing_created_mock 014", + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_existing_created_mock 013", cclut_mockTables->tables[1].columns[2].columnType, "C100") - call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_existing_created_mock 015", - cclut_mockTables->tables[1].columns[2].columnConstraint, "") - call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_existing_created_mock 016", + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_existing_created_mock 014", cclut_mockTables->tables[1].columns[3].columnName, "NEW_TABLE_DATE") - call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_existing_created_mock 017", + call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_existing_created_mock 015", cclut_mockTables->tables[1].columns[3].columnType, "DM12") - call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_existing_created_mock 018", - cclut_mockTables->tables[1].columns[3].columnConstraint, "") - call cclutAsserti4Equal(CURREF, "test_cclutDefineMockTable_existing_created_mock 019", + call cclutAsserti4Equal(CURREF, "test_cclutDefineMockTable_existing_created_mock 016", size(cclut_mockTables->tables[1].indexes, 5), 0) - call cclutAsserti4Equal(CURREF, "test_cclutDefineMockTable_existing_created_mock 020", + call cclutAsserti4Equal(CURREF, "test_cclutDefineMockTable_existing_created_mock 017", cclut_mockTables->tables[1].isFinalized, FALSE) end ;test_cclutDefineMockTable_existing_created_mock @@ -347,105 +323,6 @@ subroutine test_cclutDefineMockTable_duplicate_column_name(null) call cclutAssertvcEqual(CURREF, "test_cclutDefineMockTable_duplicate_column_name 002", mockTable, "") end ;test_cclutDefineMockTable_duplicate_column_name -;********************************************************************************************************************************** -;** cclutAddMockConstraint -;********************************************************************************************************************************** -/* test_cclutAddMockConstraint_happy ************************************************************************ -* Scenario: Adds a mock constraint to a table that has already been defined with cclutDefineMockTable * -************************************************************************************************************/ -subroutine test_cclutAddMockConstraint_happy(null) - call cclutDefineMockTable("sample_table", "sample_table_id|sample_table_text|sample_table_date", "f8|vc|dq8") - call cclutDefineMockTable("sample_table_2", "sample_table_2_id|sample_table_2_text|sample_table_2_date", - "f8|vc|dq8") - call cclutDefineMockTable("sample_table_3", "sample_table_3_id|sample_table_3_text|sample_table_3_date", - "f8|vc|dq8") - - call cclutAddMockConstraint("sample_table_2", "sample_table_2_text", "not null unique") - - call cclutAssertvcEqual(CURREF, "test_cclutAddMockConstraint_happy 001", - cclut_mockTables->tables[2].columns[2].columnConstraint, "NOT NULL UNIQUE") -end ;test_cclutAddMockConstraint_happy - -/* test_cclutAddMockConstraint_missing_tableName ************************************************************ -* Scenario: Throws an error when an empty tableName is supplied to the function (after trimming) * -************************************************************************************************************/ -subroutine test_cclutAddMockConstraint_missing_tableName(null) - declare errorMessage = vc with protect, noconstant("") - declare errorCode = i4 with protect, noconstant(0) - call cclutAddMockConstraint(" ", "sample_table_text", "not null unique") - - set errorCode = error(errorMessage, 0) - - call cclutAssertVcOperator(CURREF, "test_cclutAddMockConstraint_missing_tableName 001", trim(errorMessage, 3), - "regexplike", concat("%CCL-E-392-PRG_[0-9]+_[0-9]+\([^)]+\)[0-9]+:[0-9]+\{CCLEXCEPTION\(\)\}Exception\(100\):", - " cclutValidateParameterIsNotEmpty\(\) - tableName is a required field.")) -end ;test_cclutAddMockConstraint_missing_tableName - -/* test_cclutAddMockConstraint_missing_columnName *********************************************************** -* Scenario: Throws an error when an empty columnName is supplied to the function (after trimming) * -************************************************************************************************************/ -subroutine test_cclutAddMockConstraint_missing_columnName(null) - declare errorMessage = vc with protect, noconstant("") - declare errorCode = i4 with protect, noconstant(0) - call cclutAddMockConstraint("sample_table", " ", "not null unique") - - set errorCode = error(errorMessage, 0) - - call cclutAssertVcOperator(CURREF, "test_cclutAddMockConstraint_missing_columnName 001", trim(errorMessage, 3), - "regexplike", concat("%CCL-E-392-PRG_[0-9]+_[0-9]+\([^)]+\)[0-9]+:[0-9]+\{CCLEXCEPTION\(\)\}Exception\(100\):", - " cclutValidateParameterIsNotEmpty\(\) - columnName is a required field.")) -end ;test_cclutAddMockConstraint_missing_columnName - -/* test_cclutAddMockConstraint_unmocked_table *************************************************************** -* Scenario: Throws an error when the tableName specified has not been mocked through cclutDefineMockTable * -************************************************************************************************************/ -subroutine test_cclutAddMockConstraint_unmocked_table(null) - declare errorMessage = vc with protect, noconstant("") - declare errorCode = i4 with protect, noconstant(0) - call cclutAddMockConstraint("sample_table", "sample_table_text", "not null unique") - - set errorCode = error(errorMessage, 0) - - call cclutAssertVcOperator(CURREF, "test_cclutAddMockConstraint_unmocked_table 001", trim(errorMessage, 3), - "regexplike", concat("%CCL-E-392-PRG_[0-9]+_[0-9]+\([^)]+\)[0-9]+:[0-9]+\{CCLEXCEPTION\(\)\}Exception\(100\):", - " cclutValidateMockTableIsDefined\(SAMPLE_TABLE\) - Table has not been mocked.")) -end ;test_cclutAddMockConstraint_unmocked_table - -/* test_cclutAddMockConstraint_created_table **************************************************************** -* Scenario: Throws an error when the tableName specified has already been created * -************************************************************************************************************/ -subroutine test_cclutAddMockConstraint_created_table(null) - call cclutDefineMockTable("sample_table", "sample_table_id|sample_table_text|sample_table_date", "f8|vc|dq8") - call cclutCreateMockTable("sample_table") - - declare errorMessage = vc with protect, noconstant("") - declare errorCode = i4 with protect, noconstant(0) - call cclutAddMockConstraint("sample_table", "sample_table_text", "not null unique") - - set errorCode = error(errorMessage, 0) - - call cclutAssertVcOperator(CURREF, "test_cclutAddMockConstraint_created_table 001", trim(errorMessage, 3), - "regexplike", concat("%CCL-E-392-PRG_[0-9]+_[0-9]+\([^)]+\)[0-9]+:[0-9]+\{CCLEXCEPTION\(\)\}Exception\(100\): ", - "cclutValidateMockTableIsNotCreated\(SAMPLE_TABLE\) - Table has already been created.")) -end ;test_cclutAddMockConstraint_created_table - -/* test_cclutAddMockConstraint_invalid_column *************************************************************** -* Scenario: Throws an error when the column is not a valid column on the mocked table * -************************************************************************************************************/ -subroutine test_cclutAddMockConstraint_invalid_column(null) - call cclutDefineMockTable("sample_table", "sample_table_id|sample_table_text|sample_table_date", "f8|vc|dq8") - - declare errorMessage = vc with protect, noconstant("") - declare errorCode = i4 with protect, noconstant(0) - call cclutAddMockConstraint("sample_table", "wrong_column", "not null unique") - - set errorCode = error(errorMessage, 0) - - call cclutAssertVcOperator(CURREF, "test_cclutAddMockConstraint_invalid_column 001", trim(errorMessage, 3), - "regexplike", concat("%CCL-E-392-PRG_[0-9]+_[0-9]+\([^)]+\)[0-9]+:[0-9]+\{CCLEXCEPTION\(\)\}Exception\(100\):", - " cclutAddMockConstraint\(SAMPLE_TABLE\) - WRONG_COLUMN is not mocked on table.")) -end ;test_cclutAddMockConstraint_invalid_column - ;********************************************************************************************************************************** ;** cclutAddMockIndex ;********************************************************************************************************************************** From db8d4b43d30124845252c455ac62e66d18b3124f Mon Sep 17 00:00:00 2001 From: cernertrevor Date: Thu, 14 Feb 2019 11:40:04 -0600 Subject: [PATCH 6/7] Merge branch 'master' of https://github.com/cerner/cclunit-framework into ccl-mock # Conflicts: # cclunit-framework-source/src/test/ccl/ut_cclut_execute_test_case.inc # cclunit-framework-source/src/test/ccl/ut_cclut_execute_test_case_file.inc --- cclunit-framework-source/doc/CCLUTGUIDANCE.md | 6 +- cclunit-framework-source/doc/CCLUTMOCKING.md | 62 ++++++-- .../src/main/resources/cclutmock.inc | 9 +- .../src/main/resources/cclutmock_table.inc | 8 +- ...cclut_execute_program_with_mocks_happy.prg | 8 +- .../test/ccl/ut_cclut_execute_test_case.inc | 132 +++++++++--------- .../ccl/ut_cclut_execute_test_case_file.inc | 132 +++++++++--------- .../src/test/ccl/ut_cclut_mock.inc | 48 ++++++- 8 files changed, 244 insertions(+), 161 deletions(-) diff --git a/cclunit-framework-source/doc/CCLUTGUIDANCE.md b/cclunit-framework-source/doc/CCLUTGUIDANCE.md index c88addc..9569426 100644 --- a/cclunit-framework-source/doc/CCLUTGUIDANCE.md +++ b/cclunit-framework-source/doc/CCLUTGUIDANCE.md @@ -18,11 +18,11 @@ An illustration of the concept can be seen [here](./examples/basic_example.inc) ## CCL Mocks -In general, there are two ways to mock objects in CCL unit tests. Generally speaking, use "with replace" to mock things that are defined outside the script or called directly by the script (CCL subroutines, UARs, other scripts), and use "with curnamespace" to mock subroutines executed by the subroutine being tested. When using "with curnamespace", add the PUBLIC namespace to the real thing and use an alternate namespace to define an override. Execute the script using 'with curnamespace = "\"'. In practice, it is convenient to use the name of the test case for the alternate namespace. +In general, there are two ways to mock objects in CCL unit tests. Generally speaking, use "with replace" to mock things that are defined outside the script or called directly by the script (CCL subroutines, UARs, other scripts), and use "with curnamespace" to mock subroutines executed by the subroutine being tested. When using "with curnamespace", add the PUBLIC namespace to the real thing and use an alternate namespace to define an override. Execute the script using 'with curnamespace = "\"'. In practice, it is convenient to use the name of the test for the alternate namespace. -The CCL Unit Testing framework provides an abstraction for creating mocks. The purpose is to help make it easier to define mock tables and other mock objects to be used when executing a script. Details on the API can be found at [CCLUTMOCKING.md](../CCLUTMOCKING.md) +The CCL Unit Testing framework provides an abstraction for creating mocks. The purpose is to make it easier to define mock tables and other mock objects to be used when executing a script. Details on the API can be found at [CCLUTMOCKING.md](../CCLUTMOCKING.md) -[These unit tests](./examples/mocking_api.inc) demonstrate how to accomplish a basic "with replace" while using the CCL Unit Testing framework's mocking API. They test a script named "the_script" and executes a program called "other_script". They test for scenarios where other_script returns 0 items, more than 5 items, and a failed ("F") status. +[These unit tests](./examples/mocking_api.inc) demonstrate how to accomplish a basic "with replace" while using the CCL Unit Testing framework's mocking API. They leverage a script named "mock_other_script" to mock the behavior of "other_script" and test "the_script" in scenarios where "other_script" returns 0 items, more than 5 items and a failed ("F") status. There are other variations on this. For example, you could put asserts within mock_other_script itself. Additionally, other_script might generate its own reply structure, so you would want to do the same in mock_other_script. diff --git a/cclunit-framework-source/doc/CCLUTMOCKING.md b/cclunit-framework-source/doc/CCLUTMOCKING.md index bde5c6e..b50e968 100644 --- a/cclunit-framework-source/doc/CCLUTMOCKING.md +++ b/cclunit-framework-source/doc/CCLUTMOCKING.md @@ -2,7 +2,9 @@ # CCL Unit Mocking The CCL Unit Test framework's mocking API is available for consumers to mock certain objects to better isolate unit tests from outside variability and provide more control over the scenarios under which unit tests are run. The API provides ways to mock tables, variables, subroutines, scripts, etc. -**\*CAUTION\*** **The CCL Unit Mocking framework should only be used in non-production environments. Table mocking creates new tables against an Oracle instance for the lifetime of the test. Because the DDL is generated in a dynamic way, it is possible through inappropriate use of the framework to affect the actual table. Please only use the documented API.** +**\*CAUTION\*** **The CCL Unit Mocking framework should only be used in non-production environments. Table mocking creates new tables against an Oracle instance for the lifetime of the test. Because the DDL is generated in a dynamic way, it is possible through inappropriate use of the framework to affect an actual table. Please only use the documented API.** + +In the rare event that CCL crashes midway through a test or another abnormal abort occurs (e.g. as the result of an infinite loop in a test), it may be necessary to clean up any tables that the framework could not. All tables created by the CCL Unit Test framework will be prepended with "CUST_CCLUT_". ## Table of Contents [API](#api) @@ -28,11 +30,25 @@ cclutExecuteProgramWithMocks.     The namespace under which to execute the program. Example: -call cclutExecuteProgramWithMocks("ccl_my_program", "\^MINE^, 1.0, ^string parameter^", "MYNAMESPACE") +``` +call cclutExecuteProgramWithMocks("ccl_my_program") +call cclutExecuteProgramWithMocks("ccl_my_program", "^MINE^, 1.0, ^string parameter^") +call cclutExecuteProgramWithMocks("ccl_my_program", "", "MYNAMESPACE") +call cclutExecuteProgramWithMocks("ccl_my_program", "^MINE^, 1.0, ^string parameter^", "MYNAMESPACE") +``` + +**cclutRemoveAllMocks** + +Removes all mock implementations and mock tables that have been added through the mocking APIs. This should be called at the completion of a test case to clean up all mocks. + +Example: +``` +call cclutRemoveAllMocks(null) +``` **cclutDefineMockTable(tableName = vc, fieldNames = vc, fieldTypes = vc)** -Defines a mock table structure that can be created for use within a program. This is the first function to be called in the process of mocking a table. It must be called before cclutAddMockIndex() and cclutCreateMockTable() can be called. The table will not be mocked in cclutExecuteProgramWithMocks() unless cclutCreateMockTable() is called. This function can be called for the same table after cclutCreateMockTable() in order to redefine it; however, the existing mocked table will be dropped and cclutCreateMockTable() will need to be called again to recreate it with the new defintion. tableName, columnNames, and columnTypes are required. columnNames and columnTypes are expected to be pipe-delimited strings. The columnTypes should have the same count as columnNames and be in the same order. +Defines a mock table structure that can be created for use within a program. This is the first function to be called in the process of mocking a table. It must be called before cclutAddMockIndex() or cclutCreateMockTable() can be called. The table will not be mocked in cclutExecuteProgramWithMocks() unless finalized by calling cclutCreateMockTable(). This function can be called for the same table after cclutCreateMockTable() in order to redefine it; however, the existing mocked table will be dropped and cclutCreateMockTable() will need to be called again to recreate it with the new defintion. tableName, columnNames, and columnTypes are required. columnNames and columnTypes are expected to be pipe-delimited strings. The columnTypes should have the same count as columnNames and be in the same order. @param tableName     The table to be mocked. @@ -44,7 +60,9 @@ Defines a mock table structure that can be created for use within a program. Th     The name of the mock table (This can be used to select data for testing) Example: +``` call cclutDefineMockTable("person", "person_id|name_last|name_first|birth_dt_tm", "f8|vc|vc|dq8") +``` **cclutAddMockIndex(tableName = vc, columnNames = vc, isUnique = i4)** @@ -58,8 +76,10 @@ Adds an index to a mock table. The table must already be defined through cclutD     TRUE to create a unique index; FALSE to create a non-unique index Example: +``` call cclutAddMockIndex("person", "person_id", TRUE) call cclutAddMockIndex("person", "name_last|name_first", FALSE) +``` **cclutCreateMockTable(tableName = vc)** @@ -69,7 +89,9 @@ Creates a mock table. The table must already be defined through cclutDefineMock     The name of the source table to be mocked. Example: +``` call cclutCreateMockTable("person") +``` **cclutRemoveMockTable(tableName = vc)** @@ -80,14 +102,18 @@ mocked, it will return silently. tableName is required.     The name of the source table that is mocked. Example: +``` call cclutRemoveMockTable("person") +``` **cclutRemoveAllMockTables(null)** Removes all mock tables. Any tables that have already been created will also be dropped. Example: +``` call cclutRemoveAllMockTables(null) +``` **cclutAddMockData(tableName = vc, rowData = vc)** @@ -104,23 +130,26 @@ Supported escape values     A pipe-delimited string of data to be inserted into the mock table. Example: +``` call cclutDefineMockTable("person", "person_id|name_last|name_first|birth_dt_tm", "f8|vc|vc|dq8") call cclutCreateMockTable("person") call cclutAddMockData("person", "1.0|Washington|George|01-JAN-1970 00:00") ;Will add George Washington -call cclutAddMockData("person", "2.0|A\\|d\\\\ams|John|02-FEB-1971 11:11") ;Will add John A|d\ams +call cclutAddMockData("person", "2.0|A\|d\\ams|John|02-FEB-1971 11:11") ;Will add John A|d\ams call cclutAddMockData("person", "3.0|Jefferson|\null|03-MAR-1972 22:22") ;Will add Jefferson (no first name) call cclutAddMockData("person", "4.0|Madison||04-APR-1973 10:33") ;Will add Madison (empty string for first name) +``` **cclutClearMockData(tableName = vc)** -Clears all data from the mock table. This is functionally similar to a truncate. tableName is required. The table -must have been created through cclutCreateMockTable() or else an error will be thrown. +Clears all data from a specified mock table. This is functionally similar to a truncate. tableName is required. The table must have been created through cclutCreateMockTable() or else an error will be thrown. @param tableName     The name of the source table for the mock table to be cleared. Example: +``` call cclutClearMockData("person") +``` **cclutAddMockImplementation(originalName = vc, replaceName = vc)** @@ -132,7 +161,9 @@ Adds a mock implementation to be utilized by cclutExecuteProgramWithMocks. This     The mocked object. Example: +``` call cclutAddMockImplementation("uar_get_code_by", "mock_uar_get_code_by") +``` **cclutRemoveMockImplementation(originalName = vc)** @@ -142,21 +173,18 @@ Removes a mock implementation.     The object that is mocked. Example: +``` call cclutRemoveMockImplementation("uar_get_code_by") +``` **cclutRemoveAllMockImplementations(null)** Removes all mock implementations. Example: +``` call cclutRemoveAllMockImplementations(null) - -**cclutRemoveAllMocks** - -Removes all mock implementations and mock tables that have been added through the cclutAddMockImplementation() and cclutCreateMockTable() APIs. This should be called at the completion of a test suite to clean up all mocks. - -Example: -call cclutRemoveAllMocks(null) +``` ## Implementation Notes 1. For consistency, all mocking functions normalize names (tables, subroutines, records, etc.) to be uppercase. This matches with CCL and Oracle. @@ -279,6 +307,14 @@ Test Code: "") call cclutAssertf8Equal(CURREF, "test_get_people_happy 016", agp_reply->persons[4].birth_dt_tm, cnvtdatetime("04-APR-1973 10:33")) + + ; A contrived example to demonstrate a potential use for the return value from cclutDefineMockTable + select into "nl:" + personCount = count(*) + from (value(mock_table_person) mtp) + head report + call cclutAsserti4Equal(CURREF, "test_get_people_happy 017", cnvtint(personCount), 4) + with nocounter call cclutRemoveAllMocks(null) \ No newline at end of file diff --git a/cclunit-framework-source/src/main/resources/cclutmock.inc b/cclunit-framework-source/src/main/resources/cclutmock.inc index 44fac68..2b14332 100644 --- a/cclunit-framework-source/src/main/resources/cclutmock.inc +++ b/cclunit-framework-source/src/main/resources/cclutmock.inc @@ -12,7 +12,7 @@ declare cclutAddMockImplementation(cclutOriginalName = vc(val), cclutReplaceName = vc(val)) = null with protect declare cclutRemoveMockImplementation(cclutOriginalName = vc(val)) = null with protect declare cclutRemoveAllMockImplementations(null) = null with protect -declare cclutExecuteProgramWithMocks(cclutProgramName = vc(val), cclutParams = vc(val), +declare cclutExecuteProgramWithMocks(cclutProgramName = vc(val), cclutParams = vc(val, " "), cclutNamespace = vc(val, "PUBLIC")) = null with protect declare cclutRemoveAllMocks(null) = null with protect @@ -125,6 +125,9 @@ namespace. The namespace under which to execute the program. Example: +call cclutExecuteProgramWithMocks("ccl_my_program") +call cclutExecuteProgramWithMocks("ccl_my_program", "^MINE^, 1.0, ^string parameter^") +call cclutExecuteProgramWithMocks("ccl_my_program", "", "MYNAMESPACE") call cclutExecuteProgramWithMocks("ccl_my_program", "^MINE^, 1.0, ^string parameter^", "MYNAMESPACE") **/ subroutine cclutExecuteProgramWithMocks(cclutProgramName, cclutParams, cclutNamespace) @@ -172,8 +175,8 @@ subroutine cclutExecuteProgramWithMocks(cclutProgramName, cclutParams, cclutName end ;cclutExecuteProgramWithMocks /** -Removes all mock implementations and mock tables that have been added through the cclutAddMockImplementation() and -cclutCreateMockTable() APIs. This should be called at the completion of a test suite to clean up all mocks. +Removes all mock implementations and mock tables that have been added through the mocking APIs. This should be called +at the completion of a test case to clean up all mocks. Example: call cclutRemoveAllMocks(null) diff --git a/cclunit-framework-source/src/main/resources/cclutmock_table.inc b/cclunit-framework-source/src/main/resources/cclutmock_table.inc index 9c66ceb..c29a5b1 100644 --- a/cclunit-framework-source/src/main/resources/cclutmock_table.inc +++ b/cclunit-framework-source/src/main/resources/cclutmock_table.inc @@ -55,10 +55,10 @@ set cclut_mockTables->markerTime = cnvtint(curtime3) /** Defines a mock table structure that can be created for use within a program. This is the first function to be called in -the process of mocking a table. It must be called before cclutAddMockIndex() and cclutCreateMockTable() can be called. -The table will not be mocked in cclutExecuteProgramWithMocks() unless cclutCreateMockTable() is called. tableName, -columnNames, and columnTypes are required. columnNames and columnTypes are expected to be pipe-delimited strings. The -columnTypes should have the same count as columnNames and be in the same order. +the process of mocking a table. It must be called before cclutAddMockIndex() or cclutCreateMockTable() can be called. +The table will not be mocked in cclutExecuteProgramWithMocks() unless finalized by calling cclutCreateMockTable(). +tableName, columnNames, and columnTypes are required. columnNames and columnTypes are expected to be pipe-delimited +strings. The columnTypes should have the same count as columnNames and be in the same order. @param tableName The table to be mocked. diff --git a/cclunit-framework-source/src/test/ccl/ut_cclut_execute_program_with_mocks_happy.prg b/cclunit-framework-source/src/test/ccl/ut_cclut_execute_program_with_mocks_happy.prg index 014979f..1c6fb33 100644 --- a/cclunit-framework-source/src/test/ccl/ut_cclut_execute_program_with_mocks_happy.prg +++ b/cclunit-framework-source/src/test/ccl/ut_cclut_execute_program_with_mocks_happy.prg @@ -36,8 +36,12 @@ declare public::internalSubroutine(null) = null with protect subroutine (public::internalSubroutine(null) = null with protect) set public_subroutine = 1 - set reply->number_parameter = $1 - set reply->string_parameter = $2 + if (reflect(parameter(1, 0)) > " ") + set reply->number_parameter = $1 + endif + if (reflect(parameter(2, 0)) > " ") + set reply->string_parameter = $2 + endif declare newSize = i4 with protect, noconstant(0) diff --git a/cclunit-framework-source/src/test/ccl/ut_cclut_execute_test_case.inc b/cclunit-framework-source/src/test/ccl/ut_cclut_execute_test_case.inc index 59aeec6..1f9df05 100644 --- a/cclunit-framework-source/src/test/ccl/ut_cclut_execute_test_case.inc +++ b/cclunit-framework-source/src/test/ccl/ut_cclut_execute_test_case.inc @@ -191,67 +191,67 @@ subroutine validateListingXml(xml) declare expectedListing = vc with protect, noconstant("") set expectedListing = -~917918919920921922923924925926927928929\ -930931932933934935936937938<\ -TEXT>939940\ -94194294394494594694794894995\ -0951952953954955\ -956957958<\ -/NBR>959960961962\ -963964965966967968969970971972973974\ -97597697797897998\ -0981982983984985986987988989990991992993994995\ -996\ -997998<\ -NBR>9991000100110021\ -0031004\ -~ +~181718181819<\ +NBR>1820182118221823<\ +![CDATA[*/]]>18241825\ +1826182718281829183018311832\ +183318341835\ +18361837\ +183818391840184118421843184418451846184718481849185018511852\ +1853\ +1854185518561857\ +1858185918601861186218631864<\ +/LINE>18651866<\ +/LINE>18671868<\ +/TEXT>1869187018711872<\ +/LINE>187318741875<\ +NBR>18761877187\ +81879188018811882188318841885<\ +![CDATA[ endif]]>1886188718881889\ +18901891189218931894\ +18951896<\ +/LINE>1897189818991900190119021903<\ +/LINE>1904~ ;The next assert is a maintenance hastle when the cclut_execute_test_case code changes. ;Uncomment the echo statment to get the real value and update expectedListing accordingly. @@ -304,7 +304,7 @@ subroutine validateResultsXml(xml) call cclutAssertI4Equal(CURREF, "validate assert found 1.1", foundInd, TRUE) set lineNbr = cclut::retrieveXmlContent(xmlAssert, "lineNumber", 1, foundInd) call cclutAssertI4Equal(CURREF, "validate line number found 1.1", foundInd, TRUE) - call cclutAssertVCEqual(CURREF, "validate line number 1.1", lineNbr, "939") + call cclutAssertVCEqual(CURREF, "validate line number 1.1", lineNbr, "1839") set assertContext = cclut::retrieveXmlContent(xmlAssert, "context", 1, foundInd) call cclutAssertI4Equal(CURREF, "validate assert context found 1.1", foundInd, TRUE) call cclutAssertVCEqual(CURREF, "validate assert context 1.1", assertContext, "setupOnce executed") @@ -333,7 +333,7 @@ subroutine validateResultsXml(xml) call cclutAssertI4Equal(CURREF, "validate assert found 2.1", foundInd, TRUE) set lineNbr = cclut::retrieveXmlContent(xmlAssert, "lineNumber", 1, foundInd) call cclutAssertI4Equal(CURREF, "validate line number found 2.1", foundInd, TRUE) - call cclutAssertVCEqual(CURREF, "validate line number 2.1", lineNbr, "959") + call cclutAssertVCEqual(CURREF, "validate line number 2.1", lineNbr, "1859") set assertContext = cclut::retrieveXmlContent(xmlAssert, "context", 1, foundInd) call cclutAssertI4Equal(CURREF, "validate assert context found 2.1", foundInd, TRUE) call cclutAssertVCEqual(CURREF, "validate assert context 2.1", assertContext, "setup executed") @@ -349,7 +349,7 @@ subroutine validateResultsXml(xml) call cclutAssertI4Equal(CURREF, "validate assert found 2.2", foundInd, TRUE) set lineNbr = cclut::retrieveXmlContent(xmlAssert, "lineNumber", 1, foundInd) call cclutAssertI4Equal(CURREF, "validate line number found 2.2", foundInd, TRUE) - call cclutAssertVCEqual(CURREF, "validate line number 2.2", lineNbr, "979") + call cclutAssertVCEqual(CURREF, "validate line number 2.2", lineNbr, "1879") set assertContext = cclut::retrieveXmlContent(xmlAssert, "context", 1, foundInd) call cclutAssertI4Equal(CURREF, "validate assert context found 2.2", foundInd, TRUE) call cclutAssertVCEqual(CURREF, "validate assert context 2.2", assertContext, "testOne executed") @@ -366,7 +366,7 @@ subroutine validateResultsXml(xml) call cclutAssertI4Equal(CURREF, "validate assert found 2.3", foundInd, TRUE) set lineNbr = cclut::retrieveXmlContent(xmlAssert, "lineNumber", 1, foundInd) call cclutAssertI4Equal(CURREF, "validate line number found 2.3", foundInd, TRUE) - call cclutAssertVCEqual(CURREF, "validate line number 2.3", lineNbr, "969") + call cclutAssertVCEqual(CURREF, "validate line number 2.3", lineNbr, "1869") set assertContext = cclut::retrieveXmlContent(xmlAssert, "context", 1, foundInd) call cclutAssertI4Equal(CURREF, "validate assert context found 2.3", foundInd, TRUE) call cclutAssertVCEqual(CURREF, "validate assert context 2.3", assertContext, "teardown executed") @@ -412,7 +412,7 @@ subroutine validateResultsXml(xml) call cclutAssertI4Equal(CURREF, "validate assert found 5.1", foundInd, TRUE) set lineNbr = cclut::retrieveXmlContent(xmlAssert, "lineNumber", 1, foundInd) call cclutAssertI4Equal(CURREF, "validate line number found 5.1", foundInd, TRUE) - call cclutAssertVCEqual(CURREF, "validate line number 5.1", lineNbr, "949") + call cclutAssertVCEqual(CURREF, "validate line number 5.1", lineNbr, "1849") set assertContext = cclut::retrieveXmlContent(xmlAssert, "context", 1, foundInd) call cclutAssertI4Equal(CURREF, "validate assert context found 5.1", foundInd, TRUE) call cclutAssertVCEqual(CURREF, "validate assert context 5.1", assertContext, "teardownOnce executed") diff --git a/cclunit-framework-source/src/test/ccl/ut_cclut_execute_test_case_file.inc b/cclunit-framework-source/src/test/ccl/ut_cclut_execute_test_case_file.inc index 3a00a58..8ed800a 100644 --- a/cclunit-framework-source/src/test/ccl/ut_cclut_execute_test_case_file.inc +++ b/cclunit-framework-source/src/test/ccl/ut_cclut_execute_test_case_file.inc @@ -214,67 +214,67 @@ subroutine validateListingXml(xml) declare expectedListing = vc with protect, noconstant("") set expectedListing = -~917918919920921922923924925926927928929\ -930931932933934935936937938<\ -TEXT>939940\ -94194294394494594694794894995\ -0951952953954955\ -956957958<\ -/NBR>959960961962\ -963964965966967968969970971972973974\ -97597697797897998\ -0981982983984985986987988989990991992993994995\ -996\ -997998<\ -NBR>9991000100110021\ -0031004\ -~ +~181718181819<\ +NBR>1820182118221823<\ +![CDATA[*/]]>18241825\ +1826182718281829183018311832\ +183318341835\ +18361837\ +183818391840184118421843184418451846184718481849185018511852\ +1853\ +1854185518561857\ +1858185918601861186218631864<\ +/LINE>18651866<\ +/LINE>18671868<\ +/TEXT>1869187018711872<\ +/LINE>187318741875<\ +NBR>18761877187\ +81879188018811882188318841885<\ +![CDATA[ endif]]>1886188718881889\ +18901891189218931894\ +18951896<\ +/LINE>1897189818991900190119021903<\ +/LINE>1904~ ;The next assert is a maintenance hastle when the cclut_execute_test_case_file code changes. ;Uncomment the echo statment to get the real value and update expectedListing accordingly. @@ -324,7 +324,7 @@ subroutine validateResultsXml(xml, legacyFormat) call cclutAssertI4Equal(CURREF, "validate assert found 1.1", foundInd, TRUE) set lineNbr = cclut::retrieveXmlContent(xmlAssert, "lineNumber", 1, foundInd) call cclutAssertI4Equal(CURREF, "validate line number found 1.1", foundInd, TRUE) - call cclutAssertVCEqual(CURREF, "validate line number 1.1", lineNbr, "939") + call cclutAssertVCEqual(CURREF, "validate line number 1.1", lineNbr, "1839") set assertContext = cclut::retrieveXmlContent(xmlAssert, "context", 1, foundInd) call cclutAssertI4Equal(CURREF, "validate assert context found 1.1", foundInd, TRUE) call cclutAssertVCEqual(CURREF, "validate assert context 1.1", assertContext, "setupOnce executed") @@ -357,7 +357,7 @@ subroutine validateResultsXml(xml, legacyFormat) call cclutAssertI4Equal(CURREF, "validate assert found 2.1", foundInd, TRUE) set lineNbr = cclut::retrieveXmlContent(xmlAssert, "lineNumber", 1, foundInd) call cclutAssertI4Equal(CURREF, "validate line number found 2.1", foundInd, TRUE) - call cclutAssertVCEqual(CURREF, "validate line number 2.1", lineNbr, "959") + call cclutAssertVCEqual(CURREF, "validate line number 2.1", lineNbr, "1859") set assertContext = cclut::retrieveXmlContent(xmlAssert, "context", 1, foundInd) call cclutAssertI4Equal(CURREF, "validate assert context found 2.1", foundInd, TRUE) call cclutAssertVCEqual(CURREF, "validate assert context 2.1", assertContext, "setup executed") @@ -377,7 +377,7 @@ subroutine validateResultsXml(xml, legacyFormat) call cclutAssertI4Equal(CURREF, "validate assert found 2.2", foundInd, TRUE) set lineNbr = cclut::retrieveXmlContent(xmlAssert, "lineNumber", 1, foundInd) call cclutAssertI4Equal(CURREF, "validate line number found 2.2", foundInd, TRUE) - call cclutAssertVCEqual(CURREF, "validate line number 2.2", lineNbr, "979") + call cclutAssertVCEqual(CURREF, "validate line number 2.2", lineNbr, "1879") set assertContext = cclut::retrieveXmlContent(xmlAssert, "context", 1, foundInd) call cclutAssertI4Equal(CURREF, "validate assert context found 2.2", foundInd, TRUE) call cclutAssertVCEqual(CURREF, "validate assert context 2.2", assertContext, "testOne executed") @@ -398,7 +398,7 @@ subroutine validateResultsXml(xml, legacyFormat) call cclutAssertI4Equal(CURREF, "validate assert found 2.3", foundInd, TRUE) set lineNbr = cclut::retrieveXmlContent(xmlAssert, "lineNumber", 1, foundInd) call cclutAssertI4Equal(CURREF, "validate line number found 2.3", foundInd, TRUE) - call cclutAssertVCEqual(CURREF, "validate line number 2.3", lineNbr, "969") + call cclutAssertVCEqual(CURREF, "validate line number 2.3", lineNbr, "1869") set assertContext = cclut::retrieveXmlContent(xmlAssert, "context", 1, foundInd) call cclutAssertI4Equal(CURREF, "validate assert context found 2.3", foundInd, TRUE) call cclutAssertVCEqual(CURREF, "validate assert context 2.3", assertContext, "teardown executed") @@ -448,7 +448,7 @@ subroutine validateResultsXml(xml, legacyFormat) call cclutAssertI4Equal(CURREF, "validate assert found 5.1", foundInd, TRUE) set lineNbr = cclut::retrieveXmlContent(xmlAssert, "lineNumber", 1, foundInd) call cclutAssertI4Equal(CURREF, "validate line number found 5.1", foundInd, TRUE) - call cclutAssertVCEqual(CURREF, "validate line number 5.1", lineNbr, "949") + call cclutAssertVCEqual(CURREF, "validate line number 5.1", lineNbr, "1849") set assertContext = cclut::retrieveXmlContent(xmlAssert, "context", 1, foundInd) call cclutAssertI4Equal(CURREF, "validate assert context found 5.1", foundInd, TRUE) call cclutAssertVCEqual(CURREF, "validate assert context 5.1", assertContext, "teardownOnce executed") diff --git a/cclunit-framework-source/src/test/ccl/ut_cclut_mock.inc b/cclunit-framework-source/src/test/ccl/ut_cclut_mock.inc index 4d14f20..afc1e6f 100644 --- a/cclunit-framework-source/src/test/ccl/ut_cclut_mock.inc +++ b/cclunit-framework-source/src/test/ccl/ut_cclut_mock.inc @@ -326,6 +326,46 @@ subroutine test_cclutExecuteProgramWithMocks_happy(null) "regexplike", "1.*4.*1.*4.*test alias") end ;test_cclutExecuteProgramWithMocks_happy +/* test_cclutExecuteProgramWithMocks_no_parameters ********************************************************** +* Scenario: Executes the program with no parameters and no namespace * +************************************************************************************************************/ +subroutine test_cclutExecuteProgramWithMocks_no_parameters(null) + declare public_subroutine = i4 with protect, noconstant(0) + + record executeReply ( + 1 number_parameter = i4 + 1 string_parameter = vc + 1 regular_join[*] + 2 person_id = f8 + 2 encounter_id = f8 + 2 encounter_alias = vc + 1 left_join[*] + 2 person_id = f8 + 2 encounter_id = f8 + 2 encounter_alias = vc + 1 rdb_join[*] + 2 columns = vc + 2 data = vc + ) with protect + + call cclutDefineMockTable("sample_person", "person_id", "f8") + call cclutDefineMockTable("sample_encounter", "encounter_id|person_id", "f8|f8") + call cclutDefineMockTable("sample_encounter_alias", "encounter_id|encounter_alias", "f8|vc") + call cclutCreateMockTable("sample_person") + call cclutCreateMockTable("sample_encounter") + call cclutCreateMockTable("sample_encounter_alias") + + call cclutAddMockImplementation("REPLY", "EXECUTEREPLY") + + call cclutExecuteProgramWithMocks("ut_cclut_execute_mocks_happy") + + call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_no_parameters 001", public_subroutine, 1) + call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_no_parameters 002", + executeReply->number_parameter, 0) + call cclutAssertvcEqual(CURREF, "test_cclutExecuteProgramWithMocks_no_parameters 003", + executeReply->string_parameter, "") +end ;test_cclutExecuteProgramWithMocks_no_parameters + /* test_cclutExecuteProgramWithMocks_namespace ************************************************************** * Scenario: Executes the program using the supplied namespace * ************************************************************************************************************/ @@ -344,8 +384,8 @@ subroutine test_cclutExecuteProgramWithMocks_namespace(null) call cclutExecuteProgramWithMocks("ut_cclut_execute_mocks_happy", "", "CCLUT") call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_namespace 001", test_subroutine, 1) - call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_namespace 003", cclut::internalVariable, 1) - call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_namespace 005", cclut::internalRecord->item, 1) + call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_namespace 002", cclut::internalVariable, 1) + call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_namespace 003", cclut::internalRecord->item, 1) end ;test_cclutExecuteProgramWithMocks_namespace /* test_cclutExecuteProgramWithMocks_mock_subroutine ******************************************************** @@ -373,8 +413,8 @@ subroutine test_cclutExecuteProgramWithMocks_mock_subroutine(null) call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_mock_subroutine 001", public_subroutine, 0) call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_mock_subroutine 002", test_subroutine, 0) call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_mock_subroutine 003", mock_subroutine, 1) - call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_mock_subroutine 005", cclut::internalVariable, 1) - call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_mock_subroutine 007", + call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_mock_subroutine 004", cclut::internalVariable, 1) + call cclutAsserti4Equal(CURREF, "test_cclutExecuteProgramWithMocks_mock_subroutine 005", cclut::internalRecord->item, 1) end ;test_cclutExecuteProgramWithMocks_mock_subroutine From 145d2d9311ac995cadb0e01c35a8e1812b8d8242 Mon Sep 17 00:00:00 2001 From: cernertrevor Date: Thu, 14 Feb 2019 14:33:20 -0600 Subject: [PATCH 7/7] Update to add JavaScript syntax highlighting for code blocks. --- cclunit-framework-source/doc/CCLUTMOCKING.md | 223 ++++++++++--------- 1 file changed, 113 insertions(+), 110 deletions(-) diff --git a/cclunit-framework-source/doc/CCLUTMOCKING.md b/cclunit-framework-source/doc/CCLUTMOCKING.md index b50e968..dd7bacd 100644 --- a/cclunit-framework-source/doc/CCLUTMOCKING.md +++ b/cclunit-framework-source/doc/CCLUTMOCKING.md @@ -30,7 +30,7 @@ cclutExecuteProgramWithMocks.     The namespace under which to execute the program. Example: -``` +```javascript call cclutExecuteProgramWithMocks("ccl_my_program") call cclutExecuteProgramWithMocks("ccl_my_program", "^MINE^, 1.0, ^string parameter^") call cclutExecuteProgramWithMocks("ccl_my_program", "", "MYNAMESPACE") @@ -42,7 +42,7 @@ call cclutExecuteProgramWithMocks("ccl_my_program", "^MINE^, 1.0, ^string parame Removes all mock implementations and mock tables that have been added through the mocking APIs. This should be called at the completion of a test case to clean up all mocks. Example: -``` +```javascript call cclutRemoveAllMocks(null) ``` @@ -60,7 +60,7 @@ Defines a mock table structure that can be created for use within a program. Th     The name of the mock table (This can be used to select data for testing) Example: -``` +```javascript call cclutDefineMockTable("person", "person_id|name_last|name_first|birth_dt_tm", "f8|vc|vc|dq8") ``` @@ -76,7 +76,7 @@ Adds an index to a mock table. The table must already be defined through cclutD     TRUE to create a unique index; FALSE to create a non-unique index Example: -``` +```javascript call cclutAddMockIndex("person", "person_id", TRUE) call cclutAddMockIndex("person", "name_last|name_first", FALSE) ``` @@ -89,7 +89,7 @@ Creates a mock table. The table must already be defined through cclutDefineMock     The name of the source table to be mocked. Example: -``` +```javascript call cclutCreateMockTable("person") ``` @@ -102,7 +102,7 @@ mocked, it will return silently. tableName is required.     The name of the source table that is mocked. Example: -``` +```javascript call cclutRemoveMockTable("person") ``` @@ -111,7 +111,7 @@ call cclutRemoveMockTable("person") Removes all mock tables. Any tables that have already been created will also be dropped. Example: -``` +```javascript call cclutRemoveAllMockTables(null) ``` @@ -130,7 +130,7 @@ Supported escape values     A pipe-delimited string of data to be inserted into the mock table. Example: -``` +```javascript call cclutDefineMockTable("person", "person_id|name_last|name_first|birth_dt_tm", "f8|vc|vc|dq8") call cclutCreateMockTable("person") call cclutAddMockData("person", "1.0|Washington|George|01-JAN-1970 00:00") ;Will add George Washington @@ -147,7 +147,7 @@ Clears all data from a specified mock table. This is functionally similar to a     The name of the source table for the mock table to be cleared. Example: -``` +```javascript call cclutClearMockData("person") ``` @@ -161,7 +161,7 @@ Adds a mock implementation to be utilized by cclutExecuteProgramWithMocks. This     The mocked object. Example: -``` +```javascript call cclutAddMockImplementation("uar_get_code_by", "mock_uar_get_code_by") ``` @@ -173,7 +173,7 @@ Removes a mock implementation.     The object that is mocked. Example: -``` +```javascript call cclutRemoveMockImplementation("uar_get_code_by") ``` @@ -182,7 +182,7 @@ call cclutRemoveMockImplementation("uar_get_code_by") Removes all mock implementations. Example: -``` +```javascript call cclutRemoveAllMockImplementations(null) ``` @@ -193,13 +193,13 @@ call cclutRemoveAllMockImplementations(null) 3. Namespaces are not supported when using cclutAddMockImplementation. An example of this would be: - ``` + ```javascript call cclutAddMockImplementation("public::testSubroutine", "myNamespace::mockSubroutine") ``` Alternatives will depend on the specifics of the script-under-test, but one alternative for the example above would be to define the mock implementation under the namespace that the program uses (i.e. public::mockSubroutine) and exclude the namespaces when adding the mock: - ``` + ```javascript call cclutAddMockImplementation("testSubroutine", "mockSubroutine") ``` @@ -218,103 +218,106 @@ Below is an example of some of the APIs available in the CCL Unit Mocking framew Script-under-test: - drop program 1abc_mo_get_persons:dba go - create program 1abc_mo_get_persons:dba - - declare newSize = i4 with protect, noconstant(0) - - select into "nl:" - from person p - plan p - order by p.person_id - detail - newSize = newSize + 1 - stat = alterlist(reply->persons, newSize) - reply->persons[newSize].person_id = p.person_id - reply->persons[newSize].name_last = p.name_last - reply->persons[newSize].name_first = p.name_first - reply->persons[newSize].birth_dt_tm = p.birth_dt_tm - with nocounter - - end - go +```javascript +drop program 1abc_mo_get_persons:dba go +create program 1abc_mo_get_persons:dba + +declare newSize = i4 with protect, noconstant(0) + +select into "nl:" +from person p +plan p +order by p.person_id +detail + newSize = newSize + 1 + stat = alterlist(reply->persons, newSize) + reply->persons[newSize].person_id = p.person_id + reply->persons[newSize].name_last = p.name_last + reply->persons[newSize].name_first = p.name_first + reply->persons[newSize].birth_dt_tm = p.birth_dt_tm +with nocounter + +end +go +``` Test Code: - declare mock_table_person = vc with protect, noconstant("") +```javascript +declare mock_table_person = vc with protect, noconstant("") + +; Defining a mock person table. The return value is the name of the mocked table. +; This can be useful to perform a select on the table after the script-under-test is complete +; to verify (among other things) that an insert or a delete worked correctly. +set mock_table_person = cclutDefineMockTable("person", "person_id|name_last|name_first|birth_dt_tm", + "f8|vc|vc|dq8") + +; Add a non-unique index to name_last +call cclutAddMockIndex("person", "name_last", FALSE) + +; Creates the mock table. After this, it is available for DML statements. +call cclutCreateMockTable("person") + +; Create data for the table. +call cclutAddMockData("person", "1.0|Washington|George|01-JAN-1970 00:00") ;Will add George Washington +call cclutAddMockData("person", "2.0|Adams|John|02-FEB-1971 11:11") ;Will add John Adams +call cclutAddMockData("person", "3.0|Jefferson|\null|03-MAR-1972 22:22") ;Will add Jefferson (no first name) +call cclutAddMockData("person", "4.0|Madison||04-APR-1973 10:33") ;Will add Madison (empty string for first name) + +record agp_reply ( + 1 persons[*] + 2 person_id = f8 + 2 name_last = vc + 2 name_first = vc + 2 birth_dt_tm = dq8 +) with protect + +; Have with replace("REPLY", AGP_REPLY) be applied when executing 1abc_mo_get_persons. +call cclutAddMockImplementation("REPLY", "AGP_REPLY") + +; Execute the script-under-test +call cclutExecuteProgramWithMocks("1abc_mo_get_persons", "") + +; Do validation +call cclutAssertf8Equal(CURREF, "test_get_people_happy 001", agp_reply->persons[1].person_id, 1.0) +call cclutAssertvcEqual(CURREF, "test_get_people_happy 002", agp_reply->persons[1].name_last, + "Washington") +call cclutAssertvcEqual(CURREF, "test_get_people_happy 003", agp_reply->persons[1].name_first, + "George") +call cclutAssertf8Equal(CURREF, "test_get_people_happy 004", agp_reply->persons[1].birth_dt_tm, + cnvtdatetime("01-JAN-1970 00:00")) + +call cclutAssertf8Equal(CURREF, "test_get_people_happy 005", agp_reply->persons[2].person_id, 2.0) +call cclutAssertvcEqual(CURREF, "test_get_people_happy 006", agp_reply->persons[2].name_last, + "Adams") +call cclutAssertvcEqual(CURREF, "test_get_people_happy 007", agp_reply->persons[2].name_first, + "John") +call cclutAssertf8Equal(CURREF, "test_get_people_happy 008", agp_reply->persons[2].birth_dt_tm, + cnvtdatetime("02-FEB-1971 11:11")) + +call cclutAssertf8Equal(CURREF, "test_get_people_happy 009", agp_reply->persons[3].person_id, 3.0) +call cclutAssertvcEqual(CURREF, "test_get_people_happy 010", agp_reply->persons[3].name_last, + "Jefferson") +call cclutAssertvcEqual(CURREF, "test_get_people_happy 011", agp_reply->persons[3].name_first, + "") +call cclutAssertf8Equal(CURREF, "test_get_people_happy 012", agp_reply->persons[3].birth_dt_tm, + cnvtdatetime("03-MAR-1972 22:22")) + +call cclutAssertf8Equal(CURREF, "test_get_people_happy 013", agp_reply->persons[4].person_id, 4.0) +call cclutAssertvcEqual(CURREF, "test_get_people_happy 014", agp_reply->persons[4].name_last, + "Madison") +call cclutAssertvcEqual(CURREF, "test_get_people_happy 015", agp_reply->persons[4].name_first, + "") +call cclutAssertf8Equal(CURREF, "test_get_people_happy 016", agp_reply->persons[4].birth_dt_tm, + cnvtdatetime("04-APR-1973 10:33")) - ; Defining a mock person table. The return value is the name of the mocked table. - ; This can be useful to perform a select on the table after the script-under-test is complete - ; to verify (among other things) that an insert or a delete worked correctly. - set mock_table_person = cclutDefineMockTable("person", "person_id|name_last|name_first|birth_dt_tm", - "f8|vc|vc|dq8") - - ; Add a non-unique index to name_last - call cclutAddMockIndex("person", "name_last", FALSE) - - ; Creates the mock table. After this, it is available for DML statements. - call cclutCreateMockTable("person") - - ; Create data for the table. - call cclutAddMockData("person", "1.0|Washington|George|01-JAN-1970 00:00") ;Will add George Washington - call cclutAddMockData("person", "2.0|Adams|John|02-FEB-1971 11:11") ;Will add John Adams - call cclutAddMockData("person", "3.0|Jefferson|\null|03-MAR-1972 22:22") ;Will add Jefferson (no first name) - call cclutAddMockData("person", "4.0|Madison||04-APR-1973 10:33") ;Will add Madison (empty string for first name) - - record agp_reply ( - 1 persons[*] - 2 person_id = f8 - 2 name_last = vc - 2 name_first = vc - 2 birth_dt_tm = dq8 - ) with protect - - ; Have with replace("REPLY", AGP_REPLY) be applied when executing 1abc_mo_get_persons. - call cclutAddMockImplementation("REPLY", "AGP_REPLY") - - ; Execute the script-under-test - call cclutExecuteProgramWithMocks("1abc_mo_get_persons", "") - - ; Do validation - call cclutAssertf8Equal(CURREF, "test_get_people_happy 001", agp_reply->persons[1].person_id, 1.0) - call cclutAssertvcEqual(CURREF, "test_get_people_happy 002", agp_reply->persons[1].name_last, - "Washington") - call cclutAssertvcEqual(CURREF, "test_get_people_happy 003", agp_reply->persons[1].name_first, - "George") - call cclutAssertf8Equal(CURREF, "test_get_people_happy 004", agp_reply->persons[1].birth_dt_tm, - cnvtdatetime("01-JAN-1970 00:00")) - - call cclutAssertf8Equal(CURREF, "test_get_people_happy 005", agp_reply->persons[2].person_id, 2.0) - call cclutAssertvcEqual(CURREF, "test_get_people_happy 006", agp_reply->persons[2].name_last, - "Adams") - call cclutAssertvcEqual(CURREF, "test_get_people_happy 007", agp_reply->persons[2].name_first, - "John") - call cclutAssertf8Equal(CURREF, "test_get_people_happy 008", agp_reply->persons[2].birth_dt_tm, - cnvtdatetime("02-FEB-1971 11:11")) - - call cclutAssertf8Equal(CURREF, "test_get_people_happy 009", agp_reply->persons[3].person_id, 3.0) - call cclutAssertvcEqual(CURREF, "test_get_people_happy 010", agp_reply->persons[3].name_last, - "Jefferson") - call cclutAssertvcEqual(CURREF, "test_get_people_happy 011", agp_reply->persons[3].name_first, - "") - call cclutAssertf8Equal(CURREF, "test_get_people_happy 012", agp_reply->persons[3].birth_dt_tm, - cnvtdatetime("03-MAR-1972 22:22")) - - call cclutAssertf8Equal(CURREF, "test_get_people_happy 013", agp_reply->persons[4].person_id, 4.0) - call cclutAssertvcEqual(CURREF, "test_get_people_happy 014", agp_reply->persons[4].name_last, - "Madison") - call cclutAssertvcEqual(CURREF, "test_get_people_happy 015", agp_reply->persons[4].name_first, - "") - call cclutAssertf8Equal(CURREF, "test_get_people_happy 016", agp_reply->persons[4].birth_dt_tm, - cnvtdatetime("04-APR-1973 10:33")) - - ; A contrived example to demonstrate a potential use for the return value from cclutDefineMockTable - select into "nl:" - personCount = count(*) - from (value(mock_table_person) mtp) - head report - call cclutAsserti4Equal(CURREF, "test_get_people_happy 017", cnvtint(personCount), 4) - with nocounter - - call cclutRemoveAllMocks(null) - \ No newline at end of file +; A contrived example to demonstrate a potential use for the return value from cclutDefineMockTable +select into "nl:" + personCount = count(*) +from (value(mock_table_person) mtp) +head report + call cclutAsserti4Equal(CURREF, "test_get_people_happy 017", cnvtint(personCount), 4) +with nocounter + +call cclutRemoveAllMocks(null) +```