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.reindexing; 007 008import org.apache.camel.CamelContext; 009import org.apache.camel.EndpointInject; 010import org.apache.camel.Produce; 011import org.apache.camel.ProducerTemplate; 012import org.apache.camel.builder.AdviceWith; 013import org.apache.camel.builder.RouteBuilder; 014import org.apache.camel.component.mock.MockEndpoint; 015import org.apache.camel.model.ModelCamelContext; 016import org.apache.camel.model.TransformDefinition; 017import org.apache.camel.spring.javaconfig.CamelConfiguration; 018import org.apache.camel.util.ObjectHelper; 019import org.junit.BeforeClass; 020import org.junit.Test; 021import org.junit.runner.RunWith; 022import org.springframework.beans.factory.annotation.Autowired; 023import org.springframework.context.annotation.Bean; 024import org.springframework.context.annotation.ComponentScan; 025import org.springframework.context.annotation.Configuration; 026import org.springframework.test.annotation.DirtiesContext; 027import org.springframework.test.context.ContextConfiguration; 028import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 029import org.springframework.test.context.support.AnnotationConfigContextLoader; 030 031import java.net.InetAddress; 032import java.util.HashMap; 033import java.util.Map; 034 035import static org.apache.commons.lang3.StringUtils.isBlank; 036import static org.fcrepo.camel.FcrepoHeaders.FCREPO_URI; 037import static org.fcrepo.camel.reindexing.ReindexingHeaders.REINDEXING_RECIPIENTS; 038 039/** 040 * Test the route workflow. 041 * 042 * @author acoburn 043 * @since 2015-05-22 044 */ 045@RunWith(SpringJUnit4ClassRunner.class) 046@ContextConfiguration(classes = {RouteTest.ContextConfig.class}, loader = AnnotationConfigContextLoader.class) 047public class RouteTest { 048 049 private static final String restPrefix = "/reindexing"; 050 private static final String reindexingStream = "broker:queue:foo"; 051 private static final String baseUrl = "http://localhost/rest"; 052 private long ASSERT_PERIOD_MS = 5000; 053 054 @EndpointInject("mock:result") 055 protected MockEndpoint resultEndpoint; 056 057 @Produce("direct:start") 058 protected ProducerTemplate template; 059 060 @Autowired 061 private CamelContext camelContext; 062 063 @BeforeClass 064 public static void beforeClass() { 065 final String restPort = System.getProperty("fcrepo.dynamic.reindexing.port"); 066 if (!isBlank(restPort)) { 067 System.setProperty("reindexing.stream", reindexingStream); 068 System.setProperty("reindexing.rest.port", restPort); 069 System.setProperty("fcrepo.baseUrl", baseUrl); 070 071 } 072 System.setProperty("reindexing.rest.prefix", restPrefix); 073 } 074 075 @DirtiesContext 076 @Test 077 public void testUsageRoute() throws Exception { 078 079 final String restPort = System.getProperty("fcrepo.dynamic.reindexing.port", "9080"); 080 081 final var context = camelContext.adapt(ModelCamelContext.class); 082 083 AdviceWith.adviceWith(context, "FcrepoReindexingTraverse", a -> { 084 a.replaceFromWith("direct:traverse"); 085 a.mockEndpointsAndSkip("broker:*"); 086 a.mockEndpointsAndSkip("fcrepo:*"); 087 }); 088 089 AdviceWith.adviceWith(context, "FcrepoReindexingUsage", a -> { 090 a.weaveAddLast().to("mock:result"); 091 }); 092 093 resultEndpoint.expectedMessageCount(1); 094 resultEndpoint.message(0).body().contains("Fedora Reindexing Service"); 095 resultEndpoint.message(0).body().contains( 096 InetAddress.getLocalHost().getHostName() + ":" + restPort + restPrefix); 097 098 template.sendBody("direct:usage", null); 099 100 MockEndpoint.assertIsSatisfied(resultEndpoint); 101 } 102 103 @DirtiesContext 104 @Test 105 public void testReindexNoEndpointsRoute() throws Exception { 106 final String url = "http://localhost:8080/fcrepo/rest/foo"; 107 108 final var context = camelContext.adapt(ModelCamelContext.class); 109 110 AdviceWith.adviceWith(context, "FcrepoReindexingReindex", a -> { 111 a.mockEndpointsAndSkip(reindexingStream + "?disableTimeToLive=true"); 112 a.weaveByType(TransformDefinition.class).after().to("mock:result"); 113 }); 114 115 AdviceWith.adviceWith(context, "FcrepoReindexingTraverse", a -> { 116 a.replaceFromWith("direct:traverse"); 117 a.mockEndpointsAndSkip("broker:*"); 118 a.mockEndpointsAndSkip("fcrepo:*"); 119 }); 120 121 final var reindexingEndpoint = MockEndpoint.resolve(camelContext, "mock:" + reindexingStream); 122 reindexingEndpoint.expectedMessageCount(0); 123 reindexingEndpoint.setAssertPeriod(ASSERT_PERIOD_MS); 124 resultEndpoint.expectedMessageCount(1); 125 resultEndpoint.expectedHeaderReceived(FCREPO_URI, url); 126 resultEndpoint.expectedBodiesReceived("No endpoints configured for indexing"); 127 128 final Map<String, Object> headers = new HashMap<>(); 129 headers.put(FCREPO_URI, url); 130 headers.put(REINDEXING_RECIPIENTS, ""); 131 132 template.sendBodyAndHeaders("direct:reindex", null, headers); 133 134 MockEndpoint.assertIsSatisfied(resultEndpoint, reindexingEndpoint); 135 } 136 137 @DirtiesContext 138 @Test 139 public void testReindexWithEndpointsRoute() throws Exception { 140 final String url = "http://localhost:8080/fcrepo/rest/foo"; 141 142 final var context = camelContext.adapt(ModelCamelContext.class); 143 144 AdviceWith.adviceWith(context, "FcrepoReindexingReindex", a -> { 145 a.mockEndpointsAndSkip(reindexingStream + "?disableTimeToLive=true"); 146 a.weaveByType(TransformDefinition.class).after().to("mock:result"); 147 }); 148 149 AdviceWith.adviceWith(context, "FcrepoReindexingTraverse", a -> { 150 a.replaceFromWith("direct:traverse"); 151 a.mockEndpointsAndSkip("broker:*"); 152 a.mockEndpointsAndSkip("fcrepo:*"); 153 }); 154 155 final var reindexingEndpoint = MockEndpoint.resolve(camelContext, "mock:" + reindexingStream); 156 reindexingEndpoint.expectedMessageCount(1); 157 resultEndpoint.expectedMessageCount(1); 158 resultEndpoint.expectedHeaderReceived(FCREPO_URI, url); 159 resultEndpoint.expectedBodiesReceived("Indexing started at " + url); 160 161 final Map<String, Object> headers = new HashMap<>(); 162 headers.put(FCREPO_URI, url); 163 headers.put(REINDEXING_RECIPIENTS, "mock:endpoint"); 164 165 template.sendBodyAndHeaders("direct:reindex", null, headers); 166 167 MockEndpoint.assertIsSatisfied(resultEndpoint, reindexingEndpoint); 168 } 169 170 @DirtiesContext 171 @Test 172 public void testTraversal() throws Exception { 173 174 final String baseUrl = "http://localhost:8080/fcrepo4/rest"; 175 176 final var recipientsEndpoint = MockEndpoint.resolve(camelContext, "mock:direct:recipients"); 177 final var reindexingEndpoint = MockEndpoint.resolve(camelContext, "mock:" + reindexingStream); 178 179 recipientsEndpoint.expectedMessageCount(1); 180 reindexingEndpoint.expectedMessageCount(7); 181 reindexingEndpoint.expectedHeaderValuesReceivedInAnyOrder(FCREPO_URI, 182 baseUrl + "/foo/a", baseUrl + "/foo/b", baseUrl + "/foo/c", baseUrl + "/foo/d", baseUrl + "/foo/e", 183 baseUrl + "/foo/f", baseUrl + "/foo/g"); 184 185 final var context = camelContext.adapt(ModelCamelContext.class); 186 187 AdviceWith.adviceWith(context, "FcrepoReindexingTraverse", a -> { 188 a.replaceFromWith("direct:traverse"); 189 a.mockEndpointsAndSkip("fcrepo:*"); 190 a.mockEndpointsAndSkip(reindexingStream + "*"); 191 a.mockEndpointsAndSkip("direct:recipients"); 192 }); 193 194 template.sendBodyAndHeader("direct:traverse", ObjectHelper.loadResourceAsStream("indexable.nt"), 195 FCREPO_URI, "http://localhost:8080/fcrepo4/rest/foo"); 196 197 MockEndpoint.assertIsSatisfied(recipientsEndpoint, reindexingEndpoint); 198 } 199 200 @DirtiesContext 201 @Test 202 public void testRecipientList() throws Exception { 203 final String id = "/foo"; 204 205 206 final var context = camelContext.adapt(ModelCamelContext.class); 207 208 AdviceWith.adviceWith(context, "FcrepoReindexingTraverse", a -> { 209 a.replaceFromWith("direct:traverse"); 210 a.mockEndpointsAndSkip("broker:*"); 211 a.mockEndpointsAndSkip("fcrepo:*"); 212 }); 213 214 final var fooEndpoint = MockEndpoint.resolve(camelContext, "mock:foo"); 215 final var barEndpoint = MockEndpoint.resolve(camelContext, "mock:bar"); 216 217 fooEndpoint.expectedMessageCount(1); 218 fooEndpoint.expectedHeaderReceived(FCREPO_URI, baseUrl + id); 219 barEndpoint.expectedMessageCount(1); 220 barEndpoint.expectedHeaderReceived(FCREPO_URI, baseUrl + id); 221 222 final Map<String, Object> headers = new HashMap<>(); 223 headers.put(FCREPO_URI, baseUrl + id); 224 headers.put(REINDEXING_RECIPIENTS, "mock:foo,mock:bar"); 225 226 template.sendBodyAndHeaders("direct:recipients", null, headers); 227 228 MockEndpoint.assertIsSatisfied(fooEndpoint, barEndpoint); 229 } 230 231 @Configuration 232 @ComponentScan(basePackages = {"org.fcrepo.camel"}) 233 static class ContextConfig extends CamelConfiguration { 234 235 @Bean 236 public RouteBuilder route() { 237 return new ReindexingRouter(); 238 } 239 } 240}