code: def test_frontend_function(
      *,
      input_dtypes: Union[ivy.Dtype, List[ivy.Dtype]],
      test_flags: pf.frontend_function_flags,
      backend_to_test: str,
      on_device="cpu",
      frontend: str,
      fn_tree: str,
      gt_fn_tree: Optional[str] = None,
      rtol: Optional[float] = None,
      atol: float = 1e-06,
      tolerance_dict: Optional[dict] = None,
      test_values: bool = True,
      **all_as_kwargs_np,
  ):
      """Test a frontend function for the current backend by comparing the result
      with the function in the associated framework.
  
      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, precision_mode
      frontend
          current frontend (framework).
      fn_tree
          Path to function in frontend framework namespace.
      gt_fn_tree
          Path to function in ground truth framework namespace.
      rtol
          relative tolerance value.
      atol
          absolute tolerance value.
      tolerance_dict
          dictionary of tolerance values for specific dtypes.
      test_values
          if True, test for the correctness of the resulting values.
      all_as_kwargs_np
          input arguments to the function as keyword arguments.
  
      Returns
      -------
      ret
          optional, return value from the function
      ret_np
          optional, return value from the Numpy function
      """
      # ToDo add with_backend refactor in GC
      _switch_backend_context(
          test_flags.test_trace or test_flags.transpile
      )
  
      assert (
          not test_flags.with_out or not test_flags.inplace
      ), "only one of with_out or with_inplace can be set as True"
  
      if test_flags.with_copy is True:
          test_flags.with_out = False
          test_flags.inplace = False
  
      # split the arguments into their positional and keyword components
      args_np, kwargs_np = kwargs_to_args_n_kwargs(
          num_positional_args=test_flags.num_positional_args,
          kwargs=all_as_kwargs_np,
      )
  
      # extract all arrays from the arguments and keyword arguments
      arg_np_vals, args_idxs, c_arg_vals = _get_nested_np_arrays(
          args_np
      )
      kwarg_np_vals, kwargs_idxs, c_kwarg_vals = _get_nested_np_arrays(
          kwargs_np
      )
      # make all lists equal in length
      num_arrays = c_arg_vals + c_kwarg_vals
      if len(input_dtypes) < num_arrays:
          input_dtypes = [input_dtypes[0] for _ in range(num_arrays)]
      if len(test_flags.as_variable) < num_arrays:
          test_flags.as_variable = [
              test_flags.as_variable[0] for _ in range(num_arrays)
          ]
      if len(test_flags.native_arrays) < num_arrays:
          test_flags.native_arrays = [
              test_flags.native_arrays[0] for _ in range(num_arrays)
          ]
  
      with BackendHandler.update_backend(
          backend_to_test
      ) as ivy_backend:
          # update var flags to be compatible with float dtype and with_out args
          test_flags.as_variable = [
              v
              if ivy_backend.is_float_dtype(d)
              and not test_flags.with_out
              else False
              for v, d in zip(test_flags.as_variable, input_dtypes)
          ]
  
          local_importer = ivy_backend.utils.dynamic_import
  
          # strip the decorator to get an Ivy array
          # TODO, fix testing for jax frontend for x32
          if frontend == "jax":
              local_importer.import_module(
                  "ivy.functional.frontends.jax"
              ).config.update("jax_enable_x64", True)
  
          (
              frontend_submods,
              fn_name,
              gt_frontend_submods,
              gt_fn_name,
          ) = _get_frontend_submodules(fn_tree, gt_fn_tree)
          function_module = local_importer.import_module(
              frontend_submods
          )
          frontend_fn = getattr(function_module, fn_name)
  
          # apply test flags etc.
          args, kwargs = create_args_kwargs(
              backend=backend_to_test,
              args_np=args_np,
              arg_np_vals=arg_np_vals,
              args_idxs=args_idxs,
              kwargs_np=kwargs_np,
              kwarg_np_vals=kwarg_np_vals,
              kwargs_idxs=kwargs_idxs,
              input_dtypes=input_dtypes,
              test_flags=test_flags,
              on_device=on_device,
          )
  
          # Make copy for arguments for functions that might use
          # inplace update by default
          copy_kwargs = copy.deepcopy(kwargs)
          copy_args = copy.deepcopy(args)
  
          # Frontend array generation
          create_frontend_array = local_importer.import_module(
              f"ivy.functional.frontends.{frontend}"
          )._frontend_array
  
          if test_flags.generate_frontend_arrays:
              args_for_test, kwargs_for_test = args_to_frontend(
                  backend_to_test,
                  *args,
                  frontend_array_fn=create_frontend_array,
                  **kwargs,
              )
              copy_args, copy_kwargs = args_to_frontend(
                  backend_to_test,
                  *args,
                  frontend_array_fn=create_frontend_array,
                  **kwargs,
              )
          else:
              args_for_test = copy.deepcopy(args)
              kwargs_for_test = copy.deepcopy(kwargs)
  
          ret = get_frontend_ret(
              backend_to_test,
              frontend_fn,
              *args_for_test,
              test_trace=test_flags.test_trace,
              frontend_array_function=(
                  create_frontend_array
                  if test_flags.test_trace
                  else None
              ),
              precision_mode=test_flags.precision_mode,
              **kwargs_for_test,
          )
  
          # test if return is frontend
          _assert_frontend_ret(ret)
  
          if test_flags.with_out and "out" in list(
              inspect.signature(frontend_fn).parameters.keys()
          ):
              if not inspect.isclass(ret):
                  is_ret_tuple = issubclass(ret.__class__, tuple)
              else:
                  is_ret_tuple = issubclass(ret, tuple)
              out = ret
              if is_ret_tuple:
                  flatten_ret = flatten_frontend(
                      ret=ret,
                      backend=backend_to_test,
                      frontend_array_fn=create_frontend_array,
                  )
                  flatten_out = flatten_frontend(
                      ret=out,
                      backend=backend_to_test,
                      frontend_array_fn=create_frontend_array,
                  )
                  for ret_array, out_array in zip(
                      flatten_ret, flatten_out
                  ):
                      if (
                          ivy_backend.native_inplace_support
                          and not any(
                              (
                                  ivy_backend.isscalar(ret),
                                  ivy_backend.isscalar(out),
                              )
                          )
                      ):
                          assert (
                              ret_array.ivy_array.data
                              is out_array.ivy_array.data
                          )
                      assert ret_array is out_array
              else:
                  if ivy_backend.native_inplace_support and not any(
                      (
                          ivy_backend.isscalar(ret),
                          ivy_backend.isscalar(out),
                      )
                  ):
                      assert ret.ivy_array.data is out.ivy_array.data
                  assert ret is out
          elif test_flags.with_copy:
              assert _is_frontend_array(ret)
  
              if "copy" in list(
                  inspect.signature(frontend_fn).parameters.keys()
              ):
                  copy_kwargs["copy"] = True
              first_array = ivy_backend.func_wrapper._get_first_array(
                  *copy_args,
                  array_fn=(
                      _is_frontend_array
                      if test_flags.generate_frontend_arrays
                      else ivy_backend.is_array
                  ),
                  **copy_kwargs,
              )
              ret_ = get_frontend_ret(
                  backend_to_test,
                  frontend_fn,
                  *copy_args,
                  test_trace=test_flags.test_trace,
                  frontend_array_function=(
                      create_frontend_array
                      if test_flags.test_trace
                      else None
                  ),
                  precision_mode=test_flags.precision_mode,
                  **copy_kwargs,
              )
              if test_flags.generate_frontend_arrays:
                  first_array = first_array.ivy_array
              ret_ = ret_.ivy_array
              if "bfloat16" in str(ret_.dtype):
                  ret_ = ivy_backend.astype(ret_, ivy_backend.float64)
              if "bfloat16" in str(first_array.dtype):
                  first_array = ivy_backend.astype(
                      first_array, ivy_backend.float64
                  )
              if not ivy_backend.is_native_array(first_array):
                  first_array = first_array.data
              ret_ = ret_.data
              if hasattr(first_array, "requires_grad"):
                  first_array = first_array.detach()
              assert not np.may_share_memory(first_array, ret_)
          elif test_flags.inplace:
              assert _is_frontend_array(ret)
  
              if "inplace" in list(
                  inspect.signature(frontend_fn).parameters.keys()
              ):
                  # the function provides optional inplace update
                  copy_kwargs["inplace"] = True
                  # else the function provides inplace update by default
  
              first_array = ivy_backend.func_wrapper._get_first_array(
                  *copy_args,
                  array_fn=(
                      _is_frontend_array
                      if test_flags.generate_frontend_arrays
                      else ivy_backend.is_array
                  ),
                  **copy_kwargs,
              )
              ret_ = get_frontend_ret(
                  backend_to_test,
                  frontend_fn,
                  *copy_args,
                  test_trace=test_flags.test_trace,
                  frontend_array_function=(
                      create_frontend_array
                      if test_flags.test_trace
                      else None
                  ),
                  precision_mode=test_flags.precision_mode,
                  **copy_kwargs,
              )
              if test_flags.generate_frontend_arrays:
                  assert first_array is ret_
              elif (
                  ivy_backend.is_native_array(first_array)
                  and ivy_backend.inplace_arrays_supported()
              ):
                  assert first_array is ret_.ivy_array.data
              elif ivy_backend.is_ivy_array(first_array):
                  assert first_array.data is ret_.ivy_array.data
  
          # create NumPy args
          if test_values:
              ret_np_flat = flatten_frontend_to_np(
                  ret=ret,
                  backend=backend_to_test,
              )
  
          if not test_values:
              ret = ivy_backend.nested_map(
                  _frontend_array_to_ivy,
                  ret,
                  include_derived={"tuple": True},
              )
  
      # create frontend framework args
      frontend_config = get_frontend_config(frontend)
      args_frontend = ivy.nested_map(
          lambda x: (
              frontend_config.native_array(x)
              if isinstance(x, np.ndarray)
              else (
                  frontend_config.as_native_dtype(x)
                  if isinstance(x, frontend_config.Dtype)
                  else x
              )
          ),
          args_np,
          shallow=False,
      )
      kwargs_frontend = ivy.nested_map(
          lambda x: frontend_config.native_array(x)
          if isinstance(x, np.ndarray)
          else x,
          kwargs_np,
          shallow=False,
      )
  
      # change ivy dtypes to native dtypes
      if (
          "dtype" in kwargs_frontend
          and kwargs_frontend["dtype"] is not None
      ):
          kwargs_frontend["dtype"] = frontend_config.as_native_dtype(
              kwargs_frontend["dtype"]
          )
  
      # change ivy device to native devices
      if "device" in kwargs_frontend:
          kwargs_frontend["device"] = frontend_config.as_native_device(
              kwargs_frontend["device"]
          )
  
      # compute the return via the frontend framework
      frontend_fw = importlib.import_module(gt_frontend_submods)
      frontend_fw_fn = frontend_fw.__dict__[gt_fn_name]
      frontend_ret = frontend_fw_fn(*args_frontend, **kwargs_frontend)
  
      if test_flags.transpile:
          _get_transpiled_data_if_required(
              frontend_fn,
              frontend_fw_fn,
              frontend,
              backend_to_test,
              fn_name=f"{gt_frontend_submods}.{gt_fn_name}",
              generate_frontend_arrays=test_flags.generate_frontend_arrays,
              args_for_test=args_for_test,
              kwargs_for_test=kwargs_for_test,
              frontend_fw_args=args_frontend,
              frontend_fw_kwargs=kwargs_frontend,
          )
  
      if test_values:
          frontend_ret_np_flat = flatten_frontend_fw_to_np(
              frontend_ret,
              frontend_config.isscalar,
              frontend_config.is_native_array,
              frontend_config.to_numpy,
          )
  
      # assuming value test will be handled manually in the test function
      if not test_values:
          return (
              ret,
              frontend_ret,
          )
  
      if isinstance(rtol, dict):
          rtol = _get_framework_rtol(rtol, t_globals.CURRENT_BACKEND)
      if isinstance(atol, dict):
          atol = _get_framework_atol(atol, t_globals.CURRENT_BACKEND)
  
      value_test(
          ret_np_flat=ret_np_flat,
          ret_np_from_gt_flat=frontend_ret_np_flat,
          rtol=rtol,
          atol=atol,
          specific_tolerance_dict=tolerance_dict,
          backend=backend_to_test,
          ground_truth_backend=frontend,
      )
  
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 9 for calling a global function with example usage: test_frontend_function() and returns: ret,  frontend_ret