package com.gorillalogic.monkeytalk.processor.command;
import java.lang.reflect.Method;
import com.gorillalogic.monkeytalk.Command;
import com.gorillalogic.monkeytalk.CommandWorld;
import com.gorillalogic.monkeytalk.processor.Globals;
import com.gorillalogic.monkeytalk.processor.PlaybackListener;
import com.gorillalogic.monkeytalk.processor.PlaybackResult;
import com.gorillalogic.monkeytalk.processor.PlaybackStatus;
import com.gorillalogic.monkeytalk.processor.Scope;
import com.gorillalogic.monkeytalk.sender.Response;
import com.gorillalogic.monkeytalk.verify.Verify;
public class Vars extends BaseCommand {
public static final String VALID_VARIABLE_PATTERN = "\\A[a-zA-Z][a-zA-Z0-9_]*\\Z";
public static final String ILLEGAL_MSG = "variables must begin with a letter and contain only letters, numbers, and underscores";
public Vars(Command cmd, Scope scope, PlaybackListener listener) {
super(cmd, scope, listener);
}
public PlaybackResult define() {
listener.onStart(scope);
if (cmd.getArgs().size() == 0) {
result = new PlaybackResult(PlaybackStatus.ERROR, "command '" + cmd.getCommandName()
+ "' must define at least one variable", scope);
} else {
for (int i = 0; i < cmd.getArgs().size(); i++) {
String arg = cmd.getArgs().get(i);
String key = null;
String val = null;
if (arg.contains("=")) {
String[] parts = arg.split("=");
key = parts[0];
val = parts[1];
if (val.startsWith("\"") && val.endsWith("\"")) {
val = val.substring(1, val.length() - 1);
}
} else {
key = arg;
val = "<" + arg + ">";
}
if (!key.matches(VALID_VARIABLE_PATTERN)) {
result = new PlaybackResult(PlaybackStatus.ERROR, "command '"
+ cmd.getCommandName() + "' has illegal variable '" + key + "' -- "
+ ILLEGAL_MSG, scope);
break;
}
if (scope.getVariables().containsKey(key)) {
// we are data-driving, variables already set, so do nothing
} else if (scope.getArgs().size() > i) {
// we are running, so use parent command args
String parentArg = scope.getArgs().get(i);
if (parentArg.equals("*")) {
// star, so use default value
scope.addVariable(key, val);
} else {
if (i == 0 && parentArg.toLowerCase().endsWith(CommandWorld.DATA_EXT)) {
// we are data driving and key not found, so it's trying to use the
// datafile as the first val (which is bad)
result = new PlaybackResult(PlaybackStatus.ERROR, "datafile '"
+ parentArg + "' is missing column '" + key
+ "' from the header row", scope);
} else {
// use arg as value
scope.addVariable(key, parentArg);
}
}
} else {
// not data-driving, and no parent command ars, so just use default from
// vars.define
scope.addVariable(key, val);
}
}
}
listener.onComplete(scope, new Response());
return result;
}
public PlaybackResult verify() {
if (cmd.getArgs().size() == 0) {
return new PlaybackResult(PlaybackStatus.ERROR, "command '" + cmd.getCommand()
+ "' must have the expected value as its first arg", scope);
} else if (cmd.getArgs().size() == 1) {
return new PlaybackResult(PlaybackStatus.ERROR, "command '" + cmd.getCommand()
+ "' must have a variable as its second arg", scope);
} else {
String expected = cmd.getArgs().get(0);
String var = cmd.getArgs().get(1);
boolean inScope = scope.getVariables().containsKey(var);
if (!inScope && !Globals.hasGlobal(var)) {
return new PlaybackResult(PlaybackStatus.ERROR, "command '" + cmd.getCommand()
+ "' must have a valid variable as its second arg -- variable '" + var
+ "' not found", scope);
}
String val = (inScope ? scope.getVariables().get(var) : Globals.getGlobal(var));
String action = cmd.getAction().toLowerCase();
// use reflection to find the correct static verify method
for (Method m : Verify.class.getMethods()) {
if (action.equalsIgnoreCase(m.getName())) {
// found it, so do the verify
boolean b = false;
try {
b = (Boolean) m.invoke(null, expected, val);
} catch (Exception ex) {
ex.printStackTrace();
return new PlaybackResult(PlaybackStatus.ERROR, "command '"
+ cmd.getCommand() + "' had unknown error");
}
// figure out the response
Response resp = (b ? new Response() : new Response.Builder(
getFailedVerifyMessage(action, expected, val)).failure().build());
listener.onStart(scope);
listener.onComplete(scope, resp);
return new PlaybackResult(resp, scope);
}
}
return new PlaybackResult(PlaybackStatus.ERROR, "command '" + cmd.getCommand()
+ "' has unknown action '" + cmd.getAction() + "'");
}
}
private String getFailedVerifyMessage(String action, String expected, String val) {
if (action.equals("verifynot")) {
return "Expected not \"" + expected + "\" but found \"" + val + "\"";
} else if (action.equals("verifywildcard")) {
return "Expected match to wildcard pattern \"" + expected + "\" but found \"" + val
+ "\"";
} else if (action.equals("verifynotwildcard")) {
return "Expected non-match to wildcard pattern \"" + expected + "\" but found \"" + val
+ "\"";
} else if (action.equals("verifyregex")) {
return "Expected match to regex pattern \"" + expected + "\" but found \"" + val + "\"";
} else if (action.equals("verifynotregex")) {
return "Expected non-match to regex pattern \"" + expected + "\" but found \"" + val
+ "\"";
}
return "Expected \"" + expected + "\" but found \"" + val + "\"";
}
}