http://git-wip-us.apache.org/repos/asf/metron/blob/a5b13777/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
new file mode 100644
index 0000000..72d3f74
--- /dev/null
+++ b/metron-stellar/stellar-common/src/main/scripts/stellar
@@ -0,0 +1,34 @@
+#!/bin/bash
+#
+# 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.
+#
+
+
+BIGTOP_DEFAULTS_DIR=${BIGTOP_DEFAULTS_DIR-/etc/default}
+[ -n "${BIGTOP_DEFAULTS_DIR}" -a -r ${BIGTOP_DEFAULTS_DIR}/hbase ] && . 
${BIGTOP_DEFAULTS_DIR}/hbase
+
+# Autodetect JAVA_HOME if not defined
+if [ -e /usr/libexec/bigtop-detect-javahome ]; then
+  . /usr/libexec/bigtop-detect-javahome
+elif [ -e /usr/lib/bigtop-utils/bigtop-detect-javahome ]; then
+  . /usr/lib/bigtop-utils/bigtop-detect-javahome
+fi
+
+export HBASE_CONFIGS=/etc/hbase/conf
+export METRON_VERSION=${project.version}
+export METRON_HOME=/usr/metron/$METRON_VERSION
+java $JVMFLAGS -cp "$HBASE_CONFIGS:$METRON_HOME/lib/*" 
org.apache.metron.stellar.stellar.shell.StellarShell "$@"

http://git-wip-us.apache.org/repos/asf/metron/blob/a5b13777/metron-stellar/stellar-common/src/test/classpath-resources/custom-1.0-SNAPSHOT.jar
----------------------------------------------------------------------
diff --git 
a/metron-stellar/stellar-common/src/test/classpath-resources/custom-1.0-SNAPSHOT.jar
 
b/metron-stellar/stellar-common/src/test/classpath-resources/custom-1.0-SNAPSHOT.jar
new file mode 100644
index 0000000..7007eda
Binary files /dev/null and 
b/metron-stellar/stellar-common/src/test/classpath-resources/custom-1.0-SNAPSHOT.jar
 differ

http://git-wip-us.apache.org/repos/asf/metron/blob/a5b13777/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/common/BaseStellarProcessorTest.java
----------------------------------------------------------------------
diff --git 
a/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/common/BaseStellarProcessorTest.java
 
b/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/common/BaseStellarProcessorTest.java
new file mode 100644
index 0000000..4caca42
--- /dev/null
+++ 
b/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/common/BaseStellarProcessorTest.java
@@ -0,0 +1,116 @@
+/*
+ * 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.ParseException;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import static org.junit.Assert.*;
+
+@SuppressWarnings("ALL")
+public class BaseStellarProcessorTest {
+  @Rule
+  public final ExpectedException exception = ExpectedException.none();
+
+  BaseStellarProcessor<Object> processor;
+
+  @Before
+  public void setUp() throws Exception {
+    processor = new BaseStellarProcessor<>(Object.class);
+  }
+
+  @Test
+  public void makeSureBasicValidationIsWorking() throws Exception {
+    {
+      assertTrue(processor.validate(""));
+      assertTrue(processor.validate(null));
+      assertTrue(processor.validate("'ah'"));
+      assertTrue(processor.validate("true"));
+      assertTrue(processor.validate("1"));
+      assertTrue(processor.validate("1L"));
+      assertTrue(processor.validate("1F"));
+      assertTrue(processor.validate("1 < 2 // always true"));
+      assertTrue(processor.validate("1 < foo"));
+      assertTrue(processor.validate("(1 < foo)"));
+      assertTrue(processor.validate("foo < bar"));
+      assertTrue(processor.validate("foo < TO_FLOAT(bar)", false, 
Context.EMPTY_CONTEXT()));
+      assertTrue(processor.validate("if true then b else c"));
+      assertTrue(processor.validate("IF false THEN b ELSE c"));
+    }
+
+    {
+      assertFalse(processor.validate("'", false, Context.EMPTY_CONTEXT()));
+      assertFalse(processor.validate("(", false, Context.EMPTY_CONTEXT()));
+      assertFalse(processor.validate("()", false, Context.EMPTY_CONTEXT()));
+      assertFalse(processor.validate("'foo", false, Context.EMPTY_CONTEXT()));
+      assertFalse(processor.validate("foo << foo", false, 
Context.EMPTY_CONTEXT()));
+      assertFalse(processor.validate("1-1", false, Context.EMPTY_CONTEXT()));
+      assertFalse(processor.validate("1 -1", false, Context.EMPTY_CONTEXT()));
+      assertFalse(processor.validate("If a then b else c", false, 
Context.EMPTY_CONTEXT()));
+    }
+  }
+
+  @Test
+  public void validateShouldProperlyThrowExceptionOnInvalidStellarExpression() 
throws Exception {
+    exception.expect(ParseException.class);
+    exception.expectMessage("Unable to parse ': ");
+
+    processor.validate("'", true, Context.EMPTY_CONTEXT());
+  }
+
+  @Test
+  public void 
validateShouldProperlyThrowExceptionByDefaultOnInvalidStellarExpression() 
throws Exception {
+    exception.expect(ParseException.class);
+    exception.expectMessage("Unable to parse ': ");
+
+    processor.validate("'", Context.EMPTY_CONTEXT());
+  }
+
+  @Test
+  public void 
validateShouldProperlyThrowExceptionByDefaultOnInvalidStellarExpression2() 
throws Exception {
+    exception.expect(ParseException.class);
+    exception.expectMessage("Unable to parse ': ");
+
+    processor.validate("'");
+  }
+
+  @Test
+  public void validateMethodShouldFailOnUnknownFunctions() throws Exception {
+    exception.expect(ParseException.class);
+    exception.expectMessage(" Unable to resolve function named 
'UNKNOWN_FUNCTION'.");
+
+    assertTrue(processor.validate("1 < UNKNOWN_FUNCTION(3)", 
Context.EMPTY_CONTEXT()));
+  }
+
+  @Test
+  public void validateMethodShouldNotFailOnUnknownvariables() throws Exception 
{
+    assertTrue(processor.validate("unknown_variable\n\n"));
+    assertTrue(processor.validate("unknown_variable > 2", 
Context.EMPTY_CONTEXT()));
+  }
+
+  @Test
+  public void makeSureBasicLexerErrorsAreCaughtDuringValidation() throws 
Exception {
+    assertFalse(processor.validate("true †", false, 
Context.EMPTY_CONTEXT()));
+    assertFalse(processor.validate("¢ (1 + 2)", false, 
Context.EMPTY_CONTEXT()));
+  }
+}

http://git-wip-us.apache.org/repos/asf/metron/blob/a5b13777/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/common/DefaultStellarStatefulExecutorTest.java
----------------------------------------------------------------------
diff --git 
a/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/common/DefaultStellarStatefulExecutorTest.java
 
b/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/common/DefaultStellarStatefulExecutorTest.java
new file mode 100644
index 0000000..8c55d7d
--- /dev/null
+++ 
b/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/common/DefaultStellarStatefulExecutorTest.java
@@ -0,0 +1,189 @@
+/*
+ *
+ *  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.adrianwalker.multilinestring.Multiline;
+import org.apache.metron.stellar.dsl.Context;
+import 
org.apache.metron.stellar.dsl.functions.resolver.ClasspathFunctionResolver;
+import org.json.simple.JSONObject;
+import org.json.simple.parser.JSONParser;
+import org.json.simple.parser.ParseException;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.instanceOf;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Tests the DefaultStellarStatefulExecutor.
+ */
+@SuppressWarnings("unchecked")
+// This test class passes raw JSONObject to the the executor, which gives 
unchecked cast warnings.
+// Suppressing on the class level, given that every test is a typical example 
of use pattern.
+public class DefaultStellarStatefulExecutorTest {
+
+  /**
+   * {
+   *   "ip_src_addr": "10.0.0.1",
+   *   "ip_dst_addr": "10.0.0.20"
+   * }
+   */
+  @Multiline
+  private String input;
+
+  private JSONObject message;
+  private DefaultStellarStatefulExecutor executor;
+
+  @Before
+  public void setup() throws ParseException {
+
+    // parse the input message
+    JSONParser parser = new JSONParser();
+    message = (JSONObject) parser.parse(input);
+
+    // create the executor to test
+    executor = new DefaultStellarStatefulExecutor();
+    executor.setContext(Context.EMPTY_CONTEXT());
+
+    ClasspathFunctionResolver resolver = new ClasspathFunctionResolver();
+    executor.setFunctionResolver(resolver);
+  }
+
+  /**
+   * Ensure that a value can be assigned to a variable.
+   */
+  @Test
+  public void testAssign() {
+    executor.assign("foo", "2", message);
+
+    // verify
+    Object var = executor.getState().get("foo");
+    assertThat(var, instanceOf(Integer.class));
+    assertThat(var, equalTo(2));
+  }
+
+  /**
+   * Ensure that a variable can be resolved from a message field.
+   */
+  @Test
+  public void testAssignWithVariableResolution() {
+    executor.assign("foo", "ip_src_addr", message);
+
+    // verify
+    Object var = executor.getState().get("foo");
+    assertThat(var, instanceOf(String.class));
+    assertThat(var, equalTo("10.0.0.1"));
+  }
+
+  /**
+   * Ensure that state is maintained correctly in the execution environment.
+   */
+  @Test
+  public void testState() {
+    executor.assign("two", "2", message);
+    executor.assign("four", "4", message);
+    executor.assign("sum", "two + four", message);
+
+    // verify
+    Object var = executor.getState().get("sum");
+    assertEquals(6, var);
+  }
+
+  /**
+   * Ensure that state is maintained correctly in the execution environment.
+   */
+  @Test
+  public void testClearState() {
+    executor.assign("two", "2", message);
+    executor.clearState();
+
+    // verify
+    assertThat(executor.getState().containsKey("two"), equalTo(false));
+  }
+
+  /**
+   * Ensure that a Transformation function can be executed.
+   *
+   * There are two sets of functions in Stellar currently.  One can be 
executed with
+   * a PredicateProcessor and the other a TransformationProcessor.  The 
StellarStatefulExecutor
+   * abstracts away that complication.
+   */
+  @Test
+  public void testExecuteTransformation() {
+    String actual = executor.execute("TO_UPPER('lowercase')", message, 
String.class);
+    assertThat(actual, equalTo("LOWERCASE"));
+  }
+
+  /**
+   * Ensure that a Predicate function can be executed.
+   *
+   * There are two sets of functions in Stellar currently.  One can be 
executed with
+   * a PredicateProcessor and the other a TransformationProcessor.  The 
StellarStatefulExecutor
+   * abstracts away that complication.
+   */
+  @Ignore  //until field validations avail to Stellar
+  @Test
+  public void testExecutePredicate() {
+    boolean actual = executor.execute("IS_INTEGER(2)", message, Boolean.class);
+    assertThat(actual, equalTo(true));
+  }
+
+  /**
+   * An exception is expected if an expression results in an unexpected type.
+   */
+  @Test(expected = RuntimeException.class)
+  public void testExecuteWithWrongType() {
+    executor.execute("2 + 2", message, Boolean.class);
+  }
+
+  /**
+   * A best effort should be made to do sensible type conversions.
+   */
+  @Test
+  public void testExecuteWithTypeConversion() {
+    executor.execute("2", message, Double.class);
+    executor.execute("2", message, Float.class);
+    executor.execute("2", message, Short.class);
+    executor.execute("2", message, Long.class);
+  }
+
+  /**
+   * The executor must be serializable.
+   */
+  @Test
+  public void testSerializable() throws Exception {
+
+    // serialize
+    ByteArrayOutputStream bytes = new ByteArrayOutputStream();
+    new ObjectOutputStream(bytes).writeObject(executor);
+
+    // deserialize - success when no exceptions
+    new ObjectInputStream(new 
ByteArrayInputStream(bytes.toByteArray())).readObject();
+  }
+}

http://git-wip-us.apache.org/repos/asf/metron/blob/a5b13777/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/common/StellarArithmeticTest.java
----------------------------------------------------------------------
diff --git 
a/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/common/StellarArithmeticTest.java
 
b/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/common/StellarArithmeticTest.java
new file mode 100644
index 0000000..841ab5b
--- /dev/null
+++ 
b/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/common/StellarArithmeticTest.java
@@ -0,0 +1,332 @@
+/*
+ * 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 com.google.common.collect.ImmutableMap;
+import org.apache.commons.lang3.tuple.Pair;
+import org.apache.metron.stellar.dsl.ParseException;
+import org.apache.metron.stellar.dsl.Token;
+import org.junit.Assert;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.apache.metron.stellar.common.utils.StellarProcessorUtils.run;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+@SuppressWarnings("unchecked")
+public class StellarArithmeticTest {
+  @Rule
+  public final ExpectedException exception = ExpectedException.none();
+
+  @Test
+  public void addingLongsShouldYieldLong() throws Exception {
+    final long timestamp = 1452013350000L;
+    String query = "TO_EPOCH_TIMESTAMP('2016-01-05 17:02:30', 'yyyy-MM-dd 
HH:mm:ss', 'UTC') + 2";
+    assertEquals(timestamp + 2, run(query, new HashMap<>()));
+  }
+
+  @Test
+  public void addingIntegersShouldYieldAnInteger() throws Exception {
+    String query = "1 + 2";
+    assertEquals(3, run(query, new HashMap<>()));
+  }
+
+  @Test
+  public void addingDoublesShouldYieldADouble() throws Exception {
+    String query = "1.0 + 2.0";
+    assertEquals(3.0, run(query, new HashMap<>()));
+  }
+
+  @Test
+  public void addingDoubleAndIntegerWhereSubjectIsDoubleShouldYieldADouble() 
throws Exception {
+    String query = "2.1 + 1";
+    assertEquals(3.1, run(query, new HashMap<>()));
+  }
+
+  @Test
+  public void addingDoubleAndIntegerWhereSubjectIsIntegerShouldYieldADouble() 
throws Exception {
+    String query = "1 + 2.1";
+    assertEquals(3.1, run(query, new HashMap<>()));
+  }
+
+  @Test
+  public void testArithmetic() {
+    assertEquals(3, run("1 + 2", new HashMap<>()));
+    assertEquals(3.2, run("1.2 + 2", new HashMap<>()));
+    assertEquals(1.2e-3 + 2, run("1.2e-3 + 2", new HashMap<>()));
+    assertEquals(1.2f + 3.7, run("1.2f + 3.7", new HashMap<>()));
+    assertEquals(12L * (1.2f + 7), run("12L*(1.2f + 7)", new HashMap<>()));
+    assertEquals(12.2f * (1.2f + 7L), run("TO_FLOAT(12.2) * (1.2f + 7L)", new 
HashMap<>()));
+  }
+
+  @Test
+  public void testNumericOperations() {
+    {
+      String query = "TO_INTEGER(1 + 2*2 + 3 - 4 - 0.5)";
+      assertEquals(3, (Integer) run(query, new HashMap<>()), 1e-6);
+    }
+    {
+      String query = "1 + 2*2 + 3 - 4 - 0.5";
+      assertEquals(3.5, (Double) run(query, new HashMap<>()), 1e-6);
+    }
+    {
+      String query = "2*one*(1 + 2*2 + 3 - 4)";
+      assertEquals(8, run(query, ImmutableMap.of("one", 1)));
+    }
+    {
+      String query = "2*(1 + 2 + 3 - 4)";
+      assertEquals(4, (Integer) run(query, ImmutableMap.of("one", 1, 
"very_nearly_one", 1.000001)), 1e-6);
+    }
+    {
+      String query = "1 + 2 + 3 - 4 - 2";
+      assertEquals(0, (Integer) run(query, ImmutableMap.of("one", 1, 
"very_nearly_one", 1.000001)), 1e-6);
+    }
+    {
+      String query = "1 + 2 + 3 + 4";
+      assertEquals(10, (Integer) run(query, ImmutableMap.of("one", 1, 
"very_nearly_one", 1.000001)), 1e-6);
+    }
+    {
+      String query = "(one + 2)*3";
+      assertEquals(9, (Integer) run(query, ImmutableMap.of("one", 1, 
"very_nearly_one", 1.000001)), 1e-6);
+    }
+    {
+      String query = "TO_INTEGER((one + 2)*3.5)";
+      assertEquals(10, (Integer) run(query, ImmutableMap.of("one", 1, 
"very_nearly_one", 1.000001)), 1e-6);
+    }
+    {
+      String query = "1 + 2*3";
+      assertEquals(7, (Integer) run(query, ImmutableMap.of("one", 1, 
"very_nearly_one", 1.000001)), 1e-6);
+    }
+    {
+      String query = "TO_LONG(foo)";
+      Assert.assertNull(run(query, ImmutableMap.of("foo", "not a number")));
+    }
+    {
+      String query = "TO_LONG(foo)";
+      assertEquals(232321L, run(query, ImmutableMap.of("foo", "00232321")));
+    }
+    {
+      String query = "TO_LONG(foo)";
+      assertEquals(Long.MAX_VALUE, run(query, ImmutableMap.of("foo", 
Long.toString(Long.MAX_VALUE))));
+    }
+  }
+
+  @Test
+  public void verifyExpectedReturnTypes() throws Exception {
+    Token<Integer> integer = mock(Token.class);
+    when(integer.getValue()).thenReturn(1);
+
+    Token<Long> lng = mock(Token.class);
+    when(lng.getValue()).thenReturn(1L);
+
+    Token<Double> dbl = mock(Token.class);
+    when(dbl.getValue()).thenReturn(1.0D);
+
+    Token<Float> flt = mock(Token.class);
+    when(flt.getValue()).thenReturn(1.0F);
+
+    Map<Pair<String, String>, Class<? extends Number>> 
expectedReturnTypeMappings =
+        new HashMap<Pair<String, String>, Class<? extends Number>>() {{
+          put(Pair.of("TO_FLOAT(3.0)", "TO_LONG(1)"), Float.class);
+          put(Pair.of("TO_FLOAT(3)", "3.0"), Double.class);
+          put(Pair.of("TO_FLOAT(3)", "TO_FLOAT(3)"), Float.class);
+          put(Pair.of("TO_FLOAT(3)", "3"), Float.class);
+
+          put(Pair.of("TO_LONG(1)", "TO_LONG(1)"), Long.class);
+          put(Pair.of("TO_LONG(1)", "3.0"), Double.class);
+          put(Pair.of("TO_LONG(1)", "TO_FLOAT(3)"), Float.class);
+          put(Pair.of("TO_LONG(1)", "3"), Long.class);
+
+          put(Pair.of("3.0", "TO_LONG(1)"), Double.class);
+          put(Pair.of("3.0", "3.0"), Double.class);
+          put(Pair.of("3.0", "TO_FLOAT(3)"), Double.class);
+          put(Pair.of("3.0", "3"), Double.class);
+
+          put(Pair.of("3", "TO_LONG(1)"), Long.class);
+          put(Pair.of("3", "3.0"), Double.class);
+          put(Pair.of("3", "TO_FLOAT(3)"), Float.class);
+          put(Pair.of("3", "3"), Integer.class);
+        }};
+
+    expectedReturnTypeMappings.forEach((pair, expectedClass) -> {
+      assertTrue(run(pair.getLeft() + " * " + pair.getRight(), 
ImmutableMap.of()).getClass() == expectedClass);
+      assertTrue(run(pair.getLeft() + " + " + pair.getRight(), 
ImmutableMap.of()).getClass() == expectedClass);
+      assertTrue(run(pair.getLeft() + " - " + pair.getRight(), 
ImmutableMap.of()).getClass() == expectedClass);
+      assertTrue(run(pair.getLeft() + " / " + pair.getRight(), 
ImmutableMap.of()).getClass() == expectedClass);
+    });
+  }
+
+  @Test
+  public void happyPathFloatArithmetic() throws Exception {
+    Object run = run(".0f * 1", ImmutableMap.of());
+    assertEquals(.0f * 1, run);
+    assertEquals(Float.class, run.getClass());
+
+    Object run1 = run("0.f / 1F", ImmutableMap.of());
+    assertEquals(0.f / 1F, run1);
+    assertEquals(Float.class, run1.getClass());
+
+    Object run2 = run(".0F + 1.0f", ImmutableMap.of());
+    assertEquals(.0F + 1.0f, run2);
+    assertEquals(Float.class, run2.getClass());
+
+    Object run3 = run("0.0f - 0.1f", ImmutableMap.of());
+    assertEquals(0.0f - 0.1f, run3);
+    assertEquals(Float.class, run2.getClass());
+  }
+
+  @SuppressWarnings("PointlessArithmeticExpression")
+  @Test
+  public void happyPathLongArithmetic() throws Exception {
+    assertEquals(0L * 1L, run("0L * 1L", ImmutableMap.of()));
+    assertEquals(0l / 1L, run("0l / 1L", ImmutableMap.of()));
+    assertEquals(1L - 1l, run("1L - 1l", ImmutableMap.of()));
+    assertEquals(2147483648L + 1L, run("2147483648L + 1L", ImmutableMap.of()));
+  }
+
+  @SuppressWarnings("NumericOverflow")
+  @Test
+  public void checkInterestingCases() throws Exception {
+    assertEquals((((((1L) + .5d)))) * 6.f, run("(((((1L) + .5d)))) * 6.f", 
ImmutableMap.of()));
+    assertEquals((((((1L) + .5d)))) * 6.f / 0.f, run("(((((1L) + .5d)))) * 6.f 
/ 0.f", ImmutableMap.of()));
+    assertEquals(Double.class, run("(((((1L) + .5d)))) * 6.f / 0.f", 
ImmutableMap.of()).getClass());
+  }
+
+  @Test
+  public void makeSureStellarProperlyEvaluatesLiteralsToExpectedTypes() throws 
Exception {
+    {
+      assertEquals(Float.class, run("6.f", ImmutableMap.of()).getClass());
+      assertEquals(Float.class, run(".0f", ImmutableMap.of()).getClass());
+      assertEquals(Float.class, run("6.0F", ImmutableMap.of()).getClass());
+      assertEquals(Float.class, run("6f", ImmutableMap.of()).getClass());
+      assertEquals(Float.class, run("6e-6f", ImmutableMap.of()).getClass());
+      assertEquals(Float.class, run("6e+6f", ImmutableMap.of()).getClass());
+      assertEquals(Float.class, run("6e6f", ImmutableMap.of()).getClass());
+      assertEquals(Float.class, run("TO_FLOAT(1231)", 
ImmutableMap.of()).getClass());
+      assertEquals(Float.class, run("TO_FLOAT(12.31)", 
ImmutableMap.of()).getClass());
+      assertEquals(Float.class, run("TO_FLOAT(12.31f)", 
ImmutableMap.of()).getClass());
+      assertEquals(Float.class, run("TO_FLOAT(12L)", 
ImmutableMap.of()).getClass());
+    }
+    {
+      assertEquals(Double.class, run("6.d", ImmutableMap.of()).getClass());
+      assertEquals(Double.class, run("6.D", ImmutableMap.of()).getClass());
+      assertEquals(Double.class, run("6.0d", ImmutableMap.of()).getClass());
+      assertEquals(Double.class, run("6D", ImmutableMap.of()).getClass());
+      assertEquals(Double.class, run("6e5D", ImmutableMap.of()).getClass());
+      assertEquals(Double.class, run("6e-5D", ImmutableMap.of()).getClass());
+      assertEquals(Double.class, run("6e+5D", ImmutableMap.of()).getClass());
+      assertEquals(Double.class, run("TO_DOUBLE(1231)", 
ImmutableMap.of()).getClass());
+      assertEquals(Double.class, run("TO_DOUBLE(12.31)", 
ImmutableMap.of()).getClass());
+      assertEquals(Double.class, run("TO_DOUBLE(12.31f)", 
ImmutableMap.of()).getClass());
+      assertEquals(Double.class, run("TO_DOUBLE(12L)", 
ImmutableMap.of()).getClass());
+    }
+    {
+      assertEquals(Integer.class, run("6", ImmutableMap.of()).getClass());
+      assertEquals(Integer.class, run("60000000", 
ImmutableMap.of()).getClass());
+      assertEquals(Integer.class, run("-0", ImmutableMap.of()).getClass());
+      assertEquals(Integer.class, run("-60000000", 
ImmutableMap.of()).getClass());
+      assertEquals(Integer.class, run("TO_INTEGER(1231)", 
ImmutableMap.of()).getClass());
+      assertEquals(Integer.class, run("TO_INTEGER(12.31)", 
ImmutableMap.of()).getClass());
+      assertEquals(Integer.class, run("TO_INTEGER(12.31f)", 
ImmutableMap.of()).getClass());
+      assertEquals(Integer.class, run("TO_INTEGER(12L)", 
ImmutableMap.of()).getClass());
+    }
+    {
+      assertEquals(Long.class, run("12345678910l", 
ImmutableMap.of()).getClass());
+      assertEquals(Long.class, run("0l", ImmutableMap.of()).getClass());
+      assertEquals(Long.class, run("-0l", ImmutableMap.of()).getClass());
+      assertEquals(Long.class, run("-60000000L", 
ImmutableMap.of()).getClass());
+      assertEquals(Long.class, run("-60000000L", 
ImmutableMap.of()).getClass());
+      assertEquals(Long.class, run("TO_LONG(1231)", 
ImmutableMap.of()).getClass());
+      assertEquals(Long.class, run("TO_LONG(12.31)", 
ImmutableMap.of()).getClass());
+      assertEquals(Long.class, run("TO_LONG(12.31f)", 
ImmutableMap.of()).getClass());
+      assertEquals(Long.class, run("TO_LONG(12L)", 
ImmutableMap.of()).getClass());
+    }
+  }
+
+  @Test
+  public void parseExceptionMultipleLeadingZerosOnInteger() throws Exception {
+    exception.expect(ParseException.class);
+    run("000000", ImmutableMap.of());
+  }
+
+  @Test
+  public void parseExceptionMultipleLeadingZerosOnLong() throws Exception {
+    exception.expect(ParseException.class);
+    run("000000l", ImmutableMap.of());
+  }
+
+  @Test
+  public void parseExceptionMultipleLeadingZerosOnDouble() throws Exception {
+    exception.expect(ParseException.class);
+    run("000000d", ImmutableMap.of());
+  }
+
+  @Test
+  public void parseExceptionMultipleLeadingZerosOnFloat() throws Exception {
+    exception.expect(ParseException.class);
+    run("000000f", ImmutableMap.of());
+  }
+
+  @Test
+  public void parseExceptionMultipleLeadingNegativeSignsFloat() throws 
Exception {
+    exception.expect(ParseException.class);
+    run("--000000f", ImmutableMap.of());
+  }
+
+  @Test
+  public void parseExceptionMultipleLeadingNegativeSignsDouble() throws 
Exception {
+    exception.expect(ParseException.class);
+    run("--000000D", ImmutableMap.of());
+  }
+
+  @Test
+  public void parseExceptionMultipleLeadingNegativeSignsLong() throws 
Exception {
+    exception.expect(ParseException.class);
+    run("--000000L", ImmutableMap.of());
+  }
+
+  @Test(expected = ParseException.class)
+  public void unableToDivideByZeroWithIntegers() throws Exception {
+    run("0/0", ImmutableMap.of());
+  }
+
+  @Test(expected = ParseException.class)
+  public void unableToDivideByZeroWithLongs() throws Exception {
+    run("0L/0L", ImmutableMap.of());
+  }
+
+  @Test
+  public void ableToDivideByZero() throws Exception {
+    assertEquals(0F/0F, run("0F/0F", ImmutableMap.of()));
+    assertEquals(0D/0D, run("0D/0D", ImmutableMap.of()));
+    assertEquals(0D/0F, run("0D/0F", ImmutableMap.of()));
+    assertEquals(0F/0D, run("0F/0D", ImmutableMap.of()));
+    assertEquals(0F/0, run("0F/0", ImmutableMap.of()));
+    assertEquals(0D/0, run("0D/0", ImmutableMap.of()));
+    assertEquals(0/0D, run("0/0D", ImmutableMap.of()));
+    assertEquals(0/0F, run("0/0F", ImmutableMap.of()));
+  }
+}

http://git-wip-us.apache.org/repos/asf/metron/blob/a5b13777/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/common/StellarAssignmentTest.java
----------------------------------------------------------------------
diff --git 
a/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/common/StellarAssignmentTest.java
 
b/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/common/StellarAssignmentTest.java
new file mode 100644
index 0000000..a2a6c14
--- /dev/null
+++ 
b/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/common/StellarAssignmentTest.java
@@ -0,0 +1,64 @@
+/*
+ * 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 com.google.common.collect.ImmutableList;
+import org.apache.metron.stellar.common.StellarAssignment;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class StellarAssignmentTest {
+
+  @Test
+  public void testAssignment() {
+    for(String statement : ImmutableList.of( "foo := bar + grok"
+                                           , "foo   := bar + grok"
+                                           , "foo := bar + grok   "
+                                           )
+       )
+    {
+      StellarAssignment assignment = StellarAssignment.from(statement);
+      Assert.assertEquals("foo", assignment.getKey());
+      Assert.assertEquals("foo", assignment.getVariable());
+      Assert.assertEquals("bar + grok", assignment.getStatement());
+      Assert.assertEquals("bar + grok", assignment.getValue());
+    }
+  }
+
+  @Test
+  public void testNonAssignment() {
+    for(String statement : ImmutableList.of( "bar + grok"
+                                           , "  bar + grok"
+                                           , "bar + grok   "
+    )
+            )
+    {
+      StellarAssignment assignment = StellarAssignment.from(statement);
+      Assert.assertNull( assignment.getKey());
+      Assert.assertNull( assignment.getVariable());
+      Assert.assertEquals("bar + grok", assignment.getStatement());
+      Assert.assertEquals("bar + grok", assignment.getValue());
+    }
+  }
+
+  @Test(expected=UnsupportedOperationException.class)
+  public void testImmutability() {
+    StellarAssignment assignment = StellarAssignment.from("foo := bar");
+    assignment.setValue("myval");
+  }
+}

http://git-wip-us.apache.org/repos/asf/metron/blob/a5b13777/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/common/StellarComparisonExpressionWithOperatorTest.java
----------------------------------------------------------------------
diff --git 
a/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/common/StellarComparisonExpressionWithOperatorTest.java
 
b/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/common/StellarComparisonExpressionWithOperatorTest.java
new file mode 100644
index 0000000..44bffbc
--- /dev/null
+++ 
b/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/common/StellarComparisonExpressionWithOperatorTest.java
@@ -0,0 +1,293 @@
+/*
+ * 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 com.google.common.collect.ImmutableMap;
+import org.apache.metron.stellar.dsl.ParseException;
+import org.junit.Test;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.stream.Stream;
+
+import static org.apache.metron.stellar.common.utils.StellarProcessorUtils.run;
+import static 
org.apache.metron.stellar.common.utils.StellarProcessorUtils.runPredicate;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+@SuppressWarnings("ALL")
+public class StellarComparisonExpressionWithOperatorTest {
+  @SuppressWarnings({"RedundantConditionalExpression", "ConstantConditions"})
+  @Test
+  public void checkLessThanComparisonOperators() throws Exception {
+    assertEquals(1 < 2, run("1 < 2", ImmutableMap.of()));
+    assertEquals(1f < 2, run("1f < 2", ImmutableMap.of()));
+    assertEquals(1f < 2d, run("1f < 2d", ImmutableMap.of()));
+    assertEquals(1f < 2e-4d, run("1f < 2e-4d", ImmutableMap.of()));
+    assertEquals(1L < 2e-4d, run("1L < 2e-4d", ImmutableMap.of()));
+    assertEquals(1 < 2e-4d, run("1 < 2e-4d", ImmutableMap.of()));
+    assertEquals(1 < 2L, run("1 < 2L", ImmutableMap.of()));
+    assertEquals(1.0f < 2.0f, run("1.0f < 2.0f", ImmutableMap.of()));
+    assertEquals(1L < 3.0f, run("1L < 3.0f", ImmutableMap.of()));
+    assertEquals(1 < 3.0f, run("1 < 3.0f", ImmutableMap.of()));
+    assertEquals(1.0 < 3.0f, run("1.0 < 3.0f", ImmutableMap.of()));
+    assertEquals(false, run("foo < 3.0f", ImmutableMap.of()));
+    assertEquals(false, run("foo < foo", ImmutableMap.of()));
+    assertEquals(1L < 3.0f ? true : false, run("if 1L < 3.0f then true else 
false", ImmutableMap.of()));
+  }
+
+  @SuppressWarnings("ConstantConditions")
+  @Test
+  public void checkComparisonOperationsWithFunctions() throws Exception {
+    assertEquals(1f >= 2, run("TO_FLOAT(1) >= 2", ImmutableMap.of()));
+    assertEquals(1f <= 2, run("TO_FLOAT(1) <= TO_FLOAT(2)", 
ImmutableMap.of()));
+    assertEquals(1f == 2, run("TO_FLOAT(1) == TO_LONG(2)", ImmutableMap.of()));
+    assertEquals(12.31f == 10.2f, run("TO_FLOAT(12.31) < 10.2f", 
ImmutableMap.of()));
+  }
+
+  @Test
+  public void testSimpleOps() throws Exception {
+    final Map<String, String> variableMap = new HashMap<String, String>() {{
+      put("foo", "casey");
+      put("empty", "");
+      put("spaced", "metron is great");
+      put("foo.bar", "casey");
+    }};
+
+    assertTrue(runPredicate("'casey' == foo.bar", variableMap::get));
+    assertTrue(runPredicate("'casey' == foo", variableMap::get));
+    assertFalse(runPredicate("'casey' != foo", variableMap::get));
+    assertTrue(runPredicate("'stella' == 'stella'", variableMap::get));
+    assertFalse(runPredicate("'stella' == foo", variableMap::get));
+    assertTrue(runPredicate("foo== foo", variableMap::get));
+    assertTrue(runPredicate("empty== ''", variableMap::get));
+    assertTrue(runPredicate("spaced == 'metron is great'", variableMap::get));
+    assertTrue(runPredicate(null, variableMap::get));
+    assertTrue(runPredicate("", variableMap::get));
+    assertTrue(runPredicate(" ", variableMap::get));
+  }
+
+  @Test
+  public void compareNumberAndStringWithSameValueShouldBeFalse() throws 
Exception {
+    assertFalse(runPredicate("1 == '1'", new HashMap<>()::get));
+    assertFalse(runPredicate("'1' == 1", new HashMap<>()::get));
+  }
+
+  @Test
+  public void comparingNullShouldNotCauseNullPointer() throws Exception {
+    assertFalse(runPredicate("null == '1'", new HashMap<>()::get));
+    assertFalse(runPredicate("\"1\" == null", new HashMap<>()::get));
+    assertTrue(runPredicate("null == null", new HashMap<>()::get));
+  }
+
+  @Test
+  public void makeSureSingleQuotesAndDoubleQuotesAreEqual() throws Exception {
+    assertTrue(runPredicate("\"1\" == '1'", new HashMap<>()::get));
+    assertTrue(runPredicate("'1' == \"1\"", new HashMap<>()::get));
+    assertTrue(runPredicate("'1' == \"1\"", new HashMap<>()::get));
+  }
+
+  @Test
+  public void makeSureSingleQuoteStringsAreEvaluatedAsStrings() throws 
Exception {
+    assertFalse(runPredicate("55 == '7'", new HashMap<>()::get));
+    assertFalse(runPredicate("97 == 'a'", new HashMap<>()::get));
+  }
+
+  @Test
+  public void testNumericComparisonFunctions() throws Exception {
+    final Map<String, Object> variableMap = new HashMap<String, Object>() {{
+      put("foo", "casey");
+      put("bar", "bar.casey.grok");
+      put("ip", "192.168.0.1");
+      put("num", 7);
+      put("num2", 8.5);
+      put("num3", 7);
+      put("num4", "8.5");
+      put("empty", "");
+      put("spaced", "metron is great");
+    }};
+    assertTrue(runPredicate("num == 7", variableMap::get));
+    assertTrue(runPredicate("num < num2", variableMap::get));
+    assertTrue(runPredicate("num < TO_DOUBLE(num2)", variableMap::get));
+    assertTrue(runPredicate("num < TO_DOUBLE(num4)", variableMap::get));
+    assertTrue(runPredicate("num < 100", variableMap::get));
+    assertTrue(runPredicate("num == num3", variableMap::get));
+    assertFalse(runPredicate("num == num2", variableMap::get));
+    assertTrue(runPredicate("num == num2 || true", variableMap::get));
+    assertFalse(runPredicate("num > num2", variableMap::get));
+    assertTrue(runPredicate("num == 7 && num > 2", variableMap::get));
+  }
+
+  @Test
+  public void positiveAndNegativeZeroAreEqual() throws Exception {
+    final Map<String, Object> variableMap = new HashMap<String, Object>() {{
+      put("num", -0);
+    }};
+
+    Arrays.asList("!=", "==").forEach(op -> {
+      assertEquals("==".equals(op), runPredicate("num " + op + " 0", 
variableMap::get));
+      assertEquals("==".equals(op), runPredicate("0 " + op + " -0", 
variableMap::get));
+      assertEquals("==".equals(op), runPredicate("0 " + op + " -0d", 
variableMap::get));
+      assertEquals("==".equals(op), runPredicate("-0 " + op + " 0", 
variableMap::get));
+      assertEquals("==".equals(op), runPredicate("-0F " + op + " 0D", 
variableMap::get));
+      assertEquals("==".equals(op), runPredicate("-0.F " + op + " 0", 
variableMap::get));
+      assertEquals("==".equals(op), runPredicate("-0.F " + op + " 0F", 
variableMap::get));
+      assertEquals("==".equals(op), runPredicate("-0.D " + op + " 0D", 
variableMap::get));
+    });
+  }
+
+  @Test
+  public void naNIsNotEqualToNaN() throws Exception {
+    final Map<String, Object> variableMap = new HashMap<>();
+    Arrays.asList("!=", "==").forEach(op -> {
+      assertEquals("!=".equals(op), runPredicate("(0f/0f) " + op + " (0f/0f)", 
variableMap::get));
+      assertEquals("!=".equals(op), runPredicate("(-0f/0f) " + op + " 
(0f/0f)", variableMap::get));
+      assertEquals("!=".equals(op), runPredicate("(-0f/-0f) " + op + " 
(0f/0f)", variableMap::get));
+      assertEquals("!=".equals(op), runPredicate("(-0f/-0f) " + op + " 
(-0f/0f)", variableMap::get));
+      assertEquals("!=".equals(op), runPredicate("(-0f/-0f) " + op + " 
(-0f/-0f)", variableMap::get));
+      assertEquals("!=".equals(op), runPredicate("(0f/-0f) " + op + " 
(0f/0f)", variableMap::get));
+      assertEquals("!=".equals(op), runPredicate("(0f/-0f) " + op + " 
(-0f/0f)", variableMap::get));
+      assertEquals("!=".equals(op), runPredicate("(0f/-0f) " + op + " 
(-0f/-0f)", variableMap::get));
+      assertEquals("!=".equals(op), runPredicate("(0f/0f) " + op + " 
(-0f/0f)", variableMap::get));
+      assertEquals("!=".equals(op), runPredicate("(0f/0d) " + op + " 
(-0f/-0f)", variableMap::get));
+      assertEquals("!=".equals(op), runPredicate("(0d/-0f) " + op + " 
(0f/-0f)", variableMap::get));
+      assertEquals("!=".equals(op), runPredicate("(-0f/0f) " + op + " 
(0f/-0d)", variableMap::get));
+      assertEquals("!=".equals(op), runPredicate("(-0d/-0d) " + op + " 
(0d/-0d)", variableMap::get));
+      assertEquals("!=".equals(op), runPredicate("(0d/0d) " + op + " (0d/0d)", 
variableMap::get));
+    });
+  }
+
+  @Test
+  public void booleanComparisonTests() throws Exception {
+    final Map<String, Object> variableMap = new HashMap<String, Object>() {{
+      put("t", true);
+      put("f", false);
+    }};
+
+    assertTrue(runPredicate("t != f", variableMap::get));
+    assertTrue(runPredicate("f != t", variableMap::get));
+    assertTrue(runPredicate("true != false", variableMap::get));
+    assertFalse(runPredicate("true != true", variableMap::get));
+    assertTrue(runPredicate("false != true", variableMap::get));
+    assertFalse(runPredicate("false != false", variableMap::get));
+
+    assertFalse(runPredicate("t == f", variableMap::get));
+    assertFalse(runPredicate("f == t", variableMap::get));
+    assertFalse(runPredicate("true == false", variableMap::get));
+    assertTrue(runPredicate("true == true", variableMap::get));
+    assertFalse(runPredicate("false == true", variableMap::get));
+    assertTrue(runPredicate("false == false", variableMap::get));
+
+    assertFalse(runPredicate("null == false", variableMap::get));
+    assertFalse(runPredicate("null == true", variableMap::get));
+    assertFalse(runPredicate("true == NULL", variableMap::get));
+    assertFalse(runPredicate("false == NULL", variableMap::get));
+  }
+
+  @Test
+  public void nullComparisonTests() throws Exception {
+    final Map<String, Object> variableMap = new HashMap<>();
+
+    assertFalse(runPredicate("null == false", variableMap::get));
+    assertFalse(runPredicate("null == true", variableMap::get));
+    assertFalse(runPredicate("true == NULL", variableMap::get));
+    assertFalse(runPredicate("false == NULL", variableMap::get));
+    assertFalse(runPredicate("1 == NULL", variableMap::get));
+    assertFalse(runPredicate("'null' == NULL", variableMap::get));
+    assertFalse(runPredicate("'' == NULL", variableMap::get));
+    assertFalse(runPredicate("null == ''", variableMap::get));
+
+    assertTrue(runPredicate("NULL == null", variableMap::get));
+  }
+
+  @Test
+  public void precisionEqualityTests() throws Exception {
+    final Map<String, Object> variableMap = new HashMap<>();
+    assertEquals(0.1 + 0.2 == 0.3, runPredicate("0.1 + 0.2 == 0.3", 
variableMap::get));
+  }
+
+  @Test(expected = ParseException.class)
+  public void differentTypesShouldThrowErrorWhenUsingLT() throws Exception {
+    final Map<String, Object> variableMap = new HashMap<>();
+    runPredicate("1 < '1'", variableMap::get);
+  }
+
+  @Test(expected = ParseException.class)
+  public void differentTypesShouldThrowErrorWhenUsingLTE() throws Exception {
+    final Map<String, Object> variableMap = new HashMap<>();
+    runPredicate("'1' <= 1", variableMap::get);
+  }
+
+  @Test(expected = ParseException.class)
+  public void differentTypesShouldThrowErrorWhenUsingGT() throws Exception {
+    final Map<String, Object> variableMap = new HashMap<>();
+    runPredicate("1 > '1'", variableMap::get);
+  }
+
+  @Test(expected = ParseException.class)
+  public void differentTypesShouldThrowErrorWhenUsingGTE() throws Exception {
+    final Map<String, Object> variableMap = new HashMap<>();
+    runPredicate("'1' >= 1", variableMap::get);
+  }
+
+  @Test
+  public void differentTypesShouldThrowErrorWhenUsingComparisons() throws 
Exception {
+    final Map<String, Object> variableMap = new HashMap<>();
+    final Integer[] result = {0};
+
+    Stream.of("<", "<=", ">", ">=").forEach(op -> {
+      assertFalse(runPredicate("'1' " + op + " null", variableMap::get));
+    });
+  }
+
+  @Test
+  public void makeSurePrecisionIsProperlyHandled() throws Exception {
+    final Map<String, Object> variableMap = new HashMap<>();
+    {
+      assertEquals(1 == 1.00000001, runPredicate("1 == 1.00000001", 
variableMap::get));
+      assertEquals(1 < 1.00000001, runPredicate("1 < 1.00000001", 
variableMap::get));
+      assertEquals(1 <= 1.00000001, runPredicate("1 <= 1.00000001", 
variableMap::get));
+      assertEquals(1 > 1.00000001, runPredicate("1 > 1.00000001", 
variableMap::get));
+      assertEquals(1 >= 1.00000001, runPredicate("1 >= 1.00000001", 
variableMap::get));
+    }
+    {
+      assertEquals(1 == 1.00000001F, runPredicate("1 == 1.00000001F", 
variableMap::get));
+      assertEquals(1 < 1.00000001F, runPredicate("1 < 1.00000001F", 
variableMap::get));
+      assertEquals(1 <= 1.00000001F, runPredicate("1 <= 1.00000001F", 
variableMap::get));
+      assertEquals(1 > 1.00000001F, runPredicate("1 > 1.00000001F", 
variableMap::get));
+      assertEquals(1 >= 1.00000001F, runPredicate("1 >= 1.00000001F", 
variableMap::get));
+    }
+    {
+      assertEquals(1.00000001F == 1.00000001, runPredicate("1.00000001F == 
1.00000001", variableMap::get));
+      assertEquals(1.00000001F < 1.00000001, runPredicate("1.00000001F < 
1.00000001", variableMap::get));
+      assertEquals(1.00000001F <= 1.00000001, runPredicate("1.00000001F <= 
1.00000001", variableMap::get));
+      assertEquals(1.00000001F > 1.00000001, runPredicate("1.00000001F > 
1.00000001", variableMap::get));
+      assertEquals(1.00000001F >= 1.00000001, runPredicate("1.00000001F >= 
1.00000001", variableMap::get));
+    }
+    {
+      assertEquals(-1L == -1.00000001F, runPredicate("-1L == -1.00000001F", 
variableMap::get));
+      assertEquals(-1L < -1.00000001F, runPredicate("-1L < -1.00000001F", 
variableMap::get));
+      assertEquals(-1L <= -1.00000001F, runPredicate("-1L <= -1.00000001F", 
variableMap::get));
+      assertEquals(-1L > -1.00000001F, runPredicate("-1L > -1.00000001F", 
variableMap::get));
+      assertEquals(-1L >= -1.00000001F, runPredicate("-1L >= -1.00000001F", 
variableMap::get));
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/metron/blob/a5b13777/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
new file mode 100644
index 0000000..36a7116
--- /dev/null
+++ 
b/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/common/StellarInterpreterTest.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 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/a5b13777/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/common/StellarPredicateProcessorTest.java
----------------------------------------------------------------------
diff --git 
a/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/common/StellarPredicateProcessorTest.java
 
b/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/common/StellarPredicateProcessorTest.java
new file mode 100644
index 0000000..5c5abd4
--- /dev/null
+++ 
b/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/common/StellarPredicateProcessorTest.java
@@ -0,0 +1,36 @@
+/*
+ * 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.ParseException;
+import org.junit.Test;
+
+import static org.junit.Assert.fail;
+
+public class StellarPredicateProcessorTest {
+  @SuppressWarnings("EmptyCatchBlock")
+  @Test
+  public void testValidation() throws Exception {
+    StellarPredicateProcessor processor = new StellarPredicateProcessor();
+    try {
+      processor.validate("enrichedField1 == 'enrichedValue1");
+      fail("Invalid rule found to be valid - unclosed single quotes.");
+    } catch(ParseException e) {}
+  }
+}

http://git-wip-us.apache.org/repos/asf/metron/blob/a5b13777/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/common/evaluators/ArithmeticEvaluatorTest.java
----------------------------------------------------------------------
diff --git 
a/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/common/evaluators/ArithmeticEvaluatorTest.java
 
b/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/common/evaluators/ArithmeticEvaluatorTest.java
new file mode 100644
index 0000000..c92591a
--- /dev/null
+++ 
b/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/common/evaluators/ArithmeticEvaluatorTest.java
@@ -0,0 +1,412 @@
+/*
+ * 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.evaluators;
+
+import org.apache.commons.lang3.tuple.Pair;
+import org.apache.metron.stellar.dsl.Token;
+import org.junit.Test;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+@SuppressWarnings("unchecked")
+public class ArithmeticEvaluatorTest {
+  ArithmeticEvaluator evaluator = ArithmeticEvaluator.INSTANCE;
+
+  @Test
+  public void evaluateDoubleShouldReturnDoubleAdd() throws Exception {
+    Token<Integer> l = mock(Token.class);
+    when(l.getValue()).thenReturn(1);
+
+    Token<Double> r = mock(Token.class);
+    when(r.getValue()).thenReturn(2D);
+
+    Pair<Token<? extends Number>, Token<? extends Number>> p = Pair.of(l, r);
+
+    Token<? extends Number> evaluated = 
evaluator.evaluate(ArithmeticEvaluator.ArithmeticEvaluatorFunctions.addition(null),
 p);
+
+    assertTrue(evaluated.getValue() instanceof Double);
+    assertEquals(3.0D, evaluated.getValue());
+  }
+
+  @Test
+  public void evaluateIntegerShouldReturnIntegerAdd() throws Exception {
+    Token<Integer> l = mock(Token.class);
+    when(l.getValue()).thenReturn(1);
+
+    Token<Integer> r = mock(Token.class);
+    when(r.getValue()).thenReturn(2);
+
+    Pair<Token<? extends Number>, Token<? extends Number>> p = Pair.of(l, r);
+
+    Token<? extends Number> evaluated = 
evaluator.evaluate(ArithmeticEvaluator.ArithmeticEvaluatorFunctions.addition(null),
 p);
+
+    assertTrue(evaluated.getValue() instanceof Integer);
+    assertEquals(3, evaluated.getValue());
+  }
+
+  @Test
+  public void evaluateFloatsShouldReturnFloatAdd() throws Exception {
+    Token<Float> l = mock(Token.class);
+    when(l.getValue()).thenReturn(1F);
+
+    Token<Integer> r = mock(Token.class);
+    when(r.getValue()).thenReturn(2);
+
+    Pair<Token<? extends Number>, Token<? extends Number>> p = Pair.of(l, r);
+
+    Token<? extends Number> evaluated = 
evaluator.evaluate(ArithmeticEvaluator.ArithmeticEvaluatorFunctions.addition(null),
 p);
+
+    assertTrue(evaluated.getValue() instanceof Float);
+    assertEquals(3F, evaluated.getValue());
+  }
+
+  @Test
+  public void evaluateLongsShouldReturnLongAdd() throws Exception {
+    Token<Long> l = mock(Token.class);
+    when(l.getValue()).thenReturn(1L);
+
+    Token<Integer> r = mock(Token.class);
+    when(r.getValue()).thenReturn(2);
+
+    Pair<Token<? extends Number>, Token<? extends Number>> p = Pair.of(l, r);
+
+    Token<? extends Number> evaluated = 
evaluator.evaluate(ArithmeticEvaluator.ArithmeticEvaluatorFunctions.addition(null),
 p);
+
+    assertTrue(evaluated.getValue() instanceof Long);
+    assertEquals(3L, evaluated.getValue());
+  }
+
+  @Test
+  public void evaluateIntegerShouldReturnDoubleMul() throws Exception {
+    Token<Integer> l = mock(Token.class);
+    when(l.getValue()).thenReturn(1);
+
+    Token<Double> r = mock(Token.class);
+    when(r.getValue()).thenReturn(2D);
+
+    Pair<Token<? extends Number>, Token<? extends Number>> p = Pair.of(l, r);
+
+    Token<? extends Number> evaluated = 
evaluator.evaluate(ArithmeticEvaluator.ArithmeticEvaluatorFunctions.multiplication(null),
 p);
+
+    assertTrue(evaluated.getValue() instanceof Double);
+    assertEquals(2.0D, evaluated.getValue());
+  }
+
+  @Test
+  public void evaluateIntegerShouldReturnIntegerMul() throws Exception {
+    Token<Integer> l = mock(Token.class);
+    when(l.getValue()).thenReturn(1);
+
+    Token<Integer> r = mock(Token.class);
+    when(r.getValue()).thenReturn(2);
+
+    Pair<Token<? extends Number>, Token<? extends Number>> p = Pair.of(l, r);
+
+    Token<? extends Number> evaluated = 
evaluator.evaluate(ArithmeticEvaluator.ArithmeticEvaluatorFunctions.multiplication(null),
 p);
+
+    assertTrue(evaluated.getValue() instanceof Integer);
+    assertEquals(2, evaluated.getValue());
+  }
+
+  @Test
+  public void evaluateFloatsShouldReturnFloatMul() throws Exception {
+    Token<Float> l = mock(Token.class);
+    when(l.getValue()).thenReturn(1F);
+
+    Token<Integer> r = mock(Token.class);
+    when(r.getValue()).thenReturn(2);
+
+    Pair<Token<? extends Number>, Token<? extends Number>> p = Pair.of(l, r);
+
+    Token<? extends Number> evaluated = 
evaluator.evaluate(ArithmeticEvaluator.ArithmeticEvaluatorFunctions.multiplication(null),
 p);
+
+    assertTrue(evaluated.getValue() instanceof Float);
+    assertEquals(2F, evaluated.getValue());
+  }
+
+  @Test
+  public void evaluateLongsShouldReturnLongMul() throws Exception {
+    Token<Long> l = mock(Token.class);
+    when(l.getValue()).thenReturn(1L);
+
+    Token<Integer> r = mock(Token.class);
+    when(r.getValue()).thenReturn(2);
+
+    Pair<Token<? extends Number>, Token<? extends Number>> p = Pair.of(l, r);
+
+    Token<? extends Number> evaluated = 
evaluator.evaluate(ArithmeticEvaluator.ArithmeticEvaluatorFunctions.multiplication(null),
 p);
+
+    assertTrue(evaluated.getValue() instanceof Long);
+    assertEquals(2L, evaluated.getValue());
+  }
+
+  @Test
+  public void evaluateDoubleShouldReturnDoubleSub() throws Exception {
+    Token<Integer> l = mock(Token.class);
+    when(l.getValue()).thenReturn(1);
+
+    Token<Double> r = mock(Token.class);
+    when(r.getValue()).thenReturn(2D);
+
+    Pair<Token<? extends Number>, Token<? extends Number>> p = Pair.of(l, r);
+
+    Token<? extends Number> evaluated = 
evaluator.evaluate(ArithmeticEvaluator.ArithmeticEvaluatorFunctions.subtraction(null),
 p);
+
+    assertTrue(evaluated.getValue() instanceof Double);
+    assertEquals(-1.0D, evaluated.getValue());
+  }
+
+  @Test
+  public void evaluateIntegerShouldReturnIntegerSub() throws Exception {
+    Token<Integer> l = mock(Token.class);
+    when(l.getValue()).thenReturn(1);
+
+    Token<Integer> r = mock(Token.class);
+    when(r.getValue()).thenReturn(2);
+
+    Pair<Token<? extends Number>, Token<? extends Number>> p = Pair.of(l, r);
+
+    Token<? extends Number> evaluated = 
evaluator.evaluate(ArithmeticEvaluator.ArithmeticEvaluatorFunctions.subtraction(null),
 p);
+
+    assertTrue(evaluated.getValue() instanceof Integer);
+    assertEquals(-1, evaluated.getValue());
+  }
+
+  @Test
+  public void evaluateFloatsShouldReturnFloatSub() throws Exception {
+    Token<Float> l = mock(Token.class);
+    when(l.getValue()).thenReturn(1F);
+
+    Token<Integer> r = mock(Token.class);
+    when(r.getValue()).thenReturn(2);
+
+    Pair<Token<? extends Number>, Token<? extends Number>> p = Pair.of(l, r);
+
+    Token<? extends Number> evaluated = 
evaluator.evaluate(ArithmeticEvaluator.ArithmeticEvaluatorFunctions.subtraction(null),
 p);
+
+    assertTrue(evaluated.getValue() instanceof Float);
+    assertEquals(-1F, evaluated.getValue());
+  }
+
+  @Test
+  public void evaluateLongsShouldReturnLongSub() throws Exception {
+    Token<Long> l = mock(Token.class);
+    when(l.getValue()).thenReturn(1L);
+
+    Token<Integer> r = mock(Token.class);
+    when(r.getValue()).thenReturn(2);
+
+    Pair<Token<? extends Number>, Token<? extends Number>> p = Pair.of(l, r);
+
+    Token<? extends Number> evaluated = 
evaluator.evaluate(ArithmeticEvaluator.ArithmeticEvaluatorFunctions.subtraction(null),
 p);
+
+    assertTrue(evaluated.getValue() instanceof Long);
+    assertEquals(-1L, evaluated.getValue());
+  }
+
+  @Test
+  public void evaluateDoubleShouldReturnDoubleDiv() throws Exception {
+    Token<Integer> l = mock(Token.class);
+    when(l.getValue()).thenReturn(1);
+
+    Token<Double> r = mock(Token.class);
+    when(r.getValue()).thenReturn(2D);
+
+    Pair<Token<? extends Number>, Token<? extends Number>> p = Pair.of(l, r);
+
+    Token<? extends Number> evaluated = 
evaluator.evaluate(ArithmeticEvaluator.ArithmeticEvaluatorFunctions.division(null),
 p);
+
+    assertTrue(evaluated.getValue() instanceof Double);
+    assertEquals(1 / 2D, evaluated.getValue());
+  }
+
+  @Test
+  public void evaluateIntegerShouldReturnIntegerDiv() throws Exception {
+    Token<Integer> l = mock(Token.class);
+    when(l.getValue()).thenReturn(1);
+
+    Token<Integer> r = mock(Token.class);
+    when(r.getValue()).thenReturn(2);
+
+    Pair<Token<? extends Number>, Token<? extends Number>> p = Pair.of(l, r);
+
+    Token<? extends Number> evaluated = 
evaluator.evaluate(ArithmeticEvaluator.ArithmeticEvaluatorFunctions.division(null),
 p);
+
+    assertTrue(evaluated.getValue() instanceof Integer);
+    assertEquals(1 / 2, evaluated.getValue());
+  }
+
+  @Test
+  public void evaluateFloatsShouldReturnFloatDiv() throws Exception {
+    Token<Float> l = mock(Token.class);
+    when(l.getValue()).thenReturn(1F);
+
+    Token<Integer> r = mock(Token.class);
+    when(r.getValue()).thenReturn(2);
+
+    Pair<Token<? extends Number>, Token<? extends Number>> p = Pair.of(l, r);
+
+    Token<? extends Number> evaluated = 
evaluator.evaluate(ArithmeticEvaluator.ArithmeticEvaluatorFunctions.division(null),
 p);
+
+    assertTrue(evaluated.getValue() instanceof Float);
+    assertEquals(0.5F, evaluated.getValue());
+  }
+
+  @Test
+  public void evaluateLongsShouldReturnLongDiv() throws Exception {
+    Token<Long> l = mock(Token.class);
+    when(l.getValue()).thenReturn(1L);
+
+    Token<Integer> r = mock(Token.class);
+    when(r.getValue()).thenReturn(2);
+
+    Pair<Token<? extends Number>, Token<? extends Number>> p = Pair.of(l, r);
+
+    Token<? extends Number> evaluated = 
evaluator.evaluate(ArithmeticEvaluator.ArithmeticEvaluatorFunctions.division(null),
 p);
+
+    assertTrue(evaluated.getValue() instanceof Long);
+    assertEquals(0L, evaluated.getValue());
+  }
+
+  @Test(expected = IllegalArgumentException.class)
+  public void evaluateShouldThroughIllegalArgumentExceptionWhenInputIsNull() 
throws Exception {
+    
evaluator.evaluate(ArithmeticEvaluator.ArithmeticEvaluatorFunctions.division(null),
 null);
+  }
+
+  @Test(expected = IllegalArgumentException.class)
+  public void 
evaluateShouldThroughIllegalArgumentExceptionWhenInputsKeyIsNull() throws 
Exception {
+    Pair<Token<? extends Number>, Token<? extends Number>> p = Pair.of(null, 
mock(Token.class));
+    
evaluator.evaluate(ArithmeticEvaluator.ArithmeticEvaluatorFunctions.division(null),
 p);
+  }
+
+  @Test(expected = IllegalArgumentException.class)
+  public void 
evaluateShouldThroughIllegalArgumentExceptionWhenInputsValueIsNull() throws 
Exception {
+    Pair<Token<? extends Number>, Token<? extends Number>> p = 
Pair.of(mock(Token.class), null);
+    
evaluator.evaluate(ArithmeticEvaluator.ArithmeticEvaluatorFunctions.division(null),
 p);
+  }
+
+  @Test
+  public void evaluateShouldConvertShortsToIntegersType() throws Exception {
+    Token<Short> l = mock(Token.class);
+    when(l.getValue()).thenReturn((short) 2);
+
+    Token<Short> r = mock(Token.class);
+    when(r.getValue()).thenReturn((short) 3);
+
+    Token<? extends Number> evaluated0 = 
evaluator.evaluate(ArithmeticEvaluator.ArithmeticEvaluatorFunctions.addition(null),
 Pair.of(l, r));
+    Token<? extends Number> evaluated1 = 
evaluator.evaluate(ArithmeticEvaluator.ArithmeticEvaluatorFunctions.subtraction(null),
 Pair.of(l, r));
+    Token<? extends Number> evaluated2 = 
evaluator.evaluate(ArithmeticEvaluator.ArithmeticEvaluatorFunctions.multiplication(null),
 Pair.of(l, r));
+    Token<? extends Number> evaluated3 = 
evaluator.evaluate(ArithmeticEvaluator.ArithmeticEvaluatorFunctions.division(null),
 Pair.of(l, r));
+
+    assertTrue(evaluated0.getValue() instanceof Integer);
+    assertEquals(5, evaluated0.getValue());
+
+    assertTrue(evaluated1.getValue() instanceof Integer);
+    assertEquals(-1, evaluated1.getValue());
+
+    assertTrue(evaluated2.getValue() instanceof Integer);
+    assertEquals(6, evaluated2.getValue());
+
+    assertTrue(evaluated3.getValue() instanceof Integer);
+    assertEquals(0, evaluated3.getValue());
+  }
+
+  @Test
+  public void evaluateIntegerShouldReturnIntegerWhenLeftsValueIsNull() throws 
Exception {
+    Token<Integer> l = mock(Token.class);
+    when(l.getValue()).thenReturn(null);
+
+    Token<Integer> r = mock(Token.class);
+    when(r.getValue()).thenReturn(2);
+
+    Pair<Token<? extends Number>, Token<? extends Number>> p = Pair.of(l, r);
+
+    Token<? extends Number> evaluated = 
evaluator.evaluate(ArithmeticEvaluator.ArithmeticEvaluatorFunctions.addition(null),
 p);
+
+    assertTrue(evaluated.getValue() instanceof Integer);
+    assertEquals(2, evaluated.getValue());
+  }
+
+  @Test
+  public void evaluateIntegerShouldReturnIntegerWhenRightsValueIsNull() throws 
Exception {
+    Token<Integer> l = mock(Token.class);
+    when(l.getValue()).thenReturn(1);
+
+    Token<Integer> r = mock(Token.class);
+    when(r.getValue()).thenReturn(null);
+
+    Pair<Token<? extends Number>, Token<? extends Number>> p = Pair.of(l, r);
+
+    Token<? extends Number> evaluated = 
evaluator.evaluate(ArithmeticEvaluator.ArithmeticEvaluatorFunctions.addition(null),
 p);
+
+    assertTrue(evaluated.getValue() instanceof Integer);
+    assertEquals(1, evaluated.getValue());
+  }
+
+  @Test
+  public void verifyExpectedReturnTypes() throws Exception {
+    Token<Integer> integer = mock(Token.class);
+    when(integer.getValue()).thenReturn(1);
+
+    Token<Long> lng = mock(Token.class);
+    when(lng.getValue()).thenReturn(1L);
+
+    Token<Double> dbl = mock(Token.class);
+    when(dbl.getValue()).thenReturn(1.0D);
+
+    Token<Float> flt = mock(Token.class);
+    when(flt.getValue()).thenReturn(1.0F);
+
+    Map<Pair<Token<? extends Number>, Token<? extends Number>>, Class<? 
extends Number>> expectedReturnTypeMappings =
+        new HashMap<Pair<Token<? extends Number>, Token<? extends Number>>, 
Class<? extends Number>>() {{
+          put(Pair.of(flt, lng), Float.class);
+          put(Pair.of(flt, dbl), Double.class);
+          put(Pair.of(flt, flt), Float.class);
+          put(Pair.of(flt, integer), Float.class);
+
+          put(Pair.of(lng, lng), Long.class);
+          put(Pair.of(lng, dbl), Double.class);
+          put(Pair.of(lng, flt), Float.class);
+          put(Pair.of(lng, integer), Long.class);
+
+          put(Pair.of(dbl, lng), Double.class);
+          put(Pair.of(dbl, dbl), Double.class);
+          put(Pair.of(dbl, flt), Double.class);
+          put(Pair.of(dbl, integer), Double.class);
+
+          put(Pair.of(integer, lng), Long.class);
+          put(Pair.of(integer, dbl), Double.class);
+          put(Pair.of(integer, flt), Float.class);
+          put(Pair.of(integer, integer), Integer.class);
+    }};
+
+    expectedReturnTypeMappings.forEach( (pair, expectedClass) -> {
+      
assertTrue(evaluator.evaluate(ArithmeticEvaluator.ArithmeticEvaluatorFunctions.addition(null),
 pair).getValue().getClass() == expectedClass);
+      
assertTrue(evaluator.evaluate(ArithmeticEvaluator.ArithmeticEvaluatorFunctions.division(null),
 pair).getValue().getClass() == expectedClass);
+      
assertTrue(evaluator.evaluate(ArithmeticEvaluator.ArithmeticEvaluatorFunctions.subtraction(null),
 pair).getValue().getClass() == expectedClass);
+      
assertTrue(evaluator.evaluate(ArithmeticEvaluator.ArithmeticEvaluatorFunctions.multiplication(null),
 pair).getValue().getClass() == expectedClass);
+    });
+  }
+}

http://git-wip-us.apache.org/repos/asf/metron/blob/a5b13777/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/common/evaluators/ComparisonExpressionWithOperatorEvaluatorTest.java
----------------------------------------------------------------------
diff --git 
a/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/common/evaluators/ComparisonExpressionWithOperatorEvaluatorTest.java
 
b/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/common/evaluators/ComparisonExpressionWithOperatorEvaluatorTest.java
new file mode 100644
index 0000000..4afd4df
--- /dev/null
+++ 
b/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/common/evaluators/ComparisonExpressionWithOperatorEvaluatorTest.java
@@ -0,0 +1,126 @@
+/*
+ * 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.evaluators;
+
+import org.antlr.v4.runtime.tree.TerminalNode;
+import org.apache.metron.stellar.dsl.ParseException;
+import org.apache.metron.stellar.dsl.Token;
+import org.apache.metron.stellar.common.generated.StellarParser;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.powermock.api.mockito.PowerMockito.mock;
+import static org.powermock.api.mockito.PowerMockito.when;
+
+@SuppressWarnings({"unchecked"})
+@RunWith(PowerMockRunner.class)
+@PrepareForTest({ComparisonExpressionWithOperatorEvaluator.class, 
ComparisonExpressionWithOperatorEvaluator.Strategy.class})
+public class ComparisonExpressionWithOperatorEvaluatorTest {
+  @Rule
+  public final ExpectedException exception = ExpectedException.none();
+
+  final ComparisonExpressionWithOperatorEvaluator evaluator = 
ComparisonExpressionWithOperatorEvaluator.INSTANCE;
+
+  @Test
+  public void evaluateEqShouldProperlyCallEqualityOperatorsEvaluator() throws 
Exception {
+    Token<Double> left = mock(Token.class);
+    when(left.getValue()).thenReturn(1D);
+
+    Token<Double> right = mock(Token.class);
+    when(right.getValue()).thenReturn(1D);
+
+    StellarParser.ComparisonOpContext op = 
mock(StellarParser.ComparisonOpContext.class);
+    when(op.EQ()).thenReturn(mock(TerminalNode.class));
+
+    Token<Boolean> evaluated = evaluator.evaluate(left, right, op, null);
+
+    assertTrue(evaluated.getValue());
+  }
+
+  @Test
+  public void evaluateNotEqShouldProperlyCallEqualityOperatorsEvaluator() 
throws Exception {
+    Token<Double> left = mock(Token.class);
+    when(left.getValue()).thenReturn(1D);
+
+    Token<Double> right = mock(Token.class);
+    when(right.getValue()).thenReturn(1D);
+
+    StellarParser.ComparisonOpContext op = 
mock(StellarParser.ComparisonOpContext.class);
+    when(op.NEQ()).thenReturn(mock(TerminalNode.class));
+
+    Token<Boolean> evaluated = evaluator.evaluate(left, right, op, null);
+
+    assertFalse(evaluated.getValue());
+  }
+
+  @Test
+  public void evaluateLessThanEqShouldProperlyCallEqualityOperatorsEvaluator() 
throws Exception {
+    Token<Double> left = mock(Token.class);
+    when(left.getValue()).thenReturn(0D);
+
+    Token<Double> right = mock(Token.class);
+    when(right.getValue()).thenReturn(1D);
+
+    StellarParser.ComparisonOpContext op = 
mock(StellarParser.ComparisonOpContext.class);
+    when(op.LTE()).thenReturn(mock(TerminalNode.class));
+
+    Token<Boolean> evaluated = evaluator.evaluate(left, right, op, null);
+
+    assertTrue(evaluated.getValue());
+  }
+
+  @Test
+  public void unexpectedOperatorShouldThrowException() throws Exception {
+    exception.expect(ParseException.class);
+    exception.expectMessage("Unsupported operations. The following expression 
is invalid: ");
+
+    Token<Double> left = mock(Token.class);
+    when(left.getValue()).thenReturn(0D);
+
+    Token<Double> right = mock(Token.class);
+    when(right.getValue()).thenReturn(1D);
+
+    StellarParser.ComparisonOpContext op = 
mock(StellarParser.ComparisonOpContext.class);
+
+    evaluator.evaluate(left, right, op, null);
+  }
+
+  @Test
+  public void nonExpectedOperatorShouldThrowException() throws Exception {
+    exception.expect(ParseException.class);
+    exception.expectMessage("Unsupported operations. The following expression 
is invalid: ");
+
+    Token<String> left = mock(Token.class);
+    when(left.getValue()).thenReturn("adsf");
+
+    Token<Double> right = mock(Token.class);
+    when(right.getValue()).thenReturn(1D);
+
+    StellarParser.ComparisonOpContext op = 
mock(StellarParser.ComparisonOpContext.class);
+    when(op.LTE()).thenReturn(mock(TerminalNode.class));
+
+    evaluator.evaluate(left, right, op, null);
+  }
+}

Reply via email to