code: def test_lazy_execution(self):
      self._setup_for_chore_pipeline()
  
      # chore_a and chore_b can execute way earlier but should wait for chore_f
      self.chore_a.execution_options.strategy = (
          pipeline_pb2.NodeExecutionOptions.LAZILY_ALL_UPSTREAM_NODES_SUCCEEDED
      )
      self.chore_b.execution_options.strategy = (
          pipeline_pb2.NodeExecutionOptions.LAZILY_ALL_UPSTREAM_NODES_SUCCEEDED
      )
  
      # chore_d and chore_e are on the same level so they should execute at the
      # same time Also use LAZILY_ALL_UPSTREAM_NODES_COMPLETED to check both
      # strategies can work in the happy path.
      self.chore_d.execution_options.strategy = (
          pipeline_pb2.NodeExecutionOptions.LAZILY_ALL_UPSTREAM_NODES_COMPLETED
      )
      self.chore_e.execution_options.strategy = (
          pipeline_pb2.NodeExecutionOptions.LAZILY_ALL_UPSTREAM_NODES_COMPLETED
      )
  
      # chore_g is terminal and should execute normally.
      self.chore_g.execution_options.strategy = (
          pipeline_pb2.NodeExecutionOptions.ALL_UPSTREAM_NODES_COMPLETED
      )
  
      test_utils.fake_example_gen_run(
          self._mlmd_connection, self.eg_1, 1, 1
      )
      test_utils.fake_example_gen_run(
          self._mlmd_connection, self.eg_2, 1, 1
      )
  
      self._run_next(False, expect_nodes=[self.chore_d, self.chore_e])
      self._run_next(False, expect_nodes=[self.chore_f, self.chore_g])
  
      # Need to wait a cycle for chore_f to get marked as succesful.
      # TODO(kmonte): Figure out how to avoid this.
      self._run_next(False, expect_nodes=[])
      self._run_next(False, expect_nodes=[self.chore_a])
      self._run_next(False, expect_nodes=[self.chore_b])
      self._run_next(False, expect_nodes=[self.chore_c])
  
imports: import itertools
  import os
  from typing import Literal
  import uuid
  from absl.testing import parameterized
  from absl.testing.absltest import mock
  import tensorflow
  from tfx.dsl.compiler import constants
  from tfx.orchestration import data_types_utils
  from tfx.orchestration.experimental.core import constants
  from tfx.orchestration.experimental.core import mlmd_state
  from tfx.orchestration.experimental.core import pipeline_state
  from tfx.orchestration.experimental.core import service_jobs
  from tfx.orchestration.experimental.core import sync_pipeline_task_gen
  from tfx.orchestration.experimental.core import task
  from tfx.orchestration.experimental.core import task_gen_utils
  from tfx.orchestration.experimental.core import task_queue
  from tfx.orchestration.experimental.core import test_utils
  from tfx.orchestration.experimental.core.testing import test_sync_pipeline
  from tfx.orchestration import mlmd_connection_manager
  from tfx.orchestration.portable import runtime_parameter_utils
  from tfx.proto.orchestration import pipeline_pb2
  from tfx.utils import status
  from ml_metadata.proto import metadata_store_pb2
label_desc: Use image node_id 27 for calling the SyncPipelineTaskGeneratorTest obj's underlying member method code with example usage: obj.test_lazy_execution() without return types