def execute_testcase(testcase_filepath, data_repository, tc_context, runtype,
                     tc_parallel, queue, auto_defects, suite, jiraproj,
                     tc_onError_action, iter_ts_sys):
    """ Executes the testcase (provided as a xml file)
            - Takes a testcase xml file as input and executes each command in the testcase.
            - Computes the testcase status based on the stepstatus and the impact value of the step
            - Handles step failures as per the default/specific onError action/value
            - Calls the function to report the testcase status

    :Arguments:
        1. testcase_filepath (string) = the full path of the testcase xml file
        2. execution_dir (string) = the full path of the directory under which the 
                                    testcase execution directory will be created
                                    (the results, logs for this testcase will be 
                                    stored in this testcase execution directory.)
    """

    tc_status = True
    tc_start_time = Utils.datetime_utils.get_current_timestamp()
    tc_timestamp = str(tc_start_time)
    print_info("[{0}] Testcase execution starts".format(tc_start_time))

    get_testcase_details(testcase_filepath, data_repository, jiraproj)

    # These lines are for creating testcase junit file
    from_ts = False
    if not 'wt_junit_object' in data_repository:
        # not from testsuite
        tc_junit_object = junit_class.Junit(
            filename=data_repository['wt_name'],
            timestamp=tc_timestamp,
            name="customProject_independant_testcase_execution",
            display="False")
        if "jobid" in data_repository:
            tc_junit_object.add_jobid(data_repository["jobid"])
            del data_repository["jobid"]
        tc_junit_object.create_testcase(
            location=data_repository['wt_filedir'],
            timestamp=tc_timestamp,
            ts_timestamp=tc_timestamp,
            name=data_repository['wt_name'],
            testcasefile_path=data_repository['wt_testcase_filepath'],
            display="False")
        junit_requirements(testcase_filepath, tc_junit_object, tc_timestamp)
        data_repository['wt_ts_timestamp'] = tc_timestamp
    else:
        tc_junit_object = data_repository['wt_junit_object']
        tc_junit_object.create_testcase(
            location="from testsuite",
            timestamp=tc_timestamp,
            ts_timestamp=data_repository['wt_ts_timestamp'],
            classname=data_repository['wt_suite_name'],
            name=data_repository['wt_name'],
            testcasefile_path=data_repository['wt_testcase_filepath'])
        from_ts = True
        junit_requirements(testcase_filepath, tc_junit_object,
                           data_repository['wt_ts_timestamp'])
    data_repository['wt_tc_timestamp'] = tc_timestamp
    data_type = data_repository['wt_data_type']

    # Adding resultsdir, logsdir, title as attributes to testcase_tag in the junit result file
    # Need to remove these after making resultsdir, logsdir as part of properties tag in testcase
    tc_junit_object.add_property(
        "resultsdir", os.path.dirname(data_repository['wt_resultsdir']), "tc",
        tc_timestamp)
    tc_junit_object.add_property(
        "logsdir", os.path.dirname(data_repository['wt_logsdir']), "tc",
        tc_timestamp)
    tc_junit_object.update_attr("title", data_repository['wt_title'], "tc",
                                tc_timestamp)
    data_repository['wt_junit_object'] = tc_junit_object

    data_repository['wt_junit_object'] = tc_junit_object
    print_testcase_details_to_console(testcase_filepath, data_repository)
    step_list = get_steps_list(testcase_filepath)

    tc_state = Utils.xml_Utils.getChildTextbyParentTag(testcase_filepath,
                                                       'Details', 'State')
    if tc_state is not False and tc_state is not None and \
       tc_state.upper() == "DRAFT":
        print_warning("Testcase is in 'Draft' state, it may have keywords "
                      "that have not been developed yet. Skipping the "
                      "testcase execution and it will be marked as 'ERROR'")
        tc_status = "ERROR"
    else:
        if data_type.upper() == 'CUSTOM' and \
         runtype.upper() == 'SEQUENTIAL_KEYWORDS':
            tc_status = execute_custom(data_type, runtype,
                                       custom_sequential_kw_driver,
                                       data_repository, step_list)
        elif data_type.upper() == 'CUSTOM' and \
                runtype.upper() == 'PARALLEL_KEYWORDS':
            tc_status = execute_custom(data_type, runtype,
                                       custom_parallel_kw_driver,
                                       data_repository, step_list)
        elif data_type.upper() == 'ITERATIVE' and \
                runtype.upper() == 'SEQUENTIAL_KEYWORDS':
            print_info("iterative sequential")
            system_list = get_system_list(data_repository['wt_datafile'],
                                          iter_req=True) \
                if iter_ts_sys is None else [iter_ts_sys]
            # print len(system_list)
            if len(system_list) == 0:
                print_warning("Datatype is iterative but no systems found in "
                              "input datafile, when Datatype is iterative the "
                              "InputDataFile should have system(s) to "
                              "iterate upon")
                tc_status = False
            elif len(system_list) > 0:
                tc_status = iterative_sequential_kw_driver.main(
                    step_list, data_repository, tc_status, system_list)
        elif data_type.upper() == 'ITERATIVE' and \
                runtype.upper() == 'PARALLEL_KEYWORDS':
            print_info("iterative parallel")
            system_list = get_system_list(data_repository['wt_datafile'],
                                          iter_req=True) \
                if iter_ts_sys is None else [iter_ts_sys]
            # print len(system_list)
            if len(system_list) == 0:
                print_warning("DataType is iterative but no systems found in "
                              "input datafile, when DataType id iterative the "
                              "InputDataFile should have system(s) to "
                              "iterate upon")
                tc_status = False
            elif len(system_list) > 0:
                tc_status = iterative_parallel_kw_driver.main(
                    step_list, data_repository, tc_status, system_list)
        elif data_type.upper() == "HYBRID":
            print_info("Hybrid")
            system_list, system_node_list = get_system_list(
                data_repository['wt_datafile'], node_req=True)
            # call the hybrid driver here
            hyb_drv_obj = hybrid_driver_class.HybridDriver(
                step_list, data_repository, tc_status, system_list,
                system_node_list)
            tc_status = hyb_drv_obj.execute_hybrid_mode()
        else:
            print_warning("unsupported value provided for testcase data_type "
                          "or testsuite runtype")
            tc_status = False

    if tc_context.upper() == 'NEGATIVE':
        if all([tc_status != 'EXCEPTION', tc_status != 'ERROR']):
            print_debug(
                "Test case status is: '{0}', flip status as context is negative"
                .format(tc_status))
            tc_status = not tc_status

    if tc_status == False and tc_onError_action and tc_onError_action.upper(
    ) == 'ABORT_AS_ERROR':
        print_info(
            "Testcase status will be marked as ERROR as onError action is set to 'abort_as_error'"
        )
        tc_status = "ERROR"

    check_and_create_defects(tc_status, auto_defects, data_repository,
                             tc_junit_object)

    print("\n")
    tc_end_time = Utils.datetime_utils.get_current_timestamp()
    print_info("[{0}] Testcase execution completed".format(tc_end_time))
    tc_duration = Utils.datetime_utils.get_time_delta(tc_start_time)
    hms = Utils.datetime_utils.get_hms_for_seconds(tc_duration)
    print_info("Testcase duration= {0}".format(hms))

    tc_junit_object.update_count(tc_status, "1", "ts",
                                 data_repository['wt_ts_timestamp'])
    tc_junit_object.update_count("tests", "1", "ts",
                                 data_repository['wt_ts_timestamp'])
    tc_junit_object.update_count("tests", "1", "pj", "not appicable")
    tc_junit_object.update_attr("status", str(tc_status), "tc", tc_timestamp)
    tc_junit_object.update_attr("time", str(tc_duration), "tc", tc_timestamp)
    tc_junit_object.add_testcase_message(tc_timestamp, tc_status)

    # Adding resultsdir, logsdir, title as attributes to testcase_tag in the junit result file
    # Need to remove these after making resultsdir, logsdir as part of properties tag in testcase
    tc_junit_object.update_attr(
        "resultsdir", os.path.dirname(data_repository['wt_resultsdir']), "tc",
        tc_timestamp)
    tc_junit_object.update_attr("logsdir",
                                os.path.dirname(data_repository['wt_logsdir']),
                                "tc", tc_timestamp)

    report_testcase_result(tc_status, data_repository)
    if not from_ts:
        tc_junit_object.update_count(tc_status, "1", "pj", "not appicable")
        tc_junit_object.update_count("suites", "1", "pj", "not appicable")
        tc_junit_object.update_attr("status", str(tc_status), "ts",
                                    data_repository['wt_ts_timestamp'])
        tc_junit_object.update_attr("status", str(tc_status), "pj",
                                    "not appicable")
        tc_junit_object.update_attr("time", str(tc_duration), "ts",
                                    data_repository['wt_ts_timestamp'])
        tc_junit_object.update_attr("time", str(tc_duration), "pj",
                                    "not appicable")

        tc_junit_object.output_junit(data_repository['wt_resultsdir'])

        # Save JUnit/HTML results of the Case in MongoDB server
        if data_repository.get("db_obj") is not False:
            tc_junit_xml = data_repository[
                'wt_resultsdir'] + os.sep + tc_junit_object.filename + "_junit.xml"
            data_repository.get("db_obj").add_html_result_to_mongodb(
                tc_junit_xml)
    else:
        # send an email on TC failure(no need to send an email here when
        # executing a single case).
        if str(tc_status).upper() in ["FALSE", "ERROR", "EXCEPTION"]:
            email_setting = None
            # for first TC failure
            if "any_failures" not in data_repository:
                email_params = email.get_email_params("first_failure")
                if all(value != "" for value in email_params[:3]):
                    email_setting = "first_failure"
                data_repository['any_failures'] = True
            # for further TC failures
            if email_setting is None:
                email_params = email.get_email_params("every_failure")
                if all(value != "" for value in email_params[:3]):
                    email_setting = "every_failure"

            if email_setting is not None:
                email.compose_send_email(
                    "Test Case: ", data_repository['wt_testcase_filepath'],
                    data_repository['wt_logsdir'],
                    data_repository['wt_resultsdir'], tc_status, email_setting)

        if 'wp_results_execdir' in data_repository:
            # Create and replace existing Project junit file for each case
            tc_junit_object.output_junit(data_repository['wp_results_execdir'],
                                         print_summary=False)
        else:
            # Create and replace existing Suite junit file for each case
            tc_junit_object.output_junit(data_repository['wt_results_execdir'],
                                         print_summary=False)

    if tc_parallel:
        tc_impact = data_repository['wt_tc_impact']
        if tc_impact.upper() == 'IMPACT':
            msg = "Status of the executed test case impacts Testsuite result"
        elif tc_impact.upper() == 'NOIMPACT':
            msg = "Status of the executed test case does not impact Teststuie result"
        print_debug(msg)
        tc_name = Utils.file_Utils.getFileName(testcase_filepath)
        # put result into multiprocessing queue and later retrieve in corresponding driver
        queue.put(
            (tc_status, tc_name, tc_impact, tc_duration, tc_junit_object))

    # Save XML results of the Case in MongoDB server
    if data_repository.get("db_obj") is not False:
        data_repository.get("db_obj").add_xml_result_to_mongodb(
            data_repository['wt_resultfile'])

    # main need tc_status and data_repository values to unpack
    return tc_status, data_repository
def execute_steps(data_type, runtype, data_repository, step_list,
                  tc_junit_object, iter_ts_sys):
    """executes steps based on given data_type and runtype"""
    tc_status = True
    if data_type.upper() == 'CUSTOM' and \
        runtype.upper() == 'SEQUENTIAL_KEYWORDS':
        tc_status = execute_custom(data_type, runtype,\
                                       custom_sequential_kw_driver,\
                                       data_repository, step_list)
    elif data_type.upper() == 'CUSTOM' and \
                runtype.upper() == 'PARALLEL_KEYWORDS':
        tc_junit_object.remove_html_obj()
        data_repository["war_parallel"] = True
        tc_status = execute_custom(data_type, runtype,\
                                       custom_parallel_kw_driver,\
                                       data_repository, step_list)
    elif data_type.upper() == 'ITERATIVE' and \
                runtype.upper() == 'SEQUENTIAL_KEYWORDS':
        print_info("iterative sequential")
        system_list = get_system_list(data_repository['wt_datafile'],\
                                          iter_req=True) \
            if iter_ts_sys is None else [iter_ts_sys]
        # print len(system_list)
        if len(system_list) == 0:
            print_warning("Datatype is iterative but no systems found in "
                          "input datafile, when Datatype is iterative the "
                          "InputDataFile should have system(s) to "
                          "iterate upon")
            tc_status = False
        elif len(system_list) > 0:
            tc_status = iterative_sequential_kw_driver.main(\
                 step_list, data_repository, tc_status, system_list)
    elif data_type.upper() == 'ITERATIVE' and \
                runtype.upper() == 'PARALLEL_KEYWORDS':
        tc_junit_object.remove_html_obj()
        data_repository["war_parallel"] = True
        print_info("iterative parallel")
        system_list = get_system_list(data_repository['wt_datafile'],\
                                          iter_req=True) \
        if iter_ts_sys is None else [iter_ts_sys]
        # print len(system_list)
        if len(system_list) == 0:
            print_warning("DataType is iterative but no systems found in "
                          "input datafile, when DataType id iterative the "
                          "InputDataFile should have system(s) to "
                          "iterate upon")
            tc_status = False
        elif len(system_list) > 0:
            tc_status = iterative_parallel_kw_driver.main(\
                 step_list, data_repository, tc_status, system_list)
    elif data_type.upper() == "HYBRID":
        print_info("Hybrid")
        system_list, system_node_list = get_system_list(\
             data_repository['wt_datafile'], node_req=True)
        # call the hybrid driver here
        hyb_drv_obj = hybrid_driver_class.HybridDriver(\
             step_list, data_repository, tc_status, system_list,\
             system_node_list)
        tc_status = hyb_drv_obj.execute_hybrid_mode()
    else:
        print_warning("unsupported value provided for testcase data_type "\
                          "or testsuite runtype")
        tc_status = False

    return tc_status