Skip to content

Commit

Permalink
#44: Improved assertion message when more columns expected than prese…
Browse files Browse the repository at this point in the history
…nt. (#47)

* #44: Improved reporting of situation where more columns are expected than present.
  • Loading branch information
redcatbear authored Oct 27, 2023
1 parent 33eff40 commit 07e75bc
Show file tree
Hide file tree
Showing 7 changed files with 159 additions and 53 deletions.
50 changes: 20 additions & 30 deletions dependencies.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions doc/changes/changelog.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

28 changes: 28 additions & 0 deletions doc/changes/changes_1.6.2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Matcher for SQL Result Sets 1.6.2, released 2023-10-27

Code name: Fix expectation with too many columns

## Summary

We fixed an issue where expecting more columns than are actually in the result set would throw an `ArrayIndexOutOfBoundsException`.

## Features

* #44: Fixed `ArrayIndexOutOfBoundsException` when expecting more columns than are in the result set.

## Dependency Updates

### Test Dependency Updates

* Updated `org.testcontainers:jdbc:1.19.0` to `1.19.1`
* Updated `org.testcontainers:junit-jupiter:1.19.0` to `1.19.1`

### Plugin Dependency Updates

* Updated `com.exasol:error-code-crawler-maven-plugin:1.3.0` to `1.3.1`
* Updated `com.exasol:project-keeper-maven-plugin:2.9.12` to `2.9.14`
* Updated `org.apache.maven.plugins:maven-enforcer-plugin:3.4.0` to `3.4.1`
* Updated `org.apache.maven.plugins:maven-javadoc-plugin:3.5.0` to `3.6.0`
* Updated `org.codehaus.mojo:versions-maven-plugin:2.16.0` to `2.16.1`
* Updated `org.jacoco:jacoco-maven-plugin:0.8.10` to `0.8.11`
* Updated `org.sonarsource.scanner.maven:sonar-maven-plugin:3.9.1.2184` to `3.10.0.2594`
17 changes: 9 additions & 8 deletions pk_generated_parent.pom

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 7 additions & 6 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>hamcrest-resultset-matcher</artifactId>
<version>1.6.1</version>
<version>1.6.2</version>
<name>Matcher for SQL Result Sets</name>
<description>This project provides hamcrest matcher that compares java.sql.ResultSet objects.</description>
<url>https://github.com/exasol/hamcrest-resultset-matcher/</url>
Expand Down Expand Up @@ -30,7 +30,8 @@
<dependency>
<groupId>org.apache.derby</groupId>
<artifactId>derby</artifactId>
<version>10.15.2.0</version> <!-- Versions >= 10.16 require Java 17. -->
<version>10.15.2.0</version>
<!-- Versions >= 10.16 require Java 17. -->
<scope>test</scope>
</dependency>
<dependency>
Expand All @@ -42,7 +43,7 @@
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>junit-jupiter</artifactId>
<version>1.19.0</version>
<version>1.19.1</version>
<scope>test</scope>
</dependency>
<dependency>
Expand All @@ -53,7 +54,7 @@
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>jdbc</artifactId>
<version>1.19.0</version>
<version>1.19.1</version>
<scope>test</scope>
</dependency>
</dependencies>
Expand All @@ -62,7 +63,7 @@
<plugin>
<groupId>com.exasol</groupId>
<artifactId>project-keeper-maven-plugin</artifactId>
<version>2.9.12</version>
<version>2.9.14</version>
<executions>
<execution>
<goals>
Expand All @@ -76,7 +77,7 @@
<parent>
<artifactId>hamcrest-resultset-matcher-generated-parent</artifactId>
<groupId>com.exasol</groupId>
<version>1.6.1</version>
<version>1.6.2</version>
<relativePath>pk_generated_parent.pom</relativePath>
</parent>
</project>
32 changes: 23 additions & 9 deletions src/main/java/com/exasol/matcher/ResultSetStructureMatcher.java
Original file line number Diff line number Diff line change
Expand Up @@ -137,10 +137,12 @@ private boolean matchRowsInOrder(final ResultSet resultSet) {
boolean ok = true;
try {
int rowIndex = 0;
int matcherRowIndex = 0;
for (final List<Matcher<?>> cellMatcherRow : this.cellMatcherTable) {
++matcherRowIndex;
if (resultSet.next()) {
++rowIndex;
ok = ok && matchValuesInRow(resultSet, rowIndex, cellMatcherRow, true);
ok = ok && matchValuesInRow(resultSet, rowIndex, matcherRowIndex, cellMatcherRow, true);
} else {
ok = false;
}
Expand All @@ -162,12 +164,14 @@ private boolean matchRowsInAnyOrder(final ResultSet resultSet) {
final int numberOfRowMatchers = this.cellMatcherTable.size();
int[] matchesForRowMatcher = new int[numberOfRowMatchers];
int rowIndex = 0;
int matcherRowIndex = 0;
while (resultSet.next()) {
++rowIndex;
boolean anyMatchForThisResultRow = false;
int matcherIndex = 0;
for (final List<Matcher<?>> cellMatcherRow : this.cellMatcherTable) {
if (matchValuesInRow(resultSet, rowIndex, cellMatcherRow, false)) {
++matcherRowIndex;
if (matchValuesInRow(resultSet, rowIndex, matcherRowIndex, cellMatcherRow, false)) {
++matchesForRowMatcher[matcherIndex];
anyMatchForThisResultRow = true;
}
Expand Down Expand Up @@ -241,14 +245,15 @@ private int getExpectedColumnCount() {
* recording it at this early stage is not useful.
* </p>
*
* @param resultSet result set from which to read the cell values
* @param rowIndex index of the row in the result set
* @param cellMatcherRow list of matchers that are tested against the row's cells
* @param resultSet result set from which to read the cell values
* @param rowIndex index of the row in the result set
* @param matcherRowIndex index of the matcher definition
* @param cellMatcherRow list of matchers that are tested against the row's cells
* @param recordFirstDeviation record the first mismatch when set to {@code true}
* @return {@code true} if the given matchers match all cells in this row
*/
private boolean matchValuesInRow(final ResultSet resultSet, final int rowIndex,
final List<Matcher<?>> cellMatcherRow, final boolean recordFirstDeviation) {
private boolean matchValuesInRow(final ResultSet resultSet, final int rowIndex, int matcherRowIndex,
final List<Matcher<?>> cellMatcherRow, final boolean recordFirstDeviation) {
int columnIndex = 0;
try {
for (final Matcher<?> cellMatcher : cellMatcherRow) {
Expand All @@ -262,8 +267,10 @@ private boolean matchValuesInRow(final ResultSet resultSet, final int rowIndex,
}
}
} catch (final SQLException exception) {
throw new AssertionError("Unable to read actual result set value in row " + rowIndex + ", column "
+ columnIndex + ": " + exception.getMessage(), exception);
throw new AssertionError("Row expectation definition " + matcherRowIndex +
" tries to validate the value of row " + rowIndex + ", column "
+ columnIndex + " but that value can't be read from the result set. "
+ "This usually means the column does not exist. \nCaused by SQL error: " + exception.getMessage());
}
return true;
}
Expand Down Expand Up @@ -348,6 +355,13 @@ public static final class Builder {
private Calendar calendar;
private boolean requireSameOrder = true;

/**
* Create a new instance of a {@link ResultSetStructureMatcher.Builder}.
*/
public Builder() {
// intentionally empty
}

/**
* Add a column to the structure to be matched.
*
Expand Down
71 changes: 71 additions & 0 deletions src/test/java/com/exasol/matcher/RowMatcherIT.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package com.exasol.matcher;

import org.hamcrest.Matcher;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;
import static org.junit.jupiter.api.Assertions.*;

/**
* This integration test runs row matching tests against the Apache Derby database.
*/
class RowMatcherIT extends AbstractResultSetMatcherTest {
@BeforeEach
void beforeEach() throws SQLException {
final Connection connection = DriverManager.getConnection("jdbc:derby:memory:test;create=true");
this.statement = connection.createStatement();
}

@AfterEach
void afterEach() {
execute("DROP TABLE T");
}

// This is a regression test for https://github.com/exasol/hamcrest-resultset-matcher/issues/44
@Test
void testMatchingInAnyOrderAndExpectingThreeColumnsThrowsAssertionErrorWhenResultSetHasOnlyTwoColumns()
throws SQLException {
execute("CREATE TABLE T(I INTEGER, V VARCHAR(20))");
execute("INSERT INTO T VALUES (1, 'a'), (2, 'b')");
final Matcher<ResultSet> anyOrderMatcher = ResultSetStructureMatcher //
.table()//
.row(1, "a", 1) //
.row(greaterThan(0), "b", 3) //
.matchesInAnyOrder();
try(final ResultSet result = query("SELECT * FROM T")) {
final AssertionError error = assertThrows(AssertionError.class,
() -> anyOrderMatcher.matches(result));
assertThat(error.getMessage(), startsWith("Row expectation definition 1 tries to validate the value of row 1, "
+ "column 3 but that value can't be read from the result set. "
+ "This usually means the column does not exist. \nCaused by SQL error:"));
}
}

// This is a regression test for https://github.com/exasol/hamcrest-resultset-matcher/issues/44
@Test
void testMatchingInStrictOrderAndExpectingThreeColumnsThrowsAssertionErrorWhenResultSetHasOnlyTwoColumns()
throws SQLException {
execute("CREATE TABLE T(I INTEGER, V VARCHAR(20))");
execute("INSERT INTO T VALUES (1, 'A'), (2, 'B')");
final Matcher<ResultSet> orderedMatcher = ResultSetStructureMatcher //
.table()//
.row(1, "A", 1) //
.row(greaterThan(0), "B", 3) //
.matches();
try (final ResultSet result = query("SELECT * FROM T")) {
final AssertionError error = assertThrows(AssertionError.class, () -> orderedMatcher.matches(result));
assertThat(error.getMessage(), startsWith("Row expectation definition 1 tries to validate the value of row 1, "
+ "column 3 but that value can't be read from the result set. "
+ "This usually means the column does not exist. \nCaused by SQL error:"));

}
}
}

0 comments on commit 07e75bc

Please sign in to comment.