Skip to content

Commit eea0d38

Browse files
ChinmayMadeshicopybara-github
authored andcommitted
Internal Changes
PiperOrigin-RevId: 808012281
1 parent b202efc commit eea0d38

2 files changed

Lines changed: 76 additions & 18 deletions

File tree

testing/src/main/java/dev/cel/testing/testrunner/CelCoverageIndex.java

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import com.google.auto.value.AutoValue;
2020
import com.google.common.collect.ImmutableList;
21+
import com.google.common.io.Files;
2122
import com.google.errorprone.annotations.CanIgnoreReturnValue;
2223
import javax.annotation.concurrent.ThreadSafe;
2324
import dev.cel.common.CelAbstractSyntaxTree;
@@ -28,6 +29,8 @@
2829
import dev.cel.common.types.CelKind;
2930
import dev.cel.parser.CelUnparserVisitor;
3031
import dev.cel.runtime.CelEvaluationListener;
32+
import java.io.File;
33+
import java.io.IOException;
3134
import java.io.UnsupportedEncodingException;
3235
import java.net.URLEncoder;
3336
import java.util.Map;
@@ -156,7 +159,13 @@ public final Builder addUnencounteredBranches(String value) {
156159
}
157160
}
158161

159-
/** Returns the coverage report for the CEL test suite. */
162+
/**
163+
* Generates a coverage report for the CEL test suite.
164+
*
165+
* <p>Note: If the generated graph URL results in a `Request Entity Too Large` error, download the
166+
* `coverage_graph.txt` file from the test artifacts and upload its contents to <a
167+
* href="https://graphviz.corp.google.com/">Graphviz</a> to render the coverage graph.
168+
*/
160169
public CoverageReport generateCoverageReport() {
161170
CoverageReport.Builder reportBuilder =
162171
CoverageReport.builder().setCelExpression(new CelUnparserVisitor(ast).unparse());
@@ -170,6 +179,7 @@ public CoverageReport generateCoverageReport() {
170179
dotGraphBuilder);
171180
dotGraphBuilder.append("}");
172181
String dotGraph = dotGraphBuilder.toString();
182+
173183
CoverageReport report = reportBuilder.setDotGraph(dotGraph).build();
174184
logger.info("CEL Expression: " + report.celExpression());
175185
logger.info("Nodes: " + report.nodes());
@@ -180,6 +190,8 @@ public CoverageReport generateCoverageReport() {
180190
logger.info("Unencountered Branches: \n" + String.join("\n",
181191
report.unencounteredBranches()));
182192
logger.info("Dot Graph: " + report.dotGraph());
193+
194+
writeDotGraphToArtifact(dotGraph);
183195
return report;
184196
}
185197

@@ -392,4 +404,21 @@ private String escapeSpecialCharacters(String exprText) {
392404
.replace("{", "\\{")
393405
.replace("}", "\\}");
394406
}
407+
408+
private void writeDotGraphToArtifact(String dotGraph) {
409+
String testOutputsDir = System.getenv("TEST_UNDECLARED_OUTPUTS_DIR");
410+
if (testOutputsDir == null) {
411+
// Only for non-bazel/blaze users, we write to a subdirectory under the cwd.
412+
testOutputsDir = "cel_artifacts";
413+
}
414+
File outputDir = new File(testOutputsDir, "cel_test_coverage");
415+
if (!outputDir.exists()) {
416+
outputDir.mkdirs();
417+
}
418+
try {
419+
Files.asCharSink(new File(outputDir, "coverage_graph.txt"), UTF_8).write(dotGraph);
420+
} catch (IOException e) {
421+
throw new IllegalStateException(e);
422+
}
423+
}
395424
}

testing/src/test/java/dev/cel/testing/testrunner/CelCoverageIndexTest.java

Lines changed: 46 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,10 @@
1414
package dev.cel.testing.testrunner;
1515

1616
import static com.google.common.truth.Truth.assertThat;
17+
import static java.nio.charset.StandardCharsets.UTF_8;
1718

1819
import com.google.common.collect.ImmutableMap;
20+
import com.google.common.io.Files;
1921
import dev.cel.bundle.Cel;
2022
import dev.cel.bundle.CelFactory;
2123
import dev.cel.common.CelAbstractSyntaxTree;
@@ -27,31 +29,23 @@
2729
import dev.cel.runtime.CelEvaluationListener;
2830
import dev.cel.runtime.CelRuntime;
2931
import dev.cel.testing.testrunner.CelCoverageIndex.CoverageReport;
30-
import org.junit.Before;
32+
import java.io.File;
3133
import org.junit.Test;
3234
import org.junit.runner.RunWith;
3335
import org.junit.runners.JUnit4;
3436

3537
@RunWith(JUnit4.class)
3638
public final class CelCoverageIndexTest {
3739

38-
private Cel cel;
39-
private CelAbstractSyntaxTree ast;
40-
private CelRuntime.Program program;
41-
42-
@Before
43-
public void setUp() throws Exception {
44-
cel =
40+
@Test
41+
public void getCoverageReport_fullCoverage() throws Exception {
42+
Cel cel =
4543
CelFactory.standardCelBuilder()
4644
.addVar("x", SimpleType.INT)
4745
.addVar("y", SimpleType.INT)
4846
.build();
49-
ast = cel.compile("x > 1 && y > 1").getAst();
50-
program = cel.createProgram(ast);
51-
}
52-
53-
@Test
54-
public void getCoverageReport_fullCoverage() throws Exception {
47+
CelAbstractSyntaxTree ast = cel.compile("x > 1 && y > 1").getAst();
48+
CelRuntime.Program program = cel.createProgram(ast);
5549
CelCoverageIndex coverageIndex = new CelCoverageIndex();
5650
coverageIndex.init(ast);
5751
CelEvaluationListener listener = coverageIndex.newEvaluationListener();
@@ -74,6 +68,13 @@ public void getCoverageReport_fullCoverage() throws Exception {
7468

7569
@Test
7670
public void getCoverageReport_partialCoverage_shortCircuit() throws Exception {
71+
Cel cel =
72+
CelFactory.standardCelBuilder()
73+
.addVar("x", SimpleType.INT)
74+
.addVar("y", SimpleType.INT)
75+
.build();
76+
CelAbstractSyntaxTree ast = cel.compile("x > 1 && y > 1").getAst();
77+
CelRuntime.Program program = cel.createProgram(ast);
7778
CelCoverageIndex coverageIndex = new CelCoverageIndex();
7879
coverageIndex.init(ast);
7980
CelEvaluationListener listener = coverageIndex.newEvaluationListener();
@@ -97,15 +98,15 @@ public void getCoverageReport_partialCoverage_shortCircuit() throws Exception {
9798

9899
@Test
99100
public void getCoverageReport_comprehension_generatesDotGraph() throws Exception {
100-
cel = CelFactory.standardCelBuilder().build();
101+
Cel cel = CelFactory.standardCelBuilder().build();
101102
CelCompiler compiler =
102103
cel.toCompilerBuilder()
103104
.setOptions(CelOptions.newBuilder().populateMacroCalls(true).build())
104105
.setStandardMacros(CelStandardMacro.STANDARD_MACROS)
105106
.addLibraries(CelExtensions.comprehensions())
106107
.build();
107-
ast = compiler.compile("[1, 2, 3].all(i, i % 2 != 0)").getAst();
108-
program = cel.createProgram(ast);
108+
CelAbstractSyntaxTree ast = compiler.compile("[1, 2, 3].all(i, i % 2 != 0)").getAst();
109+
CelRuntime.Program program = cel.createProgram(ast);
109110
CelCoverageIndex coverageIndex = new CelCoverageIndex();
110111
coverageIndex.init(ast);
111112
CelEvaluationListener listener = coverageIndex.newEvaluationListener();
@@ -125,4 +126,32 @@ public void getCoverageReport_comprehension_generatesDotGraph() throws Exception
125126
.contains("label=\"{<1> exprID: 16 | <2> LoopStep} | <3> @result && i % 2 != 0\"");
126127
assertThat(report.dotGraph()).contains("label=\"{<1> exprID: 17 | <2> Result} | <3> @result\"");
127128
}
129+
130+
@Test
131+
public void getCoverageReport_fullCoverage_writesToUndeclaredOutputs() throws Exception {
132+
// Setup for a more complex graph to write.
133+
Cel cel = CelFactory.standardCelBuilder().build();
134+
CelCompiler compiler =
135+
cel.toCompilerBuilder()
136+
.setOptions(CelOptions.newBuilder().populateMacroCalls(true).build())
137+
.setStandardMacros(CelStandardMacro.STANDARD_MACROS)
138+
.addLibraries(CelExtensions.comprehensions())
139+
.build();
140+
CelAbstractSyntaxTree ast = compiler.compile("[1, 2, 3].all(i, i % 2 != 0)").getAst();
141+
CelRuntime.Program program = cel.createProgram(ast);
142+
CelCoverageIndex coverageIndex = new CelCoverageIndex();
143+
coverageIndex.init(ast);
144+
CelEvaluationListener listener = coverageIndex.newEvaluationListener();
145+
program.trace(ImmutableMap.of(), listener);
146+
147+
CoverageReport report = coverageIndex.generateCoverageReport();
148+
149+
String undeclaredOutputsDir = System.getenv("TEST_UNDECLARED_OUTPUTS_DIR");
150+
assertThat(undeclaredOutputsDir).isNotNull();
151+
152+
File outputFile = new File(undeclaredOutputsDir, "cel_test_coverage/coverage_graph.txt");
153+
154+
String fileContent = Files.asCharSource(outputFile, UTF_8).read();
155+
assertThat(fileContent).isEqualTo(report.dotGraph());
156+
}
128157
}

0 commit comments

Comments
 (0)