140 lines
4.2 KiB
Java
140 lines
4.2 KiB
Java
/*
|
|
* Copyright 2020-2020 the original author or authors.
|
|
*
|
|
* 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
|
|
*
|
|
* https://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.example;
|
|
|
|
import java.io.*;
|
|
import java.util.Arrays;
|
|
import java.util.HashMap;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.concurrent.CountDownLatch;
|
|
import java.util.concurrent.ExecutorService;
|
|
import java.util.concurrent.Executors;
|
|
import java.util.concurrent.TimeUnit;
|
|
import java.util.concurrent.atomic.AtomicInteger;
|
|
|
|
import com.google.cloud.functions.invoker.runner.Invoker;
|
|
|
|
import org.springframework.cloud.function.adapter.gcp.GcfJarLauncher;
|
|
|
|
import static org.assertj.core.api.Assertions.assertThat;
|
|
|
|
/**
|
|
* Test support class for running tests on the local Cloud Function server.
|
|
*
|
|
* @author Daniel Zou
|
|
* @author Mike Eltsufin
|
|
*/
|
|
final public class LocalServerTestSupport {
|
|
|
|
private static final ExecutorService EXECUTOR = Executors.newCachedThreadPool();
|
|
|
|
private static final String SERVER_READY_STRING = "Started ServerConnector";
|
|
|
|
private static AtomicInteger nextPort = new AtomicInteger(8080);
|
|
|
|
private LocalServerTestSupport() {
|
|
}
|
|
|
|
public static ServerProcess startServer(Class<?> springApplicationMainClass)
|
|
throws InterruptedException, IOException {
|
|
|
|
// Get the Java class path.
|
|
String myClassPath = System.getProperty("java.class.path");
|
|
assertThat(myClassPath).isNotNull();
|
|
|
|
// Setup the Java Process command line string
|
|
List<String> command = Arrays.asList(getJavaCommand(), "-classpath", myClassPath, Invoker.class.getName());
|
|
ProcessBuilder processBuilder = new ProcessBuilder().command(command).redirectErrorStream(true);
|
|
|
|
// Set environment variables.
|
|
Map<String, String> environment = new HashMap<>();
|
|
environment.put("PORT", String.valueOf(nextPort.getAndIncrement()));
|
|
environment.put("K_SERVICE", "test-function");
|
|
environment.put("FUNCTION_SIGNATURE_TYPE", "http");
|
|
environment.put("FUNCTION_TARGET", GcfJarLauncher.class.getCanonicalName());
|
|
environment.put("MAIN_CLASS", springApplicationMainClass.getCanonicalName());
|
|
processBuilder.environment().putAll(environment);
|
|
|
|
// Start the process and monitor the output logs in a separate thread.
|
|
// Once the SERVER_READY_STRING is found in the logs, we know we are ready.
|
|
Process serverProcess = processBuilder.start();
|
|
CountDownLatch ready = new CountDownLatch(1);
|
|
|
|
EXECUTOR.submit(() -> monitorOutput(serverProcess.getInputStream(), ready));
|
|
boolean serverReady = ready.await(5, TimeUnit.SECONDS);
|
|
if (!serverReady) {
|
|
serverProcess.destroy();
|
|
throw new AssertionError("Server never became ready");
|
|
}
|
|
|
|
return new ServerProcess(serverProcess);
|
|
}
|
|
|
|
private static void monitorOutput(InputStream processOutput, CountDownLatch ready) {
|
|
try (BufferedReader reader = new BufferedReader(new InputStreamReader(processOutput))) {
|
|
String line;
|
|
while ((line = reader.readLine()) != null) {
|
|
if (line.contains(SERVER_READY_STRING)) {
|
|
ready.countDown();
|
|
}
|
|
|
|
System.out.println(line);
|
|
|
|
if (line.contains("WARNING")) {
|
|
throw new AssertionError("Found warning in server output:\n" + line);
|
|
}
|
|
}
|
|
}
|
|
catch (IOException e) {
|
|
throw new UncheckedIOException(e);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns the path to the java executable.
|
|
*/
|
|
private static String getJavaCommand() {
|
|
File javaHome = new File(System.getProperty("java.home"));
|
|
assertThat(javaHome.exists()).isTrue();
|
|
|
|
File javaBin = new File(javaHome, "bin");
|
|
File javaCommand = new File(javaBin, "java");
|
|
assertThat(javaCommand.exists()).isTrue();
|
|
|
|
return javaCommand.toString();
|
|
}
|
|
|
|
static class ServerProcess implements AutoCloseable {
|
|
|
|
private final Process process;
|
|
|
|
ServerProcess(Process process) {
|
|
this.process = process;
|
|
}
|
|
|
|
Process process() {
|
|
return process;
|
|
}
|
|
|
|
@Override
|
|
public void close() {
|
|
process().destroy();
|
|
}
|
|
}
|
|
}
|