blob: 0d509905ffff20e81b0074502407323e38d9a1cc [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more contributor license
* agreements. See the NOTICE file distributed with this work for additional information regarding
* copyright ownership. The ASF licenses this file to You 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 org.apache.geode.test.junit.rules.gfsh;
import static org.assertj.core.api.Assertions.assertThat;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
/**
* All the commands represented in this script is executed within one gfsh session.
*
* all the commands in this script are executed using this bash command:
* gfsh -e command1 -e command2 -e command3 ....
*
* You can chain commands together to create a gfshScript
* GfshScript.of("command1").and("command2").and("command3", "command4")
*
* If your command started another process and you want to that process to be debuggable, you can do
* GfshScript.of("start locator", 30000).and("start server", 30001)
* this will allow locator to be debuggable at 30000 and the server to be debuggable at 30001
*
* By default, each scripts await at most 4 minutes for all the commands to finish
* and will expect success. if you want to change this, you can use:
* gfshScript.awaitAtMost(1, TimeUnit.MINUTES).expectFailure()
*
* if you want this gfsh session to be debuggable, you can use:
* gfshScript.withDebugPort(30000)
* This will allow gfsh to be debuggable at port 30000.
*
*/
public class GfshScript {
private List<DebuggableCommand> commands = new ArrayList<>();
private String name;
private TimeUnit timeoutTimeUnit = TimeUnit.MINUTES;
private int timeout = 4;
private int expectedExitValue = 0;
private List<String> extendedClasspath = new ArrayList<>();
private Random random = new Random();
private int debugPort = -1;
public GfshScript() {
this.name = defaultName();
}
public static GfshScript of(String... commands) {
GfshScript script = new GfshScript();
script.and(commands);
return script;
}
public static GfshScript of(String command, int debugPort) {
GfshScript script = new GfshScript();
script.and(command, debugPort);
return script;
}
public GfshScript and(String... commands) {
for (String command : commands) {
this.commands.add(new DebuggableCommand(command));
}
return this;
}
public GfshScript and(String command, int debugPort) {
this.commands.add(new DebuggableCommand(command, debugPort));
return this;
}
public GfshScript withName(String name) {
assertThat(name.contains(" ")).as("argument passed to withName cannot have spaces").isFalse();
this.name = name;
return this;
}
public GfshScript expectExitCode(int expectedExitCode) {
this.expectedExitValue = expectedExitCode;
return this;
}
public GfshScript expectFailure() {
return expectExitCode(1);
}
/**
* Will cause the thread that executes to wait, if necessary,
* until the subprocess executing this Gfsh script has terminated, or the specified waiting time
* elapses.
*
* @throws RuntimeException if the current thread is interrupted while waiting.
* @throws AssertionError if the specified waiting time elapses before the process exits.
*/
public GfshScript awaitAtMost(int timeout, TimeUnit timeUnit) {
this.timeout = timeout;
this.timeoutTimeUnit = timeUnit;
return this;
}
public List<String> getExtendedClasspath() {
return extendedClasspath;
}
public GfshScript addToClasspath(String classpath) {
extendedClasspath.add(classpath);
return this;
}
public GfshScript withDebugPort(int debugPort) {
this.debugPort = debugPort;
return this;
}
public GfshExecution execute(GfshRule gfshRule) {
return gfshRule.execute(this);
}
public List<DebuggableCommand> getCommands() {
return commands;
}
public String getName() {
return name;
}
public TimeUnit getTimeoutTimeUnit() {
return timeoutTimeUnit;
}
public int getTimeout() {
return timeout;
}
public int getExpectedExitValue() {
return expectedExitValue;
}
public int getDebugPort() {
return debugPort;
}
private String defaultName() {
return Long.toHexString(random.nextLong());
}
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append(name).append(": gfsh ");
builder.append(commands.stream().map(c -> "-e " + c.command).collect(Collectors.joining(" ")));
return builder.toString();
}
}