private AnnotationAttributes assertComponentScanAttributes(Class<?> element, String... expected) {
    AnnotationAttributes attributes = findMergedAnnotationAttributes(element, ComponentScan.class);

    assertNotNull("Should find @ComponentScan on " + element, attributes);
    assertArrayEquals("value: ", expected, attributes.getStringArray("value"));
    assertArrayEquals("basePackages: ", expected, attributes.getStringArray("basePackages"));

    return attributes;
  }
  private void assertGetMergedAnnotation(Class<?> element, String... expected) {
    String name = ContextConfig.class.getName();
    ContextConfig contextConfig = getMergedAnnotation(element, ContextConfig.class);

    assertNotNull("Should find @ContextConfig on " + element.getSimpleName(), contextConfig);
    assertArrayEquals("locations", expected, contextConfig.locations());
    assertArrayEquals("value", expected, contextConfig.value());
    assertArrayEquals("classes", new Class<?>[0], contextConfig.classes());

    // Verify contracts between utility methods:
    assertTrue(isAnnotated(element, name));
  }
  @Test
  public void getMergedAnnotationAttributesWithAliasedValueComposedAnnotation() {
    Class<?> element = AliasedValueComposedContextConfigClass.class;
    String name = ContextConfig.class.getName();
    AnnotationAttributes attributes = getMergedAnnotationAttributes(element, name);

    assertNotNull("Should find @ContextConfig on " + element.getSimpleName(), attributes);
    assertArrayEquals("locations", asArray("test.xml"), attributes.getStringArray("locations"));
    assertArrayEquals("value", asArray("test.xml"), attributes.getStringArray("value"));

    // Verify contracts between utility methods:
    assertTrue(isAnnotated(element, name));
  }
  @Test
  public void
      findMergedAnnotationWithLocalAliasesThatConflictWithAttributesInMetaAnnotationByConvention() {
    final String[] EMPTY = new String[0];
    Class<?> element = SpringAppConfigClass.class;
    ContextConfig contextConfig = findMergedAnnotation(element, ContextConfig.class);

    assertNotNull("Should find @ContextConfig on " + element, contextConfig);
    assertArrayEquals("locations for " + element, EMPTY, contextConfig.locations());
    // 'value' in @SpringAppConfig should not override 'value' in @ContextConfig
    assertArrayEquals("value for " + element, EMPTY, contextConfig.value());
    assertArrayEquals(
        "classes for " + element, new Class<?>[] {Number.class}, contextConfig.classes());
  }
  @Test
  public void getMergedAnnotationWithImplicitAliasesInMetaAnnotationOnComposedAnnotation() {
    Class<?> element = ComposedImplicitAliasesContextConfigClass.class;
    String name = ImplicitAliasesContextConfig.class.getName();
    ImplicitAliasesContextConfig config =
        getMergedAnnotation(element, ImplicitAliasesContextConfig.class);
    String[] expected = asArray("A.xml", "B.xml");

    assertNotNull(
        "Should find @ImplicitAliasesContextConfig on " + element.getSimpleName(), config);
    assertArrayEquals("groovyScripts", expected, config.groovyScripts());
    assertArrayEquals("xmlFiles", expected, config.xmlFiles());
    assertArrayEquals("locations", expected, config.locations());
    assertArrayEquals("value", expected, config.value());

    // Verify contracts between utility methods:
    assertTrue(isAnnotated(element, name));
  }
  private void getMergedAnnotationAttributesWithHalfConventionBasedAndHalfAliasedComposedAnnotation(
      Class<?> clazz) {
    String[] expected = asArray("explicitDeclaration");
    String name = ContextConfig.class.getName();
    String simpleName = clazz.getSimpleName();
    AnnotationAttributes attributes = getMergedAnnotationAttributes(clazz, name);

    assertNotNull("Should find @ContextConfig on " + simpleName, attributes);
    assertArrayEquals(
        "locations for class [" + clazz.getSimpleName() + "]",
        expected,
        attributes.getStringArray("locations"));
    assertArrayEquals(
        "value for class [" + clazz.getSimpleName() + "]",
        expected,
        attributes.getStringArray("value"));

    // Verify contracts between utility methods:
    assertTrue(isAnnotated(clazz, name));
  }
  @Test
  public void findMergedAnnotationForMultipleMetaAnnotationsWithClashingAttributeNames() {
    String[] xmlLocations = asArray("test.xml");
    String[] propFiles = asArray("test.properties");

    Class<?> element = AliasedComposedContextConfigAndTestPropSourceClass.class;

    ContextConfig contextConfig = findMergedAnnotation(element, ContextConfig.class);
    assertNotNull("@ContextConfig on " + element, contextConfig);
    assertArrayEquals("locations", xmlLocations, contextConfig.locations());
    assertArrayEquals("value", xmlLocations, contextConfig.value());

    // Synthesized annotation
    TestPropSource testPropSource = AnnotationUtils.findAnnotation(element, TestPropSource.class);
    assertArrayEquals("locations", propFiles, testPropSource.locations());
    assertArrayEquals("value", propFiles, testPropSource.value());

    // Merged annotation
    testPropSource = findMergedAnnotation(element, TestPropSource.class);
    assertNotNull("@TestPropSource on " + element, testPropSource);
    assertArrayEquals("locations", propFiles, testPropSource.locations());
    assertArrayEquals("value", propFiles, testPropSource.value());
  }
 private void assertWebMapping(AnnotatedElement element) throws ArrayComparisonFailure {
   WebMapping webMapping = findMergedAnnotation(element, WebMapping.class);
   assertNotNull(webMapping);
   assertArrayEquals("value attribute: ", asArray("/test"), webMapping.value());
   assertArrayEquals("path attribute: ", asArray("/test"), webMapping.path());
 }