code: def test_job_info_to_json():
      info = JobInfo(
          status=JobStatus.PENDING,
          entrypoint="echo hi",
          entrypoint_num_cpus=1,
          entrypoint_num_gpus=1,
          entrypoint_memory=4,
          entrypoint_resources={"Custom": 1},
          runtime_env={"pip": ["pkg"]},
      )
      expected_items = {
          "status": "PENDING",
          "message": (
              "Job has not started yet. It may be waiting for resources "
              "(CPUs, GPUs, memory, custom resources) to become available. "
              "It may be waiting for the runtime environment to be set up."
          ),
          "entrypoint": "echo hi",
          "entrypoint_num_cpus": 1,
          "entrypoint_num_gpus": 1,
          "entrypoint_memory": 4,
          "entrypoint_resources": {"Custom": 1},
          "runtime_env_json": '{"pip": ["pkg"]}',
      }
  
      # Check that the expected items are in the JSON.
      assert expected_items.items() <= info.to_json().items()
  
      new_job_info = JobInfo.from_json(info.to_json())
      assert new_job_info == info
  
      # If `status` is just a string, then operations like status.is_terminal()
      # would fail, so we should make sure that it's a JobStatus.
      assert isinstance(new_job_info.status, JobStatus)
  
file_path: ray/python/ray/dashboard/modules/job/tests/test_common.py
imports: import pytest
  import json
  from ray.dashboard.modules.job.common import JobInfo, JobStatus, http_uri_components_to_uri, uri_to_http_components, validate_request_type, JobSubmitRequest
  from ray.core.generated.gcs_pb2 import JobsAPIInfo
  from google.protobuf.json_format import Parse
label_desc: Use image node_id 3 for calling a global function with example usage: test_job_info_to_json() without return types