/*
* 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.runtime.module.extension.internal.runtime.operation;
import static java.nio.charset.Charset.defaultCharset;
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.StringUtils.EMPTY;
import static org.mockito.Answers.RETURNS_DEEP_STUBS;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyObject;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.mule.runtime.api.meta.model.parameter.ParameterRole.BEHAVIOUR;
import static org.mule.runtime.api.meta.model.parameter.ParameterRole.CONTENT;
import static org.mule.runtime.api.util.ExtensionModelTestUtils.visitableMock;
import static org.mule.runtime.core.api.config.MuleProperties.OBJECT_CONNECTION_MANAGER;
import static org.mule.runtime.core.api.config.MuleProperties.OBJECT_STREAMING_MANAGER;
import static org.mule.runtime.module.extension.internal.runtime.resolver.ValueResolvingContext.from;
import static org.mule.test.module.extension.internal.util.ExtensionsTestUtils.getDefaultCursorStreamProviderFactory;
import static org.mule.test.module.extension.internal.util.ExtensionsTestUtils.mockClassLoaderModelProperty;
import static org.mule.test.module.extension.internal.util.ExtensionsTestUtils.mockExceptionEnricher;
import static org.mule.test.module.extension.internal.util.ExtensionsTestUtils.mockExecutorFactory;
import static org.mule.test.module.extension.internal.util.ExtensionsTestUtils.mockMetadataResolverFactory;
import static org.mule.test.module.extension.internal.util.ExtensionsTestUtils.mockParameters;
import static org.mule.test.module.extension.internal.util.ExtensionsTestUtils.mockSubTypes;
import static org.mule.test.module.extension.internal.util.ExtensionsTestUtils.setRequires;
import static org.mule.test.module.extension.internal.util.ExtensionsTestUtils.toMetadataType;
import static reactor.core.publisher.Mono.just;
import org.mule.metadata.api.model.StringType;
import org.mule.runtime.api.lifecycle.Disposable;
import org.mule.runtime.api.lifecycle.Initialisable;
import org.mule.runtime.api.lifecycle.Lifecycle;
import org.mule.runtime.api.lifecycle.Startable;
import org.mule.runtime.api.lifecycle.Stoppable;
import org.mule.runtime.api.meta.model.ExtensionModel;
import org.mule.runtime.api.meta.model.OutputModel;
import org.mule.runtime.api.meta.model.XmlDslModel;
import org.mule.runtime.api.meta.model.config.ConfigurationModel;
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.metadata.DataType;
import org.mule.runtime.api.metadata.MediaType;
import org.mule.runtime.api.metadata.TypedValue;
import org.mule.runtime.core.api.Event;
import org.mule.runtime.core.api.MuleContext;
import org.mule.runtime.core.api.context.MuleContextAware;
import org.mule.runtime.core.api.extension.ExtensionManager;
import org.mule.runtime.core.internal.message.InternalMessage;
import org.mule.runtime.core.internal.connection.ConnectionManagerAdapter;
import org.mule.runtime.core.internal.connection.ConnectionProviderWrapper;
import org.mule.runtime.core.internal.streaming.DefaultStreamingManager;
import org.mule.runtime.core.policy.OperationExecutionFunction;
import org.mule.runtime.core.policy.OperationPolicy;
import org.mule.runtime.core.policy.PolicyManager;
import org.mule.runtime.core.retry.policies.NoRetryPolicyTemplate;
import org.mule.runtime.core.streaming.bytes.CursorStreamProviderFactory;
import org.mule.runtime.extension.api.declaration.type.ExtensionsTypeLoaderFactory;
import org.mule.runtime.extension.api.metadata.MetadataResolverFactory;
import org.mule.runtime.extension.api.metadata.NullMetadataResolver;
import org.mule.runtime.extension.api.model.ImmutableOutputModel;
import org.mule.runtime.extension.api.runtime.ConfigurationInstance;
import org.mule.runtime.extension.api.runtime.ConfigurationProvider;
import org.mule.runtime.extension.api.runtime.exception.ExceptionHandlerFactory;
import org.mule.runtime.extension.api.runtime.operation.OperationExecutor;
import org.mule.runtime.extension.api.runtime.operation.OperationExecutorFactory;
import org.mule.runtime.extension.internal.property.MetadataKeyIdModelProperty;
import org.mule.runtime.extension.internal.property.MetadataKeyPartModelProperty;
import org.mule.runtime.module.extension.internal.loader.java.property.InterceptorsModelProperty;
import org.mule.runtime.module.extension.internal.loader.java.property.QueryParameterModelProperty;
import org.mule.runtime.module.extension.internal.runtime.exception.NullExceptionHandler;
import org.mule.runtime.module.extension.internal.runtime.resolver.ResolverSet;
import org.mule.runtime.module.extension.internal.runtime.resolver.ResolverSetResult;
import org.mule.tck.junit4.AbstractMuleContextTestCase;
import org.mule.test.metadata.extension.resolver.TestNoConfigMetadataResolver;
import java.util.Map;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public abstract class AbstractOperationMessageProcessorTestCase extends AbstractMuleContextTestCase {
protected static final String EXTENSION_NAMESPACE = "extension_namespace";
protected static final String CONFIG_NAME = "config";
protected static final String OPERATION_NAME = "operation";
protected static final String TARGET_VAR = "myFlowVar";
@Mock(answer = RETURNS_DEEP_STUBS)
protected ExtensionModel extensionModel;
@Mock(answer = RETURNS_DEEP_STUBS)
protected ConfigurationModel configurationModel;
@Mock(answer = RETURNS_DEEP_STUBS)
protected OperationModel operationModel;
@Mock
protected ExtensionManager extensionManager;
@Mock
protected ConnectionManagerAdapter connectionManagerAdapter;
@Mock
protected OperationExecutorFactory operationExecutorFactory;
@Mock(extraInterfaces = {Lifecycle.class, MuleContextAware.class})
protected OperationExecutor operationExecutor;
@Mock(answer = RETURNS_DEEP_STUBS)
protected ResolverSet resolverSet;
@Mock
protected ResolverSetResult parameters;
protected Event event;
@Mock(answer = RETURNS_DEEP_STUBS)
protected InternalMessage message;
@Mock(answer = RETURNS_DEEP_STUBS)
protected MuleContext context;
@Mock
protected ConfigurationInstance configurationInstance;
@Mock
protected Object configuration;
@Mock
protected ExceptionHandlerFactory exceptionHandlerFactory;
@Mock
protected MetadataResolverFactory metadataResolverFactory;
@Mock
protected ConnectionProviderWrapper connectionProviderWrapper;
@Mock
protected ParameterModel contentMock;
@Mock
protected ParameterModel keyParamMock;
@Mock
protected OutputModel outputMock;
@Mock
protected StringType stringType;
@Mock
protected ConfigurationProvider configurationProvider;
protected ParameterGroupModel parameterGroupModel;
@Mock(answer = RETURNS_DEEP_STUBS)
protected PolicyManager mockPolicyManager;
protected OperationMessageProcessor messageProcessor;
protected CursorStreamProviderFactory cursorStreamProviderFactory;
protected String configurationName = CONFIG_NAME;
protected String target = EMPTY;
protected OperationPolicy mockOperationPolicy;
@Before
public void before() throws Exception {
muleContext.getRegistry().registerObject(OBJECT_STREAMING_MANAGER, new DefaultStreamingManager());
cursorStreamProviderFactory = getDefaultCursorStreamProviderFactory(muleContext);
event = configureEvent();
when(context.getInjector().inject(any())).thenAnswer(invocationOnMock -> {
final Object subject = invocationOnMock.getArguments()[0];
muleContext.getInjector().inject(subject);
return subject;
});
when(extensionModel.getName()).thenReturn(EXTENSION_NAMESPACE);
when(extensionModel.getConfigurationModels()).thenReturn(asList(configurationModel));
when(operationModel.getName()).thenReturn(getClass().getName());
when(operationModel.isBlocking()).thenReturn(true);
when(extensionModel.getXmlDslModel()).thenReturn(XmlDslModel.builder().setPrefix("test-extension").build());
when(operationModel.getOutput())
.thenReturn(new ImmutableOutputModel("Message.Payload", toMetadataType(String.class), false, emptySet()));
mockExecutorFactory(operationModel, operationExecutorFactory);
visitableMock(operationModel);
when(operationModel.getModelProperty(MetadataKeyIdModelProperty.class)).thenReturn(
of(new MetadataKeyIdModelProperty(ExtensionsTypeLoaderFactory
.getDefault().createTypeLoader()
.load(String.class), "someParam")));
setRequires(operationModel, true, true);
when(operationExecutorFactory.createExecutor(operationModel)).thenReturn(operationExecutor);
when(operationModel.getName()).thenReturn(OPERATION_NAME);
when(operationModel.getDisplayModel()).thenReturn(empty());
mockExceptionEnricher(operationModel, exceptionHandlerFactory);
when(exceptionHandlerFactory.createHandler()).thenReturn(new NullExceptionHandler());
mockMetadataResolverFactory(operationModel, metadataResolverFactory);
when(metadataResolverFactory.getKeyResolver()).thenReturn(new TestNoConfigMetadataResolver());
when(metadataResolverFactory.getInputResolver("content")).thenReturn(new TestNoConfigMetadataResolver());
when(metadataResolverFactory.getInputResolver("type")).thenReturn(new NullMetadataResolver());
when(metadataResolverFactory.getOutputResolver()).thenReturn(new TestNoConfigMetadataResolver());
when(metadataResolverFactory.getOutputAttributesResolver()).thenReturn(new TestNoConfigMetadataResolver());
when(metadataResolverFactory.getQueryEntityResolver()).thenReturn(new TestNoConfigMetadataResolver());
when(keyParamMock.getName()).thenReturn("type");
when(keyParamMock.getType()).thenReturn(stringType);
when(keyParamMock.getModelProperty(MetadataKeyPartModelProperty.class))
.thenReturn(of(new MetadataKeyPartModelProperty(0)));
when(keyParamMock.getRole()).thenReturn(BEHAVIOUR);
when(keyParamMock.getDisplayModel()).thenReturn(empty());
when(keyParamMock.getLayoutModel()).thenReturn(empty());
when(keyParamMock.getModelProperty(QueryParameterModelProperty.class)).thenReturn(empty());
when(contentMock.getName()).thenReturn("content");
when(contentMock.hasDynamicType()).thenReturn(true);
when(contentMock.getType()).thenReturn(stringType);
when(contentMock.getRole()).thenReturn(CONTENT);
when(contentMock.getDisplayModel()).thenReturn(empty());
when(contentMock.getLayoutModel()).thenReturn(empty());
when(contentMock.getModelProperty(MetadataKeyPartModelProperty.class)).thenReturn(empty());
when(contentMock.getModelProperty(QueryParameterModelProperty.class)).thenReturn(empty());
parameterGroupModel = mockParameters(operationModel, keyParamMock, contentMock);
when(parameterGroupModel.getDisplayModel()).thenReturn(empty());
when(parameterGroupModel.getLayoutModel()).thenReturn(empty());
when(parameterGroupModel.getModelProperty(MetadataKeyIdModelProperty.class)).thenReturn(empty());
when(outputMock.getType()).thenReturn(stringType);
when(outputMock.hasDynamicType()).thenReturn(true);
when(operationModel.getOutput()).thenReturn(outputMock);
when(operationModel.getOutputAttributes()).thenReturn(outputMock);
when(operationModel.getModelProperty(InterceptorsModelProperty.class)).thenReturn(empty());
when(operationExecutorFactory.createExecutor(operationModel)).thenReturn(operationExecutor);
when(operationExecutor.execute(any())).thenReturn(just(""));
when(resolverSet.resolve(from(event))).thenReturn(parameters);
when(configurationInstance.getName()).thenReturn(CONFIG_NAME);
when(configurationInstance.getModel()).thenReturn(configurationModel);
when(configurationInstance.getValue()).thenReturn(configuration);
when(configurationInstance.getConnectionProvider()).thenReturn(of(connectionProviderWrapper));
when(configurationProvider.get(event)).thenReturn(configurationInstance);
when(configurationProvider.getConfigurationModel()).thenReturn(configurationModel);
when(configurationProvider.getName()).thenReturn(configurationName);
when(configurationModel.getOperationModels()).thenReturn(asList(operationModel));
when(configurationModel.getOperationModel(OPERATION_NAME)).thenReturn(of(operationModel));
when(connectionProviderWrapper.getRetryPolicyTemplate()).thenReturn(new NoRetryPolicyTemplate());
mockSubTypes(extensionModel);
mockClassLoaderModelProperty(extensionModel, getClass().getClassLoader());
when(extensionManager.getConfiguration(anyString(), anyObject())).thenReturn(configurationInstance);
when(extensionManager.getConfiguration(extensionModel, operationModel, event)).thenReturn(of(configurationInstance));
when(configurationProvider.get(anyObject())).thenReturn(configurationInstance);
when(extensionManager.getConfigurationProvider(extensionModel, operationModel)).thenReturn(of(configurationProvider));
when(extensionManager.getConfigurationProvider(CONFIG_NAME)).thenReturn(of(configurationProvider));
when(mockPolicyManager.createOperationPolicy(any(), any(), any(), any())).thenAnswer(invocationOnMock -> {
if (mockOperationPolicy == null) {
mockOperationPolicy = mock(OperationPolicy.class);
when(mockOperationPolicy.process(any()))
.thenAnswer(operationPolicyInvocationMock -> ((OperationExecutionFunction) invocationOnMock.getArguments()[3])
.execute((Map<String, Object>) invocationOnMock.getArguments()[2], (Event) invocationOnMock.getArguments()[1]));
}
return mockOperationPolicy;
});
when(connectionManagerAdapter.getConnection(anyString())).thenReturn(null);
when(connectionManagerAdapter.getDefaultRetryPolicyTemplate()).thenReturn(new NoRetryPolicyTemplate());
messageProcessor = setUpOperationMessageProcessor();
}
protected Event configureEvent() throws Exception {
when(message.getPayload())
.thenReturn(new TypedValue<Object>(TEST_PAYLOAD,
DataType.builder().mediaType(MediaType.create("*", "*", defaultCharset())).build()));
return eventBuilder().message(message).build();
}
protected OperationMessageProcessor setUpOperationMessageProcessor() throws Exception {
OperationMessageProcessor messageProcessor = createOperationMessageProcessor();
messageProcessor.setMuleContext(context);
muleContext.getRegistry().registerObject(OBJECT_CONNECTION_MANAGER, connectionManagerAdapter);
muleContext.getInjector().inject(messageProcessor);
messageProcessor.initialise();
return messageProcessor;
}
protected abstract OperationMessageProcessor createOperationMessageProcessor();
@Test
public void initialise() throws Exception {
verify((MuleContextAware) operationExecutor, atLeastOnce()).setMuleContext(any(MuleContext.class));
verify((Initialisable) operationExecutor).initialise();
}
@Test
public void start() throws Exception {
messageProcessor.start();
verify((Startable) operationExecutor).start();
}
@Test
public void stop() throws Exception {
messageProcessor.stop();
verify((Stoppable) operationExecutor).stop();
}
@Test
public void dispose() throws Exception {
messageProcessor.dispose();
verify((Disposable) operationExecutor).dispose();
}
}