diff --git a/dd-java-agent/agent-debugger/debugger-bootstrap/build.gradle b/dd-java-agent/agent-debugger/debugger-bootstrap/build.gradle
index 3968a161e35..272c7b26f6f 100644
--- a/dd-java-agent/agent-debugger/debugger-bootstrap/build.gradle
+++ b/dd-java-agent/agent-debugger/debugger-bootstrap/build.gradle
@@ -14,4 +14,5 @@ dependencies {
implementation libs.slf4j
implementation libs.instrument.java
implementation project(':internal-api')
+ testImplementation libs.bundles.mockito
}
diff --git a/dd-java-agent/agent-debugger/debugger-bootstrap/src/main/java/datadog/trace/bootstrap/debugger/DebuggerContext.java b/dd-java-agent/agent-debugger/debugger-bootstrap/src/main/java/datadog/trace/bootstrap/debugger/DebuggerContext.java
index 70f1f8c0347..77ad82b864a 100644
--- a/dd-java-agent/agent-debugger/debugger-bootstrap/src/main/java/datadog/trace/bootstrap/debugger/DebuggerContext.java
+++ b/dd-java-agent/agent-debugger/debugger-bootstrap/src/main/java/datadog/trace/bootstrap/debugger/DebuggerContext.java
@@ -6,7 +6,6 @@
import datadog.trace.bootstrap.instrumentation.api.AgentSpan;
import java.lang.reflect.Method;
import java.time.Duration;
-import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -324,8 +323,8 @@ public static void evalContext(
// snapshot
if (needFreeze) {
Duration timeout =
- Duration.of(Config.get().getDynamicInstrumentationCaptureTimeout(), ChronoUnit.MILLIS);
- context.freeze(new TimeoutChecker(timeout));
+ Duration.ofMillis(Config.get().getDynamicInstrumentationCaptureTimeout());
+ context.freeze(TimeoutChecker.create(Config.get(), timeout));
}
} catch (Exception ex) {
LOGGER.debug("Error in evalContext: ", ex);
@@ -359,8 +358,8 @@ public static void evalContext(
// snapshot
if (needFreeze) {
Duration timeout =
- Duration.of(Config.get().getDynamicInstrumentationCaptureTimeout(), ChronoUnit.MILLIS);
- context.freeze(new TimeoutChecker(timeout));
+ Duration.ofMillis(Config.get().getDynamicInstrumentationCaptureTimeout());
+ context.freeze(TimeoutChecker.create(Config.get(), timeout));
}
} catch (Exception ex) {
LOGGER.debug("Error in evalContext: ", ex);
diff --git a/dd-java-agent/agent-debugger/debugger-bootstrap/src/main/java/datadog/trace/bootstrap/debugger/el/DebuggerScript.java b/dd-java-agent/agent-debugger/debugger-bootstrap/src/main/java/datadog/trace/bootstrap/debugger/el/DebuggerScript.java
index c4949ef0cb6..b248b440ba4 100644
--- a/dd-java-agent/agent-debugger/debugger-bootstrap/src/main/java/datadog/trace/bootstrap/debugger/el/DebuggerScript.java
+++ b/dd-java-agent/agent-debugger/debugger-bootstrap/src/main/java/datadog/trace/bootstrap/debugger/el/DebuggerScript.java
@@ -1,10 +1,12 @@
package datadog.trace.bootstrap.debugger.el;
+import datadog.trace.bootstrap.debugger.util.TimeoutChecker;
+
/**
* A debugger EL script interface used for communication between the instrumented code and the
* debugger EL.
* Because it must be reachable from the instrumented code it must be placed in bootstrap.
*/
public interface DebuggerScript {
- R execute(ValueReferenceResolver valueRefResolver);
+ R execute(ValueReferenceResolver valueRefResolver, TimeoutChecker timeoutChecker);
}
diff --git a/dd-java-agent/agent-debugger/debugger-bootstrap/src/main/java/datadog/trace/bootstrap/debugger/util/CpuTimeoutChecker.java b/dd-java-agent/agent-debugger/debugger-bootstrap/src/main/java/datadog/trace/bootstrap/debugger/util/CpuTimeoutChecker.java
new file mode 100644
index 00000000000..42d082ee675
--- /dev/null
+++ b/dd-java-agent/agent-debugger/debugger-bootstrap/src/main/java/datadog/trace/bootstrap/debugger/util/CpuTimeoutChecker.java
@@ -0,0 +1,26 @@
+package datadog.trace.bootstrap.debugger.util;
+
+import java.lang.management.ManagementFactory;
+import java.lang.management.ThreadMXBean;
+import java.time.Duration;
+
+public class CpuTimeoutChecker implements TimeoutChecker {
+ private final Duration timeOut;
+ private final ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
+ private final long startCpuTime;
+
+ public CpuTimeoutChecker(Duration timeout) {
+ this.timeOut = timeout;
+ startCpuTime = threadMXBean.getCurrentThreadCpuTime();
+ }
+
+ @Override
+ public boolean isTimedOut() {
+ return threadMXBean.getCurrentThreadCpuTime() - startCpuTime >= timeOut.toNanos();
+ }
+
+ @Override
+ public Duration getTimeOut() {
+ return timeOut;
+ }
+}
diff --git a/dd-java-agent/agent-debugger/debugger-bootstrap/src/main/java/datadog/trace/bootstrap/debugger/util/TimeoutChecker.java b/dd-java-agent/agent-debugger/debugger-bootstrap/src/main/java/datadog/trace/bootstrap/debugger/util/TimeoutChecker.java
index f6451afe8c0..a49bb9d3208 100644
--- a/dd-java-agent/agent-debugger/debugger-bootstrap/src/main/java/datadog/trace/bootstrap/debugger/util/TimeoutChecker.java
+++ b/dd-java-agent/agent-debugger/debugger-bootstrap/src/main/java/datadog/trace/bootstrap/debugger/util/TimeoutChecker.java
@@ -1,33 +1,21 @@
package datadog.trace.bootstrap.debugger.util;
+import datadog.trace.api.Config;
import java.time.Duration;
-import java.time.temporal.ChronoUnit;
-public class TimeoutChecker {
- public static final Duration DEFAULT_TIME_OUT = Duration.of(100, ChronoUnit.MILLIS);
+public interface TimeoutChecker {
- private final long start;
- private final Duration timeOut;
+ String CPU = "CPU";
+ String WALL = "WALL";
- public TimeoutChecker(Duration timeOut) {
- this.start = System.currentTimeMillis();
- this.timeOut = timeOut;
- }
-
- public TimeoutChecker(long start, Duration timeOut) {
- this.start = start;
- this.timeOut = timeOut;
- }
+ boolean isTimedOut();
- public boolean isTimedOut(long currentTimeMillis) {
- return (currentTimeMillis - start) > timeOut.toMillis();
- }
-
- public long getStart() {
- return start;
- }
+ Duration getTimeOut();
- public Duration getTimeOut() {
- return timeOut;
+ static TimeoutChecker create(Config config, Duration timeout) {
+ if (config.getDynamicInstrumentationTimeoutCheckerMode().equals(CPU)) {
+ return new CpuTimeoutChecker(timeout);
+ }
+ return new WallTimeoutChecker(timeout);
}
}
diff --git a/dd-java-agent/agent-debugger/debugger-bootstrap/src/main/java/datadog/trace/bootstrap/debugger/util/WallTimeoutChecker.java b/dd-java-agent/agent-debugger/debugger-bootstrap/src/main/java/datadog/trace/bootstrap/debugger/util/WallTimeoutChecker.java
new file mode 100644
index 00000000000..1bc72b69c45
--- /dev/null
+++ b/dd-java-agent/agent-debugger/debugger-bootstrap/src/main/java/datadog/trace/bootstrap/debugger/util/WallTimeoutChecker.java
@@ -0,0 +1,37 @@
+package datadog.trace.bootstrap.debugger.util;
+
+import java.time.Duration;
+
+public class WallTimeoutChecker implements TimeoutChecker {
+
+ private final long start;
+ private final Duration timeOut;
+
+ public WallTimeoutChecker(Duration timeOut) {
+ this.start = System.currentTimeMillis();
+ this.timeOut = timeOut;
+ }
+
+ public WallTimeoutChecker(long start, Duration timeOut) {
+ this.start = start;
+ this.timeOut = timeOut;
+ }
+
+ public boolean isTimedOut(long currentTimeMillis) {
+ return (currentTimeMillis - start) > timeOut.toMillis();
+ }
+
+ @Override
+ public boolean isTimedOut() {
+ return isTimedOut(System.currentTimeMillis());
+ }
+
+ public long getStart() {
+ return start;
+ }
+
+ @Override
+ public Duration getTimeOut() {
+ return timeOut;
+ }
+}
diff --git a/dd-java-agent/agent-debugger/debugger-bootstrap/src/test/java/datadog/trace/bootstrap/debugger/util/TimeoutCheckerTest.java b/dd-java-agent/agent-debugger/debugger-bootstrap/src/test/java/datadog/trace/bootstrap/debugger/util/TimeoutCheckerTest.java
index 10cd94f9042..c3d23678da6 100644
--- a/dd-java-agent/agent-debugger/debugger-bootstrap/src/test/java/datadog/trace/bootstrap/debugger/util/TimeoutCheckerTest.java
+++ b/dd-java-agent/agent-debugger/debugger-bootstrap/src/test/java/datadog/trace/bootstrap/debugger/util/TimeoutCheckerTest.java
@@ -1,20 +1,55 @@
package datadog.trace.bootstrap.debugger.util;
-import static datadog.trace.bootstrap.debugger.util.TimeoutChecker.DEFAULT_TIME_OUT;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertInstanceOf;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
-import org.junit.jupiter.api.Assertions;
+import datadog.trace.api.Config;
+import java.time.Duration;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.LockSupport;
import org.junit.jupiter.api.Test;
public class TimeoutCheckerTest {
@Test
- public void timedOut() {
+ public void wallTimedOut() {
long start = System.currentTimeMillis();
+ Duration timeout = Duration.ofMillis(100);
// assume that start & timestamp captured in instance below are very close
- TimeoutChecker timeoutChecker = new TimeoutChecker(DEFAULT_TIME_OUT);
- Assertions.assertFalse(timeoutChecker.isTimedOut(start + 1));
- Assertions.assertTrue(timeoutChecker.isTimedOut(start + DEFAULT_TIME_OUT.toMillis() * 2));
- timeoutChecker = new TimeoutChecker(start, DEFAULT_TIME_OUT);
- Assertions.assertFalse(timeoutChecker.isTimedOut(start + 1));
- Assertions.assertTrue(timeoutChecker.isTimedOut(start + DEFAULT_TIME_OUT.toMillis() * 2));
+ WallTimeoutChecker timeoutChecker = new WallTimeoutChecker(timeout);
+ assertFalse(timeoutChecker.isTimedOut(start + 1));
+ assertTrue(timeoutChecker.isTimedOut(start + timeout.toMillis() * 2));
+ timeoutChecker = new WallTimeoutChecker(start, timeout);
+ assertFalse(timeoutChecker.isTimedOut(start + 1));
+ assertTrue(timeoutChecker.isTimedOut(start + timeout.toMillis() * 2));
+ }
+
+ @Test
+ public void cpuTimedOut() {
+ CpuTimeoutChecker cpuTimeoutChecker = new CpuTimeoutChecker(Duration.ofMillis(1));
+ LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(10)); // not consume cpu
+ assertFalse(cpuTimeoutChecker.isTimedOut());
+ burnCpu(5_000_000);
+ assertTrue(cpuTimeoutChecker.isTimedOut());
+ }
+
+ static volatile int counter;
+
+ private static void burnCpu(int iterations) {
+ for (int i = 0; i < iterations; i++) {
+ counter++;
+ }
+ }
+
+ @Test
+ public void configTimeout() {
+ Config config = mock(Config.class);
+ when(config.getDynamicInstrumentationTimeoutCheckerMode()).thenReturn(TimeoutChecker.CPU);
+ assertInstanceOf(CpuTimeoutChecker.class, TimeoutChecker.create(config, Duration.ofMillis(50)));
+ when(config.getDynamicInstrumentationTimeoutCheckerMode()).thenReturn(TimeoutChecker.WALL);
+ assertInstanceOf(
+ WallTimeoutChecker.class, TimeoutChecker.create(config, Duration.ofMillis(50)));
}
}
diff --git a/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/BooleanValueExpressionAdapter.java b/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/BooleanValueExpressionAdapter.java
index c71c1b9b8de..e7986715e24 100644
--- a/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/BooleanValueExpressionAdapter.java
+++ b/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/BooleanValueExpressionAdapter.java
@@ -3,7 +3,6 @@
import com.datadog.debugger.el.expressions.BooleanExpression;
import com.datadog.debugger.el.expressions.ValueExpression;
import com.datadog.debugger.el.values.BooleanValue;
-import datadog.trace.bootstrap.debugger.el.ValueReferenceResolver;
public class BooleanValueExpressionAdapter implements ValueExpression {
@@ -14,8 +13,8 @@ public BooleanValueExpressionAdapter(BooleanExpression booleanExpression) {
}
@Override
- public BooleanValue evaluate(ValueReferenceResolver valueRefResolver) {
- Boolean result = booleanExpression.evaluate(valueRefResolver);
+ public BooleanValue evaluate(EvalContext evalContext) {
+ Boolean result = booleanExpression.evaluate(evalContext);
if (result == null) {
throw new EvaluationException(
"Boolean expression returning null", PrettyPrintVisitor.print(this));
diff --git a/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/EvalContext.java b/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/EvalContext.java
new file mode 100644
index 00000000000..bd0ece583f2
--- /dev/null
+++ b/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/EvalContext.java
@@ -0,0 +1,23 @@
+package com.datadog.debugger.el;
+
+import datadog.trace.bootstrap.debugger.el.ValueReferenceResolver;
+import datadog.trace.bootstrap.debugger.util.TimeoutChecker;
+
+public class EvalContext {
+ private final ValueReferenceResolver valueRefResolver;
+ private final TimeoutChecker timeoutChecker;
+
+ public EvalContext(
+ final ValueReferenceResolver valueRefResolver, final TimeoutChecker timeoutChecker) {
+ this.valueRefResolver = valueRefResolver;
+ this.timeoutChecker = timeoutChecker;
+ }
+
+ public ValueReferenceResolver getValueRefResolver() {
+ return valueRefResolver;
+ }
+
+ public TimeoutChecker getTimeoutChecker() {
+ return timeoutChecker;
+ }
+}
diff --git a/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/Expression.java b/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/Expression.java
index f9d29f0687a..d9b7b2e766f 100644
--- a/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/Expression.java
+++ b/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/Expression.java
@@ -1,11 +1,9 @@
package com.datadog.debugger.el;
-import datadog.trace.bootstrap.debugger.el.ValueReferenceResolver;
-
/** Represents any evaluable expression */
@FunctionalInterface
public interface Expression {
- ReturnType evaluate(ValueReferenceResolver valueRefResolver);
+ ReturnType evaluate(EvalContext evalContext);
default R accept(Visitor visitor) {
return null;
diff --git a/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/Literal.java b/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/Literal.java
index 6d5c8d2fca1..cfc3b9971d9 100644
--- a/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/Literal.java
+++ b/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/Literal.java
@@ -1,7 +1,6 @@
package com.datadog.debugger.el;
import com.datadog.debugger.el.expressions.ValueExpression;
-import datadog.trace.bootstrap.debugger.el.ValueReferenceResolver;
import datadog.trace.bootstrap.debugger.el.Values;
import java.util.Objects;
@@ -27,7 +26,7 @@ public boolean isUndefined() {
}
@Override
- public Value evaluate(ValueReferenceResolver valueRefResolver) {
+ public Value evaluate(EvalContext evalContext) {
return this;
}
diff --git a/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/ProbeCondition.java b/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/ProbeCondition.java
index f81c92a8b19..7ca052c2cab 100644
--- a/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/ProbeCondition.java
+++ b/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/ProbeCondition.java
@@ -9,6 +9,7 @@
import com.squareup.moshi.JsonWriter;
import datadog.trace.bootstrap.debugger.el.DebuggerScript;
import datadog.trace.bootstrap.debugger.el.ValueReferenceResolver;
+import datadog.trace.bootstrap.debugger.util.TimeoutChecker;
import java.io.IOException;
import javax.annotation.Nonnull;
@@ -99,12 +100,12 @@ public static ProbeCondition load(JsonReader reader) throws IOException {
}
@Override
- public Boolean execute(ValueReferenceResolver valueRefResolver) {
+ public Boolean execute(ValueReferenceResolver valueRefResolver, TimeoutChecker timeoutChecker) {
if (when == null) {
return true;
}
- if (when.evaluate(valueRefResolver)) {
- then.evaluate(valueRefResolver);
+ if (when.evaluate(new EvalContext(valueRefResolver, timeoutChecker))) {
+ then.evaluate(new EvalContext(valueRefResolver, timeoutChecker));
return true;
}
return false;
diff --git a/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/ValueScript.java b/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/ValueScript.java
index bcc940e1d5d..c446e0b12e5 100644
--- a/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/ValueScript.java
+++ b/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/ValueScript.java
@@ -1,16 +1,43 @@
package com.datadog.debugger.el;
+import com.datadog.debugger.el.expressions.BinaryExpression;
+import com.datadog.debugger.el.expressions.BinaryOperator;
+import com.datadog.debugger.el.expressions.BooleanExpression;
+import com.datadog.debugger.el.expressions.ComparisonExpression;
+import com.datadog.debugger.el.expressions.ComparisonOperator;
+import com.datadog.debugger.el.expressions.ContainsExpression;
+import com.datadog.debugger.el.expressions.EndsWithExpression;
+import com.datadog.debugger.el.expressions.FilterCollectionExpression;
import com.datadog.debugger.el.expressions.GetMemberExpression;
+import com.datadog.debugger.el.expressions.HasAllExpression;
+import com.datadog.debugger.el.expressions.HasAnyExpression;
+import com.datadog.debugger.el.expressions.IfElseExpression;
+import com.datadog.debugger.el.expressions.IfExpression;
import com.datadog.debugger.el.expressions.IndexExpression;
+import com.datadog.debugger.el.expressions.IsDefinedExpression;
+import com.datadog.debugger.el.expressions.IsEmptyExpression;
import com.datadog.debugger.el.expressions.LenExpression;
+import com.datadog.debugger.el.expressions.MatchesExpression;
+import com.datadog.debugger.el.expressions.NotExpression;
+import com.datadog.debugger.el.expressions.StartsWithExpression;
+import com.datadog.debugger.el.expressions.SubStringExpression;
import com.datadog.debugger.el.expressions.ValueExpression;
import com.datadog.debugger.el.expressions.ValueRefExpression;
+import com.datadog.debugger.el.expressions.WhenExpression;
+import com.datadog.debugger.el.values.BooleanValue;
+import com.datadog.debugger.el.values.ListValue;
+import com.datadog.debugger.el.values.MapValue;
+import com.datadog.debugger.el.values.NullValue;
+import com.datadog.debugger.el.values.NumericValue;
+import com.datadog.debugger.el.values.ObjectValue;
+import com.datadog.debugger.el.values.SetValue;
import com.datadog.debugger.el.values.StringValue;
import com.squareup.moshi.JsonAdapter;
import com.squareup.moshi.JsonReader;
import com.squareup.moshi.JsonWriter;
import datadog.trace.bootstrap.debugger.el.DebuggerScript;
import datadog.trace.bootstrap.debugger.el.ValueReferenceResolver;
+import datadog.trace.bootstrap.debugger.util.TimeoutChecker;
import java.io.IOException;
import java.util.Objects;
import java.util.regex.Matcher;
@@ -37,8 +64,8 @@ public ValueExpression> getExpr() {
}
@Override
- public Value> execute(ValueReferenceResolver valueRefResolver) {
- return expr.evaluate(valueRefResolver);
+ public Value> execute(ValueReferenceResolver valueRefResolver, TimeoutChecker timeoutChecker) {
+ return expr.evaluate(new EvalContext(valueRefResolver, timeoutChecker));
}
@Override
@@ -127,46 +154,248 @@ public void toJson(JsonWriter jsonWriter, ValueScript value) throws IOException
jsonWriter.name("dsl");
jsonWriter.value(value.dsl);
jsonWriter.name("json");
- writeValueExpression(jsonWriter, value.expr);
+ ToJsonVisitor toJsonVisitor = new ToJsonVisitor(jsonWriter);
+ value.expr.accept(toJsonVisitor);
jsonWriter.endObject();
}
- private void writeValueExpression(JsonWriter jsonWriter, ValueExpression> expr)
- throws IOException {
- if (expr instanceof Value) {
- if (expr instanceof StringValue) {
- jsonWriter.value(((StringValue) expr).getValue());
- } else {
- throw new IOException("Unsupported operation: " + expr.getClass().getTypeName());
+ private static class ToJsonVisitor implements Visitor {
+ private final JsonWriter jsonWriter;
+
+ public ToJsonVisitor(JsonWriter jsonWriter) {
+ this.jsonWriter = jsonWriter;
+ }
+
+ @Override
+ public Void visit(BinaryExpression binaryExpression) {
+ throw new UnsupportedOperationException("BinaryExpression is not supported");
+ }
+
+ @Override
+ public Void visit(BinaryOperator operator) {
+ throw new UnsupportedOperationException("BinaryOperator is not supported");
+ }
+
+ @Override
+ public Void visit(ComparisonExpression comparisonExpression) {
+ try {
+ jsonWriter.beginObject();
+ comparisonExpression.getOperator().accept(this);
+ jsonWriter.beginArray();
+ comparisonExpression.getLeft().accept(this);
+ comparisonExpression.getRight().accept(this);
+ jsonWriter.endArray();
+ jsonWriter.endObject();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
}
- return;
+ return null;
}
- jsonWriter.beginObject();
- if (expr instanceof ValueRefExpression) {
- ValueRefExpression valueRefExpr = (ValueRefExpression) expr;
- jsonWriter.name("ref");
- jsonWriter.value(valueRefExpr.getSymbolName());
- } else if (expr instanceof GetMemberExpression) {
- GetMemberExpression getMemberExpr = (GetMemberExpression) expr;
- jsonWriter.name("getmember");
- jsonWriter.beginArray();
- writeValueExpression(jsonWriter, getMemberExpr.getTarget());
- jsonWriter.value(getMemberExpr.getMemberName());
- jsonWriter.endArray();
- } else if (expr instanceof LenExpression) {
- jsonWriter.name("count");
- writeValueExpression(jsonWriter, ((LenExpression) expr).getSource());
- } else if (expr instanceof IndexExpression) {
- IndexExpression idxExpr = (IndexExpression) expr;
- jsonWriter.name("index");
- jsonWriter.beginArray();
- writeValueExpression(jsonWriter, idxExpr.getTarget());
- writeValueExpression(jsonWriter, idxExpr.getKey());
- jsonWriter.endArray();
- } else {
- throw new IOException("Unsupported operation: " + expr.getClass().getTypeName());
+
+ @Override
+ public Void visit(ComparisonOperator operator) {
+ try {
+ jsonWriter.name(operator.name().toLowerCase());
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ return null;
+ }
+
+ @Override
+ public Void visit(ContainsExpression containsExpression) {
+ throw new UnsupportedOperationException("ContainsExpression is not supported");
+ }
+
+ @Override
+ public Void visit(EndsWithExpression endsWithExpression) {
+ throw new UnsupportedOperationException("EndsWithExpression is not supported");
+ }
+
+ @Override
+ public Void visit(FilterCollectionExpression filterCollectionExpression) {
+ try {
+ jsonWriter.beginObject();
+ jsonWriter.name("filter");
+ jsonWriter.beginArray();
+ filterCollectionExpression.getSource().accept(this);
+ filterCollectionExpression.getFilterExpression().accept(this);
+ jsonWriter.endArray();
+ jsonWriter.endObject();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ return null;
+ }
+
+ @Override
+ public Void visit(HasAllExpression hasAllExpression) {
+ throw new UnsupportedOperationException("HasAllExpression is not supported");
+ }
+
+ @Override
+ public Void visit(HasAnyExpression hasAnyExpression) {
+ throw new UnsupportedOperationException("HasAnyExpression is not supported");
+ }
+
+ @Override
+ public Void visit(IfElseExpression ifElseExpression) {
+ throw new UnsupportedOperationException("IfElseExpression is not supported");
+ }
+
+ @Override
+ public Void visit(IfExpression ifExpression) {
+ throw new UnsupportedOperationException("IfExpression is not supported");
+ }
+
+ @Override
+ public Void visit(IsEmptyExpression isEmptyExpression) {
+ throw new UnsupportedOperationException("IsEmptyExpression is not supported");
+ }
+
+ @Override
+ public Void visit(IsDefinedExpression isDefinedExpression) {
+ throw new UnsupportedOperationException("IsDefinedExpression is not supported");
+ }
+
+ @Override
+ public Void visit(LenExpression lenExpression) {
+ try {
+ jsonWriter.beginObject();
+ jsonWriter.name("count");
+ lenExpression.getSource().accept(this);
+ jsonWriter.endObject();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ return null;
+ }
+
+ @Override
+ public Void visit(MatchesExpression matchesExpression) {
+ throw new UnsupportedOperationException("MatchesExpression is not supported");
+ }
+
+ @Override
+ public Void visit(NotExpression notExpression) {
+ throw new UnsupportedOperationException("NotExpression is not supported");
+ }
+
+ @Override
+ public Void visit(StartsWithExpression startsWithExpression) {
+ throw new UnsupportedOperationException("StartsWithExpression is not supported");
+ }
+
+ @Override
+ public Void visit(SubStringExpression subStringExpression) {
+ throw new UnsupportedOperationException("SubStringExpression is not supported");
+ }
+
+ @Override
+ public Void visit(ValueRefExpression valueRefExpression) {
+ try {
+ jsonWriter.beginObject();
+ jsonWriter.name("ref");
+ jsonWriter.value(valueRefExpression.getSymbolName());
+ jsonWriter.endObject();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ return null;
+ }
+
+ @Override
+ public Void visit(GetMemberExpression getMemberExpression) {
+ try {
+ jsonWriter.beginObject();
+ jsonWriter.name("getmember");
+ jsonWriter.beginArray();
+ getMemberExpression.getTarget().accept(this);
+ jsonWriter.value(getMemberExpression.getMemberName());
+ jsonWriter.endArray();
+ jsonWriter.endObject();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ return null;
+ }
+
+ @Override
+ public Void visit(IndexExpression indexExpression) {
+ try {
+ jsonWriter.beginObject();
+ jsonWriter.name("index");
+ jsonWriter.beginArray();
+ indexExpression.getTarget().accept(this);
+ indexExpression.getKey().accept(this);
+ jsonWriter.endArray();
+ jsonWriter.endObject();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ return null;
+ }
+
+ @Override
+ public Void visit(WhenExpression whenExpression) {
+ throw new UnsupportedOperationException("WhenExpression is not supported");
+ }
+
+ @Override
+ public Void visit(BooleanExpression booleanExpression) {
+ throw new UnsupportedOperationException("BooleanExpression is not supported");
+ }
+
+ @Override
+ public Void visit(ObjectValue objectValue) {
+ throw new UnsupportedOperationException("ObjectValue is not supported");
+ }
+
+ @Override
+ public Void visit(StringValue stringValue) {
+ try {
+ jsonWriter.value(stringValue.getValue());
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ return null;
+ }
+
+ @Override
+ public Void visit(NumericValue numericValue) {
+ try {
+ // TODO handle double
+ jsonWriter.value(numericValue.getValue().longValue());
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ return null;
+ }
+
+ @Override
+ public Void visit(BooleanValue booleanValue) {
+ throw new UnsupportedOperationException("BooleanValue is not supported");
+ }
+
+ @Override
+ public Void visit(NullValue nullValue) {
+ throw new UnsupportedOperationException("NullValue is not supported");
+ }
+
+ @Override
+ public Void visit(ListValue listValue) {
+ throw new UnsupportedOperationException("ListValue is not supported");
+ }
+
+ @Override
+ public Void visit(MapValue mapValue) {
+ throw new UnsupportedOperationException("MapValue is not supported");
+ }
+
+ @Override
+ public Void visit(SetValue setValue) {
+ throw new UnsupportedOperationException("SetValue is not supported");
}
- jsonWriter.endObject();
}
}
}
diff --git a/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/BinaryExpression.java b/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/BinaryExpression.java
index d4063ec5cd2..3c955d21b74 100644
--- a/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/BinaryExpression.java
+++ b/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/BinaryExpression.java
@@ -1,7 +1,7 @@
package com.datadog.debugger.el.expressions;
+import com.datadog.debugger.el.EvalContext;
import com.datadog.debugger.el.Visitor;
-import datadog.trace.bootstrap.debugger.el.ValueReferenceResolver;
/**
* Takes two {@linkplain BooleanExpression} instances and combines them with the given {@link
@@ -20,8 +20,8 @@ public BinaryExpression(
}
@Override
- public Boolean evaluate(ValueReferenceResolver valueRefResolver) {
- return operator.apply(left, right, valueRefResolver);
+ public Boolean evaluate(EvalContext evalContext) {
+ return operator.apply(left, right, evalContext);
}
@Override
diff --git a/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/BinaryOperator.java b/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/BinaryOperator.java
index ce5784b918b..3a1a7391d17 100644
--- a/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/BinaryOperator.java
+++ b/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/BinaryOperator.java
@@ -1,21 +1,19 @@
package com.datadog.debugger.el.expressions;
+import com.datadog.debugger.el.EvalContext;
import com.datadog.debugger.el.Visitor;
-import datadog.trace.bootstrap.debugger.el.ValueReferenceResolver;
public enum BinaryOperator {
AND("&&") {
@Override
- public Boolean apply(
- BooleanExpression left, BooleanExpression right, ValueReferenceResolver resolver) {
- return left.evaluate(resolver) && right.evaluate(resolver);
+ public Boolean apply(BooleanExpression left, BooleanExpression right, EvalContext evalContext) {
+ return left.evaluate(evalContext) && right.evaluate(evalContext);
}
},
OR("||") {
@Override
- public Boolean apply(
- BooleanExpression left, BooleanExpression right, ValueReferenceResolver resolver) {
- return left.evaluate(resolver) || right.evaluate(resolver);
+ public Boolean apply(BooleanExpression left, BooleanExpression right, EvalContext evalContext) {
+ return left.evaluate(evalContext) || right.evaluate(evalContext);
}
};
@@ -26,7 +24,7 @@ public Boolean apply(
}
public abstract Boolean apply(
- BooleanExpression left, BooleanExpression right, ValueReferenceResolver resolver);
+ BooleanExpression left, BooleanExpression right, EvalContext evalContext);
public R accept(Visitor visitor) {
return visitor.visit(this);
diff --git a/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/BooleanExpression.java b/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/BooleanExpression.java
index 3ff97e2d890..2f98571f03b 100644
--- a/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/BooleanExpression.java
+++ b/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/BooleanExpression.java
@@ -1,15 +1,15 @@
package com.datadog.debugger.el.expressions;
+import com.datadog.debugger.el.EvalContext;
import com.datadog.debugger.el.Expression;
import com.datadog.debugger.el.Visitor;
-import datadog.trace.bootstrap.debugger.el.ValueReferenceResolver;
/** A generic interface for expressions resolving to {@linkplain Boolean} */
public interface BooleanExpression extends Expression {
BooleanExpression TRUE =
new BooleanExpression() {
@Override
- public Boolean evaluate(ValueReferenceResolver valueRefResolver) {
+ public Boolean evaluate(EvalContext evalContext) {
return Boolean.TRUE;
}
@@ -26,7 +26,7 @@ public R accept(Visitor visitor) {
BooleanExpression FALSE =
new BooleanExpression() {
@Override
- public Boolean evaluate(ValueReferenceResolver valueRefResolver) {
+ public Boolean evaluate(EvalContext evalContext) {
return Boolean.FALSE;
}
diff --git a/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/CollectionExpressionHelper.java b/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/CollectionExpressionHelper.java
index c811c82fa73..540008c6ea1 100644
--- a/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/CollectionExpressionHelper.java
+++ b/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/CollectionExpressionHelper.java
@@ -2,13 +2,13 @@
import static com.datadog.debugger.el.PrettyPrintVisitor.print;
+import com.datadog.debugger.el.EvalContext;
import com.datadog.debugger.el.EvaluationException;
import com.datadog.debugger.el.Expression;
import com.datadog.debugger.el.Value;
import com.datadog.debugger.el.values.ListValue;
import com.datadog.debugger.el.values.MapValue;
import com.datadog.debugger.el.values.SetValue;
-import datadog.trace.bootstrap.debugger.el.ValueReferenceResolver;
import datadog.trace.bootstrap.debugger.util.WellKnownClasses;
import java.util.List;
import java.util.Map;
@@ -34,14 +34,12 @@ public static void checkSupportedList(ListValue collection, Expression> expres
}
public static Value> evaluateTargetCollection(
- ValueExpression> collectionTarget,
- Expression> expression,
- ValueReferenceResolver valueRefResolver) {
+ ValueExpression> collectionTarget, Expression> expression, EvalContext evalContext) {
if (collectionTarget == null) {
throw new EvaluationException(
"Cannot evaluate the expression for null value", print(expression));
}
- Value> value = collectionTarget.evaluate(valueRefResolver);
+ Value> value = collectionTarget.evaluate(evalContext);
if (value.isUndefined()) {
throw new EvaluationException(
"Cannot evaluate the expression for undefined value", print(expression));
diff --git a/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/ComparisonExpression.java b/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/ComparisonExpression.java
index b595921d928..8a13febaad2 100644
--- a/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/ComparisonExpression.java
+++ b/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/ComparisonExpression.java
@@ -1,10 +1,12 @@
package com.datadog.debugger.el.expressions;
+import static com.datadog.debugger.el.expressions.ExpressionHelper.checkTimeout;
+
+import com.datadog.debugger.el.EvalContext;
import com.datadog.debugger.el.EvaluationException;
import com.datadog.debugger.el.PrettyPrintVisitor;
import com.datadog.debugger.el.Value;
import com.datadog.debugger.el.Visitor;
-import datadog.trace.bootstrap.debugger.el.ValueReferenceResolver;
/**
* Takes two {@linkplain ValueExpression} instances and compares them using the given {@link
@@ -23,17 +25,19 @@ public ComparisonExpression(
}
@Override
- public Boolean evaluate(ValueReferenceResolver valueRefResolver) {
- Value> leftValue = left.evaluate(valueRefResolver);
+ public Boolean evaluate(EvalContext evalContext) {
+ Value> leftValue = left.evaluate(evalContext);
if (leftValue.isUndefined()) {
return Boolean.FALSE;
}
- Value> rightValue = right.evaluate(valueRefResolver);
+ Value> rightValue = right.evaluate(evalContext);
if (rightValue.isUndefined()) {
return Boolean.FALSE;
}
try {
- return operator.apply(leftValue, rightValue);
+ boolean result = operator.apply(leftValue, rightValue);
+ checkTimeout(evalContext.getTimeoutChecker(), this);
+ return result;
} catch (EvaluationException e) {
throw new EvaluationException(e.getMessage(), PrettyPrintVisitor.print(this));
}
diff --git a/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/ContainsExpression.java b/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/ContainsExpression.java
index d2fc6a62bbf..bde8654b551 100644
--- a/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/ContainsExpression.java
+++ b/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/ContainsExpression.java
@@ -1,11 +1,14 @@
package com.datadog.debugger.el.expressions;
+import static com.datadog.debugger.el.expressions.ExpressionHelper.checkStringLength;
+import static com.datadog.debugger.el.expressions.ExpressionHelper.checkTimeout;
+
+import com.datadog.debugger.el.EvalContext;
import com.datadog.debugger.el.EvaluationException;
import com.datadog.debugger.el.PrettyPrintVisitor;
import com.datadog.debugger.el.Value;
import com.datadog.debugger.el.Visitor;
import com.datadog.debugger.el.values.CollectionValue;
-import datadog.trace.bootstrap.debugger.el.ValueReferenceResolver;
public class ContainsExpression implements BooleanExpression {
private final ValueExpression> target;
@@ -17,8 +20,8 @@ public ContainsExpression(ValueExpression> target, ValueExpression> value) {
}
@Override
- public Boolean evaluate(ValueReferenceResolver valueRefResolver) {
- Value> targetValue = target.evaluate(valueRefResolver);
+ public Boolean evaluate(EvalContext evalContext) {
+ Value> targetValue = target.evaluate(evalContext);
if (targetValue.isUndefined()) {
throw new EvaluationException(
"Cannot evaluate the expression for undefined value", PrettyPrintVisitor.print(this));
@@ -27,22 +30,28 @@ public Boolean evaluate(ValueReferenceResolver valueRefResolver) {
throw new EvaluationException(
"Cannot evaluate the expression for null value", PrettyPrintVisitor.print(this));
}
- Value> val = value.evaluate(valueRefResolver);
+ Value> val = value.evaluate(evalContext);
if (val.isUndefined()) {
return false;
}
+ boolean result;
if (targetValue.getValue() instanceof String) {
String targetStr = (String) targetValue.getValue();
if (val.getValue() instanceof String) {
String valStr = (String) val.getValue();
- return targetStr.contains(valStr);
+ checkStringLength(valStr, this);
+ result = targetStr.contains(valStr);
+ checkTimeout(evalContext.getTimeoutChecker(), this);
+ return result;
}
throw new EvaluationException(
"Cannot evaluate the expression for non-string value", PrettyPrintVisitor.print(this));
}
if (targetValue instanceof CollectionValue) {
try {
- return ((CollectionValue>) targetValue).contains(val);
+ result = ((CollectionValue>) targetValue).contains(val);
+ checkTimeout(evalContext.getTimeoutChecker(), this);
+ return result;
} catch (RuntimeException ex) {
throw new EvaluationException(ex.getMessage(), PrettyPrintVisitor.print(this));
}
diff --git a/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/ExpressionHelper.java b/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/ExpressionHelper.java
index 43d5930dcb6..10b7a73911c 100644
--- a/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/ExpressionHelper.java
+++ b/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/ExpressionHelper.java
@@ -1,13 +1,54 @@
package com.datadog.debugger.el.expressions;
+import com.datadog.debugger.el.EvaluationException;
import com.datadog.debugger.el.Expression;
import com.datadog.debugger.el.PrettyPrintVisitor;
import com.datadog.debugger.el.RedactedException;
+import datadog.trace.bootstrap.debugger.util.TimeoutChecker;
+import java.util.Collection;
public class ExpressionHelper {
+ public static final int MAX_COLLECTION_ITEMS = 1_000_000;
+ public static final int MAX_ARRAY_ITEMS = 1_000_000;
+ public static final int MAX_STRING_LENGTH = 100_000_000;
+
public static void throwRedactedException(Expression> expr) {
String strExpr = PrettyPrintVisitor.print(expr);
throw new RedactedException(
"Could not evaluate the expression because '" + strExpr + "' was redacted", strExpr);
}
+
+ public static void checkTimeout(TimeoutChecker checker, Expression> expr) {
+ if (checker.isTimedOut()) {
+ throw new EvaluationException(
+ "timeout (" + checker.getTimeOut().toMillis() + "ms)", PrettyPrintVisitor.print(expr));
+ }
+ }
+
+ public static void checkStringLength(String val, Expression> expr) {
+ if (val == null) {
+ return;
+ }
+ if (val.length() > MAX_STRING_LENGTH) {
+ throw new EvaluationException(
+ "string too large (>" + MAX_STRING_LENGTH + ")", PrettyPrintVisitor.print(expr));
+ }
+ }
+
+ public static void checkCollectionSize(Collection> collection, Expression> expr) {
+ if (collection == null) {
+ return;
+ }
+ if (collection.size() > MAX_COLLECTION_ITEMS) {
+ throw new EvaluationException(
+ "Collection too large (>" + MAX_COLLECTION_ITEMS + ")", PrettyPrintVisitor.print(expr));
+ }
+ }
+
+ public static void checkArrayLength(int arrayLength, Expression> expr) {
+ if (arrayLength > MAX_ARRAY_ITEMS) {
+ throw new EvaluationException(
+ "Array too large (>" + MAX_ARRAY_ITEMS + ")", PrettyPrintVisitor.print(expr));
+ }
+ }
}
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 5c3e27ee173..cd4c8ef1c89 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
@@ -5,7 +5,9 @@
import static com.datadog.debugger.el.expressions.CollectionExpressionHelper.checkSupportedMap;
import static com.datadog.debugger.el.expressions.CollectionExpressionHelper.checkSupportedSet;
import static com.datadog.debugger.el.expressions.CollectionExpressionHelper.evaluateTargetCollection;
+import static com.datadog.debugger.el.expressions.ExpressionHelper.checkTimeout;
+import com.datadog.debugger.el.EvalContext;
import com.datadog.debugger.el.EvaluationException;
import com.datadog.debugger.el.Value;
import com.datadog.debugger.el.Visitor;
@@ -41,8 +43,9 @@ public FilterCollectionExpression(ValueExpression> source, BooleanExpression f
}
@Override
- public CollectionValue> evaluate(ValueReferenceResolver valueRefResolver) {
- Value> collectionValue = evaluateTargetCollection(source, filterExpression, valueRefResolver);
+ public CollectionValue> evaluate(EvalContext evalContext) {
+ Value> collectionValue = evaluateTargetCollection(source, filterExpression, evalContext);
+ ValueReferenceResolver valueRefResolver = evalContext.getValueRefResolver();
if (collectionValue instanceof ListValue) {
ListValue materialized = (ListValue) collectionValue;
checkSupportedList(materialized, this);
@@ -53,9 +56,10 @@ public CollectionValue> evaluate(ValueReferenceResolver valueRefResolver) {
Object value = materialized.get(i).getValue();
valueRefResolver.addExtension(
ValueReferences.ITERATOR_EXTENSION_NAME, CapturedValue.of(value));
- if (filterExpression.evaluate(valueRefResolver)) {
+ if (filterExpression.evaluate(evalContext)) {
filtered.add(value);
}
+ checkTimeout(evalContext.getTimeoutChecker(), this);
}
} finally {
valueRefResolver.removeExtension(ValueReferences.ITERATOR_EXTENSION_NAME);
@@ -74,9 +78,10 @@ public CollectionValue> evaluate(ValueReferenceResolver valueRefResolver) {
valueRefResolver.addExtension(
ValueReferences.ITERATOR_EXTENSION_NAME,
CapturedValue.of(new MapValue.Entry(key, value)));
- if (filterExpression.evaluate(valueRefResolver)) {
+ if (filterExpression.evaluate(evalContext)) {
filtered.put(key.getValue(), value.getValue());
}
+ checkTimeout(evalContext.getTimeoutChecker(), this);
}
} finally {
valueRefResolver.removeExtension(ValueReferences.KEY_EXTENSION_NAME);
@@ -92,9 +97,10 @@ public CollectionValue> evaluate(ValueReferenceResolver valueRefResolver) {
for (Object value : setHolder) {
valueRefResolver.addExtension(
ValueReferences.ITERATOR_EXTENSION_NAME, CapturedValue.of(value));
- if (filterExpression.evaluate(valueRefResolver)) {
+ if (filterExpression.evaluate(evalContext)) {
filtered.add(value);
}
+ checkTimeout(evalContext.getTimeoutChecker(), this);
}
} finally {
valueRefResolver.removeExtension(ValueReferences.ITERATOR_EXTENSION_NAME);
diff --git a/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/GetMemberExpression.java b/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/GetMemberExpression.java
index 45609979894..bfcfe6ee826 100644
--- a/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/GetMemberExpression.java
+++ b/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/GetMemberExpression.java
@@ -1,5 +1,8 @@
package com.datadog.debugger.el.expressions;
+import static com.datadog.debugger.el.expressions.ExpressionHelper.checkTimeout;
+
+import com.datadog.debugger.el.EvalContext;
import com.datadog.debugger.el.EvaluationException;
import com.datadog.debugger.el.Generated;
import com.datadog.debugger.el.PrettyPrintVisitor;
@@ -7,7 +10,6 @@
import com.datadog.debugger.el.ValueType;
import com.datadog.debugger.el.Visitor;
import datadog.trace.bootstrap.debugger.CapturedContext;
-import datadog.trace.bootstrap.debugger.el.ValueReferenceResolver;
import datadog.trace.bootstrap.debugger.util.Redaction;
import java.util.Objects;
@@ -21,14 +23,14 @@ public GetMemberExpression(ValueExpression> target, String memberName) {
}
@Override
- public Value> evaluate(ValueReferenceResolver valueRefResolver) {
- Value> targetValue = target.evaluate(valueRefResolver);
+ public Value> evaluate(EvalContext evalContext) {
+ Value> targetValue = target.evaluate(evalContext);
if (targetValue == Value.undefined()) {
return targetValue;
}
CapturedContext.CapturedValue member;
try {
- member = valueRefResolver.getMember(targetValue.getValue(), memberName);
+ member = evalContext.getValueRefResolver().getMember(targetValue.getValue(), memberName);
} catch (RuntimeException ex) {
throw new EvaluationException(ex.getMessage(), PrettyPrintVisitor.print(this), ex);
}
@@ -41,6 +43,7 @@ public Value> evaluate(ValueReferenceResolver valueRefResolver) {
|| Redaction.isRedactedType(memberValue.getClass().getTypeName()))) {
ExpressionHelper.throwRedactedException(this);
}
+ checkTimeout(evalContext.getTimeoutChecker(), this);
return Value.of(member.getValue(), ValueType.of(member.getType()));
}
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 6e2c449343f..90bba2f6165 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
@@ -5,7 +5,9 @@
import static com.datadog.debugger.el.expressions.CollectionExpressionHelper.checkSupportedMap;
import static com.datadog.debugger.el.expressions.CollectionExpressionHelper.checkSupportedSet;
import static com.datadog.debugger.el.expressions.CollectionExpressionHelper.evaluateTargetCollection;
+import static com.datadog.debugger.el.expressions.ExpressionHelper.checkTimeout;
+import com.datadog.debugger.el.EvalContext;
import com.datadog.debugger.el.EvaluationException;
import com.datadog.debugger.el.Value;
import com.datadog.debugger.el.Visitor;
@@ -30,8 +32,9 @@ public HasAllExpression(ValueExpression> valueExpression, BooleanExpression fi
}
@Override
- public Boolean evaluate(ValueReferenceResolver valueRefResolver) {
- Value> value = evaluateTargetCollection(valueExpression, this, valueRefResolver);
+ public Boolean evaluate(EvalContext evalContext) {
+ Value> value = evaluateTargetCollection(valueExpression, this, evalContext);
+ ValueReferenceResolver valueRefResolver = evalContext.getValueRefResolver();
if (value instanceof ListValue) {
ListValue collection = (ListValue) value;
checkSupportedList(collection, this);
@@ -44,9 +47,10 @@ public Boolean evaluate(ValueReferenceResolver valueRefResolver) {
for (int i = 0; i < len; i++) {
valueRefResolver.addExtension(
ValueReferences.ITERATOR_EXTENSION_NAME, CapturedValue.of(collection.get(i)));
- if (!filterPredicateExpression.evaluate(valueRefResolver)) {
+ if (!filterPredicateExpression.evaluate(evalContext)) {
return Boolean.FALSE;
}
+ checkTimeout(evalContext.getTimeoutChecker(), this);
}
return Boolean.TRUE;
} finally {
@@ -69,9 +73,10 @@ public Boolean evaluate(ValueReferenceResolver valueRefResolver) {
valueRefResolver.addExtension(
ValueReferences.ITERATOR_EXTENSION_NAME,
CapturedValue.of(new MapValue.Entry(key, val)));
- if (!filterPredicateExpression.evaluate(valueRefResolver)) {
+ if (!filterPredicateExpression.evaluate(evalContext)) {
return Boolean.FALSE;
}
+ checkTimeout(evalContext.getTimeoutChecker(), this);
}
return Boolean.TRUE;
} finally {
@@ -91,9 +96,10 @@ public Boolean evaluate(ValueReferenceResolver valueRefResolver) {
for (Object val : setHolder) {
valueRefResolver.addExtension(
ValueReferences.ITERATOR_EXTENSION_NAME, CapturedValue.of(val));
- if (!filterPredicateExpression.evaluate(valueRefResolver)) {
+ if (!filterPredicateExpression.evaluate(evalContext)) {
return Boolean.FALSE;
}
+ checkTimeout(evalContext.getTimeoutChecker(), this);
}
return Boolean.TRUE;
} finally {
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 23c3dea831f..7de0e110dfa 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
@@ -5,7 +5,9 @@
import static com.datadog.debugger.el.expressions.CollectionExpressionHelper.checkSupportedMap;
import static com.datadog.debugger.el.expressions.CollectionExpressionHelper.checkSupportedSet;
import static com.datadog.debugger.el.expressions.CollectionExpressionHelper.evaluateTargetCollection;
+import static com.datadog.debugger.el.expressions.ExpressionHelper.checkTimeout;
+import com.datadog.debugger.el.EvalContext;
import com.datadog.debugger.el.EvaluationException;
import com.datadog.debugger.el.Value;
import com.datadog.debugger.el.Visitor;
@@ -31,8 +33,9 @@ public HasAnyExpression(
}
@Override
- public Boolean evaluate(ValueReferenceResolver valueRefResolver) {
- Value> value = evaluateTargetCollection(valueExpression, this, valueRefResolver);
+ public Boolean evaluate(EvalContext evalContext) {
+ Value> value = evaluateTargetCollection(valueExpression, this, evalContext);
+ ValueReferenceResolver valueRefResolver = evalContext.getValueRefResolver();
if (value instanceof ListValue) {
ListValue collection = (ListValue) value;
checkSupportedList(collection, this);
@@ -45,9 +48,10 @@ public Boolean evaluate(ValueReferenceResolver valueRefResolver) {
for (int i = 0; i < len; i++) {
valueRefResolver.addExtension(
ValueReferences.ITERATOR_EXTENSION_NAME, CapturedValue.of(collection.get(i)));
- if (filterPredicateExpression.evaluate(valueRefResolver)) {
+ if (filterPredicateExpression.evaluate(evalContext)) {
return Boolean.TRUE;
}
+ checkTimeout(evalContext.getTimeoutChecker(), this);
}
return Boolean.FALSE;
@@ -72,9 +76,10 @@ public Boolean evaluate(ValueReferenceResolver valueRefResolver) {
valueRefResolver.addExtension(
ValueReferences.ITERATOR_EXTENSION_NAME,
CapturedValue.of(new MapValue.Entry(key, val)));
- if (filterPredicateExpression.evaluate(valueRefResolver)) {
+ if (filterPredicateExpression.evaluate(evalContext)) {
return Boolean.TRUE;
}
+ checkTimeout(evalContext.getTimeoutChecker(), this);
}
return Boolean.FALSE;
} catch (IllegalArgumentException | UnsupportedOperationException ex) {
@@ -95,9 +100,10 @@ public Boolean evaluate(ValueReferenceResolver valueRefResolver) {
for (Object val : setHolder) {
valueRefResolver.addExtension(
ValueReferences.ITERATOR_EXTENSION_NAME, CapturedValue.of(val));
- if (filterPredicateExpression.evaluate(valueRefResolver)) {
+ if (filterPredicateExpression.evaluate(evalContext)) {
return Boolean.TRUE;
}
+ checkTimeout(evalContext.getTimeoutChecker(), this);
}
return Boolean.FALSE;
} catch (IllegalArgumentException | UnsupportedOperationException ex) {
diff --git a/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/IfElseExpression.java b/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/IfElseExpression.java
index cdd18689b11..1914b3a9a47 100644
--- a/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/IfElseExpression.java
+++ b/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/IfElseExpression.java
@@ -1,8 +1,10 @@
package com.datadog.debugger.el.expressions;
+import static com.datadog.debugger.el.expressions.ExpressionHelper.checkTimeout;
+
+import com.datadog.debugger.el.EvalContext;
import com.datadog.debugger.el.Expression;
import com.datadog.debugger.el.Visitor;
-import datadog.trace.bootstrap.debugger.el.ValueReferenceResolver;
/** TODO: Primordial support for 'debugger watches' support */
public final class IfElseExpression implements Expression {
@@ -18,12 +20,13 @@ public IfElseExpression(
}
@Override
- public Void evaluate(ValueReferenceResolver valueRefResolver) {
- if (test.evaluate(valueRefResolver)) {
- thenExpression.evaluate(valueRefResolver);
+ public Void evaluate(EvalContext evalContext) {
+ if (test.evaluate(evalContext)) {
+ thenExpression.evaluate(evalContext);
} else {
- elseExpression.evaluate(valueRefResolver);
+ elseExpression.evaluate(evalContext);
}
+ checkTimeout(evalContext.getTimeoutChecker(), this);
return null;
}
diff --git a/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/IfExpression.java b/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/IfExpression.java
index d799b01c3b5..cce1e53aedd 100644
--- a/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/IfExpression.java
+++ b/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/IfExpression.java
@@ -1,8 +1,10 @@
package com.datadog.debugger.el.expressions;
+import static com.datadog.debugger.el.expressions.ExpressionHelper.checkTimeout;
+
+import com.datadog.debugger.el.EvalContext;
import com.datadog.debugger.el.Expression;
import com.datadog.debugger.el.Visitor;
-import datadog.trace.bootstrap.debugger.el.ValueReferenceResolver;
/** TODO: Primordial support for 'debugger watches' support */
public final class IfExpression implements Expression {
@@ -15,10 +17,11 @@ public IfExpression(BooleanExpression test, Expression> expression) {
}
@Override
- public Void evaluate(ValueReferenceResolver valueRefResolver) {
- if (test.evaluate(valueRefResolver)) {
- expression.evaluate(valueRefResolver);
+ public Void evaluate(EvalContext evalContext) {
+ if (test.evaluate(evalContext)) {
+ expression.evaluate(evalContext);
}
+ checkTimeout(evalContext.getTimeoutChecker(), this);
return null;
}
diff --git a/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/IndexExpression.java b/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/IndexExpression.java
index 9992286b0fa..8c718eb282d 100644
--- a/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/IndexExpression.java
+++ b/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/IndexExpression.java
@@ -2,14 +2,15 @@
import static com.datadog.debugger.el.expressions.CollectionExpressionHelper.checkSupportedList;
import static com.datadog.debugger.el.expressions.CollectionExpressionHelper.checkSupportedMap;
+import static com.datadog.debugger.el.expressions.ExpressionHelper.checkTimeout;
+import com.datadog.debugger.el.EvalContext;
import com.datadog.debugger.el.EvaluationException;
import com.datadog.debugger.el.PrettyPrintVisitor;
import com.datadog.debugger.el.Value;
import com.datadog.debugger.el.Visitor;
import com.datadog.debugger.el.values.ListValue;
import com.datadog.debugger.el.values.MapValue;
-import datadog.trace.bootstrap.debugger.el.ValueReferenceResolver;
import datadog.trace.bootstrap.debugger.util.Redaction;
public class IndexExpression implements ValueExpression> {
@@ -23,8 +24,8 @@ public IndexExpression(ValueExpression> target, ValueExpression> key) {
}
@Override
- public Value> evaluate(ValueReferenceResolver valueRefResolver) {
- Value> targetValue = target.evaluate(valueRefResolver);
+ public Value> evaluate(EvalContext evalContext) {
+ Value> targetValue = target.evaluate(evalContext);
if (targetValue.isUndefined()) {
throw new EvaluationException(
"Cannot evaluate the expression for undefined value", PrettyPrintVisitor.print(this));
@@ -34,7 +35,7 @@ public Value> evaluate(ValueReferenceResolver valueRefResolver) {
"Cannot evaluate the expression for null value", PrettyPrintVisitor.print(this));
}
Value> result = Value.undefinedValue();
- Value> keyValue = key.evaluate(valueRefResolver);
+ Value> keyValue = key.evaluate(evalContext);
if (keyValue == Value.undefined()) {
return result;
}
@@ -65,6 +66,7 @@ public Value> evaluate(ValueReferenceResolver valueRefResolver) {
if (obj != null && Redaction.isRedactedType(obj.getClass().getTypeName())) {
ExpressionHelper.throwRedactedException(this);
}
+ checkTimeout(evalContext.getTimeoutChecker(), this);
return Value.of(result.getValue(), result.getType());
}
diff --git a/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/IsDefinedExpression.java b/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/IsDefinedExpression.java
index 5bada175eb4..27da03e06ae 100644
--- a/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/IsDefinedExpression.java
+++ b/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/IsDefinedExpression.java
@@ -1,9 +1,11 @@
package com.datadog.debugger.el.expressions;
+import static com.datadog.debugger.el.expressions.ExpressionHelper.checkTimeout;
+
+import com.datadog.debugger.el.EvalContext;
import com.datadog.debugger.el.EvaluationException;
import com.datadog.debugger.el.Value;
import com.datadog.debugger.el.Visitor;
-import datadog.trace.bootstrap.debugger.el.ValueReferenceResolver;
/** Check whether a {@linkplain Value} was resolved correctly or symbol exists.
*/
public class IsDefinedExpression implements BooleanExpression {
@@ -14,15 +16,17 @@ public IsDefinedExpression(ValueExpression> valueExpression) {
}
@Override
- public Boolean evaluate(ValueReferenceResolver valueRefResolver) {
+ public Boolean evaluate(EvalContext evalContext) {
if (valueExpression == null) {
return Boolean.FALSE;
}
try {
- Value> value = valueExpression.evaluate(valueRefResolver);
+ Value> value = valueExpression.evaluate(evalContext);
return value.isUndefined() ? Boolean.FALSE : Boolean.TRUE;
} catch (EvaluationException ex) {
return Boolean.FALSE;
+ } finally {
+ checkTimeout(evalContext.getTimeoutChecker(), this);
}
}
diff --git a/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/IsEmptyExpression.java b/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/IsEmptyExpression.java
index 066aee72abc..1c4b43eef51 100644
--- a/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/IsEmptyExpression.java
+++ b/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/IsEmptyExpression.java
@@ -1,12 +1,14 @@
package com.datadog.debugger.el.expressions;
+import static com.datadog.debugger.el.expressions.ExpressionHelper.checkTimeout;
+
+import com.datadog.debugger.el.EvalContext;
import com.datadog.debugger.el.EvaluationException;
import com.datadog.debugger.el.PrettyPrintVisitor;
import com.datadog.debugger.el.Value;
import com.datadog.debugger.el.Visitor;
import com.datadog.debugger.el.values.CollectionValue;
import com.datadog.debugger.el.values.StringValue;
-import datadog.trace.bootstrap.debugger.el.ValueReferenceResolver;
/**
* Checks whether a {@linkplain Value} is empty.
@@ -20,8 +22,8 @@ public IsEmptyExpression(ValueExpression> valueExpression) {
}
@Override
- public Boolean evaluate(ValueReferenceResolver valueRefResolver) {
- Value> value = valueExpression.evaluate(valueRefResolver);
+ public Boolean evaluate(EvalContext evalContext) {
+ Value> value = valueExpression.evaluate(evalContext);
if (value.isUndefined()) {
throw new EvaluationException(
"Cannot evaluate the expression for undefined value", PrettyPrintVisitor.print(this));
@@ -30,12 +32,14 @@ public Boolean evaluate(ValueReferenceResolver valueRefResolver) {
throw new EvaluationException(
"Cannot evaluate the expression for null value", PrettyPrintVisitor.print(this));
}
+ boolean result = false;
if (value instanceof CollectionValue) {
- return ((CollectionValue>) value).isEmpty();
+ result = ((CollectionValue>) value).isEmpty();
} else if (value instanceof StringValue) {
- return ((StringValue) value).isEmpty();
+ result = ((StringValue) value).isEmpty();
}
- return Boolean.FALSE;
+ checkTimeout(evalContext.getTimeoutChecker(), this);
+ return result;
}
@Override
diff --git a/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/LenExpression.java b/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/LenExpression.java
index aee603c4779..3033d693cf1 100644
--- a/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/LenExpression.java
+++ b/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/LenExpression.java
@@ -1,5 +1,8 @@
package com.datadog.debugger.el.expressions;
+import static com.datadog.debugger.el.expressions.ExpressionHelper.checkTimeout;
+
+import com.datadog.debugger.el.EvalContext;
import com.datadog.debugger.el.EvaluationException;
import com.datadog.debugger.el.PrettyPrintVisitor;
import com.datadog.debugger.el.Value;
@@ -8,7 +11,6 @@
import com.datadog.debugger.el.values.CollectionValue;
import com.datadog.debugger.el.values.NumericValue;
import com.datadog.debugger.el.values.StringValue;
-import datadog.trace.bootstrap.debugger.el.ValueReferenceResolver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -28,23 +30,27 @@ public LenExpression(ValueExpression> source) {
}
@Override
- public Value evaluate(ValueReferenceResolver valueRefResolver) {
- Value> materialized = source == null ? Value.nullValue() : source.evaluate(valueRefResolver);
+ public Value evaluate(EvalContext evalContext) {
+ Value> materialized = source == null ? Value.nullValue() : source.evaluate(evalContext);
+ Value result = Value.undefined();
try {
if (materialized.isNull()) {
throw new RuntimeException("Cannot evaluate the expression for null value");
} else if (materialized.isUndefined()) {
throw new RuntimeException("Cannot evaluate the expression for undefined value");
} else if (materialized instanceof StringValue) {
- return (NumericValue) Value.of(((StringValue) materialized).length(), ValueType.INT);
+ result = (NumericValue) Value.of(((StringValue) materialized).length(), ValueType.INT);
} else if (materialized instanceof CollectionValue) {
- return (NumericValue) Value.of(((CollectionValue) materialized).count(), ValueType.INT);
+ result = (NumericValue) Value.of(((CollectionValue) materialized).count(), ValueType.INT);
+ } else {
+ throw new RuntimeException(
+ "Cannot evaluate the expression for " + materialized.getClass().getTypeName());
}
} catch (RuntimeException ex) {
throw new EvaluationException(ex.getMessage(), PrettyPrintVisitor.print(this));
}
- log.warn("Can not compute length for {}", materialized);
- return Value.undefined();
+ checkTimeout(evalContext.getTimeoutChecker(), this);
+ return result;
}
public ValueExpression> getSource() {
diff --git a/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/NotExpression.java b/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/NotExpression.java
index 6c71a7cc240..5cf8fad7607 100644
--- a/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/NotExpression.java
+++ b/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/NotExpression.java
@@ -1,7 +1,9 @@
package com.datadog.debugger.el.expressions;
+import static com.datadog.debugger.el.expressions.ExpressionHelper.checkTimeout;
+
+import com.datadog.debugger.el.EvalContext;
import com.datadog.debugger.el.Visitor;
-import datadog.trace.bootstrap.debugger.el.ValueReferenceResolver;
/** Will negate the resolved {@linkplain BooleanExpression} */
public final class NotExpression implements BooleanExpression {
@@ -12,8 +14,10 @@ public NotExpression(BooleanExpression predicate) {
}
@Override
- public Boolean evaluate(ValueReferenceResolver valueRefResolver) {
- return !predicate.evaluate(valueRefResolver);
+ public Boolean evaluate(EvalContext evalContext) {
+ boolean result = !predicate.evaluate(evalContext);
+ checkTimeout(evalContext.getTimeoutChecker(), this);
+ return result;
}
@Override
diff --git a/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/StringPredicateExpression.java b/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/StringPredicateExpression.java
index 05d59b50b3c..efb1a4f3269 100644
--- a/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/StringPredicateExpression.java
+++ b/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/StringPredicateExpression.java
@@ -1,10 +1,10 @@
package com.datadog.debugger.el.expressions;
+import com.datadog.debugger.el.EvalContext;
import com.datadog.debugger.el.EvaluationException;
import com.datadog.debugger.el.PrettyPrintVisitor;
import com.datadog.debugger.el.Value;
import com.datadog.debugger.el.values.StringValue;
-import datadog.trace.bootstrap.debugger.el.ValueReferenceResolver;
import java.util.function.BiPredicate;
public class StringPredicateExpression implements BooleanExpression {
@@ -25,9 +25,9 @@ public StringPredicateExpression(
}
@Override
- public Boolean evaluate(ValueReferenceResolver valueRefResolver) {
+ public Boolean evaluate(EvalContext evalContext) {
Value> sourceValue =
- sourceString != null ? sourceString.evaluate(valueRefResolver) : Value.nullValue();
+ sourceString != null ? sourceString.evaluate(evalContext) : Value.nullValue();
if (sourceValue.isUndefined()) {
throw new EvaluationException(
"Cannot evaluate the expression for undefined value", PrettyPrintVisitor.print(this));
@@ -38,7 +38,9 @@ public Boolean evaluate(ValueReferenceResolver valueRefResolver) {
}
if (sourceValue.getValue() instanceof String) {
String sourceStr = (String) sourceValue.getValue();
- return predicate.test(sourceStr, str.getValue());
+ boolean result = predicate.test(sourceStr, str.getValue());
+ ExpressionHelper.checkTimeout(evalContext.getTimeoutChecker(), this);
+ return result;
}
return Boolean.FALSE;
}
diff --git a/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/SubStringExpression.java b/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/SubStringExpression.java
index c50e01271c9..40e7d258e33 100644
--- a/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/SubStringExpression.java
+++ b/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/SubStringExpression.java
@@ -1,11 +1,13 @@
package com.datadog.debugger.el.expressions;
+import static com.datadog.debugger.el.expressions.ExpressionHelper.checkTimeout;
+
+import com.datadog.debugger.el.EvalContext;
import com.datadog.debugger.el.EvaluationException;
import com.datadog.debugger.el.PrettyPrintVisitor;
import com.datadog.debugger.el.Value;
import com.datadog.debugger.el.ValueType;
import com.datadog.debugger.el.Visitor;
-import datadog.trace.bootstrap.debugger.el.ValueReferenceResolver;
public class SubStringExpression implements ValueExpression> {
private final ValueExpression> source;
@@ -19,8 +21,8 @@ public SubStringExpression(ValueExpression> source, int startIndex, int endInd
}
@Override
- public Value evaluate(ValueReferenceResolver valueRefResolver) {
- Value> sourceValue = source != null ? source.evaluate(valueRefResolver) : Value.nullValue();
+ public Value evaluate(EvalContext evalContext) {
+ Value> sourceValue = source != null ? source.evaluate(evalContext) : Value.nullValue();
if (sourceValue.isUndefined()) {
throw new EvaluationException(
"Cannot evaluate the expression for undefined value", PrettyPrintVisitor.print(this));
@@ -31,7 +33,9 @@ public Value evaluate(ValueReferenceResolver valueRefResolver) {
}
if (sourceValue.getValue() instanceof String) {
String sourceStr = (String) sourceValue.getValue();
- return internalEvaluate(sourceStr);
+ Value result = internalEvaluate(sourceStr);
+ checkTimeout(evalContext.getTimeoutChecker(), this);
+ return result;
}
return Value.undefined();
}
diff --git a/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/ThenExpression.java b/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/ThenExpression.java
index 024109a5f58..e75b02fc701 100644
--- a/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/ThenExpression.java
+++ b/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/ThenExpression.java
@@ -1,12 +1,12 @@
package com.datadog.debugger.el.expressions;
+import com.datadog.debugger.el.EvalContext;
import com.datadog.debugger.el.Value;
-import datadog.trace.bootstrap.debugger.el.ValueReferenceResolver;
/** TODO: Primordial support for 'debugger watches' support */
public final class ThenExpression implements ValueExpression> {
@Override
- public Value evaluate(ValueReferenceResolver valueRefResolver) {
+ public Value evaluate(EvalContext evalContext) {
// TODO: This can be used to implement 'add watch' functionality where the script can amend the
// collected snapshot
return null;
diff --git a/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/ValueExpression.java b/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/ValueExpression.java
index 22d8e782a7d..5c43935555c 100644
--- a/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/ValueExpression.java
+++ b/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/ValueExpression.java
@@ -1,8 +1,8 @@
package com.datadog.debugger.el.expressions;
+import com.datadog.debugger.el.EvalContext;
import com.datadog.debugger.el.Expression;
import com.datadog.debugger.el.Value;
-import datadog.trace.bootstrap.debugger.el.ValueReferenceResolver;
/**
* A generic interface for expressions resolving to {@linkplain Value}
@@ -13,7 +13,7 @@ public interface ValueExpression> extends Expression {
ValueExpression> NULL =
new ValueExpression>() {
@Override
- public Value> evaluate(ValueReferenceResolver valueRefResolver) {
+ public Value> evaluate(EvalContext evalContext) {
return Value.nullValue();
}
@@ -26,7 +26,7 @@ public String toString() {
ValueExpression> UNDEFINED =
new ValueExpression>() {
@Override
- public Value> evaluate(ValueReferenceResolver valueRefResolver) {
+ public Value> evaluate(EvalContext evalContext) {
return Value.undefinedValue();
}
diff --git a/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/ValueRefExpression.java b/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/ValueRefExpression.java
index fa36ef9f15f..1b14838e167 100644
--- a/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/ValueRefExpression.java
+++ b/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/ValueRefExpression.java
@@ -1,7 +1,10 @@
package com.datadog.debugger.el.expressions;
+import static com.datadog.debugger.el.expressions.ExpressionHelper.checkTimeout;
+import static com.datadog.debugger.el.expressions.ExpressionHelper.throwRedactedException;
import static datadog.trace.bootstrap.debugger.util.Redaction.REDACTED_VALUE;
+import com.datadog.debugger.el.EvalContext;
import com.datadog.debugger.el.EvaluationException;
import com.datadog.debugger.el.Generated;
import com.datadog.debugger.el.PrettyPrintVisitor;
@@ -9,7 +12,6 @@
import com.datadog.debugger.el.ValueType;
import com.datadog.debugger.el.Visitor;
import datadog.trace.bootstrap.debugger.CapturedContext;
-import datadog.trace.bootstrap.debugger.el.ValueReferenceResolver;
import datadog.trace.bootstrap.debugger.util.Redaction;
import java.util.Objects;
@@ -22,18 +24,19 @@ public ValueRefExpression(String symbolName) {
}
@Override
- public Value> evaluate(ValueReferenceResolver valueRefResolver) {
+ public Value> evaluate(EvalContext evalContext) {
CapturedContext.CapturedValue symbol;
try {
- symbol = valueRefResolver.lookup(symbolName);
+ symbol = evalContext.getValueRefResolver().lookup(symbolName);
} catch (RuntimeException ex) {
throw new EvaluationException(ex.getMessage(), PrettyPrintVisitor.print(this));
}
if (symbol != null) {
String typeName = symbol.getType();
if (symbol.getValue() == REDACTED_VALUE || (Redaction.isRedactedType(typeName))) {
- ExpressionHelper.throwRedactedException(this);
+ throwRedactedException(this);
}
+ checkTimeout(evalContext.getTimeoutChecker(), this);
return Value.of(symbol.getValue(), ValueType.of(symbol.getType()));
}
return Value.nullValue();
diff --git a/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/WhenExpression.java b/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/WhenExpression.java
index 8ad9b0ad491..60f0b3cfb77 100644
--- a/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/WhenExpression.java
+++ b/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/expressions/WhenExpression.java
@@ -1,7 +1,7 @@
package com.datadog.debugger.el.expressions;
+import com.datadog.debugger.el.EvalContext;
import com.datadog.debugger.el.Visitor;
-import datadog.trace.bootstrap.debugger.el.ValueReferenceResolver;
/** The entry-point expression for the debugger EL */
public final class WhenExpression implements BooleanExpression {
@@ -12,8 +12,8 @@ public WhenExpression(BooleanExpression expression) {
}
@Override
- public Boolean evaluate(ValueReferenceResolver valueRefResolver) {
- return expression.evaluate(valueRefResolver);
+ public Boolean evaluate(EvalContext evalContext) {
+ return expression.evaluate(evalContext);
}
@Override
diff --git a/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/values/ListValue.java b/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/values/ListValue.java
index d0c3dcffc63..8c9ce5fbb87 100644
--- a/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/values/ListValue.java
+++ b/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/values/ListValue.java
@@ -1,10 +1,13 @@
package com.datadog.debugger.el.values;
+import static com.datadog.debugger.el.expressions.ExpressionHelper.checkArrayLength;
+import static com.datadog.debugger.el.expressions.ExpressionHelper.checkCollectionSize;
+
+import com.datadog.debugger.el.EvalContext;
import com.datadog.debugger.el.Value;
import com.datadog.debugger.el.ValueType;
import com.datadog.debugger.el.Visitor;
import com.datadog.debugger.el.expressions.ValueExpression;
-import datadog.trace.bootstrap.debugger.el.ValueReferenceResolver;
import datadog.trace.bootstrap.debugger.el.Values;
import datadog.trace.bootstrap.debugger.util.WellKnownClasses;
import java.lang.reflect.Array;
@@ -134,14 +137,17 @@ public Value> get(int index) {
@Override
public boolean contains(Value> val) {
if (listHolder instanceof Collection) {
- if (WellKnownClasses.isSafe((Collection>) listHolder)) {
- return ((Collection>) listHolder).contains(val.isNull() ? null : val.getValue());
+ Collection> collection = (Collection>) listHolder;
+ if (WellKnownClasses.isSafe(collection)) {
+ checkCollectionSize(collection, this);
+ return collection.contains(val.isNull() ? null : val.getValue());
}
throw new UnsupportedOperationException(
"Unsupported Collection class: " + listHolder.getClass().getTypeName());
}
if (arrayHolder != null) {
int count = Array.getLength(arrayHolder);
+ checkArrayLength(count, this);
if (arrayType.isPrimitive()) {
if (val.getValue() == null || val.isNull()) {
throw new IllegalArgumentException("Cannot compare null with primitive array");
@@ -255,7 +261,7 @@ public Object getValue() {
}
@Override
- public ListValue evaluate(ValueReferenceResolver valueRefResolver) {
+ public ListValue evaluate(EvalContext evalContext) {
return this;
}
diff --git a/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/values/MapValue.java b/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/values/MapValue.java
index c06680aa56e..05778531c82 100644
--- a/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/values/MapValue.java
+++ b/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/values/MapValue.java
@@ -1,10 +1,10 @@
package com.datadog.debugger.el.values;
+import com.datadog.debugger.el.EvalContext;
import com.datadog.debugger.el.Value;
import com.datadog.debugger.el.ValueType;
import com.datadog.debugger.el.Visitor;
import com.datadog.debugger.el.expressions.ValueExpression;
-import datadog.trace.bootstrap.debugger.el.ValueReferenceResolver;
import datadog.trace.bootstrap.debugger.el.Values;
import datadog.trace.bootstrap.debugger.util.WellKnownClasses;
import java.util.Collections;
@@ -144,7 +144,7 @@ public Object getValue() {
}
@Override
- public MapValue evaluate(ValueReferenceResolver valueRefResolver) {
+ public MapValue evaluate(EvalContext evalContext) {
return this;
}
diff --git a/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/values/SetValue.java b/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/values/SetValue.java
index 07651471858..9654c1b99c8 100644
--- a/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/values/SetValue.java
+++ b/dd-java-agent/agent-debugger/debugger-el/src/main/java/com/datadog/debugger/el/values/SetValue.java
@@ -1,10 +1,10 @@
package com.datadog.debugger.el.values;
+import com.datadog.debugger.el.EvalContext;
import com.datadog.debugger.el.Value;
import com.datadog.debugger.el.ValueType;
import com.datadog.debugger.el.Visitor;
import com.datadog.debugger.el.expressions.ValueExpression;
-import datadog.trace.bootstrap.debugger.el.ValueReferenceResolver;
import datadog.trace.bootstrap.debugger.el.Values;
import datadog.trace.bootstrap.debugger.util.WellKnownClasses;
import java.util.Collection;
@@ -25,7 +25,7 @@ public SetValue(Object object) {
}
@Override
- public SetValue evaluate(ValueReferenceResolver valueRefResolver) {
+ public SetValue evaluate(EvalContext evalContext) {
return this;
}
diff --git a/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/BooleanValueExpressionAdapterTest.java b/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/BooleanValueExpressionAdapterTest.java
index 3b793ecb1d6..01a09dd6569 100644
--- a/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/BooleanValueExpressionAdapterTest.java
+++ b/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/BooleanValueExpressionAdapterTest.java
@@ -1,10 +1,10 @@
package com.datadog.debugger.el;
+import static com.datadog.debugger.el.EvalContextHelper.createEvalContext;
import static org.junit.jupiter.api.Assertions.*;
import com.datadog.debugger.el.expressions.BooleanExpression;
import com.datadog.debugger.el.values.BooleanValue;
-import datadog.trace.bootstrap.debugger.el.ValueReferenceResolver;
import org.junit.jupiter.api.Test;
class BooleanValueExpressionAdapterTest {
@@ -29,20 +29,14 @@ public void testLiteral() {
public void testExpression() {
BooleanValueExpressionAdapter booleanValueExpressionAdapter =
new BooleanValueExpressionAdapter(DSL.eq(DSL.value(1), DSL.value(1)));
- BooleanValue resultValue = booleanValueExpressionAdapter.evaluate(null);
+ BooleanValue resultValue = booleanValueExpressionAdapter.evaluate(createEvalContext(this));
assertTrue(resultValue.getValue());
}
@Test
public void testNull() {
BooleanValueExpressionAdapter booleanValueExpressionAdapter =
- new BooleanValueExpressionAdapter(
- new BooleanExpression() {
- @Override
- public Boolean evaluate(ValueReferenceResolver valueRefResolver) {
- return null;
- }
- });
+ new BooleanValueExpressionAdapter(evalContext -> null);
EvaluationException ex =
assertThrows(EvaluationException.class, () -> booleanValueExpressionAdapter.evaluate(null));
assertEquals("Boolean expression returning null", ex.getMessage());
diff --git a/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/RefResolverHelper.java b/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/EvalContextHelper.java
similarity index 72%
rename from dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/RefResolverHelper.java
rename to dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/EvalContextHelper.java
index 88b33231c3f..9df06537c7e 100644
--- a/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/RefResolverHelper.java
+++ b/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/EvalContextHelper.java
@@ -1,11 +1,27 @@
package com.datadog.debugger.el;
+import datadog.trace.api.Config;
import datadog.trace.bootstrap.debugger.CapturedContext;
import datadog.trace.bootstrap.debugger.el.ValueReferenceResolver;
import datadog.trace.bootstrap.debugger.util.Redaction;
+import datadog.trace.bootstrap.debugger.util.TimeoutChecker;
+import java.time.Duration;
import java.util.*;
-public class RefResolverHelper {
+public class EvalContextHelper {
+
+ public static final Duration TEST_TIMEOUT = Duration.ofMillis(1000);
+
+ public static EvalContext createEvalContext(Object instance) {
+ // create a higher timeout for test to avoid flakiness
+ return new EvalContext(
+ createResolver(instance), TimeoutChecker.create(Config.get(), TEST_TIMEOUT));
+ }
+
+ // specify lower timeout to test timeout checker
+ public static EvalContext createEvalContext(Object instance, Duration timeout) {
+ return new EvalContext(createResolver(instance), TimeoutChecker.create(Config.get(), timeout));
+ }
public static ValueReferenceResolver createResolver(Object instance) {
CapturedContext.CapturedValue thisValue =
diff --git a/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/ExpressionTest.java b/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/ExpressionTest.java
index f88cf81e472..de75a00713f 100644
--- a/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/ExpressionTest.java
+++ b/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/ExpressionTest.java
@@ -1,6 +1,7 @@
package com.datadog.debugger.el;
import static com.datadog.debugger.el.DSL.*;
+import static com.datadog.debugger.el.EvalContextHelper.createEvalContext;
import static com.datadog.debugger.el.PrettyPrintVisitor.print;
import static org.junit.jupiter.api.Assertions.*;
@@ -9,7 +10,6 @@
import com.datadog.debugger.el.values.NumericValue;
import com.datadog.debugger.el.values.StringValue;
import datadog.trace.bootstrap.debugger.CapturedContext;
-import datadog.trace.bootstrap.debugger.el.ValueReferenceResolver;
import java.util.stream.Stream;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
@@ -21,7 +21,7 @@ class ExpressionTest {
@MethodSource("literalExpressions")
void testLiteralExpressions(Literal> literal, Object expectedValue) {
Value> value1 = literal.evaluate(null);
- Value> value2 = literal.evaluate(new CapturedContext());
+ Value> value2 = literal.evaluate(new EvalContext(new CapturedContext(), null));
assertNotNull(value1);
assertNotNull(value2);
@@ -43,16 +43,16 @@ void testPredicateExpression() {
StringValue string = new StringValue("Hello World");
StringValue emptyString = new StringValue("");
- ValueReferenceResolver resolver = new CapturedContext();
+ EvalContext evalContext = createEvalContext(this);
IsEmptyExpression isEmpty1 = new IsEmptyExpression(string);
IsEmptyExpression isEmpty2 = new IsEmptyExpression(emptyString);
- assertFalse(isEmpty1.evaluate(resolver));
- assertTrue(isEmpty2.evaluate(resolver));
+ assertFalse(isEmpty1.evaluate(evalContext));
+ assertTrue(isEmpty2.evaluate(evalContext));
- assertTrue(not(isEmpty1).evaluate(resolver));
- assertTrue(or(isEmpty1, isEmpty2).evaluate(resolver));
- assertFalse(and(isEmpty1, isEmpty2).evaluate(resolver));
+ assertTrue(not(isEmpty1).evaluate(evalContext));
+ assertTrue(or(isEmpty1, isEmpty2).evaluate(evalContext));
+ assertFalse(and(isEmpty1, isEmpty2).evaluate(evalContext));
}
@Test
diff --git a/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/ProbeConditionTest.java b/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/ProbeConditionTest.java
index 8d6f8a3eae3..50ba2590b2a 100644
--- a/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/ProbeConditionTest.java
+++ b/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/ProbeConditionTest.java
@@ -10,7 +10,11 @@
import com.squareup.moshi.JsonAdapter;
import com.squareup.moshi.Moshi;
+import datadog.trace.api.Config;
+import datadog.trace.bootstrap.debugger.el.ReflectiveFieldValueResolver;
import datadog.trace.bootstrap.debugger.el.ValueReferenceResolver;
+import datadog.trace.bootstrap.debugger.util.Redaction;
+import datadog.trace.bootstrap.debugger.util.TimeoutChecker;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
@@ -28,12 +32,22 @@
import java.util.UUID;
import java.util.stream.Collectors;
import okio.Okio;
+import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
public class ProbeConditionTest {
+ private static final Duration TEST_TIMEOUT = Duration.ofMillis(500);
// used in testExecuteCondition
private int field = 10;
+ @BeforeAll
+ static void beforeAll() {
+ // Warming up here for first call, to avoid reaching timeout when evaluating
+ Redaction.isRedactedKeyword("strList");
+ ReflectiveFieldValueResolver.getFieldAsCapturedValue(
+ ProbeConditionTest.class, new ProbeConditionTest(), "field");
+ }
+
@Test
void testExecuteCondition() throws Exception {
ProbeCondition probeCondition = loadFromResource("/test_conditional_01.json");
@@ -42,17 +56,17 @@ class Obj1 {
private int field = 10;
List field2 = new ArrayList<>();
}
- ValueReferenceResolver ctx = RefResolverHelper.createResolver(new Obj1());
+ ValueReferenceResolver ctx = EvalContextHelper.createResolver(new Obj1());
- assertTrue(probeCondition.execute(ctx));
+ assertTrue(probeCondition.execute(ctx, TimeoutChecker.create(Config.get(), TEST_TIMEOUT)));
class Obj2 {
Collection tags = Arrays.asList("hey", "world", "ko");
private int field = 10;
List field2 = new ArrayList<>();
}
- ValueReferenceResolver ctx2 = RefResolverHelper.createResolver(new Obj2());
- assertFalse(probeCondition.execute(ctx2));
+ ValueReferenceResolver ctx2 = EvalContextHelper.createResolver(new Obj2());
+ assertFalse(probeCondition.execute(ctx2, TimeoutChecker.create(Config.get(), TEST_TIMEOUT)));
}
@Test
@@ -62,18 +76,20 @@ class Obj {
Container container = new Container("hello");
}
ValueReferenceResolver ctx =
- RefResolverHelper.createResolver(
+ EvalContextHelper.createResolver(
singletonMap("this", new Obj()), singletonMap("container", new Container("world")));
- assertTrue(probeCondition.execute(ctx));
+ assertTrue(probeCondition.execute(ctx, TimeoutChecker.create(Config.get(), TEST_TIMEOUT)));
class Obj2 {
Container obj = new Container("hello");
}
ValueReferenceResolver ctx2 =
- RefResolverHelper.createResolver(
+ EvalContextHelper.createResolver(
singletonMap("this", new Obj2()), singletonMap("container", new Container("world")));
RuntimeException runtimeException =
- assertThrows(RuntimeException.class, () -> probeCondition.execute(ctx2));
+ assertThrows(
+ RuntimeException.class,
+ () -> probeCondition.execute(ctx2, TimeoutChecker.create(Config.get(), TEST_TIMEOUT)));
assertEquals("Cannot dereference field: container", runtimeException.getMessage());
}
@@ -84,8 +100,8 @@ class Obj {
int intField1 = 42;
String strField = "foo";
}
- ValueReferenceResolver ctx = RefResolverHelper.createResolver(new Obj());
- assertTrue(probeCondition.execute(ctx));
+ ValueReferenceResolver ctx = EvalContextHelper.createResolver(new Obj());
+ assertTrue(probeCondition.execute(ctx, TimeoutChecker.create(Config.get(), TEST_TIMEOUT)));
}
@Test
@@ -95,9 +111,9 @@ class Obj {
Object objField = new Object();
}
ValueReferenceResolver ctx =
- RefResolverHelper.createResolver(
+ EvalContextHelper.createResolver(
singletonMap("this", new Obj()), singletonMap("nullField", null));
- assertTrue(probeCondition.execute(ctx));
+ assertTrue(probeCondition.execute(ctx, TimeoutChecker.create(Config.get(), TEST_TIMEOUT)));
}
@Test
@@ -116,8 +132,8 @@ class Obj {
int idx = 1;
}
- ValueReferenceResolver ctx = RefResolverHelper.createResolver(new Obj());
- assertTrue(probeCondition.execute(ctx));
+ ValueReferenceResolver ctx = EvalContextHelper.createResolver(new Obj());
+ assertTrue(probeCondition.execute(ctx, TimeoutChecker.create(Config.get(), TEST_TIMEOUT)));
}
@Test
@@ -126,8 +142,8 @@ void testStringOperation() throws Exception {
class Obj {
String strField = "foobar";
}
- ValueReferenceResolver ctx = RefResolverHelper.createResolver(new Obj());
- assertTrue(probeCondition.execute(ctx));
+ ValueReferenceResolver ctx = EvalContextHelper.createResolver(new Obj());
+ assertTrue(probeCondition.execute(ctx, TimeoutChecker.create(Config.get(), TEST_TIMEOUT)));
}
@Test
@@ -148,10 +164,10 @@ void testJsonParsing() throws IOException {
class Obj {
Collection vets = Arrays.asList("vet1", "vet2", "vet3");
}
- ValueReferenceResolver ctx = RefResolverHelper.createResolver(new Obj());
+ ValueReferenceResolver ctx = EvalContextHelper.createResolver(new Obj());
// the condition checks if length of vets > 2
- assertTrue(probeCondition.execute(ctx));
+ assertTrue(probeCondition.execute(ctx, TimeoutChecker.create(Config.get(), TEST_TIMEOUT)));
}
@Test
@@ -191,9 +207,11 @@ void redaction() throws IOException {
ProbeCondition probeCondition = loadFromResource("/test_conditional_09.json");
Map args = new HashMap<>();
args.put("password", "secret123");
- ValueReferenceResolver ctx = RefResolverHelper.createResolver(args, null);
+ ValueReferenceResolver ctx = EvalContextHelper.createResolver(args, null);
EvaluationException evaluationException =
- assertThrows(EvaluationException.class, () -> probeCondition.execute(ctx));
+ assertThrows(
+ EvaluationException.class,
+ () -> probeCondition.execute(ctx, TimeoutChecker.create(Config.get(), TEST_TIMEOUT)));
assertEquals(
"Could not evaluate the expression because 'password' was redacted",
evaluationException.getMessage());
@@ -207,8 +225,8 @@ void primitives() throws IOException {
args.put("duration", Duration.ofSeconds(42));
args.put("clazz", "foo".getClass());
args.put("now", new Date(1700000000000L)); // 2023-11-14T00:00:00Z
- ValueReferenceResolver ctx = RefResolverHelper.createResolver(args, null);
- assertTrue(probeCondition.execute(ctx));
+ ValueReferenceResolver ctx = EvalContextHelper.createResolver(args, null);
+ assertTrue(probeCondition.execute(ctx, TimeoutChecker.create(Config.get(), TEST_TIMEOUT)));
}
@Test
@@ -222,8 +240,8 @@ class Obj {
Set emptySet = new HashSet<>();
Object[] emptyArray = new Object[0];
}
- ValueReferenceResolver ctx = RefResolverHelper.createResolver(new Obj());
- assertTrue(probeCondition.execute(ctx));
+ ValueReferenceResolver ctx = EvalContextHelper.createResolver(new Obj());
+ assertTrue(probeCondition.execute(ctx, TimeoutChecker.create(Config.get(), TEST_TIMEOUT)));
}
@Test
@@ -238,16 +256,24 @@ class Obj {
Object objVal = null;
char charVal = 'a';
}
- ValueReferenceResolver ctx = RefResolverHelper.createResolver(new Obj());
- assertTrue(probeCondition.execute(ctx));
+ ValueReferenceResolver ctx = EvalContextHelper.createResolver(new Obj());
+ assertTrue(probeCondition.execute(ctx, TimeoutChecker.create(Config.get(), TEST_TIMEOUT)));
}
@Test
- void testLenCount() throws Exception {
+ void testTimeoutAndLenCount() throws Exception {
ProbeCondition probeCondition = loadFromResource("/test_conditional_14.json");
class Obj {
int[] intArray = new int[] {1, 1, 1};
String[] strArray = new String[] {"foo", "bar"};
+ List largeList = new ArrayList<>();
+
+ {
+ for (int i = 0; i < 1_000; i++) {
+ largeList.add("foobar" + i);
+ }
+ }
+
Map strMap = new HashMap<>();
{
@@ -267,8 +293,18 @@ class Obj {
strList.add("foo");
}
}
- ValueReferenceResolver ctx = RefResolverHelper.createResolver(new Obj());
- assertTrue(probeCondition.execute(ctx));
+ Obj obj = new Obj();
+ ValueReferenceResolver ctx = EvalContextHelper.createResolver(obj);
+ // first call is longer so ideal to test timeout
+ EvaluationException evaluationException =
+ assertThrows(
+ EvaluationException.class,
+ () ->
+ probeCondition.execute(
+ ctx, TimeoutChecker.create(Config.get(), Duration.ofMillis(1))));
+ assertEquals("timeout (1ms)", evaluationException.getMessage());
+ // test good execution
+ assertTrue(probeCondition.execute(ctx, TimeoutChecker.create(Config.get(), TEST_TIMEOUT)));
}
@Test
@@ -278,9 +314,11 @@ class Obj {
}
List lines = loadLinesFromResource("/null_expressions.txt");
for (String line : lines) {
- ValueReferenceResolver ctx = RefResolverHelper.createResolver(new Obj());
+ ValueReferenceResolver ctx = EvalContextHelper.createResolver(new Obj());
EvaluationException ex =
- assertThrows(EvaluationException.class, () -> load(line).execute(ctx));
+ assertThrows(
+ EvaluationException.class,
+ () -> load(line).execute(ctx, TimeoutChecker.create(Config.get(), TEST_TIMEOUT)));
assertEquals("Cannot evaluate the expression for null value", ex.getMessage(), line);
}
}
@@ -299,11 +337,14 @@ class Obj {
}
List lines = loadLinesFromResource("/contains_expressions.txt");
for (String line : lines) {
- ValueReferenceResolver ctx = RefResolverHelper.createResolver(new Obj());
- assertTrue(load(line).execute(ctx));
+ ValueReferenceResolver ctx = EvalContextHelper.createResolver(new Obj());
+ assertTrue(load(line).execute(ctx, TimeoutChecker.create(Config.get(), TEST_TIMEOUT)));
}
}
+ @Test
+ public void timeoutExpressions() {}
+
private static ProbeCondition loadFromResource(String resourcePath) throws IOException {
InputStream input = ProbeConditionTest.class.getResourceAsStream(resourcePath);
Moshi moshi =
diff --git a/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/ValueScriptTest.java b/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/ValueScriptTest.java
index eefbca9956a..fccf05ffeb7 100644
--- a/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/ValueScriptTest.java
+++ b/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/ValueScriptTest.java
@@ -1,13 +1,19 @@
package com.datadog.debugger.el;
+import static com.datadog.debugger.el.EvalContextHelper.createResolver;
import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
import com.squareup.moshi.Moshi;
+import datadog.trace.api.Config;
import datadog.trace.bootstrap.debugger.el.Values;
+import datadog.trace.bootstrap.debugger.util.TimeoutChecker;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
+import java.time.Duration;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
@@ -15,22 +21,43 @@
import org.junit.jupiter.api.Test;
public class ValueScriptTest {
+ private static final Duration TEST_TIMEOUT = Duration.ofMinutes(500);
static class Obj {
String str = "hello";
int i = 10;
List list = Arrays.asList("a", "b", "c");
+ List largeList = new ArrayList<>();
long l = 100_000_000_000L;
float f = 2.5F;
double d = 3.14D;
char c = 'a';
+
+ {
+ for (int i = 0; i < 5_000; i++) {
+ largeList.add("hello" + i);
+ }
+ }
}
@Test
public void predicates() {
ValueScript valueScript = loadFromResource("/test_value_expr_01.json");
+ // first call is longer so ideal to test timeout
+ EvaluationException evaluationException =
+ assertThrows(
+ EvaluationException.class,
+ () ->
+ valueScript.execute(
+ createResolver(new Obj()),
+ TimeoutChecker.create(Config.get(), Duration.ofMillis(1))));
+ assertEquals("timeout (1ms)", evaluationException.getMessage());
+ // test good execution
assertEquals(
- Boolean.TRUE, valueScript.execute(RefResolverHelper.createResolver(new Obj())).getValue());
+ Boolean.TRUE,
+ valueScript
+ .execute(createResolver(new Obj()), TimeoutChecker.create(Config.get(), TEST_TIMEOUT))
+ .getValue());
}
@Test
@@ -40,7 +67,9 @@ public void topLevelPredicates() {
ValueScript valueScript = load(line);
assertEquals(
Boolean.TRUE,
- valueScript.execute(RefResolverHelper.createResolver(new Obj())).getValue(),
+ valueScript
+ .execute(createResolver(new Obj()), TimeoutChecker.create(Config.get(), TEST_TIMEOUT))
+ .getValue(),
line);
}
}
@@ -77,7 +106,9 @@ public void topLevelPrimitives() {
ValueScript valueScript = load(line);
assertEquals(
expectedValues[i],
- valueScript.execute(RefResolverHelper.createResolver(new Obj())).getValue(),
+ valueScript
+ .execute(createResolver(new Obj()), TimeoutChecker.create(Config.get(), TEST_TIMEOUT))
+ .getValue(),
line);
i++;
}
diff --git a/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/expressions/BinaryExpressionTest.java b/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/expressions/BinaryExpressionTest.java
index 8faaf61d48a..ef6de51409f 100644
--- a/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/expressions/BinaryExpressionTest.java
+++ b/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/expressions/BinaryExpressionTest.java
@@ -1,20 +1,23 @@
package com.datadog.debugger.el.expressions;
+import static com.datadog.debugger.el.EvalContextHelper.createEvalContext;
import static com.datadog.debugger.el.PrettyPrintVisitor.print;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
-import com.datadog.debugger.el.RefResolverHelper;
+import com.datadog.debugger.el.EvalContext;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
class BinaryExpressionTest {
+ EvalContext evalContext = createEvalContext(this);
+
@Test
void testLeftNull() {
BinaryExpression expression =
new BinaryExpression(null, BooleanExpression.TRUE, BinaryOperator.AND);
- assertFalse(expression.evaluate(RefResolverHelper.createResolver(this)));
+ assertFalse(expression.evaluate(evalContext));
assertEquals("false && true", print(expression));
}
@@ -22,7 +25,7 @@ void testLeftNull() {
void testRightNull() {
BinaryExpression expression =
new BinaryExpression(BooleanExpression.TRUE, null, BinaryOperator.AND);
- assertFalse(expression.evaluate(RefResolverHelper.createResolver(this)));
+ assertFalse(expression.evaluate(evalContext));
assertEquals("true && false", print(expression));
}
@@ -33,7 +36,7 @@ void testShortCircuitAnd() {
BooleanExpression.FALSE,
valueRefResolver -> Assertions.fail("should not reach"),
BinaryOperator.AND);
- assertFalse(expression.evaluate(RefResolverHelper.createResolver(this)));
+ assertFalse(expression.evaluate(evalContext));
assertEquals("false && null", print(expression));
}
@@ -44,7 +47,7 @@ void testShortCircuitOr() {
BooleanExpression.TRUE,
valueRefResolver -> Assertions.fail("should not reach"),
BinaryOperator.OR);
- assertTrue(expression.evaluate(RefResolverHelper.createResolver(this)));
+ assertTrue(expression.evaluate(evalContext));
assertEquals("true || null", print(expression));
}
}
diff --git a/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/expressions/ComparisonExpressionTest.java b/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/expressions/ComparisonExpressionTest.java
index d2b2e1cd8c4..28ac3425f3e 100644
--- a/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/expressions/ComparisonExpressionTest.java
+++ b/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/expressions/ComparisonExpressionTest.java
@@ -1,5 +1,6 @@
package com.datadog.debugger.el.expressions;
+import static com.datadog.debugger.el.EvalContextHelper.createEvalContext;
import static com.datadog.debugger.el.PrettyPrintVisitor.print;
import static com.datadog.debugger.el.ValueType.DOUBLE;
import static com.datadog.debugger.el.ValueType.FLOAT;
@@ -14,6 +15,7 @@
import static com.datadog.debugger.el.expressions.ComparisonOperator.LT;
import static org.junit.jupiter.api.Assertions.*;
+import com.datadog.debugger.el.EvalContext;
import com.datadog.debugger.el.EvaluationException;
import com.datadog.debugger.el.values.NumericValue;
import com.datadog.debugger.el.values.ObjectValue;
@@ -41,7 +43,7 @@ void evaluateOperator(
boolean expected,
String prettyPrint) {
ComparisonExpression expression = new ComparisonExpression(left, right, operator);
- assertEquals(expected, expression.evaluate(NoopResolver.INSTANCE));
+ assertEquals(expected, expression.evaluate(createEvalContext(NoopResolver.INSTANCE)));
assertEquals(prettyPrint, print(expression));
}
@@ -243,7 +245,7 @@ void evaluateOperatorStrings(
boolean expected,
String prettyPrint) {
ComparisonExpression expression = new ComparisonExpression(left, right, operator);
- assertEquals(expected, expression.evaluate(NoopResolver.INSTANCE));
+ assertEquals(expected, expression.evaluate(createEvalContext(NoopResolver.INSTANCE)));
assertEquals(prettyPrint, print(expression));
}
@@ -273,35 +275,35 @@ private static Stream expressionStrs() {
void evaluateSecondUndefined() {
ComparisonExpression expression =
new ComparisonExpression(new NumericValue(1, INT), ValueExpression.UNDEFINED, EQ);
- assertFalse(expression.evaluate(NoopResolver.INSTANCE));
+ assertFalse(expression.evaluate(new EvalContext(NoopResolver.INSTANCE, null)));
}
@Test
void evaluateBothUndefined() {
ComparisonExpression expression =
new ComparisonExpression(ValueExpression.UNDEFINED, ValueExpression.UNDEFINED, EQ);
- assertFalse(expression.evaluate(NoopResolver.INSTANCE));
+ assertFalse(expression.evaluate(new EvalContext(NoopResolver.INSTANCE, null)));
}
@Test
void evaluateFirstNull() {
ComparisonExpression expression =
new ComparisonExpression(ValueExpression.NULL, new NumericValue(2, INT), EQ);
- assertFalse(expression.evaluate(NoopResolver.INSTANCE));
+ assertFalse(expression.evaluate(createEvalContext(NoopResolver.INSTANCE)));
}
@Test
void evaluateSecondNull() {
ComparisonExpression expression =
new ComparisonExpression(new NumericValue(1, INT), ValueExpression.NULL, EQ);
- assertFalse(expression.evaluate(NoopResolver.INSTANCE));
+ assertFalse(expression.evaluate(createEvalContext(NoopResolver.INSTANCE)));
}
@Test
void evaluateBothNull() {
ComparisonExpression expression =
new ComparisonExpression(ValueExpression.NULL, ValueExpression.NULL, EQ);
- assertTrue(expression.evaluate(NoopResolver.INSTANCE));
+ assertTrue(expression.evaluate(createEvalContext(NoopResolver.INSTANCE)));
}
@Test
@@ -309,7 +311,9 @@ void invalidInstanceofOperand() {
ComparisonExpression expression =
new ComparisonExpression(new StringValue("foo"), new NumericValue(1, INT), INSTANCEOF);
EvaluationException evaluationException =
- assertThrows(EvaluationException.class, () -> expression.evaluate(NoopResolver.INSTANCE));
+ assertThrows(
+ EvaluationException.class,
+ () -> expression.evaluate(createEvalContext(NoopResolver.INSTANCE)));
assertEquals(
"Right operand of instanceof operator must be a string literal",
evaluationException.getMessage());
@@ -321,7 +325,9 @@ void invalidInstanceofClassName() {
ComparisonExpression expression =
new ComparisonExpression(new StringValue("foo"), new StringValue("String"), INSTANCEOF);
EvaluationException evaluationException =
- assertThrows(EvaluationException.class, () -> expression.evaluate(NoopResolver.INSTANCE));
+ assertThrows(
+ EvaluationException.class,
+ () -> expression.evaluate(createEvalContext(NoopResolver.INSTANCE)));
assertEquals("Class not found: String", evaluationException.getMessage());
assertEquals("\"foo\" instanceof \"String\"", evaluationException.getExpr());
}
diff --git a/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/expressions/ContainsExpressionTest.java b/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/expressions/ContainsExpressionTest.java
index 88b08a94c3f..60cd3d9f5c6 100644
--- a/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/expressions/ContainsExpressionTest.java
+++ b/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/expressions/ContainsExpressionTest.java
@@ -1,27 +1,46 @@
package com.datadog.debugger.el.expressions;
+import static com.datadog.debugger.el.EvalContextHelper.createEvalContext;
import static com.datadog.debugger.el.PrettyPrintVisitor.print;
import static org.junit.jupiter.api.Assertions.*;
import com.datadog.debugger.el.DSL;
+import com.datadog.debugger.el.EvalContext;
import com.datadog.debugger.el.EvaluationException;
-import com.datadog.debugger.el.RefResolverHelper;
import com.datadog.debugger.el.values.StringValue;
-import datadog.trace.bootstrap.debugger.el.ValueReferenceResolver;
import datadog.trace.bootstrap.debugger.el.Values;
+import java.time.Duration;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.concurrent.locks.LockSupport;
import org.junit.jupiter.api.Test;
class ContainsExpressionTest {
- private final ValueReferenceResolver resolver = RefResolverHelper.createResolver(this);
+ private final EvalContext evalContext = createEvalContext(this);
private List list = Arrays.asList("foo", "bar", "baz");
private List listWithNull = Arrays.asList("foo", null, "baz");
+ private List largeList = new ArrayList<>();
+
+ {
+ for (int i = 0; i < 1_000_001; i++) {
+ largeList.add(i);
+ }
+ }
+
+ private List slowList = new ArrayList<>();
+
+ {
+ for (int i = 0; i < 10_000; i++) {
+ slowList.add(String.valueOf(i));
+ }
+ }
+
private String[] arrayStr = new String[] {"foo", "bar", "baz"};
private String[] arrayStrWithNull = new String[] {"foo", null, "bar"};
private int[] arrayInt = new int[] {1, 2, 3};
@@ -60,7 +79,7 @@ class ContainsExpressionTest {
void nullExpression() {
ContainsExpression expression = new ContainsExpression(null, null);
EvaluationException exception =
- assertThrows(EvaluationException.class, () -> expression.evaluate(resolver));
+ assertThrows(EvaluationException.class, () -> expression.evaluate(evalContext));
assertEquals("Cannot evaluate the expression for null value", exception.getMessage());
assertEquals("contains(null, null)", print(expression));
}
@@ -70,7 +89,7 @@ void undefinedExpression() {
ContainsExpression expression =
new ContainsExpression(DSL.value(Values.UNDEFINED_OBJECT), new StringValue(null));
EvaluationException exception =
- assertThrows(EvaluationException.class, () -> expression.evaluate(resolver));
+ assertThrows(EvaluationException.class, () -> expression.evaluate(evalContext));
assertEquals("Cannot evaluate the expression for undefined value", exception.getMessage());
assertEquals("contains(UNDEFINED, \"null\")", print(expression));
}
@@ -79,16 +98,16 @@ void undefinedExpression() {
void stringExpression() {
ContainsExpression expression =
new ContainsExpression(DSL.value("abcd"), new StringValue("bc"));
- assertTrue(expression.evaluate(resolver));
+ assertTrue(expression.evaluate(evalContext));
assertEquals("contains(\"abcd\", \"bc\")", print(expression));
expression = new ContainsExpression(DSL.value("abc"), new StringValue("dc"));
- assertFalse(expression.evaluate(resolver));
+ assertFalse(expression.evaluate(evalContext));
assertEquals("contains(\"abc\", \"dc\")", print(expression));
ContainsExpression nullValExpression = new ContainsExpression(DSL.value("abcd"), null);
EvaluationException exception =
- assertThrows(EvaluationException.class, () -> nullValExpression.evaluate(resolver));
+ assertThrows(EvaluationException.class, () -> nullValExpression.evaluate(evalContext));
assertEquals("Cannot evaluate the expression for non-string value", exception.getMessage());
assertEquals("contains(\"abcd\", null)", print(nullValExpression));
}
@@ -96,43 +115,55 @@ void stringExpression() {
@Test
void listExpression() {
ContainsExpression expression = new ContainsExpression(DSL.ref("list"), DSL.value("bar"));
- assertTrue(expression.evaluate(resolver));
+ assertTrue(expression.evaluate(evalContext));
assertEquals("contains(list, \"bar\")", print(expression));
expression = new ContainsExpression(DSL.ref("listWithNull"), null);
- assertTrue(expression.evaluate(resolver));
+ assertTrue(expression.evaluate(evalContext));
assertEquals("contains(listWithNull, null)", print(expression));
+
+ ContainsExpression largeExpression = new ContainsExpression(DSL.ref("largeList"), DSL.value(1));
+ EvaluationException evaluationException =
+ assertThrows(EvaluationException.class, () -> largeExpression.evaluate(evalContext));
+ assertEquals("Collection too large (>1000000)", evaluationException.getMessage());
+
+ ContainsExpression slowListExpression =
+ new ContainsExpression(DSL.ref("slowList"), DSL.value(new SlowObject()));
+ assertThrows(
+ EvaluationException.class,
+ () -> slowListExpression.evaluate(createEvalContext(this, Duration.ofMillis(1))));
}
@Test
void arrayExpression() {
ContainsExpression expression = new ContainsExpression(DSL.ref("arrayStr"), DSL.value("bar"));
- assertTrue(expression.evaluate(resolver));
+ assertTrue(expression.evaluate(evalContext));
assertEquals("contains(arrayStr, \"bar\")", print(expression));
expression = new ContainsExpression(DSL.ref("arrayInt"), DSL.value(2));
- assertTrue(expression.evaluate(resolver));
+ assertTrue(expression.evaluate(evalContext));
assertEquals("contains(arrayInt, 2)", print(expression));
expression = new ContainsExpression(DSL.ref("arrayChar"), DSL.value("b"));
- assertTrue(expression.evaluate(resolver));
+ assertTrue(expression.evaluate(evalContext));
assertEquals("contains(arrayChar, \"b\")", print(expression));
expression = new ContainsExpression(DSL.ref("arrayLong"), DSL.value(2));
- assertTrue(expression.evaluate(resolver));
+ assertTrue(expression.evaluate(evalContext));
assertEquals("contains(arrayLong, 2)", print(expression));
expression = new ContainsExpression(DSL.ref("arrayDouble"), DSL.value(2.0));
- assertTrue(expression.evaluate(resolver));
+ assertTrue(expression.evaluate(evalContext));
assertEquals("contains(arrayDouble, 2.0)", print(expression));
expression = new ContainsExpression(DSL.ref("arrayStrWithNull"), null);
- assertTrue(expression.evaluate(resolver));
+ assertTrue(expression.evaluate(evalContext));
assertEquals("contains(arrayStrWithNull, null)", print(expression));
ContainsExpression primitiveNullExpression = new ContainsExpression(DSL.ref("arrayInt"), null);
EvaluationException exception =
- assertThrows(EvaluationException.class, () -> primitiveNullExpression.evaluate(resolver));
+ assertThrows(
+ EvaluationException.class, () -> primitiveNullExpression.evaluate(evalContext));
assertEquals("Cannot compare null with primitive array", exception.getMessage());
assertEquals("contains(arrayInt, null)", print(primitiveNullExpression));
}
@@ -140,22 +171,30 @@ void arrayExpression() {
@Test
void mapExpression() {
ContainsExpression expression = new ContainsExpression(DSL.ref("mapStr"), DSL.value("bar"));
- assertTrue(expression.evaluate(resolver));
+ assertTrue(expression.evaluate(evalContext));
assertEquals("contains(mapStr, \"bar\")", print(expression));
expression = new ContainsExpression(DSL.ref("mapStrWithNull"), null);
- assertTrue(expression.evaluate(resolver));
+ assertTrue(expression.evaluate(evalContext));
assertEquals("contains(mapStrWithNull, null)", print(expression));
}
@Test
void setExpression() {
ContainsExpression expression = new ContainsExpression(DSL.ref("setStr"), DSL.value("bar"));
- assertTrue(expression.evaluate(resolver));
+ assertTrue(expression.evaluate(evalContext));
assertEquals("contains(setStr, \"bar\")", print(expression));
expression = new ContainsExpression(DSL.ref("setStrWithNull"), null);
- assertTrue(expression.evaluate(resolver));
+ assertTrue(expression.evaluate(evalContext));
assertEquals("contains(setStrWithNull, null)", print(expression));
}
+
+ static class SlowObject {
+ @Override
+ public boolean equals(Object obj) {
+ LockSupport.parkNanos(1000);
+ return super.equals(obj);
+ }
+ }
}
diff --git a/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/expressions/EndsWithExpressionTest.java b/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/expressions/EndsWithExpressionTest.java
index 17a6b1c07f1..1ac730564a7 100644
--- a/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/expressions/EndsWithExpressionTest.java
+++ b/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/expressions/EndsWithExpressionTest.java
@@ -1,5 +1,6 @@
package com.datadog.debugger.el.expressions;
+import static com.datadog.debugger.el.EvalContextHelper.createEvalContext;
import static com.datadog.debugger.el.PrettyPrintVisitor.print;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
@@ -7,16 +8,15 @@
import static org.junit.jupiter.api.Assertions.assertTrue;
import com.datadog.debugger.el.DSL;
+import com.datadog.debugger.el.EvalContext;
import com.datadog.debugger.el.EvaluationException;
-import com.datadog.debugger.el.RefResolverHelper;
import com.datadog.debugger.el.values.StringValue;
-import datadog.trace.bootstrap.debugger.el.ValueReferenceResolver;
import datadog.trace.bootstrap.debugger.el.Values;
import java.net.URI;
import org.junit.jupiter.api.Test;
class EndsWithExpressionTest {
- private final ValueReferenceResolver resolver = RefResolverHelper.createResolver(this);
+ private final EvalContext evalContext = createEvalContext(this);
// used to ref lookup
URI uri = URI.create("https://www.datadoghq.com");
@@ -24,7 +24,7 @@ class EndsWithExpressionTest {
void nullExpression() {
EndsWithExpression expression = new EndsWithExpression(null, null);
EvaluationException exception =
- assertThrows(EvaluationException.class, () -> expression.evaluate(resolver));
+ assertThrows(EvaluationException.class, () -> expression.evaluate(evalContext));
assertEquals("Cannot evaluate the expression for null value", exception.getMessage());
assertEquals("endsWith(null, null)", print(expression));
}
@@ -34,7 +34,7 @@ void undefinedExpression() {
EndsWithExpression expression =
new EndsWithExpression(DSL.value(Values.UNDEFINED_OBJECT), new StringValue(null));
EvaluationException exception =
- assertThrows(EvaluationException.class, () -> expression.evaluate(resolver));
+ assertThrows(EvaluationException.class, () -> expression.evaluate(evalContext));
assertEquals("Cannot evaluate the expression for undefined value", exception.getMessage());
assertEquals("endsWith(UNDEFINED, \"null\")", print(expression));
}
@@ -42,18 +42,18 @@ void undefinedExpression() {
@Test
void stringExpression() {
EndsWithExpression expression = new EndsWithExpression(DSL.value("abc"), new StringValue("bc"));
- assertTrue(expression.evaluate(resolver));
+ assertTrue(expression.evaluate(evalContext));
assertEquals("endsWith(\"abc\", \"bc\")", print(expression));
expression = new EndsWithExpression(DSL.value("abc"), new StringValue("ab"));
- assertFalse(expression.evaluate(resolver));
+ assertFalse(expression.evaluate(evalContext));
assertEquals("endsWith(\"abc\", \"ab\")", print(expression));
}
@Test
void stringPrimitives() {
EndsWithExpression expression = new EndsWithExpression(DSL.ref("uri"), new StringValue(".com"));
- assertTrue(expression.evaluate(resolver));
+ assertTrue(expression.evaluate(evalContext));
assertEquals("endsWith(uri, \".com\")", print(expression));
}
}
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 38b0ea7e692..6d2e80cebda 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
@@ -1,32 +1,40 @@
package com.datadog.debugger.el.expressions;
import static com.datadog.debugger.el.DSL.*;
+import static com.datadog.debugger.el.EvalContextHelper.createEvalContext;
import static com.datadog.debugger.el.PrettyPrintVisitor.print;
import static org.junit.jupiter.api.Assertions.*;
+import com.datadog.debugger.el.EvalContext;
import com.datadog.debugger.el.EvaluationException;
-import com.datadog.debugger.el.RefResolverHelper;
import com.datadog.debugger.el.values.CollectionValue;
import com.datadog.debugger.el.values.ListValue;
import com.datadog.debugger.el.values.MapValue;
import com.datadog.debugger.el.values.SetValue;
import datadog.trace.bootstrap.debugger.el.ValueReferences;
import datadog.trace.bootstrap.debugger.el.Values;
+import java.time.Duration;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.List;
import java.util.Map;
+import java.util.Set;
import org.junit.jupiter.api.Test;
class FilterCollectionExpressionTest {
+
+ private final EvalContext evalContext = createEvalContext(this);
+
@Test
void testMatchingList() {
ListValue collection = new ListValue(new int[] {1, 2, 3});
FilterCollectionExpression expression =
new FilterCollectionExpression(collection, lt(ref(ValueReferences.ITERATOR_REF), value(2)));
- CollectionValue> filtered = expression.evaluate(RefResolverHelper.createResolver(this));
+ CollectionValue> filtered = expression.evaluate(evalContext);
assertNotEquals(collection, filtered);
assertEquals(1, filtered.count());
assertFalse(filtered.isEmpty());
@@ -40,7 +48,7 @@ void testEmptyList() {
ListValue collection = new ListValue(new int[0]);
FilterCollectionExpression expression =
new FilterCollectionExpression(collection, lt(ref(ValueReferences.ITERATOR_REF), value(2)));
- CollectionValue> filtered = expression.evaluate(RefResolverHelper.createResolver(this));
+ CollectionValue> filtered = expression.evaluate(evalContext);
assertNotEquals(collection, filtered);
assertTrue(filtered.isEmpty());
assertFalse(filtered.isNull());
@@ -54,9 +62,7 @@ void testNullList() {
FilterCollectionExpression expression =
new FilterCollectionExpression(collection, lt(ref(ValueReferences.ITERATOR_REF), value(2)));
EvaluationException exception =
- assertThrows(
- EvaluationException.class,
- () -> expression.evaluate(RefResolverHelper.createResolver(this)));
+ assertThrows(EvaluationException.class, () -> expression.evaluate(evalContext));
assertEquals("Cannot evaluate the expression for null value", exception.getMessage());
assertEquals("filter(null, {@it < 2})", print(expression));
}
@@ -67,9 +73,7 @@ void testNullObjectList() {
FilterCollectionExpression expression =
new FilterCollectionExpression(collection, lt(ref(ValueReferences.ITERATOR_REF), value(2)));
EvaluationException exception =
- assertThrows(
- EvaluationException.class,
- () -> expression.evaluate(RefResolverHelper.createResolver(this)));
+ assertThrows(EvaluationException.class, () -> expression.evaluate(evalContext));
assertEquals("Cannot evaluate the expression for null value", exception.getMessage());
assertEquals("filter(null, {@it < 2})", print(expression));
}
@@ -80,13 +84,27 @@ void testUndefinedList() {
FilterCollectionExpression expression =
new FilterCollectionExpression(collection, lt(ref(ValueReferences.ITERATOR_REF), value(2)));
EvaluationException exception =
- assertThrows(
- EvaluationException.class,
- () -> expression.evaluate(RefResolverHelper.createResolver(this)));
+ assertThrows(EvaluationException.class, () -> expression.evaluate(evalContext));
assertEquals("Cannot evaluate the expression for undefined value", exception.getMessage());
assertEquals("filter(null, {@it < 2})", print(expression));
}
+ @Test
+ void testLargeList() {
+ List largeList = new ArrayList<>();
+ for (int i = 0; i < 1_000_000; i++) {
+ largeList.add(i);
+ }
+ ListValue collection = new ListValue(largeList);
+ FilterCollectionExpression expression =
+ new FilterCollectionExpression(collection, lt(ref(ValueReferences.ITERATOR_REF), value(0)));
+ EvalContext timeoutEvalContext = createEvalContext(this, Duration.ofMillis(1));
+ EvaluationException exception =
+ assertThrows(EvaluationException.class, () -> expression.evaluate(timeoutEvalContext));
+ assertEquals("timeout (1ms)", exception.getMessage());
+ assertEquals("filter(List, {@it < 0})", print(expression));
+ }
+
@Test
void testMatchingMap() {
Map map = new HashMap<>();
@@ -98,7 +116,7 @@ void testMatchingMap() {
FilterCollectionExpression expression =
new FilterCollectionExpression(
collection, eq(getMember(ref(ValueReferences.ITERATOR_REF), "key"), value("b")));
- CollectionValue> filtered = expression.evaluate(RefResolverHelper.createResolver(this));
+ CollectionValue> filtered = expression.evaluate(evalContext);
assertNotEquals(collection, filtered);
assertEquals(1, filtered.count());
assertFalse(filtered.isEmpty());
@@ -108,7 +126,7 @@ void testMatchingMap() {
expression =
new FilterCollectionExpression(
collection, lt(getMember(ref(ValueReferences.ITERATOR_REF), "value"), value(2)));
- filtered = expression.evaluate(RefResolverHelper.createResolver(this));
+ filtered = expression.evaluate(evalContext);
assertNotEquals(collection, filtered);
assertEquals(1, filtered.count());
assertFalse(filtered.isEmpty());
@@ -122,7 +140,7 @@ void testEmptyMap() {
MapValue collection = new MapValue(Collections.emptyMap());
FilterCollectionExpression expression =
new FilterCollectionExpression(collection, lt(ref(ValueReferences.ITERATOR_REF), value(2)));
- CollectionValue> filtered = expression.evaluate(RefResolverHelper.createResolver(this));
+ CollectionValue> filtered = expression.evaluate(evalContext);
assertNotEquals(collection, filtered);
assertTrue(filtered.isEmpty());
assertFalse(filtered.isNull());
@@ -136,9 +154,7 @@ void testNullMap() {
FilterCollectionExpression expression =
new FilterCollectionExpression(collection, lt(ref(ValueReferences.ITERATOR_REF), value(2)));
EvaluationException exception =
- assertThrows(
- EvaluationException.class,
- () -> expression.evaluate(RefResolverHelper.createResolver(this)));
+ assertThrows(EvaluationException.class, () -> expression.evaluate(evalContext));
assertEquals("Cannot evaluate the expression for null value", exception.getMessage());
assertEquals("filter(null, {@it < 2})", print(expression));
}
@@ -149,9 +165,7 @@ void testNullObjectMap() {
FilterCollectionExpression expression =
new FilterCollectionExpression(collection, lt(ref(ValueReferences.ITERATOR_REF), value(2)));
EvaluationException exception =
- assertThrows(
- EvaluationException.class,
- () -> expression.evaluate(RefResolverHelper.createResolver(this)));
+ assertThrows(EvaluationException.class, () -> expression.evaluate(evalContext));
assertEquals("Cannot evaluate the expression for null value", exception.getMessage());
assertEquals("filter(null, {@it < 2})", print(expression));
}
@@ -162,9 +176,7 @@ void testUndefinedMap() {
FilterCollectionExpression expression =
new FilterCollectionExpression(collection, lt(ref(ValueReferences.ITERATOR_REF), value(2)));
EvaluationException exception =
- assertThrows(
- EvaluationException.class,
- () -> expression.evaluate(RefResolverHelper.createResolver(this)));
+ assertThrows(EvaluationException.class, () -> expression.evaluate(evalContext));
assertEquals("Cannot evaluate the expression for undefined value", exception.getMessage());
assertEquals("filter(null, {@it < 2})", print(expression));
}
@@ -179,25 +191,42 @@ void keyValueMap() {
FilterCollectionExpression expression =
new FilterCollectionExpression(collection, eq(ref(ValueReferences.KEY_REF), value("b")));
- CollectionValue> filtered = expression.evaluate(RefResolverHelper.createResolver(this));
+ CollectionValue> filtered = expression.evaluate(evalContext);
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));
+ filtered = expression.evaluate(evalContext);
assertNotEquals(collection, filtered);
assertEquals(1, filtered.count());
assertEquals("filter(Map, {@value == 2})", print(expression));
}
+ @Test
+ void testLargeMap() {
+ Map map = new HashMap<>();
+ for (int i = 0; i <= 1_000_000; i++) {
+ map.put(i, i);
+ }
+ MapValue collection = new MapValue(map);
+
+ FilterCollectionExpression expression =
+ new FilterCollectionExpression(collection, lt(ref(ValueReferences.ITERATOR_REF), value(0)));
+ EvalContext timeoutEvalContext = createEvalContext(this, Duration.ofMillis(1));
+ EvaluationException exception =
+ assertThrows(EvaluationException.class, () -> expression.evaluate(timeoutEvalContext));
+ assertEquals("timeout (1ms)", exception.getMessage());
+ assertEquals("filter(Map, {@it < 0})", print(expression));
+ }
+
@Test
void testMatchingSet() {
SetValue collection = new SetValue(new HashSet<>(Arrays.asList(1, 2, 3)));
FilterCollectionExpression expression =
new FilterCollectionExpression(collection, lt(ref(ValueReferences.ITERATOR_REF), value(2)));
- CollectionValue> filtered = expression.evaluate(RefResolverHelper.createResolver(this));
+ CollectionValue> filtered = expression.evaluate(evalContext);
assertNotEquals(collection, filtered);
assertEquals(1, filtered.count());
assertFalse(filtered.isEmpty());
@@ -211,7 +240,7 @@ void testEmptySet() {
SetValue collection = new SetValue(new HashSet<>());
FilterCollectionExpression expression =
new FilterCollectionExpression(collection, lt(ref(ValueReferences.ITERATOR_REF), value(2)));
- CollectionValue> filtered = expression.evaluate(RefResolverHelper.createResolver(this));
+ CollectionValue> filtered = expression.evaluate(evalContext);
assertNotEquals(collection, filtered);
assertTrue(filtered.isEmpty());
assertFalse(filtered.isNull());
@@ -225,9 +254,7 @@ void testNullSet() {
FilterCollectionExpression expression =
new FilterCollectionExpression(collection, lt(ref(ValueReferences.ITERATOR_REF), value(2)));
EvaluationException exception =
- assertThrows(
- EvaluationException.class,
- () -> expression.evaluate(RefResolverHelper.createResolver(this)));
+ assertThrows(EvaluationException.class, () -> expression.evaluate(evalContext));
assertEquals("Cannot evaluate the expression for null value", exception.getMessage());
assertEquals("filter(null, {@it < 2})", print(expression));
}
@@ -238,9 +265,7 @@ void testNullObjectSet() {
FilterCollectionExpression expression =
new FilterCollectionExpression(collection, lt(ref(ValueReferences.ITERATOR_REF), value(2)));
EvaluationException exception =
- assertThrows(
- EvaluationException.class,
- () -> expression.evaluate(RefResolverHelper.createResolver(this)));
+ assertThrows(EvaluationException.class, () -> expression.evaluate(evalContext));
assertEquals("Cannot evaluate the expression for null value", exception.getMessage());
assertEquals("filter(null, {@it < 2})", print(expression));
}
@@ -251,13 +276,28 @@ void testUndefinedSet() {
FilterCollectionExpression expression =
new FilterCollectionExpression(collection, lt(ref(ValueReferences.ITERATOR_REF), value(2)));
EvaluationException exception =
- assertThrows(
- EvaluationException.class,
- () -> expression.evaluate(RefResolverHelper.createResolver(this)));
+ assertThrows(EvaluationException.class, () -> expression.evaluate(evalContext));
assertEquals("Cannot evaluate the expression for undefined value", exception.getMessage());
assertEquals("filter(null, {@it < 2})", print(expression));
}
+ @Test
+ void testLargeSet() {
+ Set set = new HashSet<>();
+ for (int i = 0; i <= 1_000_000; i++) {
+ set.add(i);
+ }
+ SetValue collection = new SetValue(set);
+
+ FilterCollectionExpression expression =
+ new FilterCollectionExpression(collection, lt(ref(ValueReferences.ITERATOR_REF), value(0)));
+ EvalContext timeoutEvalContext = createEvalContext(this, Duration.ofMillis(1));
+ EvaluationException exception =
+ assertThrows(EvaluationException.class, () -> expression.evaluate(timeoutEvalContext));
+ assertEquals("timeout (1ms)", exception.getMessage());
+ assertEquals("filter(Set, {@it < 0})", print(expression));
+ }
+
@Test
void testUnsupportedList() {
ListValue collection = new ListValue(new CustomList());
@@ -265,9 +305,7 @@ void testUnsupportedList() {
new FilterCollectionExpression(
collection, eq(ref(ValueReferences.ITERATOR_REF), value("foo")));
EvaluationException exception =
- assertThrows(
- EvaluationException.class,
- () -> expression.evaluate(RefResolverHelper.createResolver(this)));
+ assertThrows(EvaluationException.class, () -> expression.evaluate(evalContext));
assertEquals(
"Unsupported List class: com.datadog.debugger.el.expressions.FilterCollectionExpressionTest$CustomList",
exception.getMessage());
@@ -280,9 +318,7 @@ void testUnsupportedMap() {
FilterCollectionExpression expression =
new FilterCollectionExpression(collection, eq(ref(ValueReferences.VALUE_REF), value(2)));
EvaluationException exception =
- assertThrows(
- EvaluationException.class,
- () -> expression.evaluate(RefResolverHelper.createResolver(this)));
+ assertThrows(EvaluationException.class, () -> expression.evaluate(evalContext));
assertEquals(
"Unsupported Map class: com.datadog.debugger.el.expressions.FilterCollectionExpressionTest$CustomMap",
exception.getMessage());
@@ -296,9 +332,7 @@ void testUnsupportedSet() {
new FilterCollectionExpression(
collection, eq(ref(ValueReferences.ITERATOR_REF), value("foo")));
EvaluationException exception =
- assertThrows(
- EvaluationException.class,
- () -> expression.evaluate(RefResolverHelper.createResolver(this)));
+ assertThrows(EvaluationException.class, () -> expression.evaluate(evalContext));
assertEquals(
"Unsupported Set class: com.datadog.debugger.el.expressions.FilterCollectionExpressionTest$CustomSet",
exception.getMessage());
diff --git a/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/expressions/GetMemberExpressionTest.java b/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/expressions/GetMemberExpressionTest.java
index 088c6b7bae4..6d2263b67da 100644
--- a/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/expressions/GetMemberExpressionTest.java
+++ b/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/expressions/GetMemberExpressionTest.java
@@ -1,5 +1,6 @@
package com.datadog.debugger.el.expressions;
+import static com.datadog.debugger.el.EvalContextHelper.createEvalContext;
import static com.datadog.debugger.el.PrettyPrintVisitor.print;
import static com.datadog.debugger.el.TestHelper.setFieldInConfig;
import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -8,7 +9,6 @@
import static org.junit.jupiter.api.Assertions.assertThrows;
import com.datadog.debugger.el.RedactedException;
-import com.datadog.debugger.el.RefResolverHelper;
import com.datadog.debugger.el.Value;
import datadog.trace.api.Config;
import datadog.trace.bootstrap.debugger.util.Redaction;
@@ -16,13 +16,12 @@
import org.junit.jupiter.api.Test;
class GetMemberExpressionTest {
-
@Test
void getMemberLevel1() {
GetMemberExpression expr = new GetMemberExpression(new ValueRefExpression("ref"), "b");
ObjectWithRefAndValue parent = new ObjectWithRefAndValue(null, "hello");
ExObjectWithRefAndValue instance = new ExObjectWithRefAndValue(parent, "world");
- Value> val = expr.evaluate(RefResolverHelper.createResolver(instance));
+ Value> val = expr.evaluate(createEvalContext(instance));
assertNotNull(val);
assertFalse(val.isUndefined());
assertEquals(parent.getB(), val.getValue());
@@ -37,7 +36,7 @@ void getMemberLevel2() {
ObjectWithRefAndValue root = new ObjectWithRefAndValue(null, "hello");
ObjectWithRefAndValue parent = new ObjectWithRefAndValue(root, "");
ExObjectWithRefAndValue instance = new ExObjectWithRefAndValue(parent, "world");
- Value> val = expr.evaluate(RefResolverHelper.createResolver(instance));
+ Value> val = expr.evaluate(createEvalContext(instance));
assertNotNull(val);
assertFalse(val.isUndefined());
assertEquals(root.getB(), val.getValue());
@@ -47,7 +46,7 @@ void getMemberLevel2() {
@Test
void getMemberUndefined() {
GetMemberExpression expr = new GetMemberExpression(ValueExpression.UNDEFINED, "size");
- assertEquals(Value.undefined(), expr.evaluate(RefResolverHelper.createResolver(this)));
+ assertEquals(Value.undefined(), expr.evaluate(createEvalContext(this)));
}
class StoreSecret {
@@ -73,9 +72,7 @@ void redacted() {
GetMemberExpression expr = new GetMemberExpression(new ValueRefExpression("store"), "password");
Holder instance = new Holder(new StoreSecret("secret123"));
RedactedException redactedException =
- assertThrows(
- RedactedException.class,
- () -> expr.evaluate(RefResolverHelper.createResolver(instance)));
+ assertThrows(RedactedException.class, () -> expr.evaluate(createEvalContext(instance)));
assertEquals(
"Could not evaluate the expression because 'store.password' was redacted",
redactedException.getMessage());
@@ -93,9 +90,7 @@ void redactedType() {
GetMemberExpression expr = new GetMemberExpression(new ValueRefExpression("store"), "str");
Holder instance = new Holder(new StoreSecret("secret123"));
RedactedException redactedException =
- assertThrows(
- RedactedException.class,
- () -> expr.evaluate(RefResolverHelper.createResolver(instance)));
+ assertThrows(RedactedException.class, () -> expr.evaluate(createEvalContext(instance)));
assertEquals(
"Could not evaluate the expression because 'store' was redacted",
redactedException.getMessage());
@@ -115,13 +110,13 @@ class Holder {
}
GetMemberExpression expr =
new GetMemberExpression(new ValueRefExpression("strPrimitive"), "uuid");
- Value> val = expr.evaluate(RefResolverHelper.createResolver(new Holder()));
+ Value> val = expr.evaluate(createEvalContext(new Holder()));
assertNotNull(val);
assertFalse(val.isUndefined());
assertEquals("123e4567-e89b-12d3-a456-426655440000", val.getValue());
assertEquals("strPrimitive.uuid", print(expr));
expr = new GetMemberExpression(new ValueRefExpression("strPrimitive"), "clazz");
- val = expr.evaluate(RefResolverHelper.createResolver(new Holder()));
+ val = expr.evaluate(createEvalContext(new Holder()));
assertNotNull(val);
assertFalse(val.isUndefined());
assertEquals("java.lang.String", val.getValue());
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 3b4f69ef0b8..0566d3537aa 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
@@ -1,24 +1,27 @@
package com.datadog.debugger.el.expressions;
import static com.datadog.debugger.el.DSL.*;
+import static com.datadog.debugger.el.EvalContextHelper.createEvalContext;
import static com.datadog.debugger.el.PrettyPrintVisitor.print;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
+import com.datadog.debugger.el.EvalContext;
import com.datadog.debugger.el.EvaluationException;
-import com.datadog.debugger.el.RefResolverHelper;
import com.datadog.debugger.el.values.ListValue;
import com.datadog.debugger.el.values.MapValue;
import com.datadog.debugger.el.values.SetValue;
-import datadog.trace.bootstrap.debugger.el.ValueReferenceResolver;
import datadog.trace.bootstrap.debugger.el.ValueReferences;
import datadog.trace.bootstrap.debugger.el.Values;
+import java.time.Duration;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.List;
import java.util.Map;
import java.util.Set;
import org.junit.jupiter.api.Test;
@@ -26,83 +29,83 @@
class HasAllExpressionTest {
private final int testField = 10;
+ EvalContext evalContext = createEvalContext(this);
+
@Test
void testNullPredicate() {
- ValueReferenceResolver resolver = RefResolverHelper.createResolver(this);
HasAllExpression nullExpression = new HasAllExpression(null, null);
EvaluationException exception =
- assertThrows(EvaluationException.class, () -> nullExpression.evaluate(resolver));
+ assertThrows(EvaluationException.class, () -> nullExpression.evaluate(evalContext));
assertEquals("Cannot evaluate the expression for null value", exception.getMessage());
assertEquals("all(null, {true})", print(nullExpression));
HasAllExpression undefinedExpression =
new HasAllExpression(value(Values.UNDEFINED_OBJECT), null);
exception =
- assertThrows(EvaluationException.class, () -> undefinedExpression.evaluate(resolver));
+ assertThrows(EvaluationException.class, () -> undefinedExpression.evaluate(evalContext));
assertEquals("Cannot evaluate the expression for undefined value", exception.getMessage());
assertEquals("all(UNDEFINED, {true})", print(undefinedExpression));
HasAllExpression expression = new HasAllExpression(value(new Object[] {this}), null);
- assertTrue(expression.evaluate(resolver));
+ assertTrue(expression.evaluate(evalContext));
assertEquals("all(java.lang.Object[], {true})", print(expression));
expression = new HasAllExpression(value(Collections.singletonList(this)), null);
- assertTrue(expression.evaluate(resolver));
+ assertTrue(expression.evaluate(evalContext));
assertEquals("all(List, {true})", print(expression));
expression = new HasAllExpression(value(Collections.singletonMap(this, this)), null);
- assertTrue(expression.evaluate(resolver));
+ assertTrue(expression.evaluate(evalContext));
assertEquals("all(Map, {true})", print(expression));
}
@Test
void testNullHasAll() {
- ValueReferenceResolver ctx = RefResolverHelper.createResolver(this);
HasAllExpression nullExpression1 = all(null, TRUE);
EvaluationException exception =
- assertThrows(EvaluationException.class, () -> nullExpression1.evaluate(ctx));
+ assertThrows(EvaluationException.class, () -> nullExpression1.evaluate(evalContext));
assertEquals("Cannot evaluate the expression for null value", exception.getMessage());
assertEquals("all(null, {true})", print(nullExpression1));
HasAllExpression nullExpression2 = all(null, FALSE);
- exception = assertThrows(EvaluationException.class, () -> nullExpression2.evaluate(ctx));
+ exception =
+ assertThrows(EvaluationException.class, () -> nullExpression2.evaluate(evalContext));
assertEquals("Cannot evaluate the expression for null value", exception.getMessage());
assertEquals("all(null, {false})", print(nullExpression2));
HasAllExpression nullExpression3 = all(null, eq(ref("testField"), value(10)));
- exception = assertThrows(EvaluationException.class, () -> nullExpression3.evaluate(ctx));
+ exception =
+ assertThrows(EvaluationException.class, () -> nullExpression3.evaluate(evalContext));
assertEquals("Cannot evaluate the expression for null value", exception.getMessage());
assertEquals("all(null, {testField == 10})", print(nullExpression3));
}
@Test
void testUndefinedHasAll() {
- ValueReferenceResolver ctx = RefResolverHelper.createResolver(this);
HasAllExpression undefinedExpression = all(value(Values.UNDEFINED_OBJECT), TRUE);
EvaluationException exception =
- assertThrows(EvaluationException.class, () -> undefinedExpression.evaluate(ctx));
+ assertThrows(EvaluationException.class, () -> undefinedExpression.evaluate(evalContext));
assertEquals("Cannot evaluate the expression for undefined value", exception.getMessage());
assertEquals("all(UNDEFINED, {true})", print(undefinedExpression));
HasAllExpression nullExpression = all(null, FALSE);
- exception = assertThrows(EvaluationException.class, () -> nullExpression.evaluate(ctx));
+ exception = assertThrows(EvaluationException.class, () -> nullExpression.evaluate(evalContext));
assertEquals("Cannot evaluate the expression for null value", exception.getMessage());
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));
+ exception = assertThrows(EvaluationException.class, () -> expression.evaluate(evalContext));
assertEquals("Cannot evaluate the expression for undefined value", exception.getMessage());
assertEquals("all(UNDEFINED, {testField == 10})", print(expression));
}
@Test
void testArrayHasAll() {
- ValueReferenceResolver ctx = RefResolverHelper.createResolver(this);
ValueExpression> targetExpression = value(new Object[] {this, "hello"});
HasAllExpression expression = all(targetExpression, TRUE);
- assertTrue(expression.evaluate(ctx));
+ assertTrue(expression.evaluate(evalContext));
assertEquals("all(java.lang.Object[], {true})", print(expression));
expression = all(targetExpression, FALSE);
- assertFalse(expression.evaluate(ctx));
+ assertFalse(expression.evaluate(evalContext));
assertEquals("all(java.lang.Object[], {false})", print(expression));
GetMemberExpression fldRef = getMember(ref(ValueReferences.ITERATOR_REF), "testField");
@@ -111,29 +114,28 @@ void testArrayHasAll() {
RuntimeException runtimeException =
assertThrows(
RuntimeException.class,
- () -> all(targetExpression, eq(fldRef, value(10))).evaluate(ctx));
+ () -> all(targetExpression, eq(fldRef, value(10))).evaluate(evalContext));
assertEquals("Cannot dereference field: testField", runtimeException.getMessage());
expression = all(targetExpression, eq(itRef, value("hello")));
- assertFalse(expression.evaluate(ctx));
+ assertFalse(expression.evaluate(evalContext));
assertEquals("all(java.lang.Object[], {@it == \"hello\"})", print(expression));
expression = all(targetExpression, not(isEmpty(itRef)));
- assertTrue(expression.evaluate(ctx));
+ assertTrue(expression.evaluate(evalContext));
assertEquals("all(java.lang.Object[], {not(isEmpty(@it))})", print(expression));
}
@Test
void testListHasAll() {
- ValueReferenceResolver ctx = RefResolverHelper.createResolver(this);
ValueExpression> targetExpression = value(Arrays.asList(this, "hello"));
HasAllExpression expression = all(targetExpression, TRUE);
- assertTrue(expression.evaluate(ctx));
+ assertTrue(expression.evaluate(evalContext));
assertEquals("all(List, {true})", print(expression));
expression = all(targetExpression, FALSE);
- assertFalse(expression.evaluate(ctx));
+ assertFalse(expression.evaluate(evalContext));
assertEquals("all(List, {false})", print(expression));
ValueRefExpression fldRef = ref(ValueReferences.ITERATOR_REF + "testField");
@@ -142,21 +144,36 @@ void testListHasAll() {
RuntimeException runtimeException =
assertThrows(
RuntimeException.class,
- () -> all(targetExpression, eq(fldRef, value(10))).evaluate(ctx));
+ () -> all(targetExpression, eq(fldRef, value(10))).evaluate(evalContext));
assertEquals("Cannot find synthetic var: ittestField", runtimeException.getMessage());
expression = all(targetExpression, eq(itRef, value("hello")));
- assertFalse(expression.evaluate(ctx));
+ assertFalse(expression.evaluate(evalContext));
assertEquals("all(List, {@it == \"hello\"})", print(expression));
expression = all(targetExpression, not(isEmpty(itRef)));
- assertTrue(expression.evaluate(ctx));
+ assertTrue(expression.evaluate(evalContext));
assertEquals("all(List, {not(isEmpty(@it))})", print(expression));
}
+ @Test
+ void testLargeListHasAll() {
+ List largeList = new ArrayList<>();
+ for (int i = 0; i < 1_000_000; i++) {
+ largeList.add(i);
+ }
+ ValueExpression> targetExpression = value(largeList);
+
+ HasAllExpression expression = all(targetExpression, TRUE);
+ EvalContext timeoutEvalContext = createEvalContext(this, Duration.ofMillis(1));
+ EvaluationException evaluationException =
+ assertThrows(EvaluationException.class, () -> expression.evaluate(timeoutEvalContext));
+ assertEquals("timeout (1ms)", evaluationException.getMessage());
+ assertEquals("all(List, {true})", print(expression));
+ }
+
@Test
void testMapHasAll() {
- ValueReferenceResolver ctx = RefResolverHelper.createResolver(null, null);
Map valueMap = new HashMap<>();
valueMap.put("a", "a");
valueMap.put("b", "a");
@@ -164,29 +181,44 @@ void testMapHasAll() {
ValueExpression> targetExpression = value(valueMap);
HasAllExpression expression = all(targetExpression, TRUE);
- assertTrue(expression.evaluate(ctx));
+ assertTrue(expression.evaluate(evalContext));
assertEquals("all(Map, {true})", print(expression));
expression = all(targetExpression, FALSE);
- assertFalse(expression.evaluate(ctx));
+ assertFalse(expression.evaluate(evalContext));
assertEquals("all(Map, {false})", print(expression));
expression =
all(targetExpression, eq(getMember(ref(ValueReferences.ITERATOR_REF), "key"), value("a")));
- assertFalse(expression.evaluate(ctx));
+ assertFalse(expression.evaluate(evalContext));
assertEquals("all(Map, {@it.key == \"a\"})", print(expression));
expression =
all(
targetExpression,
eq(getMember(ref(ValueReferences.ITERATOR_REF), "value"), value("a")));
- assertTrue(expression.evaluate(ctx));
+ assertTrue(expression.evaluate(evalContext));
assertEquals("all(Map, {@it.value == \"a\"})", print(expression));
}
+ @Test
+ void testLargeMapHasAll() {
+ Map largeMap = new HashMap<>();
+ for (int i = 0; i < 1_000_000; i++) {
+ largeMap.put(i, i);
+ }
+ ValueExpression> targetExpression = value(largeMap);
+
+ HasAllExpression expression = all(targetExpression, TRUE);
+ EvalContext timeoutEvalContext = createEvalContext(this, Duration.ofMillis(1));
+ EvaluationException evaluationException =
+ assertThrows(EvaluationException.class, () -> expression.evaluate(timeoutEvalContext));
+ assertEquals("timeout (1ms)", evaluationException.getMessage());
+ assertEquals("all(Map, {true})", print(expression));
+ }
+
@Test
void testSetHasAll() {
- ValueReferenceResolver ctx = RefResolverHelper.createResolver(null, null);
Set valueSet = new HashSet<>();
valueSet.add("foo");
valueSet.add("bar");
@@ -194,15 +226,15 @@ void testSetHasAll() {
ValueExpression> targetExpression = value(valueSet);
HasAllExpression expression = all(targetExpression, TRUE);
- assertTrue(expression.evaluate(ctx));
+ assertTrue(expression.evaluate(evalContext));
assertEquals("all(Set, {true})", print(expression));
expression = all(targetExpression, FALSE);
- assertFalse(expression.evaluate(ctx));
+ assertFalse(expression.evaluate(evalContext));
assertEquals("all(Set, {false})", print(expression));
expression = all(targetExpression, eq(ref(ValueReferences.ITERATOR_REF), value("key")));
- assertFalse(expression.evaluate(ctx));
+ assertFalse(expression.evaluate(evalContext));
assertEquals("all(Set, {@it == \"key\"})", print(expression));
expression =
@@ -211,48 +243,61 @@ void testSetHasAll() {
or(
eq(ref(ValueReferences.ITERATOR_REF), value("foo")),
eq(ref(ValueReferences.ITERATOR_REF), value("bar"))));
- assertTrue(expression.evaluate(ctx));
+ assertTrue(expression.evaluate(evalContext));
assertEquals("all(Set, {@it == \"foo\" || @it == \"bar\"})", print(expression));
}
+ @Test
+ void testLargeSetHasAll() {
+ Set largeSet = new HashSet<>();
+ for (int i = 0; i < 1_000_000; i++) {
+ largeSet.add(i);
+ }
+ ValueExpression> targetExpression = value(largeSet);
+
+ HasAllExpression expression = all(targetExpression, TRUE);
+ EvalContext timeoutEvalContext = createEvalContext(this, Duration.ofMillis(1));
+ EvaluationException evaluationException =
+ assertThrows(EvaluationException.class, () -> expression.evaluate(timeoutEvalContext));
+ assertEquals("timeout (1ms)", evaluationException.getMessage());
+ assertEquals("all(Set, {true})", print(expression));
+ }
+
@Test
void emptiness() {
- ValueReferenceResolver ctx = RefResolverHelper.createResolver(null, null);
HasAllExpression expression = all(value(new String[] {}), TRUE);
- assertTrue(expression.evaluate(ctx));
+ assertTrue(expression.evaluate(evalContext));
expression = all(value(Collections.emptyList()), TRUE);
- assertTrue(expression.evaluate(ctx));
+ assertTrue(expression.evaluate(evalContext));
expression = all(value(Collections.emptyMap()), TRUE);
- assertTrue(expression.evaluate(ctx));
+ assertTrue(expression.evaluate(evalContext));
expression = all(value(Collections.emptySet()), TRUE);
- assertTrue(expression.evaluate(ctx));
+ assertTrue(expression.evaluate(evalContext));
}
@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));
+ assertFalse(expression.evaluate(evalContext));
assertEquals("all(Map, {@key == \"a\"})", print(expression));
expression = all(targetExpression, eq(ref(ValueReferences.VALUE_REF), value("a")));
- assertTrue(expression.evaluate(ctx));
+ assertTrue(expression.evaluate(evalContext));
assertEquals("all(Map, {@value == \"a\"})", print(expression));
}
@Test
void testUnsupportedList() {
- ValueReferenceResolver ctx = RefResolverHelper.createResolver(null, null);
ListValue collection = new ListValue(new CustomList());
HasAllExpression expression =
all(collection, eq(ref(ValueReferences.ITERATOR_REF), value("foo")));
EvaluationException exception =
- assertThrows(EvaluationException.class, () -> expression.evaluate(ctx));
+ assertThrows(EvaluationException.class, () -> expression.evaluate(evalContext));
assertEquals(
"Unsupported List class: com.datadog.debugger.el.expressions.HasAllExpressionTest$CustomList",
exception.getMessage());
@@ -261,11 +306,10 @@ void testUnsupportedList() {
@Test
void testUnsupportedMap() {
- ValueReferenceResolver ctx = RefResolverHelper.createResolver(null, null);
MapValue collection = new MapValue(new CustomMap());
HasAllExpression expression = all(collection, eq(ref(ValueReferences.VALUE_REF), value("foo")));
EvaluationException exception =
- assertThrows(EvaluationException.class, () -> expression.evaluate(ctx));
+ assertThrows(EvaluationException.class, () -> expression.evaluate(evalContext));
assertEquals(
"Unsupported Map class: com.datadog.debugger.el.expressions.HasAllExpressionTest$CustomMap",
exception.getMessage());
@@ -274,12 +318,11 @@ void testUnsupportedMap() {
@Test
void testUnsupportedSet() {
- ValueReferenceResolver ctx = RefResolverHelper.createResolver(null, null);
SetValue collection = new SetValue(new CustomSet());
HasAllExpression expression =
all(collection, eq(ref(ValueReferences.ITERATOR_REF), value("foo")));
EvaluationException exception =
- assertThrows(EvaluationException.class, () -> expression.evaluate(ctx));
+ assertThrows(EvaluationException.class, () -> expression.evaluate(evalContext));
assertEquals(
"Unsupported Set class: com.datadog.debugger.el.expressions.HasAllExpressionTest$CustomSet",
exception.getMessage());
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 8a5ca4fa9cf..8d706b7b326 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
@@ -1,255 +1,300 @@
package com.datadog.debugger.el.expressions;
import static com.datadog.debugger.el.DSL.*;
+import static com.datadog.debugger.el.DSL.value;
+import static com.datadog.debugger.el.EvalContextHelper.createEvalContext;
import static com.datadog.debugger.el.PrettyPrintVisitor.print;
import static org.junit.jupiter.api.Assertions.*;
-import com.datadog.debugger.el.DSL;
+import com.datadog.debugger.el.EvalContext;
import com.datadog.debugger.el.EvaluationException;
-import com.datadog.debugger.el.RefResolverHelper;
import com.datadog.debugger.el.values.ListValue;
import com.datadog.debugger.el.values.MapValue;
import com.datadog.debugger.el.values.SetValue;
-import datadog.trace.bootstrap.debugger.el.ValueReferenceResolver;
import datadog.trace.bootstrap.debugger.el.ValueReferences;
import datadog.trace.bootstrap.debugger.el.Values;
+import java.time.Duration;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.List;
import java.util.Map;
import java.util.Set;
import org.junit.jupiter.api.Test;
class HasAnyExpressionTest {
private final int testField = 10;
+ EvalContext evalContext = createEvalContext(this);
@Test
void testNullPredicate() {
- ValueReferenceResolver resolver = RefResolverHelper.createResolver(this);
HasAnyExpression nullExpression = new HasAnyExpression(null, null);
EvaluationException exception =
- assertThrows(EvaluationException.class, () -> nullExpression.evaluate(resolver));
+ assertThrows(EvaluationException.class, () -> nullExpression.evaluate(evalContext));
assertEquals("Cannot evaluate the expression for null value", exception.getMessage());
assertEquals("any(null, {true})", print(nullExpression));
HasAnyExpression undefinedExpression =
new HasAnyExpression(value(Values.UNDEFINED_OBJECT), null);
exception =
- assertThrows(EvaluationException.class, () -> undefinedExpression.evaluate(resolver));
+ assertThrows(EvaluationException.class, () -> undefinedExpression.evaluate(evalContext));
assertEquals("Cannot evaluate the expression for undefined value", exception.getMessage());
assertEquals("any(UNDEFINED, {true})", print(undefinedExpression));
HasAnyExpression expression = new HasAnyExpression(value(new Object[] {this}), null);
- assertTrue(expression.evaluate(resolver));
+ assertTrue(expression.evaluate(evalContext));
assertEquals("any(java.lang.Object[], {true})", print(expression));
expression = new HasAnyExpression(value(Collections.singletonList(this)), null);
- assertTrue(expression.evaluate(resolver));
+ assertTrue(expression.evaluate(evalContext));
assertEquals("any(List, {true})", print(expression));
expression = new HasAnyExpression(value(Collections.singletonMap(this, this)), null);
- assertTrue(expression.evaluate(resolver));
+ assertTrue(expression.evaluate(evalContext));
assertEquals("any(Map, {true})", print(expression));
}
@Test
void testNullHasAny() {
- ValueReferenceResolver ctx = RefResolverHelper.createResolver(this);
HasAnyExpression nullExpression1 = any(null, BooleanExpression.TRUE);
EvaluationException exception =
- assertThrows(EvaluationException.class, () -> nullExpression1.evaluate(ctx));
+ assertThrows(EvaluationException.class, () -> nullExpression1.evaluate(evalContext));
assertEquals("Cannot evaluate the expression for null value", exception.getMessage());
assertEquals("any(null, {true})", print(nullExpression1));
HasAnyExpression nullExpression2 = any(null, BooleanExpression.FALSE);
- exception = assertThrows(EvaluationException.class, () -> nullExpression2.evaluate(ctx));
+ exception =
+ assertThrows(EvaluationException.class, () -> nullExpression2.evaluate(evalContext));
assertEquals("Cannot evaluate the expression for null value", exception.getMessage());
assertEquals("any(null, {false})", print(nullExpression2));
HasAnyExpression nullExpression3 = any(null, eq(ref("testField"), value(10)));
- exception = assertThrows(EvaluationException.class, () -> nullExpression3.evaluate(ctx));
+ exception =
+ assertThrows(EvaluationException.class, () -> nullExpression3.evaluate(evalContext));
assertEquals("Cannot evaluate the expression for null value", exception.getMessage());
assertEquals("any(null, {testField == 10})", print(nullExpression3));
}
@Test
void testUndefinedHasAny() {
- ValueReferenceResolver ctx = RefResolverHelper.createResolver(this);
HasAnyExpression undefinedExpression = any(value(Values.UNDEFINED_OBJECT), TRUE);
EvaluationException exception =
- assertThrows(EvaluationException.class, () -> undefinedExpression.evaluate(ctx));
+ assertThrows(EvaluationException.class, () -> undefinedExpression.evaluate(evalContext));
assertEquals("Cannot evaluate the expression for undefined value", exception.getMessage());
assertEquals("any(UNDEFINED, {true})", print(undefinedExpression));
HasAnyExpression nullExpression = any(null, FALSE);
- exception = assertThrows(EvaluationException.class, () -> nullExpression.evaluate(ctx));
+ exception = assertThrows(EvaluationException.class, () -> nullExpression.evaluate(evalContext));
assertEquals("Cannot evaluate the expression for null value", exception.getMessage());
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));
+ exception =
+ assertThrows(EvaluationException.class, () -> undefinedExpression2.evaluate(evalContext));
assertEquals("Cannot evaluate the expression for undefined value", exception.getMessage());
assertEquals("any(UNDEFINED, {testField == 10})", print(undefinedExpression2));
}
@Test
void testArrayHasAny() {
- ValueReferenceResolver ctx = RefResolverHelper.createResolver(null, null);
- ValueExpression> targetExpression = DSL.value(new Object[] {this, "hello"});
+ ValueExpression> targetExpression = value(new Object[] {this, "hello"});
HasAnyExpression expression = any(targetExpression, TRUE);
- assertTrue(expression.evaluate(ctx));
+ assertTrue(expression.evaluate(evalContext));
assertEquals("any(java.lang.Object[], {true})", print(expression));
expression = any(targetExpression, FALSE);
- assertFalse(expression.evaluate(ctx));
+ assertFalse(expression.evaluate(evalContext));
assertEquals("any(java.lang.Object[], {false})", print(expression));
expression =
any(
targetExpression,
eq(getMember(ref(ValueReferences.ITERATOR_REF), "testField"), value(10)));
- assertTrue(expression.evaluate(ctx));
+ assertTrue(expression.evaluate(evalContext));
assertEquals("any(java.lang.Object[], {@it.testField == 10})", print(expression));
expression = any(targetExpression, eq(ref(ValueReferences.ITERATOR_REF), value("hello")));
- assertTrue(expression.evaluate(ctx));
+ assertTrue(expression.evaluate(evalContext));
assertEquals("any(java.lang.Object[], {@it == \"hello\"})", print(expression));
}
@Test
void testListHasAny() {
- ValueReferenceResolver ctx = RefResolverHelper.createResolver(null, null);
- ValueExpression> targetExpression = DSL.value(Arrays.asList(this, "hello"));
+ ValueExpression> targetExpression = value(Arrays.asList(this, "hello"));
HasAnyExpression expression = any(targetExpression, TRUE);
- assertTrue(expression.evaluate(ctx));
+ assertTrue(expression.evaluate(evalContext));
assertEquals("any(List, {true})", print(expression));
expression = any(targetExpression, FALSE);
- assertFalse(expression.evaluate(ctx));
+ assertFalse(expression.evaluate(evalContext));
assertEquals("any(List, {false})", print(expression));
expression =
any(
targetExpression,
eq(getMember(ref(ValueReferences.ITERATOR_REF), "testField"), value(10)));
- assertTrue(expression.evaluate(ctx));
+ assertTrue(expression.evaluate(evalContext));
assertEquals("any(List, {@it.testField == 10})", print(expression));
expression = any(targetExpression, eq(ref(ValueReferences.ITERATOR_REF), value("hello")));
- assertTrue(expression.evaluate(ctx));
+ assertTrue(expression.evaluate(evalContext));
assertEquals("any(List, {@it == \"hello\"})", print(expression));
}
+ @Test
+ void testLargeListHasAny() {
+ List largeList = new ArrayList<>();
+ for (int i = 0; i < 1_000_000; i++) {
+ largeList.add(i);
+ }
+ ValueExpression> targetExpression = value(largeList);
+
+ HasAnyExpression expression = any(targetExpression, FALSE);
+ EvalContext timeoutEvalContext = createEvalContext(this, Duration.ofMillis(1));
+ EvaluationException evaluationException =
+ assertThrows(EvaluationException.class, () -> expression.evaluate(timeoutEvalContext));
+ assertEquals("timeout (1ms)", evaluationException.getMessage());
+ assertEquals("any(List, {false})", print(expression));
+ }
+
@Test
void testMapHasAny() {
- ValueReferenceResolver ctx = RefResolverHelper.createResolver(null, null);
Map valueMap = new HashMap<>();
valueMap.put("a", "a");
valueMap.put("b", null);
- ValueExpression> targetExpression = DSL.value(valueMap);
+ ValueExpression> targetExpression = value(valueMap);
HasAnyExpression expression = any(targetExpression, TRUE);
- assertTrue(expression.evaluate(ctx));
+ assertTrue(expression.evaluate(evalContext));
assertEquals("any(Map, {true})", print(expression));
expression = any(targetExpression, FALSE);
- assertFalse(expression.evaluate(ctx));
+ assertFalse(expression.evaluate(evalContext));
assertEquals("any(Map, {false})", print(expression));
expression =
any(targetExpression, eq(getMember(ref(ValueReferences.ITERATOR_REF), "key"), value("b")));
- assertTrue(expression.evaluate(ctx));
+ assertTrue(expression.evaluate(evalContext));
assertEquals("any(Map, {@it.key == \"b\"})", print(expression));
expression =
any(
targetExpression,
eq(getMember(ref(ValueReferences.ITERATOR_REF), "value"), value("a")));
- assertTrue(expression.evaluate(ctx));
+ assertTrue(expression.evaluate(evalContext));
assertEquals("any(Map, {@it.value == \"a\"})", print(expression));
expression =
any(targetExpression, eq(getMember(ref(ValueReferences.ITERATOR_REF), "key"), value("c")));
- assertFalse(expression.evaluate(ctx));
+ assertFalse(expression.evaluate(evalContext));
assertEquals("any(Map, {@it.key == \"c\"})", print(expression));
expression =
any(
targetExpression,
eq(getMember(ref(ValueReferences.ITERATOR_REF), "value"), value("c")));
- assertFalse(expression.evaluate(ctx));
+ assertFalse(expression.evaluate(evalContext));
assertEquals("any(Map, {@it.value == \"c\"})", print(expression));
}
+ @Test
+ void testLargeMapHasAny() {
+ Map largeMap = new HashMap<>();
+ for (int i = 0; i < 1_000_000; i++) {
+ largeMap.put(i, i);
+ }
+ ValueExpression> targetExpression = value(largeMap);
+
+ HasAnyExpression expression = any(targetExpression, FALSE);
+ EvalContext timeoutEvalContext = createEvalContext(this, Duration.ofMillis(1));
+ EvaluationException evaluationException =
+ assertThrows(EvaluationException.class, () -> expression.evaluate(timeoutEvalContext));
+ assertEquals("timeout (1ms)", evaluationException.getMessage());
+ assertEquals("any(Map, {false})", print(expression));
+ }
+
@Test
void testSetHasAny() {
- ValueReferenceResolver ctx = RefResolverHelper.createResolver(null, null);
Set valueSet = new HashSet<>();
valueSet.add("foo");
valueSet.add("bar");
- ValueExpression> targetExpression = DSL.value(valueSet);
+ ValueExpression> targetExpression = value(valueSet);
HasAnyExpression expression = any(targetExpression, TRUE);
- assertTrue(expression.evaluate(ctx));
+ assertTrue(expression.evaluate(evalContext));
assertEquals("any(Set, {true})", print(expression));
- targetExpression = DSL.value(valueSet);
+ targetExpression = value(valueSet);
expression = any(targetExpression, FALSE);
- assertFalse(expression.evaluate(ctx));
+ assertFalse(expression.evaluate(evalContext));
assertEquals("any(Set, {false})", print(expression));
expression = any(targetExpression, eq(ref(ValueReferences.ITERATOR_REF), value("foo")));
- assertTrue(expression.evaluate(ctx));
+ assertTrue(expression.evaluate(evalContext));
assertEquals("any(Set, {@it == \"foo\"})", print(expression));
expression = any(targetExpression, eq(ref(ValueReferences.ITERATOR_REF), value("key")));
- assertFalse(expression.evaluate(ctx));
+ assertFalse(expression.evaluate(evalContext));
assertEquals("any(Set, {@it == \"key\"})", print(expression));
}
+ @Test
+ void testLargeSetHasAny() {
+ Set largeSet = new HashSet<>();
+ for (int i = 0; i < 1_000_000; i++) {
+ largeSet.add(i);
+ }
+ ValueExpression> targetExpression = value(largeSet);
+
+ HasAnyExpression expression = any(targetExpression, FALSE);
+ EvalContext timeoutEvalContext = createEvalContext(this, Duration.ofMillis(1));
+ EvaluationException evaluationException =
+ assertThrows(EvaluationException.class, () -> expression.evaluate(timeoutEvalContext));
+ assertEquals("timeout (1ms)", evaluationException.getMessage());
+ assertEquals("any(Set, {false})", print(expression));
+ }
+
@Test
void emptiness() {
- ValueReferenceResolver ctx = RefResolverHelper.createResolver(null, null);
HasAnyExpression expression = any(value(Collections.emptyList()), TRUE);
- assertFalse(expression.evaluate(ctx));
+ assertFalse(expression.evaluate(evalContext));
assertEquals("any(List, {true})", print(expression));
expression = any(value(Collections.emptyMap()), TRUE);
- assertFalse(expression.evaluate(ctx));
+ assertFalse(expression.evaluate(evalContext));
assertEquals("any(Map, {true})", print(expression));
expression = any(value(Collections.emptySet()), TRUE);
- assertFalse(expression.evaluate(ctx));
+ assertFalse(expression.evaluate(evalContext));
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);
+ ValueExpression> targetExpression = value(valueMap);
HasAnyExpression expression =
any(targetExpression, eq(ref(ValueReferences.KEY_REF), value("b")));
- assertTrue(expression.evaluate(ctx));
+ assertTrue(expression.evaluate(evalContext));
assertEquals("any(Map, {@key == \"b\"})", print(expression));
expression = any(targetExpression, eq(ref(ValueReferences.VALUE_REF), value("a")));
- assertTrue(expression.evaluate(ctx));
+ assertTrue(expression.evaluate(evalContext));
assertEquals("any(Map, {@value == \"a\"})", print(expression));
}
@Test
void testUnsupportedList() {
- ValueReferenceResolver ctx = RefResolverHelper.createResolver(null, null);
ListValue collection = new ListValue(new CustomList());
HasAnyExpression expression =
any(collection, eq(ref(ValueReferences.ITERATOR_REF), value("foo")));
EvaluationException exception =
- assertThrows(EvaluationException.class, () -> expression.evaluate(ctx));
+ assertThrows(EvaluationException.class, () -> expression.evaluate(evalContext));
assertEquals(
"Unsupported List class: com.datadog.debugger.el.expressions.HasAnyExpressionTest$CustomList",
exception.getMessage());
@@ -258,11 +303,10 @@ void testUnsupportedList() {
@Test
void testUnsupportedMap() {
- ValueReferenceResolver ctx = RefResolverHelper.createResolver(null, null);
MapValue collection = new MapValue(new CustomMap());
HasAnyExpression expression = any(collection, eq(ref(ValueReferences.VALUE_REF), value("foo")));
EvaluationException exception =
- assertThrows(EvaluationException.class, () -> expression.evaluate(ctx));
+ assertThrows(EvaluationException.class, () -> expression.evaluate(evalContext));
assertEquals(
"Unsupported Map class: com.datadog.debugger.el.expressions.HasAnyExpressionTest$CustomMap",
exception.getMessage());
@@ -271,12 +315,11 @@ void testUnsupportedMap() {
@Test
void testUnsupportedSet() {
- ValueReferenceResolver ctx = RefResolverHelper.createResolver(null, null);
SetValue collection = new SetValue(new CustomSet());
HasAnyExpression expression =
any(collection, eq(ref(ValueReferences.ITERATOR_REF), value("foo")));
EvaluationException exception =
- assertThrows(EvaluationException.class, () -> expression.evaluate(ctx));
+ assertThrows(EvaluationException.class, () -> expression.evaluate(evalContext));
assertEquals(
"Unsupported Set class: com.datadog.debugger.el.expressions.HasAnyExpressionTest$CustomSet",
exception.getMessage());
diff --git a/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/expressions/IfElseExpressionTest.java b/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/expressions/IfElseExpressionTest.java
index f71cd714ee5..04492d597ac 100644
--- a/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/expressions/IfElseExpressionTest.java
+++ b/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/expressions/IfElseExpressionTest.java
@@ -1,15 +1,17 @@
package com.datadog.debugger.el.expressions;
+import static com.datadog.debugger.el.EvalContextHelper.createEvalContext;
import static org.junit.jupiter.api.Assertions.*;
import com.datadog.debugger.el.DSL;
+import com.datadog.debugger.el.EvalContext;
import com.datadog.debugger.el.Expression;
-import com.datadog.debugger.el.RefResolverHelper;
import com.datadog.debugger.el.values.BooleanValue;
import org.junit.jupiter.api.Test;
class IfElseExpressionTest {
private boolean guardFlag = false;
+ private EvalContext evalContext = createEvalContext(this);
@Test
void testIfTrue() {
@@ -26,7 +28,7 @@ void testIfTrue() {
return null;
};
IfElseExpression expression = DSL.doif(test, thenExpression, elseExpression);
- expression.evaluate(RefResolverHelper.createResolver(this));
+ expression.evaluate(evalContext);
assertTrue(executed[0]);
assertFalse(executed[1]);
}
@@ -45,7 +47,7 @@ void testIfFalse() {
executed[1] = true;
return null;
};
- DSL.doif(test, thenExpression, elseExpression).evaluate(RefResolverHelper.createResolver(this));
+ DSL.doif(test, thenExpression, elseExpression).evaluate(evalContext);
assertFalse(executed[0]);
assertTrue(executed[1]);
}
@@ -65,14 +67,14 @@ void testFromContext() {
return null;
};
guardFlag = false;
- DSL.doif(test, thenExpression, elseExpression).evaluate(RefResolverHelper.createResolver(this));
+ DSL.doif(test, thenExpression, elseExpression).evaluate(evalContext);
assertFalse(executed[0]);
assertTrue(executed[1]);
executed[1] = false;
guardFlag = true;
- DSL.doif(test, thenExpression, elseExpression).evaluate(RefResolverHelper.createResolver(this));
+ DSL.doif(test, thenExpression, elseExpression).evaluate(evalContext);
assertTrue(executed[0]);
assertFalse(executed[1]);
}
diff --git a/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/expressions/IfExpressionTest.java b/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/expressions/IfExpressionTest.java
index 59685f59690..cc009684627 100644
--- a/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/expressions/IfExpressionTest.java
+++ b/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/expressions/IfExpressionTest.java
@@ -1,16 +1,19 @@
package com.datadog.debugger.el.expressions;
+import static com.datadog.debugger.el.EvalContextHelper.createEvalContext;
import static org.junit.jupiter.api.Assertions.*;
import com.datadog.debugger.el.DSL;
+import com.datadog.debugger.el.EvalContext;
import com.datadog.debugger.el.Expression;
-import com.datadog.debugger.el.RefResolverHelper;
import com.datadog.debugger.el.values.BooleanValue;
import org.junit.jupiter.api.Test;
class IfExpressionTest {
private boolean guardFlag = false;
+ private EvalContext evalContext = createEvalContext(this);
+
@Test
void testIfTrue() {
boolean[] executed = new boolean[] {false};
@@ -20,7 +23,7 @@ void testIfTrue() {
executed[0] = true;
return null;
};
- DSL.doif(test, expression).evaluate(RefResolverHelper.createResolver(this));
+ DSL.doif(test, expression).evaluate(evalContext);
assertTrue(executed[0]);
}
@@ -33,7 +36,7 @@ void testIfFalse() {
executed[0] = true;
return null;
};
- DSL.doif(test, expression).evaluate(RefResolverHelper.createResolver(this));
+ DSL.doif(test, expression).evaluate(evalContext);
assertFalse(executed[0]);
}
@@ -47,11 +50,11 @@ void testFromContext() {
return null;
};
guardFlag = false;
- DSL.doif(test, expression).evaluate(RefResolverHelper.createResolver(this));
+ DSL.doif(test, expression).evaluate(evalContext);
assertFalse(executed[0]);
guardFlag = true;
- DSL.doif(test, expression).evaluate(RefResolverHelper.createResolver(this));
+ DSL.doif(test, expression).evaluate(evalContext);
assertTrue(executed[0]);
}
}
diff --git a/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/expressions/IndexExpressionTest.java b/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/expressions/IndexExpressionTest.java
index 4a6ea9ab2dd..9a36d2d054c 100644
--- a/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/expressions/IndexExpressionTest.java
+++ b/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/expressions/IndexExpressionTest.java
@@ -1,12 +1,13 @@
package com.datadog.debugger.el.expressions;
+import static com.datadog.debugger.el.EvalContextHelper.createEvalContext;
import static com.datadog.debugger.el.PrettyPrintVisitor.print;
import static com.datadog.debugger.el.TestHelper.setFieldInConfig;
import static org.junit.jupiter.api.Assertions.*;
+import com.datadog.debugger.el.EvalContext;
import com.datadog.debugger.el.EvaluationException;
import com.datadog.debugger.el.RedactedException;
-import com.datadog.debugger.el.RefResolverHelper;
import com.datadog.debugger.el.Value;
import com.datadog.debugger.el.ValueType;
import com.datadog.debugger.el.values.ListValue;
@@ -46,11 +47,13 @@ class IndexExpressionTest {
secretMap.put("foo", new StoreSecret("secret123"));
}
+ EvalContext evalContext = createEvalContext(this);
+
@Test
void testArray() {
IndexExpression expr =
new IndexExpression(new ValueRefExpression("strArray"), new NumericValue(1, ValueType.INT));
- Value> val = expr.evaluate(RefResolverHelper.createResolver(this));
+ Value> val = expr.evaluate(evalContext);
assertNotNull(val);
assertFalse(val.isUndefined());
assertEquals("bar", val.getValue());
@@ -61,7 +64,7 @@ void testArray() {
void testList() {
IndexExpression expr =
new IndexExpression(new ValueRefExpression("strList"), new NumericValue(1, ValueType.INT));
- Value> val = expr.evaluate(RefResolverHelper.createResolver(this));
+ Value> val = expr.evaluate(evalContext);
assertNotNull(val);
assertFalse(val.isUndefined());
assertEquals("bar", val.getValue());
@@ -72,7 +75,7 @@ void testList() {
void testMap() {
IndexExpression expr =
new IndexExpression(new ValueRefExpression("strMap"), new StringValue("foo"));
- Value> val = expr.evaluate(RefResolverHelper.createResolver(this));
+ Value> val = expr.evaluate(evalContext);
assertNotNull(val);
assertFalse(val.isUndefined());
assertEquals("bar", val.getValue());
@@ -84,8 +87,7 @@ void testUnsupportedSet() {
IndexExpression expr =
new IndexExpression(new SetValue(new HashSet<>()), new StringValue("foo"));
EvaluationException evaluationException =
- assertThrows(
- EvaluationException.class, () -> expr.evaluate(RefResolverHelper.createResolver(this)));
+ assertThrows(EvaluationException.class, () -> expr.evaluate(evalContext));
assertEquals(
"Cannot evaluate the expression for unsupported type: com.datadog.debugger.el.values.SetValue",
evaluationException.getMessage());
@@ -97,8 +99,7 @@ void testUnsupportedList() {
new IndexExpression(
new ListValue(new ArrayList() {}), new NumericValue(0, ValueType.INT));
EvaluationException evaluationException =
- assertThrows(
- EvaluationException.class, () -> expr.evaluate(RefResolverHelper.createResolver(this)));
+ assertThrows(EvaluationException.class, () -> expr.evaluate(evalContext));
assertEquals(
"Unsupported List class: com.datadog.debugger.el.expressions.IndexExpressionTest$1",
evaluationException.getMessage());
@@ -110,8 +111,7 @@ void testOutOfBoundsList() {
new IndexExpression(
new ListValue(new ArrayList()), new NumericValue(42, ValueType.INT));
EvaluationException evaluationException =
- assertThrows(
- EvaluationException.class, () -> expr.evaluate(RefResolverHelper.createResolver(this)));
+ assertThrows(EvaluationException.class, () -> expr.evaluate(evalContext));
assertEquals("index[42] out of bounds: [0-0]", evaluationException.getMessage());
}
@@ -120,8 +120,7 @@ void testUnsupportedMap() {
IndexExpression expr =
new IndexExpression(new MapValue(new HashMap() {}), new StringValue("foo"));
EvaluationException evaluationException =
- assertThrows(
- EvaluationException.class, () -> expr.evaluate(RefResolverHelper.createResolver(this)));
+ assertThrows(EvaluationException.class, () -> expr.evaluate(evalContext));
assertEquals(
"Unsupported Map class: com.datadog.debugger.el.expressions.IndexExpressionTest$2",
evaluationException.getMessage());
@@ -132,8 +131,7 @@ void undefined() {
IndexExpression expr =
new IndexExpression(ValueExpression.UNDEFINED, new NumericValue(1, ValueType.INT));
EvaluationException exception =
- assertThrows(
- EvaluationException.class, () -> expr.evaluate(RefResolverHelper.createResolver(this)));
+ assertThrows(EvaluationException.class, () -> expr.evaluate(evalContext));
assertEquals("Cannot evaluate the expression for undefined value", exception.getMessage());
}
@@ -142,18 +140,14 @@ void redacted() {
IndexExpression expr1 =
new IndexExpression(new ValueRefExpression("strMap"), new StringValue("password"));
RedactedException redactedException =
- assertThrows(
- RedactedException.class,
- () -> expr1.evaluate(RefResolverHelper.createResolver(this)).getValue());
+ assertThrows(RedactedException.class, () -> expr1.evaluate(evalContext).getValue());
assertEquals(
"Could not evaluate the expression because 'strMap[\"password\"]' was redacted",
redactedException.getMessage());
IndexExpression expr2 =
new IndexExpression(new ValueRefExpression("strMap"), new ValueRefExpression("str"));
redactedException =
- assertThrows(
- RedactedException.class,
- () -> expr2.evaluate(RefResolverHelper.createResolver(this)).getValue());
+ assertThrows(RedactedException.class, () -> expr2.evaluate(evalContext).getValue());
assertEquals(
"Could not evaluate the expression because 'strMap[str]' was redacted",
redactedException.getMessage());
@@ -172,9 +166,7 @@ void redactedType() {
new IndexExpression(
new ValueRefExpression("secretArray"), new NumericValue(0, ValueType.INT));
RedactedException redactedException =
- assertThrows(
- RedactedException.class,
- () -> exprArray.evaluate(RefResolverHelper.createResolver(this)).getValue());
+ assertThrows(RedactedException.class, () -> exprArray.evaluate(evalContext).getValue());
assertEquals(
"Could not evaluate the expression because 'secretArray[0]' was redacted",
redactedException.getMessage());
@@ -182,18 +174,14 @@ void redactedType() {
new IndexExpression(
new ValueRefExpression("secretList"), new NumericValue(0, ValueType.INT));
redactedException =
- assertThrows(
- RedactedException.class,
- () -> exprList.evaluate(RefResolverHelper.createResolver(this)).getValue());
+ assertThrows(RedactedException.class, () -> exprList.evaluate(evalContext).getValue());
assertEquals(
"Could not evaluate the expression because 'secretList[0]' was redacted",
redactedException.getMessage());
IndexExpression exprMap =
new IndexExpression(new ValueRefExpression("secretMap"), new StringValue("foo"));
redactedException =
- assertThrows(
- RedactedException.class,
- () -> exprMap.evaluate(RefResolverHelper.createResolver(this)).getValue());
+ assertThrows(RedactedException.class, () -> exprMap.evaluate(evalContext).getValue());
assertEquals(
"Could not evaluate the expression because 'secretMap[\"foo\"]' was redacted",
redactedException.getMessage());
@@ -207,12 +195,12 @@ void stringPrimitives() {
IndexExpression expr =
new IndexExpression(
new ValueRefExpression("uuidArray"), new NumericValue(1, ValueType.INT));
- assertEquals(UUID_2, expr.evaluate(RefResolverHelper.createResolver(this)).getValue());
+ assertEquals(UUID_2, expr.evaluate(evalContext).getValue());
expr =
new IndexExpression(new ValueRefExpression("uuidList"), new NumericValue(1, ValueType.INT));
- assertEquals(UUID_2, expr.evaluate(RefResolverHelper.createResolver(this)).getValue());
+ assertEquals(UUID_2, expr.evaluate(evalContext).getValue());
expr = new IndexExpression(new ValueRefExpression("uuidMap"), new StringValue("foo"));
- assertEquals(UUID_1, expr.evaluate(RefResolverHelper.createResolver(this)).getValue());
+ assertEquals(UUID_1, expr.evaluate(evalContext).getValue());
}
private static class StoreSecret {
diff --git a/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/expressions/IsDefinedExpressionTest.java b/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/expressions/IsDefinedExpressionTest.java
index b8911c90826..53f672cd724 100644
--- a/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/expressions/IsDefinedExpressionTest.java
+++ b/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/expressions/IsDefinedExpressionTest.java
@@ -1,12 +1,13 @@
package com.datadog.debugger.el.expressions;
+import static com.datadog.debugger.el.EvalContextHelper.createEvalContext;
import static com.datadog.debugger.el.PrettyPrintVisitor.print;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import com.datadog.debugger.el.DSL;
-import com.datadog.debugger.el.RefResolverHelper;
+import com.datadog.debugger.el.EvalContext;
import com.datadog.debugger.el.Value;
import com.datadog.debugger.el.ValueType;
import com.datadog.debugger.el.values.BooleanValue;
@@ -14,35 +15,34 @@
import com.datadog.debugger.el.values.MapValue;
import com.datadog.debugger.el.values.NumericValue;
import com.datadog.debugger.el.values.StringValue;
-import datadog.trace.bootstrap.debugger.el.ValueReferenceResolver;
import datadog.trace.bootstrap.debugger.el.Values;
import java.util.Arrays;
import java.util.Collections;
import org.junit.jupiter.api.Test;
class IsDefinedExpressionTest {
- private final ValueReferenceResolver resolver = RefResolverHelper.createResolver(this);
+ private final EvalContext evalContext = createEvalContext(this);
@Test
void testNullValue() {
IsDefinedExpression expression = new IsDefinedExpression(null);
- assertFalse(expression.evaluate(resolver));
+ assertFalse(expression.evaluate(evalContext));
assertEquals("isDefined(null)", print(expression));
expression = new IsDefinedExpression(DSL.value(Values.NULL_OBJECT));
- assertTrue(expression.evaluate(resolver));
+ assertTrue(expression.evaluate(evalContext));
assertEquals("isDefined(null)", print(expression));
expression = new IsDefinedExpression(DSL.value(Value.nullValue()));
- assertTrue(expression.evaluate(resolver));
+ assertTrue(expression.evaluate(evalContext));
assertEquals("isDefined(com.datadog.debugger.el.values.NullValue)", print(expression));
}
@Test
void testUndefinedValue() {
IsDefinedExpression expression = new IsDefinedExpression(DSL.value(Values.UNDEFINED_OBJECT));
- assertFalse(expression.evaluate(resolver));
+ assertFalse(expression.evaluate(evalContext));
assertEquals("isDefined(UNDEFINED)", print(expression));
expression = new IsDefinedExpression(DSL.ref("undefinedvar"));
- assertFalse(expression.evaluate(resolver));
+ assertFalse(expression.evaluate(evalContext));
}
@Test
@@ -52,13 +52,13 @@ void testNumericLiteral() {
NumericValue none = new NumericValue(null, ValueType.OBJECT);
IsDefinedExpression expression = new IsDefinedExpression(zero);
- assertTrue(expression.evaluate(resolver));
+ assertTrue(expression.evaluate(evalContext));
assertEquals("isDefined(0)", print(expression));
expression = new IsDefinedExpression(one);
- assertTrue(expression.evaluate(resolver));
+ assertTrue(expression.evaluate(evalContext));
assertEquals("isDefined(1)", print(expression));
expression = new IsDefinedExpression(none);
- assertTrue(expression.evaluate(resolver));
+ assertTrue(expression.evaluate(evalContext));
assertEquals("isDefined(null)", print(expression));
}
@@ -69,13 +69,13 @@ void testBooleanLiteral() {
BooleanValue none = new BooleanValue(null, ValueType.OBJECT);
IsDefinedExpression expression = new IsDefinedExpression(yes);
- assertTrue(expression.evaluate(resolver));
+ assertTrue(expression.evaluate(evalContext));
assertEquals("isDefined(true)", print(expression));
expression = new IsDefinedExpression(no);
- assertTrue(expression.evaluate(resolver));
+ assertTrue(expression.evaluate(evalContext));
assertEquals("isDefined(false)", print(expression));
expression = new IsDefinedExpression(none);
- assertTrue(expression.evaluate(resolver));
+ assertTrue(expression.evaluate(evalContext));
assertEquals("isDefined(null)", print(expression));
}
@@ -89,11 +89,11 @@ void testStringLiteral() {
IsDefinedExpression isDefined2 = new IsDefinedExpression(emptyString);
IsDefinedExpression isDefined3 = new IsDefinedExpression(nullString);
- assertTrue(isDefined1.evaluate(resolver));
+ assertTrue(isDefined1.evaluate(evalContext));
assertEquals("isDefined(\"Hello World\")", print(isDefined1));
- assertTrue(isDefined2.evaluate(resolver));
+ assertTrue(isDefined2.evaluate(evalContext));
assertEquals("isDefined(\"\")", print(isDefined2));
- assertTrue(isDefined3.evaluate(resolver));
+ assertTrue(isDefined3.evaluate(evalContext));
assertEquals("isDefined(\"null\")", print(isDefined3));
}
@@ -109,13 +109,13 @@ void testListValue() {
IsDefinedExpression isDefined3 = new IsDefinedExpression(nullList);
IsDefinedExpression isDefined4 = new IsDefinedExpression(undefinedList);
- assertTrue(isDefined1.evaluate(resolver));
+ assertTrue(isDefined1.evaluate(evalContext));
assertEquals("isDefined(List)", print(isDefined1));
- assertTrue(isDefined2.evaluate(resolver));
+ assertTrue(isDefined2.evaluate(evalContext));
assertEquals("isDefined(List)", print(isDefined2));
- assertTrue(isDefined3.evaluate(resolver));
+ assertTrue(isDefined3.evaluate(evalContext));
assertEquals("isDefined(null)", print(isDefined3));
- assertFalse(isDefined4.evaluate(resolver));
+ assertFalse(isDefined4.evaluate(evalContext));
assertEquals("isDefined(null)", print(isDefined4));
}
@@ -126,19 +126,18 @@ void testMapValue() {
MapValue nullMao = new MapValue(null);
MapValue undefinedMap = new MapValue(Values.UNDEFINED_OBJECT);
- ValueReferenceResolver resolver = RefResolverHelper.createResolver(this);
IsDefinedExpression isDefined1 = new IsDefinedExpression(map);
IsDefinedExpression isDefined2 = new IsDefinedExpression(emptyMap);
IsDefinedExpression isDefined3 = new IsDefinedExpression(nullMao);
IsDefinedExpression isDefined4 = new IsDefinedExpression(undefinedMap);
- assertTrue(isDefined1.evaluate(resolver));
+ assertTrue(isDefined1.evaluate(evalContext));
assertEquals("isDefined(Map)", print(isDefined1));
- assertTrue(isDefined2.evaluate(resolver));
+ assertTrue(isDefined2.evaluate(evalContext));
assertEquals("isDefined(Map)", print(isDefined2));
- assertTrue(isDefined3.evaluate(resolver));
+ assertTrue(isDefined3.evaluate(evalContext));
assertEquals("isDefined(null)", print(isDefined3));
- assertFalse(isDefined4.evaluate(resolver));
+ assertFalse(isDefined4.evaluate(evalContext));
assertEquals("isDefined(null)", print(isDefined4));
}
}
diff --git a/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/expressions/IsEmptyExpressionTest.java b/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/expressions/IsEmptyExpressionTest.java
index d9bb0f4ecd7..3581fd96907 100644
--- a/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/expressions/IsEmptyExpressionTest.java
+++ b/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/expressions/IsEmptyExpressionTest.java
@@ -1,11 +1,12 @@
package com.datadog.debugger.el.expressions;
+import static com.datadog.debugger.el.EvalContextHelper.createEvalContext;
import static com.datadog.debugger.el.PrettyPrintVisitor.print;
import static org.junit.jupiter.api.Assertions.*;
import com.datadog.debugger.el.DSL;
+import com.datadog.debugger.el.EvalContext;
import com.datadog.debugger.el.EvaluationException;
-import com.datadog.debugger.el.RefResolverHelper;
import com.datadog.debugger.el.Value;
import com.datadog.debugger.el.ValueType;
import com.datadog.debugger.el.values.BooleanValue;
@@ -13,7 +14,6 @@
import com.datadog.debugger.el.values.MapValue;
import com.datadog.debugger.el.values.NumericValue;
import com.datadog.debugger.el.values.StringValue;
-import datadog.trace.bootstrap.debugger.el.ValueReferenceResolver;
import datadog.trace.bootstrap.debugger.el.Values;
import java.util.Arrays;
import java.util.Collections;
@@ -21,30 +21,30 @@
import org.junit.jupiter.api.Test;
class IsEmptyExpressionTest {
+ EvalContext evalContext = createEvalContext(this);
+
@Test
void testNullValue() {
- ValueReferenceResolver resolver = RefResolverHelper.createResolver(this);
IsEmptyExpression expression1 = new IsEmptyExpression(null);
EvaluationException exception =
- assertThrows(EvaluationException.class, () -> expression1.evaluate(resolver));
+ assertThrows(EvaluationException.class, () -> expression1.evaluate(evalContext));
assertEquals("Cannot evaluate the expression for null value", exception.getMessage());
assertEquals("isEmpty(null)", print(expression1));
IsEmptyExpression expression2 = new IsEmptyExpression(DSL.value(Values.NULL_OBJECT));
- exception = assertThrows(EvaluationException.class, () -> expression2.evaluate(resolver));
+ exception = assertThrows(EvaluationException.class, () -> expression2.evaluate(evalContext));
assertEquals("Cannot evaluate the expression for null value", exception.getMessage());
assertEquals("isEmpty(null)", print(expression2));
IsEmptyExpression expression3 = new IsEmptyExpression(DSL.value(Value.nullValue()));
- exception = assertThrows(EvaluationException.class, () -> expression3.evaluate(resolver));
+ exception = assertThrows(EvaluationException.class, () -> expression3.evaluate(evalContext));
assertEquals("Cannot evaluate the expression for null value", exception.getMessage());
assertEquals("isEmpty(com.datadog.debugger.el.values.NullValue)", print(expression3));
}
@Test
void testUndefinedValue() {
- ValueReferenceResolver resolver = RefResolverHelper.createResolver(this);
IsEmptyExpression expression = new IsEmptyExpression(DSL.value(Values.UNDEFINED_OBJECT));
EvaluationException exception =
- assertThrows(EvaluationException.class, () -> expression.evaluate(resolver));
+ assertThrows(EvaluationException.class, () -> expression.evaluate(evalContext));
assertEquals("Cannot evaluate the expression for undefined value", exception.getMessage());
assertEquals("isEmpty(UNDEFINED)", print(expression));
}
@@ -55,15 +55,14 @@ void testNumericLiteral() {
NumericValue one = new NumericValue(1, ValueType.INT);
NumericValue none = new NumericValue(null, ValueType.OBJECT);
- ValueReferenceResolver resolver = RefResolverHelper.createResolver(this);
IsEmptyExpression expression = new IsEmptyExpression(zero);
- assertFalse(expression.evaluate(resolver));
+ assertFalse(expression.evaluate(evalContext));
assertEquals("isEmpty(0)", print(expression));
expression = new IsEmptyExpression(one);
- assertFalse(expression.evaluate(resolver));
+ assertFalse(expression.evaluate(evalContext));
assertEquals("isEmpty(1)", print(expression));
IsEmptyExpression nullExpression = new IsEmptyExpression(none);
- assertThrows(EvaluationException.class, () -> nullExpression.evaluate(resolver));
+ assertThrows(EvaluationException.class, () -> nullExpression.evaluate(evalContext));
assertEquals("isEmpty(null)", print(nullExpression));
}
@@ -73,16 +72,15 @@ void testBooleanLiteral() {
BooleanValue no = BooleanValue.FALSE;
BooleanValue none = new BooleanValue(null, ValueType.OBJECT);
- ValueReferenceResolver resolver = RefResolverHelper.createResolver(this);
IsEmptyExpression expression = new IsEmptyExpression(yes);
- assertFalse(expression.evaluate(resolver));
+ assertFalse(expression.evaluate(evalContext));
assertEquals("isEmpty(true)", print(expression));
expression = new IsEmptyExpression(no);
- assertFalse(expression.evaluate(resolver));
+ assertFalse(expression.evaluate(evalContext));
assertEquals("isEmpty(false)", print(expression));
IsEmptyExpression nullExpression = new IsEmptyExpression(none);
EvaluationException exception =
- assertThrows(EvaluationException.class, () -> nullExpression.evaluate(resolver));
+ assertThrows(EvaluationException.class, () -> nullExpression.evaluate(evalContext));
assertEquals("Cannot evaluate the expression for null value", exception.getMessage());
assertEquals("isEmpty(null)", print(nullExpression));
}
@@ -93,17 +91,16 @@ void testStringLiteral() {
StringValue emptyString = new StringValue("");
StringValue nullString = new StringValue(null);
- ValueReferenceResolver resolver = RefResolverHelper.createResolver(this);
IsEmptyExpression isEmpty1 = new IsEmptyExpression(string);
IsEmptyExpression isEmpty2 = new IsEmptyExpression(emptyString);
IsEmptyExpression isEmpty3 = new IsEmptyExpression(nullString);
- assertFalse(isEmpty1.evaluate(resolver));
+ assertFalse(isEmpty1.evaluate(evalContext));
assertEquals("isEmpty(\"Hello World\")", print(isEmpty1));
- assertTrue(isEmpty2.evaluate(resolver));
+ assertTrue(isEmpty2.evaluate(evalContext));
assertEquals("isEmpty(\"\")", print(isEmpty2));
EvaluationException exception =
- assertThrows(EvaluationException.class, () -> isEmpty3.evaluate(resolver));
+ assertThrows(EvaluationException.class, () -> isEmpty3.evaluate(evalContext));
assertEquals("Cannot evaluate the expression for null value", exception.getMessage());
assertEquals("isEmpty(\"null\")", print(isEmpty3));
}
@@ -117,7 +114,6 @@ void testCollectionLiteral() {
ListValue set = new ListValue(new HashSet<>(Arrays.asList("a", "b")));
ListValue emptySet = new ListValue(Collections.emptySet());
- ValueReferenceResolver resolver = RefResolverHelper.createResolver(this);
IsEmptyExpression isEmpty1 = new IsEmptyExpression(list);
IsEmptyExpression isEmpty2 = new IsEmptyExpression(emptyList);
IsEmptyExpression isEmpty3 = new IsEmptyExpression(nullList);
@@ -125,20 +121,20 @@ void testCollectionLiteral() {
IsEmptyExpression isEmpty5 = new IsEmptyExpression(set);
IsEmptyExpression isEmpty6 = new IsEmptyExpression(emptySet);
- assertFalse(isEmpty1.evaluate(resolver));
+ assertFalse(isEmpty1.evaluate(evalContext));
assertEquals("isEmpty(List)", print(isEmpty1));
- assertTrue(isEmpty2.evaluate(resolver));
+ assertTrue(isEmpty2.evaluate(evalContext));
assertEquals("isEmpty(List)", print(isEmpty2));
EvaluationException exception =
- assertThrows(EvaluationException.class, () -> isEmpty3.evaluate(resolver));
+ assertThrows(EvaluationException.class, () -> isEmpty3.evaluate(evalContext));
assertEquals("Cannot evaluate the expression for null value", exception.getMessage());
assertEquals("isEmpty(null)", print(isEmpty3));
- exception = assertThrows(EvaluationException.class, () -> isEmpty4.evaluate(resolver));
+ exception = assertThrows(EvaluationException.class, () -> isEmpty4.evaluate(evalContext));
assertEquals("Cannot evaluate the expression for undefined value", exception.getMessage());
assertEquals("isEmpty(null)", print(isEmpty4));
- assertFalse(isEmpty5.evaluate(resolver));
+ assertFalse(isEmpty5.evaluate(evalContext));
assertEquals("isEmpty(Set)", print(isEmpty5));
- assertTrue(isEmpty6.evaluate(resolver));
+ assertTrue(isEmpty6.evaluate(evalContext));
assertEquals("isEmpty(Set)", print(isEmpty6));
}
@@ -149,21 +145,20 @@ void testMapValue() {
MapValue nullMao = new MapValue(null);
MapValue undefinedMap = new MapValue(Values.UNDEFINED_OBJECT);
- ValueReferenceResolver resolver = RefResolverHelper.createResolver(this);
IsEmptyExpression isEmpty1 = new IsEmptyExpression(map);
IsEmptyExpression isEmpty2 = new IsEmptyExpression(emptyMap);
IsEmptyExpression isEmpty3 = new IsEmptyExpression(nullMao);
IsEmptyExpression isEmpty4 = new IsEmptyExpression(undefinedMap);
- assertFalse(isEmpty1.evaluate(resolver));
+ assertFalse(isEmpty1.evaluate(evalContext));
assertEquals("isEmpty(Map)", print(isEmpty1));
- assertTrue(isEmpty2.evaluate(resolver));
+ assertTrue(isEmpty2.evaluate(evalContext));
assertEquals("isEmpty(Map)", print(isEmpty2));
EvaluationException exception =
- assertThrows(EvaluationException.class, () -> isEmpty3.evaluate(resolver));
+ assertThrows(EvaluationException.class, () -> isEmpty3.evaluate(evalContext));
assertEquals("Cannot evaluate the expression for null value", exception.getMessage());
assertEquals("isEmpty(null)", print(isEmpty3));
- exception = assertThrows(EvaluationException.class, () -> isEmpty4.evaluate(resolver));
+ exception = assertThrows(EvaluationException.class, () -> isEmpty4.evaluate(evalContext));
assertEquals("Cannot evaluate the expression for undefined value", exception.getMessage());
assertEquals("isEmpty(null)", print(isEmpty4));
}
diff --git a/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/expressions/LenExpressionTest.java b/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/expressions/LenExpressionTest.java
index a978e6a8a42..5c9d150141c 100644
--- a/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/expressions/LenExpressionTest.java
+++ b/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/expressions/LenExpressionTest.java
@@ -1,12 +1,12 @@
package com.datadog.debugger.el.expressions;
+import static com.datadog.debugger.el.EvalContextHelper.createEvalContext;
import static com.datadog.debugger.el.PrettyPrintVisitor.print;
import static org.junit.jupiter.api.Assertions.*;
import com.datadog.debugger.el.DSL;
+import com.datadog.debugger.el.EvalContext;
import com.datadog.debugger.el.EvaluationException;
-import com.datadog.debugger.el.RefResolverHelper;
-import datadog.trace.bootstrap.debugger.el.ValueReferenceResolver;
import datadog.trace.bootstrap.debugger.el.Values;
import java.util.Arrays;
import java.util.Collections;
@@ -14,13 +14,13 @@
import org.junit.jupiter.api.Test;
class LenExpressionTest {
- private final ValueReferenceResolver resolver = RefResolverHelper.createResolver(this);
+ private final EvalContext evalContext = createEvalContext(this);
@Test
void nullExpression() {
LenExpression expression = new LenExpression(null);
EvaluationException exception =
- assertThrows(EvaluationException.class, () -> expression.evaluate(resolver).getValue());
+ assertThrows(EvaluationException.class, () -> expression.evaluate(evalContext).getValue());
assertEquals("Cannot evaluate the expression for null value", exception.getMessage());
assertEquals("len(null)", print(expression));
}
@@ -29,7 +29,7 @@ void nullExpression() {
void undefinedExpression() {
LenExpression expression = new LenExpression(DSL.value(Values.UNDEFINED_OBJECT));
EvaluationException exception =
- assertThrows(EvaluationException.class, () -> expression.evaluate(resolver).getValue());
+ assertThrows(EvaluationException.class, () -> expression.evaluate(evalContext).getValue());
assertEquals("Cannot evaluate the expression for undefined value", exception.getMessage());
assertEquals("len(UNDEFINED)", print(expression));
}
@@ -37,24 +37,24 @@ void undefinedExpression() {
@Test
void stringExpression() {
LenExpression expression = new LenExpression(DSL.value("a"));
- assertEquals(1, expression.evaluate(resolver).getValue());
+ assertEquals(1, expression.evaluate(evalContext).getValue());
assertEquals("len(\"a\")", print(expression));
}
@Test
void collectionExpression() {
LenExpression expression = new LenExpression(DSL.value(Arrays.asList("a", "b")));
- assertEquals(2, expression.evaluate(resolver).getValue());
+ assertEquals(2, expression.evaluate(evalContext).getValue());
assertEquals("len(List)", print(expression));
expression = new LenExpression(DSL.value(new HashSet<>(Arrays.asList("a", "b"))));
- assertEquals(2, expression.evaluate(resolver).getValue());
+ assertEquals(2, expression.evaluate(evalContext).getValue());
assertEquals("len(Set)", print(expression));
}
@Test
void mapExpression() {
LenExpression expression = new LenExpression(DSL.value(Collections.singletonMap("a", "b")));
- assertEquals(1, expression.evaluate(resolver).getValue());
+ assertEquals(1, expression.evaluate(evalContext).getValue());
assertEquals("len(Map)", print(expression));
}
}
diff --git a/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/expressions/MatchesExpressionTest.java b/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/expressions/MatchesExpressionTest.java
index 23cfc0c7c66..7e33d745532 100644
--- a/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/expressions/MatchesExpressionTest.java
+++ b/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/expressions/MatchesExpressionTest.java
@@ -1,19 +1,19 @@
package com.datadog.debugger.el.expressions;
+import static com.datadog.debugger.el.EvalContextHelper.createEvalContext;
import static com.datadog.debugger.el.PrettyPrintVisitor.print;
import static org.junit.jupiter.api.Assertions.*;
import com.datadog.debugger.el.DSL;
+import com.datadog.debugger.el.EvalContext;
import com.datadog.debugger.el.EvaluationException;
-import com.datadog.debugger.el.RefResolverHelper;
import com.datadog.debugger.el.values.StringValue;
-import datadog.trace.bootstrap.debugger.el.ValueReferenceResolver;
import datadog.trace.bootstrap.debugger.el.Values;
import java.net.URI;
import org.junit.jupiter.api.Test;
class MatchesExpressionTest {
- private final ValueReferenceResolver resolver = RefResolverHelper.createResolver(this);
+ private final EvalContext evalContext = createEvalContext(this);
// used to ref lookup
URI uri = URI.create("https://www.datadoghq.com");
@@ -21,7 +21,7 @@ class MatchesExpressionTest {
void nullExpression() {
MatchesExpression expression = new MatchesExpression(null, null);
EvaluationException exception =
- assertThrows(EvaluationException.class, () -> expression.evaluate(resolver));
+ assertThrows(EvaluationException.class, () -> expression.evaluate(evalContext));
assertEquals("Cannot evaluate the expression for null value", exception.getMessage());
assertEquals("matches(null, null)", print(expression));
}
@@ -31,7 +31,7 @@ void undefinedExpression() {
MatchesExpression expression =
new MatchesExpression(DSL.value(Values.UNDEFINED_OBJECT), new StringValue(null));
EvaluationException exception =
- assertThrows(EvaluationException.class, () -> expression.evaluate(resolver));
+ assertThrows(EvaluationException.class, () -> expression.evaluate(evalContext));
assertEquals("Cannot evaluate the expression for undefined value", exception.getMessage());
assertEquals("matches(UNDEFINED, \"null\")", print(expression));
}
@@ -39,17 +39,17 @@ void undefinedExpression() {
@Test
void stringExpression() {
MatchesExpression expression = new MatchesExpression(DSL.value("abc"), new StringValue("abc"));
- assertTrue(expression.evaluate(resolver));
+ assertTrue(expression.evaluate(evalContext));
assertEquals("matches(\"abc\", \"abc\")", print(expression));
expression = new MatchesExpression(DSL.value("abc"), new StringValue("^ab.*"));
- assertTrue(expression.evaluate(resolver));
+ assertTrue(expression.evaluate(evalContext));
assertEquals("matches(\"abc\", \"^ab.*\")", print(expression));
expression = new MatchesExpression(DSL.value("abc"), new StringValue("bc"));
- assertFalse(expression.evaluate(resolver));
+ assertFalse(expression.evaluate(evalContext));
assertEquals("matches(\"abc\", \"bc\")", print(expression));
expression = new MatchesExpression(DSL.value("abc"), new StringValue("[def]+"));
- assertFalse(expression.evaluate(resolver));
+ assertFalse(expression.evaluate(evalContext));
assertEquals("matches(\"abc\", \"[def]+\")", print(expression));
}
@@ -57,7 +57,7 @@ void stringExpression() {
void stringPrimitives() {
MatchesExpression expression =
new MatchesExpression(DSL.ref("uri"), new StringValue("^https?://w{3}\\.datadoghq\\.com$"));
- assertTrue(expression.evaluate(resolver));
+ assertTrue(expression.evaluate(evalContext));
assertEquals("matches(uri, \"^https?://w{3}\\.datadoghq\\.com$\")", print(expression));
}
}
diff --git a/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/expressions/NotExpressionTest.java b/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/expressions/NotExpressionTest.java
index ac6d251134c..bad4a9f4c0e 100644
--- a/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/expressions/NotExpressionTest.java
+++ b/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/expressions/NotExpressionTest.java
@@ -1,9 +1,9 @@
package com.datadog.debugger.el.expressions;
+import static com.datadog.debugger.el.EvalContextHelper.createEvalContext;
import static com.datadog.debugger.el.PrettyPrintVisitor.print;
import static org.junit.jupiter.api.Assertions.*;
-import com.datadog.debugger.el.RefResolverHelper;
import java.util.stream.Stream;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
@@ -14,7 +14,7 @@ class NotExpressionTest {
@MethodSource("expressions")
void testNullPredicate(BooleanExpression expression, boolean expected, String prettyPrint) {
NotExpression expr = new NotExpression(expression);
- assertEquals(expected, expr.evaluate(RefResolverHelper.createResolver(this)));
+ assertEquals(expected, expr.evaluate(createEvalContext(this)));
assertEquals(prettyPrint, print(expr));
}
diff --git a/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/expressions/StartsWithExpressionTest.java b/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/expressions/StartsWithExpressionTest.java
index 0626dc1d6ff..f17a11a7946 100644
--- a/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/expressions/StartsWithExpressionTest.java
+++ b/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/expressions/StartsWithExpressionTest.java
@@ -1,19 +1,19 @@
package com.datadog.debugger.el.expressions;
+import static com.datadog.debugger.el.EvalContextHelper.createEvalContext;
import static com.datadog.debugger.el.PrettyPrintVisitor.print;
import static org.junit.jupiter.api.Assertions.*;
import com.datadog.debugger.el.DSL;
+import com.datadog.debugger.el.EvalContext;
import com.datadog.debugger.el.EvaluationException;
-import com.datadog.debugger.el.RefResolverHelper;
import com.datadog.debugger.el.values.StringValue;
-import datadog.trace.bootstrap.debugger.el.ValueReferenceResolver;
import datadog.trace.bootstrap.debugger.el.Values;
import java.net.URI;
import org.junit.jupiter.api.Test;
class StartsWithExpressionTest {
- private final ValueReferenceResolver resolver = RefResolverHelper.createResolver(this);
+ private final EvalContext evalContext = createEvalContext(this);
// used to ref lookup
URI uri = URI.create("https://www.datadoghq.com");
@@ -21,7 +21,7 @@ class StartsWithExpressionTest {
void nullExpression() {
StartsWithExpression expression = new StartsWithExpression(null, null);
EvaluationException exception =
- assertThrows(EvaluationException.class, () -> expression.evaluate(resolver));
+ assertThrows(EvaluationException.class, () -> expression.evaluate(evalContext));
assertEquals("Cannot evaluate the expression for null value", exception.getMessage());
assertEquals("startsWith(null, null)", print(expression));
}
@@ -31,7 +31,7 @@ void undefinedExpression() {
StartsWithExpression expression =
new StartsWithExpression(DSL.value(Values.UNDEFINED_OBJECT), new StringValue(null));
EvaluationException exception =
- assertThrows(EvaluationException.class, () -> expression.evaluate(resolver));
+ assertThrows(EvaluationException.class, () -> expression.evaluate(evalContext));
assertEquals("Cannot evaluate the expression for undefined value", exception.getMessage());
assertEquals("startsWith(UNDEFINED, \"null\")", print(expression));
}
@@ -40,11 +40,11 @@ void undefinedExpression() {
void stringExpression() {
StartsWithExpression expression =
new StartsWithExpression(DSL.value("abc"), new StringValue("ab"));
- assertTrue(expression.evaluate(resolver));
+ assertTrue(expression.evaluate(evalContext));
assertEquals("startsWith(\"abc\", \"ab\")", print(expression));
expression = new StartsWithExpression(DSL.value("abc"), new StringValue("bc"));
- assertFalse(expression.evaluate(resolver));
+ assertFalse(expression.evaluate(evalContext));
assertEquals("startsWith(\"abc\", \"bc\")", print(expression));
}
@@ -52,7 +52,7 @@ void stringExpression() {
void stringPrimitives() {
StartsWithExpression expression =
new StartsWithExpression(DSL.ref("uri"), new StringValue("https"));
- assertTrue(expression.evaluate(resolver));
+ assertTrue(expression.evaluate(evalContext));
assertEquals("startsWith(uri, \"https\")", print(expression));
}
}
diff --git a/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/expressions/SubStringExpressionTest.java b/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/expressions/SubStringExpressionTest.java
index 57c2ddb8291..3e2479cdd42 100644
--- a/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/expressions/SubStringExpressionTest.java
+++ b/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/expressions/SubStringExpressionTest.java
@@ -1,19 +1,19 @@
package com.datadog.debugger.el.expressions;
+import static com.datadog.debugger.el.EvalContextHelper.createEvalContext;
import static com.datadog.debugger.el.PrettyPrintVisitor.print;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import com.datadog.debugger.el.DSL;
+import com.datadog.debugger.el.EvalContext;
import com.datadog.debugger.el.EvaluationException;
-import com.datadog.debugger.el.RefResolverHelper;
-import datadog.trace.bootstrap.debugger.el.ValueReferenceResolver;
import datadog.trace.bootstrap.debugger.el.Values;
import java.net.URI;
import org.junit.jupiter.api.Test;
public class SubStringExpressionTest {
- private final ValueReferenceResolver resolver = RefResolverHelper.createResolver(this);
+ private final EvalContext evalContext = createEvalContext(this);
// used to ref lookup
URI uri = URI.create("https://www.datadoghq.com");
Object nullValue = null;
@@ -22,11 +22,11 @@ public class SubStringExpressionTest {
void nullExpression() {
SubStringExpression expression1 = new SubStringExpression(null, 0, 0);
EvaluationException evaluationException =
- assertThrows(EvaluationException.class, () -> expression1.evaluate(resolver));
+ assertThrows(EvaluationException.class, () -> expression1.evaluate(evalContext));
assertEquals("substring(null, 0, 0)", evaluationException.getExpr());
SubStringExpression expression2 = new SubStringExpression(DSL.ref("nullValue"), 0, 0);
evaluationException =
- assertThrows(EvaluationException.class, () -> expression2.evaluate(resolver));
+ assertThrows(EvaluationException.class, () -> expression2.evaluate(evalContext));
assertEquals("substring(nullValue, 0, 0)", evaluationException.getExpr());
}
@@ -35,14 +35,14 @@ void undefinedExpression() {
SubStringExpression expression =
new SubStringExpression(DSL.value(Values.UNDEFINED_OBJECT), 0, 0);
EvaluationException evaluationException =
- assertThrows(EvaluationException.class, () -> expression.evaluate(resolver));
+ assertThrows(EvaluationException.class, () -> expression.evaluate(evalContext));
assertEquals("substring(UNDEFINED, 0, 0)", evaluationException.getExpr());
}
@Test
void stringExpression() {
SubStringExpression expression = new SubStringExpression(DSL.value("abc"), 0, 1);
- assertEquals("a", expression.evaluate(resolver).getValue());
+ assertEquals("a", expression.evaluate(evalContext).getValue());
assertEquals("substring(\"abc\", 0, 1)", print(expression));
}
@@ -50,14 +50,14 @@ void stringExpression() {
void stringOutOfBoundsExpression() {
SubStringExpression expression = new SubStringExpression(DSL.value("abc"), 0, 10);
EvaluationException evaluationException =
- assertThrows(EvaluationException.class, () -> expression.evaluate(resolver));
+ assertThrows(EvaluationException.class, () -> expression.evaluate(evalContext));
assertEquals("substring(\"abc\", 0, 10)", evaluationException.getExpr());
}
@Test
void stringPrimitives() {
SubStringExpression expression = new SubStringExpression(DSL.ref("uri"), 0, 5);
- assertEquals("https", expression.evaluate(resolver).getValue());
+ assertEquals("https", expression.evaluate(evalContext).getValue());
assertEquals("substring(uri, 0, 5)", print(expression));
}
}
diff --git a/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/expressions/ValueRefExpressionTest.java b/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/expressions/ValueRefExpressionTest.java
index c5501252962..7bc26b1540e 100644
--- a/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/expressions/ValueRefExpressionTest.java
+++ b/dd-java-agent/agent-debugger/debugger-el/src/test/java/com/datadog/debugger/el/expressions/ValueRefExpressionTest.java
@@ -1,19 +1,22 @@
package com.datadog.debugger.el.expressions;
import static com.datadog.debugger.el.DSL.*;
+import static com.datadog.debugger.el.EvalContextHelper.TEST_TIMEOUT;
+import static com.datadog.debugger.el.EvalContextHelper.createEvalContext;
+import static com.datadog.debugger.el.EvalContextHelper.createResolver;
import static com.datadog.debugger.el.PrettyPrintVisitor.print;
import static com.datadog.debugger.el.TestHelper.setFieldInConfig;
import static org.junit.jupiter.api.Assertions.*;
import com.datadog.debugger.el.DSL;
+import com.datadog.debugger.el.EvalContext;
import com.datadog.debugger.el.RedactedException;
-import com.datadog.debugger.el.RefResolverHelper;
import com.datadog.debugger.el.Value;
import datadog.trace.api.Config;
import datadog.trace.bootstrap.debugger.CapturedContext.CapturedValue;
-import datadog.trace.bootstrap.debugger.el.ValueReferenceResolver;
import datadog.trace.bootstrap.debugger.el.ValueReferences;
import datadog.trace.bootstrap.debugger.util.Redaction;
+import datadog.trace.bootstrap.debugger.util.TimeoutChecker;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
@@ -26,7 +29,7 @@ class ValueRefExpressionTest {
void testRef() {
ValueRefExpression valueRef = new ValueRefExpression("b");
ExObjectWithRefAndValue instance = new ExObjectWithRefAndValue(null, "hello");
- Value> val = valueRef.evaluate(RefResolverHelper.createResolver(instance));
+ Value> val = valueRef.evaluate(createEvalContext(instance));
assertNotNull(val);
assertFalse(val.isUndefined());
assertEquals(instance.getB(), val.getValue());
@@ -42,19 +45,21 @@ void testPredicatedRef() {
IsEmptyExpression isEmptyInvalid = new IsEmptyExpression(invalidValueRef);
ExObjectWithRefAndValue instance = new ExObjectWithRefAndValue(null, "hello");
- ValueReferenceResolver ctx = RefResolverHelper.createResolver(instance);
+ EvalContext evalContext = createEvalContext(instance);
- assertFalse(isEmpty.evaluate(ctx));
+ assertFalse(isEmpty.evaluate(evalContext));
assertEquals("isEmpty(b)", print(isEmpty));
RuntimeException runtimeException =
- assertThrows(RuntimeException.class, () -> isEmptyInvalid.evaluate(ctx));
+ assertThrows(RuntimeException.class, () -> isEmptyInvalid.evaluate(evalContext));
assertEquals("Cannot dereference field: x", runtimeException.getMessage());
runtimeException =
- assertThrows(RuntimeException.class, () -> and(isEmptyInvalid, isEmpty).evaluate(ctx));
+ assertThrows(
+ RuntimeException.class, () -> and(isEmptyInvalid, isEmpty).evaluate(evalContext));
assertEquals("Cannot dereference field: x", runtimeException.getMessage());
runtimeException =
- assertThrows(RuntimeException.class, () -> or(isEmptyInvalid, isEmpty).evaluate(ctx));
+ assertThrows(
+ RuntimeException.class, () -> or(isEmptyInvalid, isEmpty).evaluate(evalContext));
assertEquals("Cannot dereference field: x", runtimeException.getMessage());
assertEquals("isEmpty(x)", print(isEmptyInvalid));
}
@@ -74,30 +79,33 @@ class Obj {
exts.put(ValueReferences.RETURN_EXTENSION_NAME, CapturedValue.of(returnVal));
exts.put(ValueReferences.DURATION_EXTENSION_NAME, CapturedValue.of(duration));
exts.put(ValueReferences.EXCEPTION_EXTENSION_NAME, CapturedValue.of(exception));
- ValueReferenceResolver resolver =
- RefResolverHelper.createResolver(new Obj()).withExtensions(exts);
+ EvalContext evalContext =
+ new EvalContext(
+ createResolver(new Obj()).withExtensions(exts),
+ TimeoutChecker.create(Config.get(), TEST_TIMEOUT));
ValueRefExpression expression = DSL.ref(ValueReferences.DURATION_REF);
- assertEquals(duration, expression.evaluate(resolver).getValue());
+ assertEquals(duration, expression.evaluate(evalContext).getValue());
assertEquals("@duration", print(expression));
expression = DSL.ref(ValueReferences.RETURN_REF);
- assertEquals(returnVal, expression.evaluate(resolver).getValue());
+ assertEquals(returnVal, expression.evaluate(evalContext).getValue());
assertEquals("@return", print(expression));
expression = DSL.ref(ValueReferences.EXCEPTION_REF);
- assertEquals(exception, expression.evaluate(resolver).getValue());
+ assertEquals(exception, expression.evaluate(evalContext).getValue());
assertEquals("@exception", print(expression));
expression = DSL.ref("limit");
- assertEquals(511L, expression.evaluate(resolver).getValue());
+ assertEquals(511L, expression.evaluate(evalContext).getValue());
assertEquals("limit", print(expression));
expression = DSL.ref("msg");
- assertEquals("Hello there", expression.evaluate(resolver).getValue());
+ assertEquals("Hello there", expression.evaluate(evalContext).getValue());
assertEquals("msg", print(expression));
expression = DSL.ref("i");
- assertEquals(6, expression.evaluate(resolver).getValue()); // int value is widened to long
+ assertEquals(6, expression.evaluate(evalContext).getValue()); // int value is widened to long
assertEquals("i", print(expression));
ValueRefExpression invalidExpression = ref(ValueReferences.synthetic("invalid"));
RuntimeException runtimeException =
- assertThrows(RuntimeException.class, () -> invalidExpression.evaluate(resolver).getValue());
+ assertThrows(
+ RuntimeException.class, () -> invalidExpression.evaluate(evalContext).getValue());
assertEquals("Cannot find synthetic var: invalid", runtimeException.getMessage());
assertEquals("@invalid", print(invalidExpression));
}
@@ -115,9 +123,7 @@ public void redacted() {
ValueRefExpression valueRef = new ValueRefExpression("password");
StoreSecret instance = new StoreSecret("secret123");
RedactedException redactedException =
- assertThrows(
- RedactedException.class,
- () -> valueRef.evaluate(RefResolverHelper.createResolver(instance)));
+ assertThrows(RedactedException.class, () -> valueRef.evaluate(createEvalContext(instance)));
assertEquals(
"Could not evaluate the expression because 'password' was redacted",
redactedException.getMessage());
@@ -136,8 +142,7 @@ class Holder {
}
RedactedException redactedException =
assertThrows(
- RedactedException.class,
- () -> valueRef.evaluate(RefResolverHelper.createResolver(new Holder())));
+ RedactedException.class, () -> valueRef.evaluate(createEvalContext(new Holder())));
assertEquals(
"Could not evaluate the expression because 'store' was redacted",
redactedException.getMessage());
@@ -153,13 +158,13 @@ class StrPrimitive {
Class> clazz = String.class;
}
ValueRefExpression valueRef = new ValueRefExpression("uuid");
- Value> val = valueRef.evaluate(RefResolverHelper.createResolver(new StrPrimitive()));
+ Value> val = valueRef.evaluate(createEvalContext(new StrPrimitive()));
assertNotNull(val);
assertFalse(val.isUndefined());
assertEquals("123e4567-e89b-12d3-a456-426655440000", val.getValue());
assertEquals("uuid", print(valueRef));
valueRef = new ValueRefExpression("clazz");
- val = valueRef.evaluate(RefResolverHelper.createResolver(new StrPrimitive()));
+ val = valueRef.evaluate(createEvalContext(new StrPrimitive()));
assertNotNull(val);
assertFalse(val.isUndefined());
assertEquals("java.lang.String", val.getValue());
diff --git a/dd-java-agent/agent-debugger/debugger-el/src/test/resources/test_conditional_14.json b/dd-java-agent/agent-debugger/debugger-el/src/test/resources/test_conditional_14.json
index 69577b9e305..787c7f74691 100644
--- a/dd-java-agent/agent-debugger/debugger-el/src/test/resources/test_conditional_14.json
+++ b/dd-java-agent/agent-debugger/debugger-el/src/test/resources/test_conditional_14.json
@@ -7,7 +7,8 @@
{"eq": [{"count": {"ref": "strArray"}}, 2]},
{"eq": [{"count": {"ref": "strMap"}}, 2]},
{"eq": [{"count": {"ref": "strSet"}}, 1]},
- {"eq": [{"count": {"ref": "strList"}}, 1]}
+ {"eq": [{"count": {"ref": "strList"}}, 1]},
+ {"all": [{"ref": "largeList"}, {"neq": [{"ref": "@it"}, "d"]}]}
]
}
}
diff --git a/dd-java-agent/agent-debugger/debugger-el/src/test/resources/test_value_expr_01.json b/dd-java-agent/agent-debugger/debugger-el/src/test/resources/test_value_expr_01.json
index f19b01f7f57..4c8ec9294cb 100644
--- a/dd-java-agent/agent-debugger/debugger-el/src/test/resources/test_value_expr_01.json
+++ b/dd-java-agent/agent-debugger/debugger-el/src/test/resources/test_value_expr_01.json
@@ -1,9 +1,9 @@
{
"dsl": "",
"json": {
- "and": [
+ "or": [
{
- "or": [
+ "and": [
{"eq": [{"ref": "i"}, 10]},
{"==": [{"ref": "i"}, 10]},
{"lt": [{"ref": "i"}, 11]},
@@ -20,6 +20,7 @@
{"not": {"isEmpty": {"ref": "list"}}},
{"any": [{"ref": "list"}, {"eq": [{"ref": "@it"}, "a"]}]},
{"all": [{"ref": "list"}, {"neq": [{"ref": "@it"}, "d"]}]},
+ {"all": [{"ref": "largeList"}, {"neq": [{"ref": "@it"}, "d"]}]},
{"startsWith": [{"ref": "str"}, "hel"]},
{"endsWith": [{"ref": "str"}, "llo"]},
{"contains": [{"ref": "str"}, "ll"]},
diff --git a/dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/agent/JsonSnapshotSerializer.java b/dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/agent/JsonSnapshotSerializer.java
index f3971f0d331..4acfef797f9 100644
--- a/dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/agent/JsonSnapshotSerializer.java
+++ b/dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/agent/JsonSnapshotSerializer.java
@@ -10,14 +10,12 @@
import datadog.trace.bootstrap.debugger.CapturedContext;
import datadog.trace.bootstrap.debugger.DebuggerContext;
import java.time.Duration;
-import java.time.temporal.ChronoUnit;
/** Serializes snapshots in Json using Moshi */
public class JsonSnapshotSerializer implements DebuggerContext.ValueSerializer {
private static final JsonAdapter ADAPTER =
MoshiHelper.createMoshiSnapshot(
- Duration.of(
- Config.get().getDynamicInstrumentationCaptureTimeout(), ChronoUnit.MILLIS))
+ Duration.ofMillis(Config.get().getDynamicInstrumentationCaptureTimeout()))
.adapter(IntakeRequest.class);
private static final JsonAdapter VALUE_ADAPTER =
new MoshiSnapshotHelper.CapturedValueAdapter();
diff --git a/dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/agent/StringTemplateBuilder.java b/dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/agent/StringTemplateBuilder.java
index 8bd75149e39..893d1a43d65 100644
--- a/dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/agent/StringTemplateBuilder.java
+++ b/dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/agent/StringTemplateBuilder.java
@@ -7,10 +7,13 @@
import com.datadog.debugger.el.Value;
import com.datadog.debugger.el.ValueScript;
import com.datadog.debugger.probe.LogProbe;
+import datadog.trace.api.Config;
import datadog.trace.bootstrap.debugger.CapturedContext;
import datadog.trace.bootstrap.debugger.EvaluationError;
import datadog.trace.bootstrap.debugger.Limits;
import datadog.trace.bootstrap.debugger.util.Redaction;
+import datadog.trace.bootstrap.debugger.util.TimeoutChecker;
+import java.time.Duration;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -37,6 +40,9 @@ public String evaluate(CapturedContext context, LogProbe.LogStatus status) {
return null;
}
StringBuilder sb = new StringBuilder();
+ // Only one timeout for all expressions
+ Duration timeout = Duration.ofMillis(Config.get().getDynamicInstrumentationEvalTimeout());
+ TimeoutChecker timeoutChecker = TimeoutChecker.create(Config.get(), timeout);
for (LogProbe.Segment segment : segments) {
ValueScript parsedExr = segment.getParsedExpr();
if (segment.getStr() != null) {
@@ -44,7 +50,7 @@ public String evaluate(CapturedContext context, LogProbe.LogStatus status) {
} else {
if (parsedExr != null) {
try {
- Value> result = parsedExr.execute(context);
+ Value> result = parsedExr.execute(context, timeoutChecker);
if (result.isUndefined()) {
sb.append(result.getValue());
} else if (result.isNull()) {
diff --git a/dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/probe/LogProbe.java b/dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/probe/LogProbe.java
index 3418ea1af4d..a6fd0cb5519 100644
--- a/dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/probe/LogProbe.java
+++ b/dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/probe/LogProbe.java
@@ -44,7 +44,6 @@
import de.thetaphi.forbiddenapis.SuppressForbidden;
import java.io.IOException;
import java.time.Duration;
-import java.time.temporal.ChronoUnit;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
@@ -590,7 +589,9 @@ private boolean evaluateCondition(CapturedContext capture, LogStatus status) {
return true;
}
try {
- if (!probeCondition.execute(capture)) {
+ Duration timeout = Duration.ofMillis(Config.get().getDynamicInstrumentationEvalTimeout());
+ TimeoutChecker timeoutChecker = TimeoutChecker.create(Config.get(), timeout);
+ if (!probeCondition.execute(capture, timeoutChecker)) {
return false;
}
} catch (EvaluationException ex) {
@@ -720,7 +721,9 @@ private void processCaptureExpressions(CapturedContext context, LogStatus logSta
}
for (CaptureExpression captureExpression : captureExpressions) {
try {
- Value> result = captureExpression.expr.execute(context);
+ Duration timeout = Duration.ofMillis(Config.get().getDynamicInstrumentationEvalTimeout());
+ TimeoutChecker timeoutChecker = TimeoutChecker.create(Config.get(), timeout);
+ Value> result = captureExpression.expr.execute(context, timeoutChecker);
if (result.isUndefined()) {
throw new EvaluationException("UNDEFINED", captureExpression.getExpr().getDsl());
}
@@ -837,9 +840,8 @@ public void commit(CapturedContext lineContext, int line) {
if (isFullSnapshot()) {
// freeze context just before commit because line probes have only one context
Duration timeout =
- Duration.of(
- Config.get().getDynamicInstrumentationCaptureTimeout(), ChronoUnit.MILLIS);
- lineContext.freeze(new TimeoutChecker(timeout));
+ Duration.ofMillis(Config.get().getDynamicInstrumentationCaptureTimeout());
+ lineContext.freeze(TimeoutChecker.create(Config.get(), timeout));
snapshot.addLine(lineContext, line);
}
commitSnapshot(snapshot, sink);
diff --git a/dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/probe/SpanDecorationProbe.java b/dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/probe/SpanDecorationProbe.java
index af9354429d1..d0c60012153 100644
--- a/dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/probe/SpanDecorationProbe.java
+++ b/dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/probe/SpanDecorationProbe.java
@@ -10,6 +10,7 @@
import com.datadog.debugger.instrumentation.InstrumentationResult;
import com.datadog.debugger.instrumentation.MethodInfo;
import com.datadog.debugger.sink.Snapshot;
+import datadog.trace.api.Config;
import datadog.trace.api.Pair;
import datadog.trace.api.sampling.Sampler;
import datadog.trace.bootstrap.debugger.CapturedContext;
@@ -20,9 +21,11 @@
import datadog.trace.bootstrap.debugger.ProbeId;
import datadog.trace.bootstrap.debugger.ProbeImplementation;
import datadog.trace.bootstrap.debugger.ProbeRateLimiter;
+import datadog.trace.bootstrap.debugger.util.TimeoutChecker;
import datadog.trace.bootstrap.instrumentation.api.AgentSpan;
import datadog.trace.bootstrap.instrumentation.api.AgentTracer;
import datadog.trace.util.TagsHelper;
+import java.time.Duration;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -206,10 +209,13 @@ public void evaluate(
CapturedContext.Status status,
MethodLocation methodLocation,
boolean singleProbe) {
+ // Only one timeout for all conditions
+ Duration timeout = Duration.ofMillis(Config.get().getDynamicInstrumentationEvalTimeout());
+ TimeoutChecker timeoutChecker = TimeoutChecker.create(Config.get(), timeout);
for (Decoration decoration : decorations) {
if (decoration.when != null) {
try {
- boolean condition = decoration.when.execute(context);
+ boolean condition = decoration.when.execute(context, timeoutChecker);
if (!condition) {
continue;
}
diff --git a/dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/probe/TriggerProbe.java b/dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/probe/TriggerProbe.java
index f890df1d8e9..945b2a052dc 100644
--- a/dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/probe/TriggerProbe.java
+++ b/dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/probe/TriggerProbe.java
@@ -9,15 +9,18 @@
import com.datadog.debugger.instrumentation.DiagnosticMessage;
import com.datadog.debugger.instrumentation.InstrumentationResult;
import com.datadog.debugger.instrumentation.MethodInfo;
+import datadog.trace.api.Config;
import datadog.trace.api.sampling.Sampler;
import datadog.trace.bootstrap.debugger.CapturedContext;
import datadog.trace.bootstrap.debugger.CapturedContextProbe;
import datadog.trace.bootstrap.debugger.MethodLocation;
import datadog.trace.bootstrap.debugger.ProbeId;
import datadog.trace.bootstrap.debugger.ProbeRateLimiter;
+import datadog.trace.bootstrap.debugger.util.TimeoutChecker;
import datadog.trace.bootstrap.instrumentation.api.AgentSpan;
import datadog.trace.bootstrap.instrumentation.api.AgentTracer;
import datadog.trace.bootstrap.instrumentation.api.Tags;
+import java.time.Duration;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
@@ -134,7 +137,8 @@ private boolean evaluateCondition(CapturedContext capture) {
}
long start = System.nanoTime();
try {
- return probeCondition.execute(capture);
+ Duration timeout = Duration.ofMillis(Config.get().getDynamicInstrumentationEvalTimeout());
+ return probeCondition.execute(capture, TimeoutChecker.create(Config.get(), timeout));
} catch (Exception ex) {
DebuggerAgent.getSink().getProbeStatusSink().addError(probeId, ex);
return false;
diff --git a/dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/util/MoshiSnapshotHelper.java b/dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/util/MoshiSnapshotHelper.java
index 68cbb430c3e..b9aa67c28bf 100644
--- a/dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/util/MoshiSnapshotHelper.java
+++ b/dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/util/MoshiSnapshotHelper.java
@@ -21,7 +21,6 @@
import java.lang.reflect.Type;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
-import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -118,8 +117,7 @@ public void toJson(JsonWriter jsonWriter, Snapshot.Captures captures) throws IOE
jsonWriter.nullValue();
return;
}
- jsonWriter.setTag(
- TimeoutChecker.class, new TimeoutChecker(System.currentTimeMillis(), captureTimeOut));
+ jsonWriter.setTag(TimeoutChecker.class, TimeoutChecker.create(Config.get(), captureTimeOut));
jsonWriter.beginObject();
jsonWriter.name(ENTRY);
capturedContextAdapter.toJson(jsonWriter, captures.getEntry());
@@ -160,12 +158,12 @@ public void toJson(JsonWriter jsonWriter, CapturedContext capturedContext) throw
TimeoutChecker timeoutChecker = jsonWriter.tag(TimeoutChecker.class);
if (timeoutChecker == null) {
Duration timeout =
- Duration.of(Config.get().getDynamicInstrumentationCaptureTimeout(), ChronoUnit.MILLIS);
- timeoutChecker = new TimeoutChecker(timeout);
+ Duration.ofMillis(Config.get().getDynamicInstrumentationCaptureTimeout());
+ timeoutChecker = TimeoutChecker.create(Config.get(), timeout);
}
// need to 'freeze' the context before serializing it
capturedContext.freeze(timeoutChecker);
- if (timeoutChecker.isTimedOut(System.currentTimeMillis())) {
+ if (timeoutChecker.isTimedOut()) {
jsonWriter.beginObject();
jsonWriter.name(NOT_CAPTURED_REASON);
jsonWriter.value(TIMEOUT_REASON);
@@ -273,7 +271,7 @@ private SerializationResult toJsonCapturedValues(
if (count >= limits.maxFieldCount) {
return SerializationResult.FIELD_COUNT;
}
- if (timeoutChecker.isTimedOut(System.currentTimeMillis())) {
+ if (timeoutChecker.isTimedOut()) {
return SerializationResult.TIMEOUT;
}
jsonWriter.name(entry.getKey());
@@ -305,7 +303,7 @@ public void toJson(JsonWriter jsonWriter, CapturedContext.CapturedValue captured
}
TimeoutChecker timeoutChecker = capturedValue.getTimeoutChecker();
if (timeoutChecker == null) {
- timeoutChecker = new TimeoutChecker(Duration.of(10, ChronoUnit.MILLIS));
+ timeoutChecker = TimeoutChecker.create(Config.get(), Duration.ofMillis(10));
}
Object value = capturedValue.getValue();
String type = capturedValue.getType();
diff --git a/dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/util/SerializerWithLimits.java b/dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/util/SerializerWithLimits.java
index 0ee03a7f52a..211543efa14 100644
--- a/dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/util/SerializerWithLimits.java
+++ b/dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/util/SerializerWithLimits.java
@@ -137,7 +137,7 @@ public void serialize(Object value, String type, Limits limits) throws Exception
tokenWriter.epilogue(value);
return;
}
- if (timeoutChecker.isTimedOut(System.currentTimeMillis())) {
+ if (timeoutChecker.isTimedOut()) {
tokenWriter.notCaptured(NotCapturedReason.TIMEOUT);
tokenWriter.epilogue(value);
return;
diff --git a/dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/util/ValueScriptHelper.java b/dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/util/ValueScriptHelper.java
index bdbbacec81d..1ae9d5079d2 100644
--- a/dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/util/ValueScriptHelper.java
+++ b/dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/util/ValueScriptHelper.java
@@ -6,14 +6,12 @@
import datadog.trace.bootstrap.debugger.Limits;
import datadog.trace.bootstrap.debugger.util.TimeoutChecker;
import java.time.Duration;
-import java.time.temporal.ChronoUnit;
public class ValueScriptHelper {
public static void serializeValue(
StringBuilder sb, String expr, Object value, CapturedContext.Status status, Limits limits) {
- Duration timeout =
- Duration.of(Config.get().getDynamicInstrumentationCaptureTimeout(), ChronoUnit.MILLIS);
- TimeoutChecker timeoutChecker = new TimeoutChecker(timeout);
+ Duration timeout = Duration.ofMillis(Config.get().getDynamicInstrumentationCaptureTimeout());
+ TimeoutChecker timeoutChecker = TimeoutChecker.create(Config.get(), timeout);
SerializerWithLimits serializer =
new SerializerWithLimits(new StringTokenWriter(sb, status.getErrors()), timeoutChecker);
try {
diff --git a/dd-java-agent/agent-debugger/src/test/java/com/datadog/debugger/agent/SnapshotSerializationTest.java b/dd-java-agent/agent-debugger/src/test/java/com/datadog/debugger/agent/SnapshotSerializationTest.java
index 539a123b52d..0018c6d182b 100644
--- a/dd-java-agent/agent-debugger/src/test/java/com/datadog/debugger/agent/SnapshotSerializationTest.java
+++ b/dd-java-agent/agent-debugger/src/test/java/com/datadog/debugger/agent/SnapshotSerializationTest.java
@@ -31,6 +31,7 @@
import com.datadog.debugger.util.MoshiSnapshotTestHelper;
import com.squareup.moshi.JsonAdapter;
import datadog.environment.JavaVirtualMachine;
+import datadog.trace.api.Config;
import datadog.trace.bootstrap.debugger.CapturedContext;
import datadog.trace.bootstrap.debugger.CapturedStackFrame;
import datadog.trace.bootstrap.debugger.DebuggerContext;
@@ -922,11 +923,9 @@ public void fieldCount20() throws IOException {
@Test
@Flaky
public void timeOut() throws IOException {
- DebuggerContext.initValueSerializer(
- new TimeoutSnapshotSerializer(Duration.of(150, ChronoUnit.MILLIS)));
+ DebuggerContext.initValueSerializer(new TimeoutSnapshotSerializer(Duration.ofMillis(150)));
JsonAdapter adapter =
- MoshiHelper.createMoshiSnapshot(Duration.of(100, ChronoUnit.MILLIS))
- .adapter(Snapshot.class);
+ MoshiHelper.createMoshiSnapshot(Duration.ofMillis(100)).adapter(Snapshot.class);
Snapshot snapshot = createSnapshot();
CapturedContext context = new CapturedContext();
CapturedContext.CapturedValue arg1 = CapturedContext.CapturedValue.of("arg1", "int", 42);
@@ -949,7 +948,7 @@ public void valueTimeout() throws IOException {
new TimeoutSnapshotSerializer(Duration.of(20, ChronoUnit.MILLIS)));
CapturedContext.CapturedValue arg1 =
CapturedContext.CapturedValue.of("arg1", Random.class.getTypeName(), new Random(0));
- arg1.freeze(new TimeoutChecker(Duration.ofMillis(10)));
+ arg1.freeze(TimeoutChecker.create(Config.get(), Duration.ofMillis(10)));
String buffer = arg1.getStrValue();
System.out.println(buffer);
Map json = MoshiHelper.createGenericAdapter().fromJson(buffer);
diff --git a/dd-java-agent/agent-debugger/src/test/java/com/datadog/debugger/el/ELIntegrationSanityTest.java b/dd-java-agent/agent-debugger/src/test/java/com/datadog/debugger/el/ELIntegrationSanityTest.java
index 9ac26df3239..7b6382cae21 100644
--- a/dd-java-agent/agent-debugger/src/test/java/com/datadog/debugger/el/ELIntegrationSanityTest.java
+++ b/dd-java-agent/agent-debugger/src/test/java/com/datadog/debugger/el/ELIntegrationSanityTest.java
@@ -4,6 +4,7 @@
import static org.junit.jupiter.api.Assertions.assertEquals;
import com.datadog.debugger.agent.JsonSnapshotSerializer;
+import datadog.trace.api.Config;
import datadog.trace.bootstrap.debugger.CapturedContext;
import datadog.trace.bootstrap.debugger.DebuggerContext;
import datadog.trace.bootstrap.debugger.Limits;
@@ -59,12 +60,16 @@ void extractAfterEl() throws IllegalAccessException {
capturedContext.addArguments(new CapturedContext.CapturedValue[] {thisValue});
// '.name.value' is not present in the snapshot - it needs to be retrieved via reflection
- Value> val = DSL.getMember(DSL.ref("name"), "value").evaluate(capturedContext);
+ Value> val =
+ DSL.getMember(DSL.ref("name"), "value")
+ .evaluate(
+ new EvalContext(
+ capturedContext, TimeoutChecker.create(Config.get(), Duration.ofMillis(1000))));
// make sure the nested field was properly resolved
assertEquals(p.name.value, val.getValue());
// freeze the captured context
- capturedContext.freeze(new TimeoutChecker(Duration.of(1, ChronoUnit.SECONDS)));
+ capturedContext.freeze(TimeoutChecker.create(Config.get(), Duration.of(1, ChronoUnit.SECONDS)));
// after freezing the original value is removed and only the serialized json representation
// remains
diff --git a/dd-java-agent/agent-debugger/src/test/java/com/datadog/debugger/util/StringTokenWriterTest.java b/dd-java-agent/agent-debugger/src/test/java/com/datadog/debugger/util/StringTokenWriterTest.java
index 2480ca2004c..3009ff735d6 100644
--- a/dd-java-agent/agent-debugger/src/test/java/com/datadog/debugger/util/StringTokenWriterTest.java
+++ b/dd-java-agent/agent-debugger/src/test/java/com/datadog/debugger/util/StringTokenWriterTest.java
@@ -7,10 +7,10 @@
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
+import datadog.trace.api.Config;
import datadog.trace.bootstrap.debugger.Limits;
import datadog.trace.bootstrap.debugger.util.TimeoutChecker;
import java.time.Duration;
-import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -175,7 +175,7 @@ private String serializeValue(Object value, Limits limits) throws Exception {
SerializerWithLimits serializer =
new SerializerWithLimits(
new StringTokenWriter(sb, new ArrayList<>()),
- new TimeoutChecker(Duration.of(300, ChronoUnit.SECONDS)));
+ TimeoutChecker.create(Config.get(), Duration.ofSeconds(300)));
serializer.serialize(
value, value != null ? value.getClass().getTypeName() : Object.class.getTypeName(), limits);
return sb.toString();
diff --git a/dd-smoke-tests/debugger-integration-tests/src/main/java/datadog/smoketest/debugger/DebuggerTestApplication.java b/dd-smoke-tests/debugger-integration-tests/src/main/java/datadog/smoketest/debugger/DebuggerTestApplication.java
index 2c1ffc19559..030167f6496 100644
--- a/dd-smoke-tests/debugger-integration-tests/src/main/java/datadog/smoketest/debugger/DebuggerTestApplication.java
+++ b/dd-smoke-tests/debugger-integration-tests/src/main/java/datadog/smoketest/debugger/DebuggerTestApplication.java
@@ -6,7 +6,9 @@
import java.lang.management.ManagementFactory;
import java.lang.management.OperatingSystemMXBean;
+import java.util.ArrayList;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
@@ -51,6 +53,7 @@ private static void registerMethods() {
methodsByName.put("multiProbesFullMethod", Main::runFullMethod);
methodsByName.put("loopingFullMethod", Main::runLoopingFullMethod);
methodsByName.put("exceptionMethod", Main::runExceptionMethod);
+ methodsByName.put("processLargeCollection", Main::runProcessLargeCollection);
}
private static void emptyMethod(String arg) {}
@@ -82,6 +85,10 @@ private static void runExceptionMethod(String s) {
exceptionMethod(s);
}
+ private static void runProcessLargeCollection(String arg) {
+ processLargeCollection(1_000_000);
+ }
+
private static String fullMethod(
int argInt, String argStr, double argDouble, Map argMap, String... argVar) {
try {
@@ -113,4 +120,14 @@ private static void exceptionMethod(String arg) {
}
}
}
+
+ private static void processLargeCollection(int largeListSize) {
+ List largeList = new ArrayList<>();
+ for (int i = 0; i < largeListSize; i++) {
+ largeList.add("foobar" + i);
+ }
+ for (int i = 0; i < largeListSize; i++) {
+ largeList.get(i);
+ }
+ }
}
diff --git a/dd-smoke-tests/debugger-integration-tests/src/test/java/datadog/smoketest/LogProbesIntegrationTest.java b/dd-smoke-tests/debugger-integration-tests/src/test/java/datadog/smoketest/LogProbesIntegrationTest.java
index 10c2bd38bd9..2d594af97e7 100644
--- a/dd-smoke-tests/debugger-integration-tests/src/test/java/datadog/smoketest/LogProbesIntegrationTest.java
+++ b/dd-smoke-tests/debugger-integration-tests/src/test/java/datadog/smoketest/LogProbesIntegrationTest.java
@@ -1,7 +1,9 @@
package datadog.smoketest;
+import static com.datadog.debugger.el.DSL.all;
import static com.datadog.debugger.el.DSL.and;
import static com.datadog.debugger.el.DSL.eq;
+import static com.datadog.debugger.el.DSL.filter;
import static com.datadog.debugger.el.DSL.gt;
import static com.datadog.debugger.el.DSL.len;
import static com.datadog.debugger.el.DSL.nullValue;
@@ -9,6 +11,7 @@
import static com.datadog.debugger.el.DSL.value;
import static com.datadog.debugger.el.DSL.when;
import static com.datadog.debugger.util.LogProbeTestHelper.parseTemplate;
+import static java.util.Collections.singletonList;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
@@ -573,6 +576,74 @@ void testCaughtException() throws Exception {
() -> String.format("timeout snapshotReceived=%s", snapshotReceived.get()));
}
+ @Test
+ @DisplayName("testConditionTimeout")
+ void testConditionTimeout() throws Exception {
+ final String EXPECTED_UPLOADS = "4"; // 3 statuses + 1 snapshot
+ final String METHOD_NAME = "processLargeCollection";
+ LogProbe probe =
+ LogProbe.builder()
+ .probeId(PROBE_ID)
+ .where(MAIN_CLASS_NAME, METHOD_NAME)
+ .evaluateAt(MethodLocation.EXIT)
+ .captureSnapshot(true)
+ .when(
+ new ProbeCondition(
+ when(all(ref("largeList"), gt(len(ref("@it")), value(0)))),
+ "all(largeList, {len(@it) > 0}"))
+ .build();
+ setCurrentConfiguration(createConfig(probe));
+ targetProcess = createProcessBuilder(logFilePath, METHOD_NAME, EXPECTED_UPLOADS).start();
+ AtomicBoolean snapshotReceived = new AtomicBoolean();
+ registerSnapshotListener(
+ snapshot -> {
+ if (snapshot.getProbe().getProbeId().equals(PROBE_ID)) {
+ assertEquals(1, snapshot.getEvaluationErrors().size());
+ assertEquals("timeout (50ms)", snapshot.getEvaluationErrors().get(0).getMessage());
+ snapshotReceived.set(true);
+ }
+ });
+ processRequests(
+ snapshotReceived::get,
+ () -> String.format("timeout snapshotReceived=%s", snapshotReceived.get()));
+ }
+
+ @Test
+ @DisplayName("testTemplateTimeout")
+ void testTemplateTimeout() throws Exception {
+ final String EXPECTED_UPLOADS = "4"; // 3 statuses + 1 snapshot
+ final String METHOD_NAME = "processLargeCollection";
+ final String LARGE_COLLECTION_TEMPLATE = "{filter(largeList, {len(@it) > 0})}";
+ List segments =
+ singletonList(
+ new LogProbe.Segment(
+ new ValueScript(
+ filter(ref("largeList"), gt(len(ref("@it")), value(0))),
+ "filter(largeList, {len(@it) > 0})")));
+ LogProbe probe =
+ LogProbe.builder()
+ .probeId(PROBE_ID)
+ .where(MAIN_CLASS_NAME, METHOD_NAME)
+ .evaluateAt(MethodLocation.EXIT)
+ .captureSnapshot(true)
+ .template(LARGE_COLLECTION_TEMPLATE, segments)
+ .build();
+ setCurrentConfiguration(createConfig(probe));
+ targetProcess = createProcessBuilder(logFilePath, METHOD_NAME, EXPECTED_UPLOADS).start();
+ AtomicBoolean snapshotReceived = new AtomicBoolean();
+ registerSnapshotListener(
+ snapshot -> {
+ if (snapshot.getProbe().getProbeId().equals(PROBE_ID)) {
+ assertEquals(1, snapshot.getEvaluationErrors().size());
+ assertEquals("timeout (50ms)", snapshot.getEvaluationErrors().get(0).getMessage());
+ snapshotReceived.set(true);
+ }
+ });
+ processRequests(
+ snapshotReceived::get,
+ () -> String.format("timeout snapshotReceived=%s", snapshotReceived.get()));
+ }
+
private ProbeId getProbeId(int i) {
return new ProbeId(String.valueOf(i), 0);
}
diff --git a/dd-smoke-tests/debugger-integration-tests/src/test/java/datadog/smoketest/MoshiConfigTestHelper.java b/dd-smoke-tests/debugger-integration-tests/src/test/java/datadog/smoketest/MoshiConfigTestHelper.java
index a19c5833212..23eb7f6fb17 100644
--- a/dd-smoke-tests/debugger-integration-tests/src/test/java/datadog/smoketest/MoshiConfigTestHelper.java
+++ b/dd-smoke-tests/debugger-integration-tests/src/test/java/datadog/smoketest/MoshiConfigTestHelper.java
@@ -153,7 +153,20 @@ public Void visit(FilterCollectionExpression filterCollectionExpression) {
@Override
public Void visit(HasAllExpression hasAllExpression) {
- throw new UnsupportedOperationException("hasAll expression");
+ try {
+ jsonWriter.beginObject();
+ jsonWriter.name("all");
+ jsonWriter.beginArray();
+ hasAllExpression.getValueExpression().accept(this);
+ // jsonWriter.beginObject();
+ hasAllExpression.getFilterPredicateExpression().accept(this);
+ // jsonWriter.endObject();
+ jsonWriter.endArray();
+ jsonWriter.endObject();
+ } catch (IOException ex) {
+ LOGGER.debug("Cannot serialize: ", ex);
+ }
+ return null;
}
@Override
diff --git a/dd-smoke-tests/debugger-integration-tests/src/test/java/datadog/smoketest/SpanDecorationProbesIntegrationTests.java b/dd-smoke-tests/debugger-integration-tests/src/test/java/datadog/smoketest/SpanDecorationProbesIntegrationTests.java
index 93009c1a929..0785aac3a83 100644
--- a/dd-smoke-tests/debugger-integration-tests/src/test/java/datadog/smoketest/SpanDecorationProbesIntegrationTests.java
+++ b/dd-smoke-tests/debugger-integration-tests/src/test/java/datadog/smoketest/SpanDecorationProbesIntegrationTests.java
@@ -44,6 +44,8 @@ void setup(TestInfo testInfo) throws Exception {
protected ProcessBuilder createProcessBuilder(Path logFilePath, String... params) {
List commandParams = getDebuggerCommandParams();
commandParams.add("-Ddd.trace.enabled=true"); // explicitly enable tracer
+ // increase eval timeout for decoration evaluations
+ commandParams.add("-Ddd.dynamic.instrumentation.evaluation.timeout.ms=100");
return ProcessBuilderHelper.createProcessBuilder(
commandParams, logFilePath, getAppClass(), params);
}
diff --git a/dd-smoke-tests/debugger-integration-tests/src/test/java/datadog/smoketest/SpanProbesIntegrationTest.java b/dd-smoke-tests/debugger-integration-tests/src/test/java/datadog/smoketest/SpanProbesIntegrationTest.java
index 3c55b8ff759..6cf6f17f883 100644
--- a/dd-smoke-tests/debugger-integration-tests/src/test/java/datadog/smoketest/SpanProbesIntegrationTest.java
+++ b/dd-smoke-tests/debugger-integration-tests/src/test/java/datadog/smoketest/SpanProbesIntegrationTest.java
@@ -60,7 +60,7 @@ void testLineRangeSpan() throws Exception {
.probeId(PROBE_ID)
// from line: System.out.println("fullMethod");
// to line: + String.join(",", argVar);
- .where(MAIN_CLASS_NAME, 88, 97)
+ .where(MAIN_CLASS_NAME, 95, 104)
.build();
setCurrentConfiguration(createSpanConfig(spanProbe));
targetProcess = createProcessBuilder(logFilePath, METHOD_NAME, EXPECTED_UPLOADS).start();
@@ -69,7 +69,7 @@ void testLineRangeSpan() throws Exception {
registerTraceListener(
decodedTrace -> {
DecodedSpan decodedSpan = decodedTrace.getSpans().get(0);
- assertEquals("Main.fullMethod:L88-97", decodedSpan.getResource());
+ assertEquals("Main.fullMethod:L95-104", decodedSpan.getResource());
traceReceived.set(true);
});
processRequests(
@@ -92,7 +92,7 @@ void testSingleLineSpan() throws Exception {
SpanProbe.builder()
.probeId(PROBE_ID)
// on line: System.out.println("fullMethod");
- .where(MAIN_CLASS_NAME, 88)
+ .where(MAIN_CLASS_NAME, 95)
.build();
setCurrentConfiguration(createSpanConfig(spanProbe));
targetProcess = createProcessBuilder(logFilePath, METHOD_NAME, EXPECTED_UPLOADS).start();
diff --git a/dd-trace-api/src/main/java/datadog/trace/api/ConfigDefaults.java b/dd-trace-api/src/main/java/datadog/trace/api/ConfigDefaults.java
index 061698283a7..1aba2cb276b 100644
--- a/dd-trace-api/src/main/java/datadog/trace/api/ConfigDefaults.java
+++ b/dd-trace-api/src/main/java/datadog/trace/api/ConfigDefaults.java
@@ -231,7 +231,9 @@ public final class ConfigDefaults {
static final int DEFAULT_DYNAMIC_INSTRUMENTATION_UPLOAD_BATCH_SIZE = 100;
static final int DEFAULT_DYNAMIC_INSTRUMENTATION_MAX_PAYLOAD_SIZE = 1024; // KiB
static final boolean DEFAULT_DYNAMIC_INSTRUMENTATION_VERIFY_BYTECODE = true;
+ static final String DEFAULT_DYNAMIC_INSTRUMENTATION_TIMEOUT_CHECKER_MODE = "WALL";
static final int DEFAULT_DYNAMIC_INSTRUMENTATION_CAPTURE_TIMEOUT = 100; // milliseconds
+ static final int DEFAULT_DYNAMIC_INSTRUMENTATION_EVAL_TIMEOUT = 50; // milliseconds
static final int DEFAULT_DYNAMIC_INSTRUMENTATION_LOCALVAR_HOISTING_LEVEL = 1;
static final boolean DEFAULT_SYMBOL_DATABASE_ENABLED = true;
static final boolean DEFAULT_SYMBOL_DATABASE_FORCE_UPLOAD = false;
diff --git a/dd-trace-api/src/main/java/datadog/trace/api/config/DebuggerConfig.java b/dd-trace-api/src/main/java/datadog/trace/api/config/DebuggerConfig.java
index 606267fa285..1e9d90c2e43 100644
--- a/dd-trace-api/src/main/java/datadog/trace/api/config/DebuggerConfig.java
+++ b/dd-trace-api/src/main/java/datadog/trace/api/config/DebuggerConfig.java
@@ -32,8 +32,14 @@ public final class DebuggerConfig {
"dynamic.instrumentation.exclude.files";
public static final String DYNAMIC_INSTRUMENTATION_INCLUDE_FILES =
"dynamic.instrumentation.include.files";
+ public static final String DYNAMIC_INSTRUMENTATION_TIMEOUT_CHECKER_MODE =
+ "internal.dynamic.instrumentation.timeout.checker.mode";
public static final String DYNAMIC_INSTRUMENTATION_CAPTURE_TIMEOUT =
"dynamic.instrumentation.capture.timeout";
+ public static final String DYNAMIC_INSTRUMENTATION_CAPTURE_TIMEOUT_MS =
+ "dynamic.instrumentation.capture.timeout.ms";
+ public static final String DYNAMIC_INSTRUMENTATION_EVAL_TIMEOUT_MS =
+ "dynamic.instrumentation.evaluation.timeout.ms";
public static final String DYNAMIC_INSTRUMENTATION_REDACTED_IDENTIFIERS =
"dynamic.instrumentation.redacted.identifiers";
public static final String DYNAMIC_INSTRUMENTATION_REDACTION_EXCLUDED_IDENTIFIERS =
diff --git a/internal-api/src/main/java/datadog/trace/api/Config.java b/internal-api/src/main/java/datadog/trace/api/Config.java
index b10bda7c683..32e753d69fb 100644
--- a/internal-api/src/main/java/datadog/trace/api/Config.java
+++ b/internal-api/src/main/java/datadog/trace/api/Config.java
@@ -72,10 +72,12 @@
import static datadog.trace.api.ConfigDefaults.DEFAULT_DYNAMIC_INSTRUMENTATION_CLASSFILE_DUMP_ENABLED;
import static datadog.trace.api.ConfigDefaults.DEFAULT_DYNAMIC_INSTRUMENTATION_DIAGNOSTICS_INTERVAL;
import static datadog.trace.api.ConfigDefaults.DEFAULT_DYNAMIC_INSTRUMENTATION_ENABLED;
+import static datadog.trace.api.ConfigDefaults.DEFAULT_DYNAMIC_INSTRUMENTATION_EVAL_TIMEOUT;
import static datadog.trace.api.ConfigDefaults.DEFAULT_DYNAMIC_INSTRUMENTATION_LOCALVAR_HOISTING_LEVEL;
import static datadog.trace.api.ConfigDefaults.DEFAULT_DYNAMIC_INSTRUMENTATION_MAX_PAYLOAD_SIZE;
import static datadog.trace.api.ConfigDefaults.DEFAULT_DYNAMIC_INSTRUMENTATION_METRICS_ENABLED;
import static datadog.trace.api.ConfigDefaults.DEFAULT_DYNAMIC_INSTRUMENTATION_POLL_INTERVAL;
+import static datadog.trace.api.ConfigDefaults.DEFAULT_DYNAMIC_INSTRUMENTATION_TIMEOUT_CHECKER_MODE;
import static datadog.trace.api.ConfigDefaults.DEFAULT_DYNAMIC_INSTRUMENTATION_UPLOAD_BATCH_SIZE;
import static datadog.trace.api.ConfigDefaults.DEFAULT_DYNAMIC_INSTRUMENTATION_UPLOAD_FLUSH_INTERVAL;
import static datadog.trace.api.ConfigDefaults.DEFAULT_DYNAMIC_INSTRUMENTATION_UPLOAD_TIMEOUT;
@@ -325,9 +327,11 @@
import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_SOURCE_FILE_TRACKING_ENABLED;
import static datadog.trace.api.config.DebuggerConfig.DISTRIBUTED_DEBUGGER_ENABLED;
import static datadog.trace.api.config.DebuggerConfig.DYNAMIC_INSTRUMENTATION_CAPTURE_TIMEOUT;
+import static datadog.trace.api.config.DebuggerConfig.DYNAMIC_INSTRUMENTATION_CAPTURE_TIMEOUT_MS;
import static datadog.trace.api.config.DebuggerConfig.DYNAMIC_INSTRUMENTATION_CLASSFILE_DUMP_ENABLED;
import static datadog.trace.api.config.DebuggerConfig.DYNAMIC_INSTRUMENTATION_DIAGNOSTICS_INTERVAL;
import static datadog.trace.api.config.DebuggerConfig.DYNAMIC_INSTRUMENTATION_ENABLED;
+import static datadog.trace.api.config.DebuggerConfig.DYNAMIC_INSTRUMENTATION_EVAL_TIMEOUT_MS;
import static datadog.trace.api.config.DebuggerConfig.DYNAMIC_INSTRUMENTATION_EXCLUDE_FILES;
import static datadog.trace.api.config.DebuggerConfig.DYNAMIC_INSTRUMENTATION_INCLUDE_FILES;
import static datadog.trace.api.config.DebuggerConfig.DYNAMIC_INSTRUMENTATION_INSTRUMENT_THE_WORLD;
@@ -340,6 +344,7 @@
import static datadog.trace.api.config.DebuggerConfig.DYNAMIC_INSTRUMENTATION_REDACTED_TYPES;
import static datadog.trace.api.config.DebuggerConfig.DYNAMIC_INSTRUMENTATION_REDACTION_EXCLUDED_IDENTIFIERS;
import static datadog.trace.api.config.DebuggerConfig.DYNAMIC_INSTRUMENTATION_SNAPSHOT_URL;
+import static datadog.trace.api.config.DebuggerConfig.DYNAMIC_INSTRUMENTATION_TIMEOUT_CHECKER_MODE;
import static datadog.trace.api.config.DebuggerConfig.DYNAMIC_INSTRUMENTATION_UPLOAD_BATCH_SIZE;
import static datadog.trace.api.config.DebuggerConfig.DYNAMIC_INSTRUMENTATION_UPLOAD_FLUSH_INTERVAL;
import static datadog.trace.api.config.DebuggerConfig.DYNAMIC_INSTRUMENTATION_UPLOAD_INTERVAL_SECONDS;
@@ -1229,7 +1234,9 @@ public static String getHostName() {
private final String dynamicInstrumentationInstrumentTheWorld;
private final String dynamicInstrumentationExcludeFiles;
private final String dynamicInstrumentationIncludeFiles;
+ private final String dynamicInstrumentationTimeoutCheckerMode;
private final int dynamicInstrumentationCaptureTimeout;
+ private final int dynamicInstrumentationEvaluationTimeout;
private final String dynamicInstrumentationRedactedIdentifiers;
private final Set dynamicInstrumentationRedactionExcludedIdentifiers;
private final String dynamicInstrumentationRedactedTypes;
@@ -2886,10 +2893,18 @@ PROFILING_DATADOG_PROFILER_ENABLED, isDatadogProfilerSafeInCurrentEnvironment())
configProvider.getString(DYNAMIC_INSTRUMENTATION_EXCLUDE_FILES);
dynamicInstrumentationIncludeFiles =
configProvider.getString(DYNAMIC_INSTRUMENTATION_INCLUDE_FILES);
+ dynamicInstrumentationTimeoutCheckerMode =
+ configProvider.getString(
+ DYNAMIC_INSTRUMENTATION_TIMEOUT_CHECKER_MODE,
+ DEFAULT_DYNAMIC_INSTRUMENTATION_TIMEOUT_CHECKER_MODE);
dynamicInstrumentationCaptureTimeout =
configProvider.getInteger(
DYNAMIC_INSTRUMENTATION_CAPTURE_TIMEOUT,
- DEFAULT_DYNAMIC_INSTRUMENTATION_CAPTURE_TIMEOUT);
+ DEFAULT_DYNAMIC_INSTRUMENTATION_CAPTURE_TIMEOUT,
+ DYNAMIC_INSTRUMENTATION_CAPTURE_TIMEOUT_MS);
+ dynamicInstrumentationEvaluationTimeout =
+ configProvider.getInteger(
+ DYNAMIC_INSTRUMENTATION_EVAL_TIMEOUT_MS, DEFAULT_DYNAMIC_INSTRUMENTATION_EVAL_TIMEOUT);
dynamicInstrumentationRedactedIdentifiers =
configProvider.getString(DYNAMIC_INSTRUMENTATION_REDACTED_IDENTIFIERS, null);
dynamicInstrumentationRedactionExcludedIdentifiers =
@@ -4689,10 +4704,18 @@ public String getDynamicInstrumentationIncludeFiles() {
return dynamicInstrumentationIncludeFiles;
}
+ public String getDynamicInstrumentationTimeoutCheckerMode() {
+ return dynamicInstrumentationTimeoutCheckerMode;
+ }
+
public int getDynamicInstrumentationCaptureTimeout() {
return dynamicInstrumentationCaptureTimeout;
}
+ public int getDynamicInstrumentationEvalTimeout() {
+ return dynamicInstrumentationEvaluationTimeout;
+ }
+
public boolean isSymbolDatabaseEnabled() {
return symbolDatabaseEnabled;
}
diff --git a/metadata/supported-configurations.json b/metadata/supported-configurations.json
index ae081138b71..60dae10c020 100644
--- a/metadata/supported-configurations.json
+++ b/metadata/supported-configurations.json
@@ -1217,11 +1217,27 @@
"aliases": ["DD_JMXFETCH_START_DELAY"]
}
],
- "DD_DYNAMIC_INSTRUMENTATION_CAPTURE_TIMEOUT": [
+ "DD_INTERNAL_DYNAMIC_INSTRUMENTATION_TIMEOUT_CHECKER_MODE": [
{
"version": "A",
+ "type": "string",
+ "default": "WALL",
+ "aliases": []
+ }
+ ],
+ "DD_DYNAMIC_INSTRUMENTATION_CAPTURE_TIMEOUT_MS": [
+ {
+ "version": "B",
"type": "int",
"default": "100",
+ "aliases": ["DD_DYNAMIC_INSTRUMENTATION_CAPTURE_TIMEOUT"]
+ }
+ ],
+ "DD_DYNAMIC_INSTRUMENTATION_EVALUATION_TIMEOUT_MS": [
+ {
+ "version": "A",
+ "type": "int",
+ "default": "50",
"aliases": []
}
],