Skip to content

Commit 30d72e8

Browse files
dfa1claude
andcommitted
test: cover defensive exhaustive-switch arms (new-code coverage)
Post-0.12.0 the quality gate flagged branches my S1481 unnamed- pattern cleanup surfaced into the new-code window — exhaustive- switch arms for variants their caller never produces. Cover the genuinely reachable ones with real tests: CodeGen rejects a vector-of-unions schema (inline .fbs, real error path); FilterCommand's columnPredicate compiles the null-test leaves and rejects the composite/range leaves (package-private, documented, so the arms the CLI grammar can't reach are exercised directly). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent 12f3f34 commit 30d72e8

3 files changed

Lines changed: 61 additions & 1 deletion

File tree

cli/src/main/java/io/github/dfa1/vortex/cli/FilterCommand.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,10 @@ private static RowPredicate toRowPredicate(RowFilter filter) {
169169
/// Compiles a column-bound [Predicate] into a per-row test over the decoded chunk. Only the
170170
/// comparison and null-test leaves the filter grammar ([#parseFilter]) produces are supported;
171171
/// the composite and range predicate variants never arise from a parsed CLI expression.
172-
private static RowPredicate columnPredicate(String col, Predicate predicate) {
172+
///
173+
/// Package-private so the exhaustive switch's null-test and unsupported-composite arms — which
174+
/// the CLI grammar never reaches — can be exercised directly.
175+
static RowPredicate columnPredicate(String col, Predicate predicate) {
173176
return switch (predicate) {
174177
case Predicate.Gt(var val) -> (chunk, rowIdx) -> compareValue(chunk.column(col), rowIdx, val) > 0;
175178
case Predicate.Gte(var val) -> (chunk, rowIdx) -> compareValue(chunk.column(col), rowIdx, val) >= 0;

cli/src/test/java/io/github/dfa1/vortex/cli/FilterCommandTest.java

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,24 @@
11
package io.github.dfa1.vortex.cli;
22

3+
import io.github.dfa1.vortex.reader.compute.Predicate;
4+
import io.github.dfa1.vortex.csv.RowPredicate;
35
import org.junit.jupiter.api.BeforeEach;
46
import org.junit.jupiter.api.Test;
57
import org.junit.jupiter.api.io.TempDir;
68
import org.junit.jupiter.params.ParameterizedTest;
79
import org.junit.jupiter.params.provider.CsvSource;
10+
import org.junit.jupiter.params.provider.MethodSource;
811
import org.junit.jupiter.params.provider.ValueSource;
912

1013
import java.io.IOException;
1114
import java.nio.file.Path;
15+
import java.util.stream.Stream;
1216

1317
import static io.github.dfa1.vortex.cli.CliTestSupport.capture;
1418
import static io.github.dfa1.vortex.cli.CliTestSupport.writeSmallVortex;
1519
import static io.github.dfa1.vortex.cli.CliTestSupport.writeTypedVortex;
1620
import static org.assertj.core.api.Assertions.assertThat;
21+
import static org.assertj.core.api.Assertions.assertThatThrownBy;
1722

1823
class FilterCommandTest {
1924

@@ -190,4 +195,35 @@ void operatorPrefixAttack_doesNotCauseBacktracking() {
190195
assertThat(elapsedMs).isLessThan(1000);
191196
assertThat(result.status()).isNotEqualTo(ExitStatus.USAGE_ERROR);
192197
}
198+
199+
@Test
200+
void columnPredicate_nullTestLeaves_compileToARowPredicate() {
201+
// Given the null-test predicate variants — the CLI grammar never produces them, but
202+
// columnPredicate must handle them for switch exhaustiveness over Predicate
203+
// When
204+
RowPredicate isNull = FilterCommand.columnPredicate("c", new Predicate.IsNull());
205+
RowPredicate isNotNull = FilterCommand.columnPredicate("c", new Predicate.IsNotNull());
206+
207+
// Then — each compiles to a usable per-row test
208+
assertThat(isNull).isNotNull();
209+
assertThat(isNotNull).isNotNull();
210+
}
211+
212+
@ParameterizedTest
213+
@MethodSource("unsupportedCompositePredicates")
214+
void columnPredicate_compositeAndRangeLeaves_throw(Predicate predicate) {
215+
// Given a composite or range predicate the CLI cannot express
216+
// When / Then — columnPredicate rejects it rather than silently mishandling
217+
assertThatThrownBy(() -> FilterCommand.columnPredicate("c", predicate))
218+
.isInstanceOf(IllegalArgumentException.class)
219+
.hasMessageContaining("not supported on the command line");
220+
}
221+
222+
private static Stream<Predicate> unsupportedCompositePredicates() {
223+
Predicate leaf = new Predicate.Gt(1L);
224+
return Stream.of(
225+
new Predicate.Between(1L, 2L),
226+
new Predicate.And(leaf, leaf),
227+
new Predicate.Or(leaf, leaf));
228+
}
193229
}

fbs-gen/src/test/java/io/github/dfa1/vortex/fbsgen/CodeGenTest.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package io.github.dfa1.vortex.fbsgen;
22

33
import static org.assertj.core.api.Assertions.assertThat;
4+
import static org.assertj.core.api.Assertions.assertThatThrownBy;
45

56
import java.io.IOException;
67
import java.nio.file.Files;
@@ -11,6 +12,26 @@
1112

1213
class CodeGenTest {
1314

15+
@Test
16+
void vectorOfUnions_throwsFbsParseException(@TempDir Path out) {
17+
// Given a schema whose table field is a vector of a union type — the one array-element
18+
// shape the FlatBuffers layout cannot express, so the generator must reject it.
19+
String schema = """
20+
namespace x;
21+
table A { a: int; }
22+
table B { b: int; }
23+
union U { A, B }
24+
table T { items: [U]; }
25+
""";
26+
Ast.SchemaFile file = new Parser(new Lexer(schema).tokenize()).parseFile();
27+
CodeGen sut = new CodeGen(new TypeRegistry(List.of(file)));
28+
29+
// When / Then
30+
assertThatThrownBy(() -> sut.emit(out))
31+
.isInstanceOf(FbsParseException.class)
32+
.hasMessageContaining("vectors of unions are not supported");
33+
}
34+
1435
@Test
1536
void emitsOneFilePerDeclarationForAllVortexSchemas(@TempDir Path out) throws IOException {
1637
// Given + When

0 commit comments

Comments
 (0)