code: def test_parameter_key_check(referenced_parameter, raises_exception):
      """Test that references to config parameters are validated correctly.
  
      Hyperopt parameters reference the config parameters they search with `.` notation to access different subsections,
      e.g. `trainer.learning_rate`. These are added to the config as arbitrary strings, and an invalid reference should be
      considered a validation error since we will otherwise search over an unused space or defer the error to train time.
      """
      config = {
          INPUT_FEATURES: [text_feature(name="in_feature")],
          OUTPUT_FEATURES: [binary_feature(name="out_feature")],
          HYPEROPT: {
              SEARCH_ALG: {TYPE: "random"},
              PARAMETERS: {
                  referenced_parameter: {
                      "space": "choice",
                      "categories": [1, 2, 3, 4],
                  }
              },
          },
      }
  
      if raises_exception:
          with pytest.raises(ConfigValidationError):
              ModelConfig.from_dict(config)
      else:
          ModelConfig.from_dict(config)
  
file_path: ludwig/tests/ludwig/config_validation/test_validate_config_hyperopt.py
imports: from itertools import repeat
  from unittest.mock import patch
  import pytest
  import ludwig.schema.hyperopt.parameter
  import ludwig.schema.hyperopt.scheduler
  import ludwig.schema.hyperopt.search_algorithm
  from ludwig.constants import EXECUTOR, HYPEROPT, INPUT_FEATURES, OUTPUT_FEATURES, PARAMETERS, SCHEDULER, SEARCH_ALG, TYPE
  from ludwig.error import ConfigValidationError
  from ludwig.schema.hyperopt import utils
  from ludwig.schema.model_types.base import ModelConfig
  from tests.integration_tests.utils import binary_feature, text_feature
label_desc: Use image node_id 4 for calling a global function with example usage: test_parameter_key_check(referenced_parameter, raises_exception) without return types