From 35f0aeea044b7d4e2165877d4e5362f089b82829 Mon Sep 17 00:00:00 2001 From: Luke Petschauer Date: Thu, 21 Dec 2023 14:23:15 -0800 Subject: [PATCH] TDVT quarterly release (#1208) * move all internal changes external * bring in internal bug fix release * Update tdvt/tdvt/config/tdvt/tdvt.ini * Update CHANGELOG.md --- tdvt/CHANGELOG.md | 55 +++ tdvt/tdvt/config/registry/mac_arm.ini | 2 + tdvt/tdvt/config_gen/datasource_list.py | 119 ++++--- tdvt/tdvt/config_gen/gentests.py | 15 +- tdvt/tdvt/config_gen/tdvtconfig.py | 11 +- tdvt/tdvt/config_gen/test_config.py | 74 ++-- .../lodcalcs/expected.setup.lod.calcs.txt | 20 +- .../median/expected.setup.agg.median.txt | 16 +- .../expected.setup.agg.percentile.1.txt | 2 +- .../expected.setup.agg.percentile.txt | 20 +- ...ring.regexp.extract_nth.extended.xfail.txt | 18 + ...ring.regexp.extract_nth.extended.xfail.txt | 2 + .../standard/expected.setup.agg.avg.txt | 8 +- .../standard/expected.setup.cast.float.txt | 16 +- .../expected.setup.date.dateadd.hour.txt | 60 +++- .../expected.setup.date.dateadd.minute.txt | 60 +++- .../expected.setup.date.dateadd.second.txt | 60 +++- ...pected.setup.date.math.date_minus_date.txt | 4 +- .../standard/expected.setup.date.math.txt | 4 +- .../standard/expected.setup.logical.bool.txt | 12 +- .../standard/expected.setup.logical.txt | 24 +- .../standard/expected.setup.math.abs.txt | 4 +- .../standard/expected.setup.math.acos.txt | 4 +- .../standard/expected.setup.math.asin.txt | 4 +- .../standard/expected.setup.math.cos.txt | 8 +- .../standard/expected.setup.math.cot.txt | 8 +- .../standard/expected.setup.math.degree.txt | 8 +- .../standard/expected.setup.math.exp.txt | 8 +- .../standard/expected.setup.math.hexbin.txt | 8 +- .../standard/expected.setup.math.ln.txt | 8 +- .../standard/expected.setup.math.log.txt | 16 +- .../standard/expected.setup.math.pi.txt | 8 +- .../expected.setup.math.power.real.txt | 8 +- .../standard/expected.setup.math.power.txt | 4 +- .../standard/expected.setup.math.radians.txt | 8 +- .../expected.setup.math.round.B584401.txt | 8 +- .../expected.setup.math.round.extended.txt | 8 +- .../standard/expected.setup.math.round.txt | 14 +- .../standard/expected.setup.math.sin.txt | 8 +- .../standard/expected.setup.math.sqrt.txt | 8 +- .../standard/expected.setup.math.square.txt | 8 +- .../standard/expected.setup.math.tan.txt | 4 +- .../standard/expected.setup.operator.int.txt | 12 +- .../standard/expected.setup.operator.num.txt | 36 +- .../standard/setup.date.dateadd.hour.txt | 3 +- .../standard/setup.date.dateadd.minute.txt | 3 +- .../standard/setup.date.dateadd.second.txt | 4 +- .../tdeonly/expected.setup.agg.median.txt | 16 +- .../tdeonly/expected.setup.agg.percentile.txt | 20 +- ...expected.setup.operator.modulo.B643808.txt | 8 +- ...cted.setup.BUGS.B27875-asc-nulls-first.xml | 7 +- ...cted.setup.BUGS.B27875-desc-nulls-last.xml | 7 +- .../calcs/expected.setup.BUGS.B641638.xml | 4 +- .../expected.setup.Query.Filter.IsNOTNULL.xml | 4 +- .../calcs/expected.setup.join.null.bool.xml | 6 +- .../calcs/expected.setup.join.null.date.xml | 6 +- .../expected.setup.join.null.datetime.xml | 6 +- .../calcs/expected.setup.join.null.int.xml | 6 +- .../calcs/expected.setup.join.null.real.xml | 8 +- .../calcs/expected.setup.join.null.str.xml | 6 +- .../lod/expected.setup.lod.17_Nesting.xml | 14 +- ....lod.1_Difference From with Cross Join.xml | 4 +- .../expected.setup.Filter.Add_to_context.xml | 6 +- .../expected.setup.Query.CTE_singleCte.xml | 316 ++++++++++++++++++ .../expected.setup.Query.Dates_MDY.xml | 6 +- ...xpected.setup.Query.Dates_MDY_Filtered.xml | 4 +- .../expected.setup.Query.MultipleFilters.xml | 6 +- ...pected.setup.Query.Unaggregated_Filter.xml | 6 +- ...p.Query.Unaggregated_Filter_NoDateTime.xml | 6 +- .../expected.setup.ZTesting.Staples9.xml | 6 +- .../input/calcs/setup.BUGS.B59740.xml | 8 +- .../staples/setup.Query.CTE_singleCte.xml | 215 ++++++++++++ tdvt/tdvt/setup_env.py | 81 +++-- tdvt/tdvt/tabquery.py | 34 +- tdvt/tdvt/tabquery_path.py | 21 +- tdvt/tdvt/tdvt.py | 116 +++++-- tdvt/tdvt/tdvt_core.py | 105 +++--- tdvt/tdvt/test_results.py | 118 ++++++- tdvt/tdvt/version.py | 2 +- tdvt/test/tdvt_test.py | 248 +++++++++++++- .../exprtests/expected.setup.agg.avg.txt | 30 ++ .../ini/postgres_jdbc_tabquerytool.ini | 3 +- 82 files changed, 1791 insertions(+), 490 deletions(-) create mode 100644 tdvt/tdvt/config/registry/mac_arm.ini create mode 100644 tdvt/tdvt/exprtests/regexcalcs/expected.setup.string.regexp.extract_nth.extended.xfail.txt create mode 100644 tdvt/tdvt/exprtests/regexcalcs/setup.string.regexp.extract_nth.extended.xfail.txt create mode 100644 tdvt/tdvt/logicaltests/expected/staples/expected.setup.Query.CTE_singleCte.xml create mode 100644 tdvt/tdvt/logicaltests/generate/input/staples/setup.Query.CTE_singleCte.xml create mode 100644 tdvt/test/tool_test/exprtests/expected.setup.agg.avg.txt diff --git a/tdvt/CHANGELOG.md b/tdvt/CHANGELOG.md index 3a2e9dcb..cb8e40b7 100644 --- a/tdvt/CHANGELOG.md +++ b/tdvt/CHANGELOG.md @@ -4,6 +4,61 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [2.13.4] - 2023-12-20 +- Some nits from making the release PR. + +## [2.13.3] - 2023-12-04 +- Change ARM tabquery path logic, falling back to regular Mac path if no arm-specific one is found. + +## [2.13.2] - 2023-12-04 +- Add expecteds with tolerance tags. + +## [2.13.1] - 2023-12-01 +- Fix bug in Mac ARM path logic. + +## [2.13.0] - 2023-11-28 +- Add support for Apple Silicon-specific tabquery path in tdvt.ini + +## [2.12.0] - 2023-11-14 +- Add support for tolerance, changing how test actuals and expecteds are compared to use `math.isclose()` if a tolerance value is included in expected file. + +## [2.11.3] - 2023-10-15 +- Escape column names in expression tests. Contributed by @wnob via [PR 1194](https://github.com/tableau/connector-plugin-sdk/pull/1194). + +## [2.11.2] - 2023-10-09 +- Fixed error produced by zip log deletion attempts. +- Added unit testing around BatchQueueWork do_work(). + +## [2.11.1] - 2023-09-29 +- Changed verbiage and added newline to failed test run commands to test results. + +## [2.11.0] - 2023-09-27 +- Added failed test run commands to test results. + +## [2.10.0] - 2023-09-19 +- Update logging so `tdvt_log_combined.txt` is less verbose by default, but can have the current output using the `--verbose` flag. +- Update various logging calls to use the appropriate logging level throughout TDVT. +- Fix a bug that kept `tdvt_log_combined.txt` from being created but not being appended. + +## [2.9.8] - 2023-09-13 +- Add more REGEXP test cases + +## [2.9.7] - 2023-08-28 +- Added formatting for generated expected files. + +## [2.9.6] - 2023-08-28 +- Address Spark SQL test issue + +## [2.9.5] - 2023-08-28 +- Add regex/tds mangling tests. + +## [2.9.4] - 2023-08-09 +- Add more `dateadd` tests. + +## [2.9.3] - 2023-07-26 +- PR 1151 from the monolith, add missing metadata argument. + ## [2.7.6]. - 2023-10-11 - Use quoting for column references in the expression tests. diff --git a/tdvt/tdvt/config/registry/mac_arm.ini b/tdvt/tdvt/config/registry/mac_arm.ini new file mode 100644 index 00000000..c84994f5 --- /dev/null +++ b/tdvt/tdvt/config/registry/mac_arm.ini @@ -0,0 +1,2 @@ +[DatasourceRegistry] +all = * diff --git a/tdvt/tdvt/config_gen/datasource_list.py b/tdvt/tdvt/config_gen/datasource_list.py index 18472f4a..6986ebe6 100644 --- a/tdvt/tdvt/config_gen/datasource_list.py +++ b/tdvt/tdvt/config_gen/datasource_list.py @@ -68,7 +68,6 @@ def print_configurations(ds_reg, dsname, verbose): print_ds(ds, ds_reg) - def get_password_file(config): return config.get('PasswordFile', '') @@ -183,11 +182,12 @@ def load_test(config, test_dir=get_root_dir()): run_time_config.set_tabquery_paths( dsconfig.get('TabQueryPathLinux', ''), dsconfig.get('TabQueryPathMac', ''), + dsconfig.get('TabQueryPathMacArm', ''), dsconfig.get('TabQueryPathx64', '') ) test_config = TestConfig(config_name, dsconfig['LogicalQueryFormat'], run_time_config) - + logging.info("Loading test config for datasource: " + config_name) # Add the standard test suites. if standard_tests in config.sections(): try: @@ -207,8 +207,9 @@ def load_test(config, test_dir=get_root_dir()): get_expression_test_dir_path(standard, 'exprtests/standard/'), test_dir, get_password_file(standard), get_expected_message(standard), get_is_smoke_test(standard), get_is_test_enabled(standard), False) + logging.info("\tAdded standard tests.") except KeyError as e: - logging.debug(e) + logging.error(e) pass # Add the optional LOD tests. @@ -224,8 +225,9 @@ def load_test(config, test_dir=get_root_dir()): get_expression_test_dir_path(lod, 'exprtests/lodcalcs/'), test_dir, get_password_file(lod), get_expected_message(lod), get_is_smoke_test(lod), get_is_test_enabled(lod), False) + logging.info("\tAdded LOD tests.") except KeyError as e: - logging.debug(e) + logging.error(e) pass # Add the optional Staples data check test. @@ -233,13 +235,14 @@ def load_test(config, test_dir=get_root_dir()): try: staples_data = config[staples_data_test] all_ini_sections.remove(staples_data_test) - test_config.add_expression_test('expression.staples.', STAPLES_TDS, '', - get_expression_test_dir_path(staples_data, 'exprtests/staples/'), - test_dir, get_password_file(staples_data), - get_expected_message(staples_data), get_is_smoke_test(staples_data), - get_is_test_enabled(staples_data), False) + test_config.add_expression_test( +'expression.staples.', STAPLES_TDS, '', get_expression_test_dir_path(staples_data, 'exprtests/staples/'), + test_dir, get_password_file(staples_data), get_expected_message(staples_data), + get_is_smoke_test(staples_data), get_is_test_enabled(staples_data), False + ) + logging.info("\tAdded Staples data check test.") except KeyError as e: - logging.debug(e) + logging.error(e) pass # Add the optional Union test. @@ -247,12 +250,15 @@ def load_test(config, test_dir=get_root_dir()): try: union = config[union_test] all_ini_sections.remove(union_test) - test_config.add_logical_test('logical.union.', CALCS_TDS, '', - test_config.get_logical_test_path('logicaltests/setup/union/setup.*.'), - test_dir, get_password_file(union), get_expected_message(union), - get_is_smoke_test(union), get_is_test_enabled(union), False) + test_config.add_logical_test( + 'logical.union.', CALCS_TDS, '', + test_config.get_logical_test_path('logicaltests/setup/union/setup.*.'), test_dir, + get_password_file(union), get_expected_message(union), get_is_smoke_test(union), + get_is_test_enabled(union), False + ) + logging.info("\tAdded Union tests.") except KeyError as e: - logging.debug(e) + logging.error(e) pass # Add the optional Regex test. @@ -260,12 +266,13 @@ def load_test(config, test_dir=get_root_dir()): try: regex = config[regex_test] all_ini_sections.remove(regex_test) - test_config.add_expression_test('expression.regex.', CALCS_TDS, regex.get(KEY_EXCLUSIONS, ''), - get_expression_test_dir_path(regex, 'exprtests/regexcalcs/'), test_dir, - get_password_file(regex), get_expected_message(regex), - get_is_smoke_test(regex), get_is_test_enabled(regex), False) + test_config.add_expression_test( + 'expression.regex.', CALCS_TDS, regex.get(KEY_EXCLUSIONS, ''), + get_expression_test_dir_path(regex, 'exprtests/regexcalcs/'), test_dir, get_password_file(regex), + get_expected_message(regex), get_is_smoke_test(regex), get_is_test_enabled(regex), False) + logging.info("\tAdded Regex tests.") except KeyError as e: - logging.debug(e) + logging.error(e) pass # Add the optional Median test. @@ -273,12 +280,14 @@ def load_test(config, test_dir=get_root_dir()): try: median = config[median_test] all_ini_sections.remove(median_test) - test_config.add_expression_test('expression.median.', CALCS_TDS, median.get(KEY_EXCLUSIONS, ''), - get_expression_test_dir_path(median, 'exprtests/median/'), test_dir, - get_password_file(median), get_expected_message(median), - get_is_smoke_test(median), get_is_test_enabled(median), False) + test_config.add_expression_test( + 'expression.median.', CALCS_TDS, median.get(KEY_EXCLUSIONS, ''), + get_expression_test_dir_path(median, 'exprtests/median/'), test_dir, + get_password_file(median), get_expected_message(median), + get_is_smoke_test(median), get_is_test_enabled(median), False) + logging.info("\tAdded Median tests.") except KeyError as e: - logging.debug(e) + logging.error(e) pass # Add the optional Percentile test. @@ -286,12 +295,13 @@ def load_test(config, test_dir=get_root_dir()): try: percentile = config[percentile_test] all_ini_sections.remove(percentile_test) - test_config.add_expression_test('expression.percentile.', CALCS_TDS, percentile.get(KEY_EXCLUSIONS, ''), - 'exprtests/percentile', test_dir, get_password_file(percentile), - get_expected_message(percentile), get_is_smoke_test(percentile), - get_is_test_enabled(percentile), False) + test_config.add_expression_test( + 'expression.percentile.', CALCS_TDS, percentile.get(KEY_EXCLUSIONS, ''), + 'exprtests/percentile', test_dir, get_password_file(percentile), get_expected_message(percentile), + get_is_smoke_test(percentile), get_is_test_enabled(percentile), False) + logging.info("\tAdded Percentile tests.") except KeyError as e: - logging.debug(e) + logging.error(e) pass # Optional logical config settings. @@ -308,8 +318,9 @@ def load_test(config, test_dir=get_root_dir()): else: cfg_data[name][k] = cfg[k] test_config.add_logical_config(cfg_data) + logging.info("\tAdded logical config settings.") except KeyError as e: - logging.debug(e) + logging.error(e) pass # This is for custom tables with custom schema @@ -336,12 +347,13 @@ def load_test(config, test_dir=get_root_dir()): if new_expression_test in section or sect.get('Type', '') == 'expression': try: all_ini_sections.remove(section) - test_config.add_expression_test(sect.get('Name', ''), tds_name, sect.get(KEY_EXCLUSIONS, ''), - sect.get('TestPath', ''), test_dir, get_password_file(sect), - get_expected_message(sect), get_is_smoke_test(sect), - get_is_test_enabled(sect), False) + test_config.add_expression_test( + sect.get('Name', ''), tds_name, sect.get(KEY_EXCLUSIONS, ''), sect.get('TestPath', ''), test_dir, + get_password_file(sect), get_expected_message(sect), get_is_smoke_test(sect), + get_is_test_enabled(sect), False) + logging.info("\tAdded extra expression test: " + sect.get('Name', '')) except KeyError as e: - logging.debug(e) + logging.error(e) pass # Add any extra logical tests. @@ -352,29 +364,34 @@ def load_test(config, test_dir=get_root_dir()): sect.get('TestPath', ''), test_dir, get_password_file(sect), get_expected_message(sect), get_is_smoke_test(sect), get_is_test_enabled(sect), False) + logging.info("\tAdded extra logical test: " + sect.get('Name', '')) except KeyError as e: - logging.debug(e) + logging.error(e) pass # Add smoke tests elif connection_test in section: try: all_ini_sections.remove(section) test_config.add_logical_test('StaplesConnectionTest', STAPLES_TDS, sect.get(KEY_EXCLUSIONS, ''), - test_config.get_logical_test_path('logicaltests/setup/connection_test/setup.staples.*.'), # noqa: E501 + test_config.get_logical_test_path( + 'logicaltests/setup/connection_test/setup.staples.*.'), # noqa: E501 test_dir, get_password_file(sect), get_expected_message(sect), True, get_is_test_enabled(sect, 'StaplesTestEnabled'), False) test_config.add_expression_test('CastCalcsConnectionTest', CALCS_TDS, sect.get(KEY_EXCLUSIONS, ''), - get_expression_test_dir_path(sect, 'exprtests/pretest/connection_tests/calcs/'), # noqa: E501 + get_expression_test_dir_path(sect, + 'exprtests/pretest/connection_tests/calcs/'), + # noqa: E501 test_dir, get_password_file(sect), get_expected_message(sect), True, get_is_test_enabled(sect, 'CastCalcsTestEnabled'), False) + logging.info("\tAdded connection tests.") except KeyError as e: - logging.debug(e) + logging.error(e) pass if all_ini_sections: - logging.debug("Found unparsed sections in the ini file.") + logging.error("Found unparsed sections in the ini file.") for section in all_ini_sections: - logging.debug("Unparsed section: {0}".format(section)) + logging.error("Unparsed section: {0}".format(section)) logging.debug(test_config) return test_config @@ -390,14 +407,14 @@ def __init__(self, ini_file): # Read all the datasource ini files and load the test configuration. ini_files = get_all_ini_files_local_first('config') for f in ini_files: - logging.debug("Reading ini file [{}]".format(f)) + logging.info("Reading ini file [{}]".format(f)) config = configparser.ConfigParser() # Preserve the case of elements. config.optionxform = str try: config.read(f) except configparser.ParsingError as e: - logging.debug(e) + logging.error(e) continue self.add_test(load_test(config)) @@ -407,7 +424,7 @@ def __init__(self, ini_file): def load_ini_file(self, ini_file): # Create the test suites (groups of datasources to test) registry_ini_file = get_ini_path_local_first('config/registry', ini_file) - logging.debug("Reading registry ini file [{}]".format(registry_ini_file)) + logging.info("Reading registry ini file [{}]".format(registry_ini_file)) self.load_registry(registry_ini_file) def load_registry(self, registry_ini_file): @@ -417,7 +434,10 @@ def load_registry(self, registry_ini_file): ds = config['DatasourceRegistry'] for suite_name in ds: - self.suite_map[suite_name] = [x.strip() for x in self.interpret_ds_list(ds[suite_name], False).split(',')] + self.suite_map[suite_name] = [ + x.strip() for x in + self.interpret_ds_list(ds[suite_name], False).split(',') + ] except KeyError: # Create a simple default. @@ -466,6 +486,13 @@ def __init__(self): super(MacRegistry, self).__init__('mac') +class MacArmRegistry(TestRegistry): + """Mac ARM specific test suites.""" + + def __init__(self): + super(MacArmRegistry, self).__init__('mac_arm') + + class LinuxRegistry(TestRegistry): """Linux specific test suites.""" diff --git a/tdvt/tdvt/config_gen/gentests.py b/tdvt/tdvt/config_gen/gentests.py index ba10e81a..b8641832 100644 --- a/tdvt/tdvt/config_gen/gentests.py +++ b/tdvt/tdvt/config_gen/gentests.py @@ -7,6 +7,7 @@ import os import re import shutil + from string import Template from typing import Dict, List, Tuple @@ -14,9 +15,6 @@ from ..constants import CALCS_FIELDS, STAPLES_FIELDS -debug = False - - def get_logical_config_templates(ds_registry): all_templates = template_attributes.copy() @@ -129,22 +127,21 @@ def get_modified_line(line, attrs, fields, field_name_map): new_line = new_line.replace('$Staples$', staples_table_name) return new_line + + def process_test_file(filename, ds_registry, output_dir, col_names: List[List[str]]): - if debug: - print("Processing " + filename) + logging.debug("Processing " + filename) input_file = open(filename, 'r', encoding='utf-8') base_name = os.path.basename(filename) - if debug: - print("base_name " + base_name) + logging.debug("base_name " + base_name) match = re.search('setup\.(.*)\.xml', base_name) if match: test_name = match.group(1) else: test_name = os.path.splitext(base_name)[0] - if debug: - print("Test " + test_name) + logging.debug("Test " + test_name) fields = [] for table in col_names: diff --git a/tdvt/tdvt/config_gen/tdvtconfig.py b/tdvt/tdvt/config_gen/tdvtconfig.py index f884b131..dfda70ac 100644 --- a/tdvt/tdvt/config_gen/tdvtconfig.py +++ b/tdvt/tdvt/config_gen/tdvtconfig.py @@ -34,6 +34,7 @@ def __init__(self, from_args=None, from_json=None, test_config: TestConfig = Non self.iteration: int = 0 self.generate_expected = False self.schema_name: Optional[str] = None + self.loose_comparison = False if from_args: self.init_from_args(from_args) @@ -71,6 +72,8 @@ def init_from_args(self, args): self.iteration = args.perf_iteration if args.generate_expected: self.generate_expected = True + if args.loose_comparison: + self.loose_comparison = True def init_from_json(self, json): @@ -90,12 +93,13 @@ def init_from_json(self, json): rtt.set_tabquery_path_from_array(self.tabquery_path) self.tested_run_time_config = rtt self.thread_count = json.get('thread_count', self.thread_count) + self.loose_comparison = json.get('loose_comparison', self.loose_comparison) def __str__(self): return ("suite [{}]: tested sql [{}]: tested tuples [{}]: tested error [{}]: output dir [{}]: " + - "logical [{}]: config file [{}]: override [{}]: tds [{}]: thread [{}]").format( + "logical [{}]: config file [{}]: override [{}]: tds [{}]: thread [{}], loose comparison [{}]").format( self.suite_name, self.tested_sql, self.tested_tuples, self.tested_error, self.output_dir, - self.logical, self.config_file, self.d_override, self.tds, self.thread_count) + self.logical, self.config_file, self.d_override, self.tds, self.thread_count, self.loose_comparison) def __json__(self): return { @@ -111,7 +115,8 @@ def __json__(self): 'tds': self.tds, 'noheader': self.noheader, 'tabquery_path': self.tabquery_path, - 'thread_count': self.thread_count} + 'thread_count': self.thread_count, + 'loose_comparison': self.loose_comparison} def __eq__(self, other): if isinstance(other, self.__class__): diff --git a/tdvt/tdvt/config_gen/test_config.py b/tdvt/tdvt/config_gen/test_config.py index c35fba98..1794ba53 100644 --- a/tdvt/tdvt/config_gen/test_config.py +++ b/tdvt/tdvt/config_gen/test_config.py @@ -24,13 +24,16 @@ def __init__(self, root_dir, full_test_path): def __str__(self): return self.test_path + class TestSet(object): """ Represents everything needed to run a set of tests. This includes a path to the test files, which tds etc. """ - def __init__(self, ds_name, root_dir, config_name, tds_name, exclusions, test_pattern, is_logical, suite_name, password_file, - expected_message: str = '', smoke_test: bool = False, test_is_enabled: bool = True, - test_is_skipped: bool = False): + def __init__( + self, ds_name, root_dir, config_name, tds_name, exclusions, test_pattern, is_logical, suite_name, password_file, + expected_message: str = '', smoke_test: bool = False, test_is_enabled: bool = True, + test_is_skipped: bool = False + ): self.ds_name = ds_name self.suite_name = suite_name self.config_name = config_name @@ -52,7 +55,9 @@ def is_logical_test(self): return self.is_logical def get_password_file_name(self): - return get_resource_full_path(self.root_dir, self.suite_name + ".password", "tds") if not self.password_file else get_resource_full_path(self.root_dir, self.password_file, "tds") + return get_resource_full_path(self.root_dir, self.suite_name + ".password", "tds") \ + if not self.password_file \ + else get_resource_full_path(self.root_dir, self.password_file, "tds") def get_expected_message(self): return self.expected_message @@ -117,7 +122,7 @@ def __generate_test_file_list(self): break if added_test == len(tests_to_run): - logging.debug("Could not find any tests for [" + "] or [".join(checked_paths) + "]. Check the path.") + logging.error("Could not find any tests for [" + "] or [".join(checked_paths) + "]. Check the path.") logging.debug("Found " + str(len(tests_to_run)) + " tests to run before exclusions.") @@ -147,7 +152,10 @@ def get_exclusions(self): return [] if not self.exclusions else self.exclusions.split(',') def __str__(self): - return "[name={0}] [tds={1}] [exclusions={2}] [test pattern={3}] [is_logical={4}] [root_dir={5}]".format(self.config_name, self.tds_name, self.exclusions, self.test_pattern, self.is_logical, self.root_dir) + return ( + f"[name={self.config_name}] [tds={self.tds_name}] [exclusions={self.exclusions}] \ + [test pattern={self.test_pattern}] [is_logical={self.is_logical}] [root_dir={self.root_dir}]" + ) def __eq__(self, other): if isinstance(other, self.__class__): @@ -213,12 +221,16 @@ def get_actual_and_base_file_path(self, test_file, output_dir): existing_output_filepath, actual_output_filepath, base_test_name, base_filepath, expected_dir = get_logical_test_file_paths(test_file, output_dir) return actual_output_filepath, base_filepath + class ExpressionTestSet(TestSet): - def __init__(self, ds_name, root_dir, config_name, tds_name, exclusions, test_pattern, suite, password_file='', - expected_message='', smoke_test=False, test_is_enabled=True, test_is_skipped=False): - super(ExpressionTestSet, self).__init__(ds_name, root_dir, config_name, tds_name, - exclusions, test_pattern, False, suite, password_file, expected_message, - smoke_test, test_is_enabled, test_is_skipped) + def __init__( + self, ds_name, root_dir, config_name, tds_name, exclusions, test_pattern, suite, password_file='', + expected_message='', smoke_test=False, test_is_enabled=True, test_is_skipped=False + ): + super(ExpressionTestSet, self).__init__( + ds_name, root_dir, config_name, tds_name, exclusions, test_pattern, False, suite, password_file, + expected_message, smoke_test, test_is_enabled, test_is_skipped + ) def get_expected_output_file_path(self, test_file, output_dir): base_test_file = get_base_test(test_file) @@ -226,42 +238,48 @@ def get_expected_output_file_path(self, test_file, output_dir): existing_output_filepath, actual_diff_file, setup, expected_files, next_path = get_test_file_paths(test_file_root, base_test_file, output_dir) return existing_output_filepath + class SingleLogicalTestSet(LogicalTestSet): def __init__(self, ds_name, root_dir, test_pattern, tds_pattern, exclude_pattern, ds_info, password_file='', expected_message='', smoke_test=False, test_is_enabled=True, test_is_skipped=False): - super(SingleLogicalTestSet, self).__init__(ds_name, root_dir, 'temp' + ds_info.dsname, tds_pattern, - exclude_pattern, test_pattern, ds_info.dsname, - password_file, expected_message, smoke_test, test_is_enabled, - test_is_skipped) + super(SingleLogicalTestSet, self).__init__( + ds_name, root_dir, 'temp' + ds_info.dsname, tds_pattern, exclude_pattern, test_pattern, ds_info.dsname, + password_file, expected_message, smoke_test, test_is_enabled, test_is_skipped + ) self.test_pattern = self.test_pattern.replace('?', ds_info.logical_config_name) self.tds_name = tds_pattern.replace('*', ds_info.dsname) + class SingleExpressionTestSet(ExpressionTestSet): def __init__(self, ds_name, root_dir, test_pattern, tds_pattern, exclude_pattern, ds_info, password_file='', - expected_message='', smoke_test=False, test_is_enabled=True, test_is_skipped=False): - super(SingleExpressionTestSet, self).__init__(ds_name, root_dir, 'temp' + ds_info.dsname, tds_pattern, - exclude_pattern, test_pattern, ds_info.dsname, - password_file, expected_message, smoke_test, test_is_enabled, - test_is_skipped) + expected_message='', smoke_test=False, test_is_enabled=True, test_is_skipped=False, + ): + super(SingleExpressionTestSet, self).__init__( + ds_name, root_dir, 'temp' + ds_info.dsname, tds_pattern, exclude_pattern, test_pattern, ds_info.dsname, + password_file, expected_message, smoke_test, test_is_enabled, test_is_skipped + ) self.tds_name = tds_pattern.replace('*', ds_info.dsname) + def build_config_name(prefix, dsname): return prefix + dsname + '.cfg' + def build_tds_name(prefix, dsname): return prefix + dsname + '.tds' + class RunTimeTestConfig(object): """ Tracks specifics about how a group of tests were run. """ def __init__( self, - timeout_seconds: int=60*60, - maxthread: int=0, - d_override: str='', - run_as_perf: bool=False, - schema_name: Optional[str]=None, + timeout_seconds: int = 60*60, + maxthread: int = 0, + d_override: str = '', + run_as_perf: bool = False, + schema_name: Optional[str] = None, ): self.timeout_seconds = timeout_seconds self.d_override = d_override @@ -270,10 +288,10 @@ def __init__( self.schema_name = schema_name self.tabquery_paths = None - def set_tabquery_paths(self, linux_path, mac_path, windows_path): - if not linux_path and not mac_path and not windows_path: + def set_tabquery_paths(self, linux_path, mac_path, mac_arm_path, windows_path): + if not linux_path and not mac_path and not mac_arm_path and not windows_path: return - self.tabquery_paths = TabQueryPath(linux_path, mac_path, windows_path) + self.tabquery_paths = TabQueryPath(linux_path, mac_path, mac_arm_path, windows_path) def set_tabquery_path_from_array(self, path_list): if not path_list: diff --git a/tdvt/tdvt/exprtests/lodcalcs/expected.setup.lod.calcs.txt b/tdvt/tdvt/exprtests/lodcalcs/expected.setup.lod.calcs.txt index 3596dfa3..b8e7c1e2 100644 --- a/tdvt/tdvt/exprtests/lodcalcs/expected.setup.lod.calcs.txt +++ b/tdvt/tdvt/exprtests/lodcalcs/expected.setup.lod.calcs.txt @@ -1,8 +1,8 @@ - + - [cast_calcs.sqlserver].[TEMP(Test)(2300115098)(0)] + [cast_calcs.sqlserver].[TEMP(Test)(2300115098)(0)] 2.47 @@ -57,20 +57,20 @@
- + - [cast_calcs.sqlserver].[TEMP(Test)(4279721284)(0)] + [cast_calcs.sqlserver].[TEMP(Test)(4279721284)(0)] 166.68
- + - [cast_calcs.sqlserver].[TEMP(Test)(3262646021)(0)] + [cast_calcs.sqlserver].[TEMP(Test)(3262646021)(0)] 2.47 @@ -125,20 +125,20 @@
- + - [cast_calcs.sqlserver].[TEMP(Test)(3502400386)(0)] + [cast_calcs.sqlserver].[TEMP(Test)(3502400386)(0)] 17.0
- + - [cast_calcs.sqlserver].[TEMP(Test)(1869227114)(0)] + [cast_calcs.sqlserver].[TEMP(Test)(1869227114)(0)] 2.47 diff --git a/tdvt/tdvt/exprtests/median/expected.setup.agg.median.txt b/tdvt/tdvt/exprtests/median/expected.setup.agg.median.txt index 4796674b..a4a0c403 100644 --- a/tdvt/tdvt/exprtests/median/expected.setup.agg.median.txt +++ b/tdvt/tdvt/exprtests/median/expected.setup.agg.median.txt @@ -1,38 +1,38 @@ - +
- [cast_calcs.hyper].[TEMP(Test)(925086242)(0)] + [cast_calcs.hyper].[TEMP(Test)(925086242)(0)] 0.0
- + - [cast_calcs.hyper].[TEMP(Test)(3622506995)(0)] + [cast_calcs.hyper].[TEMP(Test)(3622506995)(0)] 10.98
- + - [cast_calcs.hyper].[TEMP(Test)(1798641580)(0)] + [cast_calcs.hyper].[TEMP(Test)(1798641580)(0)] 4.295
- + - [cast_calcs.hyper].[TEMP(Test)(1667576385)(0)] + [cast_calcs.hyper].[TEMP(Test)(1667576385)(0)] 1988.0 diff --git a/tdvt/tdvt/exprtests/percentile/expected.setup.agg.percentile.1.txt b/tdvt/tdvt/exprtests/percentile/expected.setup.agg.percentile.1.txt index 1b4dd928..85a524df 100644 --- a/tdvt/tdvt/exprtests/percentile/expected.setup.agg.percentile.1.txt +++ b/tdvt/tdvt/exprtests/percentile/expected.setup.agg.percentile.1.txt @@ -5,7 +5,7 @@ [cast_calcs.sparksql].[TEMP(Test)(1005283190)(0)] - 9.98 + 10.98
diff --git a/tdvt/tdvt/exprtests/percentile/expected.setup.agg.percentile.txt b/tdvt/tdvt/exprtests/percentile/expected.setup.agg.percentile.txt index 22125349..f9ba0c10 100644 --- a/tdvt/tdvt/exprtests/percentile/expected.setup.agg.percentile.txt +++ b/tdvt/tdvt/exprtests/percentile/expected.setup.agg.percentile.txt @@ -1,48 +1,48 @@ - + - [cast_calcs.hyper].[TEMP(Test)(1005283190)(0)] + [cast_calcs.hyper].[TEMP(Test)(1005283190)(0)] 10.98
- + - [cast_calcs.hyper].[TEMP(Test)(3070691569)(0)] + [cast_calcs.hyper].[TEMP(Test)(3070691569)(0)] 8.9175
- + - [cast_calcs.hyper].[TEMP(Test)(1236390098)(0)] + [cast_calcs.hyper].[TEMP(Test)(1236390098)(0)] -9.0
- + - [cast_calcs.hyper].[TEMP(Test)(1981734878)(0)] + [cast_calcs.hyper].[TEMP(Test)(1981734878)(0)] 3.0
- + - [cast_calcs.hyper].[TEMP(Test)(1162356411)(0)] + [cast_calcs.hyper].[TEMP(Test)(1162356411)(0)] 1988.0 diff --git a/tdvt/tdvt/exprtests/regexcalcs/expected.setup.string.regexp.extract_nth.extended.xfail.txt b/tdvt/tdvt/exprtests/regexcalcs/expected.setup.string.regexp.extract_nth.extended.xfail.txt new file mode 100644 index 00000000..61ff71a1 --- /dev/null +++ b/tdvt/tdvt/exprtests/regexcalcs/expected.setup.string.regexp.extract_nth.extended.xfail.txt @@ -0,0 +1,18 @@ + + + + No more than 9 capture groups can be specified. + + Invalid Expression +
+
+
+ + + No more than 9 capture groups can be specified. + + Invalid Expression + +
+
+
\ No newline at end of file diff --git a/tdvt/tdvt/exprtests/regexcalcs/setup.string.regexp.extract_nth.extended.xfail.txt b/tdvt/tdvt/exprtests/regexcalcs/setup.string.regexp.extract_nth.extended.xfail.txt new file mode 100644 index 00000000..0b985ccc --- /dev/null +++ b/tdvt/tdvt/exprtests/regexcalcs/setup.string.regexp.extract_nth.extended.xfail.txt @@ -0,0 +1,2 @@ +REGEXP_EXTRACT_NTH("tableau123", "[a-z]{7}([0-9]{3})", 10) //"No more than 9 capture groups can be specified." +REGEXP_EXTRACT_NTH("tableau123", "([a-z]{7})([0-9]{3})", 10) //"No more than 9 capture groups can be specified." \ No newline at end of file diff --git a/tdvt/tdvt/exprtests/standard/expected.setup.agg.avg.txt b/tdvt/tdvt/exprtests/standard/expected.setup.agg.avg.txt index a2195863..5b780e13 100644 --- a/tdvt/tdvt/exprtests/standard/expected.setup.agg.avg.txt +++ b/tdvt/tdvt/exprtests/standard/expected.setup.agg.avg.txt @@ -1,18 +1,18 @@ - + - [cast_calcs.postgres91].[TEMP(Test)(3952218057)(0)] + [cast_calcs.postgres91].[TEMP(Test)(3952218057)(0)] 6.1818182
- + - [cast_calcs.postgres91].[TEMP(Test)(1371989636)(0)] + [cast_calcs.postgres91].[TEMP(Test)(1371989636)(0)] 2.0016667 diff --git a/tdvt/tdvt/exprtests/standard/expected.setup.cast.float.txt b/tdvt/tdvt/exprtests/standard/expected.setup.cast.float.txt index 95da22eb..425f0f62 100644 --- a/tdvt/tdvt/exprtests/standard/expected.setup.cast.float.txt +++ b/tdvt/tdvt/exprtests/standard/expected.setup.cast.float.txt @@ -1,8 +1,8 @@ - +
- [cast_calcs.postgres91].[TEMP(Test)(1533389080)(0)] + [cast_calcs.postgres91].[TEMP(Test)(1533389080)(0)] %null% @@ -30,10 +30,10 @@
- + - [cast_calcs.postgres91].[TEMP(Test)(2538631291)(0)] + [cast_calcs.postgres91].[TEMP(Test)(2538631291)(0)] %null% @@ -46,10 +46,10 @@
- + - [cast_calcs.postgres91].[TEMP(Test)(64617177)(0)] + [cast_calcs.postgres91].[TEMP(Test)(64617177)(0)] %null% @@ -71,10 +71,10 @@
- + - [cast_calcs.postgres91].[TEMP(Test)(2707307071)(0)] + [cast_calcs.postgres91].[TEMP(Test)(2707307071)(0)] %null% diff --git a/tdvt/tdvt/exprtests/standard/expected.setup.date.dateadd.hour.txt b/tdvt/tdvt/exprtests/standard/expected.setup.date.dateadd.hour.txt index d12aa20c..bfd2f52f 100644 --- a/tdvt/tdvt/exprtests/standard/expected.setup.date.dateadd.hour.txt +++ b/tdvt/tdvt/exprtests/standard/expected.setup.date.dateadd.hour.txt @@ -1,4 +1,62 @@ + +
+ + [cast_calcs.postgres].[TEMP(Test)(4261466899)(0)] + + + #1972-07-12 01:00:00# + + + #1974-03-17 01:00:00# + + + #1974-05-03 01:00:00# + + + #1976-09-09 01:00:00# + + + #1977-02-08 01:00:00# + + + #1977-04-20 01:00:00# + + + #1980-07-26 01:00:00# + + + #1980-11-07 01:00:00# + + + #1988-01-05 01:00:00# + + + #1994-04-20 01:00:00# + + + #1995-06-04 01:00:00# + + + #1995-09-03 01:00:00# + + + #1997-05-30 01:00:00# + + + #1997-09-19 01:00:00# + + + #1998-08-12 01:00:00# + + + #2001-02-04 01:00:00# + + + #2002-04-27 01:00:00# + +
+
@@ -57,4 +115,4 @@
-
+
\ No newline at end of file diff --git a/tdvt/tdvt/exprtests/standard/expected.setup.date.dateadd.minute.txt b/tdvt/tdvt/exprtests/standard/expected.setup.date.dateadd.minute.txt index 1eac8472..9e8b2d18 100644 --- a/tdvt/tdvt/exprtests/standard/expected.setup.date.dateadd.minute.txt +++ b/tdvt/tdvt/exprtests/standard/expected.setup.date.dateadd.minute.txt @@ -1,4 +1,62 @@ + + + + [cast_calcs.postgres].[TEMP(Test)(2741755004)(0)] + + + #1972-07-12 00:01:00# + + + #1974-03-17 00:01:00# + + + #1974-05-03 00:01:00# + + + #1976-09-09 00:01:00# + + + #1977-02-08 00:01:00# + + + #1977-04-20 00:01:00# + + + #1980-07-26 00:01:00# + + + #1980-11-07 00:01:00# + + + #1988-01-05 00:01:00# + + + #1994-04-20 00:01:00# + + + #1995-06-04 00:01:00# + + + #1995-09-03 00:01:00# + + + #1997-05-30 00:01:00# + + + #1997-09-19 00:01:00# + + + #1998-08-12 00:01:00# + + + #2001-02-04 00:01:00# + + + #2002-04-27 00:01:00# + +
+
@@ -57,4 +115,4 @@
-
+ \ No newline at end of file diff --git a/tdvt/tdvt/exprtests/standard/expected.setup.date.dateadd.second.txt b/tdvt/tdvt/exprtests/standard/expected.setup.date.dateadd.second.txt index 03e2bb2f..77634f31 100644 --- a/tdvt/tdvt/exprtests/standard/expected.setup.date.dateadd.second.txt +++ b/tdvt/tdvt/exprtests/standard/expected.setup.date.dateadd.second.txt @@ -1,4 +1,62 @@ + + + + [cast_calcs.postgres].[TEMP(Test)(621896091)(0)] + + + #1972-07-12 00:00:01# + + + #1974-03-17 00:00:01# + + + #1974-05-03 00:00:01# + + + #1976-09-09 00:00:01# + + + #1977-02-08 00:00:01# + + + #1977-04-20 00:00:01# + + + #1980-07-26 00:00:01# + + + #1980-11-07 00:00:01# + + + #1988-01-05 00:00:01# + + + #1994-04-20 00:00:01# + + + #1995-06-04 00:00:01# + + + #1995-09-03 00:00:01# + + + #1997-05-30 00:00:01# + + + #1997-09-19 00:00:01# + + + #1998-08-12 00:00:01# + + + #2001-02-04 00:00:01# + + + #2002-04-27 00:00:01# + +
+
@@ -57,4 +115,4 @@
-
+ \ No newline at end of file diff --git a/tdvt/tdvt/exprtests/standard/expected.setup.date.math.date_minus_date.txt b/tdvt/tdvt/exprtests/standard/expected.setup.date.math.date_minus_date.txt index 0bc7f050..9ad0e757 100644 --- a/tdvt/tdvt/exprtests/standard/expected.setup.date.math.date_minus_date.txt +++ b/tdvt/tdvt/exprtests/standard/expected.setup.date.math.date_minus_date.txt @@ -1,8 +1,8 @@ - + - [cast_calcs.postgres91].[TEMP(Test)(1152843842)(0)] + [cast_calcs.postgres91].[TEMP(Test)(1152843842)(0)] 0.0 diff --git a/tdvt/tdvt/exprtests/standard/expected.setup.date.math.txt b/tdvt/tdvt/exprtests/standard/expected.setup.date.math.txt index 2561caf0..1cc130fd 100644 --- a/tdvt/tdvt/exprtests/standard/expected.setup.date.math.txt +++ b/tdvt/tdvt/exprtests/standard/expected.setup.date.math.txt @@ -251,10 +251,10 @@
- + - [cast_calcs.postgres91].[TEMP(Test)(2141740056)(0)] + [cast_calcs.postgres91].[TEMP(Test)(2141740056)(0)] 0.0 diff --git a/tdvt/tdvt/exprtests/standard/expected.setup.logical.bool.txt b/tdvt/tdvt/exprtests/standard/expected.setup.logical.bool.txt index 76ea6ea4..714a4afb 100644 --- a/tdvt/tdvt/exprtests/standard/expected.setup.logical.bool.txt +++ b/tdvt/tdvt/exprtests/standard/expected.setup.logical.bool.txt @@ -58,10 +58,10 @@
- + - [cast_calcs.sqlserver].[TEMP(Test)(3428504110)(0)] + [cast_calcs.sqlserver].[TEMP(Test)(3428504110)(0)] %null% @@ -156,10 +156,10 @@
- + - [cast_calcs.sqlserver].[TEMP(Test)(750655768)(0)] + [cast_calcs.sqlserver].[TEMP(Test)(750655768)(0)] %null% @@ -257,10 +257,10 @@
- + - [cast_calcs.sqlserver].[TEMP(Test)(898375479)(0)] + [cast_calcs.sqlserver].[TEMP(Test)(898375479)(0)] %null% diff --git a/tdvt/tdvt/exprtests/standard/expected.setup.logical.txt b/tdvt/tdvt/exprtests/standard/expected.setup.logical.txt index 364a8bba..b64b60ec 100644 --- a/tdvt/tdvt/exprtests/standard/expected.setup.logical.txt +++ b/tdvt/tdvt/exprtests/standard/expected.setup.logical.txt @@ -147,10 +147,10 @@
- + - [cast_calcs.sqlserver].[TEMP(Test)(2733626226)(0)] + [cast_calcs.sqlserver].[TEMP(Test)(2733626226)(0)] %null% @@ -414,10 +414,10 @@
- + - [cast_calcs.sqlserver].[TEMP(Test)(1162317302)(0)] + [cast_calcs.sqlserver].[TEMP(Test)(1162317302)(0)] %null% @@ -534,10 +534,10 @@
- + - [cast_calcs.sqlserver].[TEMP(Test)(4224438892)(0)] + [cast_calcs.sqlserver].[TEMP(Test)(4224438892)(0)] -14.21 @@ -658,10 +658,10 @@
- + - [cast_calcs.sqlserver].[TEMP(Test)(709594122)(0)] + [cast_calcs.sqlserver].[TEMP(Test)(709594122)(0)] 2.47 @@ -820,10 +820,10 @@
- + - [cast_calcs.sqlserver].[TEMP(Test)(4143049742)(0)] + [cast_calcs.sqlserver].[TEMP(Test)(4143049742)(0)] %null% @@ -961,10 +961,10 @@
- + - [cast_calcs.sqlserver].[TEMP(Test)(1574830296)(0)] + [cast_calcs.sqlserver].[TEMP(Test)(1574830296)(0)] %null% diff --git a/tdvt/tdvt/exprtests/standard/expected.setup.math.abs.txt b/tdvt/tdvt/exprtests/standard/expected.setup.math.abs.txt index 7020afd0..375b78e1 100644 --- a/tdvt/tdvt/exprtests/standard/expected.setup.math.abs.txt +++ b/tdvt/tdvt/exprtests/standard/expected.setup.math.abs.txt @@ -30,10 +30,10 @@
- + - [cast_calcs.postgres91].[TEMP(Test)(3816473022)(0)] + [cast_calcs.postgres91].[TEMP(Test)(3816473022)(0)] %null% diff --git a/tdvt/tdvt/exprtests/standard/expected.setup.math.acos.txt b/tdvt/tdvt/exprtests/standard/expected.setup.math.acos.txt index d2c7a78a..7ef01803 100644 --- a/tdvt/tdvt/exprtests/standard/expected.setup.math.acos.txt +++ b/tdvt/tdvt/exprtests/standard/expected.setup.math.acos.txt @@ -1,8 +1,8 @@ - +
- [cast_calcs.postgres91].[TEMP(Test)(4196263986)(0)] + [cast_calcs.postgres91].[TEMP(Test)(4196263986)(0)] %null% diff --git a/tdvt/tdvt/exprtests/standard/expected.setup.math.asin.txt b/tdvt/tdvt/exprtests/standard/expected.setup.math.asin.txt index 2c3c2274..7551d5ee 100644 --- a/tdvt/tdvt/exprtests/standard/expected.setup.math.asin.txt +++ b/tdvt/tdvt/exprtests/standard/expected.setup.math.asin.txt @@ -1,8 +1,8 @@ - +
- [cast_calcs.postgres91].[TEMP(Test)(1317198372)(0)] + [cast_calcs.postgres91].[TEMP(Test)(1317198372)(0)] %null% diff --git a/tdvt/tdvt/exprtests/standard/expected.setup.math.cos.txt b/tdvt/tdvt/exprtests/standard/expected.setup.math.cos.txt index 0aefbd01..b8534061 100644 --- a/tdvt/tdvt/exprtests/standard/expected.setup.math.cos.txt +++ b/tdvt/tdvt/exprtests/standard/expected.setup.math.cos.txt @@ -1,8 +1,8 @@ - +
- [cast_calcs.postgres91].[TEMP(Test)(344207442)(0)] + [cast_calcs.postgres91].[TEMP(Test)(344207442)(0)] -0.9899925 @@ -30,10 +30,10 @@
- + - [cast_calcs.postgres91].[TEMP(Test)(1355320598)(0)] + [cast_calcs.postgres91].[TEMP(Test)(1355320598)(0)] %null% diff --git a/tdvt/tdvt/exprtests/standard/expected.setup.math.cot.txt b/tdvt/tdvt/exprtests/standard/expected.setup.math.cot.txt index 4b1b6c1d..c1f1b062 100644 --- a/tdvt/tdvt/exprtests/standard/expected.setup.math.cot.txt +++ b/tdvt/tdvt/exprtests/standard/expected.setup.math.cot.txt @@ -1,8 +1,8 @@ - +
- [cast_calcs.postgres91].[TEMP(Test)(2415226193)(0)] + [cast_calcs.postgres91].[TEMP(Test)(2415226193)(0)] %null% @@ -45,10 +45,10 @@
- + - [cast_calcs.postgres91].[TEMP(Test)(2834009176)(0)] + [cast_calcs.postgres91].[TEMP(Test)(2834009176)(0)] %null% diff --git a/tdvt/tdvt/exprtests/standard/expected.setup.math.degree.txt b/tdvt/tdvt/exprtests/standard/expected.setup.math.degree.txt index 803bca1f..b942ba16 100644 --- a/tdvt/tdvt/exprtests/standard/expected.setup.math.degree.txt +++ b/tdvt/tdvt/exprtests/standard/expected.setup.math.degree.txt @@ -1,8 +1,8 @@ - +
- [cast_calcs.postgres91].[TEMP(Test)(2688244734)(0)] + [cast_calcs.postgres91].[TEMP(Test)(2688244734)(0)] -515.66202 @@ -45,10 +45,10 @@
- + - [cast_calcs.postgres91].[TEMP(Test)(583539797)(0)] + [cast_calcs.postgres91].[TEMP(Test)(583539797)(0)] %null% diff --git a/tdvt/tdvt/exprtests/standard/expected.setup.math.exp.txt b/tdvt/tdvt/exprtests/standard/expected.setup.math.exp.txt index 5ad7064b..b3c1de3f 100644 --- a/tdvt/tdvt/exprtests/standard/expected.setup.math.exp.txt +++ b/tdvt/tdvt/exprtests/standard/expected.setup.math.exp.txt @@ -1,8 +1,8 @@ - +
- [cast_calcs.postgres91].[TEMP(Test)(526466750)(0)] + [cast_calcs.postgres91].[TEMP(Test)(526466750)(0)] %null% @@ -33,10 +33,10 @@
- + - [cast_calcs.postgres91].[TEMP(Test)(2988208579)(0)] + [cast_calcs.postgres91].[TEMP(Test)(2988208579)(0)] 0.0001234098 diff --git a/tdvt/tdvt/exprtests/standard/expected.setup.math.hexbin.txt b/tdvt/tdvt/exprtests/standard/expected.setup.math.hexbin.txt index 7dc7f8ea..d2e2fea2 100644 --- a/tdvt/tdvt/exprtests/standard/expected.setup.math.hexbin.txt +++ b/tdvt/tdvt/exprtests/standard/expected.setup.math.hexbin.txt @@ -1,8 +1,8 @@ - +
- [cast_calcs.postgres91].[TEMP(Test)(2503102272)(0)] + [cast_calcs.postgres91].[TEMP(Test)(2503102272)(0)] -9.0 @@ -39,10 +39,10 @@
- + - [cast_calcs.postgres91].[TEMP(Test)(2977666156)(0)] + [cast_calcs.postgres91].[TEMP(Test)(2977666156)(0)] 1.732 diff --git a/tdvt/tdvt/exprtests/standard/expected.setup.math.ln.txt b/tdvt/tdvt/exprtests/standard/expected.setup.math.ln.txt index 7905528f..feae5d02 100644 --- a/tdvt/tdvt/exprtests/standard/expected.setup.math.ln.txt +++ b/tdvt/tdvt/exprtests/standard/expected.setup.math.ln.txt @@ -1,8 +1,8 @@ - +
- [cast_calcs.postgres91].[TEMP(Test)(2832324438)(0)] + [cast_calcs.postgres91].[TEMP(Test)(2832324438)(0)] %null% @@ -27,10 +27,10 @@
- + - [cast_calcs.postgres91].[TEMP(Test)(1125921255)(0)] + [cast_calcs.postgres91].[TEMP(Test)(1125921255)(0)] %null% diff --git a/tdvt/tdvt/exprtests/standard/expected.setup.math.log.txt b/tdvt/tdvt/exprtests/standard/expected.setup.math.log.txt index 0ea8dcb4..a4a73b74 100644 --- a/tdvt/tdvt/exprtests/standard/expected.setup.math.log.txt +++ b/tdvt/tdvt/exprtests/standard/expected.setup.math.log.txt @@ -1,8 +1,8 @@ - +
- [cast_calcs.postgres91].[TEMP(Test)(114283928)(0)] + [cast_calcs.postgres91].[TEMP(Test)(114283928)(0)] %null% @@ -27,10 +27,10 @@
- + - [cast_calcs.postgres91].[TEMP(Test)(3322085183)(0)] + [cast_calcs.postgres91].[TEMP(Test)(3322085183)(0)] %null% @@ -55,10 +55,10 @@
- + - [cast_calcs.postgres91].[TEMP(Test)(1814892178)(0)] + [cast_calcs.postgres91].[TEMP(Test)(1814892178)(0)] %null% @@ -77,10 +77,10 @@
- + - [cast_calcs.postgres91].[TEMP(Test)(3081102343)(0)] + [cast_calcs.postgres91].[TEMP(Test)(3081102343)(0)] %null% diff --git a/tdvt/tdvt/exprtests/standard/expected.setup.math.pi.txt b/tdvt/tdvt/exprtests/standard/expected.setup.math.pi.txt index 35930d37..ae3f2673 100644 --- a/tdvt/tdvt/exprtests/standard/expected.setup.math.pi.txt +++ b/tdvt/tdvt/exprtests/standard/expected.setup.math.pi.txt @@ -1,18 +1,18 @@ - +
- [cast_calcs.postgres91].[TEMP(Test)(356598120)(0)] + [cast_calcs.postgres91].[TEMP(Test)(356598120)(0)] 3.1415927
- + - [cast_calcs.postgres91].[TEMP(Test)(1299212312)(0)] + [cast_calcs.postgres91].[TEMP(Test)(1299212312)(0)] %null% diff --git a/tdvt/tdvt/exprtests/standard/expected.setup.math.power.real.txt b/tdvt/tdvt/exprtests/standard/expected.setup.math.power.real.txt index 134a8d0e..0d17047f 100644 --- a/tdvt/tdvt/exprtests/standard/expected.setup.math.power.real.txt +++ b/tdvt/tdvt/exprtests/standard/expected.setup.math.power.real.txt @@ -1,8 +1,8 @@ - +
- [cast_calcs.postgres91].[TEMP(Test)(3264960529)(0)] + [cast_calcs.postgres91].[TEMP(Test)(3264960529)(0)] %null% @@ -30,10 +30,10 @@
- + - [cast_calcs.postgres91].[TEMP(Test)(2631457506)(0)] + [cast_calcs.postgres91].[TEMP(Test)(2631457506)(0)] %null% diff --git a/tdvt/tdvt/exprtests/standard/expected.setup.math.power.txt b/tdvt/tdvt/exprtests/standard/expected.setup.math.power.txt index fa95440d..e5fc068a 100644 --- a/tdvt/tdvt/exprtests/standard/expected.setup.math.power.txt +++ b/tdvt/tdvt/exprtests/standard/expected.setup.math.power.txt @@ -1,8 +1,8 @@ - +
- [cast_calcs.postgres91].[TEMP(Test)(3037854782)(0)] + [cast_calcs.postgres91].[TEMP(Test)(3037854782)(0)] 0.0 diff --git a/tdvt/tdvt/exprtests/standard/expected.setup.math.radians.txt b/tdvt/tdvt/exprtests/standard/expected.setup.math.radians.txt index 22cafc91..0c791d83 100644 --- a/tdvt/tdvt/exprtests/standard/expected.setup.math.radians.txt +++ b/tdvt/tdvt/exprtests/standard/expected.setup.math.radians.txt @@ -1,8 +1,8 @@ - +
- [cast_calcs.postgres91].[TEMP(Test)(1973795369)(0)] + [cast_calcs.postgres91].[TEMP(Test)(1973795369)(0)] -0.15707963 @@ -45,10 +45,10 @@
- + - [cast_calcs.postgres91].[TEMP(Test)(2823743498)(0)] + [cast_calcs.postgres91].[TEMP(Test)(2823743498)(0)] %null% diff --git a/tdvt/tdvt/exprtests/standard/expected.setup.math.round.B584401.txt b/tdvt/tdvt/exprtests/standard/expected.setup.math.round.B584401.txt index d920a57a..feae39cd 100644 --- a/tdvt/tdvt/exprtests/standard/expected.setup.math.round.B584401.txt +++ b/tdvt/tdvt/exprtests/standard/expected.setup.math.round.B584401.txt @@ -1,8 +1,8 @@ - +
- [cast_calcs.hyper].[TEMP(Test)(3830326670)(0)] + [cast_calcs.hyper].[TEMP(Test)(3830326670)(0)] -20.0 @@ -45,10 +45,10 @@
- + - [cast_calcs.hyper].[TEMP(Test)(4174655436)(0)] + [cast_calcs.hyper].[TEMP(Test)(4174655436)(0)] -20.0 diff --git a/tdvt/tdvt/exprtests/standard/expected.setup.math.round.extended.txt b/tdvt/tdvt/exprtests/standard/expected.setup.math.round.extended.txt index 580aaeca..fc3e74b2 100644 --- a/tdvt/tdvt/exprtests/standard/expected.setup.math.round.extended.txt +++ b/tdvt/tdvt/exprtests/standard/expected.setup.math.round.extended.txt @@ -1,8 +1,8 @@ - +
- [cast_calcs.postgres].[TEMP(Test)(2652477747)(0)] + [cast_calcs.postgres].[TEMP(Test)(2652477747)(0)] %null% @@ -33,10 +33,10 @@
- + - [cast_calcs.postgres].[TEMP(Test)(105980138)(0)] + [cast_calcs.postgres].[TEMP(Test)(105980138)(0)] %null% diff --git a/tdvt/tdvt/exprtests/standard/expected.setup.math.round.txt b/tdvt/tdvt/exprtests/standard/expected.setup.math.round.txt index 210d46e5..86b9d8b5 100644 --- a/tdvt/tdvt/exprtests/standard/expected.setup.math.round.txt +++ b/tdvt/tdvt/exprtests/standard/expected.setup.math.round.txt @@ -1,8 +1,8 @@ - +
- [cast_calcs.postgres91].[TEMP(Test)(366741644)(0)] + [cast_calcs.postgres91].[TEMP(Test)(366741644)(0)] -9.0 @@ -48,7 +48,7 @@
- [cast_calcs.postgres91].[TEMP(Test)(1240237577)(0)] + [cast_calcs.postgres91].[TEMP(Test)(1240237577)(0)] -9.0 @@ -91,10 +91,10 @@
- + - [cast_calcs.postgres91].[TEMP(Test)(3892529067)(0)] + [cast_calcs.postgres91].[TEMP(Test)(3892529067)(0)] %null% @@ -125,10 +125,10 @@
- + - [cast_calcs.postgres91].[TEMP(Test)(2722044748)(0)] + [cast_calcs.postgres91].[TEMP(Test)(2722044748)(0)] %null% diff --git a/tdvt/tdvt/exprtests/standard/expected.setup.math.sin.txt b/tdvt/tdvt/exprtests/standard/expected.setup.math.sin.txt index 0831870d..a60468c8 100644 --- a/tdvt/tdvt/exprtests/standard/expected.setup.math.sin.txt +++ b/tdvt/tdvt/exprtests/standard/expected.setup.math.sin.txt @@ -1,8 +1,8 @@ - +
- [cast_calcs.postgres91].[TEMP(Test)(527156183)(0)] + [cast_calcs.postgres91].[TEMP(Test)(527156183)(0)] -0.98935825 @@ -45,10 +45,10 @@
- + - [cast_calcs.postgres91].[TEMP(Test)(1184030290)(0)] + [cast_calcs.postgres91].[TEMP(Test)(1184030290)(0)] %null% diff --git a/tdvt/tdvt/exprtests/standard/expected.setup.math.sqrt.txt b/tdvt/tdvt/exprtests/standard/expected.setup.math.sqrt.txt index bba86ccd..ff8b5186 100644 --- a/tdvt/tdvt/exprtests/standard/expected.setup.math.sqrt.txt +++ b/tdvt/tdvt/exprtests/standard/expected.setup.math.sqrt.txt @@ -1,8 +1,8 @@ - +
- [cast_calcs.postgres91].[TEMP(Test)(2398974448)(0)] + [cast_calcs.postgres91].[TEMP(Test)(2398974448)(0)] %null% @@ -30,10 +30,10 @@
- + - [cast_calcs.postgres91].[TEMP(Test)(634651992)(0)] + [cast_calcs.postgres91].[TEMP(Test)(634651992)(0)] %null% diff --git a/tdvt/tdvt/exprtests/standard/expected.setup.math.square.txt b/tdvt/tdvt/exprtests/standard/expected.setup.math.square.txt index ca15724b..a557a129 100644 --- a/tdvt/tdvt/exprtests/standard/expected.setup.math.square.txt +++ b/tdvt/tdvt/exprtests/standard/expected.setup.math.square.txt @@ -1,8 +1,8 @@ - +
- [cast_calcs.postgres91].[TEMP(Test)(3898674109)(0)] + [cast_calcs.postgres91].[TEMP(Test)(3898674109)(0)] 0 @@ -30,10 +30,10 @@
- + - [cast_calcs.postgres91].[TEMP(Test)(1119897860)(0)] + [cast_calcs.postgres91].[TEMP(Test)(1119897860)(0)] %null% diff --git a/tdvt/tdvt/exprtests/standard/expected.setup.math.tan.txt b/tdvt/tdvt/exprtests/standard/expected.setup.math.tan.txt index fa6e2a75..3cc77d50 100644 --- a/tdvt/tdvt/exprtests/standard/expected.setup.math.tan.txt +++ b/tdvt/tdvt/exprtests/standard/expected.setup.math.tan.txt @@ -1,8 +1,8 @@ - +
- [cast_calcs.postgres91].[TEMP(Test)(1227693937)(0)] + [cast_calcs.postgres91].[TEMP(Test)(1227693937)(0)] -3.380515 diff --git a/tdvt/tdvt/exprtests/standard/expected.setup.operator.int.txt b/tdvt/tdvt/exprtests/standard/expected.setup.operator.int.txt index a9cc2703..3ce21470 100644 --- a/tdvt/tdvt/exprtests/standard/expected.setup.operator.int.txt +++ b/tdvt/tdvt/exprtests/standard/expected.setup.operator.int.txt @@ -18,10 +18,10 @@
- + - [cast_calcs.postgres].[TEMP(Test)(2402101080)(0)] + [cast_calcs.postgres].[TEMP(Test)(2402101080)(0)] %null% @@ -40,10 +40,10 @@
- + - [cast_calcs.postgres].[TEMP(Test)(3559262472)(0)] + [cast_calcs.postgres].[TEMP(Test)(3559262472)(0)] %null% @@ -95,10 +95,10 @@
- + - [cast_calcs.postgres].[TEMP(Test)(4265403921)(0)] + [cast_calcs.postgres].[TEMP(Test)(4265403921)(0)] %null% diff --git a/tdvt/tdvt/exprtests/standard/expected.setup.operator.num.txt b/tdvt/tdvt/exprtests/standard/expected.setup.operator.num.txt index d3f75bc1..faa098a1 100644 --- a/tdvt/tdvt/exprtests/standard/expected.setup.operator.num.txt +++ b/tdvt/tdvt/exprtests/standard/expected.setup.operator.num.txt @@ -1,8 +1,8 @@ - +
- [cast_calcs.postgres].[TEMP(Test)(3816473022)(0)] + [cast_calcs.postgres].[TEMP(Test)(3816473022)(0)] %null% @@ -24,10 +24,10 @@
- + - [cast_calcs.postgres].[TEMP(Test)(965512284)(0)] + [cast_calcs.postgres].[TEMP(Test)(965512284)(0)] %null% @@ -58,10 +58,10 @@
- + - [cast_calcs.postgres].[TEMP(Test)(1826927073)(0)] + [cast_calcs.postgres].[TEMP(Test)(1826927073)(0)] 2.47 @@ -116,10 +116,10 @@
- + - [cast_calcs.postgres].[TEMP(Test)(4188722171)(0)] + [cast_calcs.postgres].[TEMP(Test)(4188722171)(0)] %null% @@ -150,10 +150,10 @@
- + - [cast_calcs.postgres].[TEMP(Test)(272703322)(0)] + [cast_calcs.postgres].[TEMP(Test)(272703322)(0)] %null% @@ -280,10 +280,10 @@
- + - [cast_calcs.postgres].[TEMP(Test)(3781247900)(0)] + [cast_calcs.postgres].[TEMP(Test)(3781247900)(0)] %null% @@ -346,10 +346,10 @@
- + - [cast_calcs.postgres].[TEMP(Test)(977554451)(0)] + [cast_calcs.postgres].[TEMP(Test)(977554451)(0)] %null% @@ -380,10 +380,10 @@
- + - [cast_calcs.postgres].[TEMP(Test)(637953353)(0)] + [cast_calcs.postgres].[TEMP(Test)(637953353)(0)] %null% @@ -405,10 +405,10 @@
- + - [cast_calcs.postgres].[TEMP(Test)(1861245368)(0)] + [cast_calcs.postgres].[TEMP(Test)(1861245368)(0)] %null% diff --git a/tdvt/tdvt/exprtests/standard/setup.date.dateadd.hour.txt b/tdvt/tdvt/exprtests/standard/setup.date.dateadd.hour.txt index 3acdeb30..6241570f 100644 --- a/tdvt/tdvt/exprtests/standard/setup.date.dateadd.hour.txt +++ b/tdvt/tdvt/exprtests/standard/setup.date.dateadd.hour.txt @@ -1,2 +1,3 @@ -DATEADD('hour', 1, [datetime0]) +DATEADD('hour', 1, [date2]) +DATEADD('hour', 1, [datetime0]) \ No newline at end of file diff --git a/tdvt/tdvt/exprtests/standard/setup.date.dateadd.minute.txt b/tdvt/tdvt/exprtests/standard/setup.date.dateadd.minute.txt index 088b43c5..cd715cc9 100644 --- a/tdvt/tdvt/exprtests/standard/setup.date.dateadd.minute.txt +++ b/tdvt/tdvt/exprtests/standard/setup.date.dateadd.minute.txt @@ -1,2 +1,3 @@ -DATEADD('minute', 1, [datetime0]) +DATEADD('minute', 1, [date2]) +DATEADD('minute', 1, [datetime0]) \ No newline at end of file diff --git a/tdvt/tdvt/exprtests/standard/setup.date.dateadd.second.txt b/tdvt/tdvt/exprtests/standard/setup.date.dateadd.second.txt index 2da854fb..38e56232 100644 --- a/tdvt/tdvt/exprtests/standard/setup.date.dateadd.second.txt +++ b/tdvt/tdvt/exprtests/standard/setup.date.dateadd.second.txt @@ -1 +1,3 @@ -DATEADD('second', 1, [datetime0]) +DATEADD('second', 1, [date2]) + +DATEADD('second', 1, [datetime0]) \ No newline at end of file diff --git a/tdvt/tdvt/exprtests/tdeonly/expected.setup.agg.median.txt b/tdvt/tdvt/exprtests/tdeonly/expected.setup.agg.median.txt index 4796674b..a4a0c403 100644 --- a/tdvt/tdvt/exprtests/tdeonly/expected.setup.agg.median.txt +++ b/tdvt/tdvt/exprtests/tdeonly/expected.setup.agg.median.txt @@ -1,38 +1,38 @@ - +
- [cast_calcs.hyper].[TEMP(Test)(925086242)(0)] + [cast_calcs.hyper].[TEMP(Test)(925086242)(0)] 0.0
- + - [cast_calcs.hyper].[TEMP(Test)(3622506995)(0)] + [cast_calcs.hyper].[TEMP(Test)(3622506995)(0)] 10.98
- + - [cast_calcs.hyper].[TEMP(Test)(1798641580)(0)] + [cast_calcs.hyper].[TEMP(Test)(1798641580)(0)] 4.295
- + - [cast_calcs.hyper].[TEMP(Test)(1667576385)(0)] + [cast_calcs.hyper].[TEMP(Test)(1667576385)(0)] 1988.0 diff --git a/tdvt/tdvt/exprtests/tdeonly/expected.setup.agg.percentile.txt b/tdvt/tdvt/exprtests/tdeonly/expected.setup.agg.percentile.txt index 22125349..f9ba0c10 100644 --- a/tdvt/tdvt/exprtests/tdeonly/expected.setup.agg.percentile.txt +++ b/tdvt/tdvt/exprtests/tdeonly/expected.setup.agg.percentile.txt @@ -1,48 +1,48 @@ - +
- [cast_calcs.hyper].[TEMP(Test)(1005283190)(0)] + [cast_calcs.hyper].[TEMP(Test)(1005283190)(0)] 10.98
- + - [cast_calcs.hyper].[TEMP(Test)(3070691569)(0)] + [cast_calcs.hyper].[TEMP(Test)(3070691569)(0)] 8.9175
- + - [cast_calcs.hyper].[TEMP(Test)(1236390098)(0)] + [cast_calcs.hyper].[TEMP(Test)(1236390098)(0)] -9.0
- + - [cast_calcs.hyper].[TEMP(Test)(1981734878)(0)] + [cast_calcs.hyper].[TEMP(Test)(1981734878)(0)] 3.0
- + - [cast_calcs.hyper].[TEMP(Test)(1162356411)(0)] + [cast_calcs.hyper].[TEMP(Test)(1162356411)(0)] 1988.0 diff --git a/tdvt/tdvt/exprtests/tdeonly/expected.setup.operator.modulo.B643808.txt b/tdvt/tdvt/exprtests/tdeonly/expected.setup.operator.modulo.B643808.txt index e48897fa..5cee4de6 100644 --- a/tdvt/tdvt/exprtests/tdeonly/expected.setup.operator.modulo.B643808.txt +++ b/tdvt/tdvt/exprtests/tdeonly/expected.setup.operator.modulo.B643808.txt @@ -1,8 +1,8 @@ - +
- [cast_calcs.hyper_native].[TEMP(Test)(89230338)(0)] + [cast_calcs.hyper_native].[TEMP(Test)(89230338)(0)] %null% @@ -65,10 +65,10 @@
- + - [cast_calcs.hyper_native].[TEMP(Test)(3148432521)(0)] + [cast_calcs.hyper_native].[TEMP(Test)(3148432521)(0)] %null% diff --git a/tdvt/tdvt/logicaltests/expected/calcs/expected.setup.BUGS.B27875-asc-nulls-first.xml b/tdvt/tdvt/logicaltests/expected/calcs/expected.setup.BUGS.B27875-asc-nulls-first.xml index 70bbc137..35126813 100644 --- a/tdvt/tdvt/logicaltests/expected/calcs/expected.setup.BUGS.B27875-asc-nulls-first.xml +++ b/tdvt/tdvt/logicaltests/expected/calcs/expected.setup.BUGS.B27875-asc-nulls-first.xml @@ -1,11 +1,14 @@ - +
[cast_calcs.postgres91].[key] - [cast_calcs.postgres91].[sum:num2:ok] + [cast_calcs.postgres91].[sum:num2:ok] "key02" diff --git a/tdvt/tdvt/logicaltests/expected/calcs/expected.setup.BUGS.B27875-desc-nulls-last.xml b/tdvt/tdvt/logicaltests/expected/calcs/expected.setup.BUGS.B27875-desc-nulls-last.xml index 66301ccf..d52ccb47 100644 --- a/tdvt/tdvt/logicaltests/expected/calcs/expected.setup.BUGS.B27875-desc-nulls-last.xml +++ b/tdvt/tdvt/logicaltests/expected/calcs/expected.setup.BUGS.B27875-desc-nulls-last.xml @@ -1,11 +1,14 @@ - +
[cast_calcs.postgres91].[key] - [cast_calcs.postgres91].[sum:num2:ok] + [cast_calcs.postgres91].[sum:num2:ok] "key00" diff --git a/tdvt/tdvt/logicaltests/expected/calcs/expected.setup.BUGS.B641638.xml b/tdvt/tdvt/logicaltests/expected/calcs/expected.setup.BUGS.B641638.xml index c0ac8bba..0b78dd07 100644 --- a/tdvt/tdvt/logicaltests/expected/calcs/expected.setup.BUGS.B641638.xml +++ b/tdvt/tdvt/logicaltests/expected/calcs/expected.setup.BUGS.B641638.xml @@ -1,11 +1,11 @@ - +
[cast_calcs.hyper_native].[str1] - [cast_calcs.hyper_native].[sum:num1:ok] + [cast_calcs.hyper_native].[sum:num1:ok] [cast_calcs.hyper_native].[time0] diff --git a/tdvt/tdvt/logicaltests/expected/calcs/expected.setup.Query.Filter.IsNOTNULL.xml b/tdvt/tdvt/logicaltests/expected/calcs/expected.setup.Query.Filter.IsNOTNULL.xml index 0866da48..7de7d7e5 100644 --- a/tdvt/tdvt/logicaltests/expected/calcs/expected.setup.Query.Filter.IsNOTNULL.xml +++ b/tdvt/tdvt/logicaltests/expected/calcs/expected.setup.Query.Filter.IsNOTNULL.xml @@ -1,11 +1,11 @@ - +
[cast_calcs.postgres91].[str2] - [cast_calcs.postgres91].[sum:num3:ok] + [cast_calcs.postgres91].[sum:num3:ok] "eight" diff --git a/tdvt/tdvt/logicaltests/expected/calcs/expected.setup.join.null.bool.xml b/tdvt/tdvt/logicaltests/expected/calcs/expected.setup.join.null.bool.xml index a5be9144..63a80b89 100644 --- a/tdvt/tdvt/logicaltests/expected/calcs/expected.setup.join.null.bool.xml +++ b/tdvt/tdvt/logicaltests/expected/calcs/expected.setup.join.null.bool.xml @@ -1,12 +1,12 @@ - +
- [cast_calcs.bigquery_sql].[Calculation_845269395859349504] + [cast_calcs.bigquery_sql].[Calculation_845269395859349504] [cast_calcs.bigquery_sql].[bool1] - [cast_calcs.bigquery_sql].[sum:num1:ok] + [cast_calcs.bigquery_sql].[sum:num1:ok] 2.47 diff --git a/tdvt/tdvt/logicaltests/expected/calcs/expected.setup.join.null.date.xml b/tdvt/tdvt/logicaltests/expected/calcs/expected.setup.join.null.date.xml index 1fa7c446..831c34e5 100644 --- a/tdvt/tdvt/logicaltests/expected/calcs/expected.setup.join.null.date.xml +++ b/tdvt/tdvt/logicaltests/expected/calcs/expected.setup.join.null.date.xml @@ -1,12 +1,12 @@ - +
- [cast_calcs.bigquery_sql].[Calculation_845269395859349504] + [cast_calcs.bigquery_sql].[Calculation_845269395859349504] [cast_calcs.bigquery_sql].[date0] - [cast_calcs.bigquery_sql].[sum:num1:ok] + [cast_calcs.bigquery_sql].[sum:num1:ok] 2.47 diff --git a/tdvt/tdvt/logicaltests/expected/calcs/expected.setup.join.null.datetime.xml b/tdvt/tdvt/logicaltests/expected/calcs/expected.setup.join.null.datetime.xml index 2badb3b6..3aed52fb 100644 --- a/tdvt/tdvt/logicaltests/expected/calcs/expected.setup.join.null.datetime.xml +++ b/tdvt/tdvt/logicaltests/expected/calcs/expected.setup.join.null.datetime.xml @@ -1,12 +1,12 @@ - +
[cast_calcs.bigquery_sql].[Calculation_3278620569574133760] - [cast_calcs.bigquery_sql].[Calculation_845269395859349504] - [cast_calcs.bigquery_sql].[sum:num1:ok] + [cast_calcs.bigquery_sql].[Calculation_845269395859349504] + [cast_calcs.bigquery_sql].[sum:num1:ok] %null% diff --git a/tdvt/tdvt/logicaltests/expected/calcs/expected.setup.join.null.int.xml b/tdvt/tdvt/logicaltests/expected/calcs/expected.setup.join.null.int.xml index bcf51e8f..946078b2 100644 --- a/tdvt/tdvt/logicaltests/expected/calcs/expected.setup.join.null.int.xml +++ b/tdvt/tdvt/logicaltests/expected/calcs/expected.setup.join.null.int.xml @@ -1,12 +1,12 @@ - +
- [cast_calcs.bigquery_sql].[Calculation_845269395859349504] + [cast_calcs.bigquery_sql].[Calculation_845269395859349504] [cast_calcs.bigquery_sql].[int1] - [cast_calcs.bigquery_sql].[sum:num1:ok] + [cast_calcs.bigquery_sql].[sum:num1:ok] 2.47 diff --git a/tdvt/tdvt/logicaltests/expected/calcs/expected.setup.join.null.real.xml b/tdvt/tdvt/logicaltests/expected/calcs/expected.setup.join.null.real.xml index a045af7d..86f5ed7f 100644 --- a/tdvt/tdvt/logicaltests/expected/calcs/expected.setup.join.null.real.xml +++ b/tdvt/tdvt/logicaltests/expected/calcs/expected.setup.join.null.real.xml @@ -1,12 +1,12 @@ - +
- [cast_calcs.bigquery_sql].[Calculation_845269395859349504] - [cast_calcs.bigquery_sql].[num2] - [cast_calcs.bigquery_sql].[sum:num1:ok] + [cast_calcs.bigquery_sql].[Calculation_845269395859349504] + [cast_calcs.bigquery_sql].[num2] + [cast_calcs.bigquery_sql].[sum:num1:ok] 2.47 diff --git a/tdvt/tdvt/logicaltests/expected/calcs/expected.setup.join.null.str.xml b/tdvt/tdvt/logicaltests/expected/calcs/expected.setup.join.null.str.xml index 695c5fc0..54d42d30 100644 --- a/tdvt/tdvt/logicaltests/expected/calcs/expected.setup.join.null.str.xml +++ b/tdvt/tdvt/logicaltests/expected/calcs/expected.setup.join.null.str.xml @@ -1,12 +1,12 @@ - +
- [cast_calcs.bigquery_sql].[Calculation_845269395859349504] + [cast_calcs.bigquery_sql].[Calculation_845269395859349504] [cast_calcs.bigquery_sql].[str2] - [cast_calcs.bigquery_sql].[sum:num1:ok] + [cast_calcs.bigquery_sql].[sum:num1:ok] 2.47 diff --git a/tdvt/tdvt/logicaltests/expected/lod/expected.setup.lod.17_Nesting.xml b/tdvt/tdvt/logicaltests/expected/lod/expected.setup.lod.17_Nesting.xml index e0b9cc82..818bc584 100644 --- a/tdvt/tdvt/logicaltests/expected/lod/expected.setup.lod.17_Nesting.xml +++ b/tdvt/tdvt/logicaltests/expected/lod/expected.setup.lod.17_Nesting.xml @@ -1,17 +1,17 @@ - +
[Staples.sqlserver].[Prod Type1] [Staples.sqlserver].[Ship Mode] - [Staples.sqlserver].[TEMP(attr:LOD - Nesting - 1 (copy):qk)(1075333431)(0)] - [Staples.sqlserver].[TEMP(attr:LOD - Nesting - 1 (copy):qk)(260755027)(0)] - [Staples.sqlserver].[avg:Calculation_8601225013155991:ok] - [Staples.sqlserver].[sum:Calculation_9271225012544475:ok] - [Staples.sqlserver].[sum:LOD - Nesting - 2 (copy):ok] - [Staples.sqlserver].[sum:LOD - Nesting - 3 (copy):ok] + [Staples.sqlserver].[TEMP(attr:LOD - Nesting - 1 (copy):qk)(1075333431)(0)] + [Staples.sqlserver].[TEMP(attr:LOD - Nesting - 1 (copy):qk)(260755027)(0)] + [Staples.sqlserver].[avg:Calculation_8601225013155991:ok] + [Staples.sqlserver].[sum:Calculation_9271225012544475:ok] + [Staples.sqlserver].[sum:LOD - Nesting - 2 (copy):ok] + [Staples.sqlserver].[sum:LOD - Nesting - 3 (copy):ok] "FURNITURE" diff --git a/tdvt/tdvt/logicaltests/expected/lod/expected.setup.lod.1_Difference From with Cross Join.xml b/tdvt/tdvt/logicaltests/expected/lod/expected.setup.lod.1_Difference From with Cross Join.xml index e9c2aa68..08b840cd 100644 --- a/tdvt/tdvt/logicaltests/expected/lod/expected.setup.lod.1_Difference From with Cross Join.xml +++ b/tdvt/tdvt/logicaltests/expected/lod/expected.setup.lod.1_Difference From with Cross Join.xml @@ -1,12 +1,12 @@ - +
[Staples.sqlserver].[Customer Name] [Staples.sqlserver].[LOD - Fixed - 2 (copy)] - [Staples.sqlserver].[sum:Sales Total:ok] + [Staples.sqlserver].[sum:Sales Total:ok] "Barbara Fisher" diff --git a/tdvt/tdvt/logicaltests/expected/staples/expected.setup.Filter.Add_to_context.xml b/tdvt/tdvt/logicaltests/expected/staples/expected.setup.Filter.Add_to_context.xml index 9b5158fd..21ac6ddb 100644 --- a/tdvt/tdvt/logicaltests/expected/staples/expected.setup.Filter.Add_to_context.xml +++ b/tdvt/tdvt/logicaltests/expected/staples/expected.setup.Filter.Add_to_context.xml @@ -1,7 +1,7 @@ - +
[Staples.postgres91].[Market Segment] @@ -9,8 +9,8 @@ [Staples.postgres91].[Prod Type2] [Staples.postgres91].[Prod Type3] [Staples.postgres91].[Prod Type4] - [Staples.postgres91].[sum:Gross Profit:ok] - [Staples.postgres91].[sum:Sales Total:ok] + [Staples.postgres91].[sum:Gross Profit:ok] + [Staples.postgres91].[sum:Sales Total:ok] "CONSUMER" diff --git a/tdvt/tdvt/logicaltests/expected/staples/expected.setup.Query.CTE_singleCte.xml b/tdvt/tdvt/logicaltests/expected/staples/expected.setup.Query.CTE_singleCte.xml new file mode 100644 index 00000000..54383c48 --- /dev/null +++ b/tdvt/tdvt/logicaltests/expected/staples/expected.setup.Query.CTE_singleCte.xml @@ -0,0 +1,316 @@ + + + + +
+ + [Staples.bigquery_sql].[CustomerName] + [Staples.bigquery_sql].[sum:Employee Salary:ok] + + + "Barbara Fisher" + 44405776.0 + + + "Dario Medina" + 52701843.0 + + + "Dave Hallsten" + 30683483.0 + + + "David Flashing" + 51528465.0 + + + "David Wiener" + 51290263.0 + + + "Deanra Eno" + 46227429.0 + + + "Debra Catini-Entman" + 40756714.0 + + + "Elizabeth Moffitt" + 43345104.0 + + + "Ellis Ballard" + 51710350.0 + + + "Frank Olsen" + 35807186.0 + + + "Grace Kelly" + 49587677.0 + + + "Hallie Redmond" + 50993068.0 + + + "Harold Pawlan" + 56916533.0 + + + "Heather Jas-Hannaway" + 45220003.0 + + + "Henia Zydlo" + 46118471.0 + + + "Herbert Flentye" + 36304883.0 + + + "Hilary Holden" + 54067372.0 + + + "Jack O'Briant" + 31668130.0 + + + "Jane Waco" + 41708117.0 + + + "Jas O'Carroll" + 43259440.0 + + + "Jason Gross" + 43208889.0 + + + "Jasper Cacioppo" + 59785948.0 + + + "Jennifer Patt" + 41586537.0 + + + "Jesus Ocampo" + 58026067.0 + + + "Jim Sink" + 42919036.0 + + + "Joseph Airdo" + 27375222.0 + + + "Karen Seio" + 52872967.0 + + + "Laura Armstrong" + 50723679.0 + + + "Lela Donovan" + 40377464.0 + + + "Lena Cacioppo" + 58573802.0 + + + "Lynn Smith-Reed" + 48434016.0 + + + "Mary O'Rourke" + 48148667.0 + + + "Mary Zewe" + 57348820.0 + + + "MaryBeth Skach" + 51986779.0 + + + "Mathew Reese" + 51031701.0 + + + "Maurice Satty" + 40681046.0 + + + "Maxwell Schwartz" + 52567452.0 + + + "Meg O'Connel" + 40395457.0 + + + "Meg Tillman-Sachs" + 50398310.0 + + + "Michael Moore" + 42798249.0 + + + "Michael Oakman" + 40878893.0 + + + "Naresj Patel" + 55638077.0 + + + "Nathan Mautz" + 55776979.0 + + + "Noel Staavos" + 58044837.0 + + + "Nona Balk" + 38561172.0 + + + "Olvera Toch" + 41911856.0 + + + "Patrick O'Brill" + 40324965.0 + + + "Paul Prost" + 34626470.0 + + + "Peter McVee" + 48648960.0 + + + "Pierre Wener" + 40755986.0 + + + "Quincy Jones" + 52550136.0 + + + "Rick Reed" + 59611858.0 + + + "Robert Marley" + 37196248.0 + + + "Rose O'Brian-Murray" + 39253747.0 + + + "Roy Skaria" + 63700463.0 + + + "Sandra Glassco" + 46413253.0 + + + "Sarah Jordon-Smith" + 50481536.0 + + + "Seth Vernon" + 38571567.0 + + + "Sharelle Roach-McGee" + 46400044.0 + + + "Sheri Gordon" + 32549519.0 + + + "Shui Tom" + 49474245.0 + + + "Skye Norling-Christen" + 45694416.0 + + + "Speros Goranitis" + 38758075.0 + + + "Stephanie Ulpright" + 29366188.0 + + + "Steven Roelle" + 37257991.0 + + + "Sue Ann Reed-Freeman" + 36208964.0 + + + "Suzanne McNair" + 54090069.0 + + + "Tanja Norvell" + 47577855.0 + + + "Thomas Boland" + 49958801.0 + + + "Thomas Seio" + 46373010.0 + + + "Tonja Turnell" + 42371823.0 + + + "Tracy Zic" + 36717227.0 + + + "Victor Price" + 42411843.0 + + + "William Brown" + 35103545.0 + + + "Yoseph Carroll-Englig" + 52222043.0 + + + "Zyzzy Zzuyzyzyk" + 56807183.0 + +
+
+
diff --git a/tdvt/tdvt/logicaltests/expected/staples/expected.setup.Query.Dates_MDY.xml b/tdvt/tdvt/logicaltests/expected/staples/expected.setup.Query.Dates_MDY.xml index 17cb64b9..53d5b8a9 100644 --- a/tdvt/tdvt/logicaltests/expected/staples/expected.setup.Query.Dates_MDY.xml +++ b/tdvt/tdvt/logicaltests/expected/staples/expected.setup.Query.Dates_MDY.xml @@ -1,11 +1,11 @@ - + - [Staples.postgres91].[md:Order Date:ok] - [Staples.postgres91].[sum:Gross Profit:ok] + [Staples.postgres91].[md:Order Date:ok] + [Staples.postgres91].[sum:Gross Profit:ok] 19970101 diff --git a/tdvt/tdvt/logicaltests/expected/staples/expected.setup.Query.Dates_MDY_Filtered.xml b/tdvt/tdvt/logicaltests/expected/staples/expected.setup.Query.Dates_MDY_Filtered.xml index 3b4241cd..526664ad 100644 --- a/tdvt/tdvt/logicaltests/expected/staples/expected.setup.Query.Dates_MDY_Filtered.xml +++ b/tdvt/tdvt/logicaltests/expected/staples/expected.setup.Query.Dates_MDY_Filtered.xml @@ -1,11 +1,11 @@ - +
[Staples.postgres91].[md:Order Date:ok] - [Staples.postgres91].[sum:Gross Profit:ok] + [Staples.postgres91].[sum:Gross Profit:ok] 19970102 diff --git a/tdvt/tdvt/logicaltests/expected/staples/expected.setup.Query.MultipleFilters.xml b/tdvt/tdvt/logicaltests/expected/staples/expected.setup.Query.MultipleFilters.xml index 557b4cf9..212e8afa 100644 --- a/tdvt/tdvt/logicaltests/expected/staples/expected.setup.Query.MultipleFilters.xml +++ b/tdvt/tdvt/logicaltests/expected/staples/expected.setup.Query.MultipleFilters.xml @@ -1,15 +1,15 @@ - +
[Staples.postgres91].[Call Center Region] [Staples.postgres91].[Order ID] [Staples.postgres91].[Product Container] - [Staples.postgres91].[avg:Gross Profit:ok] + [Staples.postgres91].[avg:Gross Profit:ok] [Staples.postgres91].[mn:Order Date:ok] - [Staples.postgres91].[sum:Price:ok] + [Staples.postgres91].[sum:Price:ok] [Staples.postgres91].[yr:Order Date:ok] diff --git a/tdvt/tdvt/logicaltests/expected/staples/expected.setup.Query.Unaggregated_Filter.xml b/tdvt/tdvt/logicaltests/expected/staples/expected.setup.Query.Unaggregated_Filter.xml index a987f56c..1054d77f 100644 --- a/tdvt/tdvt/logicaltests/expected/staples/expected.setup.Query.Unaggregated_Filter.xml +++ b/tdvt/tdvt/logicaltests/expected/staples/expected.setup.Query.Unaggregated_Filter.xml @@ -1,13 +1,13 @@ - +
[Staples.postgres91].[Call Center Region] [Staples.postgres91].[PID] - [Staples.postgres91].[sum:Customer Balance:ok] - [Staples.postgres91].[sum:Order Quantity:ok] + [Staples.postgres91].[sum:Customer Balance:ok] + [Staples.postgres91].[sum:Order Quantity:ok] [Staples.postgres91].[yr:Order Date:ok] diff --git a/tdvt/tdvt/logicaltests/expected/staples/expected.setup.Query.Unaggregated_Filter_NoDateTime.xml b/tdvt/tdvt/logicaltests/expected/staples/expected.setup.Query.Unaggregated_Filter_NoDateTime.xml index 5f035d9e..92014784 100644 --- a/tdvt/tdvt/logicaltests/expected/staples/expected.setup.Query.Unaggregated_Filter_NoDateTime.xml +++ b/tdvt/tdvt/logicaltests/expected/staples/expected.setup.Query.Unaggregated_Filter_NoDateTime.xml @@ -1,13 +1,13 @@ - +
[Staples.postgres91].[Call Center Region] [Staples.postgres91].[PID] - [Staples.postgres91].[sum:Customer Balance:ok] - [Staples.postgres91].[sum:Order Quantity:ok] + [Staples.postgres91].[sum:Customer Balance:ok] + [Staples.postgres91].[sum:Order Quantity:ok] [Staples.postgres91].[yr:Order Date:ok] diff --git a/tdvt/tdvt/logicaltests/expected/staples/expected.setup.ZTesting.Staples9.xml b/tdvt/tdvt/logicaltests/expected/staples/expected.setup.ZTesting.Staples9.xml index 6ebc0906..3e1a8417 100644 --- a/tdvt/tdvt/logicaltests/expected/staples/expected.setup.ZTesting.Staples9.xml +++ b/tdvt/tdvt/logicaltests/expected/staples/expected.setup.ZTesting.Staples9.xml @@ -1,12 +1,12 @@ - +
[Staples.postgres91].[PID] - [Staples.postgres91].[sum:Gross Profit:ok] - [Staples.postgres91].[sum:Sales Total:ok] + [Staples.postgres91].[sum:Gross Profit:ok] + [Staples.postgres91].[sum:Sales Total:ok] 45686 diff --git a/tdvt/tdvt/logicaltests/generate/input/calcs/setup.BUGS.B59740.xml b/tdvt/tdvt/logicaltests/generate/input/calcs/setup.BUGS.B59740.xml index f5db4476..8182af8f 100644 --- a/tdvt/tdvt/logicaltests/generate/input/calcs/setup.BUGS.B59740.xml +++ b/tdvt/tdvt/logicaltests/generate/input/calcs/setup.BUGS.B59740.xml @@ -49,16 +49,16 @@ - + - + - + - + diff --git a/tdvt/tdvt/logicaltests/generate/input/staples/setup.Query.CTE_singleCte.xml b/tdvt/tdvt/logicaltests/generate/input/staples/setup.Query.CTE_singleCte.xml new file mode 100644 index 00000000..02bdf326 --- /dev/null +++ b/tdvt/tdvt/logicaltests/generate/input/staples/setup.Query.CTE_singleCte.xml @@ -0,0 +1,215 @@ + + + [Customer Name] + [sum:Employee Salary:ok] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + s + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tdvt/tdvt/setup_env.py b/tdvt/tdvt/setup_env.py index 57f4726b..639d6ef0 100644 --- a/tdvt/tdvt/setup_env.py +++ b/tdvt/tdvt/setup_env.py @@ -11,6 +11,7 @@ from .constants import CUSTOM_TABLE_TEST_SET + def create_test_environment(): """Create directories and necessary ini files.""" create_setup_structure() @@ -245,32 +246,66 @@ def update_tds_files(name, connection_password_name): def mangle_tds(file_path, connection_password_name): print('Modifying ' + file_path) try: - r1 = re.compile('(^\s*)') - r2 = re.compile('(^\s*<.*relation connection=\').*?(\' .*>)') - r3 = re.compile('(^\s*)') - - f = open(file_path, 'r') - new_tds = '' - for line in f: - new_line = line.rstrip() - m1 = r1.match(line) - if m1: - new_line = m1.group(1) + 'leaf' + m1.group(2) - - m2 = r2.match(line) - if m2: - new_line = m2.group(1) + 'leaf' + m2.group(2) - - m3 = r3.match(line) - if m3 and not 'tdvtconnection=\'' in line.lower(): - new_line = m3.group(1) + ' tdvtconnection=\'' + connection_password_name + '\' ' + m3.group(2) - - new_tds += new_line + '\n' - - f.close() + with open(file_path, 'r') as f: + new_tds = updated_tds_as_str(f, connection_password_name) f = open(file_path, 'w') f.write(new_tds) f.close() except IOError as e: print(e) return + + +def get_tds_new_line(rmatch: Optional[re.Match[str]], mid_str: str, connection_password_name=None): + new_line = '' + new_line = rmatch.group(1) + mid_str + connection_password_name + '\' ' + rmatch.group(2) + + return new_line + + +def updated_tds_as_str(f, connection_name) -> str: + r1 = re.compile('(^\s*)') + r2 = re.compile('(^\s*<.*relation connection=\').*?(\' .*>)') + r3 = re.compile('(^\s*)') + + new_tds = '' + + for line in f: + new_line = line.rstrip() + m1 = r1.match(line) + if m1: + new_line = m1.group(1) + 'leaf' + m1.group(2) + + m2 = r2.match(line) + if m2: + new_line = m2.group(1) + 'leaf' + m2.group(2) + + m3 = r3.match(line) + if m3 and not 'tdvtconnection=\'' in line.lower(): + new_line = m3.group(1) + 'tdvtconnection=\'' + connection_name + m3.group(2) + + new_tds += new_line + '\n' + return new_tds + +def get_failed_cmd_line(cls, index): + res_info = cls.combined_output[index] + ds = res_info.get('Suite') + tds_name = res_info.get('TDSName') + ab_path = res_info.get('TestPath') + test_type = res_info.get('Test Type') + if test_type == 'expression': + test_type = 'exp' + else: + test_type = 'logp' + if get_root_dir() in ab_path: + test_path = ab_path.split(get_root_dir())[1].replace('\\','/').lstrip('/') + else: + test_path = ab_path + str_info = {'ds': ds, + 'tds_name': tds_name, + 'test_path': test_path, + 'test_type': test_type + } + cmd_line = 'python -m run-pattern {ds} --{test_type} {test_path} --tdp {tds_name}.tds'.format(**str_info) + + return cmd_line \ No newline at end of file diff --git a/tdvt/tdvt/tabquery.py b/tdvt/tdvt/tabquery.py index 96a4c76f..56729fda 100644 --- a/tdvt/tdvt/tabquery.py +++ b/tdvt/tdvt/tabquery.py @@ -1,4 +1,6 @@ import configparser +import logging +import platform import sys from .resources import * @@ -21,16 +23,31 @@ def configure_tabquery_path(): config = configparser.ConfigParser() tdvt_cfg = get_ini_path_local_first('config/tdvt', 'tdvt') - logging.debug("Reading tdvt ini file [{}]".format(tdvt_cfg)) + logging.info("Reading tdvt ini file [{}]".format(tdvt_cfg)) config.read(tdvt_cfg) - if sys.platform.startswith("darwin"): - tab_cli_exe = config['DEFAULT']['TAB_CLI_EXE_MAC'] - elif sys.platform.startswith("linux"): + logging.info(f"Running TDVT on {platform.system()}/{platform.machine()}") + if platform.system() == "Darwin": + tab_cli_exe_key = "TAB_CLI_EXE_MAC_ARM" if platform.machine() == "arm64" else "TAB_CLI_EXE_MAC" + try: + tab_cli_exe = config['DEFAULT'][tab_cli_exe_key] + except KeyError: + if tab_cli_exe_key == 'TAB_CLI_EXE_MAC_ARM': + logging.warning(f"TDVT is running on an ARM Mac, but TAB_CLI_EXE_MAC_ARM does not exist in " + f"{tdvt_cfg}. Falling back to TAB_CLI_EXE_MAC path.") + tab_cli_exe = config['DEFAULT']['TAB_CLI_EXE_MAC'] + logging.info("Using TAB_CLI_EXE_MAC path") + else: + logging.error(f"Could not get {tab_cli_exe_key} from {tdvt_cfg}, exiting.") + sys.exit(1) + elif platform.system() == "Linux": tab_cli_exe = config['DEFAULT']['TAB_CLI_EXE_LINUX'] + logging.info("Using TAB_CLI_EXE_LINUX path.") else: tab_cli_exe = config['DEFAULT']['TAB_CLI_EXE_X64'] - logging.debug("Reading tdvt ini file tabquerycli path is [{}]".format(tab_cli_exe)) + logging.info("Using TAB_CLI_EXE_X86 path.") + + logging.info(f"Reading tdvt ini {tdvt_cfg} file tabquerycli path is {tab_cli_exe}") def get_max_process_level_of_parallelization(desired_threads): if sys.platform.startswith("darwin") and 'tabquerytool' in tab_cli_exe: @@ -40,6 +57,7 @@ def get_max_process_level_of_parallelization(desired_threads): def build_tabquery_command_line(work): tb = TabqueryCommandLine() + cmdline = tb.build_tabquery_command_line(work) return cmdline @@ -109,12 +127,12 @@ def tabquerycli_exists(tabquery_cli_path: TabQueryPath = None): if tabquery_cli_path: resolved_path = tabquery_cli_path.get_path(sys.platform) if os.path.isfile(resolved_path): - logging.debug("Found tabquery at [{0}]".format(resolved_path)) + logging.info("Found tabquery at [{0}]".format(resolved_path)) return True if os.path.isfile(tab_cli_exe): - logging.debug("Found tabquery at [{0}]".format(tab_cli_exe)) + logging.info("Found tabquery at [{0}]".format(tab_cli_exe)) return True - logging.debug("Could not find tabquery at [{0}]".format(tab_cli_exe)) + logging.error("Could not find tabquery at [{0}]".format(tab_cli_exe)) return False diff --git a/tdvt/tdvt/tabquery_path.py b/tdvt/tdvt/tabquery_path.py index 7430c454..69c78e79 100644 --- a/tdvt/tdvt/tabquery_path.py +++ b/tdvt/tdvt/tabquery_path.py @@ -1,23 +1,30 @@ +import sys +import platform + + class TabQueryPath(object): - def __init__(self, linux_path, mac_path, windows_path): + def __init__(self, linux_path, mac_path, mac_arm_path, windows_path): self.linux_path = linux_path self.mac_path = mac_path + self.mac_arm_path = mac_arm_path self.windows_path = windows_path @staticmethod def from_array(paths): - if len(paths) != 3: + if len(paths) != 4: raise IndexError - t = TabQueryPath(paths[0], paths[1], paths[2]) + t = TabQueryPath(paths[0], paths[1], paths[2], paths[3]) return t def to_array(self): - return [self.linux_path, self.mac_path, self.windows_path] + return [self.linux_path, self.mac_path, self.mac_arm_path, self.windows_path] - def get_path(self, os): - if os.startswith("darwin"): + def get_path(self, operating_system): + if operating_system.startswith("darwin") and platform.machine() == 'arm64': + return self.mac_arm_path + elif operating_system.startswith("darwin"): return self.mac_path - elif os.startswith("linux"): + elif operating_system.startswith("linux"): return self.linux_path else: return self.windows_path \ No newline at end of file diff --git a/tdvt/tdvt/tdvt.py b/tdvt/tdvt/tdvt.py index ecaf0ff6..b69e1f4e 100644 --- a/tdvt/tdvt/tdvt.py +++ b/tdvt/tdvt/tdvt.py @@ -4,6 +4,7 @@ """ import sys +import platform if sys.version_info[0] < 3: raise EnvironmentError("TDVT requires Python 3 or greater.") @@ -25,13 +26,13 @@ from .config_gen.datasource_list import TestRegistry, print_ds, print_configurations, print_logical_configurations from .config_gen.tdvtconfig import TdvtInvocation from .config_gen.test_config import TestSet, SingleLogicalTestSet, SingleExpressionTestSet, FileTestSet, TestConfig, RunTimeTestConfig -from .setup_env import create_test_environment, add_datasource +from .setup_env import create_test_environment, add_datasource, get_failed_cmd_line from .tabquery import * from .tdvt_core import generate_files, run_diff, run_tests, run_connectors_test_core, return_csv_dialect from .version import __version__ # This contains the dictionary of configs you can run. -from .config_gen.datasource_list import WindowsRegistry, MacRegistry, LinuxRegistry +from .config_gen.datasource_list import WindowsRegistry, MacRegistry, MacArmRegistry, LinuxRegistry TDVT_LOG_FILE_NAME = 'tdvt_log_combined.txt' @@ -56,7 +57,7 @@ def copy_output_file(cls, src_name, src_dir, csv_dialect): cls.combined_output.append(row) except IOError as e: - logging.debug("Exception while copying files: " + str(e)) + logging.error("Exception while copying files: " + str(e)) return @classmethod @@ -65,6 +66,13 @@ def write_test_results_csv(cls, perf_run: bool, custom_output_dir: str = ''): logging.debug("write_test_results_csv called with no test output") return + # Create command line string for failed test. + failed_test_cmd = '' + for i in range(len(cls.combined_output)): + if cls.combined_output[i].get('Passed') == 'False': + failed_test_cmd = get_failed_cmd_line(cls, i) + cls.combined_output[i]['Error Msg'] += ' To run this test: \n' + failed_test_cmd + logging.debug("Copying output to {0}".format(cls.output_csv)) # Sort combined_output on the number of distinct functions (order of complexity) sort_by_complexity = lambda row: len(row['Functions'].split(',')) @@ -88,7 +96,7 @@ def write_test_results_csv(cls, perf_run: bool, custom_output_dir: str = ''): for row in cls.combined_output: writer.writerow(row) except IOError as e: - logging.debug("Exception while writing to file: " + str(e)) + logging.error("Exception while writing to file: " + str(e)) return def do_test_queue_work(i, q): @@ -208,7 +216,8 @@ def run(self): # Send output to null. DEVNULL = open(os.devnull, 'wb') output = DEVNULL if not self.verbose else None - logging.debug("\nRunning tdvt " + str(self.test_config) + " tdvt thread id: " + str(self.thread_id) + "\n") + logging.info("Running tdvt\tRunning {0}-{1}".format(self.test_config.suite_name, self.test_config.config_file)) + logging.debug("\t\tthread id: {}".format(self.thread_id)) print("Running {0} {1} {2}\n".format(self.test_config.suite_name, self.test_config.config_file, str(self.thread_id))) @@ -237,9 +246,11 @@ def delete_output_files(root_dir): continue -def get_datasource_registry(platform): +def get_datasource_registry(platform_name): """Get the datasources to run based on the suite parameter.""" - if sys.platform.startswith("darwin"): + if sys.platform.startswith("darwin") and platform.machine() == 'arm64': + reg = MacArmRegistry() + elif sys.platform.startswith("darwin"): reg = MacRegistry() elif sys.platform.startswith("linux"): reg = LinuxRegistry() @@ -376,11 +387,11 @@ def enqueue_tests(ds_info, args, suite): for x in tests: if not x.generate_test_file_list(): - logging.error("No tests found for config " + str(x)) - return test_set_configs + logging.error("No tests found for config {}".format(x.config_name)) + continue for test_set in tests: - tdvt_invocation = TdvtInvocation(from_args=args, test_config = ds_info) + tdvt_invocation = TdvtInvocation(from_args=args, test_config=ds_info) tdvt_invocation.logical = test_set.is_logical_test() tdvt_invocation.tds = test_set.tds_name tdvt_invocation.config_file = test_set.config_name @@ -417,17 +428,19 @@ def get_level_of_parallelization(args): The 'run' argument can also take the --verify flag to run a connection test against tests with SmokeTest = True set. run postgres_odbc --verify - Both logical and expression tests are run by default. - Run all expression tests + Both logical and expression tests are run by default; you can run only one suite using the -e or -q flag. + Run all expression tests: run postgres_odbc -e - Run all logical tests + Run all logical tests: run postgres_odbc -q There are multiple suites of expression tests, for example, standard and LOD (level of detail). The config files that drive the tests are named expression_test.sqlserver.cfg and expression.lod.sqlserver.cfg. To run just one of those try entering part of the config name as an argument: run postgres_odbc -e lod + + To run a single test set, using the run-pattern command rather than the run command. See the run-pattern command for more details. ''' @@ -475,10 +488,33 @@ def get_level_of_parallelization(args): run_file_usage_text = ''' ''' - def create_parser() -> argparse.ArgumentParser: - parser = argparse.ArgumentParser(description='TDVT - Tableau Datasource Verification Tool.') - parser.add_argument('--verbose', dest='verbose', action='store_true', help='Verbose output.', required=False) + parser = argparse.ArgumentParser( + formatter_class=argparse.RawTextHelpFormatter, + description=""" + _____ ______ _______ + |_ _| _ \ \ / /_ _| + | | | | | \ \ / / | | + | | | |_| |\ V / | | + |_| |____/ \_/ |_| + The Tableau Datasource Verification Tool + """ + ) + parser.add_argument( + '--verbose', + dest='verbose', + action='store_true', + help='Verbose logging - DEBUG level and up. Default is INFO', + required=False + ) + parser.add_argument( + '--loose-comparison', + dest='loose_comparison', + action='store_true', + default=False, + help='Loose comparison. Default is strict comparison.', + required=False + ) #Common run test options. run_test_common_parser = argparse.ArgumentParser(description='Common test run options.', add_help=False) @@ -564,12 +600,16 @@ def check_if_custom_output_dir_exists(custom_output_dir: str) -> bool: return Path(custom_output_dir).is_dir() -def return_logging_path(args: argparse.ArgumentParser) -> str: - if hasattr(args, 'custom_output_dir'): - if args.custom_output_dir is not None and check_if_custom_output_dir_exists(args.custom_output_dir): +def return_logging_path(args: argparse.Namespace) -> str: + if hasattr(args, "custom_output_dir"): + if args.custom_output_dir is not None and check_if_custom_output_dir_exists( + args.custom_output_dir + ): return os.path.join(args.custom_output_dir, TDVT_LOG_FILE_NAME) elif args.custom_output_dir is not None: - sys.exit("The specified output directory doesn't exist: %s" % Path(args.custom_output_dir)) + sys.exit( + f"The specified output directory doesn't exist: {args.custom_output_dir}" + ) else: pass return TDVT_LOG_FILE_NAME @@ -579,19 +619,17 @@ def init(): parser = create_parser() args = parser.parse_args() # Create logger. - logging.basicConfig(filename=return_logging_path(args), level=logging.DEBUG, filemode='w', - format='%(asctime)s %(message)s') + log_path = return_logging_path(args) + logging.basicConfig(filename=log_path, level=logging.INFO, filemode='w', + format='%(asctime)s %(levelname)s %(message)s', force=True) logger = logging.getLogger() + if args.verbose: + logger.setLevel(logging.DEBUG) ch = logging.StreamHandler() - if 'verbose' in args and args.verbose: - # Log to console also. - ch.setLevel(logging.DEBUG) - else: - args.verbose = False - ch.setLevel(logging.WARNING) + ch.setLevel(logging.WARNING) logger.addHandler(ch) - logging.debug('TDVT version: ' + str(__version__)) + logging.info('TDVT version: ' + str(__version__)) logging.debug('TDVT Arguments: ' + str(args)) ds_reg = get_datasource_registry(sys.platform) configure_tabquery_path() @@ -637,7 +675,7 @@ def test_runner(all_tests: List[TestRunner], test_queue: queue.Queue, max_thread def run_tests_impl( tests: List[Tuple[TestSet, TdvtInvocation]], max_threads: int, - args + args: argparse.Namespace, ) -> Optional[Tuple[int, int, int, int]]: if not tests: print("No tests found. Check arguments.") @@ -722,6 +760,7 @@ def run_tests_impl( test_queue.put(item) print("\nStarting tests. Creating " + str(max_threads) + " worker threads.") + logging.info("Testing using {} threads.".format(max_threads)) start_time = time.time() failed_tests, skipped_tests, disabled_tests, total_tests = test_runner(final_work, test_queue, max_threads) @@ -746,8 +785,13 @@ def run_tests_impl( print("\tMain test time: {} seconds".format(main_test_time)) print("\tTotal time: {} seconds".format(total_run_time)) + logging.info("Test Count: {}, Tests Run: {}, Passed: {}, Failed: {}, Disabled: {}, Skipped: {}".format( + total_tests, total_tests_run, total_passed_tests, failed_tests, disabled_tests, skipped_tests + ) + ) return failed_tests, skipped_tests, disabled_tests, total_tests + def get_ds_list(ds): if not ds: return [] @@ -755,7 +799,11 @@ def get_ds_list(ds): ds_list = [x.strip() for x in ds_list] return ds_list -def run_desired_tests(args, ds_registry: TestRegistry): + +def run_desired_tests( + args: argparse.Namespace, + ds_registry: TestRegistry +): generate_files(ds_registry, False) ds_to_run = ds_registry.get_datasources(get_ds_list(args.ds)) if not ds_to_run: @@ -814,10 +862,11 @@ def run_connectors_test(args): else: print(run_connectors_test_core( args.conn_test, args.conn_test_file)) + def run_file(run_file: Path, output_dir: Path, threads: int, args) -> int: """Rerun all the failed tests listed in the json file.""" - logging.debug("Running failed tests from : " + str(run_file)) + logging.info("Running failed tests from : " + str(run_file)) # See if we need to generate test setup files. root_directory = get_root_dir() @@ -827,12 +876,14 @@ def run_file(run_file: Path, output_dir: Path, threads: int, args) -> int: # This can be a retry-step. return 0 + def run_generate(ds_registry): start_time = time.time() generate_files(ds_registry, True) end_time = time.time() - start_time print("Done: " + str(end_time)) + def main(): parser, ds_registry, args = init() @@ -876,5 +927,6 @@ def main(): parser.print_help() sys.exit(-1) + if __name__ == '__main__': main() diff --git a/tdvt/tdvt/tdvt_core.py b/tdvt/tdvt/tdvt_core.py index dfcdef57..3df0d44d 100644 --- a/tdvt/tdvt/tdvt_core.py +++ b/tdvt/tdvt/tdvt_core.py @@ -28,6 +28,7 @@ from .tabquery import build_connectors_test_tabquery_command_line, build_tabquery_command_line from .test_results import * + class ConnectorsTest(object): def __init__(self, conn_test_name, conn_test_file, conn_test_password_file): self.conn_test_name = conn_test_name @@ -37,9 +38,14 @@ def __init__(self, conn_test_name, conn_test_file, conn_test_password_file): self.cmd_output: str = '' def run_connectors_test(self): - cmdline = build_connectors_test_tabquery_command_line(self.conn_test_name, self.conn_test_file, self.conn_test_password_file) - self.cmd_output = str(subprocess.check_output(cmdline, stderr=subprocess.STDOUT, universal_newlines=True, - timeout=self.timeout_seconds)) + cmdline = build_connectors_test_tabquery_command_line( + self.conn_test_name, self.conn_test_file, self.conn_test_password_file + ) + self.cmd_output = str( + subprocess.check_output( + cmdline, stderr=subprocess.STDOUT, universal_newlines=True, timeout=self.timeout_seconds + ) + ) print(self.cmd_output) sys.exit(0) @@ -55,8 +61,11 @@ def set_base_test_names(self, test_file): self.test_name = get_base_test(test_file) self.test_file = test_file if self.logical: - existing_output_filepath, actual_output_filepath, base_test_name, base_filepath, expected_dir = get_logical_test_file_paths( - self.test_file, self.output_dir) + existing_output_filepath, actual_output_filepath, base_test_name, base_filepath, expected_dir = ( + get_logical_test_file_paths( + self.test_file, self.output_dir + ) + ) # Make sure to set the generic (ie non-templatized) test name. self.test_name = base_test_name @@ -70,7 +79,6 @@ def __init__(self, test_config, test_set: TestSet): self.timeout_seconds = test_config.timeout_seconds self.cmd_output = '' self.saved_error_message = None - self.log_zip_file = '' self.verbose = test_config.verbose self.test_name = self.test_set.config_name self.setup_logs_and_tests() @@ -99,7 +107,7 @@ def load_test_metadata(self): entry.add_function(row['Function Categorized']) entry.add_category(row['Test Category']) except IOError as e: - logging.debug("Error loading test metadata: " + str(e)) + logging.error("Error loading test metadata: " + str(e)) def add_test_result(self, test_file, result): self.results[test_file] = result @@ -207,7 +215,7 @@ def process_test_results(self, test_list): sys.stdout.write('E') continue else: - logging.debug(self.get_thread_msg() + "Error: could not find test output file:" + existing_output_filepath) + logging.error(self.get_thread_msg() + "Error: could not find test output file:" + existing_output_filepath) sys.stdout.write('?') self.add_missing_test_failure(t) continue @@ -259,7 +267,7 @@ def run(self, test_list): try: self.setup_files(test_list) except IOError as e: - logging.debug(self.get_thread_msg() + "Output dir IOError " + str(e)) + logging.error(self.get_thread_msg() + "Output dir IOError " + str(e)) return 0 cmdline = build_tabquery_command_line(self) @@ -270,7 +278,7 @@ def run(self, test_list): self.run_process(cmdline) except subprocess.CalledProcessError as e: error_output = str(e.output) - logging.debug( + logging.error( self.get_thread_msg() + "CalledProcessError: Return code: " + str(e.returncode) + " " + error_output) # Let processing continue so it can try and find any output file which will contain database error messages. # Save the error message in case there is no result file to get it from. @@ -279,18 +287,18 @@ def run(self, test_list): if self.test_set.expected_message and self.test_set.expected_message in self.saved_error_message: self.error_state = TestErrorExpected() elif e.returncode == 18: - logging.debug(self.get_thread_msg() + "Tests aborted") + logging.error(self.get_thread_msg() + "Tests aborted") sys.stdout.write('A') self.error_state = TestErrorAbort() else: self.error_state = TestErrorOther() except subprocess.TimeoutExpired as e: - logging.debug(self.get_thread_msg() + "Test timed out") + logging.error(self.get_thread_msg() + "Test timed out") sys.stdout.write('T') self.error_state = TestErrorTimeout() self.timeout = True except RuntimeError as e: - logging.debug(self.get_thread_msg() + "RuntimeError: " + str(e)) + logging.error(self.get_thread_msg() + "RuntimeError: " + str(e)) self.saved_error_message = str(e) self.error_state = TestErrorOther() @@ -319,13 +327,6 @@ def do_work(work: BatchQueueWork): passed = False break - if passed and not work.verbose: - try: - os.remove(work.log_zip_file) - except Exception as e: - logging.debug(work.get_thread_msg() + "got exception deleting zipped log file: " + str(e)) - pass - def try_move(srcfile, destfile): move_attempt = 0 @@ -337,9 +338,30 @@ def try_move(srcfile, destfile): except: time.sleep(0.05) +def try_clean_and_move(srcfile, destfile): + file_xml = get_cleaned_results(srcfile) + with open(destfile, 'w') as file2: + file2.write(file_xml) + try: + os.remove(srcfile) + except FileNotFoundError as e: + logging.error(f"Unable to delete source file {srcfile}, with error {e}") +def get_cleaned_results(srcfile): + file_xml = '' + try: + with open(srcfile, 'r') as file1: + file_xml = file1.read() + file_xml = re.sub(r"[\S\s]*?<\/sql>\s*\n ", '', file_xml) + file_xml = re.sub(r"[\S\s]*?<\/query-time>\s*\n ", '', file_xml) + + except FileNotFoundError: + msg = "The file " + srcfile + "does not exist." + print(msg) + + return file_xml def save_results_diff(actual_file, diff_file, expected_file, diff_string): # Save a diff against the best matching file. @@ -352,19 +374,20 @@ def save_results_diff(actual_file, diff_file, expected_file, diff_string): except: pass - def expected_contains_error_tag(expected_file) -> bool: """ - This function + This function looks for datasource errors in the `actual` tuples. """ with open(expected_file, 'r') as f: file_content = f.read() - if '' in file_content: - return True - return False - - -def compare_results(test_name, test_file, full_test_file, work): + return '' in file_content + +def compare_results( + test_name, + test_file, + full_test_file, + work +) -> TestResult: """Return a TestResult object that specifies what was tested and whether it passed. test_file is the full path to the test file (base test name without any logical specification). full_test_file is the full path to the actual test file. @@ -379,7 +402,7 @@ def compare_results(test_name, test_file, full_test_file, work): result = TestResult(test_name, test_config, full_test_file, '', work.test_set) # There should be an actual file at this point. eg actual.setup.math.txt. if not os.path.isfile(actual_file): - logging.debug(work.get_thread_msg() + "Did not find actual file: " + actual_file) + logging.error(work.get_thread_msg() + "Did not find actual file: " + actual_file) result.error_status = TestErrorMissingActual() return result @@ -387,14 +410,14 @@ def compare_results(test_name, test_file, full_test_file, work): actual_xml = parse(actual_file).getroot() result.add_test_results(actual_xml, actual_file) except ParseError as e: - logging.debug(work.get_thread_msg() + "Exception parsing actual file: " + actual_file + " exception: " + str(e)) + logging.error(work.get_thread_msg() + "Exception parsing actual file: " + actual_file + " exception: " + str(e)) result.error_status = TestErrorMissingActual() return result expected_file_version: int = 0 for expected_file in expected_files: if not os.path.isfile(expected_file): - logging.debug(work.get_thread_msg() + "Did not find expected file " + expected_file) + logging.error(work.get_thread_msg() + "Did not find expected file " + expected_file) if test_config.generate_expected: # There is an actual but no expected, copy the actual to expected and return since there is nothing to compare against. # This is off by default since it can make tests pass when they should really fail. Might be a good command line option though. @@ -406,7 +429,7 @@ def compare_results(test_name, test_file, full_test_file, work): logging.warning("No actual file found, generating and moving expected file.") logging.debug( work.get_thread_msg() + "Copying actual [{}] to expected [{}]".format(actual_file, expected_file)) - try_move(actual_file, expected_file) + try_clean_and_move(actual_file, expected_file) result.error_status = TestErrorMissingActual() return result # Try other possible expected files. These are numbered like 'expected.setup.math.1.txt', 'expected.setup.math.2.txt' etc. @@ -415,7 +438,7 @@ def compare_results(test_name, test_file, full_test_file, work): try: expected_output.add_test_results(parse(expected_file).getroot(), '') except ParseError as e: - logging.debug( + logging.error( work.get_thread_msg() + "Exception parsing expected file: " + expected_file + " exception: " + str(e)) diff_counts, diff_string = result.diff_test_results(expected_output) @@ -444,7 +467,7 @@ def compare_results(test_name, test_file, full_test_file, work): base_test_file, test_config.output_dir) logging.debug(work.get_thread_msg() + "Copying actual [{}] to expected [{}]".format(actual_file, next_path)) - try_move(actual_file, next_path) + try_clean_and_move(actual_file, next_path) # This will re-diff the results against the best expected file to ensure the test pass indicator and diff count is correct. diff_count, diff_string = result.diff_test_results(result.best_matching_expected_results) save_results_diff(actual_file, actual_diff_file, result.path_to_expected, diff_string) @@ -491,7 +514,7 @@ def write_standard_test_output(all_test_results: Dict[str, TestResult], output_d json_file.write(json_str) json_file.close() except Exception: - logging.debug("Error writing ouput file [{0}].".format(json_file_path)) + logging.error("Error writing ouput file [{0}].".format(json_file_path)) def get_tuple_display_limit(): @@ -499,14 +522,14 @@ def get_tuple_display_limit(): def get_csv_row_data(tds_name: str, test_name: str, test_path: str, test_result: TestResult, test_case_index=0): - # A few of the tests generate thousands of tuples. Limit how many to include in the csv since it makes it unweildly. + # A few of the tests generate thousands of tuples. Limit how many to include in the csv since it makes it unwieldy. passed = False skipped = False disabled = False matched_expected = None diff_count = None test_case_name = None - error_msg = None # A description on why the test failed. This may or may not the query error in test output. + error_msg = None # A description on why the test failed. This may or may not the query error in test output. error_type = None time = None expected_time = None @@ -514,7 +537,7 @@ def get_csv_row_data(tds_name: str, test_name: str, test_path: str, test_result: expected_sql = None actual_tuples = None expected_tuples = None - actual_error = None # The query error in test output, which may be expected. Not to be confused with error_msg. + actual_error = None # The query error in test output, which may be expected. Not to be confused with error_msg. expected_error = None suite = test_result.test_config.suite_name if test_result else '' test_set_name = test_result.test_config.config_file if test_result else '' @@ -670,7 +693,7 @@ def write_csv_test_output( try: file_out = open(csv_file_path, 'w', encoding='utf8') except IOError: - logging.debug("Could not open output file [{0}].".format(csv_file_path)) + logging.error("Could not open output file [{0}].".format(csv_file_path)) return # set writer to use correct csv dialect @@ -761,12 +784,12 @@ def run_diff(test_config, diff): try: actual_xml = parse(actual).getroot() except ParseError as e: - logging.debug("Exception parsing actual file: " + actual + " exception: " + str(e)) + logging.error("Exception parsing actual file: " + actual + " exception: " + str(e)) continue try: expected_xml = parse(f).getroot() except ParseError as e: - logging.debug("Exception parsing expected file: " + f + " exception: " + str(e)) + logging.error("Exception parsing expected file: " + f + " exception: " + str(e)) continue result = TestResult(test_config=test_config) diff --git a/tdvt/tdvt/test_results.py b/tdvt/tdvt/test_results.py index eac5ce68..e6988fb9 100644 --- a/tdvt/tdvt/test_results.py +++ b/tdvt/tdvt/test_results.py @@ -1,5 +1,5 @@ """ Test result and configuration related classes. """ - +import logging import math import json import re @@ -42,7 +42,8 @@ class TestCaseResult(object): ie The math.round test contains ROUND(int), ROUND(num) etc test cases. """ - def __init__(self, name, id, sql, query_time, error_msg, error_type, table, test_config, test_metadata): + def __init__(self, name, id, sql, query_time, error_msg, error_type, table, test_config, test_metadata, + test_tolerance=None): self.name = name self.id = id self.sql = sql @@ -57,6 +58,7 @@ def __init__(self, name, id, sql, query_time, error_msg, error_type, table, test self.passed_error = False self.tested_config = test_config self.test_metadata = test_metadata + self.test_tolerance = test_tolerance def set_diff(self, diff_string, diff_count): self.diff_string = diff_string @@ -210,7 +212,7 @@ def __init__(self, base_name='', test_config=TdvtInvocation(), test_file='', rel self.path_to_expected = '' self.path_to_actual = '' self.overall_error_message = '' - self.test_case_map = [] + self.test_case_map: list[Optional[TestCaseResult]] = [] self.cmd_output = '' self.relative_test_file = relative_test_file self.test_set: Optional[TestSet] = test_set @@ -322,10 +324,22 @@ def add_test_results(self, test_xml, actual_path): sq = node.text if node is not None else '' test_child_name = test_child.get('name') + + test_child_tolerance = test_child.get('tolerance') if not test_child_name: continue - test_result = TestCaseResult(test_child_name, str( - i), sq, query_time, error_msg, error_type, test_child.find('table'), self.test_config, self.test_metadata) + test_result = TestCaseResult( + test_child_name, + str(i), + sq, + query_time, + error_msg, + error_type, + test_child.find('table'), + self.test_config, + self.test_metadata, + test_child_tolerance + ) temp_test_cases.append(test_result) if temp_test_cases: @@ -446,7 +460,7 @@ def get_skipped_count(self): def get_test_case_count(self): return len(self.test_case_map) if self.test_case_map else 0 - def get_test_case(self, index): + def get_test_case(self, index: int) -> Optional[TestCaseResult]: case = None try: case = self.test_case_map[index] @@ -483,7 +497,7 @@ def diff_test_results(self, expected_output: 'TestResult'): # Compare the tuples. if config.tested_tuples: - diff, diff_string = self.diff_table_node(actual_testcase_self, expected_testcase_self.table, + diff, diff_string = self.diff_table_node(actual_testcase_self, expected_testcase_self, diff_string, expected_testcase_self.name) actual_testcase_self.passed_tuples = diff == 0 diff_counts[test_case] = diff @@ -498,12 +512,55 @@ def diff_test_results(self, expected_output: 'TestResult'): self.diff_string = diff_string return diff_counts, diff_string - def diff_table_node(self, actual_result: TestCaseResult, expected_table, diff_string, test_name): - if actual_result.table is None or expected_table is None: + def actual_expected_comparison( + self, + expected: str, + actual: str, + tolerance: Optional[float], + loose_comparison_enabled: bool, + data_type: Optional[str] = None + ) -> bool: + """ + Compares actual and expected values, returning True if they match. + """ + if actual == '%null%': + return expected == actual + elif data_type and tolerance and loose_comparison_enabled: + + if data_type == 'float': + try: + cleaned_expected = float(expected.replace('"', '').replace('"', '')) + cleaned_actual = float(actual.replace('"', '').replace('"', '')) + except ValueError: + logging.error( + f'Could not convert expected or actual to {data_type}. Expected: {expected}, actual: {actual}' + ) + return expected != actual + logging.info(f"Loose comparison enabled for {self.name}: tolerance={tolerance}, data_type={data_type}") + return math.isclose(cleaned_actual, cleaned_expected, rel_tol=tolerance) + else: + return expected == actual + else: + return expected == actual + + def diff_table_node( + self, + actual_result: TestCaseResult, + expected_result: TestCaseResult, + diff_string: str, + test_name: str + ) -> tuple[int, str]: + if actual_result.table is None or expected_result is None: return (-1, diff_string) + # TODO: add flexibility about tolerance if it exists; maybe we want date stamp flexibility, etc. + + expected_result_table = expected_result.table + test_case_tolerance = self.get_test_case_tolerance(expected_result) + actual_tuples = actual_result.table.findall('tuple') - expected_tuples = expected_table.findall('tuple') + expected_tuples = expected_result_table.findall('tuple') + column_return_type = expected_result_table.findall('schema/column') if actual_tuples == None and expected_tuples == None: return (0, diff_string) @@ -526,6 +583,11 @@ def diff_table_node(self, actual_result: TestCaseResult, expected_table, diff_st diff_count = 0 + data_type_list = [item.attrib.get('return-type') for item in column_return_type] + + if not data_type_list: + data_type_list = [None] + expected_tuple_list = [] for j in expected_tuples: for k in j.findall('value'): @@ -536,17 +598,39 @@ def diff_table_node(self, actual_result: TestCaseResult, expected_table, diff_st for k in j.findall('value'): actual_tuple_list.append(k.text) - diff_count = sum(a != b for a, b in zip( - actual_tuple_list, expected_tuple_list)) + full_count_data_type = data_type_list * (len(actual_tuple_list) // len(data_type_list)) + + if len(full_count_data_type) != len(actual_tuple_list): + logging.error("Data type list and actual tuple list are not the same length.") + return -1, 'Error: Data type list and actual tuple list are not the same length.' + + loose_comparison_enabled = self.test_config.loose_comparison + + diff_count = 0 diff_count += abs(len(actual_tuple_list) - len(expected_tuple_list)) - for a, b in zip(actual_tuple_list, expected_tuple_list): - if a != b: + for actual_value, expected_value, data_type in zip( + actual_tuple_list, expected_tuple_list, full_count_data_type + ): + if not self.actual_expected_comparison( + actual_value, expected_value, test_case_tolerance, loose_comparison_enabled, data_type + ): + diff_count += 1 diff_string += "\t <<<< >>>> \n" - diff_string += "\tactual: " + a + "\n" - diff_string += "\texpected: " + b + "\n" + diff_string += "\tactual: " + actual_value + "\n" + diff_string += "\texpected: " + expected_value + "\n" + + return diff_count, diff_string - return (diff_count, diff_string) + def get_test_case_tolerance(self, expected_result) -> Optional[float]: + test_case_tolerance = expected_result.test_tolerance + if test_case_tolerance: + try: + test_case_tolerance = float(test_case_tolerance) + except ValueError: + logging.warning("Tolerance couldn't be cast to float. Not using.") + test_case_tolerance = None + return test_case_tolerance def diff_sql_node(self, actual_sql, expected_sql, diff_string): if actual_sql == None and expected_sql == None: diff --git a/tdvt/tdvt/version.py b/tdvt/tdvt/version.py index 95a25954..ce094cb0 100644 --- a/tdvt/tdvt/version.py +++ b/tdvt/tdvt/version.py @@ -1 +1 @@ -__version__ = '2.7.6' +__version__ = '2.13.4' diff --git a/tdvt/test/tdvt_test.py b/tdvt/test/tdvt_test.py index 5b9ea739..98a94e26 100644 --- a/tdvt/test/tdvt_test.py +++ b/tdvt/test/tdvt_test.py @@ -15,11 +15,13 @@ import io import logging +import platform +import re import shutil import subprocess +import sys import unittest -from collections import Counter from pathlib import Path from typing import List from unittest import mock @@ -34,9 +36,13 @@ from tdvt.tabquery import * from tdvt.config_gen.test_creator import TestCreator +from tdvt.setup_env import updated_tds_as_str, get_failed_cmd_line +from tdvt.tdvt_core import get_cleaned_results, do_work +from tdvt.tdvt import TestOutputFiles class DiffTest(unittest.TestCase): + def test_diff(self): logging.debug("Starting diff tests:\n") subdir = 'diff_tests' @@ -316,8 +322,9 @@ def setUp(self): def test_command_line_override_full(self): linux_path = 'some_other_linux' mac_path = 'another_mac' + mac_arm_path = 'another_arm_mac' win_path = 'something_windows.exe' - self.test_config.tested_run_time_config.set_tabquery_paths(linux_path, mac_path, win_path) + self.test_config.tested_run_time_config.set_tabquery_paths(linux_path, mac_path, mac_arm_path, win_path) work = tdvt_core.BatchQueueWork(self.test_config, self.test_set) cmd_line = build_tabquery_command_line_local(work) @@ -334,7 +341,7 @@ def test_command_line_override_full(self): def test_command_line_full(self): self.test_config.output_dir = 'my/output/dir' self.test_config.d_override = '-DLogLevel=Debug' - self.test_config.tested_run_time_config.set_tabquery_paths("tabquerytool", "tabquerytool", "tabquerytool.exe") + self.test_config.tested_run_time_config.set_tabquery_paths("tabquerytool", "tabquerytool", "tabquerycli", "tabquerytool.exe") work = tdvt_core.BatchQueueWork(self.test_config, self.test_set) cmd_line = build_tabquery_command_line_local(work) @@ -349,7 +356,7 @@ def test_command_line_full(self): def test_password_file(self): self.test_config.output_dir = 'my/output/dir' - self.test_config.tested_run_time_config.set_tabquery_paths("tabquerytool", "tabquerytool", "tabquerytool.exe") + self.test_config.tested_run_time_config.set_tabquery_paths("tabquerytool", "tabquerytool", "tabquerycli", "tabquerytool.exe") suite = 'password_test' self.test_set = ExpressionTestSet('', TEST_DIRECTORY, 'mytest', self.test_config.tds, '', self.test_file, suite) @@ -359,7 +366,7 @@ def test_password_file(self): self.assertTrue('--password-file' in cmd_line_str and 'password_test.password' in cmd_line_str) def test_command_line_no_expected(self): - self.test_config.tested_run_time_config.set_tabquery_paths("tabquerytool", "tabquerytool", "tabquerytool.exe") + self.test_config.tested_run_time_config.set_tabquery_paths("tabquerytool", "tabquerytool", "tabquerycli", "tabquerytool.exe") work = tdvt_core.BatchQueueWork(self.test_config, self.test_set) cmd_line = build_tabquery_command_line_local(work) cmd_line_str = ' '.join(cmd_line) @@ -373,7 +380,7 @@ def test_command_line_no_expected(self): def test_command_line_multiple_override(self): self.test_config.d_override = '-DLogLevel=Debug -DUseJDBC -DOverride=MongoDBConnector:on,SomethingElse:off' - self.test_config.tested_run_time_config.set_tabquery_paths("tabquerytool", "tabquerytool", "tabquerytool.exe") + self.test_config.tested_run_time_config.set_tabquery_paths("tabquerytool", "tabquerytool", "tabquerycli", "tabquerytool.exe") work = tdvt_core.BatchQueueWork(self.test_config, self.test_set) cmd_line = build_tabquery_command_line_local(work) @@ -396,7 +403,7 @@ def test_command_line_multiple_override_from_invocation(self): test_file = 'some/test/file.txt' test_set = ExpressionTestSet('', TEST_DIRECTORY, 'mytest', test_config.tds, '', self.test_file, '') - test_config.tested_run_time_config.set_tabquery_paths("tabquerytool", "tabquerytool", "tabquerytool.exe") + test_config.tested_run_time_config.set_tabquery_paths("tabquerytool", "tabquerytool", "tabquerycli", "tabquerytool.exe") work = tdvt_core.BatchQueueWork(test_config, self.test_set) cmd_line = build_tabquery_command_line_local(work) @@ -630,7 +637,7 @@ def test_load_command_line_override(self): config = configparser.ConfigParser() config.read(get_path('tool_test/ini', 'override.ini', __name__)) test_config = datasource_list.load_test(config, TEST_DIRECTORY) - x = test_config.get_logical_tests() + test_config.get_expression_tests() + list_of_test_sets = test_config.get_logical_tests() + test_config.get_expression_tests() test1 = LogicalTestSet(test_config.dsname, TEST_DIRECTORY, 'logical.calcs.bigquery', 'cast_calcs.bigquery.tds', '', 'logicaltests/setup/calcs/setup.*.bigquery.xml', test_config.dsname) @@ -647,15 +654,18 @@ def test_load_command_line_override(self): 'Override did not match: ' + test_config.run_time_config.d_override) for test in tests: - found = [y for y in x if y == test] - self.assertTrue(found, "[Did not find expected value of [{0}]".format(test)) + found = [y for y in list_of_test_sets if y == test] + self.assertTrue(found, "[Did not find expected value of [{0}]; found {1}".format(test, found)) def test_load_tabquery_override(self): config = configparser.ConfigParser() config.read(get_path('tool_test/ini', 'postgres_jdbc_tabquerytool.ini', __name__)) test_config = datasource_list.load_test(config, TEST_DIRECTORY) - self.assertTrue(test_config.run_time_config.tabquery_paths.get_path("darwin") == 'tabquerytool_mac') + if sys.platform.startswith('darwin') and platform.machine() == 'arm64': + self.assertTrue(test_config.run_time_config.tabquery_paths.get_path("darwin") == 'tabquerytool_mac_arm') + else: + self.assertTrue(test_config.run_time_config.tabquery_paths.get_path("darwin") == 'tabquerytool_mac') self.assertTrue(test_config.run_time_config.tabquery_paths.get_path("linux") == 'tabquerytool_linux') self.assertTrue(test_config.run_time_config.tabquery_paths.get_path("win32") == 'tabquerytool_windows.exe') @@ -977,27 +987,45 @@ def check_errors(self, expected_message, expected_state, mock_batch, error_count "Expected [{0}] got [{1}]".format(expected_message, actual_message)) self.assertIsInstance(mock_batch.results[test_file].error_status, expected_state) + def test_get_cleaned_results(self): + srcfile = TEST_DIRECTORY + '/exprtests/expected.setup.agg.avg.txt' + cleaned_results = get_cleaned_results(srcfile) + self.assertIn("AVG([int0])'>\n
", cleaned_results) + self.assertIn("AVG([num4])'>\n
", cleaned_results) + class TabQueryPathTest(unittest.TestCase): def test_init(self): - t = TabQueryPath('linux/linux', 'mac/mac/mac', 'win\\win.exe') - a = str(t.get_path('darwin')) - self.assertTrue(str(t.get_path('darwin')) == 'mac/mac/mac') + t = TabQueryPath('linux/linux', 'mac/mac/mac', 'mac_arm/mac_arm/mac_arm', 'win\\win.exe') + if sys.platform.startswith("darwin"): + if platform.machine() == 'arm64': + self.assertTrue(str(t.get_path('darwin')) == 'mac_arm/mac_arm/mac_arm') + else: + self.assertTrue(str(t.get_path('darwin')) == 'mac/mac/mac') self.assertTrue(str(t.get_path('linux')) == 'linux/linux') self.assertTrue(str(t.get_path('windows')) == 'win\\win.exe') def test_string(self): - t = TabQueryPath('linux', 'mac', 'win') - self.assertTrue(t.get_path('darwin') == 'mac') + t = TabQueryPath('linux', 'mac', 'mac_arm', 'win') + if sys.platform.startswith("darwin"): + if platform.machine() == 'arm64': + self.assertTrue(t.get_path('darwin') == 'mac_arm') + else: + self.assertTrue(t.get_path('darwin') == 'mac') self.assertTrue(t.get_path('linux') == 'linux') self.assertTrue(t.get_path('windows') == 'win') string_value = t.to_array() self.assertTrue(string_value[0] == 'linux') self.assertTrue(string_value[1] == 'mac') - self.assertTrue(string_value[2] == 'win') + self.assertTrue(string_value[2] == 'mac_arm') + self.assertTrue(string_value[3] == 'win') t2 = TabQueryPath.from_array(string_value) - self.assertTrue(t2.get_path('darwin') == 'mac') + if sys.platform.startswith("darwin"): + if platform.machine() == 'arm64': + self.assertTrue(t2.get_path('darwin') == 'mac_arm') + else: + self.assertTrue(t2.get_path('darwin') == 'mac') self.assertTrue(t2.get_path('linux') == 'linux') self.assertTrue(t2.get_path('windows') == 'win') @@ -1152,6 +1180,190 @@ def test_map_user_cols_to_test_cols_missing_t0(self): 'zzz': ['k', 's0', 's1', 'z']} ) +class MangleTest(unittest.TestCase): + + with open('tool_test/tds/cast_calcs.tde.tds', 'r') as f: + new_lines = updated_tds_as_str(f, 'postgres_connection') + + def test_mangletds_tdvtconnection(self): + self.assertIn( + "", + self.new_lines + ) + + def test_mangletds_relation_connection(self): + self.assertIn( + "", + self.new_lines + ) + + def test_mangletds_named_connection(self): + self.assertIn( + "", + self.new_lines + ) + +class TestOutputFilesTest(unittest.TestCase): + good_test_results = TestOutputFiles() + good_test_results.combined_output = [ + {'Suite': 'postgres', 'Test Set': 'StaplesConnectionTestpostgres', 'TDSName': 'Staples.postgres', + 'TestName': 'staples.connection.test', + 'TestPath': 'path/to/tdvt/root/logicaltests/setup/connection_test/setup.staples.connection.test.simple.xml', + 'Passed': 'True', 'Closest Expected': '0', 'Diff count': '0', + 'Test Case': 'path/to/tdvt/root/tdvt/tdvt/tdvt/logicaltests/setup/connection_test/setup.staples.connection.test.simple.xml', + 'Test Type': 'logical', 'Priority': 'unknown', 'Categories': 'unknown', 'Functions': 'unknown', + 'Process Output': 'Attempting to run query...\nRun query successful! Check output file\n', 'Error Msg': 'None', + 'Error Type': 'None', 'Query Time (ms)': '169.0', + 'Generated SQL': '\n SELECT "Staples"."Discount" AS "Ship Priority"\nFROM "Staples"\nGROUP BY 1\n ', + 'Actual (100)tuples': '"0"\n"0.01"\n"0.02"\n"0.03"\n"0.04"\n"0.05"\n"0.06"\n"0.07"\n"0.08"\n"0.09"\n"0.1"\n"0.11"\n"0.12"\n"0.13"\n"0.15"\n"0.21"\n"0.24"\n"0.27"\n"0.3"\n"0.36"\n"0.39"', + 'Expected (100)tuples': '"0"\n"0.01"\n"0.02"\n"0.03"\n"0.04"\n"0.05"\n"0.06"\n"0.07"\n"0.08"\n"0.09"\n"0.1"\n"0.11"\n"0.12"\n"0.13"\n"0.15"\n"0.21"\n"0.24"\n"0.27"\n"0.3"\n"0.36"\n"0.39"'}, + {'Suite': 'postgres', 'Test Set': 'CastCalcsConnectionTestpostgres', 'TDSName': 'cast_calcs.postgres', + 'TestName': 'calcs_connection_test', + 'TestPath': 'path/to/tdvt/root/tdvt/tdvt/tdvt/exprtests/pretest/connection_tests/calcs/setup.calcs_connection_test.txt', + 'Passed': 'True', 'Closest Expected': '0', 'Diff count': '0', 'Test Case': 'key', 'Test Type': 'expression', + 'Priority': 'unknown', 'Categories': 'unknown', 'Functions': 'unknown', 'Process Output': '', + 'Error Msg': 'None', 'Error Type': 'None', 'Query Time (ms)': '200.0', + 'Generated SQL': '\n SELECT "Calcs"."key" AS "TEMP(Test)(3382465274)(0)"\nFROM "Calcs"\nGROUP BY 1\n ', + 'Actual (100)tuples': '"key00"\n"key01"\n"key02"\n"key03"\n"key04"\n"key05"\n"key06"\n"key07"\n"key08"\n"key09"\n"key10"\n"key11"\n"key12"\n"key13"\n"key14"\n"key15"\n"key16"', + 'Expected (100)tuples': '"key00"\n"key01"\n"key02"\n"key03"\n"key04"\n"key05"\n"key06"\n"key07"\n"key08"\n"key09"\n"key10"\n"key11"\n"key12"\n"key13"\n"key14"\n"key15"\n"key16"'}] + + def test_logical_test_return(self): + cmd_line = get_failed_cmd_line(self.good_test_results, 0) + expected = 'python -m run-pattern postgres --logp path/to/tdvt/root/logicaltests/setup/connection_test/setup.staples.connection.test.simple.xml --tdp Staples.postgres.tds' + self.assertEqual(cmd_line, expected) + + def test_expression_test_return(self): + cmd_line = get_failed_cmd_line(self.good_test_results, 1) + expected = 'python -m run-pattern postgres --exp path/to/tdvt/root/tdvt/tdvt/tdvt/exprtests/pretest/connection_tests/calcs/setup.calcs_connection_test.txt --tdp cast_calcs.postgres.tds' + self.assertEqual(cmd_line, expected) + + +class Do_WorkFunctionTest(unittest.TestCase): + def setUp(self): + error_message = 'Mock RunTime Error' + self.mock_tests = [TestFile('tests', './tests/e/suite1/setup.mytest.txt')] + self.test_config = TdvtInvocation() + self.ts1_expr = MockTestSet('not used', 'not used', 'mock ds', 'tests', 'mock config', 'mock.tds', '', + 'tests/*.txt', False, 'mock suite expression', '', '') + self.mock_batch = MockBatchQueueWork(self.mock_tests, self.test_config, self.ts1_expr) + + def tearDown(self): + pass + + def test_mock_batch_init(self): + self.assertIsInstance(self.mock_batch, MockBatchQueueWork) + + def test_mock_batch_do_work(self): + do_work(self.mock_batch) + self.assertEqual(self.mock_batch.error_state, None) + + def test_mock_batch_do_work_disabled_test(self): + self.mock_batch.test_set.test_is_enabled = False + do_work(self.mock_batch) + + self.assertIsInstance(self.mock_batch.error_state, TestErrorDisabledTest) + + def test_mock_batch_do_work_skipped_test(self): + self.mock_batch.test_set.test_is_skipped = True + do_work(self.mock_batch) + + self.assertIsInstance(self.mock_batch.error_state, TestErrorSkippedTest) + + +class ToleranceTest(unittest.TestCase): + """ + The TestResult.actual_expected_comparison() method returns True when actual & expected match, and False if there is + no match. + """ + tr = TestResult() + + def test_actual_expected_nulls_that_match_no_tolerance(self): + + self.assertTrue( + self.tr.actual_expected_comparison('%null%', '%null%', None, False) + ) + + def test_actual_expected_nulls_match_with_tolerance_and_data_type(self): + self.assertTrue( + self.tr.actual_expected_comparison('%null%', '%null%', 0.05, True, 'float') + ) + + def test_actual_is_null_expected_is_float(self): + self.assertFalse( + self.tr.actual_expected_comparison('1.001', '%null%', 0.05, True, 'float') + ) + + def test_actual_expected_comparison_method_no_match_no_tolerance(self): + self.assertFalse( + self.tr.actual_expected_comparison('1', '2', None, False) + ) + + def test_actual_expected_comparison_method_no_match_no_tolerance_loose_enabled(self): + self.assertFalse( + self.tr.actual_expected_comparison('1', '2', None, True) + ) + + def test_actual_expected_comparison_method_match_with_or_without_tolerance(self): + self.assertTrue( + self.tr.actual_expected_comparison('1.01', '1.01', 0.05, True, 'float') + ) + + def test_actual_expected_comparison_method_match_with_or_without_tolerance_loose_disabled(self): + self.assertTrue( + self.tr.actual_expected_comparison('1.01', '1.01', 0.05, False, 'float') + ) + + def test_actual_expected_comparison_method_match_only_with_tolerance(self): + self.assertTrue( + self.tr.actual_expected_comparison('1.01', '1.05', 0.05, True, 'float') + ) + + def test_actual_expected_comparison_method_no_match_with_tolerance(self): + self.assertFalse( + self.tr.actual_expected_comparison('1.01', '1.25', 0.05, True, 'float') + ) + + def test_actual_expected_comparison_tolerance_with_trailing_zeors(self): + # this test is for GitHub Issue 1178 + self.assertTrue( + self.tr.actual_expected_comparison('1.01', '1.0100000', 0.05, True, 'float') + ) + + def test_actual_is_float_expected_is_int_with_tolerance(self): + self.assertTrue( + self.tr.actual_expected_comparison('1', '1.01', 0.05, True, 'float') + ) + + def test_actual_is_int_expected_is_float_with_tolerance(self): + self.assertTrue( + self.tr.actual_expected_comparison('1.01', '1', 0.05, True, 'float') + ) + + def test_comparison_method_with_tolerance_but_no_datatype_matches(self): + self.assertTrue( + self.tr.actual_expected_comparison('1.01', '1.01', 0.05, True, None) + ) + + def test_comparison_method_with_tolerance_but_no_datatype_does_not_match(self): + self.assertFalse( + self.tr.actual_expected_comparison('1.01', '1.25', 0.05, True, None) + ) + + def test_comparison_method_with_datatype_only(self): + self.assertTrue( + self.tr.actual_expected_comparison('1.01', '1.01', None, True, 'float') + ) + + def test_comparison_method_with_datatype_only_does_not_match(self): + self.assertFalse( + self.tr.actual_expected_comparison('1.01', '1.25', None, True, 'float') + ) + + def test_comparison_method_with_null_as_actual(self): + self.assertFalse( + self.tr.actual_expected_comparison('1.00', '%null%', .05, True, 'float') + ) + ROOT_DIRECTORY = pkg_resources.resource_filename(__name__, '') TEST_DIRECTORY = pkg_resources.resource_filename(__name__, 'tool_test') diff --git a/tdvt/test/tool_test/exprtests/expected.setup.agg.avg.txt b/tdvt/test/tool_test/exprtests/expected.setup.agg.avg.txt new file mode 100644 index 00000000..194bb3de --- /dev/null +++ b/tdvt/test/tool_test/exprtests/expected.setup.agg.avg.txt @@ -0,0 +1,30 @@ + + + + SELECT AVG("Calcs"."int0") AS "TEMP(Test)(3952218057)(0)" FROM "Calcs" HAVING (COUNT(1) > 0) + + 308.000 +
+ + [cast_calcs.postgres].[TEMP(Test)(3952218057)(0)] + + + 6.1818182 + +
+
+ + + SELECT AVG("Calcs"."num4") AS "TEMP(Test)(1371989636)(0)" FROM "Calcs" HAVING (COUNT(1) > 0) + + 232.000 + + + [cast_calcs.postgres].[TEMP(Test)(1371989636)(0)] + + + 2.0016667 + +
+
+
\ No newline at end of file diff --git a/tdvt/test/tool_test/ini/postgres_jdbc_tabquerytool.ini b/tdvt/test/tool_test/ini/postgres_jdbc_tabquerytool.ini index 5657b787..08d0d49f 100644 --- a/tdvt/test/tool_test/ini/postgres_jdbc_tabquerytool.ini +++ b/tdvt/test/tool_test/ini/postgres_jdbc_tabquerytool.ini @@ -3,7 +3,8 @@ Name = postgres_jdbc_tabquerytool LogicalQueryFormat = simple_public CommandLineOverride = -DConnectPluginsPath=plugins TabQueryPathLinux = tabquerytool_linux -TabQueryPathMac = tabquerytool_mac +TabQueryPathMac = tabquerytool_mac +TabQueryPathMacArm = tabquerytool_mac_arm TabQueryPathx64 = tabquerytool_windows.exe [ConnectionTests]