docstr: Test GS initalization and validation with nodes
code: def test_gs_setup_with_nodes(self) -> None:
      """Test GS initalization and validation with nodes"""
      sobol_model_spec = ModelSpec(
          model_enum=Models.SOBOL,
          model_kwargs={},
          model_gen_kwargs={"n": 2},
      )
      node_1_criterion = [
          MaxTrials(
              threshold=4,
              block_gen_if_met=False,
              transition_to="node_2",
              only_in_statuses=None,
              not_in_statuses=[
                  TrialStatus.FAILED,
                  TrialStatus.ABANDONED,
              ],
          ),
          MinTrials(
              only_in_statuses=[
                  TrialStatus.COMPLETED,
                  TrialStatus.EARLY_STOPPED,
              ],
              threshold=2,
              transition_to="node_2",
          ),
          MaxGenerationParallelism(
              threshold=1,
              only_in_statuses=[TrialStatus.RUNNING],
              block_gen_if_met=True,
              block_transition_if_unmet=False,
          ),
      ]
  
      # check error raised if node names are not unique
      with self.assertRaisesRegex(
          GenerationStrategyMisconfiguredException, "All node names"
      ):
          GenerationStrategy(
              nodes=[
                  GenerationNode(
                      node_name="node_1",
                      transition_criteria=node_1_criterion,
                      model_specs=[sobol_model_spec],
                  ),
                  GenerationNode(
                      node_name="node_1",
                      model_specs=[sobol_model_spec],
                  ),
              ],
          )
      # check error raised if transition to arguemnt is not valid
      with self.assertRaisesRegex(
          GenerationStrategyMisconfiguredException,
          "`transition_to` argument",
      ):
          GenerationStrategy(
              nodes=[
                  GenerationNode(
                      node_name="node_1",
                      transition_criteria=node_1_criterion,
                      model_specs=[sobol_model_spec],
                  ),
                  GenerationNode(
                      node_name="node_3",
                      model_specs=[sobol_model_spec],
                  ),
              ],
          )
  
      # check error raised if provided both steps and nodes
      with self.assertRaisesRegex(
          GenerationStrategyMisconfiguredException,
          "either steps or nodes",
      ):
          GenerationStrategy(
              nodes=[
                  GenerationNode(
                      node_name="node_1",
                      transition_criteria=node_1_criterion,
                      model_specs=[sobol_model_spec],
                  ),
                  GenerationNode(
                      node_name="node_3",
                      model_specs=[sobol_model_spec],
                  ),
              ],
              steps=[
                  GenerationStep(
                      model=Models.SOBOL,
                      num_trials=5,
                      model_kwargs=self.step_model_kwargs,
                  ),
                  GenerationStep(
                      model=Models.GPEI,
                      num_trials=-1,
                      model_kwargs=self.step_model_kwargs,
                  ),
              ],
          )
  
      # check error raised if provided both steps and nodes under node list
      with self.assertRaisesRegex(
          GenerationStrategyMisconfiguredException,
          "must either be a GenerationStep",
      ):
          GenerationStrategy(
              nodes=[
                  GenerationNode(
                      node_name="node_1",
                      transition_criteria=node_1_criterion,
                      model_specs=[sobol_model_spec],
                  ),
                  GenerationStep(
                      model=Models.SOBOL,
                      num_trials=5,
                      model_kwargs=self.step_model_kwargs,
                  ),
                  GenerationNode(
                      node_name="node_2",
                      model_specs=[sobol_model_spec],
                  ),
              ],
          )
      # check that warning is logged if no nodes have transition arguments
      with self.assertLogs(
          GenerationStrategy.__module__, logging.WARNING
      ) as logger:
          warning_msg = (
              "None of the nodes in this GenerationStrategy "
              "contain a `transition_to` argument in their transition_criteria. "
          )
          GenerationStrategy(
              nodes=[
                  GenerationNode(
                      node_name="node_1",
                      model_specs=[sobol_model_spec],
                  ),
                  GenerationNode(
                      node_name="node_3",
                      model_specs=[sobol_model_spec],
                  ),
              ],
          )
          self.assertTrue(
              any(warning_msg in output for output in logger.output),
              logger.output,
          )
  
imports: import logging
  from typing import cast, List
  from unittest import mock
  from unittest.mock import MagicMock, patch
  from ax.core.arm import Arm
  from ax.core.base_trial import TrialStatus
  from ax.core.experiment import Experiment
  from ax.core.generator_run import GeneratorRun
  from ax.core.observation import ObservationFeatures
  from ax.core.parameter import ChoiceParameter, FixedParameter, Parameter, ParameterType
  from ax.core.search_space import SearchSpace
  from ax.core.utils import get_pending_observation_features_based_on_trial_status
  from ax.exceptions.core import DataRequiredError, UnsupportedError, UserInputError
  from ax.exceptions.generation_strategy import GenerationStrategyCompleted, GenerationStrategyMisconfiguredException, GenerationStrategyRepeatedPoints, MaxParallelismReachedException
  from ax.modelbridge.discrete import DiscreteModelBridge
  from ax.modelbridge.factory import get_sobol
  from ax.modelbridge.generation_node import GenerationNode
  from ax.modelbridge.generation_strategy import GenerationStep, GenerationStrategy
  from ax.modelbridge.model_spec import ModelSpec
  from ax.modelbridge.random import RandomModelBridge
  from ax.modelbridge.registry import Cont_X_trans, MODEL_KEY_TO_MODEL_SETUP, Models
  from ax.modelbridge.torch import TorchModelBridge
  from ax.modelbridge.transition_criterion import MaxGenerationParallelism, MaxTrials, MinTrials
  from ax.models.random.sobol import SobolGenerator
  from ax.utils.common.equality import same_elements
  from ax.utils.common.mock import mock_patch_method_original
  from ax.utils.common.testutils import TestCase
  from ax.utils.common.typeutils import not_none
  from ax.utils.testing.core_stubs import get_branin_data, get_branin_experiment, get_choice_parameter, get_data, get_experiment_with_multi_objective, get_hierarchical_search_space_experiment
label_desc: Use image node_id 28 for calling the TestGenerationStrategy obj's underlying member method code with example usage: obj.test_gs_setup_with_nodes() without return types