/*
* Copyright 2015 Netflix, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.netflix.discovery.shared.transport;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.UriBuilder;
import java.net.URI;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import com.netflix.appinfo.InstanceInfo;
import com.netflix.appinfo.InstanceInfo.InstanceStatus;
import com.netflix.discovery.shared.Applications;
import com.netflix.discovery.util.EurekaEntityComparators;
import com.netflix.discovery.util.InstanceInfoGenerator;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import static com.netflix.discovery.shared.transport.EurekaHttpResponse.anEurekaHttpResponse;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
/**
* @author Tomasz Bak
*/
public abstract class EurekaHttpClientCompatibilityTestSuite {
private static final String REMOTE_REGION = "us-east-1";
private final EurekaHttpClient requestHandler = mock(EurekaHttpClient.class);
private final List<EurekaHttpRequest> observedHttpRequests = new CopyOnWriteArrayList<>();
private final EurekaTransportEventListener transportEventListener = new EurekaTransportEventListener() {
@Override
public void onHttpRequest(EurekaHttpRequest request) {
observedHttpRequests.add(request);
}
};
private SimpleEurekaHttpServer httpServer;
protected EurekaHttpClientCompatibilityTestSuite() {
}
@Before
public void setUp() throws Exception {
httpServer = new SimpleEurekaHttpServer(requestHandler, transportEventListener);
}
@After
public void tearDown() throws Exception {
httpServer.shutdown();
}
protected abstract EurekaHttpClient getEurekaHttpClient(URI serviceURI);
protected EurekaHttpClient getEurekaHttpClient() {
return getEurekaHttpClient(getHttpServer().getServiceURI());
}
protected EurekaHttpClient getEurekaClientWithBasicAuthentication(String userName, String password) {
URI serviceURI = UriBuilder.fromUri(getHttpServer().getServiceURI()).userInfo(userName + ':' + password).build();
return getEurekaHttpClient(serviceURI);
}
protected SimpleEurekaHttpServer getHttpServer() {
return httpServer;
}
@Test
public void testRegisterRequest() throws Exception {
InstanceInfo instance = InstanceInfoGenerator.takeOne();
when(requestHandler.register(instance)).thenReturn(EurekaHttpResponse.status(204));
EurekaHttpResponse<Void> httpResponse = getEurekaHttpClient().register(instance);
assertThat(httpResponse.getStatusCode(), is(equalTo(204)));
}
@Test
public void testCancelRequest() throws Exception {
InstanceInfo instance = InstanceInfoGenerator.takeOne();
when(requestHandler.cancel(instance.getAppName(), instance.getId())).thenReturn(EurekaHttpResponse.status(200));
EurekaHttpResponse<Void> httpResponse = getEurekaHttpClient().cancel(instance.getAppName(), instance.getId());
assertThat(httpResponse.getStatusCode(), is(equalTo(200)));
}
@Test
public void testHeartbeatRequest() throws Exception {
InstanceInfo instance = InstanceInfoGenerator.takeOne();
InstanceInfo updated = new InstanceInfo.Builder(instance).setHostName("another.host").build();
when(requestHandler.sendHeartBeat(instance.getAppName(), instance.getId(), null, null)).thenReturn(createResponse(updated));
EurekaHttpResponse<InstanceInfo> httpResponse = getEurekaHttpClient().sendHeartBeat(instance.getAppName(), instance.getId(), instance, null);
verifyResponseOkWithEntity(updated, httpResponse);
}
@Test
public void testStatusUpdateRequest() throws Exception {
InstanceInfo instance = InstanceInfoGenerator.takeOne();
when(requestHandler.statusUpdate(instance.getAppName(), instance.getId(), InstanceStatus.OUT_OF_SERVICE, null))
.thenReturn(EurekaHttpResponse.status(200));
EurekaHttpResponse<Void> httpResponse = getEurekaHttpClient().statusUpdate(instance.getAppName(), instance.getId(), InstanceStatus.OUT_OF_SERVICE, instance);
assertThat(httpResponse.getStatusCode(), is(equalTo(200)));
}
@Test
public void testGetApplicationsRequest() throws Exception {
Applications apps = InstanceInfoGenerator.newBuilder(2, 1).build().toApplications();
when(requestHandler.getApplications()).thenReturn(createResponse(apps));
EurekaHttpResponse<Applications> httpResponse = getEurekaHttpClient().getApplications();
verifyResponseOkWithEntity(apps, httpResponse);
}
@Test
public void testGetApplicationsWithRemoteRegionRequest() throws Exception {
Applications apps = InstanceInfoGenerator.newBuilder(2, 1).build().toApplications();
when(requestHandler.getApplications(REMOTE_REGION)).thenReturn(createResponse(apps));
EurekaHttpResponse<Applications> httpResponse = getEurekaHttpClient().getApplications(REMOTE_REGION);
verifyResponseOkWithEntity(apps, httpResponse);
}
@Test
public void testGetDeltaRequest() throws Exception {
Applications delta = InstanceInfoGenerator.newBuilder(2, 1).build().takeDelta(2);
when(requestHandler.getDelta()).thenReturn(createResponse(delta));
EurekaHttpResponse<Applications> httpResponse = getEurekaHttpClient().getDelta();
verifyResponseOkWithEntity(delta, httpResponse);
}
@Test
public void testGetDeltaWithRemoteRegionRequest() throws Exception {
Applications delta = InstanceInfoGenerator.newBuilder(2, 1).build().takeDelta(2);
when(requestHandler.getDelta(REMOTE_REGION)).thenReturn(createResponse(delta));
EurekaHttpResponse<Applications> httpResponse = getEurekaHttpClient().getDelta(REMOTE_REGION);
verifyResponseOkWithEntity(delta, httpResponse);
}
@Test
public void testGetInstanceRequest() throws Exception {
InstanceInfo instance = InstanceInfoGenerator.takeOne();
when(requestHandler.getInstance(instance.getId())).thenReturn(createResponse(instance));
EurekaHttpResponse<InstanceInfo> httpResponse = getEurekaHttpClient().getInstance(instance.getId());
verifyResponseOkWithEntity(instance, httpResponse);
}
@Test
public void testGetApplicationInstanceRequest() throws Exception {
InstanceInfo instance = InstanceInfoGenerator.takeOne();
when(requestHandler.getInstance(instance.getAppName(), instance.getId())).thenReturn(createResponse(instance));
EurekaHttpResponse<InstanceInfo> httpResponse = getEurekaHttpClient().getInstance(instance.getAppName(), instance.getId());
verifyResponseOkWithEntity(instance, httpResponse);
}
@Test
public void testGetVipRequest() throws Exception {
Applications vipApps = InstanceInfoGenerator.newBuilder(1, 2).build().toApplications();
String vipAddress = vipApps.getRegisteredApplications().get(0).getInstances().get(0).getVIPAddress();
when(requestHandler.getVip(vipAddress)).thenReturn(createResponse(vipApps));
EurekaHttpResponse<Applications> httpResponse = getEurekaHttpClient().getVip(vipAddress);
verifyResponseOkWithEntity(vipApps, httpResponse);
}
@Test
public void testGetVipWithRemoteRegionRequest() throws Exception {
Applications vipApps = InstanceInfoGenerator.newBuilder(1, 2).build().toApplications();
String vipAddress = vipApps.getRegisteredApplications().get(0).getInstances().get(0).getVIPAddress();
when(requestHandler.getVip(vipAddress, REMOTE_REGION)).thenReturn(createResponse(vipApps));
EurekaHttpResponse<Applications> httpResponse = getEurekaHttpClient().getVip(vipAddress, REMOTE_REGION);
verifyResponseOkWithEntity(vipApps, httpResponse);
}
@Test
public void testGetSecureVipRequest() throws Exception {
Applications vipApps = InstanceInfoGenerator.newBuilder(1, 2).build().toApplications();
String secureVipAddress = vipApps.getRegisteredApplications().get(0).getInstances().get(0).getSecureVipAddress();
when(requestHandler.getSecureVip(secureVipAddress)).thenReturn(createResponse(vipApps));
EurekaHttpResponse<Applications> httpResponse = getEurekaHttpClient().getSecureVip(secureVipAddress);
verifyResponseOkWithEntity(vipApps, httpResponse);
}
@Test
public void testGetSecureVipWithRemoteRegionRequest() throws Exception {
Applications vipApps = InstanceInfoGenerator.newBuilder(1, 2).build().toApplications();
String secureVipAddress = vipApps.getRegisteredApplications().get(0).getInstances().get(0).getSecureVipAddress();
when(requestHandler.getSecureVip(secureVipAddress, REMOTE_REGION)).thenReturn(createResponse(vipApps));
EurekaHttpResponse<Applications> httpResponse = getEurekaHttpClient().getSecureVip(secureVipAddress, REMOTE_REGION);
verifyResponseOkWithEntity(vipApps, httpResponse);
}
@Test
public void testStatusUpdateDeleteRequest() throws Exception {
InstanceInfo instance = InstanceInfoGenerator.takeOne();
when(requestHandler.deleteStatusOverride(instance.getAppName(), instance.getId(), null))
.thenReturn(EurekaHttpResponse.status(200));
EurekaHttpResponse<Void> httpResponse = getEurekaHttpClient().deleteStatusOverride(instance.getAppName(), instance.getId(), instance);
assertThat(httpResponse.getStatusCode(), is(equalTo(200)));
}
@Test
public void testBasicAuthentication() throws Exception {
InstanceInfo instance = InstanceInfoGenerator.takeOne();
when(requestHandler.register(instance)).thenReturn(EurekaHttpResponse.status(204));
EurekaHttpResponse<Void> httpResponse = getEurekaClientWithBasicAuthentication("myuser", "mypassword").register(instance);
assertThat(httpResponse.getStatusCode(), is(equalTo(204)));
assertThat(observedHttpRequests.get(0).getHeaders().containsKey(HttpHeaders.AUTHORIZATION), is(true));
}
private static void verifyResponseOkWithEntity(Applications original, EurekaHttpResponse<Applications> httpResponse) {
assertThat(httpResponse.getStatusCode(), is(equalTo(200)));
assertThat(httpResponse.getEntity(), is(notNullValue()));
assertThat(EurekaEntityComparators.equal(httpResponse.getEntity(), original), is(true));
}
private static void verifyResponseOkWithEntity(InstanceInfo original, EurekaHttpResponse<InstanceInfo> httpResponse) {
assertThat(httpResponse.getStatusCode(), is(equalTo(200)));
assertThat(httpResponse.getEntity(), is(notNullValue()));
assertThat(EurekaEntityComparators.equal(httpResponse.getEntity(), original), is(true));
}
private static <T> EurekaHttpResponse<T> createResponse(T entity) {
return anEurekaHttpResponse(200, entity).headers(HttpHeaders.CONTENT_TYPE, "application/json").build();
}
}