http://git-wip-us.apache.org/repos/asf/metron/blob/2dd01b17/metron-stellar/stellar-common/src/main/java/org/apache/metron/stellar/common/shell/specials/AssignmentCommand.java
----------------------------------------------------------------------
diff --git 
a/metron-stellar/stellar-common/src/main/java/org/apache/metron/stellar/common/shell/specials/AssignmentCommand.java
 
b/metron-stellar/stellar-common/src/main/java/org/apache/metron/stellar/common/shell/specials/AssignmentCommand.java
new file mode 100644
index 0000000..e253b3b
--- /dev/null
+++ 
b/metron-stellar/stellar-common/src/main/java/org/apache/metron/stellar/common/shell/specials/AssignmentCommand.java
@@ -0,0 +1,85 @@
+/*
+ *  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.metron.stellar.common.shell.specials;
+
+import org.apache.metron.stellar.common.StellarAssignment;
+import org.apache.metron.stellar.common.shell.StellarShellExecutor;
+import org.apache.metron.stellar.common.shell.StellarResult;
+
+import java.util.Optional;
+import java.util.function.Function;
+
+import static org.apache.metron.stellar.common.shell.StellarResult.error;
+
+/**
+ * A special command that allows for variable assignment.  Variable
+ * assignment is not implemented directly within Stellar.
+ *
+ *    x := 2 + 2
+ */
+public class AssignmentCommand implements SpecialCommand {
+
+  public static final String ASSIGNMENT_OP = ":=";
+
+  @Override
+  public Function<String, Boolean> getMatcher() {
+    return (input) -> StellarAssignment.isAssignment(input);
+  }
+
+  @Override
+  public String getCommand() {
+    return ASSIGNMENT_OP;
+  }
+
+  /**
+   * Handles variable assignment.
+   * @param input The assignment expression to execute.
+   * @param executor A stellar execution environment.
+   * @return
+   */
+  @Override
+  public StellarResult execute(String input, StellarShellExecutor executor) {
+    assert StellarAssignment.isAssignment(input);
+
+    // extract the variable and assignment expression
+    StellarAssignment assignment = StellarAssignment.from(input);
+    String varName = assignment.getVariable();
+    String varExpr = assignment.getStatement();
+
+    // execute the stellar expression
+    StellarResult result = executor.execute(varExpr);
+    if(result.isSuccess()) {
+
+      Object value = null;
+      if(result.getValue().isPresent()) {
+        value = result.getValue().get();
+
+      } else if(result.isValueNull()) {
+        value = null;
+      }
+
+      // variable assignment
+      executor.assign(varName, value, Optional.of(varExpr));
+      return result;
+
+    } else {
+      return error("Assignment expression failed");
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/metron/blob/2dd01b17/metron-stellar/stellar-common/src/main/java/org/apache/metron/stellar/common/shell/specials/Comment.java
----------------------------------------------------------------------
diff --git 
a/metron-stellar/stellar-common/src/main/java/org/apache/metron/stellar/common/shell/specials/Comment.java
 
b/metron-stellar/stellar-common/src/main/java/org/apache/metron/stellar/common/shell/specials/Comment.java
new file mode 100644
index 0000000..cea0c91
--- /dev/null
+++ 
b/metron-stellar/stellar-common/src/main/java/org/apache/metron/stellar/common/shell/specials/Comment.java
@@ -0,0 +1,53 @@
+/*
+ *  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.metron.stellar.common.shell.specials;
+
+import org.apache.metron.stellar.common.shell.StellarShellExecutor;
+import org.apache.metron.stellar.common.shell.StellarResult;
+
+import java.util.function.Function;
+
+import static org.apache.commons.lang3.StringUtils.startsWith;
+import static org.apache.commons.lang3.StringUtils.trimToEmpty;
+import static org.apache.metron.stellar.common.shell.StellarResult.noop;
+
+/**
+ * A special command that handles comments.
+ *
+ *    # this is a comment
+ */
+public class Comment implements SpecialCommand {
+
+  public static final String COMMENT_PREFIX = "#";
+
+  @Override
+  public String getCommand() {
+    return "#";
+  }
+
+  @Override
+  public Function<String, Boolean> getMatcher() {
+    return (input) -> startsWith(trimToEmpty(input), COMMENT_PREFIX);
+  }
+
+  @Override
+  public StellarResult execute(String expression, StellarShellExecutor 
executor) {
+    return noop();
+  }
+}

http://git-wip-us.apache.org/repos/asf/metron/blob/2dd01b17/metron-stellar/stellar-common/src/main/java/org/apache/metron/stellar/common/shell/specials/DocCommand.java
----------------------------------------------------------------------
diff --git 
a/metron-stellar/stellar-common/src/main/java/org/apache/metron/stellar/common/shell/specials/DocCommand.java
 
b/metron-stellar/stellar-common/src/main/java/org/apache/metron/stellar/common/shell/specials/DocCommand.java
new file mode 100644
index 0000000..f362f74
--- /dev/null
+++ 
b/metron-stellar/stellar-common/src/main/java/org/apache/metron/stellar/common/shell/specials/DocCommand.java
@@ -0,0 +1,105 @@
+/*
+ *  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.metron.stellar.common.shell.specials;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.metron.stellar.common.shell.StellarShellExecutor;
+import org.apache.metron.stellar.common.shell.StellarResult;
+import org.apache.metron.stellar.dsl.StellarFunctionInfo;
+
+import java.util.Optional;
+import java.util.Spliterator;
+import java.util.function.Function;
+import java.util.stream.StreamSupport;
+
+import static org.apache.metron.stellar.common.shell.StellarResult.error;
+import static org.apache.metron.stellar.common.shell.StellarResult.success;
+
+/**
+ * A special command that allows a user to request doc string
+ * about a Stellar function.
+ *
+ * For example `?TO_STRING` will output the docs for the function `TO_STRING`
+ */
+public class DocCommand implements SpecialCommand {
+
+  public static final String DOC_PREFIX = "?";
+
+  @Override
+  public String getCommand() {
+    return DOC_PREFIX;
+  }
+
+  @Override
+  public Function<String, Boolean> getMatcher() {
+    return (input) -> StringUtils.startsWith(input, DOC_PREFIX);
+  }
+
+  @Override
+  public StellarResult execute(String command, StellarShellExecutor executor) {
+    StellarResult result;
+
+    // expect ?functionName
+    String functionName = StringUtils.substring(command, 1);
+
+    // grab any docs for the given function
+    Spliterator<StellarFunctionInfo> fnIterator = 
executor.getFunctionResolver().getFunctionInfo().spliterator();
+    Optional<StellarFunctionInfo> functionInfo = StreamSupport
+            .stream(fnIterator, false)
+            .filter(info -> StringUtils.equals(functionName, info.getName()))
+            .findFirst();
+
+    if(functionInfo.isPresent()) {
+      result = success(docFormat(functionInfo.get()));
+    } else {
+      result = error(String.format("No docs available for function '%s'", 
functionName));
+    }
+
+    return result;
+  }
+
+  /**
+   * Formats the Stellar function info object into a readable string.
+   * @param info The stellar function info object.
+   * @return A readable string.
+   */
+  private String docFormat(StellarFunctionInfo info) {
+    StringBuffer docString = new StringBuffer();
+
+    // name
+    docString.append(info.getName() + "\n");
+
+    // description
+    docString.append(String.format("Description: %-60s\n\n", 
info.getDescription()));
+
+    // params
+    if(info.getParams().length > 0) {
+      docString.append("Arguments:\n");
+      for(String param : info.getParams()) {
+        docString.append(String.format("\t%-60s\n", param));
+      }
+      docString.append("\n");
+    }
+
+    // returns
+    docString.append(String.format("Returns: %-60s\n", info.getReturns()));
+
+    return docString.toString();
+  }
+}

http://git-wip-us.apache.org/repos/asf/metron/blob/2dd01b17/metron-stellar/stellar-common/src/main/java/org/apache/metron/stellar/common/shell/specials/MagicDefineGlobal.java
----------------------------------------------------------------------
diff --git 
a/metron-stellar/stellar-common/src/main/java/org/apache/metron/stellar/common/shell/specials/MagicDefineGlobal.java
 
b/metron-stellar/stellar-common/src/main/java/org/apache/metron/stellar/common/shell/specials/MagicDefineGlobal.java
new file mode 100644
index 0000000..6e094f9
--- /dev/null
+++ 
b/metron-stellar/stellar-common/src/main/java/org/apache/metron/stellar/common/shell/specials/MagicDefineGlobal.java
@@ -0,0 +1,86 @@
+/*
+ *  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.metron.stellar.common.shell.specials;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.metron.stellar.common.StellarAssignment;
+import org.apache.metron.stellar.common.shell.StellarShellExecutor;
+import org.apache.metron.stellar.common.shell.StellarResult;
+
+import java.util.function.Function;
+
+import static org.apache.commons.lang3.StringUtils.startsWith;
+import static org.apache.commons.lang3.StringUtils.trimToEmpty;
+import static org.apache.metron.stellar.common.shell.StellarResult.error;
+import static org.apache.metron.stellar.common.shell.StellarResult.success;
+
+/**
+ * Allows a variable to be defined (or redefined) a within the global 
configuration.
+ *
+ *   %define newVar := newValue
+ */
+public class MagicDefineGlobal implements SpecialCommand {
+
+  public static final String MAGIC_DEFINE = "%define";
+
+  @Override
+  public String getCommand() {
+    return MAGIC_DEFINE;
+  }
+
+  @Override
+  public Function<String, Boolean> getMatcher() {
+    return (input) -> startsWith(trimToEmpty(input), MAGIC_DEFINE);
+  }
+
+  @Override
+  public StellarResult execute(String command, StellarShellExecutor executor) {
+
+    // grab the expression in '%define <assign-expression>'
+    String assignExpr = 
StringUtils.trimToEmpty(command.substring(MAGIC_DEFINE.length()));
+    if(StringUtils.length(assignExpr) < 1) {
+      return error(MAGIC_DEFINE + " missing assignment expression");
+    }
+
+    // the expression must be an assignment
+    if(!StellarAssignment.isAssignment(assignExpr)) {
+      return error(MAGIC_DEFINE + " expected assignment expression");
+    }
+
+    // execute the expression
+    StellarAssignment expr = StellarAssignment.from(assignExpr);
+    StellarResult result = executor.execute(expr.getStatement());
+
+    // execution must be successful
+    if(!result.isSuccess()) {
+      return error(MAGIC_DEFINE + " expression execution failed");
+    }
+
+    // expression should have a result
+    if(!result.getValue().isPresent()) {
+      return error(MAGIC_DEFINE + " expression produced no result");
+    }
+
+    // alter the global configuration
+    Object value = result.getValue().get();
+    executor.getGlobalConfig().put(expr.getVariable(), value);
+
+    return success(value);
+  }
+}

http://git-wip-us.apache.org/repos/asf/metron/blob/2dd01b17/metron-stellar/stellar-common/src/main/java/org/apache/metron/stellar/common/shell/specials/MagicListFunctions.java
----------------------------------------------------------------------
diff --git 
a/metron-stellar/stellar-common/src/main/java/org/apache/metron/stellar/common/shell/specials/MagicListFunctions.java
 
b/metron-stellar/stellar-common/src/main/java/org/apache/metron/stellar/common/shell/specials/MagicListFunctions.java
new file mode 100644
index 0000000..22fc002
--- /dev/null
+++ 
b/metron-stellar/stellar-common/src/main/java/org/apache/metron/stellar/common/shell/specials/MagicListFunctions.java
@@ -0,0 +1,72 @@
+/*
+ *  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.metron.stellar.common.shell.specials;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.metron.stellar.common.shell.StellarShellExecutor;
+import org.apache.metron.stellar.common.shell.StellarResult;
+
+import java.util.function.Function;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+import java.util.stream.StreamSupport;
+
+import static org.apache.commons.lang3.StringUtils.*;
+
+/**
+ * A MagicCommand that lists the functions available within
+ * a Stellar execution environment.
+ *
+ *    %functions
+ */
+public class MagicListFunctions implements SpecialCommand {
+
+  public static final String MAGIC_FUNCTIONS = "%functions";
+
+  @Override
+  public String getCommand() {
+    return MAGIC_FUNCTIONS;
+  }
+
+  @Override
+  public Function<String, Boolean> getMatcher() {
+    return (input) -> startsWith(trimToEmpty(input), MAGIC_FUNCTIONS);
+  }
+
+  @Override
+  public StellarResult execute(String command, StellarShellExecutor executor) {
+
+    // if '%functions FOO' then show only functions that contain 'FOO'
+    String startsWith = 
StringUtils.trimToEmpty(command.substring(MAGIC_FUNCTIONS.length()));
+    Predicate<String> nameFilter = (name -> true);
+    if (StringUtils.isNotBlank(startsWith)) {
+      nameFilter = (name -> name.contains(startsWith));
+    }
+
+    // '%functions' -> list all functions in scope
+    String functions = StreamSupport
+            
.stream(executor.getFunctionResolver().getFunctionInfo().spliterator(), false)
+            .map(info -> String.format("%s", info.getName()))
+            .filter(nameFilter)
+            .sorted()
+            .collect(Collectors.joining(", "));
+
+    return StellarResult.success(functions);
+  }
+}

http://git-wip-us.apache.org/repos/asf/metron/blob/2dd01b17/metron-stellar/stellar-common/src/main/java/org/apache/metron/stellar/common/shell/specials/MagicListGlobals.java
----------------------------------------------------------------------
diff --git 
a/metron-stellar/stellar-common/src/main/java/org/apache/metron/stellar/common/shell/specials/MagicListGlobals.java
 
b/metron-stellar/stellar-common/src/main/java/org/apache/metron/stellar/common/shell/specials/MagicListGlobals.java
new file mode 100644
index 0000000..09a6679
--- /dev/null
+++ 
b/metron-stellar/stellar-common/src/main/java/org/apache/metron/stellar/common/shell/specials/MagicListGlobals.java
@@ -0,0 +1,54 @@
+/*
+ *  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.metron.stellar.common.shell.specials;
+
+import org.apache.metron.stellar.common.shell.StellarShellExecutor;
+import org.apache.metron.stellar.common.shell.StellarResult;
+
+import java.util.Map;
+import java.util.function.Function;
+
+import static org.apache.commons.lang3.StringUtils.startsWith;
+import static org.apache.commons.lang3.StringUtils.trimToEmpty;
+
+/**
+ * Displays all currently defined global configuration variables.
+ *
+ *    %globals
+ */
+public class MagicListGlobals implements SpecialCommand {
+
+  public static final String MAGIC_GLOBALS = "%globals";
+
+  @Override
+  public String getCommand() {
+    return MAGIC_GLOBALS;
+  }
+
+  @Override
+  public Function<String, Boolean> getMatcher() {
+    return (input) -> startsWith(trimToEmpty(input), MAGIC_GLOBALS);
+  }
+
+  @Override
+  public StellarResult execute(String command, StellarShellExecutor executor) {
+    Map<String, Object> globals = executor.getGlobalConfig();
+    return StellarResult.success(globals.toString());
+  }
+}

http://git-wip-us.apache.org/repos/asf/metron/blob/2dd01b17/metron-stellar/stellar-common/src/main/java/org/apache/metron/stellar/common/shell/specials/MagicListVariables.java
----------------------------------------------------------------------
diff --git 
a/metron-stellar/stellar-common/src/main/java/org/apache/metron/stellar/common/shell/specials/MagicListVariables.java
 
b/metron-stellar/stellar-common/src/main/java/org/apache/metron/stellar/common/shell/specials/MagicListVariables.java
new file mode 100644
index 0000000..5669c44
--- /dev/null
+++ 
b/metron-stellar/stellar-common/src/main/java/org/apache/metron/stellar/common/shell/specials/MagicListVariables.java
@@ -0,0 +1,88 @@
+/*
+ *  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.metron.stellar.common.shell.specials;
+
+import org.apache.metron.stellar.common.shell.StellarShellExecutor;
+import org.apache.metron.stellar.common.shell.StellarResult;
+import org.apache.metron.stellar.common.shell.VariableResult;
+
+import java.util.Map;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+import static org.apache.commons.lang3.StringUtils.startsWith;
+import static org.apache.commons.lang3.StringUtils.trimToEmpty;
+import static org.apache.metron.stellar.common.shell.StellarResult.success;
+
+/**
+ * A MagicCommand that lists the variables available within
+ * the Stellar execution environment.
+ *
+ *    %vars
+ */
+public class MagicListVariables implements SpecialCommand {
+
+  public static final String MAGIC_VARS = "%vars";
+
+  @Override
+  public String getCommand() {
+    return MAGIC_VARS;
+  }
+
+  @Override
+  public Function<String, Boolean> getMatcher() {
+    return (input) -> startsWith(trimToEmpty(input), MAGIC_VARS);
+  }
+
+  /**
+   * Lists each variable, its value, and if available, the expression that 
resulted in that value.
+   *
+   *    x = 4 via `2 + 2`
+   *
+   * @param command The command to execute.
+   * @param executor A stellar execution environment.
+   * @return
+   */
+  @Override
+  public StellarResult execute(String command, StellarShellExecutor executor) {
+
+    // format a string containing each variable and it's value
+    String vars = executor
+            .getState()
+            .entrySet()
+            .stream()
+            .map(e -> format(e))
+            .collect(Collectors.joining(", "));
+
+    return success(vars);
+  }
+
+  private String format(Map.Entry<String, VariableResult> var) {
+
+    // 'varName = varValue'
+    String out = String.format("%s = %s", var.getKey(), 
var.getValue().getResult());
+
+    // 'via varExpression', if the expression is known
+    if(var.getValue().getExpression().isPresent()) {
+      out += String.format(" via `%s`", var.getValue().getExpression().get());
+    }
+
+    return out;
+  }
+}

http://git-wip-us.apache.org/repos/asf/metron/blob/2dd01b17/metron-stellar/stellar-common/src/main/java/org/apache/metron/stellar/common/shell/specials/MagicUndefineGlobal.java
----------------------------------------------------------------------
diff --git 
a/metron-stellar/stellar-common/src/main/java/org/apache/metron/stellar/common/shell/specials/MagicUndefineGlobal.java
 
b/metron-stellar/stellar-common/src/main/java/org/apache/metron/stellar/common/shell/specials/MagicUndefineGlobal.java
new file mode 100644
index 0000000..b7727e7
--- /dev/null
+++ 
b/metron-stellar/stellar-common/src/main/java/org/apache/metron/stellar/common/shell/specials/MagicUndefineGlobal.java
@@ -0,0 +1,70 @@
+/*
+ *  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.metron.stellar.common.shell.specials;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.metron.stellar.common.shell.StellarShellExecutor;
+import org.apache.metron.stellar.common.shell.StellarResult;
+
+import java.util.Map;
+import java.util.function.Function;
+
+import static org.apache.commons.lang3.StringUtils.startsWith;
+import static org.apache.commons.lang3.StringUtils.trimToEmpty;
+import static org.apache.metron.stellar.common.shell.StellarResult.noop;
+import static org.apache.metron.stellar.common.shell.StellarResult.error;
+
+/**
+ * Allows a variable to be removed from the global configuration.
+ *
+ *    %undefine varName
+ */
+public class MagicUndefineGlobal implements SpecialCommand {
+
+  public static final String MAGIC_UNDEFINE = "%undefine";
+
+  @Override
+  public String getCommand() {
+    return MAGIC_UNDEFINE;
+  }
+
+  @Override
+  public Function<String, Boolean> getMatcher() {
+    return (input) -> startsWith(trimToEmpty(input), MAGIC_UNDEFINE);
+  }
+
+  @Override
+  public StellarResult execute(String command, StellarShellExecutor executor) {
+    StellarResult result;
+
+    String variable = 
StringUtils.trimToEmpty(command.substring(MAGIC_UNDEFINE.length()));
+    if(StringUtils.isNotBlank(variable)) {
+
+      // remove the variable from the globals
+      Map<String, Object> globals = executor.getGlobalConfig();
+      globals.remove(variable);
+      result = noop();
+
+    } else {
+      result = error(String.format("%s expected name of global, got '%s'", 
MAGIC_UNDEFINE, variable));
+    }
+
+    return result;
+  }
+}

http://git-wip-us.apache.org/repos/asf/metron/blob/2dd01b17/metron-stellar/stellar-common/src/main/java/org/apache/metron/stellar/common/shell/specials/QuitCommand.java
----------------------------------------------------------------------
diff --git 
a/metron-stellar/stellar-common/src/main/java/org/apache/metron/stellar/common/shell/specials/QuitCommand.java
 
b/metron-stellar/stellar-common/src/main/java/org/apache/metron/stellar/common/shell/specials/QuitCommand.java
new file mode 100644
index 0000000..7786d4d
--- /dev/null
+++ 
b/metron-stellar/stellar-common/src/main/java/org/apache/metron/stellar/common/shell/specials/QuitCommand.java
@@ -0,0 +1,51 @@
+/*
+ *  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.metron.stellar.common.shell.specials;
+
+import org.apache.metron.stellar.common.shell.StellarShellExecutor;
+import org.apache.metron.stellar.common.shell.StellarResult;
+
+import java.util.function.Function;
+
+import static org.apache.metron.stellar.common.shell.StellarResult.terminate;
+
+/**
+ * A special command that allows the user to 'quit' their REPL session.
+ *
+ *    quit
+ */
+public class QuitCommand implements SpecialCommand {
+
+  public static final String QUIT_COMMAND = "quit";
+
+  @Override
+  public String getCommand() {
+    return QUIT_COMMAND;
+  }
+
+  @Override
+  public Function<String, Boolean> getMatcher() {
+    return (input) -> QUIT_COMMAND.equals(input);
+  }
+
+  @Override
+  public StellarResult execute(String command, StellarShellExecutor executor) {
+    return terminate();
+  }
+}

http://git-wip-us.apache.org/repos/asf/metron/blob/2dd01b17/metron-stellar/stellar-common/src/main/java/org/apache/metron/stellar/common/shell/specials/SpecialCommand.java
----------------------------------------------------------------------
diff --git 
a/metron-stellar/stellar-common/src/main/java/org/apache/metron/stellar/common/shell/specials/SpecialCommand.java
 
b/metron-stellar/stellar-common/src/main/java/org/apache/metron/stellar/common/shell/specials/SpecialCommand.java
new file mode 100644
index 0000000..a40e1e5
--- /dev/null
+++ 
b/metron-stellar/stellar-common/src/main/java/org/apache/metron/stellar/common/shell/specials/SpecialCommand.java
@@ -0,0 +1,60 @@
+/*
+ *
+ *  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.metron.stellar.common.shell.specials;
+
+import org.apache.metron.stellar.common.shell.StellarShellExecutor;
+import org.apache.metron.stellar.common.shell.StellarResult;
+
+import java.util.function.Function;
+
+/**
+ * A special command that can be run within a Stellar execution
+ * environment.
+ *
+ * Most functionality expected of running Stellar in a shell-like
+ * environment, that is not directly implemented in the Stellar
+ * language itself, is implemented as a SpecialCommand. This
+ * includes magics, doc strings, comments and quit.
+ *
+ * This is typically an action performed on the execution
+ * environment, not something that could be executed within Stellar.
+ */
+public interface SpecialCommand {
+
+  /**
+   * @return A function that when applied to the input buffer returns
+   * true, if this special command should be applied.
+   */
+  Function<String, Boolean> getMatcher();
+
+  /**
+   * @return The name of the command, used for auto-completion.
+   */
+  String getCommand();
+
+  /**
+   * Execute the magic command.
+   * @param expression The expression to execute.
+   * @param executor A stellar execution environment.
+   * @return The result of executing the magic command.
+   */
+  StellarResult execute(String expression, StellarShellExecutor executor);
+}

http://git-wip-us.apache.org/repos/asf/metron/blob/2dd01b17/metron-stellar/stellar-common/src/main/java/org/apache/metron/stellar/dsl/Context.java
----------------------------------------------------------------------
diff --git 
a/metron-stellar/stellar-common/src/main/java/org/apache/metron/stellar/dsl/Context.java
 
b/metron-stellar/stellar-common/src/main/java/org/apache/metron/stellar/dsl/Context.java
index 3dbcc82..9568a05 100644
--- 
a/metron-stellar/stellar-common/src/main/java/org/apache/metron/stellar/dsl/Context.java
+++ 
b/metron-stellar/stellar-common/src/main/java/org/apache/metron/stellar/dsl/Context.java
@@ -34,6 +34,8 @@ public class Context implements Serializable {
     , ZOOKEEPER_CLIENT
     , SERVICE_DISCOVERER
     , STELLAR_CONFIG
+    , CONSOLE
+    , SHELL_VARIABLES
   }
 
   public enum ActivityType {
@@ -72,16 +74,9 @@ public class Context implements Serializable {
   }
 
   public static Context EMPTY_CONTEXT() {
-    return
-            new Context(new HashMap<>()){
-              @Override
-              public Optional<Object> getCapability(String capability) {
-                return Optional.empty();
-              }
-            };
+    return new Context(new HashMap<>()){};
   }
 
-
   private Map<String, Capability> capabilities;
 
   private Context( Map<String, Capability> capabilities) {
@@ -93,7 +88,6 @@ public class Context implements Serializable {
   }
 
   public Optional<Object> getCapability(Enum<?> capability, boolean 
errorIfNotThere) {
-
     return getCapability(capability.toString(), errorIfNotThere);
   }
 

http://git-wip-us.apache.org/repos/asf/metron/blob/2dd01b17/metron-stellar/stellar-common/src/main/scripts/stellar
----------------------------------------------------------------------
diff --git a/metron-stellar/stellar-common/src/main/scripts/stellar 
b/metron-stellar/stellar-common/src/main/scripts/stellar
index 2f1cdbe..7b0f06d 100644
--- a/metron-stellar/stellar-common/src/main/scripts/stellar
+++ b/metron-stellar/stellar-common/src/main/scripts/stellar
@@ -33,4 +33,4 @@ export METRON_VERSION=${project.version}
 export METRON_HOME=/usr/metron/$METRON_VERSION
 export STELLAR_LIB=$(find $METRON_HOME/lib/ -name metron-parsers*.jar)
 export MANAGEMENT_LIB=$(find $METRON_HOME/lib/ -name metron-management*.jar)
-java $JVMFLAGS -cp 
"${CONTRIB:-$METRON_HOME/contrib}:$STELLAR_LIB:$MANAGEMENT_LIB:$HBASE_CONFIGS" 
org.apache.metron.stellar.common.shell.StellarShell "$@"
+java $JVMFLAGS -cp 
"${CONTRIB:-$METRON_HOME/contrib}:$STELLAR_LIB:$MANAGEMENT_LIB:$HBASE_CONFIGS" 
org.apache.metron.stellar.common.shell.cli.StellarShell "$@"

http://git-wip-us.apache.org/repos/asf/metron/blob/2dd01b17/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/common/StellarCompilerTest.java
----------------------------------------------------------------------
diff --git 
a/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/common/StellarCompilerTest.java
 
b/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/common/StellarCompilerTest.java
new file mode 100644
index 0000000..f10ee5c
--- /dev/null
+++ 
b/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/common/StellarCompilerTest.java
@@ -0,0 +1,169 @@
+/*
+ * 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.metron.stellar.common;
+
+import org.apache.metron.stellar.dsl.Context;
+import org.apache.metron.stellar.dsl.Token;
+import org.apache.metron.stellar.dsl.VariableResolver;
+import org.apache.metron.stellar.dsl.functions.resolver.FunctionResolver;
+import org.apache.metron.stellar.common.evaluators.ArithmeticEvaluator;
+import 
org.apache.metron.stellar.common.evaluators.ComparisonExpressionWithOperatorEvaluator;
+import org.apache.metron.stellar.common.evaluators.NumberLiteralEvaluator;
+import org.apache.metron.stellar.common.generated.StellarParser;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import java.util.ArrayDeque;
+import java.util.Deque;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.verify;
+import static org.powermock.api.mockito.PowerMockito.*;
+
+
+@RunWith(PowerMockRunner.class)
+@PrepareForTest({Deque.class, ArithmeticEvaluator.class, 
NumberLiteralEvaluator.class, ComparisonExpressionWithOperatorEvaluator.class})
+public class StellarCompilerTest {
+  VariableResolver variableResolver;
+  FunctionResolver functionResolver;
+  Context context;
+  Deque<Token<?>> tokenStack;
+  ArithmeticEvaluator arithmeticEvaluator;
+  NumberLiteralEvaluator numberLiteralEvaluator;
+  ComparisonExpressionWithOperatorEvaluator 
comparisonExpressionWithOperatorEvaluator;
+  StellarCompiler compiler;
+  StellarCompiler.Expression expression;
+
+  @SuppressWarnings("unchecked")
+  @Before
+  public void setUp() throws Exception {
+    variableResolver = mock(VariableResolver.class);
+    functionResolver = mock(FunctionResolver.class);
+    context = mock(Context.class);
+    tokenStack = new ArrayDeque<>();
+    arithmeticEvaluator = mock(ArithmeticEvaluator.class);
+    numberLiteralEvaluator = mock(NumberLiteralEvaluator.class);
+    comparisonExpressionWithOperatorEvaluator = 
mock(ComparisonExpressionWithOperatorEvaluator.class);
+    expression = new StellarCompiler.Expression(tokenStack);
+    compiler = new StellarCompiler(expression, arithmeticEvaluator, 
numberLiteralEvaluator, comparisonExpressionWithOperatorEvaluator);
+  }
+
+  @Test
+  public void exitIntLiteralShouldProperlyParseStringsAsIntegers() throws 
Exception {
+    StellarParser.IntLiteralContext ctx = 
mock(StellarParser.IntLiteralContext.class);
+    Token result = mock(Token.class);
+    when(ctx.getText()).thenReturn("1000");
+    when(numberLiteralEvaluator.evaluate(ctx, null)).thenReturn(result);
+    compiler.exitIntLiteral(ctx);
+    verify(numberLiteralEvaluator).evaluate(ctx, null);
+    Assert.assertEquals(1, tokenStack.size());
+    Assert.assertEquals(tokenStack.getFirst(), result);
+    verifyZeroInteractions(variableResolver);
+    verifyZeroInteractions(functionResolver);
+    verifyZeroInteractions(context);
+    verifyZeroInteractions(arithmeticEvaluator);
+    verifyZeroInteractions(comparisonExpressionWithOperatorEvaluator);
+  }
+
+  @Test
+  public void exitDoubleLiteralShouldProperlyParseStringsAsDoubles() throws 
Exception {
+    StellarParser.DoubleLiteralContext ctx = 
mock(StellarParser.DoubleLiteralContext.class);
+    Token result = mock(Token.class);
+    when(numberLiteralEvaluator.evaluate(ctx, null)).thenReturn(result);
+    when(ctx.getText()).thenReturn("1000D");
+
+    compiler.exitDoubleLiteral(ctx);
+
+    verify(numberLiteralEvaluator).evaluate(ctx, null);
+    Assert.assertEquals(1, tokenStack.size());
+    Assert.assertEquals(tokenStack.getFirst(), result);
+    verifyZeroInteractions(variableResolver);
+    verifyZeroInteractions(functionResolver);
+    verifyZeroInteractions(context);
+    verifyZeroInteractions(arithmeticEvaluator);
+    verifyZeroInteractions(comparisonExpressionWithOperatorEvaluator);
+  }
+
+  @Test
+  public void exitFloatLiteralShouldProperlyParseStringsAsFloats() throws 
Exception {
+    StellarParser.FloatLiteralContext ctx = 
mock(StellarParser.FloatLiteralContext.class);
+    when(ctx.getText()).thenReturn("1000f");
+    Token result = mock(Token.class);
+    when(numberLiteralEvaluator.evaluate(ctx, null)).thenReturn(result);
+
+    compiler.exitFloatLiteral(ctx);
+
+    verify(numberLiteralEvaluator).evaluate(ctx, null);
+    Assert.assertEquals(1, tokenStack.size());
+    Assert.assertEquals(tokenStack.getFirst(), result);
+    verifyZeroInteractions(variableResolver);
+    verifyZeroInteractions(functionResolver);
+    verifyZeroInteractions(context);
+    verifyZeroInteractions(arithmeticEvaluator);
+    verifyZeroInteractions(comparisonExpressionWithOperatorEvaluator);
+  }
+
+  @Test
+  public void exitLongLiteralShouldProperlyParseStringsAsLongs() throws 
Exception {
+    StellarParser.LongLiteralContext ctx = 
mock(StellarParser.LongLiteralContext.class);
+    when(ctx.getText()).thenReturn("1000l");
+    Token result = mock(Token.class);
+    when(numberLiteralEvaluator.evaluate(ctx, null)).thenReturn(result);
+
+    compiler.exitLongLiteral(ctx);
+
+    verify(numberLiteralEvaluator).evaluate(ctx, null);
+    Assert.assertEquals(1, tokenStack.size());
+    Assert.assertEquals(tokenStack.getFirst(), result);
+    verifyZeroInteractions(variableResolver);
+    verifyZeroInteractions(functionResolver);
+    verifyZeroInteractions(context);
+    verifyZeroInteractions(arithmeticEvaluator);
+    verifyZeroInteractions(comparisonExpressionWithOperatorEvaluator);
+  }
+
+  @Test
+  public void properlyCompareTwoNumbers() throws Exception {
+    StellarParser.ComparisonExpressionWithOperatorContext ctx = 
mock(StellarParser.ComparisonExpressionWithOperatorContext.class);
+    StellarParser.ComparisonOpContext mockOp = 
mock(StellarParser.ComparisonOpContext.class);
+    when(ctx.comp_operator()).thenReturn(mockOp);
+    Token result = mock(Token.class);
+    when(comparisonExpressionWithOperatorEvaluator.evaluate(any(Token.class), 
any(Token.class), any(StellarParser.ComparisonOpContext.class), 
any())).thenReturn(result);
+
+    compiler.exitComparisonExpressionWithOperator(ctx);
+    Assert.assertEquals(1, tokenStack.size());
+    StellarCompiler.DeferredFunction func = (StellarCompiler.DeferredFunction) 
tokenStack.pop().getValue();
+    tokenStack.push(new Token<>(1000, Integer.class, null));
+    tokenStack.push(new Token<>(1500f, Float.class, null));
+    func.apply(tokenStack, new StellarCompiler.ExpressionState(context, 
functionResolver, variableResolver));
+    Assert.assertEquals(1, tokenStack.size());
+    Assert.assertEquals(tokenStack.getFirst(), result);
+    
verify(comparisonExpressionWithOperatorEvaluator).evaluate(any(Token.class), 
any(Token.class), eq(mockOp), any());
+    verifyZeroInteractions(numberLiteralEvaluator);
+    verifyZeroInteractions(variableResolver);
+    verifyZeroInteractions(functionResolver);
+    verifyZeroInteractions(context);
+    verifyZeroInteractions(arithmeticEvaluator);
+  }
+}

http://git-wip-us.apache.org/repos/asf/metron/blob/2dd01b17/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/common/StellarInterpreterTest.java
----------------------------------------------------------------------
diff --git 
a/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/common/StellarInterpreterTest.java
 
b/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/common/StellarInterpreterTest.java
deleted file mode 100644
index 36a7116..0000000
--- 
a/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/common/StellarInterpreterTest.java
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * 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.metron.stellar.common;
-
-import org.apache.metron.stellar.dsl.Context;
-import org.apache.metron.stellar.dsl.Token;
-import org.apache.metron.stellar.dsl.VariableResolver;
-import org.apache.metron.stellar.dsl.functions.resolver.FunctionResolver;
-import org.apache.metron.stellar.common.evaluators.ArithmeticEvaluator;
-import 
org.apache.metron.stellar.common.evaluators.ComparisonExpressionWithOperatorEvaluator;
-import org.apache.metron.stellar.common.evaluators.NumberLiteralEvaluator;
-import org.apache.metron.stellar.common.generated.StellarParser;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.powermock.core.classloader.annotations.PrepareForTest;
-import org.powermock.modules.junit4.PowerMockRunner;
-
-import java.util.ArrayDeque;
-import java.util.Deque;
-
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.verify;
-import static org.powermock.api.mockito.PowerMockito.*;
-
-
-@RunWith(PowerMockRunner.class)
-@PrepareForTest({Deque.class, ArithmeticEvaluator.class, 
NumberLiteralEvaluator.class, ComparisonExpressionWithOperatorEvaluator.class})
-public class StellarInterpreterTest {
-  VariableResolver variableResolver;
-  FunctionResolver functionResolver;
-  Context context;
-  Deque<Token<?>> tokenStack;
-  ArithmeticEvaluator arithmeticEvaluator;
-  NumberLiteralEvaluator numberLiteralEvaluator;
-  ComparisonExpressionWithOperatorEvaluator 
comparisonExpressionWithOperatorEvaluator;
-  StellarCompiler compiler;
-  StellarCompiler.Expression expression;
-
-  @SuppressWarnings("unchecked")
-  @Before
-  public void setUp() throws Exception {
-    variableResolver = mock(VariableResolver.class);
-    functionResolver = mock(FunctionResolver.class);
-    context = mock(Context.class);
-    tokenStack = new ArrayDeque<>();
-    arithmeticEvaluator = mock(ArithmeticEvaluator.class);
-    numberLiteralEvaluator = mock(NumberLiteralEvaluator.class);
-    comparisonExpressionWithOperatorEvaluator = 
mock(ComparisonExpressionWithOperatorEvaluator.class);
-    expression = new StellarCompiler.Expression(tokenStack);
-    compiler = new StellarCompiler(expression, arithmeticEvaluator, 
numberLiteralEvaluator, comparisonExpressionWithOperatorEvaluator);
-  }
-
-  @Test
-  public void exitIntLiteralShouldProperlyParseStringsAsIntegers() throws 
Exception {
-    StellarParser.IntLiteralContext ctx = 
mock(StellarParser.IntLiteralContext.class);
-    Token result = mock(Token.class);
-    when(ctx.getText()).thenReturn("1000");
-    when(numberLiteralEvaluator.evaluate(ctx, null)).thenReturn(result);
-    compiler.exitIntLiteral(ctx);
-    verify(numberLiteralEvaluator).evaluate(ctx, null);
-    Assert.assertEquals(1, tokenStack.size());
-    Assert.assertEquals(tokenStack.getFirst(), result);
-    verifyZeroInteractions(variableResolver);
-    verifyZeroInteractions(functionResolver);
-    verifyZeroInteractions(context);
-    verifyZeroInteractions(arithmeticEvaluator);
-    verifyZeroInteractions(comparisonExpressionWithOperatorEvaluator);
-  }
-
-  @Test
-  public void exitDoubleLiteralShouldProperlyParseStringsAsDoubles() throws 
Exception {
-    StellarParser.DoubleLiteralContext ctx = 
mock(StellarParser.DoubleLiteralContext.class);
-    Token result = mock(Token.class);
-    when(numberLiteralEvaluator.evaluate(ctx, null)).thenReturn(result);
-    when(ctx.getText()).thenReturn("1000D");
-
-    compiler.exitDoubleLiteral(ctx);
-
-    verify(numberLiteralEvaluator).evaluate(ctx, null);
-    Assert.assertEquals(1, tokenStack.size());
-    Assert.assertEquals(tokenStack.getFirst(), result);
-    verifyZeroInteractions(variableResolver);
-    verifyZeroInteractions(functionResolver);
-    verifyZeroInteractions(context);
-    verifyZeroInteractions(arithmeticEvaluator);
-    verifyZeroInteractions(comparisonExpressionWithOperatorEvaluator);
-  }
-
-  @Test
-  public void exitFloatLiteralShouldProperlyParseStringsAsFloats() throws 
Exception {
-    StellarParser.FloatLiteralContext ctx = 
mock(StellarParser.FloatLiteralContext.class);
-    when(ctx.getText()).thenReturn("1000f");
-    Token result = mock(Token.class);
-    when(numberLiteralEvaluator.evaluate(ctx, null)).thenReturn(result);
-
-    compiler.exitFloatLiteral(ctx);
-
-    verify(numberLiteralEvaluator).evaluate(ctx, null);
-    Assert.assertEquals(1, tokenStack.size());
-    Assert.assertEquals(tokenStack.getFirst(), result);
-    verifyZeroInteractions(variableResolver);
-    verifyZeroInteractions(functionResolver);
-    verifyZeroInteractions(context);
-    verifyZeroInteractions(arithmeticEvaluator);
-    verifyZeroInteractions(comparisonExpressionWithOperatorEvaluator);
-  }
-
-  @Test
-  public void exitLongLiteralShouldProperlyParseStringsAsLongs() throws 
Exception {
-    StellarParser.LongLiteralContext ctx = 
mock(StellarParser.LongLiteralContext.class);
-    when(ctx.getText()).thenReturn("1000l");
-    Token result = mock(Token.class);
-    when(numberLiteralEvaluator.evaluate(ctx, null)).thenReturn(result);
-
-    compiler.exitLongLiteral(ctx);
-
-    verify(numberLiteralEvaluator).evaluate(ctx, null);
-    Assert.assertEquals(1, tokenStack.size());
-    Assert.assertEquals(tokenStack.getFirst(), result);
-    verifyZeroInteractions(variableResolver);
-    verifyZeroInteractions(functionResolver);
-    verifyZeroInteractions(context);
-    verifyZeroInteractions(arithmeticEvaluator);
-    verifyZeroInteractions(comparisonExpressionWithOperatorEvaluator);
-  }
-
-  @Test
-  public void properlyCompareTwoNumbers() throws Exception {
-    StellarParser.ComparisonExpressionWithOperatorContext ctx = 
mock(StellarParser.ComparisonExpressionWithOperatorContext.class);
-    StellarParser.ComparisonOpContext mockOp = 
mock(StellarParser.ComparisonOpContext.class);
-    when(ctx.comp_operator()).thenReturn(mockOp);
-    Token result = mock(Token.class);
-    when(comparisonExpressionWithOperatorEvaluator.evaluate(any(Token.class), 
any(Token.class), any(StellarParser.ComparisonOpContext.class), 
any())).thenReturn(result);
-
-    compiler.exitComparisonExpressionWithOperator(ctx);
-    Assert.assertEquals(1, tokenStack.size());
-    StellarCompiler.DeferredFunction func = (StellarCompiler.DeferredFunction) 
tokenStack.pop().getValue();
-    tokenStack.push(new Token<>(1000, Integer.class, null));
-    tokenStack.push(new Token<>(1500f, Float.class, null));
-    func.apply(tokenStack, new StellarCompiler.ExpressionState(context, 
functionResolver, variableResolver));
-    Assert.assertEquals(1, tokenStack.size());
-    Assert.assertEquals(tokenStack.getFirst(), result);
-    
verify(comparisonExpressionWithOperatorEvaluator).evaluate(any(Token.class), 
any(Token.class), eq(mockOp), any());
-    verifyZeroInteractions(numberLiteralEvaluator);
-    verifyZeroInteractions(variableResolver);
-    verifyZeroInteractions(functionResolver);
-    verifyZeroInteractions(context);
-    verifyZeroInteractions(arithmeticEvaluator);
-  }
-}

http://git-wip-us.apache.org/repos/asf/metron/blob/2dd01b17/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/common/shell/DefaultStellarAutoCompleterTest.java
----------------------------------------------------------------------
diff --git 
a/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/common/shell/DefaultStellarAutoCompleterTest.java
 
b/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/common/shell/DefaultStellarAutoCompleterTest.java
new file mode 100644
index 0000000..0d9d5e1
--- /dev/null
+++ 
b/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/common/shell/DefaultStellarAutoCompleterTest.java
@@ -0,0 +1,190 @@
+/*
+ *
+ *  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.metron.stellar.common.shell;
+
+import com.google.common.collect.Lists;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.List;
+
+import static org.hamcrest.CoreMatchers.*;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.Matchers.contains;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Tests the DefaultStellarAutoCompleter class.
+ */
+public class DefaultStellarAutoCompleterTest {
+
+  DefaultStellarAutoCompleter completer;
+
+  @Before
+  public void setup() {
+    completer = new DefaultStellarAutoCompleter();
+  }
+
+  @Test
+  public void testAutoCompleteFunction() {
+
+    // setup some candidate functions for auto-completion
+    completer.addCandidateFunction("FREUD");
+    completer.addCandidateFunction("FRIEND");
+    completer.addCandidateFunction("FOE");
+
+    // need help auto-completer!
+    Iterable<String> result = completer.autoComplete("FR");
+
+    // there are only 2 candidates that make any sense
+    List<String> completes = Lists.newArrayList(result);
+    assertEquals(2, completes.size());
+
+    // these are functions and so should include an opening paren
+    assertThat(completes, hasItem("FREUD("));
+    assertThat(completes, hasItem("FRIEND("));
+  }
+
+  @Test
+  public void testNoCandidateFunctions() {
+
+    // setup some candidate functions for auto-completion
+    completer.addCandidateFunction("FREUD");
+    completer.addCandidateFunction("FRIEND");
+    completer.addCandidateFunction("FOE");
+
+    // need help auto-completer!
+    Iterable<String> result = completer.autoComplete("G");
+
+    // there are no candidates that make any sense
+    List<String> completes = Lists.newArrayList(result);
+    assertEquals(0, completes.size());
+  }
+
+  @Test
+  public void testAutoCompleteVariable() {
+
+    // setup some candidates for auto-completion
+    completer.addCandidateVariable("very");
+    completer.addCandidateVariable("vast");
+    completer.addCandidateVariable("vat");
+
+    // need help auto-completer!
+    Iterable<String> result = completer.autoComplete("va");
+
+    // there are only 2 candidates that make any sense
+    List<String> completes = Lists.newArrayList(result);
+    assertEquals(2, completes.size());
+    assertThat(completes, hasItem("vast"));
+    assertThat(completes, hasItem("vat"));
+  }
+
+  @Test
+  public void testNoCandidateVariable() {
+
+    // setup some candidates for auto-completion
+    completer.addCandidateVariable("very");
+    completer.addCandidateVariable("vast");
+    completer.addCandidateVariable("vat");
+
+    // need help auto-completer!
+    Iterable<String> result = completer.autoComplete("x");
+
+    // there are only no candidates that make any sense
+    List<String> completes = Lists.newArrayList(result);
+    assertEquals(0, completes.size());
+  }
+
+  @Test
+  public void testAutoCompleteDocString() {
+
+    // setup some candidate functions for auto-completion
+    completer.addCandidateFunction("FREUD");
+    completer.addCandidateFunction("FRIEND");
+    completer.addCandidateFunction("FOE");
+
+    // need help auto-completer!
+    Iterable<String> result = completer.autoComplete("?FR");
+
+    // there are only 2 candidates that make any sense
+    List<String> completes = Lists.newArrayList(result);
+    assertEquals(2, completes.size());
+
+    // the suggestions should include the docstring prefix
+    assertThat(completes, hasItem("?FREUD"));
+    assertThat(completes, hasItem("?FRIEND"));
+  }
+
+  @Test
+  public void testNoCandidateDocStrings() {
+
+    // setup some candidate functions for auto-completion
+    completer.addCandidateFunction("FREUD");
+    completer.addCandidateFunction("FRIEND");
+    completer.addCandidateFunction("FOE");
+
+    // need help auto-completer!
+    Iterable<String> result = completer.autoComplete("?G");
+
+    // there are only no candidates that make any sense
+    List<String> completes = Lists.newArrayList(result);
+    assertEquals(0, completes.size());
+  }
+
+  @Test
+  public void testAutoCompleteMagic() {
+
+    // setup some candidate functions for auto-completion
+    completer.addCandidateFunction("%vars");
+    completer.addCandidateFunction("%vast");
+    completer.addCandidateFunction("%verbotten");
+
+    // need help auto-completer!
+    Iterable<String> result = completer.autoComplete("%va");
+
+    // there are only 2 candidates that make any sense
+    List<String> completes = Lists.newArrayList(result);
+    assertEquals(2, completes.size());
+
+    // the suggestions should include the docstring prefix
+    assertThat(completes, hasItem("%vars"));
+    assertThat(completes, hasItem("%vast"));
+  }
+
+  @Test
+  public void testNoCandidateMagic() {
+
+    // setup some candidate functions for auto-completion
+    completer.addCandidateFunction("%vars");
+    completer.addCandidateFunction("%vast");
+    completer.addCandidateFunction("%verbotten");
+
+    // need help auto-completer!
+    Iterable<String> result = completer.autoComplete("%xy");
+
+    // there are only no candidates that make any sense
+    List<String> completes = Lists.newArrayList(result);
+    assertEquals(0, completes.size());
+  }
+}

http://git-wip-us.apache.org/repos/asf/metron/blob/2dd01b17/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/common/shell/DefaultStellarShellExecutorTest.java
----------------------------------------------------------------------
diff --git 
a/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/common/shell/DefaultStellarShellExecutorTest.java
 
b/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/common/shell/DefaultStellarShellExecutorTest.java
new file mode 100644
index 0000000..ebba84f
--- /dev/null
+++ 
b/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/common/shell/DefaultStellarShellExecutorTest.java
@@ -0,0 +1,298 @@
+/*
+ *
+ *  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.metron.stellar.common.shell;
+
+import com.google.common.collect.ImmutableMap;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Properties;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Tests the DefaultStellarShellExecutor class.
+ */
+public class DefaultStellarShellExecutorTest {
+
+  DefaultStellarShellExecutor executor;
+  boolean notified;
+
+  @Before
+  public void setup() throws Exception {
+    Properties props = new Properties();
+    executor = new DefaultStellarShellExecutor(props, Optional.empty());
+    executor.init();
+  }
+
+  @Test
+  public void testAssignment() {
+
+    // x = 2 + 2
+    {
+      StellarResult result = executor.execute("x := 2 + 2");
+      assertTrue(result.isSuccess());
+      assertTrue(result.getValue().isPresent());
+      assertEquals(4, result.getValue().get());
+      assertEquals(4, executor.getVariables().get("x"));
+    }
+
+    // y = x + 2
+    {
+      StellarResult result = executor.execute("y := x + 2");
+      assertTrue(result.isSuccess());
+      assertTrue(result.getValue().isPresent());
+      assertEquals(6, result.getValue().get());
+      assertEquals(6, executor.getVariables().get("y"));
+    }
+
+    // z = x + y
+    {
+      StellarResult result = executor.execute("z := x + y");
+      assertTrue(result.isSuccess());
+      assertTrue(result.getValue().isPresent());
+      assertEquals(10, result.getValue().get());
+      assertEquals(10, executor.getVariables().get("z"));
+    }
+  }
+
+  @Test
+  @SuppressWarnings("unchecked")
+  public void testAssignmentOfLists() {
+    List<Integer> expected = Arrays.asList(1,2,3,4,5);
+
+    // assign a list to a variable
+    StellarResult result = executor.execute("x := [1,2,3,4,5]");
+
+    // the result should be a list
+    assertTrue(result.isSuccess());
+    assertTrue(result.getValue().isPresent());
+    assertEquals(expected, result.getValue().get());
+
+    // the variable should also be the same list
+    List<Integer> variable = (List<Integer>) executor.getVariables().get("x");
+    assertEquals(expected, variable);
+  }
+
+  @Test
+  @SuppressWarnings("unchecked")
+  public void testAssignmentOfMaps() {
+    Map<String, Integer> expected = ImmutableMap.<String, Integer>builder()
+            .put("a", 10)
+            .put("b", 20)
+            .build();
+
+    // assign a list to a variable
+    StellarResult result = executor.execute("x := {'a':10, 'b':20}");
+
+    // the result should be a map
+    assertTrue(result.isSuccess());
+    assertTrue(result.getValue().isPresent());
+    assertEquals(expected, result.getValue().get());
+
+    // the variable should also be the same list
+    Map<String, Integer> variable = (Map<String, Integer>) 
executor.getVariables().get("x");
+    assertEquals(expected, variable);
+  }
+
+  @Test
+  public void testAssignmentWithOddWhitespace() {
+    StellarResult result = executor.execute("   x   :=    2 +      2      ");
+    assertTrue(result.isSuccess());
+    assertTrue(result.getValue().isPresent());
+    assertEquals(4, result.getValue().get());
+    assertEquals(4, executor.getVariables().get("x"));
+  }
+
+  @Test
+  public void testBadAssignment() {
+    StellarResult result = executor.execute("x := 2 + ");
+    assertTrue(result.isError());
+    assertTrue(result.getException().isPresent());
+  }
+
+  @Test
+  public void testExpression() {
+    StellarResult result = executor.execute("2 + 2");
+    assertTrue(result.isSuccess());
+    assertTrue(result.getValue().isPresent());
+    assertEquals(4, result.getValue().get());
+  }
+
+  @Test
+  public void testExpressionWithOddWhitespace() {
+    StellarResult result = executor.execute("    2    +    2");
+    assertTrue(result.isSuccess());
+    assertTrue(result.getValue().isPresent());
+    assertEquals(4, result.getValue().get());
+  }
+
+  @Test
+  public void testBadExpression() {
+    StellarResult result = executor.execute("2 + ");
+    assertTrue(result.isError());
+    assertTrue(result.getException().isPresent());
+  }
+
+  @Test
+  public void testMagicCommand() {
+    // create a var that we can see with the magic command
+    executor.execute("x := 2 + 2");
+
+    // just testing that we can execute the magic, not the actual result
+    StellarResult result = executor.execute("%vars");
+    assertTrue(result.isSuccess());
+    assertTrue(result.getValue().isPresent());
+    assertNotNull(result.getValue().get());
+  }
+
+  @Test
+  public void testDefineGlobal() {
+
+    // create a global var
+    executor.execute("%define x := 2");
+
+    assertFalse(executor.getVariables().containsKey("x"));
+
+    // the global should have been defined
+    assertEquals(2, executor.getGlobalConfig().get("x"));
+  }
+
+  @Test
+  public void testBadMagicCommand() {
+    StellarResult result = executor.execute("%invalid");
+    assertTrue(result.isError());
+    assertTrue(result.getException().isPresent());
+  }
+
+  @Test
+  public void testDocCommand() {
+    // just testing that we can execute the doc, not the actual result
+    StellarResult result = executor.execute("?TO_STRING");
+    assertTrue(result.isSuccess());
+    assertTrue(result.getValue().isPresent());
+    assertNotNull(result.getValue().get());
+  }
+
+  @Test
+  public void testBadDocCommand() {
+    StellarResult result = executor.execute("?INVALID");
+    assertTrue(result.isError());
+    assertTrue(result.getException().isPresent());
+  }
+
+  @Test
+  public void testQuit() {
+    StellarResult result = executor.execute("quit");
+    assertTrue(result.isTerminate());
+  }
+
+  @Test
+  public void testAssign() {
+    {
+      // this is how variables get loaded into the REPL directly from a file
+      executor.assign("x", 10, Optional.empty());
+    }
+    {
+      StellarResult result = executor.execute("x + 2");
+      assertTrue(result.isSuccess());
+      assertTrue(result.getValue().isPresent());
+      assertEquals(12, result.getValue().get());
+    }
+  }
+
+  @Test
+  public void testNotifyVariableListeners() {
+    notified = false;
+    executor.addVariableListener((var, value) -> {
+      assertEquals("x", var);
+      assertEquals(4, value.getResult());
+      notified = true;
+    });
+
+    executor.execute("x := 2 + 2");
+    assertTrue(notified);
+  }
+
+  @Test
+  public void testNotifySpecialListeners() throws Exception {
+
+    // setup an executor
+    notified = false;
+    Properties props = new Properties();
+    DefaultStellarShellExecutor executor = new 
DefaultStellarShellExecutor(props, Optional.empty());
+
+    // setup listener
+    notified = false;
+    executor.addSpecialListener((magic) -> {
+      assertNotNull(magic);
+      assertNotNull(magic.getCommand());
+      notified = true;
+    });
+
+    // initialize... magics should be setup during initialization
+    executor.init();
+    assertTrue(notified);
+  }
+
+  @Test
+  public void testNotifyFunctionListeners() throws Exception {
+    // setup an executor
+    notified = false;
+    Properties props = new Properties();
+    DefaultStellarShellExecutor executor = new 
DefaultStellarShellExecutor(props, Optional.empty());
+
+    // setup listener
+    notified = false;
+    executor.addFunctionListener((fn) -> {
+      assertNotNull(fn);
+      assertNotNull(fn.getName());
+      assertNotNull(fn.getFunction());
+      notified = true;
+    });
+
+    // initialize... magics should be setup during initialization
+    executor.init();
+    assertTrue(notified);
+  }
+
+  @Test
+  public void testEmptyInput() {
+    StellarResult result = executor.execute("");
+    assertTrue(result.isSuccess());
+    assertTrue(result.getValue().isPresent());
+    assertEquals("", result.getValue().get());
+  }
+
+  @Test
+  public void testComment() {
+    StellarResult result = executor.execute("# this is a comment");
+    assertTrue(result.isSuccess());
+    assertTrue(result.getValue().isPresent());
+    assertEquals("", result.getValue().get());
+  }
+}

http://git-wip-us.apache.org/repos/asf/metron/blob/2dd01b17/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/common/shell/StellarResultTest.java
----------------------------------------------------------------------
diff --git 
a/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/common/shell/StellarResultTest.java
 
b/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/common/shell/StellarResultTest.java
new file mode 100644
index 0000000..6431ee3
--- /dev/null
+++ 
b/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/common/shell/StellarResultTest.java
@@ -0,0 +1,165 @@
+/*
+ *
+ *  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.metron.stellar.common.shell;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertFalse;
+
+public class StellarResultTest {
+
+  /**
+   * Tests the 'success' method which is used to retrieve a StellarShellResult
+   * indicating success.
+   */
+  @Test
+  public void testSuccess() {
+    final int expected = 2;
+
+    // retrieve a result that indicates success
+    StellarResult result = StellarResult.success(expected);
+    assertNotNull(result);
+
+    // validate the value
+    assertTrue(result.getValue().isPresent());
+    assertEquals(expected, result.getValue().get());
+
+    // validate the exception
+    assertFalse(result.getException().isPresent());
+
+    // validate status
+    assertEquals(StellarResult.Status.SUCCESS, result.getStatus());
+    assertTrue(result.isSuccess());
+    assertFalse(result.isError());
+    assertFalse(result.isTerminate());
+  }
+
+  /**
+   * Tests the 'error' method which is used to retrieve a StellarShellResult
+   * indicating that an error occurred.
+   */
+  @Test
+  public void testError() {
+    final String expected = "my error message";
+
+    // retrieve a result that indicates success
+    StellarResult result = StellarResult.error(expected);
+    assertNotNull(result);
+
+    // validate the value
+    assertFalse(result.getValue().isPresent());
+
+    // validate the exception
+    assertTrue(result.getException().isPresent());
+    assertEquals(expected, result.getException().get().getMessage());
+
+    // validate status
+    assertEquals(StellarResult.Status.ERROR, result.getStatus());
+    assertFalse(result.isSuccess());
+    assertTrue(result.isError());
+    assertFalse(result.isTerminate());
+  }
+
+  /**
+   * Tests the 'terminate' method which is used to retrieve a 
StellarShellResult
+   * indicating that a termination request was made.
+   */
+  @Test
+  public void testTerminate() {
+
+    // retrieve a result that indicates success
+    StellarResult result = StellarResult.terminate();
+    assertNotNull(result);
+
+    // validate the value
+    assertTrue(result.getValue().isPresent());
+
+    // validate the exception
+    assertFalse(result.getException().isPresent());
+
+    // validate status
+    assertEquals(StellarResult.Status.TERMINATE, result.getStatus());
+    assertFalse(result.isSuccess());
+    assertFalse(result.isError());
+    assertTrue(result.isTerminate());
+  }
+
+  /**
+   * Tests the 'noop' method which is used to retrieve a StellarShellResult
+   * indicating that no operation occurred, nor was required.
+   */
+  @Test
+  public void testNoop() {
+
+    // retrieve a result that indicates success
+    StellarResult result = StellarResult.noop();
+    assertNotNull(result);
+
+    // validate the value
+    assertTrue(result.getValue().isPresent());
+
+    // validate the exception
+    assertFalse(result.getException().isPresent());
+
+    // validate status
+    assertEquals(StellarResult.Status.SUCCESS, result.getStatus());
+    assertTrue(result.isSuccess());
+    assertFalse(result.isError());
+    assertFalse(result.isTerminate());
+  }
+
+  /**
+   * A success result where the value is null is perfectly acceptable.
+   */
+  @Test
+  public void testSuccessWithNull() {
+    final Object expected = null;
+
+    // retrieve a result that indicates success
+    StellarResult result = StellarResult.success(expected);
+    assertNotNull(result);
+
+    // validate the value
+    assertTrue(result.isValueNull());
+
+    // validate the exception
+    assertFalse(result.getException().isPresent());
+
+    // validate status
+    assertEquals(StellarResult.Status.SUCCESS, result.getStatus());
+    assertTrue(result.isSuccess());
+    assertFalse(result.isError());
+    assertFalse(result.isTerminate());
+  }
+
+  /**
+   * Tests the behavior of isValueNull() with error, noop and terminate 
conditions.
+   */
+  @Test
+  public void testNonSuccessWithNull() {
+    assertFalse(StellarResult.error(new Exception()).isValueNull());
+    assertFalse(StellarResult.error("error msg").isValueNull());
+    assertFalse(StellarResult.noop().isValueNull());
+    assertFalse(StellarResult.terminate().isValueNull());
+  }
+}

http://git-wip-us.apache.org/repos/asf/metron/blob/2dd01b17/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/common/shell/StellarShellOptionsValidatorTest.java
----------------------------------------------------------------------
diff --git 
a/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/common/shell/StellarShellOptionsValidatorTest.java
 
b/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/common/shell/StellarShellOptionsValidatorTest.java
deleted file mode 100644
index 67a8ae7..0000000
--- 
a/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/common/shell/StellarShellOptionsValidatorTest.java
+++ /dev/null
@@ -1,187 +0,0 @@
-/*
- *
- *  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.metron.stellar.common.shell;
-
-import org.apache.commons.cli.CommandLine;
-import org.apache.commons.cli.CommandLineParser;
-import org.apache.commons.cli.Options;
-import org.apache.commons.cli.PosixParser;
-import org.junit.Assert;
-import org.junit.Test;
-
-import java.io.File;
-import java.util.regex.Pattern;
-
-import static org.junit.Assert.*;
-
-public class StellarShellOptionsValidatorTest {
-
-  @Test
-  public void validateOptions() throws Exception {
-    String[] validZHostArg = new String[]{"-z", "localhost:8888"};
-    String[] validZHostArgNoPort = new String[]{"-z", "localhost"};
-    String[] validZIPArgNoPort = new String[]{"-z", "10.10.10.3"};
-    String[] validZHostArgList = new String[]{"-z", 
"localhost:8888,localhost:2181,localhost"};
-    String[] validZIPArg = new String[]{"-z", "10.10.10.3:9999"};
-    String[] invalidZNameArg = new String[]{"-z", "!!!@!!@!:8882"};
-    String[] invalidZIPArg = new String[]{"-z", "11111.22222.10.3:3332"};
-    String[] invalidZMissingNameArg = new String[]{"-z", ":8882"};
-    String[] invalidZZeroPortArg = new String[]{"-z", "youtube.com:0"};
-    String[] invalidZHugePortArg = new String[]{"-z", "youtube.com:75565"};
-
-
-    String existingFileName = "./target/existsFile";
-    String nonExistentFile = "./target/doesNotExist";
-
-    String[] validVFileArg = new String[]{"-v", existingFileName};
-    String[] validIrcFileArg = new String[]{"-irc", existingFileName};
-    String[] validPFileArg = new String[]{"-p", existingFileName};
-    String[] invalidVFileArg = new String[]{"-v", nonExistentFile};
-    String[] invalidIrcFileArg = new String[]{"-irc", nonExistentFile};
-    String[] invalidPFileArg = new String[]{"-p", nonExistentFile};
-
-    File existingFile = new File(existingFileName);
-    if (!existingFile.exists()) {
-      existingFile.createNewFile();
-    }
-    Options options = new Options();
-    options.addOption("z", "zookeeper", true, "Zookeeper URL");
-    options.addOption("v", "variables", true, "File containing a JSON Map of 
variables");
-    options.addOption("irc", "inputrc", true,
-        "File containing the inputrc if not the default ~/.inputrc");
-    options.addOption("na", "no_ansi", false, "Make the input prompt not use 
ANSI colors.");
-    options.addOption("h", "help", false, "Print help");
-    options.addOption("p", "properties", true, "File containing Stellar 
properties");
-
-    CommandLineParser parser = new PosixParser();
-
-    // these should work
-    CommandLine commandLine = parser.parse(options, validZHostArg);
-    StellarShellOptionsValidator.validateOptions(commandLine);
-
-    commandLine = parser.parse(options, validZIPArg);
-    StellarShellOptionsValidator.validateOptions(commandLine);
-
-    commandLine = parser.parse(options, validVFileArg);
-    StellarShellOptionsValidator.validateOptions(commandLine);
-
-    commandLine = parser.parse(options, validIrcFileArg);
-    StellarShellOptionsValidator.validateOptions(commandLine);
-
-    commandLine = parser.parse(options, validPFileArg);
-    StellarShellOptionsValidator.validateOptions(commandLine);
-
-    commandLine = parser.parse(options, validZHostArgNoPort);
-    StellarShellOptionsValidator.validateOptions(commandLine);
-
-    commandLine = parser.parse(options, validZHostArgList);
-    StellarShellOptionsValidator.validateOptions(commandLine);
-
-    commandLine = parser.parse(options, validZIPArgNoPort);
-    StellarShellOptionsValidator.validateOptions(commandLine);
-    // these should not
-
-    boolean thrown = false;
-
-
-    try {
-      commandLine = parser.parse(options, invalidZNameArg);
-      StellarShellOptionsValidator.validateOptions(commandLine);
-    } catch (IllegalArgumentException e) {
-      thrown = true;
-    }
-    Assert.assertTrue("Did not catch failure for providing invalid host name 
", thrown);
-    thrown = false;
-
-    try {
-      commandLine = parser.parse(options, invalidZIPArg);
-      StellarShellOptionsValidator.validateOptions(commandLine);
-    } catch (IllegalArgumentException e) {
-      thrown = true;
-    }
-    Assert.assertTrue("Did not catch failure for providing invalid ip address 
", thrown);
-    thrown = false;
-
-    try {
-      commandLine = parser.parse(options, invalidZMissingNameArg);
-      StellarShellOptionsValidator.validateOptions(commandLine);
-    } catch (IllegalArgumentException e) {
-      thrown = true;
-    }
-    Assert.assertTrue("Did not catch failure for only providing port ", 
thrown);
-    thrown = false;
-
-    try {
-      commandLine = parser.parse(options, invalidZZeroPortArg);
-      StellarShellOptionsValidator.validateOptions(commandLine);
-    } catch (IllegalArgumentException e) {
-      thrown = true;
-    }
-    Assert.assertTrue("Did not catch failure for 0 port ", thrown);
-    thrown = false;
-
-    try {
-      commandLine = parser.parse(options, invalidZHugePortArg);
-      StellarShellOptionsValidator.validateOptions(commandLine);
-    } catch (IllegalArgumentException e) {
-      thrown = true;
-    }
-    Assert.assertTrue("Did not catch failure for port out of range ", thrown);
-    thrown = false;
-
-    try {
-      commandLine = parser.parse(options, invalidVFileArg);
-      StellarShellOptionsValidator.validateOptions(commandLine);
-    } catch (IllegalArgumentException e) {
-      thrown = true;
-    }
-    Assert.assertTrue("Did not catch failure for passing non-existant file to 
-v ", thrown);
-    thrown = false;
-
-    try {
-      commandLine = parser.parse(options, invalidVFileArg);
-      StellarShellOptionsValidator.validateOptions(commandLine);
-    } catch (IllegalArgumentException e) {
-      thrown = true;
-    }
-    Assert.assertTrue("Did not catch failure for passing non-existant file to 
-v ", thrown);
-    thrown = false;
-
-    try {
-      commandLine = parser.parse(options, invalidIrcFileArg);
-      StellarShellOptionsValidator.validateOptions(commandLine);
-    } catch (IllegalArgumentException e) {
-      thrown = true;
-    }
-    Assert.assertTrue("Did not catch failure for passing non-existant file to 
-irc ", thrown);
-    thrown = false;
-
-    try {
-      commandLine = parser.parse(options, invalidPFileArg);
-      StellarShellOptionsValidator.validateOptions(commandLine);
-    } catch (IllegalArgumentException e) {
-      thrown = true;
-    }
-    Assert.assertTrue("Did not catch failure for passing non-existant file to 
-p ", thrown);
-    thrown = false;
-  }
-
-}
\ No newline at end of file

Reply via email to