code: def test_do_with_cache(self, provide_first_input_cache):
      # First run that creates cache.
      self._exec_properties[
          standard_component_specs.MODULE_FILE_KEY
      ] = self._module_file
      if provide_first_input_cache:
          self._input_dict[
              standard_component_specs.ANALYZER_CACHE_KEY
          ] = []
      metrics = self._run_pipeline_get_metrics()
  
      # The test data has 9909 instances in the train dataset, and 5091 instances
      # in the eval dataset. Since the analysis dataset (train) is read twice when
      # no input cache is present (once for analysis and once for transform), the
      # expected value of the num_instances counter is: 9909 * 2 + 5091 = 24909.
      # (SE - 10500 * 2 + 4500 = 25500)
      self.assertMetricsCounterEqual(
          metrics,
          "num_instances",
          self._CACHE_TEST_METRICS[
              "num_instances_tfx.Transform_1st_run"
          ],
          ["tfx.Transform"],
      )
  
      # Additionally we have 24909 (SE - 25500) instances due to generating
      # statistics.
      self.assertMetricsCounterEqual(
          metrics,
          "num_instances",
          self._CACHE_TEST_METRICS[
              "num_instances_tfx.DataValidation_1st_run"
          ],
          ["tfx.DataValidation"],
      )
      self._verify_transform_outputs(store_cache=True)
  
      # Second run from cache.
      self._output_data_dir = self._get_output_data_dir("2nd_run")
      analyzer_cache_artifact = standard_artifacts.TransformCache()
      analyzer_cache_artifact.uri = (
          self._updated_analyzer_cache_artifact.uri
      )
  
      self._make_base_do_params(
          self._SOURCE_DATA_DIR, self._output_data_dir
      )
  
      self._input_dict[standard_component_specs.ANALYZER_CACHE_KEY] = [
          analyzer_cache_artifact
      ]
  
      self._exec_properties[
          standard_component_specs.MODULE_FILE_KEY
      ] = self._module_file
      metrics = self._run_pipeline_get_metrics()
  
      # Since input cache should now cover all analysis (train) paths, the train
      # and eval sets are each read exactly once for transform. Thus, the
      # expected value of the num_instances counter is: 9909 + 5091 = 15000.
      # (SE - 10500 + 4500 = 15000)
      self.assertMetricsCounterEqual(
          metrics,
          "num_instances",
          self._CACHE_TEST_METRICS[
              "num_instances_tfx.Transform_2nd_run"
          ],
          ["tfx.Transform"],
      )
  
      # Additionally we have 24909 (SE - 25500) instances due to generating
      # statistics.
      self.assertMetricsCounterEqual(
          metrics,
          "num_instances",
          self._CACHE_TEST_METRICS[
              "num_instances_tfx.DataValidation_2nd_run"
          ],
          ["tfx.DataValidation"],
      )
      self._verify_transform_outputs(store_cache=True)
  
imports: import copy
  import json
  import os
  import re
  import tempfile
  from unittest import mock
  from absl.testing import parameterized
  import apache_beam
  import tensorflow
  import tensorflow_data_validation
  import tensorflow_transform
  from tensorflow_transform.beam import tft_unit
  from tfx import types
  from tfx.components.testdata.module_file import transform_module
  from tfx.components.transform import executor
  from tfx.dsl.io import fileio
  from tfx.proto import example_gen_pb2
  from tfx.proto import transform_pb2
  from tfx.types import artifact_utils
  from tfx.types import standard_artifacts
  from tfx.types import standard_component_specs
  from tfx.utils import io_utils
  from tfx.utils import name_utils
  from tfx.utils import proto_utils
label_desc: Use image node_id 27 for calling the ExecutorTest obj's underlying member method code with example usage: obj.test_do_with_cache(provide_first_input_cache) without return types