001/*
002 * The contents of this file are subject to the license and copyright
003 * detailed in the LICENSE and NOTICE files at the root of the source
004 * tree.
005 */
006package org.fcrepo.camel.httpforwarding.integration;
007
008import com.github.tomakehurst.wiremock.WireMockServer;
009import com.github.tomakehurst.wiremock.client.WireMock;
010import com.github.tomakehurst.wiremock.core.WireMockConfiguration;
011import org.apache.camel.CamelContext;
012import org.apache.camel.EndpointInject;
013import org.apache.camel.Produce;
014import org.apache.camel.ProducerTemplate;
015import org.apache.camel.builder.AdviceWith;
016import org.apache.camel.component.activemq.ActiveMQComponent;
017import org.apache.camel.component.mock.MockEndpoint;
018import org.apache.camel.model.ModelCamelContext;
019import org.apache.camel.spring.javaconfig.CamelConfiguration;
020import org.junit.After;
021import org.junit.Before;
022import org.junit.BeforeClass;
023import org.junit.Test;
024import org.junit.runner.RunWith;
025import org.slf4j.Logger;
026import org.springframework.beans.factory.annotation.Autowired;
027import org.springframework.context.annotation.Bean;
028import org.springframework.context.annotation.ComponentScan;
029import org.springframework.context.annotation.Configuration;
030import org.springframework.test.annotation.DirtiesContext;
031import org.springframework.test.context.ContextConfiguration;
032import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
033import org.springframework.test.context.support.AnnotationConfigContextLoader;
034
035import static com.github.tomakehurst.wiremock.client.WireMock.equalTo;
036import static com.github.tomakehurst.wiremock.client.WireMock.ok;
037import static com.github.tomakehurst.wiremock.client.WireMock.post;
038import static com.github.tomakehurst.wiremock.client.WireMock.postRequestedFor;
039import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
040import static java.lang.Integer.parseInt;
041import static org.fcrepo.camel.httpforwarding.integration.TestUtils.getEvent;
042import static org.slf4j.LoggerFactory.getLogger;
043
044/**
045 * Test the route workflow.
046 *
047 * @author Aaron Coburn
048 * @since 2015-04-10
049 */
050@RunWith(SpringJUnit4ClassRunner.class)
051@ContextConfiguration(classes = {RouteUpdateIT.ContextConfig.class}, loader = AnnotationConfigContextLoader.class)
052public class RouteUpdateIT {
053
054    final private Logger logger = getLogger(RouteUpdateIT.class);
055
056    private static final String AS_NS = "https://www.w3.org/ns/activitystreams#";
057
058    private static final String MOCK_ENDPOINT = "/endpoint";
059
060    private static final String MOCKSERVER_PORT = System.getProperty(
061            "mockserver.dynamic.test.port", "8080");
062
063    private static final String FCREPO_PORT = System.getProperty(
064            "fcrepo.dynamic.test.port", "8080");
065
066    private static final String JMS_PORT = System.getProperty(
067            "fcrepo.dynamic.jms.port", "61616");
068
069    private String fullPath = "http://localhost:" + FCREPO_PORT + "/fcrepo/rest/" + "fake-identifier";
070
071
072    @EndpointInject("mock:result")
073    protected MockEndpoint resultEndpoint;
074
075    @Produce("direct:start")
076    protected ProducerTemplate template;
077
078    @Autowired
079    private CamelContext camelContext;
080
081    private WireMockServer mockServer;
082
083    @BeforeClass
084    public static void beforeClass() {
085        System.setProperty("http.enabled", "true");
086        System.setProperty("http.baseUrl", "http://localhost:" + MOCKSERVER_PORT + MOCK_ENDPOINT);
087        System.setProperty("jms.brokerUrl", "tcp://localhost:" + JMS_PORT);
088        System.setProperty("http.input.stream", "direct:start");
089        System.setProperty("http.reindex.stream", "direct:reindex");
090        System.setProperty("fcrepo.baseUrl", "http://localhost:" + FCREPO_PORT + "/fcrepo/rest");
091        System.setProperty("error.maxRedeliveries", "1");
092    }
093
094    @After
095    public void tearDownMockServer() {
096        logger.info("Stopping HTTP Server");
097        mockServer.stop();
098    }
099
100    @Before
101    public void setUpMockServer() throws Exception {
102        mockServer = new WireMockServer(WireMockConfiguration.options().port(parseInt(MOCKSERVER_PORT)));
103        mockServer.start();
104    }
105
106    @DirtiesContext
107    @Test
108    public void testAddedEventRouter() throws Exception {
109        final var mockServerEndpoint = "mock:http:localhost:" + MOCKSERVER_PORT + MOCK_ENDPOINT;
110        final var idMatcher = WireMock.matchingJsonPath("$.id", equalTo(fullPath));
111        final var typeMatcher = WireMock.matchingJsonPath("$.type", equalTo(AS_NS + "Update"));
112
113        // have the http server return a 200
114        mockServer.stubFor(post(urlEqualTo(MOCK_ENDPOINT)).willReturn(ok()));
115
116        final var context = camelContext.adapt(ModelCamelContext.class);
117
118        AdviceWith.adviceWith(context, "FcrepoHttpRouter", a -> a.mockEndpoints("*"));
119        AdviceWith.adviceWith(context, "FcrepoHttpAddType", a -> a.mockEndpoints("*"));
120        AdviceWith.adviceWith(context, "FcrepoHttpSend", a -> a.mockEndpoints("*"));
121
122        final var mockServerMockEndpoint = MockEndpoint.resolve(camelContext, mockServerEndpoint);
123        mockServerMockEndpoint.expectedMessageCount(1);
124        final var updateEndpoint = MockEndpoint.resolve(camelContext, "mock://direct:send.to.http");
125        updateEndpoint.expectedMessageCount(1);
126
127        logger.info("fullPath={}", fullPath);
128        template.sendBodyAndHeader(
129            "direct:start", getEvent(fullPath, AS_NS + "Update"), "org.fcrepo.jms.eventtype", AS_NS + "Update"
130        );
131
132        mockServer.verify(1, postRequestedFor(urlEqualTo(MOCK_ENDPOINT))
133            .withRequestBody(idMatcher.and(typeMatcher)));
134        MockEndpoint.assertIsSatisfied(mockServerMockEndpoint, updateEndpoint);
135    }
136
137    @Configuration
138    @ComponentScan(basePackages = "org.fcrepo.camel")
139    static class ContextConfig extends CamelConfiguration {
140        @Bean
141        public ActiveMQComponent broker() {
142            final var component = new ActiveMQComponent();
143            component.setBrokerURL("tcp://localhost:" + JMS_PORT);
144            return component;
145        }
146    }
147}