http://git-wip-us.apache.org/repos/asf/metron/blob/a5b13777/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/dsl/functions/BasicStellarTest.java
----------------------------------------------------------------------
diff --git 
a/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/dsl/functions/BasicStellarTest.java
 
b/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/dsl/functions/BasicStellarTest.java
new file mode 100644
index 0000000..871055a
--- /dev/null
+++ 
b/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/dsl/functions/BasicStellarTest.java
@@ -0,0 +1,739 @@
+/*
+ * 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.dsl.functions;
+
+import com.google.common.base.Joiner;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.metron.stellar.common.StellarProcessor;
+import org.apache.metron.stellar.dsl.Context;
+import org.apache.metron.stellar.dsl.ParseException;
+import org.apache.metron.stellar.dsl.Stellar;
+import org.apache.metron.stellar.dsl.StellarFunction;
+import 
org.apache.metron.stellar.dsl.functions.resolver.ClasspathFunctionResolver;
+import org.junit.Assert;
+import org.junit.Ignore;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import java.util.*;
+
+import static org.apache.metron.stellar.common.utils.StellarProcessorUtils.run;
+import static 
org.apache.metron.stellar.common.utils.StellarProcessorUtils.runPredicate;
+
+@SuppressWarnings("ALL")
+public class BasicStellarTest {
+
+  @Stellar(
+          description="throw exception",
+          name="THROW",
+          params = {
+           "message - exception message"
+          },
+          returns="nothing"
+  )
+  public static class Throw implements StellarFunction {
+
+    @Override
+    public Object apply(List<Object> args, Context context) throws 
ParseException {
+      throw new IllegalStateException(Joiner.on(" ").join(args));
+    }
+
+    @Override
+    public void initialize(Context context) {
+
+    }
+
+    @Override
+    public boolean isInitialized() {
+      return true;
+    }
+  }
+
+  @Stellar(
+          description="Always returns true",
+          name="RET_TRUE",
+          params = {
+           "arg* - Any set of args you wish to give it (including the empty 
set), they're ignored."
+          },
+          returns="true"
+  )
+  public static class TrueFunc implements StellarFunction {
+
+    @Override
+    public Object apply(List<Object> args, Context context) throws 
ParseException {
+      return true;
+    }
+
+    @Override
+    public void initialize(Context context) {
+
+    }
+
+    @Override
+    public boolean isInitialized() {
+      return true;
+    }
+  }
+
+  @Test
+  public void ensureDocumentation() {
+    ClassLoader classLoader = getClass().getClassLoader();
+    int numFound = 0;
+    for (Class<?> clazz : new ClasspathFunctionResolver().resolvables()) {
+      if (clazz.isAnnotationPresent(Stellar.class)) {
+        numFound++;
+        Stellar annotation = clazz.getAnnotation(Stellar.class);
+        Assert.assertFalse("Must specify a name for " + 
clazz.getName(),StringUtils.isEmpty(annotation.name()));
+        Assert.assertFalse("Must specify a description annotation for " + 
clazz.getName(),StringUtils.isEmpty(annotation.description()));
+        Assert.assertTrue("Must specify a non-empty params for " + 
clazz.getName(), annotation.params().length > 0);
+        Assert.assertTrue("Must specify a non-empty params for " + 
clazz.getName(), StringUtils.isNoneEmpty(annotation.params()));
+        Assert.assertFalse("Must specify a returns annotation for " + 
clazz.getName(), StringUtils.isEmpty(annotation.returns()));
+      }
+    }
+    Assert.assertTrue(numFound > 0);
+  }
+
+  @Test
+  public void testEscapedLiterals() {
+    Assert.assertEquals("'bar'", run("\"'bar'\"", new HashMap<>()));
+    Assert.assertEquals("'BAR'", run("TO_UPPER('\\'bar\\'')", new 
HashMap<>()));
+    Assert.assertEquals("\"bar\"", run("\"\\\"bar\\\"\"", new HashMap<>()));
+    Assert.assertEquals("\"bar\"", run("'\"bar\"'", new HashMap<>()));
+    Assert.assertEquals("\"BAR\"", run("TO_UPPER(\"\\\"bar\\\"\")", new 
HashMap<>()));
+    Assert.assertEquals("bar \\ foo", run("'bar \\\\ foo'", new HashMap<>()));
+    Assert.assertEquals("bar \\\\ foo", run("'bar \\\\\\\\ foo'", new 
HashMap<>()));
+    Assert.assertEquals("bar\nfoo", run("'bar\\nfoo'", new HashMap<>()));
+    Assert.assertEquals("bar\n\nfoo", run("'bar\\n\\nfoo'", new HashMap<>()));
+    Assert.assertEquals("bar\tfoo", run("'bar\\tfoo'", new HashMap<>()));
+    Assert.assertEquals("bar\t\tfoo", run("'bar\\t\\tfoo'", new HashMap<>()));
+    Assert.assertEquals("bar\rfoo", run("'bar\\rfoo'", new HashMap<>()));
+    Assert.assertEquals("'bar'", run("'\\'bar\\''", new HashMap<>()));
+  }
+
+  @Test
+  public void testVariableResolution() {
+    {
+      String query = "bar:variable";
+      Assert.assertEquals("bar", run(query, ImmutableMap.of("bar:variable", 
"bar")));
+      Assert.assertEquals("grok", run(query, ImmutableMap.of("bar:variable", 
"grok")));
+    }
+    {
+      String query = "JOIN(['foo', bar:variable], '')";
+      Assert.assertEquals("foobar", run(query, ImmutableMap.of("bar:variable", 
"bar")));
+      Assert.assertEquals("foogrok", run(query, 
ImmutableMap.of("bar:variable", "grok")));
+    }
+    {
+      String query = "MAP_GET('bar', { 'foo' : 1, 'bar' : bar:variable})";
+      Assert.assertEquals("bar", run(query, ImmutableMap.of("bar:variable", 
"bar")));
+      Assert.assertEquals("grok", run(query, ImmutableMap.of("bar:variable", 
"grok")));
+    }
+  }
+
+  @Test
+  public void testIfThenElseBug1() {
+    String query = "50 + (true == true ? 10 : 20)";
+    Assert.assertEquals(60, run(query, new HashMap<>()));
+  }
+
+  @Test
+  public void testIfThenElseBug2() {
+    String query = "50 + (true == false ? 10 : 20)";
+    Assert.assertEquals(70, run(query, new HashMap<>()));
+  }
+
+  @Test
+  public void testIfThenElseBug3() {
+    String query = "50 * (true == false ? 2 : 10) + 20";
+    Assert.assertEquals(520, run(query, new HashMap<>()));
+  }
+
+  @Test
+  public void testIfThenElseBug4() {
+    String query = "TO_INTEGER(true == true ? 10.0 : 20.0 )";
+    Assert.assertEquals(10, run(query, new HashMap<>()));
+  }
+
+  @Test
+  public void testVariablesUsed() {
+    StellarProcessor processor = new StellarProcessor();
+    {
+      Assert.assertEquals(new HashSet<>(), processor.variablesUsed("if 1 < 2 
then 'one' else 'two'"));
+    }
+    {
+      Assert.assertEquals(ImmutableSet.of("one")
+                         , processor.variablesUsed("if 1 < 2 then one else 
'two'"));
+    }
+    {
+      Assert.assertEquals(ImmutableSet.of("one", "two")
+                         , processor.variablesUsed("if 1 < 2 then one else 
two"));
+    }
+    {
+      Assert.assertEquals(ImmutableSet.of("bar")
+                         , processor.variablesUsed("MAP_GET('foo', { 'foo' : 
bar})"));
+    }
+  }
+
+
+  @Test
+  public void testFunctionEmptyArgs() {
+    {
+      String query = "STARTS_WITH(casey, 'case') or MAP_EXISTS()";
+      Assert.assertTrue((Boolean)run(query, ImmutableMap.of("casey", 
"casey")));
+    }
+    {
+      String query = "true or MAP_EXISTS()";
+      Assert.assertTrue((Boolean)run(query, new HashMap<>()));
+    }
+    {
+      String query = "MAP_EXISTS() or true";
+      Assert.assertTrue((Boolean)run(query, new HashMap<>()));
+    }
+  }
+  @Test
+  public void testNull() {
+    {
+      String query = "if 1 < 2 then NULL else true";
+      Assert.assertNull(run(query, new HashMap<>()));
+    }
+    {
+      String query = "1 < 2 ? NULL : true";
+      Assert.assertNull(run(query, new HashMap<>()));
+    }
+    {
+      String query = "null == null ? true : false";
+      Assert.assertTrue((Boolean)run(query, new HashMap<>()));
+    }
+  }
+
+  @Test
+  public void testMapConstant() {
+    {
+      String query = "MAP_GET('bar', { 'foo' : 1, 'bar' : 'bar'})";
+      Assert.assertEquals("bar", run(query, new HashMap<>()));
+    }
+    {
+      String query = "MAP_GET('blah', {  'blah' : 1 < 2 })";
+      Assert.assertEquals(true, run(query, new HashMap<>()));
+    }
+    {
+      String query = "MAP_GET('blah', {  'blah' : not(STARTS_WITH(casey, 
'case')) })";
+      Assert.assertEquals(false, run(query, ImmutableMap.of("casey", 
"casey")));
+    }
+    {
+      String query = "MAP_GET('blah', {  'blah' : one })";
+      Assert.assertEquals(1, run(query, ImmutableMap.of("one", 1)));
+    }
+    {
+      String query = "MAP_GET('blah', {  'blah' : null })";
+      Assert.assertNull(run(query, new HashMap<>()));
+    }
+    {
+      String query = "MAP_GET('BLAH', {  TO_UPPER('blah') : null })";
+      Assert.assertNull(run(query, new HashMap<>()));
+    }
+    {
+      String query = "MAP_GET('BLAH', {  TO_UPPER('blah') : 1 < 2 })";
+      Assert.assertEquals(true, run(query, new HashMap<>()));
+    }
+  }
+
+  @Test
+  public void testIfThenElse() {
+    {
+      String query = "if STARTS_WITH(casey, 'case') then 'one' else 'two'";
+      Assert.assertEquals("one", run(query, ImmutableMap.of("casey", 
"casey")));
+    }
+    {
+      String query = "if 1 < 2 then 'one' else 'two'";
+      Assert.assertEquals("one", run(query, new HashMap<>()));
+    }
+    {
+      String query = "if 1 + 1 < 2 then 'one' else 'two'";
+      Assert.assertEquals("two", run(query, new HashMap<>()));
+    }
+    {
+      String query = "if 1 + 1 <= 2 AND 1 + 2 in [3] then 'one' else 'two'";
+      Assert.assertEquals("one", run(query, new HashMap<>()));
+    }
+    {
+      String query = "if 1 + 1 <= 2 AND (1 + 2 in [3]) then 'one' else 'two'";
+      Assert.assertEquals("one", run(query, new HashMap<>()));
+    }
+    {
+      String query = "if not(1 < 2) then 'one' else 'two'";
+      Assert.assertEquals("two", run(query, new HashMap<>()));
+    }
+    {
+      String query = "if 1 == 1.0000001 then 'one' else 'two'";
+      Assert.assertEquals("two", run(query, new HashMap<>()));
+    }
+    {
+      String query = "if one < two then 'one' else 'two'";
+      Assert.assertEquals("one", run(query, ImmutableMap.of("one", 1, "two", 
2)));
+    }
+    {
+      String query = "if one == very_nearly_one then 'one' else 'two'";
+      Assert.assertEquals("two", run(query, ImmutableMap.of("one", 1, 
"very_nearly_one", 1.0000001)));
+    }
+    {
+      String query = "if one == very_nearly_one OR one == very_nearly_one then 
'one' else 'two'";
+      Assert.assertEquals("two", run(query, ImmutableMap.of("one", 1, 
"very_nearly_one", 1.0000001)));
+    }
+    {
+      String query = "if one == very_nearly_one OR one != very_nearly_one then 
'one' else 'two'";
+      Assert.assertEquals("one", run(query, ImmutableMap.of("one", 1, 
"very_nearly_one", 1.0000001)));
+    }
+    {
+      String query = "if one != very_nearly_one OR one == very_nearly_one then 
'one' else 'two'";
+      Assert.assertEquals("one", run(query, ImmutableMap.of("one", 1, 
"very_nearly_one", 1.0000001)));
+    }
+    {
+      String query = "if 'foo' in ['foo'] OR one == very_nearly_one then 'one' 
else 'two'";
+      Assert.assertEquals("one", run(query, ImmutableMap.of("one", 1, 
"very_nearly_one", 1.0000001)));
+    }
+    {
+      String query = "if ('foo' in ['foo']) OR one == very_nearly_one then 
'one' else 'two'";
+      Assert.assertEquals("one", run(query, ImmutableMap.of("one", 1, 
"very_nearly_one", 1.0000001)));
+    }
+    {
+      String query = "if not('foo' in ['foo']) OR one == very_nearly_one then 
'one' else 'two'";
+      Assert.assertEquals("two", run(query, ImmutableMap.of("one", 1, 
"very_nearly_one", 1.0000001)));
+    }
+    {
+      String query = "if not('foo' in ['foo'] OR one == very_nearly_one) then 
'one' else 'two'";
+      Assert.assertEquals("two", run(query, ImmutableMap.of("one", 1, 
"very_nearly_one", 1.0000001)));
+    }
+    {
+      String query = "1 < 2 ? 'one' : 'two'";
+      Assert.assertEquals("one", run(query, new HashMap<>()));
+    }
+    {
+      String query = "1 < 2 ? TO_UPPER('one') : 'two'";
+      Assert.assertEquals("ONE", run(query, new HashMap<>()));
+    }
+    {
+      String query = "1 < 2 ? one : 'two'";
+      Assert.assertEquals("one", run(query, ImmutableMap.of("one", "one")));
+    }
+    {
+      String query = "1 < 2 ? one*3 : 'two'";
+      Assert.assertTrue(Math.abs(3 - (int) run(query, ImmutableMap.of("one", 
1))) < 1e-6);
+    }
+    {
+      String query = "1 < 2 AND 1 < 2 ? one*3 : 'two'";
+      Assert.assertTrue(Math.abs(3 - (int) run(query, ImmutableMap.of("one", 
1))) < 1e-6);
+    }
+    {
+      String query = "1 < 2 AND 1 > 2 ? one*3 : 'two'";
+      Assert.assertEquals("two", run(query, ImmutableMap.of("one", 1)));
+    }
+    {
+      String query = "1 > 2 AND 1 < 2 ? one*3 : 'two'";
+      Assert.assertEquals("two", run(query, ImmutableMap.of("one", 1)));
+    }
+    {
+      String query = "1 < 2 AND 'foo' in ['', 'foo'] ? one*3 : 'two'";
+      Assert.assertEquals(3, run(query, ImmutableMap.of("one", 1)));
+    }
+    {
+      String query = "1 < 2 AND ('foo' in ['', 'foo']) ? one*3 : 'two'";
+      Assert.assertEquals(3, run(query, ImmutableMap.of("one", 1)));
+    }
+    {
+      String query = "'foo' in ['', 'foo'] ? one*3 : 'two'";
+      Assert.assertEquals(3, run(query, ImmutableMap.of("one", 1)));
+    }
+  }
+
+  @Test
+  public void testInNotIN(){
+    HashMap variables = new HashMap<>();
+    boolean thrown = false;
+    try{
+      Object o = run("in in ['','in']" ,variables );
+    }catch(ParseException pe) {
+      thrown = true;
+    }
+    Assert.assertTrue(thrown);
+    thrown = false;
+
+    try{
+      Assert.assertEquals(true,run("'in' in ['','in']" ,variables ));
+    }catch(ParseException pe) {
+      thrown = true;
+    }
+    Assert.assertFalse(thrown);
+  }
+
+  @Test
+  public void testHappyPath() {
+    String query = "TO_UPPER(TRIM(foo))";
+    Assert.assertEquals("CASEY", run(query, ImmutableMap.of("foo", "casey ")));
+  }
+
+  @Test
+  public void testLengthString(){
+    String query = "LENGTH(foo)";
+    Assert.assertEquals(5, run(query,ImmutableMap.of("foo","abcde")));
+  }
+  @Test
+  public void testLengthCollection(){
+    String query = "LENGTH(foo)";
+    Collection c = Arrays.asList(1,2,3,4,5);
+    Assert.assertEquals(5, run(query,ImmutableMap.of("foo",c)));
+  }
+
+  @Test
+  public void testEmptyLengthString(){
+    String query = "LENGTH(foo)";
+    Assert.assertEquals(0,run(query,ImmutableMap.of("foo","")));
+  }
+  @Test
+  public void testEmptyLengthCollection(){
+    String query = "LENGTH(foo)";
+    Collection c = new ArrayList();
+    Assert.assertEquals(0,run(query,ImmutableMap.of("foo",c)));
+  }
+  @Test
+  public void testNoVarLength(){
+    String query = "LENGTH(foo)";
+    Assert.assertEquals(0,run(query,ImmutableMap.of()));
+  }
+
+  @Test
+  public void testJoin() {
+    String query = "JOIN( [ TO_UPPER(TRIM(foo)), 'bar' ], ',')";
+    Assert.assertEquals("CASEY,bar", run(query, ImmutableMap.of("foo", "casey 
")));
+  }
+
+  @Test
+  public void testSplit() {
+    String query = "JOIN( SPLIT(foo, ':'), ',')";
+    Assert.assertEquals("casey,bar", run(query, ImmutableMap.of("foo", 
"casey:bar")));
+  }
+
+  @Test
+  public void testMapGet() {
+    String query = "MAP_GET(dc, dc2tz, 'UTC')";
+    Assert.assertEquals("UTC"
+                       , run(query, ImmutableMap.of("dc", "nyc"
+                                                   ,"dc2tz", 
ImmutableMap.of("la", "PST")
+                                                   )
+                            )
+                       );
+    Assert.assertEquals("EST"
+                       , run(query, ImmutableMap.of("dc", "nyc"
+                                                   ,"dc2tz", 
ImmutableMap.of("nyc", "EST")
+                                                   )
+                            )
+                       );
+  }
+
+  @Test
+  public void testTLDExtraction() {
+    String query = "DOMAIN_TO_TLD(foo)";
+    Assert.assertEquals("co.uk", run(query, ImmutableMap.of("foo", 
"www.google.co.uk")));
+  }
+
+  @Test
+  public void testTLDRemoval() {
+    String query = "DOMAIN_REMOVE_TLD(foo)";
+    Assert.assertEquals("www.google", run(query, ImmutableMap.of("foo", 
"www.google.co.uk")));
+  }
+
+  @Test
+  public void testSubdomainRemoval() {
+    String query = "DOMAIN_REMOVE_SUBDOMAINS(foo)";
+    Assert.assertEquals("google.co.uk", run(query, ImmutableMap.of("foo", 
"www.google.co.uk")));
+    Assert.assertEquals("google.com", run(query, ImmutableMap.of("foo", 
"www.google.com")));
+  }
+
+  @Test
+  public void testURLToHost() {
+    String query = "URL_TO_HOST(foo)";
+    Assert.assertEquals("www.google.co.uk", run(query, ImmutableMap.of("foo", 
"http://www.google.co.uk/my/path";)));
+  }
+
+  @Test
+  public void testURLToPort() {
+    String query = "URL_TO_PORT(foo)";
+    Assert.assertEquals(80, run(query, ImmutableMap.of("foo", 
"http://www.google.co.uk/my/path";)));
+  }
+
+  @Test
+  public void testURLToProtocol() {
+    String query = "URL_TO_PROTOCOL(foo)";
+    Assert.assertEquals("http", run(query, ImmutableMap.of("foo", 
"http://www.google.co.uk/my/path";)));
+  }
+
+  @Test
+  public void testURLToPath() {
+    String query = "URL_TO_PATH(foo)";
+    Assert.assertEquals("/my/path", run(query, ImmutableMap.of("foo", 
"http://www.google.co.uk/my/path";)));
+  }
+
+  @Ignore //until field transformations avail to Stellar
+  @Test
+  public void testProtocolToName() {
+    String query = "PROTOCOL_TO_NAME(protocol)";
+    Assert.assertEquals("TCP", run(query, ImmutableMap.of("protocol", "6")));
+    Assert.assertEquals("TCP", run(query, ImmutableMap.of("protocol", 6)));
+    Assert.assertEquals(null, run(query, ImmutableMap.of("foo", 6)));
+    Assert.assertEquals("chicken", run(query, ImmutableMap.of("protocol", 
"chicken")));
+  }
+
+  @Test
+  public void testDateConversion() {
+    long expected =1452013350000L;
+    {
+      String query = "TO_EPOCH_TIMESTAMP(foo, 'yyyy-MM-dd HH:mm:ss', 'UTC')";
+      Assert.assertEquals(expected, run(query, ImmutableMap.of("foo", 
"2016-01-05 17:02:30")));
+    }
+    {
+      String query = "TO_EPOCH_TIMESTAMP(foo, 'yyyy-MM-dd HH:mm:ss')";
+      Long ts = (Long) run(query, ImmutableMap.of("foo", "2016-01-05 
17:02:30"));
+      //is it within 24 hours of the UTC?
+      Assert.assertTrue(Math.abs(ts - expected) < 8.64e+7);
+    }
+  }
+
+  @Test
+  public void testToString() {
+    Assert.assertEquals("5", run("TO_STRING(foo)", ImmutableMap.of("foo", 5)));
+  }
+
+  @Test
+  public void testToInteger() {
+    Assert.assertEquals(5, run("TO_INTEGER(foo)", ImmutableMap.of("foo", 
"5")));
+    Assert.assertEquals(5, run("TO_INTEGER(foo)", ImmutableMap.of("foo", 5)));
+  }
+
+  @Test
+  public void testToDouble() {
+    Assert.assertEquals(5.1d, run("TO_DOUBLE(foo)", ImmutableMap.of("foo", 
5.1d)));
+    Assert.assertEquals(5.1d, run("TO_DOUBLE(foo)", ImmutableMap.of("foo", 
"5.1")));
+  }
+
+  @Test
+  public void testGet() {
+    Map<String, Object> variables = ImmutableMap.of("foo", "www.google.co.uk");
+    Assert.assertEquals("www", run("GET_FIRST(SPLIT(DOMAIN_REMOVE_TLD(foo), 
'.'))", variables));
+    Assert.assertEquals("www", run("GET(SPLIT(DOMAIN_REMOVE_TLD(foo), '.'), 
0)", variables));
+    Assert.assertEquals("google", run("GET_LAST(SPLIT(DOMAIN_REMOVE_TLD(foo), 
'.'))", variables));
+    Assert.assertEquals("google", run("GET(SPLIT(DOMAIN_REMOVE_TLD(foo), '.'), 
1)", variables));
+  }
+
+  @Test
+  public void testBooleanOps() throws Exception {
+    final Map<String, String> variableMap = new HashMap<String, String>() {{
+      put("foo", "casey");
+      put("empty", "");
+      put("spaced", "metron is great");
+    }};
+    Assert.assertFalse(runPredicate("not('casey' == foo and true)", v -> 
variableMap.get(v)));
+    Assert.assertTrue(runPredicate("not(not('casey' == foo and true))", v -> 
variableMap.get(v)));
+    Assert.assertTrue(runPredicate("('casey' == foo) && ( false != true )", v 
-> variableMap.get(v)));
+    Assert.assertFalse(runPredicate("('casey' == foo) and (FALSE == TRUE)", v 
-> variableMap.get(v)));
+    Assert.assertFalse(runPredicate("'casey' == foo and FALSE", v -> 
variableMap.get(v)));
+    Assert.assertTrue(runPredicate("'casey' == foo and true", v -> 
variableMap.get(v)));
+    Assert.assertTrue(runPredicate("true", v -> variableMap.get(v)));
+    Assert.assertTrue(runPredicate("TRUE", v -> variableMap.get(v)));
+  }
+
+  @Test
+  public void testInCollection() throws Exception {
+    final Map<String, String> variableMap = new HashMap<String, String>() {{
+      put("foo", "casey");
+      put("empty", "");
+    }};
+    Assert.assertTrue(runPredicate("foo in [ 'casey', 'david' ]", v -> 
variableMap.get(v)));
+    Assert.assertFalse(runPredicate("foo in [ ]", v -> variableMap.get(v)));
+    Assert.assertTrue(runPredicate("foo in [ foo, 'david' ]", v -> 
variableMap.get(v)));
+    Assert.assertTrue(runPredicate("foo in [ 'casey', 'david' ] and 'casey' == 
foo", v -> variableMap.get(v)));
+    Assert.assertTrue(runPredicate("foo in [ 'casey', 'david' ] and foo == 
'casey'", v -> variableMap.get(v)));
+    Assert.assertTrue(runPredicate("foo in [ 'casey' ]", v -> 
variableMap.get(v)));
+    Assert.assertFalse(runPredicate("foo not in [ 'casey', 'david' ]", v -> 
variableMap.get(v)));
+    Assert.assertFalse(runPredicate("foo not in [ 'casey', 'david' ] and 
'casey' == foo", v -> variableMap.get(v)));
+    Assert.assertTrue(runPredicate("null in [ null, 'something' ]", v -> 
variableMap.get(v)));
+    Assert.assertFalse(runPredicate("null not in [ null, 'something' ]", v -> 
variableMap.get(v)));
+  }
+
+  @Test
+  public void testInMap() throws Exception {
+    final Map<String, String> variableMap = new HashMap<String, String>() {{
+      put("foo", "casey");
+      put("empty", "");
+    }};
+    Assert.assertTrue(runPredicate("'casey' in { foo : 5 }", v -> 
variableMap.get(v)));
+    Assert.assertFalse(runPredicate("'casey' not in { foo : 5 }", v -> 
variableMap.get(v)));
+    Assert.assertTrue(runPredicate("foo in { foo : 5 }", v -> 
variableMap.get(v)));
+    Assert.assertFalse(runPredicate("foo not in { foo : 5 }", v -> 
variableMap.get(v)));
+    Assert.assertTrue(runPredicate("'foo' in { 'foo' : 5 }", v -> 
variableMap.get(v)));
+    Assert.assertFalse(runPredicate("'foo' not in { 'foo' : 5 }", v -> 
variableMap.get(v)));
+    Assert.assertTrue(runPredicate("foo in { 'casey' : 5 }", v -> 
variableMap.get(v)));
+    Assert.assertFalse(runPredicate("foo not in { 'casey' : 5 }", v -> 
variableMap.get(v)));
+    Assert.assertFalse(runPredicate("empty in { foo : 5 }", v -> 
variableMap.get(v)));
+    Assert.assertTrue(runPredicate("empty not in { foo : 5 }", v -> 
variableMap.get(v)));
+    Assert.assertFalse(runPredicate("'foo' in { }", v -> variableMap.get(v)));
+    Assert.assertFalse(runPredicate("null in { 'foo' : 5 }", v -> 
variableMap.get(v)));
+    Assert.assertTrue(runPredicate("null not in { 'foo' : 5 }", v -> 
variableMap.get(v)));
+  }
+
+  @Test
+  public void testInString() throws Exception {
+    final Map<String, String> variableMap = new HashMap<String, String>() {{
+      put("foo", "casey");
+      put("empty", "");
+    }};
+    Assert.assertTrue(runPredicate("'case' in foo", v -> variableMap.get(v)));
+    Assert.assertFalse(runPredicate("'case' not in foo", v -> 
variableMap.get(v)));
+    Assert.assertFalse(runPredicate("'case' in empty", v -> 
variableMap.get(v)));
+    Assert.assertTrue(runPredicate("'case' not in empty", v -> 
variableMap.get(v)));
+    Assert.assertFalse(runPredicate("'case' in [ foo ]", v -> 
variableMap.get(v)));
+    Assert.assertTrue(runPredicate("'case' not in [ foo ]", v -> 
variableMap.get(v)));
+    Assert.assertFalse(runPredicate("null in foo", v -> variableMap.get(v)));
+    Assert.assertTrue(runPredicate("null not in foo", v -> 
variableMap.get(v)));
+  }
+
+  @Test
+  public void inNestedInStatement() throws Exception {
+    final Map<String, String> variableMap = new HashMap<>();
+
+    Assert.assertTrue(runPredicate("('grok' not in 'foobar') == true", 
variableMap::get));
+    Assert.assertTrue(runPredicate("'grok' not in ('foobar' == true)", 
variableMap::get));
+    Assert.assertFalse(runPredicate("'grok' in 'grokbar' == true", 
variableMap::get));
+    Assert.assertTrue(runPredicate("false in 'grokbar' == true", 
variableMap::get));
+
+    Assert.assertTrue(runPredicate("('foo' in 'foobar') == true", 
variableMap::get));
+    Assert.assertFalse(runPredicate("'foo' in ('foobar' == true)", 
variableMap::get));
+    Assert.assertTrue(runPredicate("'grok' not in 'grokbar' == true", 
variableMap::get));
+    Assert.assertTrue(runPredicate("false in 'grokbar' == true", 
variableMap::get));
+    Assert.assertTrue(runPredicate("'foo' in ['foo'] AND 'bar' in ['bar']", 
variableMap::get));
+    Assert.assertTrue(runPredicate("('foo' in ['foo']) AND 'bar' in ['bar']", 
variableMap::get));
+    Assert.assertTrue(runPredicate("'foo' in ['foo'] AND ('bar' in ['bar'])", 
variableMap::get));
+    Assert.assertTrue(runPredicate("('foo' in ['foo']) AND ('bar' in 
['bar'])", variableMap::get));
+    Assert.assertTrue(runPredicate("('foo' in ['foo'] AND 'bar' in ['bar'])", 
variableMap::get));
+  }
+
+  @Test
+  public void testExists() throws Exception {
+    final Map<String, String> variableMap = new HashMap<String, String>() {{
+      put("foo", "casey");
+      put("empty", "");
+      put("spaced", "metron is great");
+    }};
+    Assert.assertTrue(runPredicate("exists(foo)", v -> variableMap.get(v)));
+    Assert.assertFalse(runPredicate("exists(bar)", v -> variableMap.get(v)));
+    Assert.assertTrue(runPredicate("exists(bar) or true", v -> 
variableMap.get(v)));
+  }
+
+  @Test
+  public void testMapFunctions_advanced() 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("empty", "");
+      put("spaced", "metron is great");
+      put("myMap", ImmutableMap.of("casey", "apple"));
+    }};
+    Assert.assertTrue(runPredicate("MAP_EXISTS(foo, myMap)", v -> 
variableMap.get(v)));
+  }
+
+  @Test
+  public void testLogicalFunctions() throws Exception {
+    final Map<String, String> variableMap = new HashMap<String, String>() {{
+      put("foo", "casey");
+      put("ip", "192.168.0.1");
+      put("ip_src_addr", "192.168.0.1");
+      put("ip_dst_addr", "10.0.0.1");
+      put("other_ip", "10.168.0.1");
+      put("empty", "");
+      put("spaced", "metron is great");
+    }};
+    Assert.assertTrue(runPredicate("IN_SUBNET(ip, '192.168.0.0/24')", v -> 
variableMap.get(v)));
+    Assert.assertTrue(runPredicate("IN_SUBNET(ip, '192.168.0.0/24', 
'11.0.0.0/24')", v -> variableMap.get(v)));
+    Assert.assertTrue(runPredicate("IN_SUBNET(ip, '192.168.0.0/24', 
'11.0.0.0/24') in [true]", v -> variableMap.get(v)));
+    Assert.assertTrue(runPredicate("true in IN_SUBNET(ip, '192.168.0.0/24', 
'11.0.0.0/24')", v -> variableMap.get(v)));
+    Assert.assertFalse(runPredicate("IN_SUBNET(ip_dst_addr, '192.168.0.0/24', 
'11.0.0.0/24')", v -> variableMap.get(v)));
+    Assert.assertFalse(runPredicate("IN_SUBNET(other_ip, '192.168.0.0/24')", v 
-> variableMap.get(v)));
+    Assert.assertFalse(runPredicate("IN_SUBNET(blah, '192.168.0.0/24')", v -> 
variableMap.get(v)));
+    Assert.assertTrue(runPredicate("true and STARTS_WITH(foo, 'ca')", v -> 
variableMap.get(v)));
+    Assert.assertTrue(runPredicate("true and STARTS_WITH(TO_UPPER(foo), 
'CA')", v -> variableMap.get(v)));
+    Assert.assertTrue(runPredicate("(true and STARTS_WITH(TO_UPPER(foo), 
'CA')) || true", v -> variableMap.get(v)));
+    Assert.assertTrue(runPredicate("true and ENDS_WITH(foo, 'sey')", v -> 
variableMap.get(v)));
+    Assert.assertTrue(runPredicate("not(IN_SUBNET(ip_src_addr, 
'192.168.0.0/24') and IN_SUBNET(ip_dst_addr, '192.168.0.0/24'))", v-> 
variableMap.get(v)));
+    Assert.assertTrue(runPredicate("IN_SUBNET(ip_src_addr, '192.168.0.0/24')", 
v-> variableMap.get(v)));
+    Assert.assertFalse(runPredicate("not(IN_SUBNET(ip_src_addr, 
'192.168.0.0/24'))", v-> variableMap.get(v)));
+    Assert.assertFalse(runPredicate("IN_SUBNET(ip_dst_addr, 
'192.168.0.0/24')", v-> variableMap.get(v)));
+    Assert.assertTrue(runPredicate("not(IN_SUBNET(ip_dst_addr, 
'192.168.0.0/24'))", v-> variableMap.get(v)));
+  }
+
+  @Test
+  public void testShortCircuit_conditional() throws Exception {
+    Assert.assertEquals("foo", run("if true then 'foo' else (if false then 
'bar' else 'grok')", new HashMap<>()));
+    Assert.assertEquals("foo", run("if true_var != null && true_var then 'foo' 
else (if false then 'bar' else 'grok')", ImmutableMap.of("true_var", true)));
+    Assert.assertEquals("foo", run("if true then 'foo' else 
THROW('expression')", new HashMap<>()));
+    Assert.assertEquals("foo", run("true ? 'foo' : THROW('expression')", new 
HashMap<>()));
+    Assert.assertEquals("foo", run("if false then THROW('exception') else 
'foo'", new HashMap<>()));
+    Assert.assertEquals("foo", run("false ? THROW('exception') : 'foo'", new 
HashMap<>()));
+    Assert.assertEquals(true, run("RET_TRUE(if true then 'foo' else 
THROW('expression'))", new HashMap<>()));
+    Assert.assertEquals("foo", run("if true or (true or THROW('if exception')) 
then 'foo' else THROW('expression')", new HashMap<>()));
+    Assert.assertEquals("foo", run("if true or (false or THROW('if 
exception')) then 'foo' else THROW('expression')", new HashMap<>()));
+    Assert.assertEquals("foo", run("if NOT(true or (false or THROW('if 
exception'))) then THROW('expression') else 'foo'", new HashMap<>()));
+    Assert.assertEquals("foo", run("if NOT('metron' in [ 'metron', 
'metronicus'] ) then THROW('expression') else 'foo'", new HashMap<>()));
+  }
+
+  @Test
+  public void testShortCircuit_boolean() throws Exception {
+    Assert.assertTrue(runPredicate("'metron' in ['metron', 'metronicus', 
'mortron'] or (true or THROW('exception'))", x -> null));
+    Assert.assertTrue(runPredicate("true or (true or THROW('exception'))", x 
-> null));
+    Assert.assertTrue(runPredicate("true or (false or THROW('exception'))", x 
-> null));
+    Assert.assertTrue(runPredicate("TO_UPPER('foo') == 'FOO' or (true or 
THROW('exception'))", x -> null));
+    Assert.assertFalse(runPredicate("false and (true or THROW('exception'))", 
x -> null));
+    Assert.assertTrue(runPredicate("true or false or false or true", x -> 
null));
+    Assert.assertFalse(runPredicate("false or (false and THROW('exception'))", 
x -> null));
+    Assert.assertTrue(runPredicate("'casey' == 'casey' or THROW('exception')", 
x -> null));
+    Assert.assertTrue(runPredicate("TO_UPPER('casey') == 'CASEY' or 
THROW('exception')", x -> null));
+    Assert.assertTrue(runPredicate("NOT(TO_UPPER('casey') != 'CASEY') or 
THROW('exception')", x -> null));
+    Assert.assertTrue(runPredicate("(TO_UPPER('casey') == 'CASEY') or 
THROW('exception')", x -> null));
+    Assert.assertFalse(runPredicate("NOT(NOT(TO_UPPER('casey') != 'CASEY') or 
THROW('exception'))", x -> null));
+    Assert.assertFalse(runPredicate("NOT(NOT(TO_UPPER('casey') != 'CASEY')) 
and THROW('exception')", x -> null));
+    Assert.assertTrue(runPredicate("RET_TRUE('foo') or THROW('exception')", x 
-> null));
+    Assert.assertFalse(runPredicate("NOT(foo == null or THROW('exception')) 
and THROW('and exception')", x -> null));
+    Assert.assertTrue(runPredicate("(foo == null or THROW('exception') ) or 
THROW('and exception')", x -> null));
+    Assert.assertTrue(runPredicate("( RET_TRUE('foo', true, false) or ( foo == 
null or THROW('exception') ) or THROW('and exception')) or THROW('or 
exception')", x -> null));
+  }
+
+  @Rule
+  public ExpectedException thrown = ExpectedException.none();
+
+  @Test
+  public void non_boolean_predicate_throws_exception() {
+    final Map<String, String> variableMap = new HashMap<String, String>() {{
+      put("protocol", "http");
+    }};
+    thrown.expect(IllegalArgumentException.class);
+    thrown.expectMessage("The rule 'TO_UPPER(protocol)' does not return a 
boolean value.");
+    runPredicate("TO_UPPER(protocol)", v -> variableMap.get(v));
+  }
+}

http://git-wip-us.apache.org/repos/asf/metron/blob/a5b13777/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/dsl/functions/ConversionFunctionsTest.java
----------------------------------------------------------------------
diff --git 
a/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/dsl/functions/ConversionFunctionsTest.java
 
b/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/dsl/functions/ConversionFunctionsTest.java
new file mode 100644
index 0000000..099d540
--- /dev/null
+++ 
b/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/dsl/functions/ConversionFunctionsTest.java
@@ -0,0 +1,44 @@
+/*
+ * 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.dsl.functions;
+
+import org.junit.Test;
+
+import java.util.Collections;
+
+import static org.junit.Assert.assertEquals;
+
+public class ConversionFunctionsTest {
+
+  @Test
+  public void conversionFunctionsShouldProperlyConvertToSpecificType() throws 
Exception {
+    assertEquals(1D, new 
ConversionFunctions.TO_DOUBLE().apply(Collections.singletonList(1)));
+    assertEquals(1F, new 
ConversionFunctions.TO_FLOAT().apply(Collections.singletonList(1.0D)));
+    assertEquals(1, new 
ConversionFunctions.TO_INTEGER().apply(Collections.singletonList(1.0D)));
+    assertEquals(1L, new 
ConversionFunctions.TO_LONG().apply(Collections.singletonList(1F)));
+  }
+
+  @Test
+  public void conversionFunctionsShouldProperlyHandleNull() throws Exception {
+    assertEquals(null, new 
ConversionFunctions.TO_DOUBLE().apply(Collections.singletonList(null)));
+    assertEquals(null, new 
ConversionFunctions.TO_FLOAT().apply(Collections.singletonList(null)));
+    assertEquals(null, new 
ConversionFunctions.TO_INTEGER().apply(Collections.singletonList(null)));
+    assertEquals(null, new 
ConversionFunctions.TO_LONG().apply(Collections.singletonList(null)));
+  }
+}

http://git-wip-us.apache.org/repos/asf/metron/blob/a5b13777/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/dsl/functions/DataStructureFunctionsTest.java
----------------------------------------------------------------------
diff --git 
a/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/dsl/functions/DataStructureFunctionsTest.java
 
b/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/dsl/functions/DataStructureFunctionsTest.java
new file mode 100644
index 0000000..735b803
--- /dev/null
+++ 
b/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/dsl/functions/DataStructureFunctionsTest.java
@@ -0,0 +1,121 @@
+/**
+ * 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.dsl.functions;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import org.hamcrest.CoreMatchers;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.apache.metron.stellar.common.utils.StellarProcessorUtils.run;
+
+public class DataStructureFunctionsTest {
+
+  @Test
+  public void is_empty_handles_happy_path() {
+    DataStructureFunctions.IsEmpty isEmpty = new 
DataStructureFunctions.IsEmpty();
+    {
+      boolean empty = (boolean) isEmpty.apply(ImmutableList.of("hello"));
+      Assert.assertThat("should be false", empty, CoreMatchers.equalTo(false));
+    }
+    {
+      boolean empty = (boolean) 
isEmpty.apply(ImmutableList.of(ImmutableList.of("hello", "world")));
+      Assert.assertThat("should be false", empty, CoreMatchers.equalTo(false));
+    }
+    {
+      boolean empty = (boolean) isEmpty.apply(ImmutableList.of(1));
+      Assert.assertThat("should be false", empty, CoreMatchers.equalTo(false));
+    }
+  }
+
+  @Test
+  public void is_empty_handles_empty_values() {
+    DataStructureFunctions.IsEmpty isEmpty = new 
DataStructureFunctions.IsEmpty();
+    {
+      boolean empty = (boolean) isEmpty.apply(ImmutableList.of());
+      Assert.assertThat("should be true", empty, CoreMatchers.equalTo(true));
+    }
+    {
+      boolean empty = (boolean) isEmpty.apply(null);
+      Assert.assertThat("should be true", empty, CoreMatchers.equalTo(true));
+    }
+    {
+      boolean empty = (boolean) isEmpty.apply(ImmutableList.of(""));
+      Assert.assertThat("should be true", empty, CoreMatchers.equalTo(true));
+    }
+  }
+
+  @Test
+  public void listAdd_number() {
+    for(String expr : ImmutableList.of("LIST_ADD(my_list, 1)"
+                                      ,"LIST_ADD([], 1)"
+                                      ,"LIST_ADD([], val)"
+                                      )
+       )
+    {
+      Object o = run(expr, ImmutableMap.of("my_list", new ArrayList<>(), 
"val", 1));
+      Assert.assertTrue(o instanceof List);
+      List<Number> result = (List<Number>) o;
+      Assert.assertEquals(1, result.size());
+      Assert.assertEquals(1, result.get(0));
+    }
+  }
+
+  @Test
+  public void listAdd_mixed() {
+    for(String expr : ImmutableList.of("LIST_ADD(my_list, 1)"
+                                      ,"LIST_ADD(['foo'], 1)"
+                                      ,"LIST_ADD(['foo'], val)"
+                                      )
+       )
+    {
+      ArrayList<Object> list = new ArrayList<>();
+      list.add("foo");
+      Object o = run(expr, ImmutableMap.of("my_list", list, "val", 1));
+      Assert.assertTrue(o instanceof List);
+      List<Object> result = (List<Object>) o;
+      Assert.assertEquals(2, result.size());
+      Assert.assertEquals("foo", result.get(0));
+      Assert.assertEquals(1, result.get(1));
+    }
+  }
+
+  @Test
+  public void listAdd_number_nonempty() {
+    for(String expr : ImmutableList.of("LIST_ADD(my_list, 2)"
+                                      ,"LIST_ADD([1], 2)"
+                                      ,"LIST_ADD([1], val)"
+                                      )
+       )
+    {
+      ArrayList<Integer> list = new ArrayList<>();
+      list.add(1);
+      Object o = run(expr, ImmutableMap.of("my_list", list, "val", 2));
+      Assert.assertTrue(o instanceof List);
+      List<Number> result = (List<Number>) o;
+      Assert.assertEquals(2, result.size());
+      Assert.assertEquals(1, result.get(0));
+      Assert.assertEquals(2, result.get(1));
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/metron/blob/a5b13777/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/dsl/functions/DateFunctionsTest.java
----------------------------------------------------------------------
diff --git 
a/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/dsl/functions/DateFunctionsTest.java
 
b/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/dsl/functions/DateFunctionsTest.java
new file mode 100644
index 0000000..a36f8ff
--- /dev/null
+++ 
b/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/dsl/functions/DateFunctionsTest.java
@@ -0,0 +1,232 @@
+/*
+ *
+ *  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.dsl.functions;
+
+import org.apache.metron.stellar.common.StellarProcessor;
+import org.apache.metron.stellar.dsl.Context;
+import org.apache.metron.stellar.dsl.StellarFunctions;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.Calendar;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Tests the DateFunctions class.
+ */
+public class DateFunctionsTest {
+
+  private Map<String, Object> variables = new HashMap<>();
+  private Calendar calendar;
+
+  /**
+   * Runs a Stellar expression.
+   * @param expr The expression to run.
+   */
+  private Object run(String expr) {
+    StellarProcessor processor = new StellarProcessor();
+    assertTrue(processor.validate(expr));
+    return processor.parse(expr, x -> variables.get(x), 
StellarFunctions.FUNCTION_RESOLVER(), Context.EMPTY_CONTEXT());
+  }
+
+  /**
+   * Thu Aug 25 2016 09:27:10 EST
+   */
+  private long AUG2016 = 1472131630748L;
+
+  @Before
+  public void setup() {
+    variables.put("epoch", AUG2016);
+    calendar = Calendar.getInstance();
+  }
+
+  @Test
+  public void testDayOfWeek() {
+    Object result = run("DAY_OF_WEEK(epoch)");
+    assertEquals(Calendar.THURSDAY, result);
+  }
+
+  /**
+   * If no argument, then return the current day of week.
+   */
+  @Test
+  public void testDayOfWeekNow() {
+    Object result = run("DAY_OF_WEEK()");
+    assertEquals(calendar.get(Calendar.DAY_OF_WEEK), result);
+  }
+
+  /**
+   * If refer to variable that does not exist, expect null returned.
+   */
+  @Test
+  public void testDayOfWeekNull() {
+    Object result = run("DAY_OF_WEEK(nada)");
+    assertEquals(null, result);
+  }
+
+  @Test
+  public void testWeekOfMonth() {
+    Object result = run("WEEK_OF_MONTH(epoch)");
+    assertEquals(4, result);
+  }
+
+  /**
+   * If no argument, then return the current week of month.
+   */
+  @Test
+  public void testWeekOfMonthNow() {
+    Object result = run("WEEK_OF_MONTH()");
+    assertEquals(calendar.get(Calendar.WEEK_OF_MONTH), result);
+  }
+
+  /**
+   * If refer to variable that does not exist, expect null returned.
+   */
+  @Test
+  public void testWeekOfMonthNull() {
+    Object result = run("WEEK_OF_MONTH(nada)");
+    assertEquals(null, result);
+  }
+
+  @Test
+  public void testMonth() {
+    Object result = run("MONTH(epoch)");
+    assertEquals(Calendar.AUGUST, result);
+  }
+
+  /**
+   * If no argument, then return the current month.
+   */
+  @Test
+  public void testMonthNow() {
+    Object result = run("MONTH()");
+    assertEquals(calendar.get(Calendar.MONTH), result);
+  }
+
+  /**
+   * If refer to variable that does not exist, expect null returned.
+   */
+  @Test
+  public void testMonthNull() {
+    Object result = run("MONTH(nada)");
+    assertEquals(null, result);
+  }
+
+  @Test
+  public void testYear() {
+    Object result = run("YEAR(epoch)");
+    assertEquals(2016, result);
+  }
+
+  /**
+   * If no argument, then return the current year.
+   */
+  @Test
+  public void testYearNow() {
+    Object result = run("YEAR()");
+    assertEquals(calendar.get(Calendar.YEAR), result);
+  }
+
+  /**
+   * If refer to variable that does not exist, expect null returned.
+   */
+  @Test
+  public void testYearNull() {
+    Object result = run("YEAR(nada)");
+    assertEquals(null, result);
+  }
+
+  @Test
+  public void testDayOfMonth() {
+    Object result = run("DAY_OF_MONTH(epoch)");
+    assertEquals(25, result);
+  }
+
+  /**
+   * If no argument, then return the current day of month.
+   */
+  @Test
+  public void testDayOfMonthNow() {
+    Object result = run("DAY_OF_MONTH()");
+    assertEquals(calendar.get(Calendar.DAY_OF_MONTH), result);
+  }
+
+  /**
+   * If refer to variable that does not exist, expect null returned.
+   */
+  @Test
+  public void testDayOfMonthNull() {
+    Object result = run("DAY_OF_MONTH(nada)");
+    assertEquals(null, result);
+  }
+
+  @Test
+  public void testWeekOfYear() {
+    Object result = run("WEEK_OF_YEAR(epoch)");
+    assertEquals(35, result);
+  }
+
+  /**
+   * If no argument, then return the current week of year.
+   */
+  @Test
+  public void testWeekOfYearNow() {
+    Object result = run("WEEK_OF_YEAR()");
+    assertEquals(calendar.get(Calendar.WEEK_OF_YEAR), result);
+  }
+
+  /**
+   * If refer to variable that does not exist, expect null returned.
+   */
+  @Test
+  public void testWeekOfYearNull() {
+    Object result = run("WEEK_OF_YEAR(nada)");
+    assertEquals(null, result);
+  }
+
+  @Test
+  public void testDayOfYear() {
+    Object result = run("DAY_OF_YEAR(epoch)");
+    assertEquals(238, result);
+  }
+
+  /**
+   * If no argument, then return the current day of year.
+   */
+  @Test
+  public void testDayOfYearNow() {
+    Object result = run("DAY_OF_YEAR()");
+    assertEquals(calendar.get(Calendar.DAY_OF_YEAR), result);
+  }
+
+  /**
+   * If refer to variable that does not exist, expect null returned.
+   */
+  @Test
+  public void testDayOfYearNull() {
+    Object result = run("DAY_OF_YEAR(nada)");
+    assertEquals(null, result);
+  }
+}

http://git-wip-us.apache.org/repos/asf/metron/blob/a5b13777/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/dsl/functions/FunctionalFunctionsTest.java
----------------------------------------------------------------------
diff --git 
a/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/dsl/functions/FunctionalFunctionsTest.java
 
b/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/dsl/functions/FunctionalFunctionsTest.java
new file mode 100644
index 0000000..3eec2b0
--- /dev/null
+++ 
b/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/dsl/functions/FunctionalFunctionsTest.java
@@ -0,0 +1,291 @@
+/**
+ * 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.dsl.functions;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import org.hamcrest.CoreMatchers;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.List;
+
+import static org.apache.metron.stellar.common.utils.StellarProcessorUtils.run;
+
+public class FunctionalFunctionsTest {
+
+  @Test
+  public void testRecursive() {
+    for (String expr : ImmutableList.of( "MAP(list, inner_list -> 
REDUCE(inner_list, (x, y) -> x + y, 0) )"
+                                       , "MAP(list, (inner_list) -> 
REDUCE(inner_list, (x, y) -> x + y, 0) )"
+                                       )
+        )
+    {
+      Object o = run(expr, ImmutableMap.of("list", 
ImmutableList.of(ImmutableList.of(1, 2, 3), ImmutableList.of(4, 5, 6))));
+      Assert.assertTrue(o instanceof List);
+      List<Number> result = (List<Number>) o;
+      Assert.assertEquals(2, result.size());
+      Assert.assertEquals(6, result.get(0));
+      Assert.assertEquals(15, result.get(1));
+    }
+  }
+
+  @Test
+  public void testMap_null() {
+    for (String expr : ImmutableList.of( "MAP([ 1, 2, null], x -> if x == null 
then 0 else 2*x )"
+                                       , "MAP([ 1, 2, null], x -> x == null ? 
0 : 2*x )"
+                                       , "MAP([ 1, foo, baz], x -> x == null ? 
0 : 2*x )"
+    )
+            )
+    {
+      Object o = run(expr, ImmutableMap.of("foo", 2, "bar", 3));
+      Assert.assertTrue(o instanceof List);
+      List<String> result = (List<String>) o;
+      Assert.assertEquals(3, result.size());
+      Assert.assertEquals(2, result.get(0));
+      Assert.assertEquals(4, result.get(1));
+      Assert.assertEquals(0, result.get(2));
+    }
+  }
+
+
+  @Test
+  public void testMap() {
+    for (String expr : ImmutableList.of( "MAP([ 'foo', 'bar'], (x) -> 
TO_UPPER(x) )"
+                                       , "MAP([ foo, 'bar'], (x) -> 
TO_UPPER(x) )"
+                                       , "MAP([ foo, bar], (x) -> TO_UPPER(x) 
)"
+                                       , "MAP([ foo, bar], x -> TO_UPPER(x) )"
+                                       , "MAP([ foo, bar], x -> 
true?TO_UPPER(x):THROW('error') )"
+                                       , "MAP([ foo, bar], x -> 
false?THROW('error'):TO_UPPER(x) )"
+                                       )
+        )
+    {
+      Object o = run(expr, ImmutableMap.of("foo", "foo", "bar", "bar"));
+      Assert.assertTrue(o instanceof List);
+      List<String> result = (List<String>) o;
+      Assert.assertEquals(2, result.size());
+      Assert.assertEquals("FOO", result.get(0));
+      Assert.assertEquals("BAR", result.get(1));
+    }
+  }
+
+
+  @Test
+  public void testMap_conditional() {
+    for (String expr : ImmutableList.of("MAP([ 'foo', 'bar'], (item) -> item 
== 'foo' )"
+                                       ,"MAP([ foo, bar], (item) -> item == 
'foo' )"
+                                       ,"MAP([ foo, bar], (item) -> item == 
foo )"
+                                       ,"MAP([ foo, bar], item -> item == foo 
)"
+                                       )
+        )
+    {
+      Object o = run(expr, ImmutableMap.of("foo", "foo", "bar", "bar"));
+      Assert.assertTrue(o instanceof List);
+      List<Boolean> result = (List<Boolean>) o;
+      Assert.assertEquals(2, result.size());
+      Assert.assertEquals(true, result.get(0));
+      Assert.assertEquals(false, result.get(1));
+    }
+  }
+
+  @Test
+  public void testFilter() {
+    for (String expr : ImmutableList.of("FILTER([ 'foo', 'bar'], (item) -> 
item == 'foo' )"
+                                       ,"FILTER([ 'foo', bar], (item) -> item 
== 'foo' )"
+                                       ,"FILTER([ foo, bar], (item) -> item == 
'foo' )"
+                                       ,"FILTER([ foo, bar], (item) -> (item 
== 'foo' && true) )"
+                                       ,"FILTER([ foo, bar], (item) -> if item 
== 'foo' then true else false )"
+                                       ,"FILTER([ foo, bar], item -> if item 
== 'foo' then true else false )"
+                                       )
+        )
+    {
+      Object o = run(expr, ImmutableMap.of("foo", "foo", "bar", "bar"));
+      Assert.assertTrue(o instanceof List);
+      List<String> result = (List<String>) o;
+      Assert.assertEquals(1, result.size());
+      Assert.assertEquals("foo", result.get(0));
+    }
+  }
+
+
+  @Test
+  public void testFilter_shortcircuit() {
+    for (String expr : ImmutableList.of("FILTER([ 'foo'], item -> item == 
'foo' or THROW('exception') )"
+                                       ,"FILTER([ 'foo'], (item) -> item == 
'foo' or THROW('exception') )"
+                                       )
+        )
+    {
+      Object o = run(expr, ImmutableMap.of("foo", "foo", "bar", "bar"));
+      Assert.assertTrue(o instanceof List);
+      List<String> result = (List<String>) o;
+      Assert.assertEquals(1, result.size());
+      Assert.assertEquals("foo", result.get(0));
+    }
+  }
+
+  @Test
+  public void testFilter_null() {
+    for (String expr : ImmutableList.of("FILTER([ 'foo', null], item -> item 
== null )"
+                                       ,"FILTER([ 'foo', baz], (item) -> item 
== null )"
+                                       )
+        )
+    {
+      Object o = run(expr, ImmutableMap.of("foo", "foo", "bar", "bar"));
+      Assert.assertTrue(o instanceof List);
+      List<String> result = (List<String>) o;
+      Assert.assertEquals(1, result.size());
+      Assert.assertEquals(null, result.get(0));
+    }
+  }
+
+  @Test
+  public void testFilter_notnull() {
+    for (String expr : ImmutableList.of("FILTER([ 'foo', null], item -> item 
!= null )"
+                                       ,"FILTER([ 'foo', baz], (item) -> item 
!= null )"
+                                       ,"FILTER([ foo, baz], (item) -> item != 
null )"
+                                       )
+        )
+    {
+      Object o = run(expr, ImmutableMap.of("foo", "foo", "bar", "bar"));
+      Assert.assertTrue(o instanceof List);
+      List<String> result = (List<String>) o;
+      Assert.assertEquals(1, result.size());
+      Assert.assertEquals("foo", result.get(0));
+    }
+  }
+
+  @Test
+  public void testFilter_none() {
+    for (String expr : ImmutableList.of( "FILTER([ foo, bar], () -> false  )"
+                                       , "FILTER([ 'foo', 'bar'], (item)-> 
false )"
+                                       ,"FILTER([ 'foo', bar], (item ) -> 
false )"
+                                       ,"FILTER([ foo, bar], (item) -> false )"
+                                       ,"FILTER([ foo, bar], item -> false )"
+
+                                       )
+        )
+    {
+      Object o = run(expr, ImmutableMap.of("foo", "foo", "bar", "bar"));
+      Assert.assertTrue(o instanceof List);
+      List<String> result = (List<String>) o;
+      Assert.assertEquals(0, result.size());
+    }
+  }
+
+  @Test
+  public void testFilter_all() {
+    for (String expr : ImmutableList.of("FILTER([ 'foo', 'bar'], (item) -> 
true )"
+                                       ,"FILTER([ 'foo', bar], (item) -> true 
)"
+                                       ,"FILTER([ foo, bar], (item) -> true )"
+                                       ,"FILTER([ foo, bar], item -> true )"
+                                       ,"FILTER([ foo, bar], ()-> true )"
+                                       )
+        )
+    {
+      Object o = run(expr, ImmutableMap.of("foo", "foo", "bar", "bar"));
+      Assert.assertTrue(o instanceof List);
+      List<String> result = (List<String>) o;
+      Assert.assertEquals(2, result.size());
+      Assert.assertEquals("foo", result.get(0));
+      Assert.assertEquals("bar", result.get(1));
+    }
+  }
+
+  @Test
+  public void testReduce_null() {
+    for (String expr : ImmutableList.of("REDUCE([ 1, 2, 3, null], (x, y) -> if 
y != null then x + y else x , 0 )"
+                                       ,"REDUCE([ foo, bar, 3, baz], (sum, y) 
-> if y != null then sum + y else sum, 0 )"
+                                       )
+        )
+    {
+      Object o = run(expr, ImmutableMap.of("foo", 1, "bar", 2));
+      Assert.assertTrue(o instanceof Number);
+      Number result = (Number) o;
+      Assert.assertEquals(6, result.intValue());
+    }
+  }
+
+  @Test
+  public void testReduce() {
+    for (String expr : ImmutableList.of("REDUCE([ 1, 2, 3 ], (x, y) -> x + y , 
0 )"
+                                       ,"REDUCE([ foo, bar, 3 ], (x, y) -> x + 
y , 0 )"
+                                       )
+        )
+    {
+      Object o = run(expr, ImmutableMap.of("foo", 1, "bar", 2));
+      Assert.assertTrue(o instanceof Number);
+      Number result = (Number) o;
+      Assert.assertEquals(6, result.intValue());
+    }
+  }
+
+  @Test
+  public void testReduce_on_various_list_sizes() {
+    {
+      String expr = "REDUCE([ 1, 2, 3, 4 ], (x, y) -> x + y , 0 )";
+      Object o = run(expr, ImmutableMap.of());
+      Assert.assertTrue(o instanceof Number);
+      Number result = (Number) o;
+      Assert.assertEquals(10, result.intValue());
+    }
+    {
+      String expr = "REDUCE([ 1, 2 ], (x, y) -> x + y , 0 )";
+      Object o = run(expr, ImmutableMap.of());
+      Assert.assertTrue(o instanceof Number);
+      Number result = (Number) o;
+      Assert.assertEquals(3, result.intValue());
+    }
+    {
+      String expr = "REDUCE([ 1 ], (x, y) -> x + y , 0 )";
+      Object o = run(expr, ImmutableMap.of());
+      Assert.assertTrue(o instanceof Number);
+      Number result = (Number) o;
+      Assert.assertEquals(1, result.intValue());
+    }
+  }
+
+  @Test
+  public void testReduce_NonNumeric() {
+    for (String expr : ImmutableList.of("REDUCE([ 'foo', 'bar', 'grok'], (x, 
y) -> LIST_ADD(x, y), [] )"
+                                       )
+        )
+    {
+      Object o = run(expr, ImmutableMap.of("foo", 1, "bar", 2));
+      Assert.assertTrue(o instanceof List);
+      List<String> result = (List<String>) o;
+      Assert.assertEquals(3, result.size());
+      Assert.assertEquals("foo", result.get(0));
+      Assert.assertEquals("bar", result.get(1));
+      Assert.assertEquals("grok", result.get(2));
+    }
+  }
+
+  @Test
+  public void testReduce_returns_null_when_less_than_3_args() {
+    {
+      String expr = "REDUCE([ 1, 2, 3 ], (x, y) -> LIST_ADD(x, y))";
+      Assert.assertThat(run(expr, ImmutableMap.of()), 
CoreMatchers.equalTo(null));
+    }
+    {
+      String expr = "REDUCE([ 1, 2, 3 ])";
+      Assert.assertThat(run(expr, ImmutableMap.of()), 
CoreMatchers.equalTo(null));
+    }
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/metron/blob/a5b13777/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/dsl/functions/MathFunctionsTest.java
----------------------------------------------------------------------
diff --git 
a/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/dsl/functions/MathFunctionsTest.java
 
b/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/dsl/functions/MathFunctionsTest.java
new file mode 100644
index 0000000..d427fb4
--- /dev/null
+++ 
b/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/dsl/functions/MathFunctionsTest.java
@@ -0,0 +1,47 @@
+/*
+ *
+ *  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.dsl.functions;
+
+import com.google.common.collect.ImmutableMap;
+import org.apache.metron.stellar.common.StellarProcessor;
+import org.apache.metron.stellar.dsl.Context;
+import org.apache.metron.stellar.dsl.StellarFunctions;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.Map;
+
+public class MathFunctionsTest {
+  public static Object run(String rule, Map<String, Object> variables) {
+    Context context = Context.EMPTY_CONTEXT();
+    StellarProcessor processor = new StellarProcessor();
+    Assert.assertTrue(rule + " not valid.", processor.validate(rule, context));
+    return processor.parse(rule, x -> variables.get(x), 
StellarFunctions.FUNCTION_RESOLVER(), context);
+  }
+
+  @Test
+  public void testAbs() {
+    Assert.assertEquals((Double)run("ABS(value)", ImmutableMap.of("value", 
0)), 0, 1e-7);
+    Assert.assertTrue(Double.isNaN((Double)run("ABS(value)", 
ImmutableMap.of("value", Double.NaN))));
+    Assert.assertEquals((Double)run("ABS(value)", ImmutableMap.of("value", 
10.5)), 10.5, 1e-7);
+    Assert.assertEquals((Double)run("ABS(value)", ImmutableMap.of("value", 
-10.5)), 10.5, 1e-7);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/metron/blob/a5b13777/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/dsl/functions/StringFunctionsTest.java
----------------------------------------------------------------------
diff --git 
a/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/dsl/functions/StringFunctionsTest.java
 
b/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/dsl/functions/StringFunctionsTest.java
new file mode 100644
index 0000000..ab6ca82
--- /dev/null
+++ 
b/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/dsl/functions/StringFunctionsTest.java
@@ -0,0 +1,430 @@
+/**
+ * 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.dsl.functions;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import org.apache.commons.collections4.map.HashedMap;
+import org.apache.metron.stellar.dsl.ParseException;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.Calendar;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.apache.metron.stellar.common.utils.StellarProcessorUtils.run;
+import static 
org.apache.metron.stellar.common.utils.StellarProcessorUtils.runPredicate;
+
+public class StringFunctionsTest {
+
+  @Test
+  public void testStringFunctions() throws Exception {
+    final Map<String, String> variableMap = new HashMap<String, String>() {{
+      put("foo", "casey");
+      put("ip", "192.168.0.1");
+      put("empty", "");
+      put("spaced", "metron is great");
+    }};
+    Assert.assertTrue(runPredicate("true and TO_UPPER(foo) == 'CASEY'", v -> 
variableMap.get(v)));
+    Assert.assertTrue(runPredicate("foo in [ TO_LOWER('CASEY'), 'david' ]", v 
-> variableMap.get(v)));
+    Assert.assertTrue(runPredicate("TO_UPPER(foo) in [ TO_UPPER('casey'), 
'david' ] and IN_SUBNET(ip, '192.168.0.0/24')", v -> variableMap.get(v)));
+    Assert.assertFalse(runPredicate("TO_LOWER(foo) in [ TO_UPPER('casey'), 
'david' ]", v -> variableMap.get(v)));
+  }
+
+  @Test
+  public void testStringFunctions_advanced() 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("empty", "");
+      put("spaced", "metron is great");
+      put("myList", ImmutableList.of("casey", "apple", "orange"));
+    }};
+    Assert.assertTrue(runPredicate("foo in SPLIT(bar, '.')", v -> 
variableMap.get(v)));
+    Assert.assertFalse(runPredicate("foo in SPLIT(ip, '.')", v -> 
variableMap.get(v)));
+    Assert.assertTrue(runPredicate("foo in myList", v -> variableMap.get(v)));
+    Assert.assertFalse(runPredicate("foo not in myList", v -> 
variableMap.get(v)));
+  }
+
+  @Test
+  public void testLeftRightFills() throws Exception {
+    final Map<String, Object> variableMap = new HashMap<String, Object>() {{
+      put("foo", null);
+      put("bar", null);
+      put("notInt", "oh my");
+    }};
+
+    //LEFT
+    Object left = run("FILL_LEFT('123','X', 10)", new HashedMap());
+    Assert.assertNotNull(left);
+    Assert.assertEquals(10, ((String) left).length());
+    Assert.assertEquals("XXXXXXX123", (String) left);
+
+    //RIGHT
+    Object right = run("FILL_RIGHT('123','X', 10)", new HashedMap());
+    Assert.assertNotNull(right);
+    Assert.assertEquals(10, ((String) right).length());
+    Assert.assertEquals("123XXXXXXX", (String) right);
+
+    //INPUT ALREADY LENGTH
+    Object same = run("FILL_RIGHT('123','X', 3)", new HashedMap());
+    Assert.assertEquals(3, ((String) same).length());
+    Assert.assertEquals("123", (String) same);
+
+    //INPUT BIGGER THAN LENGTH
+    Object tooBig = run("FILL_RIGHT('1234567890','X', 3)", new HashedMap());
+    Assert.assertEquals(10, ((String) tooBig).length());
+    Assert.assertEquals("1234567890", (String) tooBig);
+
+    //NULL VARIABLES
+    boolean thrown = false;
+    try {
+      run("FILL_RIGHT('123',foo,bar)", variableMap);
+    } catch (ParseException pe) {
+      thrown = true;
+      Assert.assertTrue(pe.getMessage().contains("are both required"));
+    }
+    Assert.assertTrue(thrown);
+    thrown = false;
+
+    // NULL LENGTH
+    try {
+      run("FILL_RIGHT('123','X',bar)", variableMap);
+    } catch (ParseException pe) {
+      thrown = true;
+      Assert.assertTrue(pe.getMessage().contains("are both required"));
+    }
+    Assert.assertTrue(thrown);
+    thrown = false;
+
+    // NULL FILL
+    try {
+      run("FILL_RIGHT('123',foo, 7)", variableMap);
+    } catch (ParseException pe) {
+      thrown = true;
+      Assert.assertTrue(pe.getMessage().contains("are both required"));
+    }
+    Assert.assertTrue(thrown);
+    thrown = false;
+
+    // NON INTEGER LENGTH
+    try {
+      run("FILL_RIGHT('123','X', 'z' )", new HashedMap());
+    } catch (ParseException pe) {
+      thrown = true;
+      Assert.assertTrue(pe.getMessage().contains("not a valid Integer"));
+    }
+    Assert.assertTrue(thrown);
+    thrown = false;
+
+    // EMPTY STRING PAD
+    try {
+      Object returnValue = run("FILL_RIGHT('123','', 10 )", new HashedMap());
+    } catch (ParseException pe) {
+      thrown = true;
+      Assert.assertTrue(pe.getMessage().contains("cannot be an empty"));
+    }
+    Assert.assertTrue(thrown);
+    thrown = false;
+
+    //MISSING LENGTH PARAMETER
+    try {
+      run("FILL_RIGHT('123',foo)", variableMap);
+    } catch (ParseException pe) {
+      thrown = true;
+      Assert.assertTrue(pe.getMessage().contains("expects three"));
+    }
+    Assert.assertTrue(thrown);
+  }
+
+  @Test
+  public void shannonEntropyTest() throws Exception {
+    //test empty string
+    Assert.assertEquals(0.0, (Double) run("STRING_ENTROPY('')", new 
HashMap<>()), 0.0);
+    Assert.assertEquals(0.0, (Double) run("STRING_ENTROPY(foo)", 
ImmutableMap.of("foo", "")), 0.0);
+
+    /*
+    Now consider the string aaaaaaaaaabbbbbccccc or 10 a's followed by 5 b's 
and 5 c's.
+    The probabilities of each character is as follows:
+    p(a) = 1/2
+    p(b) = 1/4
+    p(c) = 1/4
+    so the shannon entropy should be
+      -p(a)*log_2(p(a)) - p(b)*log_2(p(b)) - p(c)*log_2(p(c)) =
+      -0.5*-1 - 0.25*-2 - 0.25*-2 = 1.5
+     */
+    Assert.assertEquals(1.5, (Double) run("STRING_ENTROPY(foo)", 
ImmutableMap.of("foo", "aaaaaaaaaabbbbbccccc")), 0.0);
+  }
+
+  @Test
+  public void testFormat() throws Exception {
+
+    Map<String, Object> vars = ImmutableMap.of(
+            "cal", new Calendar.Builder().setDate(2017, 02, 02).build(),
+            "x", 234,
+            "y", 3);
+
+    Assert.assertEquals("no args",        run("FORMAT('no args')", vars));
+    Assert.assertEquals("234.0",          run("FORMAT('%.1f', 
TO_DOUBLE(234))", vars));
+    Assert.assertEquals("000234",         run("FORMAT('%06d', 234)", vars));
+    Assert.assertEquals("03 2,2017",      run("FORMAT('%1$tm %1$te,%1$tY', 
cal)", vars));
+    Assert.assertEquals("234 > 3",        run("FORMAT('%d > %d', x, y)", 
vars));
+    Assert.assertEquals("missing: null",  run("FORMAT('missing: %d', 
missing)", vars));
+  }
+
+  /**
+   * FORMAT - Not passing a format string will throw an exception
+   */
+  @Test(expected = ParseException.class)
+  public void testFormatWithNoArguments() throws Exception {
+    run("FORMAT()", Collections.emptyMap());
+  }
+
+  /**
+   * FORMAT - Forgetting to pass an argument required by the format string 
will throw an exception.
+   */
+  @Test(expected = ParseException.class)
+  public void testFormatWithMissingArguments() throws Exception {
+    run("FORMAT('missing arg: %d')", Collections.emptyMap());
+  }
+
+
+  /**
+   * CHOMP StringFunction
+   *
+   * @throws Exception
+   */
+  @Test
+  public void testChomp() throws Exception {
+    Assert.assertEquals("abc",  run("CHOMP('abc')", new HashedMap()));
+    Assert.assertEquals("abc",  run("CHOMP(msg)", ImmutableMap.of("msg", 
"abc\r\n")));
+    Assert.assertEquals("",     run("CHOMP(msg)", ImmutableMap.of("msg", 
"\n")));
+    Assert.assertEquals("",     run("CHOMP('')", new HashedMap()));
+    Assert.assertEquals(null,   run("CHOMP(msg)", new HashedMap()));
+    Assert.assertEquals(null,   run("CHOMP(null)", new HashedMap()));
+
+    // No input
+    boolean thrown = false;
+    try {
+      run("CHOMP()", Collections.emptyMap());
+    } catch (ParseException pe) {
+      thrown = true;
+      Assert.assertTrue(pe.getMessage().contains("missing argument"));
+    }
+    Assert.assertTrue(thrown);
+    thrown = false;
+
+    // Integer input
+    try {
+      run("CHOMP(123)", Collections.emptyMap());
+    } catch (ParseException pe) {
+      thrown = true;
+      Assert.assertTrue(pe.getMessage().contains("cannot be cast"));
+    }
+    Assert.assertTrue(thrown);
+
+  }
+
+  /**
+   * CHOP StringFunction
+   *
+   * @throws Exception
+   */
+  @Test
+  public void testChop() throws Exception {
+    Assert.assertEquals("ab",   run("CHOP('abc')", new HashedMap()));
+    Assert.assertEquals(null,   run("CHOP(null)", new HashedMap()));
+    Assert.assertEquals(null,   run("CHOP(msg)", new HashedMap()));
+    Assert.assertEquals("abc",  run("CHOP(msg)", ImmutableMap.of("msg", 
"abc\r\n")));
+    Assert.assertEquals("",     run("CHOP(msg)", ImmutableMap.of("msg", "")));
+    Assert.assertEquals("",     run("CHOP(msg)", ImmutableMap.of("msg", 
"\n")));
+    Assert.assertEquals("",     run("CHOP('')", new HashedMap()));
+
+    // No input
+    boolean thrown = false;
+    try {
+      run("CHOP()", Collections.emptyMap());
+    } catch (ParseException pe) {
+      thrown = true;
+      Assert.assertTrue(pe.getMessage().contains("missing argument"));
+    }
+    Assert.assertTrue(thrown);
+    thrown = false;
+
+    // Integer input
+    try {
+      run("CHOP(123)", Collections.emptyMap());
+    } catch (ParseException pe) {
+      thrown = true;
+      Assert.assertTrue(pe.getMessage().contains("cannot be cast"));
+    }
+    Assert.assertTrue(thrown);
+
+  }
+
+  /**
+   * PREPEND_IF_MISSING StringFunction
+   */
+  @Test
+  public void testPrependIfMissing() throws Exception {
+    Assert.assertEquals("xyzabc",     run("PREPEND_IF_MISSING('abc', 'xyz')", 
new HashedMap()));
+    Assert.assertEquals("xyzXYZabc",  run("PREPEND_IF_MISSING('XYZabc', 'xyz', 
'mno')", new HashedMap()));
+    Assert.assertEquals("mnoXYZabc",  run("PREPEND_IF_MISSING('mnoXYZabc', 
'xyz', 'mno')", new HashedMap()));
+    Assert.assertEquals(null,         run("PREPEND_IF_MISSING(null, null, 
null)", new HashedMap()));
+    Assert.assertEquals("xyz",        run("PREPEND_IF_MISSING('', 'xyz', 
null)", new HashedMap()));
+
+    // No input
+    boolean thrown = false;
+    try {
+      run("PREPEND_IF_MISSING()", Collections.emptyMap());
+    } catch (ParseException pe) {
+      thrown = true;
+      Assert.assertTrue(pe.getMessage().contains("incorrect arguments"));
+    }
+    Assert.assertTrue(thrown);
+    thrown = false;
+
+    // Incorrect number of arguments - 1
+    try {
+      run("PREPEND_IF_MISSING('abc')", Collections.emptyMap());
+    } catch (ParseException pe) {
+      thrown = true;
+      Assert.assertTrue(pe.getMessage().contains("incorrect arguments"));
+    }
+    Assert.assertTrue(thrown);
+    thrown = false;
+
+    // Incorrect number of arguments - 2
+    try {
+      run("PREPEND_IF_MISSING('abc', 'def', 'ghi', 'jkl')", 
Collections.emptyMap());
+    } catch (ParseException pe) {
+      thrown = true;
+      Assert.assertTrue(pe.getMessage().contains("incorrect arguments"));
+    }
+    Assert.assertTrue(thrown);
+    thrown = false;
+
+    // Integer input
+    try {
+      run("PREPEND_IF_MISSING(123, 'abc')", Collections.emptyMap());
+    } catch (ParseException pe) {
+      thrown = true;
+      Assert.assertTrue(pe.getMessage().contains("cannot be cast"));
+    }
+    Assert.assertTrue(thrown);
+
+  }
+
+  /**
+   * APPEND_IF_MISSING StringFunction
+   */
+  @Test
+  public void testAppendIfMissing() throws Exception {
+    Assert.assertEquals("apachemetron",   run("APPEND_IF_MISSING('apache', 
'metron')", new HashedMap()));
+    Assert.assertEquals("abcXYZxyz",      run("APPEND_IF_MISSING('abcXYZ', 
'xyz', 'mno')", new HashedMap()));
+    Assert.assertEquals(null,             run("APPEND_IF_MISSING(null, null, 
null)", new HashedMap()));
+    Assert.assertEquals("xyz",            run("APPEND_IF_MISSING('', 'xyz', 
null)", new HashedMap()));
+
+    // No input
+    boolean thrown = false;
+    try {
+      run("APPEND_IF_MISSING()", Collections.emptyMap());
+    } catch (ParseException pe) {
+      thrown = true;
+      Assert.assertTrue(pe.getMessage().contains("incorrect arguments"));
+    }
+    Assert.assertTrue(thrown);
+    thrown = false;
+
+    // Incorrect number of arguments - 1
+    try {
+      run("APPEND_IF_MISSING('abc')", Collections.emptyMap());
+    } catch (ParseException pe) {
+      thrown = true;
+      Assert.assertTrue(pe.getMessage().contains("incorrect arguments"));
+    }
+    Assert.assertTrue(thrown);
+    thrown = false;
+
+    // Incorrect number of arguments - 2
+    try {
+      run("APPEND_IF_MISSING('abc', 'def', 'ghi', 'jkl')", 
Collections.emptyMap());
+    } catch (ParseException pe) {
+      thrown = true;
+      Assert.assertTrue(pe.getMessage().contains("incorrect arguments"));
+    }
+    Assert.assertTrue(thrown);
+    thrown = false;
+
+    // Integer input
+    try {
+      run("APPEND_IF_MISSING(123, 'abc')", Collections.emptyMap());
+    } catch (ParseException pe) {
+      thrown = true;
+      Assert.assertTrue(pe.getMessage().contains("cannot be cast"));
+    }
+    Assert.assertTrue(thrown);
+
+  }
+
+  /**
+   * COUNT_MATCHES StringFunction
+   */
+  @Test
+  public void testCountMatches() throws Exception {
+    Assert.assertEquals(0, (int) run("COUNT_MATCHES(null, '*')", new 
HashedMap()));
+    Assert.assertEquals(2, (int) run("COUNT_MATCHES('apachemetron', 'e')", new 
HashedMap()));
+    Assert.assertEquals(2, (int) run("COUNT_MATCHES('anand', 'an')", new 
HashedMap()));
+    Assert.assertEquals(0, (int) run("COUNT_MATCHES('abcd', null)", new 
HashedMap()));
+
+    // No input
+    boolean thrown = false;
+    try {
+      run("COUNT_MATCHES()", Collections.emptyMap());
+    } catch (ParseException pe) {
+      thrown = true;
+      Assert.assertTrue(pe.getMessage().contains("incorrect arguments"));
+    }
+    Assert.assertTrue(thrown);
+    thrown = false;
+
+    // Incorrect number of arguments - 1
+    try {
+      run("COUNT_MATCHES('abc')", Collections.emptyMap());
+    } catch (ParseException pe) {
+      thrown = true;
+      Assert.assertTrue(pe.getMessage().contains("incorrect arguments"));
+    }
+    Assert.assertTrue(thrown);
+    thrown = false;
+
+    // Integer input
+    try {
+      run("COUNT_MATCHES(123, 456)", Collections.emptyMap());
+    } catch (ParseException pe) {
+      thrown = true;
+      Assert.assertTrue(pe.getMessage().contains("cannot be cast"));
+    }
+    Assert.assertTrue(thrown);
+
+  }
+}

http://git-wip-us.apache.org/repos/asf/metron/blob/a5b13777/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/dsl/functions/SystemFunctionsTest.java
----------------------------------------------------------------------
diff --git 
a/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/dsl/functions/SystemFunctionsTest.java
 
b/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/dsl/functions/SystemFunctionsTest.java
new file mode 100644
index 0000000..9dff323
--- /dev/null
+++ 
b/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/dsl/functions/SystemFunctionsTest.java
@@ -0,0 +1,78 @@
+/**
+ * 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.dsl.functions;
+
+import com.google.common.collect.ImmutableList;
+import org.apache.metron.stellar.common.system.Environment;
+import org.junit.Test;
+
+import java.util.ArrayList;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class SystemFunctionsTest {
+
+  @Test
+  public void smoke_test_non_mocked_env() {
+    SystemFunctions.EnvGet envGet = new SystemFunctions.EnvGet();
+    String envVal = (String) envGet.apply(ImmutableList.of("ENV_GET_VAR"));
+    assertThat("Value should not exist", envVal, equalTo(null));
+  }
+
+  @Test
+  public void env_get_returns_value() {
+    Environment env = mock(Environment.class);
+    when(env.get("ENV_GET_VAR")).thenReturn("ENV_GET_VALUE");
+    SystemFunctions.EnvGet envGet = new SystemFunctions.EnvGet(env);
+    String envVal = (String) envGet.apply(ImmutableList.of("ENV_GET_VAR"));
+    assertThat("Value should match", envVal, equalTo("ENV_GET_VALUE"));
+  }
+
+  @Test
+  public void env_get_returns_null_if_key_is_not_string() {
+    SystemFunctions.EnvGet envGet = new SystemFunctions.EnvGet();
+    String envVal = (String) envGet.apply(ImmutableList.of(new ArrayList()));
+    assertThat("Value should be null", envVal, equalTo(null));
+  }
+
+  @Test
+  public void property_get_returns_value() {
+    System.getProperties().put("ENV_GET_VAR", "ENV_GET_VALUE");
+    SystemFunctions.PropertyGet propertyGet = new 
SystemFunctions.PropertyGet();
+    String propertyVal = (String) 
propertyGet.apply(ImmutableList.of("ENV_GET_VAR"));
+    assertThat("Value should match", propertyVal, equalTo("ENV_GET_VALUE"));
+  }
+
+  @Test
+  public void property_get_nonexistent_returns_null() {
+    SystemFunctions.PropertyGet propertyGet = new 
SystemFunctions.PropertyGet();
+    String propertyVal = (String) 
propertyGet.apply(ImmutableList.of("PROPERTY_MISSING"));
+    assertThat("Value should not exist", propertyVal, equalTo(null));
+  }
+
+  @Test
+  public void property_get_returns_null_if_key_is_not_string() {
+    SystemFunctions.PropertyGet propertyGet = new 
SystemFunctions.PropertyGet();
+    String propertyVal = (String) propertyGet.apply(ImmutableList.of(new 
ArrayList()));
+    assertThat("Value should be null", propertyVal, equalTo(null));
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/metron/blob/a5b13777/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/dsl/functions/resolver/ClasspathFunctionResolverTest.java
----------------------------------------------------------------------
diff --git 
a/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/dsl/functions/resolver/ClasspathFunctionResolverTest.java
 
b/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/dsl/functions/resolver/ClasspathFunctionResolverTest.java
new file mode 100644
index 0000000..72cd53a
--- /dev/null
+++ 
b/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/dsl/functions/resolver/ClasspathFunctionResolverTest.java
@@ -0,0 +1,139 @@
+/**
+ * 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.dsl.functions.resolver;
+
+import com.google.common.collect.Lists;
+import org.apache.commons.vfs2.FileSystemException;
+import org.apache.metron.stellar.dsl.Context;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import java.io.File;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Properties;
+
+import static 
org.apache.metron.stellar.dsl.functions.resolver.ClasspathFunctionResolver.Config.*;
+
+public class ClasspathFunctionResolverTest {
+
+  private static List<String> expectedFunctions;
+
+  @BeforeClass
+  public static void setup() {
+
+    // search the entire classpath for functions - provides a baseline to test 
against
+    Properties config = new Properties();
+    // use a permissive regex that should not filter anything
+    ClasspathFunctionResolver resolver = create(config);
+
+    expectedFunctions = Lists.newArrayList(resolver.getFunctions());
+  }
+
+  /**
+   * Create a function resolver to test.
+   * @param config The configuration for Stellar.
+   */
+  public static ClasspathFunctionResolver create(Properties config) {
+    ClasspathFunctionResolver resolver = new ClasspathFunctionResolver();
+
+    Context context = new Context.Builder()
+            .with(Context.Capabilities.STELLAR_CONFIG, () -> config)
+            .build();
+    resolver.initialize(context);
+
+    return resolver;
+  }
+
+  @Test
+  public void testInclude() {
+
+    // setup - include all `org.apache.metron.*` functions
+    Properties config = new Properties();
+    config.put(STELLAR_SEARCH_INCLUDES_KEY.param(), "org.apache.metron.*");
+
+    // execute
+    ClasspathFunctionResolver resolver = create(config);
+    List<String> actual = Lists.newArrayList(resolver.getFunctions());
+
+    // validate - should have found all of the functions
+    Assert.assertEquals(expectedFunctions, actual);
+  }
+
+  @Test
+  public void testWithMultipleIncludes() {
+
+    // setup - include all of the common and management functions, which is 
most of them
+    Properties config = new Properties();
+    config.put(STELLAR_SEARCH_INCLUDES_KEY.param(), 
"org.apache.metron.common.*, org.apache.metron.management.*");
+
+    // execute
+    ClasspathFunctionResolver resolver = create(config);
+    List<String> actual = Lists.newArrayList(resolver.getFunctions());
+
+    // validate - should have found all of the functions
+    Assert.assertTrue(actual.size() > 0);
+    Assert.assertTrue(actual.size() <= expectedFunctions.size());
+  }
+
+  @Test
+  public void testExclude() {
+
+    // setup - exclude all `org.apache.metron.*` functions
+    Properties config = new Properties();
+    config.put(STELLAR_SEARCH_EXCLUDES_KEY.param(), "org.apache.metron.*");
+
+    // use a permissive regex that should not filter anything
+    ClasspathFunctionResolver resolver = create(config);
+    List<String> actual = Lists.newArrayList(resolver.getFunctions());
+
+    // both should have resolved the same functions
+    Assert.assertEquals(0, actual.size());
+  }
+
+  @Ignore  //until relocate dependencies for 
src/test/classpath-resources/custom-1.0-SNAPSHOT.jar
+  @Test
+  public void testExternalLocal() throws FileSystemException, 
ClassNotFoundException {
+    File jar = new File("src/test/classpath-resources");
+    Assert.assertTrue(jar.exists());
+    Properties config = new Properties();
+    config.put(STELLAR_VFS_PATHS.param(), jar.toURI() + "/.*.jar");
+
+    ClasspathFunctionResolver resolver = create(config);
+    HashSet<String> functions = new 
HashSet<>(Lists.newArrayList(resolver.getFunctions()));
+    Assert.assertTrue(functions.contains("NOW"));
+  }
+
+
+  @Ignore  //until relocate dependencies for 
src/test/classpath-resources/custom-1.0-SNAPSHOT.jar
+  @Test
+  public void testExternalHDFS() throws FileSystemException, 
ClassNotFoundException {
+    /* TODO: this needs to test HDFS, not local filesystem */
+    File jar = new File("src/test/classpath-resources");
+    Assert.assertTrue(jar.exists());
+    Properties config = new Properties();
+    config.put(STELLAR_VFS_PATHS.param(), jar.toURI() + "/.*.jar");
+
+    ClasspathFunctionResolver resolver = create(config);
+    HashSet<String> functions = new 
HashSet<>(Lists.newArrayList(resolver.getFunctions()));
+    Assert.assertTrue(functions.contains("NOW"));
+  }
+}

Reply via email to