/**
* 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.repackaged.com.google.protobuf.MessageLite;
import com.google.apphosting.api.ApiBasePb;
import com.google.apphosting.api.ApiProxy;
import com.google.apphosting.vmruntime.VmApiProxyDelegate;
import com.google.apphosting.vmruntime.VmApiProxyEnvironment;
import java.util.LinkedList;
/**
* ApiProxyDelegate that stores all incoming API requests and returns
* pre-configured responses.
*/
public class FakeableVmApiProxyDelegate extends VmApiProxyDelegate {
public LinkedList<MessageLite> responses = new LinkedList<>();
public LinkedList<ApiRequest> requests = new LinkedList<>();
public boolean ignoreLogging = true;
public FakeableVmApiProxyDelegate() {
}
@Override
protected byte[] runSyncCall(VmApiProxyEnvironment environment, String packageName,
String methodName, byte[] requestData, int timeoutMs) throws ApiProxy.ApiProxyException {
// Lots of tests triggers logging. Ignore calls to the logservice by default. Tests
// verifying logging behavior can enable the log api capture calling setIgnoreLogging(false).
if (ignoreLogging && "logservice".equals(packageName)) {
return new ApiBasePb.VoidProto().toByteArray();
}
if ("google.util".equals(packageName) && "Delay".equals(methodName)) {
return handleDelayApi(requestData);
}
requests.add(new ApiRequest(environment, packageName, methodName, requestData));
if (responses.isEmpty()) {
throw new RuntimeException(
"Got unexpected ApiProxy call to: " + packageName + "/" + methodName);
}
return responses.removeFirst().toByteArray();
}
public void setIgnoreLogging(boolean ignore) {
this.ignoreLogging = ignore;
}
/**
* Add a API response to return on the next API call.
*
* @param message The protocol buffer to return.
*/
public void addApiResponse(MessageLite message) {
responses.add(message);
}
/**
* Returns the last API request made through the delegate.
*
* @return A serialized protocol buffer.
*/
public ApiRequest getLastRequest() {
return requests.getLast();
}
private byte[] handleDelayApi(byte[] requestData) {
ApiBasePb.Integer32Proto intRequest = new ApiBasePb.Integer32Proto();
intRequest.parseFrom(requestData);
try {
Thread.sleep(intRequest.getValue());
} catch (InterruptedException e) {
throw new ApiProxy.ApiProxyException("Got unexpected thread interrupt!");
}
return new ApiBasePb.VoidProto().toByteArray();
}
public boolean waitForLogFlush() throws InterruptedException {
for (int i = 0; i < 10; i++) {
if (requests.size() > 0 && "logservice".equals(requests.getLast().packageName)) {
return requests.getLast().waitForAllApiCalls();
}
Thread.sleep(100);
}
return false;
}
}