/**
* Copyright 2015 Google Inc. All Rights Reserved.
*
* 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.google.apphosting.vmruntime.jetty9;
import com.google.appengine.api.utils.SystemProperty;
import com.google.apphosting.api.ApiProxy;
import com.google.apphosting.vmruntime.VmApiProxyDelegate;
import com.google.apphosting.vmruntime.VmApiProxyEnvironment;
import com.google.apphosting.vmruntime.VmRuntimeUtils;
import static com.google.apphosting.vmruntime.jetty9.VmRuntimeTestBase.PROJECT;
import static com.google.apphosting.vmruntime.jetty9.VmRuntimeTestBase.VERSION;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Arrays;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import static junit.framework.TestCase.assertEquals;
import static junit.framework.TestCase.assertNotNull;
import static junit.framework.TestCase.assertTrue;
import org.apache.commons.httpclient.Header;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.GetMethod;
/**
* Misc individual Jetty9 vmengines tests.
*
*/
public class VmRuntimeJettyKitchenSinkTest extends VmRuntimeTestBase {
@Override
protected void setUp() throws Exception {
appengineWebXml = "WEB-INF/sessions-disabled-appengine-web.xml";
super.setUp();
}
/**
* Test that non compiled jsp files can be served.
*
* @throws Exception
*/
public void testJspNotCompiled() throws Exception {
int iter = 0;
int end = 6;
String[] lines
= fetchUrl(createUrl(String.format("/hello_not_compiled.jsp?start=%d&end=%d", iter, end)));
String iterationFormat = "<h2>Iteration %d</h2>";
for (String line : lines) {
System.out.println(line);
if (!line.contains("Iteration")) {
continue;
}
assertEquals(line.trim(), String.format(iterationFormat, iter++));
}
assertEquals(end + 1, iter);
}
/**
* Tests that mapping a servlet to / works.
*
* @throws Exception
*/
public void testWelcomeServlet() throws Exception {
String[] lines = fetchUrl(createUrl("/"));
assertTrue(Arrays.asList(lines).contains("Hello, World!"));
}
/**
* Tests that app.yaml is protected
*/
public void testAppYamlHidden() throws Exception {
HttpURLConnection connection = (HttpURLConnection) createUrl("/app.yaml").openConnection();
connection.connect();
assertEquals(404, connection.getResponseCode());
}
/**
* Test that the API Proxy was configured by the VmRuntimeFilter.
*
* @throws Exception
*/
public void testApiProxyInstall() throws Exception {
assertNotNull(ApiProxy.getDelegate());
assertEquals(VmApiProxyDelegate.class.getCanonicalName(),
ApiProxy.getDelegate().getClass().getCanonicalName());
}
/**
* Test that the thread local environment is set up on each request.
*
* @throws Exception
*/
public void testEnvironmentInstall() throws Exception {
String[] lines = fetchUrl(createUrl("/CurrentEnvironmentAccessor"));
List<String> expectedLines = Arrays.asList(
"testpartition~google.com:test-project",
"testbackend",
"testversion.0");
assertEquals(expectedLines, Arrays.asList(lines));
}
/**
* Test that the health check servlet was loaded and responds with "ok" with
* the proper version provided.
*
* @throws Exception
*/
public void testHealthOK() throws Exception {
String[] lines = fetchUrl(createUrl("/_ah/health"));
assertEquals(1, lines.length);
assertEquals("ok", lines[0].trim());
}
public void testAsyncRequests_WaitUntilDone() throws Exception {
long sleepTime = 2000;
FakeableVmApiProxyDelegate fakeApiProxy = new FakeableVmApiProxyDelegate();
ApiProxy.setDelegate(fakeApiProxy);
HttpClient httpClient = new HttpClient();
httpClient.getHttpConnectionManager().getParams().setConnectionTimeout(5000);
GetMethod get = new GetMethod(createUrl("/sleep").toString());
get.addRequestHeader("Use-Async-Sleep-Api", "true");
get.addRequestHeader("Sleep-Time", Long.toString(sleepTime));
long startTime = System.currentTimeMillis();
int httpCode = httpClient.executeMethod(get);
assertEquals(200, httpCode);
Header vmApiWaitTime = get.getResponseHeader(VmRuntimeUtils.ASYNC_API_WAIT_HEADER);
assertNotNull(vmApiWaitTime);
assertTrue(Integer.parseInt(vmApiWaitTime.getValue()) > 0);
long elapsed = System.currentTimeMillis() - startTime;
assertTrue(elapsed >= sleepTime);
}
/**
* Test that all AppEngine specific system properties are set up when the
* VmRuntimeFilter is initialized.
*
* @throws Exception
*/
public void testSystemProperties() throws Exception {
String[] lines = fetchUrl(createUrl("/printSystemProperties"));
assertEquals(7, lines.length);
assertEquals("sysprop1 value", lines[0]);
assertEquals("sysprop2 value", lines[1]);
assertEquals("null", lines[2]);
assertEquals(SystemProperty.Environment.Value.Production.name(), lines[3]);
assertTrue(lines[4].startsWith("Google App Engine/"));
assertEquals(PROJECT, lines[5]);
assertEquals(VERSION + ".0", lines[6]);
}
/**
* Test that the warmup handler is installed.
*/
public void testWarmup() throws Exception {
String[] lines = fetchUrl(createUrl("/_ah/warmup")); // fetchUrl() fails on non-OK return codes.
assertEquals(0, lines.length);
}
/**
* Test that sessions are disabled. Disabling sessions means that the default HashSessionManager
* is being used, which keeps sessions in memory only. Enabling sessions uses the appengine SessionManager
* which will use Datastore and memcache as persistent backing stores.
*
* @throws Exception
*/
public void testSessions() throws Exception {
for (int i = 1; i <= 5; i++) {
String[] lines = fetchUrl(createUrl("/count?type=session"));
assertEquals(1, lines.length);
assertEquals("1", lines[0]); // We're not passing in any session cookie so each request is a fresh session.
}
}
public void testSsl_NoSSL() throws Exception {
HttpClient httpClient = new HttpClient();
httpClient.getHttpConnectionManager().getParams().setConnectionTimeout(30000);
GetMethod get = new GetMethod(createUrl("/test-ssl").toString());
int httpCode = httpClient.executeMethod(get);
assertEquals(200, httpCode);
String expected = "false:http:http://localhost:"+port+"/test-ssl";
assertEquals(expected, get.getResponseBodyAsString());
}
public void testSsl_WithSSL() throws Exception {
HttpClient httpClient = new HttpClient();
httpClient.getHttpConnectionManager().getParams().setConnectionTimeout(30000);
GetMethod get = new GetMethod(createUrl("/test-ssl").toString());
get.addRequestHeader(VmApiProxyEnvironment.HTTPS_HEADER, "on");
int httpCode = httpClient.executeMethod(get);
assertEquals(200, httpCode);
assertEquals("true:https:https://localhost/test-ssl", get.getResponseBodyAsString());
}
public void testWithUntrustedInboundIp() throws Exception {
HttpClient httpClient = new HttpClient();
httpClient.getHttpConnectionManager().getParams().setConnectionTimeout(30000);
GetMethod get = new GetMethod(createUrlForHostIP("/test-ssl").toString());
int httpCode = httpClient.executeMethod(get);
assertEquals(200, httpCode);
}
protected int fetchResponseCode(URL url) throws IOException {
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.connect();
return connection.getResponseCode();
}
public void testShutDown() throws Exception {
int code = fetchResponseCode(createUrl("/_ah/health"));
assertEquals(HttpServletResponse.SC_OK, code);
// Send a request to /_ah/stop to trigger lameduck.
String[] lines = fetchUrl(createUrl("/_ah/stop"));
assertEquals(1, lines.length);
assertEquals("ok", lines[0].trim());
code = fetchResponseCode(createUrl("/_ah/health"));
assertEquals(HttpServletResponse.SC_BAD_GATEWAY, code);
}
}