package com.geekbeast.rhizome.tests.bootstrap; import com.dataloom.retrofit.LoomByteConverterFactory; import com.dataloom.retrofit.LoomCallAdapterFactory; import com.dataloom.retrofit.LoomJacksonConverterFactory; import com.fasterxml.jackson.databind.ObjectMapper; import com.geekbeast.rhizome.tests.configurations.TestConfiguration; import com.geekbeast.rhizome.tests.controllers.SimpleControllerAPI; import com.geekbeast.rhizome.tests.pods.DispatcherServletsPod; import com.google.common.base.Optional; import com.google.common.net.HttpHeaders; import com.kryptnostic.rhizome.core.Cutting; import com.kryptnostic.rhizome.core.Rhizome; import com.kryptnostic.rhizome.pods.hazelcast.RegistryBasedHazelcastInstanceConfigurationPod; import digital.loom.rhizome.authentication.Auth0SecurityTestPod; import digital.loom.rhizome.authentication.Auth0TestPod; import digital.loom.rhizome.authentication.AuthenticationTest; import okhttp3.OkHttpClient; import okhttp3.Response; import org.apache.commons.lang3.RandomStringUtils; import org.apache.commons.lang3.RandomUtils; import org.apache.commons.lang3.StringUtils; import org.junit.AfterClass; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.BeansException; import org.springframework.http.HttpStatus; import retrofit2.Retrofit; import javax.ws.rs.core.MediaType; import java.io.IOException; public class RhizomeTests { private final static Logger logger = LoggerFactory.getLogger( RhizomeTests.class ); private static Retrofit adapter; public static final byte[] TEST_BYTES = RandomUtils.nextBytes( 1 << 12 ); private static Rhizome rhizome = null; private static TestConfiguration expected = null; @BeforeClass public static void plant() throws Exception { final String jwtToken = AuthenticationTest.authenticate().getCredentials().getIdToken(); rhizome = new Rhizome( Auth0TestPod.class, Auth0SecurityTestPod.class, DispatcherServletsPod.class, RegistryBasedHazelcastInstanceConfigurationPod.class ); rhizome.sprout(); logger.info( "Successfully started Rhizome microservice." ); /* * These interceptor are finicky and order dependent. Jetty doesn't do gzip unless content is long enough so * only verify gzip is enabled if contentLength > 2K. Exact value is tough since it is post compression. */ OkHttpClient httpClient = new OkHttpClient.Builder() .addInterceptor( chain -> { Response response = chain.proceed( chain.request() ); int responseCode = response.code(); if ( responseCode >= 200 && responseCode < 300 && response.body().contentLength() > 2048 ) { Assert.assertTrue( "Content encoding header must be present", response.headers().names().contains( HttpHeaders.CONTENT_ENCODING ) ); Assert.assertEquals( "gzip", response.headers().get( HttpHeaders.CONTENT_ENCODING ) ); } return response; } ) .addInterceptor( chain -> { Response response = chain.proceed( chain.request() ); if ( response.code() == HttpStatus.I_AM_A_TEAPOT.value() ) { Assert.assertTrue( StringUtils.startsWith( response.body().contentType().toString(), MediaType.TEXT_PLAIN ) ); return response.newBuilder().code( 200 ).build(); } return response; } ) .addInterceptor( chain -> chain .proceed( chain.request().newBuilder().addHeader( "Authorization", "Bearer " + jwtToken ) .build() ) ) .build(); adapter = new Retrofit.Builder().baseUrl( "http://localhost:8081/rhizome/api/" ).client( httpClient ) .addConverterFactory( new LoomByteConverterFactory() ) .addConverterFactory( new LoomJacksonConverterFactory() ) .addCallAdapterFactory( new LoomCallAdapterFactory() ).build(); SimpleControllerAPI api = adapter.create( SimpleControllerAPI.class ); TestConfiguration configuration = api.getTestConfiguration(); Assert.assertNull( configuration ); expected = new TestConfiguration( RandomStringUtils.random( 10 ), Optional.<String> absent() ); TestConfiguration actual = api.setTestConfiguration( expected ); Assert.assertEquals( expected, actual ); } @Test public void getCutting() { Assert.assertNotNull( "Cuttings of the rhizome must always be present.", rhizome.getContext().getBean( Cutting.class ) ); } @Test public void testReadWriteConfiguration() { // We're assuming that data is not persisted across runs here. SimpleControllerAPI api = adapter.create( SimpleControllerAPI.class ); TestConfiguration actual = api.getTestConfiguration(); Assert.assertEquals( expected, actual ); } @Test public void testByteArray() throws IOException { SimpleControllerAPI api = adapter.create( SimpleControllerAPI.class ); byte[] response = api.gzipTest(); Assert.assertNotNull( response ); Assert.assertArrayEquals( TEST_BYTES, response ); } @Test public void teapotTest() throws IOException { SimpleControllerAPI api = adapter.create( SimpleControllerAPI.class ); Assert.assertEquals( "I AM A TEAPOT!", api.teapot() ); } @Test public void testSimpleControllerGets() throws Exception { SimpleControllerAPI api = adapter.create( SimpleControllerAPI.class ); ObjectMapper mapper = new ObjectMapper(); logger.info( "Context configuration: {}", mapper.writeValueAsString( api.getContextConfiguration() ) ); logger.info( "Jetty configuration: {}", mapper.writeValueAsString( api.getJettyConfiguration() ) ); } @Test public void testGetAdminEndpoint() { SimpleControllerAPI api = adapter.create( SimpleControllerAPI.class ); TestConfiguration actual = api.getTestConfigurationSecuredAdmin(); } @Test public void testGetFooEndpoint() { SimpleControllerAPI api = adapter.create( SimpleControllerAPI.class ); TestConfiguration actual = api.getTestConfigurationSecuredFoo(); Assert.assertNull( actual ); } @Test public void testGetUserEndpoint() { SimpleControllerAPI api = adapter.create( SimpleControllerAPI.class ); TestConfiguration actual = api.getTestConfigurationSecuredUser(); Assert.assertEquals( expected, actual ); } @AfterClass public static void plow() throws BeansException, Exception { logger.info( "Finished testing loading servlet pod." ); rhizome.wilt(); logger.info( "Successfully shutdown Jetty, exiting main thread" ); } }