private static void assertPropertiesSupported(
      ConfigurationMetadata<?> metadata,
      Set<String> propertyNames,
      boolean allowDeprecatedProperties) {
    Set<String> supportedProperties = new TreeSet<>();
    Set<String> nonDeprecatedProperties = new TreeSet<>();
    for (AttributeMetadata attribute : metadata.getAttributes().values()) {
      if (attribute.getInjectionPoint().getProperty() != null) {
        nonDeprecatedProperties.add(attribute.getInjectionPoint().getProperty());
        supportedProperties.add(attribute.getInjectionPoint().getProperty());
      }
      for (ConfigurationMetadata.InjectionPointMetaData deprecated :
          attribute.getLegacyInjectionPoints()) {
        supportedProperties.add(deprecated.getProperty());
      }
    }
    if (!supportedProperties.containsAll(propertyNames)) {
      TreeSet<String> unsupportedProperties = new TreeSet<>(propertyNames);
      unsupportedProperties.removeAll(supportedProperties);
      Assert.fail("Unsupported properties: " + unsupportedProperties);
    }

    // check for usage of deprecated properties
    if (!allowDeprecatedProperties && !nonDeprecatedProperties.containsAll(propertyNames)) {
      TreeSet<String> deprecatedProperties = new TreeSet<>(propertyNames);
      deprecatedProperties.removeAll(nonDeprecatedProperties);
      Assert.fail("Deprecated properties: " + deprecatedProperties);
    }
  }
  @SafeVarargs
  public static <T> void assertDeprecatedEquivalence(
      Class<T> configClass,
      Map<String, String> currentProperties,
      Map<String, String>... oldPropertiesList) {
    Assert.assertNotNull(configClass, "configClass");
    Assert.assertNotNull(currentProperties, "currentProperties");
    Assert.assertNotNull(oldPropertiesList, "oldPropertiesList");

    ConfigurationMetadata<T> metadata =
        ConfigurationMetadata.getValidConfigurationMetadata(configClass);

    // verify all current properties are supported and not deprecated
    assertPropertiesSupported(metadata, currentProperties.keySet(), false);

    // verify all old properties are supported (deprecation allowed)
    for (Map<String, String> evenOlderProperties : oldPropertiesList) {
      assertPropertiesSupported(metadata, evenOlderProperties.keySet(), true);
    }

    // verify that all deprecated properties are tested
    Set<String> knownDeprecatedProperties = new TreeSet<>();
    for (AttributeMetadata attribute : metadata.getAttributes().values()) {
      for (ConfigurationMetadata.InjectionPointMetaData deprecated :
          attribute.getLegacyInjectionPoints()) {
        knownDeprecatedProperties.add(deprecated.getProperty());
      }
    }
    Set<String> suppliedDeprecatedProperties = new TreeSet<>();
    for (Map<String, String> evenOlderProperties : oldPropertiesList) {
      suppliedDeprecatedProperties.addAll(evenOlderProperties.keySet());
    }
    if (!suppliedDeprecatedProperties.containsAll(knownDeprecatedProperties)) {
      TreeSet<String> untestedDeprecatedProperties = new TreeSet<>(knownDeprecatedProperties);
      untestedDeprecatedProperties.removeAll(suppliedDeprecatedProperties);
      Assert.fail("Untested deprecated properties: " + untestedDeprecatedProperties);
    }

    // verify property sets create equivalent configurations
    T currentConfiguration = newInstance(configClass, currentProperties);
    for (Map<String, String> evenOlderProperties : oldPropertiesList) {
      T evenOlderConfiguration = newInstance(configClass, evenOlderProperties);
      assertAttributesEqual(metadata, currentConfiguration, evenOlderConfiguration);
    }
  }