diff --git a/dd-java-agent/agent-debugger/debugger-bootstrap/src/main/java/datadog/trace/bootstrap/debugger/el/ValueReferences.java b/dd-java-agent/agent-debugger/debugger-bootstrap/src/main/java/datadog/trace/bootstrap/debugger/el/ValueReferences.java index 2903bac33fc..c64844e5e83 100644 --- a/dd-java-agent/agent-debugger/debugger-bootstrap/src/main/java/datadog/trace/bootstrap/debugger/el/ValueReferences.java +++ b/dd-java-agent/agent-debugger/debugger-bootstrap/src/main/java/datadog/trace/bootstrap/debugger/el/ValueReferences.java @@ -14,10 +14,14 @@ public final class ValueReferences { public static String RETURN_EXTENSION_NAME = "return"; public static String ITERATOR_EXTENSION_NAME = "it"; public static String EXCEPTION_EXTENSION_NAME = "exception"; + public static String KEY_EXTENSION_NAME = "key"; + public static String VALUE_EXTENSION_NAME = "value"; public static String DURATION_REF = SYNTHETIC_PREFIX + DURATION_EXTENSION_NAME; public static String RETURN_REF = SYNTHETIC_PREFIX + RETURN_EXTENSION_NAME; public static String ITERATOR_REF = SYNTHETIC_PREFIX + ITERATOR_EXTENSION_NAME; public static String EXCEPTION_REF = SYNTHETIC_PREFIX + EXCEPTION_EXTENSION_NAME; + public static String KEY_REF = SYNTHETIC_PREFIX + KEY_EXTENSION_NAME; + public static String VALUE_REF = SYNTHETIC_PREFIX + VALUE_EXTENSION_NAME; public static String synthetic(String name) { return SYNTHETIC_PREFIX + name; diff --git a/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/PrettyPrintVisitor.java b/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/PrettyPrintVisitor.java index 02d6ef3be10..f0295f66de3 100644 --- a/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/PrettyPrintVisitor.java +++ b/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/PrettyPrintVisitor.java @@ -89,27 +89,27 @@ public String visit(EndsWithExpression endsWithExpression) { public String visit(FilterCollectionExpression filterCollectionExpression) { return "filter(" + nullSafeAccept(filterCollectionExpression.getSource()) - + ", " + + ", {" + nullSafeAccept(filterCollectionExpression.getFilterExpression()) - + ")"; + + "})"; } @Override public String visit(HasAllExpression hasAllExpression) { return "all(" + nullSafeAccept(hasAllExpression.getValueExpression()) - + ", " + + ", {" + nullSafeAccept(hasAllExpression.getFilterPredicateExpression()) - + ")"; + + "})"; } @Override public String visit(HasAnyExpression hasAnyExpression) { return "any(" + nullSafeAccept(hasAnyExpression.getValueExpression()) - + ", " + + ", {" + nullSafeAccept(hasAnyExpression.getFilterPredicateExpression()) - + ")"; + + "})"; } @Override diff --git a/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/FilterCollectionExpression.java b/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/FilterCollectionExpression.java index 6ff19eaec84..df0ff96906e 100644 --- a/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/FilterCollectionExpression.java +++ b/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/FilterCollectionExpression.java @@ -58,13 +58,14 @@ public CollectionValue evaluate(ValueReferenceResolver valueRefResolver) { } else if (collectionValue instanceof MapValue) { MapValue materialized = (MapValue) collectionValue; Map filtered = new HashMap<>(); - for (Value key : materialized.getKeys()) { Value value = key.isUndefined() ? Value.undefinedValue() : materialized.get(key); - if (filterExpression.evaluate( - valueRefResolver.withExtensions( - Collections.singletonMap( - ValueReferences.ITERATOR_EXTENSION_NAME, new MapValue.Entry(key, value))))) { + Map valueRefExtensions = new HashMap<>(); + valueRefExtensions.put(ValueReferences.KEY_EXTENSION_NAME, key); + valueRefExtensions.put(ValueReferences.VALUE_EXTENSION_NAME, value); + valueRefExtensions.put( + ValueReferences.ITERATOR_EXTENSION_NAME, new MapValue.Entry(key, value)); + if (filterExpression.evaluate(valueRefResolver.withExtensions(valueRefExtensions))) { filtered.put(key.getValue(), value.getValue()); } } diff --git a/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/HasAllExpression.java b/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/HasAllExpression.java index 8037dc4b45a..4b410618618 100644 --- a/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/HasAllExpression.java +++ b/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/HasAllExpression.java @@ -11,6 +11,8 @@ import datadog.trace.bootstrap.debugger.el.ValueReferences; import datadog.trace.bootstrap.debugger.util.WellKnownClasses; import java.util.Collections; +import java.util.HashMap; +import java.util.Map; import java.util.Set; /** @@ -65,10 +67,13 @@ public Boolean evaluate(ValueReferenceResolver valueRefResolver) { } for (Value key : map.getKeys()) { Value val = key.isUndefined() ? Value.undefinedValue() : map.get(key); + Map valueRefExtensions = new HashMap<>(); + valueRefExtensions.put(ValueReferences.KEY_EXTENSION_NAME, key); + valueRefExtensions.put(ValueReferences.VALUE_EXTENSION_NAME, val); + valueRefExtensions.put( + ValueReferences.ITERATOR_EXTENSION_NAME, new MapValue.Entry(key, val)); if (!filterPredicateExpression.evaluate( - valueRefResolver.withExtensions( - Collections.singletonMap( - ValueReferences.ITERATOR_EXTENSION_NAME, new MapValue.Entry(key, val))))) { + valueRefResolver.withExtensions(valueRefExtensions))) { return Boolean.FALSE; } } diff --git a/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/HasAnyExpression.java b/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/HasAnyExpression.java index 7ede0129c71..e27db98ffbc 100644 --- a/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/HasAnyExpression.java +++ b/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/HasAnyExpression.java @@ -11,6 +11,8 @@ import datadog.trace.bootstrap.debugger.el.ValueReferences; import datadog.trace.bootstrap.debugger.util.WellKnownClasses; import java.util.Collections; +import java.util.HashMap; +import java.util.Map; import java.util.Set; /** @@ -65,11 +67,13 @@ public Boolean evaluate(ValueReferenceResolver valueRefResolver) { } for (Value key : map.getKeys()) { Value val = key.isUndefined() ? Value.undefinedValue() : map.get(key); - + Map valueRefExtensions = new HashMap<>(); + valueRefExtensions.put(ValueReferences.KEY_EXTENSION_NAME, key); + valueRefExtensions.put(ValueReferences.VALUE_EXTENSION_NAME, val); + valueRefExtensions.put( + ValueReferences.ITERATOR_EXTENSION_NAME, new MapValue.Entry(key, val)); if (filterPredicateExpression.evaluate( - valueRefResolver.withExtensions( - Collections.singletonMap( - ValueReferences.ITERATOR_EXTENSION_NAME, new MapValue.Entry(key, val))))) { + valueRefResolver.withExtensions(valueRefExtensions))) { return Boolean.TRUE; } } diff --git a/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/expressions/FilterCollectionExpressionTest.java b/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/expressions/FilterCollectionExpressionTest.java index 73912da08be..1c3aa4896a8 100644 --- a/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/expressions/FilterCollectionExpressionTest.java +++ b/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/expressions/FilterCollectionExpressionTest.java @@ -28,7 +28,7 @@ void testMatchingList() { assertFalse(filtered.isEmpty()); assertFalse(filtered.isNull()); assertFalse(filtered.isUndefined()); - assertEquals("filter(int[], @it < 2)", print(expression)); + assertEquals("filter(int[], {@it < 2})", print(expression)); } @Test @@ -41,7 +41,7 @@ void testEmptyList() { assertTrue(filtered.isEmpty()); assertFalse(filtered.isNull()); assertFalse(filtered.isUndefined()); - assertEquals("filter(int[], @it < 2)", print(expression)); + assertEquals("filter(int[], {@it < 2})", print(expression)); } @Test @@ -52,7 +52,7 @@ void testNullList() { CollectionValue filtered = expression.evaluate(RefResolverHelper.createResolver(this)); assertEquals(collection, filtered); assertTrue(filtered.isNull()); - assertEquals("filter(null, @it < 2)", print(expression)); + assertEquals("filter(null, {@it < 2})", print(expression)); } @Test @@ -63,7 +63,7 @@ void testNullObjectList() { CollectionValue filtered = expression.evaluate(RefResolverHelper.createResolver(this)); assertEquals(collection, filtered); assertTrue(filtered.isNull()); - assertEquals("filter(null, @it < 2)", print(expression)); + assertEquals("filter(null, {@it < 2})", print(expression)); } @Test @@ -74,7 +74,7 @@ void testUndefinedList() { CollectionValue filtered = expression.evaluate(RefResolverHelper.createResolver(this)); assertEquals(collection, filtered); assertTrue(filtered.isUndefined()); - assertEquals("filter(null, @it < 2)", print(expression)); + assertEquals("filter(null, {@it < 2})", print(expression)); } @Test @@ -104,7 +104,7 @@ void testMatchingMap() { assertFalse(filtered.isEmpty()); assertFalse(filtered.isNull()); assertFalse(filtered.isUndefined()); - assertEquals("filter(Map, @it.value < 2)", print(expression)); + assertEquals("filter(Map, {@it.value < 2})", print(expression)); } @Test @@ -117,7 +117,7 @@ void testEmptyMap() { assertTrue(filtered.isEmpty()); assertFalse(filtered.isNull()); assertFalse(filtered.isUndefined()); - assertEquals("filter(Map, @it < 2)", print(expression)); + assertEquals("filter(Map, {@it < 2})", print(expression)); } @Test @@ -128,7 +128,7 @@ void testNullMap() { CollectionValue filtered = expression.evaluate(RefResolverHelper.createResolver(this)); assertEquals(collection, filtered); assertTrue(filtered.isNull()); - assertEquals("filter(null, @it < 2)", print(expression)); + assertEquals("filter(null, {@it < 2})", print(expression)); } @Test @@ -139,7 +139,7 @@ void testNullObjectMap() { CollectionValue filtered = expression.evaluate(RefResolverHelper.createResolver(this)); assertEquals(collection, filtered); assertTrue(filtered.isNull()); - assertEquals("filter(null, @it < 2)", print(expression)); + assertEquals("filter(null, {@it < 2})", print(expression)); } @Test @@ -150,6 +150,29 @@ void testUndefinedMap() { CollectionValue filtered = expression.evaluate(RefResolverHelper.createResolver(this)); assertEquals(collection, filtered); assertTrue(filtered.isUndefined()); - assertEquals("filter(null, @it < 2)", print(expression)); + assertEquals("filter(null, {@it < 2})", print(expression)); + } + + @Test + void keyValueMap() { + Map map = new HashMap<>(); + map.put("a", 1); + map.put("b", 2); + map.put("c", 3); + MapValue collection = new MapValue(map); + + FilterCollectionExpression expression = + new FilterCollectionExpression(collection, eq(ref(ValueReferences.KEY_REF), value("b"))); + CollectionValue filtered = expression.evaluate(RefResolverHelper.createResolver(this)); + assertNotEquals(collection, filtered); + assertEquals(1, filtered.count()); + assertEquals("filter(Map, {@key == \"b\"})", print(expression)); + + expression = + new FilterCollectionExpression(collection, eq(ref(ValueReferences.VALUE_REF), value(2))); + filtered = expression.evaluate(RefResolverHelper.createResolver(this)); + assertNotEquals(collection, filtered); + assertEquals(1, filtered.count()); + assertEquals("filter(Map, {@value == 2})", print(expression)); } } diff --git a/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/expressions/HasAllExpressionTest.java b/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/expressions/HasAllExpressionTest.java index 4b0d66cd566..c22df80c34c 100644 --- a/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/expressions/HasAllExpressionTest.java +++ b/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/expressions/HasAllExpressionTest.java @@ -30,23 +30,23 @@ void testNullPredicate() { EvaluationException exception = assertThrows(EvaluationException.class, () -> nullExpression.evaluate(resolver)); assertEquals("Cannot evaluate the expression for null value", exception.getMessage()); - assertEquals("all(null, true)", print(nullExpression)); + assertEquals("all(null, {true})", print(nullExpression)); HasAllExpression undefinedExpression = new HasAllExpression(value(Values.UNDEFINED_OBJECT), null); exception = assertThrows(EvaluationException.class, () -> undefinedExpression.evaluate(resolver)); assertEquals("Cannot evaluate the expression for undefined value", exception.getMessage()); - assertEquals("all(UNDEFINED, true)", print(undefinedExpression)); + assertEquals("all(UNDEFINED, {true})", print(undefinedExpression)); HasAllExpression expression = new HasAllExpression(value(this), null); assertTrue(expression.evaluate(resolver)); assertEquals( - "all(com.datadog.debugger.el.expressions.HasAllExpressionTest, true)", print(expression)); + "all(com.datadog.debugger.el.expressions.HasAllExpressionTest, {true})", print(expression)); expression = new HasAllExpression(value(Collections.singletonList(this)), null); assertTrue(expression.evaluate(resolver)); - assertEquals("all(List, true)", print(expression)); + assertEquals("all(List, {true})", print(expression)); expression = new HasAllExpression(value(Collections.singletonMap(this, this)), null); assertTrue(expression.evaluate(resolver)); - assertEquals("all(Map, true)", print(expression)); + assertEquals("all(Map, {true})", print(expression)); } @Test @@ -56,17 +56,17 @@ void testNullHasAll() { EvaluationException exception = assertThrows(EvaluationException.class, () -> nullExpression1.evaluate(ctx)); assertEquals("Cannot evaluate the expression for null value", exception.getMessage()); - assertEquals("all(null, true)", print(nullExpression1)); + assertEquals("all(null, {true})", print(nullExpression1)); HasAllExpression nullExpression2 = all(null, FALSE); exception = assertThrows(EvaluationException.class, () -> nullExpression2.evaluate(ctx)); assertEquals("Cannot evaluate the expression for null value", exception.getMessage()); - assertEquals("all(null, false)", print(nullExpression2)); + assertEquals("all(null, {false})", print(nullExpression2)); HasAllExpression nullExpression3 = all(null, eq(ref("testField"), value(10))); exception = assertThrows(EvaluationException.class, () -> nullExpression3.evaluate(ctx)); assertEquals("Cannot evaluate the expression for null value", exception.getMessage()); - assertEquals("all(null, testField == 10)", print(nullExpression3)); + assertEquals("all(null, {testField == 10})", print(nullExpression3)); } @Test @@ -76,18 +76,18 @@ void testUndefinedHasAll() { EvaluationException exception = assertThrows(EvaluationException.class, () -> undefinedExpression.evaluate(ctx)); assertEquals("Cannot evaluate the expression for undefined value", exception.getMessage()); - assertEquals("all(UNDEFINED, true)", print(undefinedExpression)); + assertEquals("all(UNDEFINED, {true})", print(undefinedExpression)); HasAllExpression nullExpression = all(null, FALSE); exception = assertThrows(EvaluationException.class, () -> nullExpression.evaluate(ctx)); assertEquals("Cannot evaluate the expression for null value", exception.getMessage()); - assertEquals("all(null, false)", print(nullExpression)); + assertEquals("all(null, {false})", print(nullExpression)); HasAllExpression expression = all(value(Values.UNDEFINED_OBJECT), eq(ref("testField"), value(10))); exception = assertThrows(EvaluationException.class, () -> expression.evaluate(ctx)); assertEquals("Cannot evaluate the expression for undefined value", exception.getMessage()); - assertEquals("all(UNDEFINED, testField == 10)", print(expression)); + assertEquals("all(UNDEFINED, {testField == 10})", print(expression)); } @Test @@ -97,17 +97,18 @@ void testSingleElementHasAll() { HasAllExpression expression = all(targetExpression, TRUE); assertTrue(expression.evaluate(ctx)); assertEquals( - "all(com.datadog.debugger.el.expressions.HasAllExpressionTest, true)", print(expression)); + "all(com.datadog.debugger.el.expressions.HasAllExpressionTest, {true})", print(expression)); expression = all(targetExpression, FALSE); assertFalse(expression.evaluate(ctx)); assertEquals( - "all(com.datadog.debugger.el.expressions.HasAllExpressionTest, false)", print(expression)); + "all(com.datadog.debugger.el.expressions.HasAllExpressionTest, {false})", + print(expression)); expression = all(targetExpression, eq(ref("testField"), value(10))); assertTrue(expression.evaluate(ctx)); assertEquals( - "all(com.datadog.debugger.el.expressions.HasAllExpressionTest, testField == 10)", + "all(com.datadog.debugger.el.expressions.HasAllExpressionTest, {testField == 10})", print(expression)); } @@ -118,9 +119,11 @@ void testArrayHasAll() { HasAllExpression expression = all(targetExpression, TRUE); assertTrue(expression.evaluate(ctx)); + assertEquals("all(java.lang.Object[], {true})", print(expression)); expression = all(targetExpression, FALSE); assertFalse(expression.evaluate(ctx)); + assertEquals("all(java.lang.Object[], {false})", print(expression)); GetMemberExpression fldRef = getMember(ref(ValueReferences.ITERATOR_REF), "testField"); ValueRefExpression itRef = ref(ValueReferences.ITERATOR_REF); @@ -133,9 +136,11 @@ void testArrayHasAll() { expression = all(targetExpression, eq(itRef, value("hello"))); assertFalse(expression.evaluate(ctx)); + assertEquals("all(java.lang.Object[], {@it == \"hello\"})", print(expression)); expression = all(targetExpression, not(isEmpty(itRef))); assertTrue(expression.evaluate(ctx)); + assertEquals("all(java.lang.Object[], {not(isEmpty(@it))})", print(expression)); } @Test @@ -145,9 +150,11 @@ void testListHasAll() { HasAllExpression expression = all(targetExpression, TRUE); assertTrue(expression.evaluate(ctx)); + assertEquals("all(List, {true})", print(expression)); expression = all(targetExpression, FALSE); assertFalse(expression.evaluate(ctx)); + assertEquals("all(List, {false})", print(expression)); ValueRefExpression fldRef = ref(ValueReferences.ITERATOR_REF + "testField"); ValueRefExpression itRef = ref(ValueReferences.ITERATOR_REF); @@ -160,9 +167,11 @@ void testListHasAll() { expression = all(targetExpression, eq(itRef, value("hello"))); assertFalse(expression.evaluate(ctx)); + assertEquals("all(List, {@it == \"hello\"})", print(expression)); expression = all(targetExpression, not(isEmpty(itRef))); assertTrue(expression.evaluate(ctx)); + assertEquals("all(List, {not(isEmpty(@it))})", print(expression)); } @Test @@ -176,19 +185,23 @@ void testMapHasAll() { HasAllExpression expression = all(targetExpression, TRUE); assertTrue(expression.evaluate(ctx)); + assertEquals("all(Map, {true})", print(expression)); expression = all(targetExpression, FALSE); assertFalse(expression.evaluate(ctx)); + assertEquals("all(Map, {false})", print(expression)); expression = all(targetExpression, eq(getMember(ref(ValueReferences.ITERATOR_REF), "key"), value("a"))); assertFalse(expression.evaluate(ctx)); + assertEquals("all(Map, {@it.key == \"a\"})", print(expression)); expression = all( targetExpression, eq(getMember(ref(ValueReferences.ITERATOR_REF), "value"), value("a"))); assertTrue(expression.evaluate(ctx)); + assertEquals("all(Map, {@it.value == \"a\"})", print(expression)); } @Test @@ -202,12 +215,15 @@ void testSetHasAll() { HasAllExpression expression = all(targetExpression, TRUE); assertTrue(expression.evaluate(ctx)); + assertEquals("all(Set, {true})", print(expression)); expression = all(targetExpression, FALSE); assertFalse(expression.evaluate(ctx)); + assertEquals("all(Set, {false})", print(expression)); expression = all(targetExpression, eq(ref(ValueReferences.ITERATOR_REF), value("key"))); assertFalse(expression.evaluate(ctx)); + assertEquals("all(Set, {@it == \"key\"})", print(expression)); expression = all( @@ -216,6 +232,7 @@ void testSetHasAll() { eq(ref(ValueReferences.ITERATOR_REF), value("foo")), eq(ref(ValueReferences.ITERATOR_REF), value("bar")))); assertTrue(expression.evaluate(ctx)); + assertEquals("all(Set, {@it == \"foo\" || @it == \"bar\"})", print(expression)); } @Test @@ -230,4 +247,21 @@ void emptiness() { expression = all(value(Collections.emptySet()), TRUE); assertTrue(expression.evaluate(ctx)); } + + @Test + void keyValueMap() { + ValueReferenceResolver ctx = RefResolverHelper.createResolver(null, null); + Map valueMap = new HashMap<>(); + valueMap.put("a", "a"); + valueMap.put("b", "a"); + ValueExpression targetExpression = value(valueMap); + HasAllExpression expression = + all(targetExpression, eq(ref(ValueReferences.KEY_REF), value("a"))); + assertFalse(expression.evaluate(ctx)); + assertEquals("all(Map, {@key == \"a\"})", print(expression)); + + expression = all(targetExpression, eq(ref(ValueReferences.VALUE_REF), value("a"))); + assertTrue(expression.evaluate(ctx)); + assertEquals("all(Map, {@value == \"a\"})", print(expression)); + } } diff --git a/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/expressions/HasAnyExpressionTest.java b/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/expressions/HasAnyExpressionTest.java index c3fe235fd39..fb597f06cfb 100644 --- a/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/expressions/HasAnyExpressionTest.java +++ b/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/expressions/HasAnyExpressionTest.java @@ -29,23 +29,23 @@ void testNullPredicate() { EvaluationException exception = assertThrows(EvaluationException.class, () -> nullExpression.evaluate(resolver)); assertEquals("Cannot evaluate the expression for null value", exception.getMessage()); - assertEquals("any(null, true)", print(nullExpression)); + assertEquals("any(null, {true})", print(nullExpression)); HasAnyExpression undefinedExpression = new HasAnyExpression(value(Values.UNDEFINED_OBJECT), null); exception = assertThrows(EvaluationException.class, () -> undefinedExpression.evaluate(resolver)); assertEquals("Cannot evaluate the expression for undefined value", exception.getMessage()); - assertEquals("any(UNDEFINED, true)", print(undefinedExpression)); + assertEquals("any(UNDEFINED, {true})", print(undefinedExpression)); HasAnyExpression expression = new HasAnyExpression(value(this), null); assertTrue(expression.evaluate(resolver)); assertEquals( - "any(com.datadog.debugger.el.expressions.HasAnyExpressionTest, true)", print(expression)); + "any(com.datadog.debugger.el.expressions.HasAnyExpressionTest, {true})", print(expression)); expression = new HasAnyExpression(value(Collections.singletonList(this)), null); assertTrue(expression.evaluate(resolver)); - assertEquals("any(List, true)", print(expression)); + assertEquals("any(List, {true})", print(expression)); expression = new HasAnyExpression(value(Collections.singletonMap(this, this)), null); assertTrue(expression.evaluate(resolver)); - assertEquals("any(Map, true)", print(expression)); + assertEquals("any(Map, {true})", print(expression)); } @Test @@ -55,17 +55,17 @@ void testNullHasAny() { EvaluationException exception = assertThrows(EvaluationException.class, () -> nullExpression1.evaluate(ctx)); assertEquals("Cannot evaluate the expression for null value", exception.getMessage()); - assertEquals("any(null, true)", print(nullExpression1)); + assertEquals("any(null, {true})", print(nullExpression1)); HasAnyExpression nullExpression2 = any(null, BooleanExpression.FALSE); exception = assertThrows(EvaluationException.class, () -> nullExpression2.evaluate(ctx)); assertEquals("Cannot evaluate the expression for null value", exception.getMessage()); - assertEquals("any(null, false)", print(nullExpression2)); + assertEquals("any(null, {false})", print(nullExpression2)); HasAnyExpression nullExpression3 = any(null, eq(ref("testField"), value(10))); exception = assertThrows(EvaluationException.class, () -> nullExpression3.evaluate(ctx)); assertEquals("Cannot evaluate the expression for null value", exception.getMessage()); - assertEquals("any(null, testField == 10)", print(nullExpression3)); + assertEquals("any(null, {testField == 10})", print(nullExpression3)); } @Test @@ -75,18 +75,18 @@ void testUndefinedHasAny() { EvaluationException exception = assertThrows(EvaluationException.class, () -> undefinedExpression.evaluate(ctx)); assertEquals("Cannot evaluate the expression for undefined value", exception.getMessage()); - assertEquals("any(UNDEFINED, true)", print(undefinedExpression)); + assertEquals("any(UNDEFINED, {true})", print(undefinedExpression)); HasAnyExpression nullExpression = any(null, FALSE); exception = assertThrows(EvaluationException.class, () -> nullExpression.evaluate(ctx)); assertEquals("Cannot evaluate the expression for null value", exception.getMessage()); - assertEquals("any(null, false)", print(nullExpression)); + assertEquals("any(null, {false})", print(nullExpression)); HasAnyExpression undefinedExpression2 = any(value(Values.UNDEFINED_OBJECT), eq(ref("testField"), value(10))); exception = assertThrows(EvaluationException.class, () -> undefinedExpression2.evaluate(ctx)); assertEquals("Cannot evaluate the expression for undefined value", exception.getMessage()); - assertEquals("any(UNDEFINED, testField == 10)", print(undefinedExpression2)); + assertEquals("any(UNDEFINED, {testField == 10})", print(undefinedExpression2)); } @Test @@ -96,12 +96,13 @@ void testSingleElementHasAny() { HasAnyExpression expression = any(targetExpression, TRUE); assertTrue(expression.evaluate(ctx)); assertEquals( - "any(com.datadog.debugger.el.expressions.HasAnyExpressionTest, true)", print(expression)); + "any(com.datadog.debugger.el.expressions.HasAnyExpressionTest, {true})", print(expression)); expression = any(targetExpression, FALSE); assertFalse(expression.evaluate(ctx)); assertEquals( - "any(com.datadog.debugger.el.expressions.HasAnyExpressionTest, false)", print(expression)); + "any(com.datadog.debugger.el.expressions.HasAnyExpressionTest, {false})", + print(expression)); expression = any( @@ -109,7 +110,7 @@ void testSingleElementHasAny() { eq(getMember(ref(ValueReferences.ITERATOR_REF), "testField"), value(10))); assertTrue(expression.evaluate(ctx)); assertEquals( - "any(com.datadog.debugger.el.expressions.HasAnyExpressionTest, @it.testField == 10)", + "any(com.datadog.debugger.el.expressions.HasAnyExpressionTest, {@it.testField == 10})", print(expression)); } @@ -120,22 +121,22 @@ void testArrayHasAny() { HasAnyExpression expression = any(targetExpression, TRUE); assertTrue(expression.evaluate(ctx)); - assertEquals("any(java.lang.Object[], true)", print(expression)); + assertEquals("any(java.lang.Object[], {true})", print(expression)); expression = any(targetExpression, FALSE); assertFalse(expression.evaluate(ctx)); - assertEquals("any(java.lang.Object[], false)", print(expression)); + assertEquals("any(java.lang.Object[], {false})", print(expression)); expression = any( targetExpression, eq(getMember(ref(ValueReferences.ITERATOR_REF), "testField"), value(10))); assertTrue(expression.evaluate(ctx)); - assertEquals("any(java.lang.Object[], @it.testField == 10)", print(expression)); + assertEquals("any(java.lang.Object[], {@it.testField == 10})", print(expression)); expression = any(targetExpression, eq(ref(ValueReferences.ITERATOR_REF), value("hello"))); assertTrue(expression.evaluate(ctx)); - assertEquals("any(java.lang.Object[], @it == \"hello\")", print(expression)); + assertEquals("any(java.lang.Object[], {@it == \"hello\"})", print(expression)); } @Test @@ -145,22 +146,22 @@ void testListHasAny() { HasAnyExpression expression = any(targetExpression, TRUE); assertTrue(expression.evaluate(ctx)); - assertEquals("any(List, true)", print(expression)); + assertEquals("any(List, {true})", print(expression)); expression = any(targetExpression, FALSE); assertFalse(expression.evaluate(ctx)); - assertEquals("any(List, false)", print(expression)); + assertEquals("any(List, {false})", print(expression)); expression = any( targetExpression, eq(getMember(ref(ValueReferences.ITERATOR_REF), "testField"), value(10))); assertTrue(expression.evaluate(ctx)); - assertEquals("any(List, @it.testField == 10)", print(expression)); + assertEquals("any(List, {@it.testField == 10})", print(expression)); expression = any(targetExpression, eq(ref(ValueReferences.ITERATOR_REF), value("hello"))); assertTrue(expression.evaluate(ctx)); - assertEquals("any(List, @it == \"hello\")", print(expression)); + assertEquals("any(List, {@it == \"hello\"})", print(expression)); } @Test @@ -174,35 +175,35 @@ void testMapHasAny() { HasAnyExpression expression = any(targetExpression, TRUE); assertTrue(expression.evaluate(ctx)); - assertEquals("any(Map, true)", print(expression)); + assertEquals("any(Map, {true})", print(expression)); expression = any(targetExpression, FALSE); assertFalse(expression.evaluate(ctx)); - assertEquals("any(Map, false)", print(expression)); + assertEquals("any(Map, {false})", print(expression)); expression = any(targetExpression, eq(getMember(ref(ValueReferences.ITERATOR_REF), "key"), value("b"))); assertTrue(expression.evaluate(ctx)); - assertEquals("any(Map, @it.key == \"b\")", print(expression)); + assertEquals("any(Map, {@it.key == \"b\"})", print(expression)); expression = any( targetExpression, eq(getMember(ref(ValueReferences.ITERATOR_REF), "value"), value("a"))); assertTrue(expression.evaluate(ctx)); - assertEquals("any(Map, @it.value == \"a\")", print(expression)); + assertEquals("any(Map, {@it.value == \"a\"})", print(expression)); expression = any(targetExpression, eq(getMember(ref(ValueReferences.ITERATOR_REF), "key"), value("c"))); assertFalse(expression.evaluate(ctx)); - assertEquals("any(Map, @it.key == \"c\")", print(expression)); + assertEquals("any(Map, {@it.key == \"c\"})", print(expression)); expression = any( targetExpression, eq(getMember(ref(ValueReferences.ITERATOR_REF), "value"), value("c"))); assertFalse(expression.evaluate(ctx)); - assertEquals("any(Map, @it.value == \"c\")", print(expression)); + assertEquals("any(Map, {@it.value == \"c\"})", print(expression)); } @Test @@ -215,20 +216,20 @@ void testSetHasAny() { ValueExpression targetExpression = DSL.value(valueSet); HasAnyExpression expression = any(targetExpression, TRUE); assertTrue(expression.evaluate(ctx)); - assertEquals("any(Set, true)", print(expression)); + assertEquals("any(Set, {true})", print(expression)); targetExpression = DSL.value(valueSet); expression = any(targetExpression, FALSE); assertFalse(expression.evaluate(ctx)); - assertEquals("any(Set, false)", print(expression)); + assertEquals("any(Set, {false})", print(expression)); expression = any(targetExpression, eq(ref(ValueReferences.ITERATOR_REF), value("foo"))); assertTrue(expression.evaluate(ctx)); - assertEquals("any(Set, @it == \"foo\")", print(expression)); + assertEquals("any(Set, {@it == \"foo\"})", print(expression)); expression = any(targetExpression, eq(ref(ValueReferences.ITERATOR_REF), value("key"))); assertFalse(expression.evaluate(ctx)); - assertEquals("any(Set, @it == \"key\")", print(expression)); + assertEquals("any(Set, {@it == \"key\"})", print(expression)); } @Test @@ -236,14 +237,32 @@ void emptiness() { ValueReferenceResolver ctx = RefResolverHelper.createResolver(null, null); HasAnyExpression expression = any(value(Collections.emptyList()), TRUE); assertFalse(expression.evaluate(ctx)); - assertEquals("any(List, true)", print(expression)); + assertEquals("any(List, {true})", print(expression)); expression = any(value(Collections.emptyMap()), TRUE); assertFalse(expression.evaluate(ctx)); - assertEquals("any(Map, true)", print(expression)); + assertEquals("any(Map, {true})", print(expression)); expression = any(value(Collections.emptySet()), TRUE); assertFalse(expression.evaluate(ctx)); - assertEquals("any(Set, true)", print(expression)); + assertEquals("any(Set, {true})", print(expression)); + } + + @Test + void keyValueMap() { + ValueReferenceResolver ctx = RefResolverHelper.createResolver(null, null); + Map valueMap = new HashMap<>(); + valueMap.put("a", "a"); + valueMap.put("b", null); + + ValueExpression targetExpression = DSL.value(valueMap); + HasAnyExpression expression = + any(targetExpression, eq(ref(ValueReferences.KEY_REF), value("b"))); + assertTrue(expression.evaluate(ctx)); + assertEquals("any(Map, {@key == \"b\"})", print(expression)); + + expression = any(targetExpression, eq(ref(ValueReferences.VALUE_REF), value("a"))); + assertTrue(expression.evaluate(ctx)); + assertEquals("any(Map, {@value == \"a\"})", print(expression)); } }