code: def test_safe_to_scale(
      node_set: Set[NodeID],
      cpu_workers_to_delete: List[NodeID],
      gpu_workers_to_delete: List[NodeID],
  ):
      # NodeData values unimportant for this test.
      mock_node_data = NodeData("-", "-", "-", "-")
      node_data_dict = {node_id: mock_node_data for node_id in node_set}
  
      raycluster = _get_basic_ray_cr_workers_to_delete(
          cpu_workers_to_delete, gpu_workers_to_delete
      )
  
      def mock_patch(kuberay_provider, path, patch_payload):
          patch = jsonpatch.JsonPatch(patch_payload)
          kuberay_provider._patched_raycluster = patch.apply(
              kuberay_provider._raycluster
          )
  
      with mock.patch.object(
          KubeRayNodeProvider, "__init__", return_value=None
      ), mock.patch.object(KubeRayNodeProvider, "_patch", mock_patch):
          kr_node_provider = KubeRayNodeProvider(
              provider_config={}, cluster_name="fake"
          )
          kr_node_provider.cluster_name = "fake"
          kr_node_provider._patched_raycluster = raycluster
          kr_node_provider._raycluster = raycluster
          kr_node_provider.node_data_dict = node_data_dict
          actual_safe = kr_node_provider.safe_to_scale()
  
      expected_safe = not any(
          cpu_worker_to_delete in node_set
          for cpu_worker_to_delete in cpu_workers_to_delete
      ) and not any(
          gpu_worker_to_delete in node_set
          for gpu_worker_to_delete in gpu_workers_to_delete
      )
      assert expected_safe is actual_safe
      patched_cpu_workers_to_delete = (
          kr_node_provider._patched_raycluster["spec"][
              "workerGroupSpecs"
          ][0]["scaleStrategy"]["workersToDelete"]
      )
      patched_gpu_workers_to_delete = (
          kr_node_provider._patched_raycluster["spec"][
              "workerGroupSpecs"
          ][1]["scaleStrategy"]["workersToDelete"]
      )
  
      if expected_safe:
          # Cleaned up workers to delete
          assert patched_cpu_workers_to_delete == []
          assert patched_gpu_workers_to_delete == []
      else:
          # Did not clean up workers to delete
          assert patched_cpu_workers_to_delete == cpu_workers_to_delete
          assert patched_gpu_workers_to_delete == gpu_workers_to_delete
  
imports: import copy
  import mock
  import sys
  import jsonpatch
  import pytest
  from ray.autoscaler.batching_node_provider import NodeData
  from ray.autoscaler._private.kuberay.node_provider import _worker_group_index, _worker_group_max_replicas, _worker_group_replicas, KubeRayNodeProvider, ScaleRequest
  from ray.autoscaler._private.util import NodeID
  from pathlib import Path
  import yaml
  from ray.tests.kuberay.test_autoscaling_config import get_basic_ray_cr
  from typing import Set, List
label_desc: Use image node_id 8 for calling a global function with example usage: test_safe_to_scale(node_set, cpu_workers_to_delete, gpu_workers_to_delete) without return types