code: def test_function(
      *,
      input_dtypes: Union[ivy.Dtype, List[ivy.Dtype]],
      test_flags: FunctionTestFlags,
      fn_name: str,
      rtol_: Optional[float] = None,
      atol_: float = 1e-06,
      tolerance_dict: Optional[dict] = None,
      test_values: bool = True,
      xs_grad_idxs=None,
      ret_grad_idxs=None,
      backend_to_test: str,
      on_device: str,
      return_flat_np_arrays: bool = False,
      **all_as_kwargs_np,
  ):
      """Test a function that consumes (or returns) arrays for the current
      backend by comparing the result with numpy.
  
      Parameters
      ----------
      input_dtypes
          data types of the input arguments in order.
      test_flags
          FunctionTestFlags object that stores all testing flags, including:
          num_positional_args, with_out, instance_method, as_variable,
          native_arrays, container, gradient
      fw
          current backend (framework).
      fn_name
          name of the function to test.
      rtol_
          relative tolerance value.
      atol_
          absolute tolerance value.
      test_values
          if True, test for the correctness of the resulting values.
      xs_grad_idxs
          Indices of the input arrays to compute gradients with respect to. If None,
          gradients are returned with respect to all input arrays. (Default value = None)
      ret_grad_idxs
          Indices of the returned arrays for which to return computed gradients. If None,
          gradients are returned for all returned arrays. (Default value = None)
      on_device
          The device on which to create arrays
      return_flat_np_arrays
          If test_values is False, this flag dictates whether the original returns are
          returned, or whether the flattened numpy arrays are returned.
      all_as_kwargs_np
          input arguments to the function as keyword arguments.
  
      Returns
      -------
      ret
          optional, return value from the function
      ret_gt
          optional, return value from the Ground Truth function
  
      Examples
      --------
      >>> input_dtypes = 'float64'
      >>> as_variable_flags = False
      >>> with_out = False
      >>> num_positional_args = 0
      >>> native_array_flags = False
      >>> container_flags = False
      >>> instance_method = False
      >>> test_flags = FunctionTestFlags(num_positional_args, with_out,
          instance_method,
          as_variable,
          native_arrays,
          container_flags,
          none)
      >>> fw = "torch"
      >>> fn_name = "abs"
      >>> x = np.array([-1])
      >>> test_function(input_dtypes, test_flags, fw, fn_name, x=x)
  
      >>> input_dtypes = ['float64', 'float32']
      >>> as_variable_flags = [False, True]
      >>> with_out = False
      >>> num_positional_args = 1
      >>> native_array_flags = [True, False]
      >>> container_flags = [False, False]
      >>> instance_method = False
      >>> test_flags = FunctionTestFlags(num_positional_args, with_out,
          instance_method,
          as_variable,
          native_arrays,
          container_flags,
          none)
      >>> fw = "numpy"
      >>> fn_name = "add"
      >>> x1 = np.array([1, 3, 4])
      >>> x2 = np.array([-3, 15, 24])
      >>> test_function(input_dtypes, test_flags, fw, fn_name, x1=x1, x2=x2)
      """
      _switch_backend_context(
          test_flags.test_trace or test_flags.transpile
      )
      ground_truth_backend = test_flags.ground_truth_backend
  
      if test_flags.container[0]:
          test_flags.with_copy = False
  
      if test_flags.with_copy is True:
          test_flags.with_out = False
  
      if mod_backend[backend_to_test]:
          # multiprocessing
          proc, input_queue, output_queue = mod_backend[backend_to_test]
          input_queue.put(
              (
                  "function_backend_computation",
                  backend_to_test,
                  test_flags,
                  all_as_kwargs_np,
                  input_dtypes,
                  on_device,
                  fn_name,
              )
          )
          (
              ret_from_target,
              ret_np_flat_from_target,
              ret_device,
              args_np,
              arg_np_arrays,
              arrays_args_indices,
              kwargs_np,
              arrays_kwargs_indices,
              kwarg_np_arrays,
              test_flags,
              input_dtypes,
          ) = output_queue.get()
      else:
          (
              ret_from_target,
              ret_np_flat_from_target,
              ret_device,
              args_np,
              arg_np_arrays,
              arrays_args_indices,
              kwargs_np,
              arrays_kwargs_indices,
              kwarg_np_arrays,
              test_flags,
              input_dtypes,
          ) = test_function_backend_computation(
              backend_to_test,
              test_flags,
              all_as_kwargs_np,
              input_dtypes,
              on_device,
              fn_name,
          )
  
      # compute the return with a Ground Truth backend
      if mod_backend[ground_truth_backend]:
          proc, input_queue, output_queue = mod_backend[
              ground_truth_backend
          ]
          input_queue.put(
              (
                  "function_ground_truth_computation",
                  ground_truth_backend,
                  on_device,
                  args_np,
                  arg_np_arrays,
                  arrays_args_indices,
                  kwargs_np,
                  arrays_kwargs_indices,
                  kwarg_np_arrays,
                  input_dtypes,
                  test_flags,
                  fn_name,
              )
          )
          (
              ret_from_gt,
              ret_np_from_gt_flat,
              ret_from_gt_device,
              test_flags,
              fw_list,
          ) = output_queue.get()
      else:
          (
              ret_from_gt,
              ret_np_from_gt_flat,
              ret_from_gt_device,
              test_flags,
              fw_list,
          ) = test_function_ground_truth_computation(
              ground_truth_backend,
              on_device,
              args_np,
              arg_np_arrays,
              arrays_args_indices,
              kwargs_np,
              arrays_kwargs_indices,
              kwarg_np_arrays,
              input_dtypes,
              test_flags,
              fn_name,
          )
  
      if test_flags.transpile:
          if mod_backend[backend_to_test]:
              proc, input_queue, output_queue = mod_backend[
                  backend_to_test
              ]
              input_queue.put(
                  (
                      "transpile_if_required_backend",
                      backend_to_test,
                      fn_name,
                      args_np,
                      kwargs_np,
                  )
              )
          else:
              _transpile_if_required_backend(
                  backend_to_test,
                  fn_name,
                  args=args_np,
                  kwargs=kwargs_np,
              )
  
      # Gradient test
      # TODO enable back , ADD backend_to_test to the call below
  
      if (
          test_flags.test_gradients
          and not test_flags.instance_method
          and "bool" not in input_dtypes
          and not any(
              d in ["complex64", "complex128"] for d in input_dtypes
          )
      ):
          if backend_to_test not in fw_list or not ivy.nested_argwhere(
              all_as_kwargs_np,
              lambda x: (
                  x.dtype in fw_list[backend_to_test]
                  if isinstance(x, np.ndarray)
                  else None
              ),
          ):
              gradient_test(
                  fn=fn_name,
                  all_as_kwargs_np=all_as_kwargs_np,
                  args_np=args_np,
                  kwargs_np=kwargs_np,
                  input_dtypes=input_dtypes,
                  test_flags=test_flags,
                  rtol_=rtol_,
                  atol_=atol_,
                  xs_grad_idxs=xs_grad_idxs,
                  ret_grad_idxs=ret_grad_idxs,
                  ground_truth_backend=ground_truth_backend,
                  backend_to_test=backend_to_test,
                  on_device=on_device,
              )
  
      # assuming value test will be handled manually in the test function
      if not test_values:
          if return_flat_np_arrays:
              return ret_np_flat_from_target, ret_np_from_gt_flat
          return ret_from_target, ret_from_gt
  
      if isinstance(rtol_, dict):
          rtol_ = _get_framework_rtol(rtol_, backend_to_test)
      if isinstance(atol_, dict):
          atol_ = _get_framework_atol(atol_, backend_to_test)
  
      # value test
      value_test(
          ret_np_flat=ret_np_flat_from_target,
          ret_np_from_gt_flat=ret_np_from_gt_flat,
          rtol=rtol_,
          atol=atol_,
          specific_tolerance_dict=tolerance_dict,
          backend=backend_to_test,
          ground_truth_backend=test_flags.ground_truth_backend,
      )
      if not test_flags.test_trace:
          assert_same_type(
              ret_from_target,
              ret_from_gt,
              backend_to_test,
              test_flags.ground_truth_backend,
          )
  
      assert ret_device == ret_from_gt_device, (
          f"ground truth backend ({test_flags.ground_truth_backend}) returned array on"
          f" device {ret_from_gt_device} but target backend ({backend_to_test})"
          f" returned array on device {ret_device}"
      )
      if ret_device is not None:
          assert ret_device == on_device, (
              f"device is set to {on_device}, but ground truth produced array on"
              f" {ret_device}"
          )
  
imports: import copy
  import time
  from typing import Union, List, Optional
  import numpy
  import types
  import importlib
  import inspect
  from collections import OrderedDict
  from .globals import mod_backend
  from .pipeline_helper import BackendHandler, BackendHandlerMode, get_frontend_config
  import ivy
  from ivy_tests.test_ivy.helpers.test_parameter_flags import FunctionTestFlags
  import ivy_tests.test_ivy.helpers.test_parameter_flags
  import ivy_tests.test_ivy.helpers.globals
  from ivy.functional.ivy.data_type import _get_function_list, _get_functions_from_string
  from ivy_tests.test_ivy.test_frontends import NativeClass
  from ivy_tests.test_ivy.helpers.structs import FrontendMethodData
  from ivy_tests.test_ivy.helpers.testing_helpers import _create_transpile_report
  from .assertions import value_test, assert_same_type, check_unsupported_dtype
label_desc: Use image node_id 6 for calling a global function with example usage: test_function() and returns: ret_from_target,  ret_from_gt, ret_np_flat_from_target,  ret_np_from_gt_flat