code: def assert_nodes(
      actual_nodes: List[NodeInfo],
      expected_nodes: List[ExpectedNodeInfo],
  ):
      assert len(actual_nodes) == len(expected_nodes)
      # Sort the nodes by id.
      actual_nodes = sorted(actual_nodes, key=lambda node: node.node_id)
      expected_nodes = sorted(
          expected_nodes, key=lambda node: node.node_id
      )
  
      for actual_node, expected_node in zip(
          actual_nodes, expected_nodes
      ):
          if expected_node.node_id is not None:
              assert actual_node.node_id == expected_node.node_id
          if expected_node.node_status is not None:
              assert (
                  actual_node.node_status == expected_node.node_status
              )
          if expected_node.instance_id is not None:
              assert (
                  actual_node.instance_id == expected_node.instance_id
              )
          if expected_node.ray_node_type_name is not None:
              assert (
                  actual_node.ray_node_type_name
                  == expected_node.ray_node_type_name
              )
          if expected_node.instance_type_name is not None:
              assert (
                  actual_node.instance_type_name
                  == expected_node.instance_type_name
              )
          if expected_node.ip_address is not None:
              assert actual_node.ip_address == expected_node.ip_address
          if expected_node.details is not None:
              assert expected_node.details in actual_node.details
  
          if expected_node.idle_time_check_cb:
              assert expected_node.idle_time_check_cb(
                  actual_node.resource_usage.idle_time_ms
              )
  
          if expected_node.total_resources:
              for (
                  resource_name,
                  total,
              ) in expected_node.total_resources.items():
                  assert (
                      total
                      == get_total_resources(
                          actual_node.resource_usage.usage
                      )[resource_name]
                  )
  
          if expected_node.available_resources:
              for (
                  resource_name,
                  available,
              ) in expected_node.available_resources.items():
                  assert (
                      available
                      == get_available_resources(
                          actual_node.resource_usage.usage
                      )[resource_name]
                  )
  
imports: import os
  import sys
  import time
  from dataclasses import dataclass
  from typing import Callable, List, Optional, Tuple
  import pytest
  import ray
  import ray._private.ray_constants
  from ray._private.test_utils import wait_for_condition
  from ray.autoscaler.v2.schema import ClusterStatus, LaunchRequest, NodeInfo, ResourceRequestByCount
  from ray.autoscaler.v2.sdk import get_cluster_status, request_cluster_resources
  from ray.autoscaler.v2.tests.util import get_available_resources, get_cluster_resource_state, get_total_resources, report_autoscaling_state
  from ray.core.generated import autoscaler_pb2, autoscaler_pb2_grpc
  from ray.core.generated.autoscaler_pb2 import ClusterResourceState, NodeStatus
  from ray.util.state.api import list_nodes
label_desc: Use image node_id 5 for calling a global function with example usage: assert_nodes(actual_nodes, expected_nodes) without return types