/**
* 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.tests.usercode.testservlets;
import com.google.appengine.api.utils.SystemProperty;
import com.google.apphosting.api.ApiProxy;
import com.google.apphosting.api.DeadlineExceededException;
import java.io.IOException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* This servlet checks to see whether getRemainingMillis() decrements over time.
*
*/
public class RemainingMillisServlet extends HttpServlet {
@Override
public void doGet(HttpServletRequest req, HttpServletResponse res) throws IOException {
final long firstCall = ApiProxy.getCurrentEnvironment().getRemainingMillis();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException("Interrupted while sleeping.");
}
final long secondCall = ApiProxy.getCurrentEnvironment().getRemainingMillis();
if (secondCall >= firstCall) {
throw new RuntimeException(
"Time is not moving (or moving backwards): initial call = '"
+ firstCall
+ "', subsequent call = '"
+ secondCall
+ "'.");
}
res.setContentType("text/plain");
res
.getWriter()
.println("You are the bread and the knife, " + "the crystal goblet and the wine.");
// Unfortunately, if we're using this servlet to test the DevAppServer we can't continue
// because it does not ever time out requests.
if (SystemProperty.environment.value() == SystemProperty.Environment.Value.Development) {
return;
}
try {
Thread.sleep(600000); //Sleep 10 minutes, this should guarantee an exception is thrown.
throw new RuntimeException(
"Expected the DeadlineExceededException to be thrown after" + "sleeping for 10mins");
} catch (DeadlineExceededException e) {
// There is an inherent race condition here that exists in the java runtime in general.
// The problem that users run into here, is that they end up having to write code that
// is gauranteed to complete in a specific amount of wall clock time. In production,
// this time is represented by a sleep that occurs in deadline_manager.cc and has little
// to do with the java runtime itself. Therefore, this segment of the test is always going
// to be potentially flaky, we just try to do as much work before we get into this
// exception handler as possible so that we don't run over our allocated cleanup time.
if (ApiProxy.getCurrentEnvironment().getRemainingMillis() > 0) {
throw new RuntimeException(
"getRemainingMillis returned a result indicating there was time "
+ "remaining after DeadlineExceededException was thrown");
}
return;
} catch (InterruptedException e) {
throw new RuntimeException("The serving thread was interrupted before the deadline");
}
}
}