Skip to content

Commit

Permalink
ensmarten templated tests
Browse files Browse the repository at this point in the history
refactor a little
  • Loading branch information
evanchooly committed May 31, 2023
1 parent e4a5062 commit 2144e56
Show file tree
Hide file tree
Showing 4 changed files with 130 additions and 120 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,10 @@

package dev.morphia.test.aggregation;

import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

import com.fasterxml.jackson.databind.ObjectMapper;

import dev.morphia.aggregation.Aggregation;
import dev.morphia.aggregation.AggregationImpl;
import dev.morphia.test.aggregation.expressions.TemplatedTestBase;

import org.bson.Document;
Expand All @@ -36,64 +29,16 @@
import static java.lang.String.format;
import static java.util.Arrays.stream;
import static java.util.stream.Collectors.toList;
import static org.bson.json.JsonWriterSettings.builder;
import static org.testng.Assert.assertEquals;

@SuppressWarnings({ "unused", "MismatchedQueryAndUpdateOfCollection" })
public class AggregationTest extends TemplatedTestBase {

protected final ObjectMapper mapper = new ObjectMapper();

public void testPipeline(double serverVersion, String resourceName,
Function<Aggregation<Document>, Aggregation<Document>> pipeline) {
testPipeline(serverVersion, resourceName, true, true, pipeline);
}

public void testPipeline(double serverVersion, String resourceName, boolean removeIds, boolean orderMatters,
Function<Aggregation<Document>, Aggregation<Document>> pipeline) {
String collection = "aggtest";
checkMinServerVersion(serverVersion);
loadData(collection, resourceName);

List<Document> documents = runPipeline(resourceName, pipeline.apply(getDs().aggregate(collection)));

List<Document> actual = removeIds ? removeIds(documents) : documents;
List<Document> expected = loadExpected(resourceName);

if (orderMatters) {
assertEquals(actual, expected);
} else {
assertListEquals(actual, expected);
}
}

@SuppressWarnings({ "unchecked", "rawtypes" })
protected List<Document> runPipeline(String pipelineTemplate, Aggregation<Document> aggregation) {
String pipelineName = format("%s/%s/pipeline.json", prefix(), pipelineTemplate);
try {
List<Document> pipeline = ((AggregationImpl) aggregation).pipeline();

Iterator<Map<String, Object>> iterator = mapper.readValue(getClass().getResourceAsStream(pipelineName), List.class)
.iterator();
for (Document stage : pipeline) {
Object next = iterator.next();
assertEquals(mapper.readValue(stage.toJson(), Map.class), next,
pipeline.stream()
.map(d -> d.toJson(builder()
.indent(true)
.build()))
.collect(Collectors.joining("\n", "[\n", "\n]")));
}

try (var cursor = aggregation.execute(Document.class)) {
return cursor.toList();
}
} catch (IOException e) {
throw new RuntimeException(e.getMessage(), e);
}

}

protected void cakeSales() {
insert("cakeSales", parseDocs(
"{ _id: 0, type: 'chocolate', orderDate: ISODate('2020-05-18T14:10:30Z'), state: 'CA', price: 13, quantity: 120 }",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,78 @@
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.mongodb.lang.NonNull;

import dev.morphia.aggregation.Aggregation;
import dev.morphia.aggregation.AggregationImpl;
import dev.morphia.mapping.codec.reader.DocumentReader;
import dev.morphia.query.FindOptions;
import dev.morphia.query.Query;
import dev.morphia.test.TestBase;

import org.bson.Document;
import org.bson.codecs.DecoderContext;
import org.jetbrains.annotations.NotNull;

import static java.lang.Character.toLowerCase;
import static java.lang.String.format;
import static java.util.stream.Collectors.toList;
import static org.bson.json.JsonWriterSettings.builder;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.fail;

public class TemplatedTestBase extends TestBase {
public abstract class TemplatedTestBase extends TestBase {
protected final ObjectMapper mapper = new ObjectMapper();

public final String prefix() {
String root = getClass().getSimpleName().substring(4);
return toLowerCase(root.charAt(0)) + root.substring(1);
}

public void testPipeline(double serverVersion, String resourceNamed, boolean removeIds, boolean orderMatters,
Function<Aggregation<Document>, Aggregation<Document>> pipeline) {
String collection = "aggtest";
checkMinServerVersion(serverVersion);
var resourceName = discoverResourceName(new Exception().getStackTrace());
loadData(collection, resourceName);

List<Document> documents = runPipeline(resourceName, pipeline.apply(getDs().aggregate(collection)));

List<Document> actual = removeIds ? removeIds(documents) : documents;
List<Document> expected = loadExpected(resourceName);

if (orderMatters) {
assertEquals(actual, expected);
} else {
assertListEquals(actual, expected);
}
}

public <D> void testQuery(Query<D> query, FindOptions options, boolean orderMatters) {
var resourceName = discoverResourceName(new Exception().getStackTrace());

loadData(getDs().getCollection(query.getEntityClass()).getNamespace().getCollectionName(), resourceName);

List<D> actual = runQuery(resourceName, query, options);

List<D> expected = map(query.getEntityClass(), loadExpected(resourceName));

if (orderMatters) {
assertEquals(actual, expected);
} else {
assertListEquals(actual, expected);
}
}

protected void loadData(String collection, String resourceName) {
insert(collection, loadJson(format("%s/%s/data.json", prefix(), resourceName)));
}
Expand Down Expand Up @@ -71,4 +124,78 @@ protected <T> List<T> loadJson(Class<T> type, String name) {
}
return data;
}

@SuppressWarnings({ "unchecked", "rawtypes" })
protected List<Document> runPipeline(String pipelineTemplate, Aggregation<Document> aggregation) {
String pipelineName = format("%s/%s/pipeline.json", prefix(), pipelineTemplate);
try {
List<Document> pipeline = ((AggregationImpl) aggregation).pipeline();

Iterator<Map<String, Object>> iterator = mapper.readValue(getClass().getResourceAsStream(pipelineName), List.class)
.iterator();
for (Document stage : pipeline) {
Object next = iterator.next();
assertEquals(mapper.readValue(stage.toJson(), Map.class), next,
pipeline.stream()
.map(d -> d.toJson(builder()
.indent(true)
.build()))
.collect(Collectors.joining("\n", "[\n", "\n]")));
}

try (var cursor = aggregation.execute(Document.class)) {
return cursor.toList();
}
} catch (IOException e) {
throw new RuntimeException(e.getMessage(), e);
}

}

@NonNull
protected <D> List<D> runQuery(@NonNull String queryTemplate, @NonNull Query<D> query,
@NonNull FindOptions options) {
String queryName = format("%s/%s/query.json", prefix(), queryTemplate);
try {

InputStream stream = getClass().getResourceAsStream(queryName);
assertNotNull(stream, "Could not find query template: " + queryName);
Document expectedQuery;
try (InputStreamReader reader = new InputStreamReader(stream)) {
expectedQuery = Document.parse(new BufferedReader(reader).readLine());
}

assertDocumentEquals(query.toDocument(), expectedQuery);

try (var cursor = query.iterator(options)) {
return cursor.toList();
}
} catch (IOException e) {
throw new RuntimeException(e.getMessage(), e);
}
}

private String discoverResourceName(StackTraceElement[] stackTrace) {
String methodName = Arrays.stream(stackTrace)
.filter(e -> !(e.getMethodName().equals("testPipeline") ||
e.getMethodName().equals("testQuery")))
.findFirst()
.get().getMethodName();
if (methodName.startsWith("test")) {
methodName = methodName.substring(4);
methodName = methodName.substring(0, 1).toLowerCase() + methodName.substring(1);
}
return methodName;
}

private <D> List<D> map(Class<D> entityClass, List<Document> documents) {
var codec = getDs().getCodecRegistry().get(entityClass);

DecoderContext context = DecoderContext.builder().build();
return documents.stream()
.map(document -> {
return codec.decode(new DocumentReader(document), context);
})
.collect(toList());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

public class TestLinearFill extends AggregationTest {
@Test
public void testMissingValues() {
public void missingValues() {
testPipeline(5.3, "missingValues", true, false, (aggregation) -> {
return aggregation
.setWindowFields(setWindowFields()
Expand Down
64 changes: 1 addition & 63 deletions core/src/test/java/dev/morphia/test/query/TestSorts.java
Original file line number Diff line number Diff line change
@@ -1,61 +1,22 @@
package dev.morphia.test.query;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.List;
import java.util.Objects;

import com.mongodb.lang.NonNull;

import dev.morphia.annotations.Entity;
import dev.morphia.annotations.Id;
import dev.morphia.annotations.Text;
import dev.morphia.mapping.codec.reader.DocumentReader;
import dev.morphia.query.FindOptions;
import dev.morphia.query.Query;
import dev.morphia.test.aggregation.expressions.TemplatedTestBase;

import org.bson.Document;
import org.bson.codecs.DecoderContext;
import org.testng.annotations.Test;

import static dev.morphia.query.Meta.textScore;
import static dev.morphia.query.Sort.ascending;
import static dev.morphia.query.filters.Filters.text;
import static java.lang.String.format;
import static java.util.stream.Collectors.*;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;

public class TestSorts extends TemplatedTestBase {
public <D> void testQuery(double serverVersion, String resourceName, boolean orderMatters, Query<D> query, FindOptions options) {
checkMinServerVersion(serverVersion);

loadData(getDs().getCollection(query.getEntityClass()).getNamespace().getCollectionName(), resourceName);

List<D> actual = runQuery(resourceName, query, options);

List<D> expected = map(query.getEntityClass(), loadExpected(resourceName));

if (orderMatters) {
assertEquals(actual, expected);
} else {
assertListEquals(actual, expected);
}
}

private <D> List<D> map(Class<D> entityClass, List<Document> documents) {
var codec = getDs().getCodecRegistry().get(entityClass);

DecoderContext context = DecoderContext.builder().build();
return documents.stream()
.map(document -> {
return codec.decode(new DocumentReader(document), context);
})
.collect(toList());
}

@Test
public void metaAndSorts() {
Expand All @@ -69,30 +30,7 @@ public void metaAndSorts() {
.sort(textScore("textScore"),
ascending("subject"));

testQuery(0, "metaAndSorts", true, query, options);
}

@NonNull
protected <D> List<D> runQuery(@NonNull String queryTemplate, @NonNull Query<D> query,
@NonNull FindOptions options) {
String queryName = format("%s/%s/query.json", prefix(), queryTemplate);
try {

InputStream stream = getClass().getResourceAsStream(queryName);
assertNotNull(stream, "Could not find query template: " + queryName);
Document expectedQuery;
try (InputStreamReader reader = new InputStreamReader(stream)) {
expectedQuery = Document.parse(new BufferedReader(reader).readLine());
}

assertDocumentEquals(query.toDocument(), expectedQuery);

try (var cursor = query.iterator(options)) {
return cursor.toList();
}
} catch (IOException e) {
throw new RuntimeException(e.getMessage(), e);
}
testQuery(query, options, true);
}

@Entity(useDiscriminator = false)
Expand Down

0 comments on commit 2144e56

Please sign in to comment.