code: def test_jumpstart_cache_evaluates_md5_hash(mock_boto3_client):
      mock_json = json.dumps(
          [
              {
                  "model_id": "pytorch-ic-imagenet-inception-v3-classification-4",
                  "version": "2.0.0",
                  "min_version": "2.49.0",
                  "spec_key": "community_models_specs/pytorch-ic-"
                  "imagenet-inception-v3-classification-4/specs_v2.0.0.json",
              }
          ]
      )
  
      bucket_name = "bucket_name"
      now = datetime.datetime.fromtimestamp(1636730651.079551)
  
      with patch("datetime.datetime") as mock_datetime:
          mock_datetime.now.return_value = now
  
          cache = JumpStartModelsCache(
              s3_bucket_name=bucket_name,
              s3_cache_expiration_horizon=datetime.timedelta(hours=1),
          )
  
          mock_boto3_client.return_value.get_object.return_value = {
              "Body": botocore.response.StreamingBody(
                  io.BytesIO(bytes(mock_json, "utf-8")),
                  content_length=len(mock_json),
              ),
              "ETag": "hash1",
          }
          mock_boto3_client.return_value.head_object.return_value = {
              "ETag": "hash1"
          }
  
          cache.get_header(
              model_id="pytorch-ic-imagenet-inception-v3-classification-4",
              semantic_version_str="*",
          )
  
          # first time accessing cache should just involve get_object
          mock_boto3_client.return_value.get_object.assert_called_with(
              Bucket=bucket_name,
              Key=JUMPSTART_DEFAULT_MANIFEST_FILE_S3_KEY,
          )
          mock_boto3_client.return_value.head_object.assert_not_called()
  
          mock_boto3_client.return_value.get_object.reset_mock()
          mock_boto3_client.return_value.head_object.reset_mock()
  
          # second time accessing cache should just involve head_object if hash hasn't changed
          mock_boto3_client.return_value.get_object.return_value = {
              "Body": botocore.response.StreamingBody(
                  io.BytesIO(bytes(mock_json, "utf-8")),
                  content_length=len(mock_json),
              ),
              "ETag": "hash1",
          }
          mock_boto3_client.return_value.head_object.return_value = {
              "ETag": "hash1"
          }
  
          # invalidate cache
          mock_datetime.now.return_value += datetime.timedelta(hours=2)
  
          cache.get_header(
              model_id="pytorch-ic-imagenet-inception-v3-classification-4",
              semantic_version_str="*",
          )
  
          mock_boto3_client.return_value.head_object.assert_called_with(
              Bucket=bucket_name,
              Key=JUMPSTART_DEFAULT_MANIFEST_FILE_S3_KEY,
          )
          mock_boto3_client.return_value.get_object.assert_not_called()
  
          mock_boto3_client.return_value.get_object.reset_mock()
          mock_boto3_client.return_value.head_object.reset_mock()
  
          # third time accessing cache should involve head_object and get_object if hash has changed
          mock_boto3_client.return_value.head_object.return_value = {
              "ETag": "hash2"
          }
          mock_boto3_client.return_value.get_object.return_value = {
              "Body": botocore.response.StreamingBody(
                  io.BytesIO(bytes(mock_json, "utf-8")),
                  content_length=len(mock_json),
              ),
              "ETag": "hash2",
          }
  
          # invalidate cache
          mock_datetime.now.return_value += datetime.timedelta(hours=2)
  
          cache.get_header(
              model_id="pytorch-ic-imagenet-inception-v3-classification-4",
              semantic_version_str="*",
          )
  
          mock_boto3_client.return_value.get_object.assert_called_with(
              Bucket=bucket_name,
              Key=JUMPSTART_DEFAULT_MANIFEST_FILE_S3_KEY,
          )
          mock_boto3_client.return_value.head_object.assert_called_with(
              Bucket=bucket_name,
              Key=JUMPSTART_DEFAULT_MANIFEST_FILE_S3_KEY,
          )
  
imports: from __future__ import absolute_import
  import copy
  import datetime
  import io
  import json
  from unittest.mock import Mock, call, mock_open
  from botocore.stub import Stubber
  import botocore
  from mock.mock import MagicMock
  import pytest
  from mock import patch
  from sagemaker.jumpstart.cache import JUMPSTART_DEFAULT_MANIFEST_FILE_S3_KEY, JumpStartModelsCache
  from sagemaker.jumpstart.constants import ENV_VARIABLE_JUMPSTART_MANIFEST_LOCAL_ROOT_DIR_OVERRIDE, ENV_VARIABLE_JUMPSTART_SPECS_LOCAL_ROOT_DIR_OVERRIDE
  from sagemaker.jumpstart.types import JumpStartModelHeader, JumpStartModelSpecs, JumpStartVersionedModelId
  from tests.unit.sagemaker.jumpstart.utils import get_spec_from_base_spec, patched_retrieval_function
  from tests.unit.sagemaker.jumpstart.constants import BASE_MANIFEST, BASE_SPEC
  from sagemaker.jumpstart.utils import get_jumpstart_content_bucket
label_desc: Use image node_id 6 for calling a global function with example usage: test_jumpstart_cache_evaluates_md5_hash(mock_boto3_client) without return types