Skip to content

Commit

Permalink
Make sure all Streams are closed in tests
Browse files Browse the repository at this point in the history
Not closing the streams results in geotools warnings about resource
leaks for not closing FeatureReaders/Iterators.

Make sure all tests do close the streams to identify possible leaks in
production code.

The `@Cleanup` lombok annotation makes it easy.
  • Loading branch information
groldan committed Dec 6, 2023
1 parent e9f53af commit 3c12ed7
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,9 @@ public Stream<GeodataRecord> getFeatures() {
int characteristics = Spliterator.DISTINCT | Spliterator.NONNULL;
Spliterator<SimpleFeature> spliterator = Spliterators.spliteratorUnknownSize(iterator, characteristics);
Stream<SimpleFeature> stream = StreamSupport.stream(spliterator, false);
stream = stream.onClose(it::close);
stream = stream.onClose(() -> {
it.close();
});
return stream.map(featureMapper);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@
import com.camptocamp.opendata.ogc.features.model.FeatureCollection;
import com.google.common.base.Splitter;

import lombok.Cleanup;

public abstract class AbstractCollectionsApiImplIT {

protected @Autowired CollectionsApiImpl collectionsApi;
Expand Down Expand Up @@ -66,15 +68,21 @@ public void testGetCollections() {
public void testGetItems() {
FeaturesQuery query = FeaturesQuery.of("locations").withLimit(10);
ResponseEntity<FeatureCollection> response = collectionsApi.getFeatures(query);
assertThat(response.getBody().getFeatures().toList().size()).isEqualTo(10);

@Cleanup
Stream<GeodataRecord> features = response.getBody().getFeatures();
assertThat(features.toList().size()).isEqualTo(10);
}

@Test
public void testGetItemsWithFilter() {
FeaturesQuery query = FeaturesQuery.of("locations").withFilter("number = 140");
ResponseEntity<FeatureCollection> response = collectionsApi.getFeatures(query);

assertThat(response.getBody().getFeatures().count()).isEqualTo(1);
@Cleanup
Stream<GeodataRecord> features = response.getBody().getFeatures();
assertThat(features.count()).isEqualTo(1);

}

@ParameterizedTest
Expand Down Expand Up @@ -144,14 +152,15 @@ private void testPagingConsistency(FeaturesQuery query, Comparator<GeodataRecord
assertThat(collection.getNumberReturned()).as("numberReturned should be equal to page size")
.isEqualTo(page.getPageSize());
}
try (Stream<GeodataRecord> features = collection.getFeatures()) {
features.forEach(rec -> {
String id = rec.getId();
assertThat(idsReturned).as("Duplicate feature returned on page " + pageNumber).doesNotContain(id);
idsReturned.add(id);
records.add(rec);
});
}

@Cleanup
Stream<GeodataRecord> features = collection.getFeatures();
features.forEach(rec -> {
String id = rec.getId();
assertThat(idsReturned).as("Duplicate feature returned on page " + pageNumber).doesNotContain(id);
idsReturned.add(id);
records.add(rec);
});
}
// verify expected order
// var sorted = new ArrayList<>(records);
Expand All @@ -171,8 +180,10 @@ public void testGetItemsWithFilter_property_name_with_spaces() throws Exception

FeatureCollection body = response.getBody();

int expected = (int) body.getFeatures()
.filter(c -> "B".equals(c.getProperty(propetyName).orElseThrow().getValue())).count();
@Cleanup
Stream<GeodataRecord> features = body.getFeatures();
int expected = (int) features.filter(c -> "B".equals(c.getProperty(propetyName).orElseThrow().getValue()))
.count();
assertThat(expected).isGreaterThan(0);

final String cqlFilter = "\"%s\" = 'B'".formatted(propetyName);
Expand All @@ -181,13 +192,18 @@ public void testGetItemsWithFilter_property_name_with_spaces() throws Exception

response = collectionsApi.getFeatures(FeaturesQuery.of(collectionName).withFilter(cqlFilter));
body = response.getBody();
assertThat(body.getFeatures().count()).isEqualTo(expected);
@Cleanup
Stream<GeodataRecord> features1 = body.getFeatures();
assertThat(features1.count()).isEqualTo(expected);

response = collectionsApi
.getFeatures(FeaturesQuery.of(collectionName).withFilter(cqlFilter).withLimit(expected));

body = response.getBody();
assertThat(body.getFeatures().count()).isEqualTo(expected);

@Cleanup
Stream<GeodataRecord> features2 = body.getFeatures();
assertThat(features2.count()).isEqualTo(expected);
}

private void assertECQL_FilterCanBeParsed(final String propetyName, final String filter) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import java.util.Comparator;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import javax.sql.DataSource;

Expand Down Expand Up @@ -41,6 +42,8 @@
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;

import lombok.Cleanup;

@SpringBootTest(classes = OgcFeaturesApp.class)
@ActiveProfiles("postgis")
@Testcontainers
Expand Down Expand Up @@ -183,25 +186,35 @@ public void testGetItems_survives_schema_change() throws SQLException {

FeaturesQuery query = FeaturesQuery.of("locations").withLimit(10);
ResponseEntity<FeatureCollection> response = collectionsApi.getFeatures(query);
assertThat(response.getBody().getFeatures().toList().size()).isEqualTo(10);

@Cleanup
Stream<GeodataRecord> features = response.getBody().getFeatures();
assertThat(features.toList().size()).isEqualTo(10);

renameColumn("locations", "year", "año");

response = collectionsApi.getFeatures(query);
assertThat(response.getBody().getFeatures().toList().size()).isEqualTo(10);
@Cleanup
Stream<GeodataRecord> features1 = response.getBody().getFeatures();
assertThat(features1.toList().size()).isEqualTo(10);

dropColumn("locations", "año");

response = collectionsApi.getFeatures(query);
assertThat(response.getBody().getFeatures().toList().size()).isEqualTo(10);

@Cleanup
Stream<GeodataRecord> features2 = response.getBody().getFeatures();
assertThat(features2.toList().size()).isEqualTo(10);
}

@Test
public void testGetItem_survives_schema_change() throws SQLException {
FeaturesQuery query = FeaturesQuery.of("locations").withLimit(1);
GeodataRecord before = collectionsApi.getFeatures(query).getBody().getFeatures().findFirst().orElseThrow();
assertThat(before.getProperty("number")).isPresent();

@Cleanup
Stream<GeodataRecord> features = collectionsApi.getFeatures(query).getBody().getFeatures();
GeodataRecord before = features.findFirst().orElseThrow();
assertThat(before.getProperty("number")).isPresent();
final String id = before.getId();

renameColumn("locations", "number", "número");
Expand Down

0 comments on commit 3c12ed7

Please sign in to comment.