Skip to content

Commit

Permalink
HPCC-30310 Allow esdl ecl command to output to stdout
Browse files Browse the repository at this point in the history
Update esdl ecl command to allow output to stdout by making the outputDir
parameter optional. When using stdout, restrict the use of options to those
combinations that result in a single file output.

Disabled verbose output in the call to EsdlCmdHelper::convertECMtoESXDL to
avoid printing extra text to stdout.

Update esdl regression test with cases for esdl ecl, though the suite needs
independent updates to bring tests of the other commands in line with
recent platform changes. This will be handled in the ticket HPCC-30699.

Signed-off-by: Terrence Asselin <[email protected]>
  • Loading branch information
asselitx committed Dec 1, 2023
1 parent 1850d9c commit 5747ab4
Show file tree
Hide file tree
Showing 6 changed files with 405 additions and 54 deletions.
139 changes: 138 additions & 1 deletion testing/esp/esdlcmd/esdlcmd-test.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ def __init__(self, stats, exe_path, output_base, test_path):
self.test_path = test_path
self.stats = stats

# This class is base for commands related to services: wsdl, xsd, cpp and java.
class TestCaseBase:
"""Settings for a specific test case."""

Expand Down Expand Up @@ -103,6 +104,110 @@ def validate_results(self):
logging.debug('TestCaseBase implementation called, no comparison run')
return False

# This class is the base for the 'transform' commands: ecl and xml.
# In a future update, investigate refactoring the base classes so there is a single
# parent with any shared capabilities.
#
# When writing to stdout, the key directory should contain a file named 'from-stdout.ecl'
# that contains the expected output.
class TestCaseTransformBase:
def __init__(self, run_settings, name, command, esdl_file, xsl_path, use_stdout, expected_err=None, options=None):
self.run_settings = run_settings
self.name = name
self.command = command
self.esdl_path = (self.run_settings.test_path / 'inputs' / esdl_file)
self.xsl_path = xsl_path
self.options = options
self.output_path = Path(self.run_settings.output_base) / name
self.stdout = use_stdout
self.expected_err = expected_err
if self.stdout:
self.args = [
str(run_settings.exe_path),
self.command,
self.esdl_path,
'-cde',
self.xsl_path,
]
else:
self.args = [
str(run_settings.exe_path),
self.command,
self.esdl_path,
self.output_path,
'-cde',
self.xsl_path,
]

if options:
self.args.extend(options)

self.result = None

def run_test(self):
safe_mkdir(self.output_path)
logging.debug("Test %s args: %s", self.name, str(self.args))
self.result = subprocess.run(self.args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)

if self.expected_err != None and self.expected_err == self.result.stderr:
success = True
elif self.result.returncode != 0:
logging.error('Error running "esdl %s" for test "%s": %s', self.command, self.name, self.result.stderr)
success = False
else:
success = self.validate_results()

self.run_settings.stats.add_count(success)

def is_same(self, dir1, dir2):
"""
Compare two directory trees content.
Return False if they differ, True is they are the same.
"""
compared = DirectoryCompare(dir1, dir2)
if (compared.left_only or compared.right_only or compared.diff_files
or compared.funny_files):
return False
for subdir in compared.common_dirs:
if not self.is_same(os.path.join(dir1, subdir), os.path.join(dir2, subdir)):
return False
return True

def validate_results(self):
"""Compare test case results to the known key.
Return True if the two are identical or False otherwise.
"""
outName = self.output_path
key = (self.run_settings.test_path / 'key' / self.name)

# When output was stdout, write the captured stdout text to a file named 'from-stdout.ecl'
# in the output directory. This allows us to use the same method of comparing the key
# and result.
if self.stdout:
if self.result.stdout != None and len(self.result.stdout) > 0:
with open((outName / 'from-stdout.ecl'), 'w', encoding='utf-8') as f:
f.write(self.result.stdout)
else:
logging.error('Missing stdout output for test %s', self.name)
return False

if (not key.exists()):
logging.error('Missing key file %s', str(key))
return False

if (not outName.exists()):
logging.error('Missing output for test %s', self.name)
return False

if (not self.is_same(str(key), str(outName))):
logging.debug('Comparing key %s to output %s', str(key), str(outName))
logging.error('Test failed: %s', self.name)
return False
else:
logging.debug('Passed: %s', self.name)
return True


class TestCaseXSD(TestCaseBase):
"""Test case for the wsdl or xsd commands.
Expand Down Expand Up @@ -212,6 +317,8 @@ def parse_options():
the parsed options and arguments.
"""

command_values = ['all', 'cpp', 'ecl', 'java', 'wsdl', 'xsd']

parser = argparse.ArgumentParser(description=DESC)
parser.add_argument('testroot',
help='Path of the root folder of the esdlcmd testing project')
Expand All @@ -231,7 +338,15 @@ def parse_options():
help='Enable debug logging of test cases',
action='store_true', default=False)

parser.add_argument('-c', '--commands',
help='esdl commands to run tests for, use once for each command or pass "all" to test all commands. Defaults to "all".',
action="append", choices=command_values)

args = parser.parse_args()

if args.commands == None:
args.commands = ['all']

return args


Expand Down Expand Up @@ -278,6 +393,11 @@ def main():
stats = Statistics()
run_settings = TestRun(stats, exe_path, args.outdir, test_path)

esdl_includes_path = str(test_path / 'inputs')

expected_err_multi_file_incl = '\nOutput to stdout is not supported for multiple files. Either add the Rollup\noption or specify an output directory.\n'
expected_err_multi_file_expanded = '\nOutput to stdout is not supported for multiple files. Remove the Output expanded\n XML option or specify an output directory.\n'

test_cases = [
# wsdl
TestCaseXSD(run_settings, 'wstest-wsdl-default', 'wsdl', 'ws_test.ecm', 'WsTest',
Expand Down Expand Up @@ -390,10 +510,27 @@ def main():
# A single element is created for each request structure defined. This is default behavior.
TestCaseXSD(run_settings, 'use-request-name', 'wsdl', 'ws_userequestname.ecm', 'WsUseRequestName',
xsl_base_path),

# ecl
TestCaseTransformBase(run_settings, 'ecl-stdout-single', 'ecl', 'ws_test.ecm', xsl_base_path, use_stdout=True),

TestCaseTransformBase(run_settings, 'ecl-stdout-incl-err', 'ecl', 'ws_test.ecm', xsl_base_path, use_stdout=True,
expected_err=expected_err_multi_file_incl, options=['-I', esdl_includes_path, '--includes']),

TestCaseTransformBase(run_settings, 'ecl-stdout-expanded-err', 'ecl', 'ws_test.ecm', xsl_base_path, use_stdout=True,
expected_err=expected_err_multi_file_expanded, options=['-x']),

TestCaseTransformBase(run_settings, 'ecl-stdout-incl-rollup', 'ecl', 'ws_test.ecm', xsl_base_path, use_stdout=True,
options=['-I', esdl_includes_path, '--includes', '--rollup']),

TestCaseTransformBase(run_settings, 'ecl-incl', 'ecl', 'ws_test.ecm', xsl_base_path, use_stdout=False,
options=['-I', esdl_includes_path, '--includes'])

]

for case in test_cases:
case.run_test()
if 'all' in args.commands or case.command in args.commands:
case.run_test()

logging.info('Success count: %d', stats.successCount)
logging.info('Failure count: %d', stats.failureCount)
Expand Down
37 changes: 37 additions & 0 deletions testing/esp/esdlcmd/key/ecl-incl/allversionreport.ecl
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*** Not to be hand edited (changes will be lost on re-generation) ***/
/*** ECL Interface generated by esdl2ecl version 1.0 from allversionreport.xml. ***/
/*===================================================*/


EXPORT allversionreport := MODULE

EXPORT t_FooBar := RECORD
UTF8 Foo {XPATH('Foo')};
UTF8 Bar {XPATH('Bar')};
END;

EXPORT t_AllVersionArrays := RECORD
SET OF UTF8 StringArray {XPATH('StringArray/Item'), MAXCOUNT(1)}; // max_count must be specified in ESDL defintion!
DATASET(t_FooBar) FooBarArray {XPATH('FooBarArray/FooBar'), MAXCOUNT(1)}; // max_count must be specified in ESDL defintion!
DATASET(t_FooBar) NamedItemFooBarArray {XPATH('NamedItemFooBarArray/NamedItem'), MAXCOUNT(1)}; // max_count must be specified in ESDL defintion!
END;

EXPORT t_AllVersionReportRequest := RECORD
UTF8 OptionalDeveloperStringVal {XPATH('OptionalDeveloperStringVal')};//hidden[developer]
INTEGER Annotate20ColsIntVal {XPATH('Annotate20ColsIntVal')};
t_AllVersionArrays Arrays {XPATH('Arrays')};
UTF8 UnrelentingForce {XPATH('UnrelentingForce')}; //values['1','2','3','']
END;

EXPORT t_AllVersionReportResponse := RECORD
UTF8 ResultVal {XPATH('ResultVal')};
t_AllVersionArrays ResultArrays {XPATH('ResultArrays')};
END;


END;

/*** Not to be hand edited (changes will be lost on re-generation) ***/
/*** ECL Interface generated by esdl2ecl version 1.0 from allversionreport.xml. ***/
/*===================================================*/

40 changes: 40 additions & 0 deletions testing/esp/esdlcmd/key/ecl-incl/ws_test.ecl
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*** Not to be hand edited (changes will be lost on re-generation) ***/
/*** ECL Interface generated by esdl2ecl version 1.0 from ws_test.xml. ***/
/*===================================================*/


EXPORT ws_test := MODULE

EXPORT t_MinVersionReportRequest := RECORD
UTF8 RequestString {XPATH('RequestString')};
END;

EXPORT t_VersionRangeReportRequest := RECORD
UTF8 RequestString {XPATH('RequestString')};
END;

EXPORT t_VersionRangeReportResponse := RECORD
UTF8 ResponseString {XPATH('ResponseString')};
END;

/*Empty record generated from empty EsdlRequest
EXPORT t_WsTestPingRequest := RECORD
END;
*/

EXPORT t_MinVersionReportResponse := RECORD
UTF8 ResponseString {XPATH('ResponseString')};
END;

/*Empty record generated from empty EsdlResponse
EXPORT t_WsTestPingResponse := RECORD
END;
*/


END;

/*** Not to be hand edited (changes will be lost on re-generation) ***/
/*** ECL Interface generated by esdl2ecl version 1.0 from ws_test.xml. ***/
/*===================================================*/

63 changes: 63 additions & 0 deletions testing/esp/esdlcmd/key/ecl-stdout-incl-rollup/from-stdout.ecl
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*** Not to be hand edited (changes will be lost on re-generation) ***/
/*** ECL Interface generated by esdl2ecl version 1.0 from ws_test.xml. ***/
/*===================================================*/


EXPORT ws_test := MODULE

EXPORT t_FooBar := RECORD
UTF8 Foo {XPATH('Foo')};
UTF8 Bar {XPATH('Bar')};
END;

EXPORT t_AllVersionArrays := RECORD
SET OF UTF8 StringArray {XPATH('StringArray/Item'), MAXCOUNT(1)}; // max_count must be specified in ESDL defintion!
DATASET(t_FooBar) FooBarArray {XPATH('FooBarArray/FooBar'), MAXCOUNT(1)}; // max_count must be specified in ESDL defintion!
DATASET(t_FooBar) NamedItemFooBarArray {XPATH('NamedItemFooBarArray/NamedItem'), MAXCOUNT(1)}; // max_count must be specified in ESDL defintion!
END;

EXPORT t_AllVersionReportRequest := RECORD
UTF8 OptionalDeveloperStringVal {XPATH('OptionalDeveloperStringVal')};//hidden[developer]
INTEGER Annotate20ColsIntVal {XPATH('Annotate20ColsIntVal')};
t_AllVersionArrays Arrays {XPATH('Arrays')};
UTF8 UnrelentingForce {XPATH('UnrelentingForce')}; //values['1','2','3','']
END;

EXPORT t_MinVersionReportRequest := RECORD
UTF8 RequestString {XPATH('RequestString')};
END;

EXPORT t_VersionRangeReportRequest := RECORD
UTF8 RequestString {XPATH('RequestString')};
END;

EXPORT t_VersionRangeReportResponse := RECORD
UTF8 ResponseString {XPATH('ResponseString')};
END;

/*Empty record generated from empty EsdlRequest
EXPORT t_WsTestPingRequest := RECORD
END;
*/

EXPORT t_AllVersionReportResponse := RECORD
UTF8 ResultVal {XPATH('ResultVal')};
t_AllVersionArrays ResultArrays {XPATH('ResultArrays')};
END;

EXPORT t_MinVersionReportResponse := RECORD
UTF8 ResponseString {XPATH('ResponseString')};
END;

/*Empty record generated from empty EsdlResponse
EXPORT t_WsTestPingResponse := RECORD
END;
*/


END;

/*** Not to be hand edited (changes will be lost on re-generation) ***/
/*** ECL Interface generated by esdl2ecl version 1.0 from ws_test.xml. ***/
/*===================================================*/

40 changes: 40 additions & 0 deletions testing/esp/esdlcmd/key/ecl-stdout-single/from-stdout.ecl
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*** Not to be hand edited (changes will be lost on re-generation) ***/
/*** ECL Interface generated by esdl2ecl version 1.0 from ws_test.xml. ***/
/*===================================================*/


EXPORT ws_test := MODULE

EXPORT t_MinVersionReportRequest := RECORD
UTF8 RequestString {XPATH('RequestString')};
END;

EXPORT t_VersionRangeReportRequest := RECORD
UTF8 RequestString {XPATH('RequestString')};
END;

EXPORT t_VersionRangeReportResponse := RECORD
UTF8 ResponseString {XPATH('ResponseString')};
END;

/*Empty record generated from empty EsdlRequest
EXPORT t_WsTestPingRequest := RECORD
END;
*/

EXPORT t_MinVersionReportResponse := RECORD
UTF8 ResponseString {XPATH('ResponseString')};
END;

/*Empty record generated from empty EsdlResponse
EXPORT t_WsTestPingResponse := RECORD
END;
*/


END;

/*** Not to be hand edited (changes will be lost on re-generation) ***/
/*** ECL Interface generated by esdl2ecl version 1.0 from ws_test.xml. ***/
/*===================================================*/

Loading

0 comments on commit 5747ab4

Please sign in to comment.