/* * Copyright (c) MuleSoft, Inc. All rights reserved. http://www.mulesoft.com * The software in this package is published under the terms of the CPAL v1.0 * license, a copy of which has been included with this distribution in the * LICENSE.txt file. */ package org.mule.test.module.extension.internal.util; import static com.google.common.collect.ImmutableSet.copyOf; import static java.util.Arrays.asList; import static java.util.Collections.emptySet; import static java.util.Optional.empty; import static java.util.Optional.of; import static org.apache.commons.lang.ArrayUtils.isEmpty; import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.instanceOf; import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertThat; import static org.mockito.Answers.RETURNS_DEEP_STUBS; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.same; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import static org.mockito.Mockito.withSettings; import static org.mule.metadata.api.model.MetadataFormat.JAVA; import static org.mule.metadata.api.utils.MetadataTypeUtils.getTypeId; import static org.mule.metadata.java.api.utils.JavaTypeUtils.getType; import static org.mule.runtime.api.meta.model.parameter.ParameterGroupModel.DEFAULT_GROUP_NAME; import static org.mule.runtime.api.meta.model.parameter.ParameterRole.BEHAVIOUR; import org.mule.metadata.api.ClassTypeLoader; import org.mule.metadata.api.builder.ArrayTypeBuilder; import org.mule.metadata.api.builder.BaseTypeBuilder; import org.mule.metadata.api.builder.TypeBuilder; import org.mule.metadata.api.model.ArrayType; import org.mule.metadata.api.model.MetadataType; import org.mule.metadata.api.model.ObjectType; import org.mule.metadata.java.api.handler.TypeHandlerManager; import org.mule.metadata.java.api.utils.ParsingContext; import org.mule.metadata.message.MessageMetadataType; import org.mule.runtime.api.message.Message; import org.mule.runtime.api.meta.model.EnrichableModel; import org.mule.runtime.api.meta.model.ExtensionModel; import org.mule.runtime.api.meta.model.ModelProperty; import org.mule.runtime.api.meta.model.ParameterDslConfiguration; import org.mule.runtime.api.meta.model.SubTypesModel; import org.mule.runtime.api.meta.model.config.ConfigurationModel; import org.mule.runtime.api.meta.model.declaration.fluent.ParameterDeclaration; import org.mule.runtime.api.meta.model.declaration.fluent.ParameterGroupDeclaration; import org.mule.runtime.api.meta.model.declaration.fluent.ParameterizedDeclaration; import org.mule.runtime.api.meta.model.operation.OperationModel; import org.mule.runtime.api.meta.model.parameter.ParameterGroupModel; import org.mule.runtime.api.meta.model.parameter.ParameterModel; import org.mule.runtime.api.meta.model.parameter.ParameterizedModel; import org.mule.runtime.core.api.Event; import org.mule.runtime.core.api.MuleContext; import org.mule.runtime.core.api.extension.ExtensionManager; import org.mule.runtime.core.api.registry.RegistrationException; import org.mule.runtime.core.internal.streaming.bytes.SimpleByteBufferManager; import org.mule.runtime.core.internal.streaming.bytes.factory.InMemoryCursorStreamProviderFactory; import org.mule.runtime.core.streaming.StreamingManager; import org.mule.runtime.core.streaming.bytes.CursorStreamProviderFactory; import org.mule.runtime.core.streaming.bytes.InMemoryCursorStreamConfig; import org.mule.runtime.extension.api.declaration.type.ExtensionsTypeHandlerManagerFactory; import org.mule.runtime.extension.api.declaration.type.ExtensionsTypeLoaderFactory; import org.mule.runtime.extension.api.exception.IllegalModelDefinitionException; import org.mule.runtime.extension.api.loader.ExtensionModelValidator; import org.mule.runtime.extension.api.loader.ProblemsReporter; import org.mule.runtime.extension.api.metadata.MetadataResolverFactory; import org.mule.runtime.extension.api.runtime.ConfigurationInstance; import org.mule.runtime.extension.api.runtime.InterceptorFactory; import org.mule.runtime.extension.api.runtime.config.ConfigurationFactory; import org.mule.runtime.extension.api.runtime.exception.ExceptionHandlerFactory; import org.mule.runtime.extension.api.runtime.operation.OperationExecutorFactory; import org.mule.runtime.module.extension.internal.loader.java.property.ClassLoaderModelProperty; import org.mule.runtime.module.extension.internal.loader.java.property.ConfigTypeModelProperty; import org.mule.runtime.module.extension.internal.loader.java.property.ConfigurationFactoryModelProperty; import org.mule.runtime.module.extension.internal.loader.java.property.ConnectivityModelProperty; import org.mule.runtime.module.extension.internal.loader.java.property.ExceptionHandlerModelProperty; import org.mule.runtime.module.extension.internal.loader.java.property.InterceptorsModelProperty; import org.mule.runtime.module.extension.internal.loader.java.property.MetadataResolverFactoryModelProperty; import org.mule.runtime.module.extension.internal.loader.java.property.OperationExecutorModelProperty; import org.mule.runtime.module.extension.internal.loader.java.property.ParameterGroupModelProperty; import org.mule.runtime.module.extension.internal.runtime.resolver.ValueResolver; import org.mule.runtime.module.extension.internal.runtime.resolver.ValueResolvingContext; import org.mule.runtime.module.extension.internal.util.MuleExtensionUtils; import com.google.common.collect.ImmutableList; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Optional; import org.custommonkey.xmlunit.DetailedDiff; import org.custommonkey.xmlunit.Diff; import org.custommonkey.xmlunit.Difference; import org.custommonkey.xmlunit.XMLUnit; import org.hamcrest.Matcher; public final class ExtensionsTestUtils { public static final ClassTypeLoader TYPE_LOADER = ExtensionsTypeLoaderFactory.getDefault().createTypeLoader(); public static final BaseTypeBuilder TYPE_BUILDER = BaseTypeBuilder.create(JAVA); public static final String HELLO_WORLD = "Hello World!"; private ExtensionsTestUtils() {} public static MetadataType toMetadataType(Class<?> type) { return TYPE_LOADER.load(type); } public static ProblemsReporter validate(Class<?> clazz, ExtensionModelValidator validator) { return validate(MuleExtensionUtils.loadExtension(clazz), validator); } public static ProblemsReporter validate(ExtensionModel model, ExtensionModelValidator validator) { ProblemsReporter problemsReporter = new ProblemsReporter(model); validator.validate(model, problemsReporter); if (problemsReporter.hasErrors()) { throw new IllegalModelDefinitionException(problemsReporter.toString()); } return problemsReporter; } public static ArrayType arrayOf(Class<? extends Collection> clazz, TypeBuilder itemType) { ArrayTypeBuilder arrayTypeBuilder = TYPE_BUILDER.arrayType(); arrayTypeBuilder.id(clazz.getName()); arrayTypeBuilder.of(itemType); return arrayTypeBuilder.build(); } public static ObjectType dictionaryOf(Class<? extends Map> clazz, TypeBuilder<?> valueTypeBuilder) { return TYPE_BUILDER.objectType().id(clazz.getName()).openWith(valueTypeBuilder).build(); } public static TypeBuilder<?> objectTypeBuilder(Class<?> clazz) { BaseTypeBuilder typeBuilder = BaseTypeBuilder.create(JAVA); final TypeHandlerManager typeHandlerManager = new ExtensionsTypeHandlerManagerFactory() .createTypeHandlerManager(); typeHandlerManager.handle(clazz, new ParsingContext(), typeBuilder); return typeBuilder; } public static ValueResolver getResolver(Object value) throws Exception { return getResolver(value, null, true); } public static ValueResolver getResolver(Object value, ValueResolvingContext context, boolean dynamic, Class<?>... extraInterfaces) throws Exception { ValueResolver resolver; if (isEmpty(extraInterfaces)) { resolver = mock(ValueResolver.class); } else { resolver = mock(ValueResolver.class, withSettings().extraInterfaces(extraInterfaces)); } when(resolver.resolve(context != null ? same(context) : any(ValueResolvingContext.class))).thenReturn(value); when(resolver.isDynamic()).thenReturn(dynamic); return resolver; } public static void assertMessageType(MetadataType type, MetadataType payloadType, MetadataType attributesType) { assertThat(type, is(instanceOf(MessageMetadataType.class))); assertThat(getTypeId(type).get(), is(Message.class.getName())); MessageMetadataType messageType = (MessageMetadataType) type; assertThat(messageType.getPayloadType().get(), equalTo(payloadType)); assertThat(messageType.getAttributesType().get(), equalTo(attributesType)); } public static void assertMessageType(MetadataType type, Matcher payloadMatch, Matcher attributesMatcher) { assertThat(type, is(instanceOf(MessageMetadataType.class))); assertThat(getTypeId(type).get(), is(Message.class.getName())); MessageMetadataType messageType = (MessageMetadataType) type; assertThat(messageType.getPayloadType().get(), payloadMatch); assertThat(messageType.getAttributesType().get(), attributesMatcher); } public static ParameterModel getParameter(String name, Class<?> type) { ParameterModel parameterModel = getParameter(); when(parameterModel.getName()).thenReturn(name); when(parameterModel.getType()).thenReturn(toMetadataType(type)); when(parameterModel.getLayoutModel()).thenReturn(empty()); return parameterModel; } public static ParameterModel getParameter(String name, MetadataType metadataType) { ParameterModel parameterModel = getParameter(); when(parameterModel.getName()).thenReturn(name); when(parameterModel.getType()).thenReturn(metadataType); return parameterModel; } private static ParameterModel getParameter() { ParameterModel parameterModel = mock(ParameterModel.class); when(parameterModel.getModelProperty(any())).thenReturn(Optional.empty()); when(parameterModel.getDslConfiguration()).thenReturn(ParameterDslConfiguration.getDefaultInstance()); when(parameterModel.getRole()).thenReturn(BEHAVIOUR); return parameterModel; } public static void stubRegistryKeys(MuleContext muleContext, final String... keys) { when(muleContext.getRegistry().get(anyString())).thenAnswer(invocation -> { String name = (String) invocation.getArguments()[0]; if (name != null) { for (String key : keys) { if (name.contains(key)) { return null; } } } return RETURNS_DEEP_STUBS.get().answer(invocation); }); } public static <C> C getConfigurationFromRegistry(String key, Event muleEvent, MuleContext muleContext) throws Exception { return (C) getConfigurationInstanceFromRegistry(key, muleEvent, muleContext).getValue(); } public static ConfigurationInstance getConfigurationInstanceFromRegistry(String key, Event muleEvent, MuleContext muleContext) throws Exception { ExtensionManager extensionManager = muleContext.getExtensionManager(); return extensionManager.getConfiguration(key, muleEvent); } /** * Receives to {@link String} representation of two XML files and verify that they are semantically equivalent * * @param expected the reference content * @param actual the actual content * @throws Exception if comparison fails */ public static void compareXML(String expected, String actual) throws Exception { XMLUnit.setNormalizeWhitespace(true); XMLUnit.setIgnoreWhitespace(true); XMLUnit.setIgnoreComments(true); XMLUnit.setIgnoreAttributeOrder(false); Diff diff = XMLUnit.compareXML(expected, actual); if (!(diff.similar() && diff.identical())) { System.out.println(actual); DetailedDiff detDiff = new DetailedDiff(diff); @SuppressWarnings("rawtypes") List differences = detDiff.getAllDifferences(); StringBuilder diffLines = new StringBuilder(); for (Object object : differences) { Difference difference = (Difference) object; diffLines.append(difference.toString() + '\n'); } throw new IllegalArgumentException("Actual XML differs from expected: \n" + diffLines.toString()); } } public static void mockClassLoaderModelProperty(ExtensionModel extensionModel, ClassLoader classLoader) { when(extensionModel.getModelProperty(ClassLoaderModelProperty.class)) .thenReturn(of(new ClassLoaderModelProperty(classLoader))); } public static void setRequires(EnrichableModel model, boolean requiresConfig, boolean requiresConnection) { if (requiresConfig) { when(model.getModelProperty(ConfigTypeModelProperty.class)).thenReturn(of(mock(ConfigTypeModelProperty.class))); } if (requiresConnection) { when(model.getModelProperty(ConnectivityModelProperty.class)).thenReturn(of(mock(ConnectivityModelProperty.class))); } } public static void mockSubTypes(ExtensionModel mockModel, SubTypesModel... subtypes) { if (isEmpty(subtypes)) { when(mockModel.getSubTypes()).thenReturn(emptySet()); } else { when(mockModel.getSubTypes()).thenReturn(copyOf(subtypes)); } } public static ParameterGroupModel mockParameters(ParameterizedModel parameterizedModel, ParameterModel... parameterModels) { return mockParameters(parameterizedModel, DEFAULT_GROUP_NAME, parameterModels); } public static ParameterGroupModel mockParameters(ParameterizedModel parameterizedModel, String groupName, ParameterModel... parameterModels) { ParameterGroupModel group = mock(ParameterGroupModel.class); when(group.getName()).thenReturn(groupName); when(group.getModelProperty(ParameterGroupModelProperty.class)).thenReturn(empty()); when(parameterizedModel.getParameterGroupModels()).thenReturn(asList(group)); when(group.getParameterModels()).thenReturn(asList(parameterModels)); when(parameterizedModel.getAllParameterModels()).thenReturn(asList(parameterModels)); return group; } public static ParameterGroupDeclaration mockParameters(ParameterizedDeclaration declaration, ParameterDeclaration... parameters) { return mockParameters(declaration, DEFAULT_GROUP_NAME, parameters); } public static ParameterGroupDeclaration mockParameters(ParameterizedDeclaration declaration, String groupName, ParameterDeclaration... parameters) { ParameterGroupDeclaration group = mock(ParameterGroupDeclaration.class); when(group.getName()).thenReturn(groupName); when(declaration.getParameterGroups()).thenReturn(asList(group)); when(declaration.getParameterGroup(groupName)).thenReturn(group); List<ParameterDeclaration> params = new ArrayList<>(asList(parameters)); when(group.getParameters()).thenReturn(params); when(declaration.getAllParameters()).thenReturn(params); return group; } public static void mockExceptionEnricher(EnrichableModel enrichableModel, ExceptionHandlerFactory exceptionHandlerFactory) { Optional<ExceptionHandlerModelProperty> property = exceptionHandlerFactory != null ? of(new ExceptionHandlerModelProperty(exceptionHandlerFactory)) : empty(); when(enrichableModel.getModelProperty(ExceptionHandlerModelProperty.class)).thenReturn(property); } public static void mockInterceptors(EnrichableModel enrichableModel, List<InterceptorFactory> interceptorFactories) { if (interceptorFactories == null) { interceptorFactories = ImmutableList.of(); } when(enrichableModel.getModelProperty(InterceptorsModelProperty.class)) .thenReturn(of(new InterceptorsModelProperty(interceptorFactories))); } public static void mockConfigurationInstance(ConfigurationModel configurationModel, Object config) { ConfigurationFactory configurationFactory = mock(ConfigurationFactory.class); when(configurationFactory.newInstance()).thenReturn(config); when(configurationFactory.getObjectType()).thenReturn((Class) config.getClass()); when(configurationModel.getModelProperty(any())).thenAnswer(invocationOnMock -> { Class<? extends ModelProperty> propertyType = (Class<? extends ModelProperty>) invocationOnMock.getArguments()[0]; if (ConfigurationFactoryModelProperty.class.equals(propertyType)) { return of(new ConfigurationFactoryModelProperty(configurationFactory)); } return empty(); }); } public static void mockMetadataResolverFactory(EnrichableModel model, MetadataResolverFactory factory) { Optional<MetadataResolverFactoryModelProperty> property = factory != null ? of(new MetadataResolverFactoryModelProperty(factory)) : empty(); when(model.getModelProperty(MetadataResolverFactoryModelProperty.class)).thenReturn(property); } public static void mockExecutorFactory(OperationModel operationModel, OperationExecutorFactory operationExecutorFactory) { when(operationModel.getModelProperty(OperationExecutorModelProperty.class)) .thenReturn(of(new OperationExecutorModelProperty(operationExecutorFactory))); } public static CursorStreamProviderFactory getDefaultCursorStreamProviderFactory(MuleContext muleContext) { try { return muleContext.getRegistry().lookupObject(StreamingManager.class).forBytes().getDefaultCursorProviderFactory(); } catch (RegistrationException e) { throw new RuntimeException(e); } } public static CursorStreamProviderFactory getDefaultCursorStreamProviderFactory() { return new InMemoryCursorStreamProviderFactory(new SimpleByteBufferManager(), InMemoryCursorStreamConfig.getDefault()); } public static void assertType(MetadataType metadataType, Class<?> expectedRawType, Class<? extends MetadataType> typeQualifier) { assertThat(metadataType, is(instanceOf(typeQualifier))); assertThat(expectedRawType.isAssignableFrom(getType(metadataType)), is(true)); } }