-
Notifications
You must be signed in to change notification settings - Fork 304
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
HPCC-30310 esdl ecl output to stdout #17971
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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.""" | ||
|
||
|
@@ -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) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It should probably be do an "else return False" here after line 192. Otherwise, the tests in the next few lines will compare with previously created "from-stdout.ecl" from previous test runs. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fixed |
||
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. | ||
|
@@ -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') | ||
|
@@ -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) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Any reason not to use "default" parameter rather than the extra code in 345. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That was my first approach, but I saw that using |
||
|
||
args = parser.parse_args() | ||
|
||
if args.commands == None: | ||
args.commands = ['all'] | ||
|
||
return args | ||
|
||
|
||
|
@@ -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', | ||
|
@@ -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) | ||
|
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. ***/ | ||
/*===================================================*/ | ||
|
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. ***/ | ||
/*===================================================*/ | ||
|
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. ***/ | ||
/*===================================================*/ | ||
|
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. ***/ | ||
/*===================================================*/ | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this check be done first before the expected_err != None check (in Line 153)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not in this case. The check on 153 captures any tests that are expected to return an error by making sure the error message printed matches what is expected. Then any other test returning an error return code is a failure. I can't make an analogous check of stderr, because the esdl command prints some non-failure messages to stderr.