From dc774b3f9a31123171ea9b300e0ce364ed319d5f Mon Sep 17 00:00:00 2001 From: Thomas Latham Date: Tue, 29 Oct 2024 13:18:51 +0000 Subject: [PATCH] Sanity test fixes, review comments, logging & test improvements --- galaxy.yml | 2 +- plugins/module_utils/_data_set_utils.py | 82 ++++----- plugins/module_utils/_global_catalog.py | 50 +++--- tests/sanity/ignore-2.17.txt | 15 ++ tests/unit/helpers/data_set_helper.py | 42 ++++- tests/unit/module_utils/test_dataset_utils.py | 93 +++++----- .../unit/module_utils/test_global_catalog.py | 161 +++++++++--------- tests/unit/modules/test_global_catalog.py | 53 +++--- 8 files changed, 260 insertions(+), 238 deletions(-) create mode 100644 tests/sanity/ignore-2.17.txt diff --git a/galaxy.yml b/galaxy.yml index 0611c132..7efd517f 100644 --- a/galaxy.yml +++ b/galaxy.yml @@ -8,7 +8,7 @@ namespace: ibm name: ibm_zos_cics # The collection version -version: 2.2.0 +version: 2.1.0 # Collection README file readme: README.md diff --git a/plugins/module_utils/_data_set_utils.py b/plugins/module_utils/_data_set_utils.py index 057f378e..a6ec727c 100644 --- a/plugins/module_utils/_data_set_utils.py +++ b/plugins/module_utils/_data_set_utils.py @@ -274,20 +274,21 @@ def _execute_command(command): module = AnsibleModuleHelper(argument_spec={}) return module.run_command(command) + def _submit_jcl(jcl_uss_path, job_name): - executions =[] + executions = [] command = "jsub -f '{0}'".format(jcl_uss_path) - rc, stdout,stderr = _execute_command(command) + rc, stdout, stderr = _execute_command(command) executions.append( - _execution( - name="Submit jcl job {0} for {1}".format(jcl_uss_path, job_name), - rc=rc, - stdout=stdout, - stderr=stderr)) + _execution( + name="Submit JCL job for {0}".format(job_name), + rc=rc, + stdout=stdout, + stderr=stderr)) if rc != 0: raise MVSExecutionException( - "RC {0} when submitting jcl from {1}".format( + "RC {0} when submitting JCL from {1}".format( rc, jcl_uss_path), executions) return executions @@ -295,45 +296,32 @@ def _submit_jcl(jcl_uss_path, job_name): def _get_job_output(job_id, job_name): executions = [] - try: - jobs = job_output(job_id=job_id, job_name=job_name) - - #There should only be one job found for the JCL submitted - if (len(jobs) != 1): - raise MVSExecutionException( - "Query for job status for {0} with job id {1} returned more than one result. Jobs returned: {2}".format( - job_name, - job_id, - jobs), executions) - - executions.append( - _execution( - name="Get job output for {0}".format(job_id), - rc=jobs[0].get("ret_code").get("code"), - stdout=jobs[0].get("ret_code").get("msg", ""), - stderr=jobs[0].get("ret_code").get("msg_txt", ""))) - except Exception as e: - raise MVSExecutionException( - "Query for {0} job submitted under Job ID {1} failed. An exception occured: {2}".format( - job_name, - job_id, - e), executions) - - try: - # job output fails to get the ddname content in its response. Call direct into zoau to do it - for i in range(len(jobs[0].get("ddnames"))): - dd_executions, job_stdout = _get_job_dd(job_id, jobs[0]["ddnames"][i]["ddname"]) - - #Put the content back in the job response object - jobs[0]["ddnames"][i]["content"] = job_stdout - executions.append(dd_executions) - - return jobs[0], executions - except Exception as e: + jobs = job_output(job_id=job_id, job_name=job_name) + + # There should only be one job found for the JCL submitted + if (len(jobs) != 1): raise MVSExecutionException( - "Could not get all job DDs for {0}. An exception occured: {1}".format( - job_name, - e), executions) + "Query for job status for {0} with job ID {1} returned more than one result. Jobs returned: {2}".format( + job_name, + job_id, + jobs), executions) + + executions.append( + _execution( + name="Get job output for {0}".format(job_id), + rc=jobs[0]["ret_code"].get("code"), + stdout=jobs[0]["ret_code"].get("msg", ""), + stderr=jobs[0]["ret_code"].get("msg_txt", ""))) + + # job output fails to get the ddname content in its response. Call direct into zoau to do it + for i in range(len(jobs[0].get("ddnames"))): + dd_executions, job_stdout = _get_job_dd(job_id, jobs[0]["ddnames"][i]["ddname"]) + + # Put the content back in the job response object + jobs[0]["ddnames"][i]["content"] = job_stdout + executions.append(dd_executions) + + return jobs[0], executions def _get_job_dd(job_id, dd_name): @@ -343,7 +331,7 @@ def _get_job_dd(job_id, dd_name): rc, stdout, stderr = _execute_command(command) executions.append( _execution( - name="Get job dd {0} output for {1}".format(dd_name, job_id), + name="Get job DD {0} output for {1}".format(dd_name, job_id), rc=rc, stdout=stdout, stderr=stderr)) diff --git a/plugins/module_utils/_global_catalog.py b/plugins/module_utils/_global_catalog.py index 670113b3..2b533981 100644 --- a/plugins/module_utils/_global_catalog.py +++ b/plugins/module_utils/_global_catalog.py @@ -6,15 +6,16 @@ # FOR INTERNAL USE IN THE COLLECTION ONLY. from __future__ import (absolute_import, division, print_function) -import os +from os import remove __metaclass__ = type from ansible_collections.ibm.ibm_zos_cics.plugins.module_utils._response import MVSExecutionException, _execution from ansible_collections.ibm.ibm_zos_cics.plugins.module_utils._data_set_utils import MVS_CMD_RETRY_ATTEMPTS, _submit_jcl, _get_job_output -import tempfile +from tempfile import NamedTemporaryFile from time import sleep + def _get_value_from_line(line): # type: (list[str]) -> str | None val = None if len(line) == 1: @@ -55,15 +56,16 @@ def _get_catalog_records(stdout): # type: (str) -> tuple[str | None, str | None return (autostart_override, nextstart) + def _create_dfhrmutl_jcl(location, sdfhload, cmd=""): steplib_line = f"//STEPLIB DD DSNAME={sdfhload},DISP=SHR" dfhgcd_line = f"//DFHGCD DD DSNAME={location},DISP=OLD" # Validate line lengths - _validate_line_length(steplib_line, sdfhload) - _validate_line_length(dfhgcd_line, location) - + _validate_line_length(steplib_line, sdfhload, "cics_data_sets") + _validate_line_length(dfhgcd_line, location, "region_data_sets") + jcl = "" - if (cmd ==""): + if (cmd == ""): jcl = f''' //DFHRMUTL JOB //RMUTL EXEC PGM=DFHRMUTL,REGION=1M @@ -86,7 +88,7 @@ def _create_dfhrmutl_jcl(location, sdfhload, cmd=""): ''' # Create a temporary file - with tempfile.NamedTemporaryFile(mode='w+', delete=False) as fp: + with NamedTemporaryFile(mode='w+', delete=False) as fp: fp.write(jcl) fp.flush() @@ -94,29 +96,24 @@ def _create_dfhrmutl_jcl(location, sdfhload, cmd=""): qualified_file_path = fp.name return qualified_file_path -def _validate_line_length(line, name): + +def _validate_line_length(line, name, parameter): """ Validates that the JCL line does not exceed MAX_LINE_LENGTH. Raises ValueError if validation fails. """ if len(line) > MAX_LINE_LENGTH: - raise ValueError(f"{name} line exceeds {MAX_LINE_LENGTH} characters: {len(line)}") + raise ValueError(f"Value supplied for {parameter} ({name}) is {len(line) - MAX_LINE_LENGTH} characters too long") return True -def _validate_name_params(param): - if any(len(part) > MAX_NAME_LENGTH for part in param.split('.')): - raise ValueError(f"One or more parts of {param} exceeds MAX_NAME_LENGTH:{MAX_NAME_LENGTH}") - return True def _run_dfhrmutl( location, # type: str sdfhload, # type: str cmd="" # type: str ): - # type: (...) -> tuple[list[dict[str, str| int]], tuple[str | None, str | None]] | list[dict[str, str| int]] - _validate_name_params(location) - _validate_name_params(sdfhload) - + # type: (...) -> tuple[list[dict[str, str| int]], tuple[str | None, str | None]] | list[dict[str, str| int]] + qualified_file_path = _create_dfhrmutl_jcl( location, sdfhload, @@ -126,11 +123,11 @@ def _run_dfhrmutl( try: for x in range(MVS_CMD_RETRY_ATTEMPTS): dfhrmutl_response, jcl_executions = _execute_dfhrmutl(qualified_file_path) - dfhrmutl_rc = dfhrmutl_response.get("ret_code").get("code") + dfhrmutl_rc = dfhrmutl_response["ret_code"].get("code") allContent = [] for ddname in dfhrmutl_response.get("ddnames"): - allContent += ddname.get("content") + allContent += ddname.get("content") stdout_raw = "".join(allContent) executions.append(jcl_executions) @@ -141,8 +138,8 @@ def _run_dfhrmutl( x + 1), rc=dfhrmutl_rc, stdout=stdout_raw, - stderr=dfhrmutl_response.get("ret_code").get("msg_txt", ""))) - + stderr=dfhrmutl_response["ret_code"].get("msg_txt", ""))) + if dfhrmutl_rc not in (0, 16): raise MVSExecutionException( "DFHRMUTL failed with RC {0}".format( @@ -171,7 +168,7 @@ def _run_dfhrmutl( if cmd != "": return executions finally: - os.remove(qualified_file_path) + remove(qualified_file_path) return executions, _get_catalog_records(stdout_raw) @@ -179,8 +176,8 @@ def _execute_dfhrmutl(rmutl_jcl_path, job_name="DFHRMUTL"): executions = _submit_jcl(rmutl_jcl_path, job_name) job_id = executions[0].get("stdout").strip() - #Give RMUTL a second to run - sleep(1) + # Give RMUTL a second to run + sleep(JOB_SUBMIT_WAIT_TIME) job, job_executions = _get_job_output(job_id, job_name) executions.append(job_executions) @@ -209,6 +206,7 @@ def _get_idcams_cmd_gcd(dataset): # type: (dict) -> dict return defaults +# IDCAMS Consts RECORD_COUNT_DEFAULT = 4089 RECORD_SIZE_DEFAULT = 32760 CONTROL_INTERVAL_SIZE_DEFAULT = 32768 @@ -217,5 +215,7 @@ def _get_idcams_cmd_gcd(dataset): # type: (dict) -> dict CI_PERCENT = 10 CA_PERCENT = 10 SHARE_CROSSREGION = 2 + +# RMUTL Consts MAX_LINE_LENGTH = 72 -MAX_NAME_LENGTH = 8 +JOB_SUBMIT_WAIT_TIME = 1 diff --git a/tests/sanity/ignore-2.17.txt b/tests/sanity/ignore-2.17.txt new file mode 100644 index 00000000..6550864b --- /dev/null +++ b/tests/sanity/ignore-2.17.txt @@ -0,0 +1,15 @@ +plugins/modules/cmci_get.py validate-modules:missing-gplv3-license # Licence is Apache-2.0 +plugins/modules/cmci_action.py validate-modules:missing-gplv3-license # Licence is Apache-2.0 +plugins/modules/cmci_create.py validate-modules:missing-gplv3-license # Licence is Apache-2.0 +plugins/modules/cmci_delete.py validate-modules:missing-gplv3-license # Licence is Apache-2.0 +plugins/modules/cmci_update.py validate-modules:missing-gplv3-license # Licence is Apache-2.0 +plugins/modules/global_catalog.py validate-modules:missing-gplv3-license # Licence is Apache-2.0 +plugins/modules/local_catalog.py validate-modules:missing-gplv3-license # Licence is Apache-2.0 +plugins/modules/local_request_queue.py validate-modules:missing-gplv3-license # Licence is Apache-2.0 +plugins/modules/td_intrapartition.py validate-modules:missing-gplv3-license # Licence is Apache-2.0 +plugins/modules/aux_temp_storage.py validate-modules:missing-gplv3-license # Licence is Apache-2.0 +plugins/modules/aux_trace.py validate-modules:missing-gplv3-license # Licence is Apache-2.0 +plugins/modules/csd.py validate-modules:missing-gplv3-license # Licence is Apache-2.0 +plugins/modules/transaction_dump.py validate-modules:missing-gplv3-license # Licence is Apache-2.0 +plugins/modules/region_jcl.py validate-modules:missing-gplv3-license # Licence is Apache-2.0 +plugins/modules/stop_region.py validate-modules:missing-gplv3-license # Licence is Apache-2.0 diff --git a/tests/unit/helpers/data_set_helper.py b/tests/unit/helpers/data_set_helper.py index 6c14864c..1b70ae2e 100644 --- a/tests/unit/helpers/data_set_helper.py +++ b/tests/unit/helpers/data_set_helper.py @@ -419,22 +419,43 @@ def CSDUP_add_group_stdout(data_set_name): DFH5109 I END OF DFHCSDUP UTILITY JOB. HIGHEST RETURN CODE WAS: 0 """.format(data_set_name) + +def get_rmutl_executions(): + job = get_sample_job_output() + executions = [ + _execution( + name="Submit JCL job for {0}".format(job["job_id"]), + rc=0, + stdout="", + stderr="" + ), + get_job_output_execution() + ] + + for dd in job.get("ddnames"): + executions.append(get_job_dd_output_execution(ddname=dd["content"], job_id=job["job_id"])) + + return executions + + def get_job_output_execution(rc=0): job = get_sample_job_output() return _execution( name="Get job output for {0}".format(job["job_id"]), rc=rc, - stdout=job.get("ret_code").get("msg"), - stderr=job.get("ret_code").get("msg_txt") + stdout=job["ret_code"]["msg"], + stderr=job["ret_code"]["msg_txt"] ) -def _get_job_dd_output(ddname, job_id): + +def get_job_dd_output(ddname, job_id): return ( - _get_job_dd_output_execution(rc=0, ddname=ddname, job_id=job_id), + get_job_dd_output_execution(rc=0, ddname=ddname, job_id=job_id), RMUTL_stdout("AUTOINIT", job_id) ) -def _get_job_dd_output_execution(rc = 0, ddname="", job_id=""): + +def get_job_dd_output_execution(rc=0, ddname="", job_id=""): return _execution( name=JOB_DD_return_name(ddname, job_id), rc=rc, @@ -442,8 +463,10 @@ def _get_job_dd_output_execution(rc = 0, ddname="", job_id=""): stderr="CC" ) + def JOB_DD_return_name(ddname, job_id): - return "Get job dd {0} output for {1}".format(ddname, job_id) + return f"Get job DD {ddname} output for {job_id}" + def get_sample_job_output(content="", rc=0, err="CC"): return { @@ -453,7 +476,7 @@ def get_sample_job_output(content="", rc=0, err="CC"): { "byte_count": 0, "content": [ - "{0}".format(content) + content ], "ddname": "JESMSGLG", "id": "?", @@ -510,10 +533,11 @@ def get_sample_job_output(content="", rc=0, err="CC"): "system": "" } -def _get_sample_job_output_with_content(): + +def get_sample_job_output_with_content(): job = get_sample_job_output() for dd in job.get("ddnames"): - dd["content"] = RMUTL_stdout("AUTOINIT", job.get("job_id")) + dd["content"] = RMUTL_stdout("AUTOINIT", job["job_id"]) return job diff --git a/tests/unit/module_utils/test_dataset_utils.py b/tests/unit/module_utils/test_dataset_utils.py index bfbc42c4..ca319761 100644 --- a/tests/unit/module_utils/test_dataset_utils.py +++ b/tests/unit/module_utils/test_dataset_utils.py @@ -20,9 +20,9 @@ get_job_output_execution as JOB_EXECUTION, JOB_DD_return_name, RMUTL_stdout, - _get_job_dd_output, - _get_job_dd_output_execution, - _get_sample_job_output_with_content + get_job_dd_output, + get_job_dd_output_execution, + get_sample_job_output_with_content ) from ansible_collections.ibm.ibm_zos_core.plugins.module_utils.dd_statement import DatasetDefinition @@ -709,7 +709,8 @@ def test__write_jcl_to_data_set_fail(): assert e.value.message == "Failed to copy JCL content to data set" assert e.value.executions == expected_executions -def test_data_set_utils_submit_jcl(): + +def test__submit_jcl(): jcl_uss_path = "jcl/uss/path" job_name = "Job_Name" rc = 0 @@ -718,16 +719,17 @@ def test_data_set_utils_submit_jcl(): data_set_utils._execute_command = MagicMock(return_value=(rc, stdout, stderr)) expected_executions = [{ - "name": "Submit jcl job {0} for {1}".format(jcl_uss_path, job_name), + "name": "Submit JCL job for {0}".format(job_name), "rc": 0, "stdout": "", "stderr": "" }] - executions= data_set_utils._submit_jcl(jcl_uss_path, job_name) + executions = data_set_utils._submit_jcl(jcl_uss_path, job_name) assert expected_executions == executions -def test_data_set_utils_submit_jcl_failed(): + +def test__submit_jcl_failed(): jcl_uss_path = "jcl/uss/path" job_name = "Job_Name" rc = 16 @@ -736,23 +738,22 @@ def test_data_set_utils_submit_jcl_failed(): data_set_utils._execute_command = MagicMock(return_value=(rc, stdout, stderr)) expected_executions = [{ - "name": "Submit jcl job {0} for {1}".format(jcl_uss_path, job_name), + "name": "Submit JCL job for {0}".format(job_name), "rc": 16, "stdout": "CC", "stderr": "CC" }] with pytest.raises(MVSExecutionException) as e: data_set_utils._submit_jcl(jcl_uss_path, job_name) - assert e.value.message == "RC {0} when submitting jcl from {1}".format(rc, jcl_uss_path) - assert e.value.executions == expected_executions - + assert e.value.message == "RC {0} when submitting JCL from {1}".format(rc, jcl_uss_path) + assert e.value.executions == expected_executions -def test_data_set_utils_get_job_output(): +def test__get_job_output(): job_id = "JOB12345" - expected_execution=[ + expected_execution = [ JOB_EXECUTION(), - _execution( + _execution( name=JOB_DD_return_name("JESMSGLG", job_id), rc=0, stdout=RMUTL_stdout("AUTOINIT", job_id), @@ -777,78 +778,74 @@ def test_data_set_utils_get_job_output(): stderr="CC", ) ] - expected_result = _get_sample_job_output_with_content() - data_set_utils.job_output = MagicMock(return_value=[JOB_OUTPUT()]) - job_id= JOB_OUTPUT().get("job_id") + expected_result = get_sample_job_output_with_content() + data_set_utils.job_output = MagicMock(return_value=[JOB_OUTPUT()]) + job_id = JOB_OUTPUT().get("job_id") data_set_utils._get_job_dd = MagicMock(side_effect=[ - _get_job_dd_output("JESMSGLG", job_id), - _get_job_dd_output("JESJCL", job_id), - _get_job_dd_output("JESSYSMSG", job_id), - _get_job_dd_output("SYSPRINT", job_id) + get_job_dd_output("JESMSGLG", job_id), + get_job_dd_output("JESJCL", job_id), + get_job_dd_output("JESSYSMSG", job_id), + get_job_dd_output("SYSPRINT", job_id) ]) result, executions = data_set_utils._get_job_output(job_id=job_id, job_name="DFHRMUTL") assert result == expected_result assert executions == expected_execution -def test_data_set_utils_get_job_output_multiple_jobs_failure(): + +def test__get_job_output_multiple_jobs_failure(): job_id = JOB_OUTPUT()["job_id"] job_name = JOB_OUTPUT()["job_name"] - + mock_jobs = [ JOB_OUTPUT(), {"ret_code": {"code": 1, "msg": "Error", "msg_txt": "Job failed"}} ] expected_executions = [] - data_set_utils.job_output = MagicMock(return_value = mock_jobs) - - with pytest.raises(MVSExecutionException) as e: - data_set_utils._get_job_output(job_id, job_name) - - assert e.value.executions == expected_executions - assert f"Query for {job_name} job submitted under Job ID {job_id} failed" in e.value.message - -def test_data_set_utils_get_job_output_get_dd_failure(): - job_id = JOB_OUTPUT()["job_id"] - job_name = JOB_OUTPUT()["job_name"] - - expected_executions = [JOB_EXECUTION()] - expected_exception = TypeError("Failed to get DD content") - data_set_utils.job_output = MagicMock(return_value=[JOB_OUTPUT()]) - data_set_utils._get_job_dd = MagicMock(return_value=expected_exception) - + expected_exception = MVSExecutionException( + "Query for job status for {0} with job ID {1} returned more than one result. Jobs returned: ".format( + job_name, + job_id + ), expected_executions + ) + data_set_utils.job_output = MagicMock(return_value=mock_jobs) + with pytest.raises(MVSExecutionException) as e: data_set_utils._get_job_output(job_id, job_name) - + assert e.value.executions == expected_executions - assert f"Could not get all job DDs for {job_name}. An exception occured: " in str(e.value.message) + assert expected_exception.message in e.value.message + -def test_data_set_utils_get_job_dd(): +def test__get_job_dd(): job_id = "JOB12345" dd_name = "DD Name" rc = 0 stdout = RMUTL_stdout("AUTOINIT", job_id) stderr = "CC" - mock_dd_execution = [_get_job_dd_output_execution(rc, dd_name, job_id)] + mock_dd_execution = [get_job_dd_output_execution(rc, dd_name, job_id)] data_set_utils._execute_command = MagicMock(return_value=(rc, stdout, stderr)) result_execution, result = data_set_utils._get_job_dd(job_id, dd_name) assert result == stdout assert result_execution == mock_dd_execution -def test_data_set_utils_get_job_dd_failure(): + +def test__get_job_dd_failure(): job_id = "JOB12345" dd_name = "DD Name" rc = 8 stdout = RMUTL_stdout("AUTOINIT", job_id) stderr = "CC" - mock_dd_execution = [_get_job_dd_output_execution(rc, dd_name, job_id)] + expected_message = f"RC 8 when getting job output for DD Name from {job_id}" + + mock_dd_execution = [get_job_dd_output_execution(rc, dd_name, job_id)] data_set_utils._execute_command = MagicMock(return_value=(rc, stdout, stderr)) - + with pytest.raises(Exception) as e: data_set_utils._get_job_dd(job_id, dd_name) assert e.type == MVSExecutionException - assert f"RC 8 when getting job output for DD Name from {job_id}" in str(e.value) + assert expected_message in str(e.value) assert e.value.executions == mock_dd_execution diff --git a/tests/unit/module_utils/test_global_catalog.py b/tests/unit/module_utils/test_global_catalog.py index 30a40817..bab1388b 100644 --- a/tests/unit/module_utils/test_global_catalog.py +++ b/tests/unit/module_utils/test_global_catalog.py @@ -11,7 +11,8 @@ RMUTL_get_run_name, RMUTL_stdout, RMUTL_update_run_name, - get_sample_job_output as JOB_OUTPUT + get_sample_job_output as JOB_OUTPUT, + get_rmutl_executions as RMUTL_EXECUTIONS ) __metaclass__ = type from ansible_collections.ibm.ibm_zos_cics.plugins.module_utils import _data_set_utils as data_set_utils @@ -21,15 +22,12 @@ _execution, ) from ansible_collections.ibm.ibm_zos_cics.plugins.modules.global_catalog import SPACE_PRIMARY_DEFAULT, SPACE_SECONDARY_DEFAULT -from ansible_collections.ibm.ibm_zos_core.plugins.module_utils.zos_mvs_raw import ( - MVSCmdResponse, -) import pytest import sys -import tempfile +from os import remove try: - from unittest.mock import MagicMock, patch + from unittest.mock import MagicMock except ImportError: from mock import MagicMock @@ -186,62 +184,61 @@ def test_get_idcams_cmd_multiple_volumes(): ) -def test_global_catalog_get_records_autoinit_unknown(): +def test_get_records_autoinit_unknown(): stdout = RMUTL_stdout("AUTOINIT", "UNKNOWN") resp = global_catalog._get_catalog_records(stdout=stdout) assert resp == ("AUTOINIT", "UNKNOWN") -def test_global_catalog_get_records_autoasis_emergency(): +def test_get_records_autoasis_emergency(): stdout = RMUTL_stdout("AUTOASIS", "EMERGENCY") resp = global_catalog._get_catalog_records(stdout=stdout) assert resp == ("AUTOASIS", "EMERGENCY") -def test_global_catalog_get_records_autocold_emergency(): +def test_get_records_autocold_emergency(): stdout = RMUTL_stdout("AUTOCOLD", "EMERGENCY") resp = global_catalog._get_catalog_records(stdout=stdout) assert resp == ("AUTOCOLD", "EMERGENCY") -def test_global_catalog_create_dfhrmutl_jcl(): + +def test_create_dfhrmutl_jcl(): location = "DATA.SET" sdfhload = "SDFH.LOAD" cmd = "HI" - mock_file = MagicMock() - mock_file.name = '/mocked/path/to/tempfile' - mock_file.__enter__.return_value = mock_file - with patch('tempfile.NamedTemporaryFile', return_value=mock_file) as mock_tempfile: - result = global_catalog._create_dfhrmutl_jcl(location, sdfhload, cmd) + result = global_catalog._create_dfhrmutl_jcl(location, sdfhload, cmd) + + # Check that the file create has the content we expect in it + with open(result, 'r') as file: + content = file.read() + assert location in content + assert sdfhload in content + assert cmd in content + + # Remove the file once we're finished with it + remove(result) - mock_tempfile.assert_called_once_with(mode='w+', delete=False) - assert result == '/mocked/path/to/tempfile' -def test_global_catalog_validate_line_length(): - line = "//STEPLIB DD DSNAME=CTS560.CICS730.SDFHLOAD,DISP=SHR" +def test_validate_line_length(): + sdfhload = "CTS560.CICS730.SDFHLOAD" + line = f"//STEPLIB DD DSNAME={sdfhload},DISP=SHR" name = "SDFHLOAD" - result = global_catalog._validate_line_length(line, name) + result = global_catalog._validate_line_length(line, sdfhload, name) assert result is True -def test_global_catalog_validate_line_length_failed(): - line = "//STEPLIB DD DSNAME=CTS560.CICS730.SDFHLOAD,DISP=SHR this is inavlid line with more the 72 chars" + +def test_validate_line_length_failed(): + sdfhload = "CTS560.CICS730.SDFHLOAD" + line = f"//STEPLIB DD DSNAME={sdfhload},DISP=SHR this is invalid line with more the 72 chars" name = "SDFHLOAD" with pytest.raises(ValueError): - global_catalog._validate_line_length(line, name) - -def test_global_catalog_validate_name_params(): - name = "CTS560.CICS730.SDFHLOAD" - result = global_catalog._validate_name_params(name) - assert result is True + global_catalog._validate_line_length(line, sdfhload, name) -def test_global_catalog_validate_name_params_failed(): - name = "CTS560.CICS730.SDFHLOAD1" - with pytest.raises(ValueError): - global_catalog._validate_name_params(name) -def test_global_catalog_run_rmutl_with_cmd(): +def test_run_rmutl_with_cmd(): executions = [ - [], + RMUTL_EXECUTIONS(), _execution( name=RMUTL_update_run_name(1), rc=0, @@ -253,7 +250,7 @@ def test_global_catalog_run_rmutl_with_cmd(): global_catalog._execute_dfhrmutl = MagicMock( return_value=( JOB_OUTPUT(), - [] + RMUTL_EXECUTIONS() )) result = global_catalog._run_dfhrmutl( @@ -263,16 +260,16 @@ def test_global_catalog_run_rmutl_with_cmd(): assert result == executions -def test_global_catalog_run_rmutl_with_cmd_and_failure(): +def test_run_rmutl_with_cmd_and_failure(): executions = [ - [], + RMUTL_EXECUTIONS(), _execution( name=RMUTL_update_run_name(1), rc=16, stdout=" ABC \n REASON: X'A8'", stderr="CC", ), - [], + RMUTL_EXECUTIONS(), _execution( name=RMUTL_update_run_name(2), rc=0, @@ -282,8 +279,8 @@ def test_global_catalog_run_rmutl_with_cmd_and_failure(): ] global_catalog._execute_dfhrmutl = MagicMock( side_effect=[ - (JOB_OUTPUT(" ABC \n REASON: X'A8'", 16), []), - (JOB_OUTPUT(), []) + (JOB_OUTPUT(" ABC \n REASON: X'A8'", 16), RMUTL_EXECUTIONS()), + (JOB_OUTPUT(), RMUTL_EXECUTIONS()) ]) result = global_catalog._run_dfhrmutl( location="DATA.SET", sdfhload="SDFH.LOAD", cmd="HI" @@ -292,17 +289,17 @@ def test_global_catalog_run_rmutl_with_cmd_and_failure(): assert result == executions -def test_global_catalog_run_rmutl_no_cmd(): +def test_run_rmutl_no_cmd(): rmutl_stdout = RMUTL_stdout("AUTOASIS", "EMERGENCY") global_catalog._execute_dfhrmutl = MagicMock( return_value=( JOB_OUTPUT(rmutl_stdout), - [] + RMUTL_EXECUTIONS() )) expected_executions = [ - [], + RMUTL_EXECUTIONS(), _execution( name=RMUTL_get_run_name(1), rc=0, @@ -319,18 +316,18 @@ def test_global_catalog_run_rmutl_no_cmd(): assert actual_details == expected_details -def test_global_catalog_run_rmutl_no_cmd_with_failure(): +def test_run_rmutl_no_cmd_with_failure(): rmutl_stdout = RMUTL_stdout("AUTOASIS", "EMERGENCY") expected_executions = [ - [], + RMUTL_EXECUTIONS(), _execution( name=RMUTL_get_run_name(1), rc=16, stdout=" ABC \n REASON: X'A8'", stderr="CC", ), - [], + RMUTL_EXECUTIONS(), _execution( name=RMUTL_get_run_name(2), rc=0, @@ -341,8 +338,8 @@ def test_global_catalog_run_rmutl_no_cmd_with_failure(): expected_details = ("AUTOASIS", "EMERGENCY") global_catalog._execute_dfhrmutl = MagicMock( side_effect=[ - (JOB_OUTPUT(" ABC \n REASON: X'A8'", 16), []), - (JOB_OUTPUT(rmutl_stdout), []) + (JOB_OUTPUT(" ABC \n REASON: X'A8'", 16), RMUTL_EXECUTIONS()), + (JOB_OUTPUT(rmutl_stdout), RMUTL_EXECUTIONS()) ] ) actual_executions, actual_details = global_catalog._run_dfhrmutl( @@ -353,46 +350,46 @@ def test_global_catalog_run_rmutl_no_cmd_with_failure(): assert actual_details == expected_details -def test_global_catalog_run_rmutl_no_cmd_many_failures(): +def test_run_rmutl_no_cmd_many_failures(): rmutl_stdout = RMUTL_stdout("AUTOINIT", "UNKNOWN") expected_executions = [ - [], + RMUTL_EXECUTIONS(), _execution( name=RMUTL_get_run_name(1), rc=16, stdout=" ABC \n REASON: X'A8'", stderr="CC", ), - [], + RMUTL_EXECUTIONS(), _execution( name=RMUTL_get_run_name(2), rc=16, stdout="\n\n\n REASON: X'A8'", stderr="CC", ), - [], + RMUTL_EXECUTIONS(), _execution( name=RMUTL_get_run_name(3), rc=16, stdout="REASON:X'A8'", stderr="CC", ), - [], + RMUTL_EXECUTIONS(), _execution( name=RMUTL_get_run_name(4), rc=16, stdout="\n REASON:X'A8'", stderr="CC", ), - [], + RMUTL_EXECUTIONS(), _execution( name=RMUTL_get_run_name(5), rc=16, stdout=" ABC \n REASON: X 'A8'", stderr="CC", ), - [], + RMUTL_EXECUTIONS(), _execution( name=RMUTL_get_run_name(6), rc=0, @@ -403,15 +400,15 @@ def test_global_catalog_run_rmutl_no_cmd_many_failures(): expected_details = ("AUTOINIT", "UNKNOWN") global_catalog._execute_dfhrmutl = MagicMock( side_effect=[ - (JOB_OUTPUT(" ABC \n REASON: X'A8'", 16), []), - (JOB_OUTPUT("\n\n\n REASON: X'A8'", 16), []), - (JOB_OUTPUT("REASON:X'A8'", 16), []), - (JOB_OUTPUT("\n REASON:X'A8'", 16), []), - (JOB_OUTPUT(" ABC \n REASON: X 'A8'", 16), []), - (JOB_OUTPUT(rmutl_stdout), []) + (JOB_OUTPUT(" ABC \n REASON: X'A8'", 16), RMUTL_EXECUTIONS()), + (JOB_OUTPUT("\n\n\n REASON: X'A8'", 16), RMUTL_EXECUTIONS()), + (JOB_OUTPUT("REASON:X'A8'", 16), RMUTL_EXECUTIONS()), + (JOB_OUTPUT("\n REASON:X'A8'", 16), RMUTL_EXECUTIONS()), + (JOB_OUTPUT(" ABC \n REASON: X 'A8'", 16), RMUTL_EXECUTIONS()), + (JOB_OUTPUT(rmutl_stdout), RMUTL_EXECUTIONS()) ] ) - global_catalog._get_rmutl_dds = MagicMock(return_value=[]) + global_catalog._get_rmutl_dds = MagicMock(return_value=RMUTL_EXECUTIONS()) actual_executions, actual_details = global_catalog._run_dfhrmutl( location="DATA.SET", sdfhload="SDFH.LOAD" ) @@ -420,13 +417,13 @@ def test_global_catalog_run_rmutl_no_cmd_many_failures(): assert actual_details == expected_details -def test_global_catalog_run_rmutl_rc16_error(): +def test_run_rmutl_rc16_error(): global_catalog._execute_dfhrmutl = MagicMock( - return_value=(JOB_OUTPUT(" ABC \n REASON: X'12'", 16), []) + return_value=(JOB_OUTPUT(" ABC \n REASON: X'12'", 16), RMUTL_EXECUTIONS()) ) expected_executions = [ - [], + RMUTL_EXECUTIONS(), _execution( name=RMUTL_update_run_name(1), rc=16, @@ -443,19 +440,19 @@ def test_global_catalog_run_rmutl_rc16_error(): assert e.executions == expected_executions -def test_global_catalog_run_rmutl_many_rc16_error(): +def test_run_rmutl_many_rc16_error(): global_catalog._execute_dfhrmutl = MagicMock( side_effect=[ - (JOB_OUTPUT(" ABC \n REASON: X'A8'", 16), []), - (JOB_OUTPUT("\n\n\n REASON: X'A8'", 16), []), - (JOB_OUTPUT("REASON:X'B2'", 16), []) + (JOB_OUTPUT(" ABC \n REASON: X'A8'", 16), RMUTL_EXECUTIONS()), + (JOB_OUTPUT("\n\n\n REASON: X'A8'", 16), RMUTL_EXECUTIONS()), + (JOB_OUTPUT("REASON:X'B2'", 16), RMUTL_EXECUTIONS()) ] ) expected_executions = [ - [], _execution(name=RMUTL_update_run_name(1), rc=16, stdout=" ABC \n REASON: X'A8'", stderr="CC"), - [], _execution(name=RMUTL_update_run_name(2), rc=16, stdout="\n\n\n REASON: X'A8'", stderr="CC"), - [], _execution(name=RMUTL_update_run_name(3), rc=16, stdout="REASON:X'B2'", stderr="CC"), + RMUTL_EXECUTIONS(), _execution(name=RMUTL_update_run_name(1), rc=16, stdout=" ABC \n REASON: X'A8'", stderr="CC"), + RMUTL_EXECUTIONS(), _execution(name=RMUTL_update_run_name(2), rc=16, stdout="\n\n\n REASON: X'A8'", stderr="CC"), + RMUTL_EXECUTIONS(), _execution(name=RMUTL_update_run_name(3), rc=16, stdout="REASON:X'B2'", stderr="CC"), ] with pytest.raises(MVSExecutionException) as e: @@ -466,19 +463,19 @@ def test_global_catalog_run_rmutl_many_rc16_error(): assert e.executions == expected_executions -def test_global_catalog_run_rmutl_many_rc_error(): +def test_run_rmutl_many_rc_error(): global_catalog._execute_dfhrmutl = MagicMock( side_effect=[ - (JOB_OUTPUT(" ABC \n REASON: X'A8'", 16), []), - (JOB_OUTPUT("\n\n\n REASON: X'A8'", 16), []), - (JOB_OUTPUT("REASON:X'A8'", 15), []) + (JOB_OUTPUT(" ABC \n REASON: X'A8'", 16), RMUTL_EXECUTIONS()), + (JOB_OUTPUT("\n\n\n REASON: X'A8'", 16), RMUTL_EXECUTIONS()), + (JOB_OUTPUT("REASON:X'A8'", 15), RMUTL_EXECUTIONS()) ] ) expected_executions = [ - [], _execution(name=RMUTL_update_run_name(1), rc=16, stdout=" ABC \n REASON: X'A8'", stderr="CC"), - [], _execution(name=RMUTL_update_run_name(2), rc=16, stdout="\n\n\n REASON: X'A8'", stderr="CC"), - [], _execution(name=RMUTL_update_run_name(3), rc=15, stdout="REASON:X'A8'", stderr="CC") + RMUTL_EXECUTIONS(), _execution(name=RMUTL_update_run_name(1), rc=16, stdout=" ABC \n REASON: X'A8'", stderr="CC"), + RMUTL_EXECUTIONS(), _execution(name=RMUTL_update_run_name(2), rc=16, stdout="\n\n\n REASON: X'A8'", stderr="CC"), + RMUTL_EXECUTIONS(), _execution(name=RMUTL_update_run_name(3), rc=15, stdout="REASON:X'A8'", stderr="CC") ] with pytest.raises(MVSExecutionException) as e: @@ -489,11 +486,11 @@ def test_global_catalog_run_rmutl_many_rc_error(): assert e.executions == expected_executions -def test_global_catalog_run_rmutl_rc_not_0(): +def test_run_rmutl_rc_not_0(): global_catalog._execute_dfhrmutl = MagicMock( - return_value=(JOB_OUTPUT(rc=123), []) + return_value=(JOB_OUTPUT(rc=123), RMUTL_EXECUTIONS()) ) - expected_executions = [[], _execution(name=RMUTL_update_run_name(1), rc=123, stdout="", stderr="CC")] + expected_executions = [RMUTL_EXECUTIONS(), _execution(name=RMUTL_update_run_name(1), rc=123, stdout="", stderr="CC")] with pytest.raises(MVSExecutionException) as e: global_catalog._run_dfhrmutl( diff --git a/tests/unit/modules/test_global_catalog.py b/tests/unit/modules/test_global_catalog.py index 846eb115..49135fea 100644 --- a/tests/unit/modules/test_global_catalog.py +++ b/tests/unit/modules/test_global_catalog.py @@ -23,7 +23,8 @@ RMUTL_stdout, RMUTL_update_run_name, set_module_args, - get_sample_job_output as JOB_OUTPUT + get_sample_job_output as JOB_OUTPUT, + get_rmutl_executions as RMUTL_EXECUTIONS ) from ansible_collections.ibm.ibm_zos_cics.plugins.modules import global_catalog from ansible_collections.ibm.ibm_zos_cics.plugins.module_utils import _icetool as icetool @@ -85,7 +86,7 @@ def test_create_an_intial_global_catalog(): ] ) global_catalog_utils._execute_dfhrmutl = MagicMock( - return_value=(JOB_OUTPUT(RMUTL_stdout("AUTOINIT", "UNKNOWN"), err=RMUTL_stderr(NAME)), []) + return_value=(JOB_OUTPUT(RMUTL_stdout("AUTOINIT", "UNKNOWN"), err=RMUTL_stderr(NAME)), RMUTL_EXECUTIONS()) ) gcd_module.main() @@ -103,7 +104,7 @@ def test_create_an_intial_global_catalog(): stdout=IDCAMS_create_stdout(NAME), stderr="", ), - [], + RMUTL_EXECUTIONS(), _execution( name=RMUTL_update_run_name(1), rc=0, @@ -116,7 +117,7 @@ def test_create_an_intial_global_catalog(): stdout=LISTDS_data_set(NAME, "VSAM"), stderr="", ), - [], + RMUTL_EXECUTIONS(), _execution( name=RMUTL_get_run_name(1), rc=0, @@ -167,7 +168,7 @@ def test_delete_an_existing_global_catalog(): ) ) global_catalog_utils._execute_dfhrmutl = MagicMock( - return_value=(JOB_OUTPUT(RMUTL_stdout("AUTOINIT", "UNKNOWN"), err=RMUTL_stderr(NAME)), []) + return_value=(JOB_OUTPUT(RMUTL_stdout("AUTOINIT", "UNKNOWN"), err=RMUTL_stderr(NAME)), RMUTL_EXECUTIONS()) ) gcd_module.main() @@ -179,7 +180,7 @@ def test_delete_an_existing_global_catalog(): stdout=LISTDS_data_set(NAME, "VSAM"), stderr="", ), - [], + RMUTL_EXECUTIONS(), _execution( name=RMUTL_get_run_name(1), rc=0, @@ -276,7 +277,7 @@ def test_warm_start_a_global_catalog(): ) ) global_catalog_utils._execute_dfhrmutl = MagicMock( - return_value=(JOB_OUTPUT(RMUTL_stdout("AUTOASIS", "UNKNOWN"), err=RMUTL_stderr(NAME)), []) + return_value=(JOB_OUTPUT(RMUTL_stdout("AUTOASIS", "UNKNOWN"), err=RMUTL_stderr(NAME)), RMUTL_EXECUTIONS()) ) icetool._execute_icetool = MagicMock( return_value=MVSCmdResponse( @@ -295,7 +296,7 @@ def test_warm_start_a_global_catalog(): stdout=LISTDS_data_set(NAME, "VSAM"), stderr="" ), - [], + RMUTL_EXECUTIONS(), _execution( name=RMUTL_get_run_name(1), rc=0, @@ -308,7 +309,7 @@ def test_warm_start_a_global_catalog(): stdout=ICETOOL_stdout(52), stderr=ICETOOL_stderr() ), - [], + RMUTL_EXECUTIONS(), _execution( name=RMUTL_update_run_name(1), rc=0, @@ -321,7 +322,7 @@ def test_warm_start_a_global_catalog(): stdout=LISTDS_data_set(NAME, "VSAM"), stderr="" ), - [], + RMUTL_EXECUTIONS(), _execution( name=RMUTL_get_run_name(1), rc=0, @@ -362,7 +363,7 @@ def test_error_warm_start_a_unused_global_catalog(): ) ) global_catalog_utils._execute_dfhrmutl = MagicMock( - return_value=(JOB_OUTPUT(RMUTL_stdout("AUTOINIT", "UNKNOWN"), err=RMUTL_stderr(NAME)), []) + return_value=(JOB_OUTPUT(RMUTL_stdout("AUTOINIT", "UNKNOWN"), err=RMUTL_stderr(NAME)), RMUTL_EXECUTIONS()) ) icetool._execute_icetool = MagicMock( return_value=MVSCmdResponse( @@ -381,7 +382,7 @@ def test_error_warm_start_a_unused_global_catalog(): stdout=LISTDS_data_set(NAME, "VSAM"), stderr="" ), - [], + RMUTL_EXECUTIONS(), _execution( name=RMUTL_get_run_name(1), rc=0, @@ -394,7 +395,7 @@ def test_error_warm_start_a_unused_global_catalog(): stdout=ICETOOL_stdout(0), stderr=ICETOOL_stderr() ), - [], + RMUTL_EXECUTIONS(), _execution( name=RMUTL_update_run_name(1), rc=0, @@ -407,7 +408,7 @@ def test_error_warm_start_a_unused_global_catalog(): stdout=LISTDS_data_set(NAME, "VSAM"), stderr="" ), - [], + RMUTL_EXECUTIONS(), _execution( name=RMUTL_get_run_name(1), rc=0, @@ -444,7 +445,7 @@ def test_error_warm_start_a_non_existent_global_catalog(): return_value=MVSCmdResponse(8, LISTDS_data_set_doesnt_exist(NAME), "") ) global_catalog_utils._execute_dfhrmutl = MagicMock( - return_value=(JOB_OUTPUT(RMUTL_stdout("AUTOINIT", "UNKNOWN"), err=RMUTL_stderr(NAME)), []) + return_value=(JOB_OUTPUT(RMUTL_stdout("AUTOINIT", "UNKNOWN"), err=RMUTL_stderr(NAME)), RMUTL_EXECUTIONS()) ) gcd_module.main() @@ -456,7 +457,7 @@ def test_error_warm_start_a_non_existent_global_catalog(): stdout=LISTDS_data_set_doesnt_exist(NAME), stderr="" ), - [], + RMUTL_EXECUTIONS(), _execution( name=RMUTL_update_run_name(1), rc=0, @@ -499,7 +500,7 @@ def tests_cold_start_non_existent_catalog(): return_value=MVSCmdResponse(8, LISTDS_data_set_doesnt_exist(NAME), "") ) global_catalog_utils._execute_dfhrmutl = MagicMock( - return_value=(JOB_OUTPUT(RMUTL_stdout("AUTOCOLD", "UNKNOWN"), err=RMUTL_stderr(NAME)), []) + return_value=(JOB_OUTPUT(RMUTL_stdout("AUTOCOLD", "UNKNOWN"), err=RMUTL_stderr(NAME)), RMUTL_EXECUTIONS()) ) gcd_module.main() @@ -511,7 +512,7 @@ def tests_cold_start_non_existent_catalog(): stdout=LISTDS_data_set_doesnt_exist(NAME), stderr="" ), - [], + RMUTL_EXECUTIONS(), _execution( name=RMUTL_update_run_name(1), rc=0, @@ -554,7 +555,7 @@ def test_cold_start_unused_catalog(): return_value=MVSCmdResponse(0, LISTDS_data_set(NAME, "VSAM"), "") ) global_catalog_utils._execute_dfhrmutl = MagicMock( - return_value=(JOB_OUTPUT(RMUTL_stdout("AUTOINIT", "UNKNOWN"), err=RMUTL_stderr(NAME)), []) + return_value=(JOB_OUTPUT(RMUTL_stdout("AUTOINIT", "UNKNOWN"), err=RMUTL_stderr(NAME)), RMUTL_EXECUTIONS()) ) gcd_module.main() @@ -566,14 +567,14 @@ def test_cold_start_unused_catalog(): stdout=LISTDS_data_set(NAME, "VSAM"), stderr="", ), - [], + RMUTL_EXECUTIONS(), _execution( name=RMUTL_get_run_name(1), rc=0, stdout=RMUTL_stdout("AUTOINIT", "UNKNOWN"), stderr=RMUTL_stderr(NAME) ), - [], + RMUTL_EXECUTIONS(), _execution( name=RMUTL_update_run_name(1), rc=0, @@ -586,7 +587,7 @@ def test_cold_start_unused_catalog(): stdout=LISTDS_data_set(NAME, "VSAM"), stderr="", ), - [], + RMUTL_EXECUTIONS(), _execution( name=RMUTL_get_run_name(1), rc=0, @@ -623,7 +624,7 @@ def test_cold_start_global_catalog(): return_value=MVSCmdResponse(0, LISTDS_data_set(NAME, "VSAM"), "") ) global_catalog_utils._execute_dfhrmutl = MagicMock( - return_value=(JOB_OUTPUT(RMUTL_stdout("AUTOCOLD", "UNKNOWN"), err=RMUTL_stderr(NAME)), []) + return_value=(JOB_OUTPUT(RMUTL_stdout("AUTOCOLD", "UNKNOWN"), err=RMUTL_stderr(NAME)), RMUTL_EXECUTIONS()) ) gcd_module.main() @@ -635,14 +636,14 @@ def test_cold_start_global_catalog(): stdout=LISTDS_data_set(NAME, "VSAM"), stderr="" ), - [], + RMUTL_EXECUTIONS(), _execution( name=RMUTL_get_run_name(1), rc=0, stdout=RMUTL_stdout("AUTOCOLD", "UNKNOWN"), stderr=RMUTL_stderr(NAME) ), - [], + RMUTL_EXECUTIONS(), _execution( name=RMUTL_update_run_name(1), rc=0, @@ -655,7 +656,7 @@ def test_cold_start_global_catalog(): stdout=LISTDS_data_set(NAME, "VSAM"), stderr="" ), - [], + RMUTL_EXECUTIONS(), _execution( name=RMUTL_get_run_name(1), rc=0,