code: def test_clipper_property_validation():
      config = {
          "input_features": [
              category_feature(
                  encoder={"type": "dense", "vocab_size": 2},
                  reduce_input="sum",
              ),
              number_feature(),
          ],
          "output_features": [binary_feature()],
          "combiner": {
              "type": "tabnet",
          },
          TRAINER: {},
      }
      check_schema(config)
  
      # Test null/empty clipper:
      config[TRAINER]["gradient_clipping"] = None
      check_schema(config)
      config[TRAINER]["gradient_clipping"] = {}
      check_schema(config)
      assert (
          ECDTrainerConfig.Schema()
          .load(config[TRAINER])
          .gradient_clipping
          == ECDTrainerConfig.Schema().load({}).gradient_clipping
      )
  
      # Test invalid clipper type:
      config[TRAINER]["gradient_clipping"] = 0
      with pytest.raises(ConfigValidationError):
          check_schema(config)
      config[TRAINER]["gradient_clipping"] = "invalid"
      with pytest.raises(ConfigValidationError):
          check_schema(config)
  
      # Test that an optimizer's property types are enforced:
      config[TRAINER]["gradient_clipping"] = {"clipglobalnorm": None}
      check_schema(config)
      config[TRAINER]["gradient_clipping"] = {"clipglobalnorm": 1}
      check_schema(config)
      config[TRAINER]["gradient_clipping"] = {
          "clipglobalnorm": "invalid"
      }
      with pytest.raises(ConfigValidationError):
          check_schema(config)
  
      # Test extra keys are excluded and defaults are loaded appropriately:
      config[TRAINER]["gradient_clipping"] = {"clipnorm": 1}
      config[TRAINER]["gradient_clipping"]["extra_key"] = "invalid"
      assert not hasattr(
          ECDTrainerConfig.Schema()
          .load(config[TRAINER])
          .gradient_clipping,
          "extra_key",
      )
  
file_path: ludwig/tests/ludwig/config_validation/test_validate_config_trainer.py
imports: import pytest
  from ludwig.config_validation.validation import check_schema
  from ludwig.constants import TRAINER
  from ludwig.error import ConfigValidationError
  from ludwig.schema.optimizers import optimizer_registry
  from ludwig.schema.trainer import ECDTrainerConfig
  from tests.integration_tests.utils import binary_feature, category_feature, number_feature
label_desc: Use image node_id 4 for calling a global function with example usage: test_clipper_property_validation() without return types