blob: c93e4a1122457ba4dd9d017f94881cc0ce6554f4 [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.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.HashMap;
import java.util.List;
import java.util.Map;
import static org.apache.metron.stellar.common.utils.StellarProcessorUtils.run;
public class FunctionalFunctionsTest {
@Test
public void testZipLongest_boundary() {
for (String expr : ImmutableList.of( "ZIP_LONGEST()"
, "ZIP_LONGEST( null, null )"
, "ZIP_LONGEST( [], null )"
, "ZIP_LONGEST( [], [] )"
, "ZIP_LONGEST( null, [] )"
)
)
{
List<List<Object>> o = (List<List<Object>>) run(expr, new HashMap<>());
Assert.assertEquals(0, o.size());
}
}
@Test
public void testZip_longest() {
Map<String, Object> variables = ImmutableMap.of(
"list1" , ImmutableList.of(1, 2, 3)
,"list2", ImmutableList.of(4, 5, 6, 7)
);
for (String expr : ImmutableList.of( "ZIP_LONGEST(list1)"
, "ZIP_LONGEST( [1, 2, 3])"
)
)
{
List<List<Object>> o = (List<List<Object>>) run(expr, variables);
Assert.assertEquals(3, o.size());
for (int i = 0; i < 3; ++i) {
List l = o.get(i);
Assert.assertEquals(1, l.size());
Assert.assertEquals(i+1, l.get(0));
}
}
for (String expr : ImmutableList.of( "ZIP_LONGEST(list1, list2)"
, "ZIP_LONGEST( [1, 2, 3], [4, 5, 6, 7] )"
)
)
{
List<List<Object>> o = (List<List<Object>>) run(expr, variables);
Assert.assertEquals(4, o.size());
for (int i = 0; i < 3; ++i) {
List l = o.get(i);
Assert.assertEquals(2, l.size());
Assert.assertEquals(i+1, l.get(0));
Assert.assertEquals(i+4, l.get(1));
}
{
int i = 3;
List l = o.get(i);
Assert.assertEquals(2, l.size());
Assert.assertNull(l.get(0));
Assert.assertEquals(i+4, l.get(1));
}
}
for (String expr : ImmutableList.of(
"REDUCE(ZIP_LONGEST(list2, list1), (s, x) -> s + GET_FIRST(x) * GET_LAST(x), 0)"
, "REDUCE(ZIP_LONGEST( [1, 2, 3], [4, 5, 6, 7] ), (s, x) -> s + GET_FIRST(x) * GET_LAST(x), 0)"
, "REDUCE(ZIP_LONGEST(list1, list2), (s, x) -> s + GET_FIRST(x) * GET_LAST(x), 0)" //this works because stellar treats nulls as 0 in arithmetic operations.
, "REDUCE(ZIP_LONGEST(list1, list2), (s, x) -> s + (GET_FIRST(x) == null?0:GET_FIRST(x)) * (GET_LAST(x) == null?0:GET_LAST(x)), 0)" //with proper guarding NOT assuming stellar peculiarities
)
)
{
int o = (int) run(expr, variables);
Assert.assertEquals(1*4 + 2*5 + 3*6, o, 1e-7);
}
}
@Test
public void testZip_boundary() {
for (String expr : ImmutableList.of( "ZIP()"
, "ZIP( null, null )"
, "ZIP( [], null )"
, "ZIP( [], [] )"
, "ZIP( null, [] )"
)
)
{
List<List<Object>> o = (List<List<Object>>) run(expr, new HashMap<>());
Assert.assertEquals(0, o.size());
}
}
@Test
public void testZip() {
Map<String, Object> variables = ImmutableMap.of(
"list1" , ImmutableList.of(1, 2, 3)
,"list2", ImmutableList.of(4, 5, 6)
);
for (String expr : ImmutableList.of( "ZIP(list1)"
, "ZIP( [1, 2, 3])"
)
)
{
List<List<Object>> o = (List<List<Object>>) run(expr, variables);
Assert.assertEquals(3, o.size());
for (int i = 0; i < 3; ++i) {
List l = o.get(i);
Assert.assertEquals(1, l.size());
Assert.assertEquals(i+1, l.get(0));
}
}
for (String expr : ImmutableList.of( "ZIP(list1, list2)"
, "ZIP( [1, 2, 3], [4, 5, 6] )"
, "ZIP( [1, 2, 3], [4, 5, 6, 7] )"
)
)
{
List<List<Object>> o = (List<List<Object>>) run(expr, variables);
Assert.assertEquals(3, o.size());
for (int i = 0; i < 3; ++i) {
List l = o.get(i);
Assert.assertEquals(2, l.size());
Assert.assertEquals(i+1, l.get(0));
Assert.assertEquals(i+4, l.get(1));
}
}
for (String expr : ImmutableList.of(
"REDUCE(ZIP(list1, list2), (s, x) -> s + GET_FIRST(x) * GET_LAST(x), 0)"
, "REDUCE(ZIP( [1, 2, 3], [4, 5, 6] ), (s, x) -> s + GET_FIRST(x) * GET_LAST(x), 0)"
, "REDUCE(ZIP( [1, 2, 3], [4, 5, 6, 7] ), (s, x) -> s + GET_FIRST(x) * GET_LAST(x), 0)"
)
)
{
int o = (int) run(expr, variables);
Assert.assertEquals(1*4 + 2*5 + 3*6, o, 1e-7);
}
}
@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 )"
)
)
{
Map<String,Object> variableMap = new HashMap<String,Object>(){{
put("foo",2);
put("bar", 3);
put("baz",null);
}};
Object o = run(expr,variableMap);
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 )"
)
)
{
Map<String,Object> variableMap = new HashMap<String,Object>(){{
put("foo","foo");
put("bar","bar");
put("baz",null);
}};
Object o = run(expr,variableMap);
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 )"
)
)
{
Map<String,Object> variableMap = new HashMap<String,Object>(){{
put("foo","foo");
put("bar","bar");
put("baz",null);
}};
Object o = run(expr,variableMap);
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 )"
)
)
{
Map<String,Object> variableMap = new HashMap<String,Object>(){{
put("foo",1);
put("bar", 2);
put("baz",null);
}};
Object o = run(expr,variableMap);
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,"x",0,"y",0));
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));
}
}
}