-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feature/concurrency tests #6
Changes from 5 commits
66fa8b6
1ff8078
9138f96
daf2c25
a477769
04d8e9c
8116216
22315e5
79d4221
65adfdf
41b78f4
f741adf
e29f313
4c0754b
52f8728
c6777a6
d5189d3
8a10dc2
b9f9eed
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,9 +16,9 @@ public final class Add<T> implements Operation { | |
@AvroSchema(DefaultSchema.VALUE) | ||
public final T value; | ||
|
||
@SuppressWarnings("unused") // no arg constructor needed by Avro | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
private Add() { | ||
this.path = null; | ||
this.value = null; | ||
this(null, null); | ||
} | ||
|
||
/** | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,9 +13,9 @@ public final class Copy implements Operation { | |
public final Path from; | ||
public final Path path; | ||
|
||
@SuppressWarnings("unused") // no arg constructor needed by Avro | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. no-arg |
||
private Copy() { | ||
from = null; | ||
path = null; | ||
this(null, null); | ||
} | ||
|
||
/** | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -31,9 +31,7 @@ public interface CustomTypes { | |
|
||
interface PatchType { | ||
String NAME = Patch.class.getSimpleName(); | ||
String DOC = "This record represents a JSON PATCH operation holding a sequence of operations to apply to a" | ||
+ " given object."; | ||
|
||
String DOC = "This record represents a PATCH holding a sequence of operations to apply to a given object."; | ||
static Schema create(Schema valueSchema) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Defining an interface method. This is new to me. Would love to understand more. |
||
Schema.Field operations = new Schema.Field("operations", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Better to move the literal ("operations") to a constant before using it here and other places. |
||
Schema.createArray(OperationTypes.Operation.create(valueSchema)), | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -33,8 +33,8 @@ public final class CustomTypeSerializer { | |
|
||
private CustomTypeSerializer(Schema schema) { | ||
Objects.nonNull(schema); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can the schema even be null? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nope :-) |
||
writer = AvroData.get().createDatumWriter(schema); | ||
reader = AvroData.get().createDatumReader(schema); | ||
this.writer = AvroData.get().createDatumWriter(schema); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ugh... |
||
this.reader = AvroData.get().createDatumReader(schema); | ||
} | ||
|
||
public byte[] toBytes(Patch value) throws IOException { | ||
|
@@ -49,10 +49,10 @@ public Patch toObject(byte[] bytes) throws IOException { | |
} | ||
|
||
public static class Builder { | ||
final List<Schema> types = new ArrayList<>(); | ||
protected final List<Schema> types; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Considering that both a method for adding a type and a schema exist, the combination of declaration and variable name is a little confusing. |
||
|
||
public Builder() { | ||
AvroData.get(); | ||
this.types = new ArrayList<>(); | ||
} | ||
|
||
public Builder nullable() { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,10 +8,11 @@ | |
|
||
public final class AvroData extends ReflectData { | ||
|
||
public static List<Conversion<?>> CONVERTERS = | ||
ImmutableList.of(new DateConversion(), new BigIntegerConversion(), new BigDecimalConversion(), | ||
new UUIDConversion()); | ||
|
||
public static final List<Conversion<?>> CONVERTERS = ImmutableList.of( | ||
new DateConversion(), | ||
new BigIntegerConversion(), | ||
new BigDecimalConversion(), | ||
new UUIDConversion()); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd say according to K&R style we would need to insert a line break before the last closing brace... |
||
private static final AvroData INSTANCE = new AvroData(); | ||
|
||
private AvroData() { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -88,7 +88,8 @@ public void serializesTest() throws IOException { | |
|
||
@Test | ||
public void serializesBunchOfOperations() throws IOException { | ||
Patch patch = new Patch(ImmutableList.of(new Add<>(Path.of("person", "name"), "John Doe"), | ||
Patch patch = new Patch(ImmutableList.of( | ||
new Add<>(Path.of("person", "name"), "John Doe"), | ||
new Copy(Path.parse("/person/firstName"), Path.parse("/person/lastName")), | ||
new Move(Path.parse("/person/firstName"), Path.parse("/person/lastName")), | ||
new Remove(Path.parse("/person/name")), | ||
|
@@ -103,7 +104,8 @@ public void serializesBunchOfOperations() throws IOException { | |
public void serializesDefaultValueTypes() throws IOException { | ||
Date date = new Date(); | ||
UUID uuid = UUID.randomUUID(); | ||
Patch patch = new Patch(ImmutableList.of(new Add<>(Path.of("some", "value"), "John Doe"), | ||
Patch patch = new Patch(ImmutableList.of( | ||
new Add<>(Path.of("some", "value"), "John Doe"), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. API wise this seems to be strange and very cumbersome. Path.of seems to be a looooot of boilerplate. Especially when it is not possible (maybe I'm missing something?) to create a base path and then just add a child to it. IMO Path either needs a possibility to have a base path and then add children or otherwise people will likely start using it like this which does not seem to be right:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You could do |
||
new Add<>(Path.of("some", "value"), 42), | ||
new Add<>(Path.of("some", "value"), 42L), | ||
new Add<>(Path.of("some", "value"), uuid), | ||
|
@@ -118,19 +120,28 @@ public void serializesDefaultValueTypes() throws IOException { | |
} | ||
|
||
@Test | ||
public void serializesArbitraryHeaders() throws IOException { | ||
Patch patch = new Patch(Collections.EMPTY_LIST, ImmutableMap.of("header 1", UUID.randomUUID(), | ||
"header 2", new Date(), "header 3", 1234L, "header 4", new BigDecimal("3214123453.123512345"))); | ||
|
||
public void serializesArbitraryHeadersWithoutOperations() throws IOException { | ||
Patch patch = new Patch(Collections.EMPTY_LIST, | ||
ImmutableMap.of( | ||
"header 1", UUID.randomUUID(), | ||
"header 2", new Date(), | ||
"header 3", 1234L, | ||
"header 4", new BigDecimal("3214123453.123512345"))); | ||
byte[] bytes = patch.toBytes(); | ||
assertThat(patch, is(equalTo(Patch.of(bytes)))); | ||
} | ||
|
||
patch = new Patch(ImmutableList.of(new Copy(Path.of("from", "here"), Path.of("to", "there")), | ||
new Move(Path.of("from", "here"), Path.of("to", "there"))), | ||
ImmutableMap.of("header 1", UUID.randomUUID(), | ||
"header 2", new Date(), "header 3", 1234L, "header 4", new BigDecimal("3214123453.123512345"))); | ||
|
||
bytes = patch.toBytes(); | ||
@Test | ||
public void serializesArbitraryHeadersWithOperations() throws IOException { | ||
Patch patch = new Patch(ImmutableList.of( | ||
new Copy(Path.of("from", "here"), Path.of("to", "there")), | ||
new Move(Path.of("from", "here"), Path.of("to", "there"))), | ||
ImmutableMap.of( | ||
"header 1", UUID.randomUUID(), | ||
"header 2", new Date(), | ||
"header 3", 1234L, | ||
"header 4", new BigDecimal("3214123453.123512345"))); | ||
byte[] bytes = patch.toBytes();; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. remove ; |
||
assertThat(patch, is(equalTo(Patch.of(bytes)))); | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,6 +8,7 @@ | |
|
||
import java.util.*; | ||
import java.util.function.Function; | ||
import java.util.stream.Collectors; | ||
|
||
import static org.hamcrest.core.AllOf.allOf; | ||
|
||
|
@@ -45,12 +46,9 @@ public static <T extends Operation> Matcher<Iterable<T>> hasItems(T... items) { | |
} | ||
|
||
public static <T extends Operation> Matcher<Iterable<T>> hasItems(List<T> items) { | ||
List<Matcher<? super Iterable<T>>> all = new ArrayList<Matcher<? super Iterable<T>>>(items.size()); | ||
for (T element : items) { | ||
all.add(hasItem(element)); | ||
} | ||
|
||
return allOf(all); | ||
return allOf(items.stream() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Insert line break before |
||
.map(item -> hasItem(item)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
.collect(Collectors.toList())); | ||
} | ||
|
||
public static <T extends Operation> Matcher<List<T>> hasItemsOrdered(List<T> expected) { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
package io.datanerds.avropatch.operation.matcher; | ||
|
||
import com.google.common.collect.ImmutableList; | ||
import com.google.common.collect.ImmutableMap; | ||
import io.datanerds.avropatch.Patch; | ||
import io.datanerds.avropatch.operation.Copy; | ||
import io.datanerds.avropatch.operation.Move; | ||
import io.datanerds.avropatch.operation.Operation; | ||
import io.datanerds.avropatch.operation.Path; | ||
import org.junit.Test; | ||
import org.junit.experimental.runners.Enclosed; | ||
import org.junit.runner.RunWith; | ||
|
||
import java.io.IOException; | ||
import java.util.Collections; | ||
import java.util.UUID; | ||
|
||
import static io.datanerds.avropatch.operation.matcher.PatchMatcher.equalTo; | ||
import static org.hamcrest.CoreMatchers.is; | ||
import static org.hamcrest.CoreMatchers.not; | ||
import static org.hamcrest.MatcherAssert.assertThat; | ||
|
||
@RunWith(Enclosed.class) | ||
public class PatchMatcherTest { | ||
|
||
public static class Headers { | ||
private final UUID uuid = UUID.randomUUID(); | ||
private final Patch patchWithHeader = new Patch(Collections.EMPTY_LIST, ImmutableMap.of("header", uuid)); | ||
private final Patch patchWithHeaderSibling = new Patch(Collections.EMPTY_LIST, ImmutableMap.of("header", uuid)); | ||
private final Patch differentHeader = new Patch(Collections.EMPTY_LIST, ImmutableMap.of("header 2", uuid)); | ||
private final Patch differentHeaderValue = new Patch(Collections.EMPTY_LIST, | ||
ImmutableMap.of("header", UUID.randomUUID())); | ||
|
||
@Test | ||
public void equality() throws IOException { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Split the two asserts into two tests. Each assertion should be in a separate test to avoid failing assertions being hidden by assertions already failing before. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Best rule would be one assertion per test method. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Perhaps you could elaborate a bit on the test methods by naming them so they explain what is tested exactly. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since we're considering to get rid of these classes (see #7), I'll ignore it for now. |
||
assertThat(patchWithHeader, is(equalTo(patchWithHeaderSibling))); | ||
assertThat(patchWithHeaderSibling, is(equalTo(patchWithHeader))); | ||
} | ||
|
||
@Test | ||
public void inequality() throws IOException { | ||
assertThat(patchWithHeader, is(not(equalTo(differentHeader)))); | ||
assertThat(patchWithHeader, is(not(equalTo(differentHeaderValue)))); | ||
} | ||
} | ||
|
||
public static class Operations { | ||
private final Operation copy = new Copy(Path.of("from", "here"), Path.of("to", "there")); | ||
private final Operation move = new Move(Path.of("from", "here"), Path.of("to", "there")); | ||
private final Patch copyMovePatch = new Patch(ImmutableList.of(copy, move), Collections.EMPTY_MAP); | ||
private final Patch copyMovePatchSibling = new Patch(ImmutableList.of(copy, move), Collections.EMPTY_MAP); | ||
private final Patch withoutMoveOperation = new Patch(ImmutableList.of(copy), Collections.EMPTY_MAP); | ||
private final Patch reverseOperationOrder = new Patch(ImmutableList.of(move, copy), Collections.EMPTY_MAP); | ||
|
||
@Test | ||
public void equality() throws IOException { | ||
assertThat(copyMovePatch, is(equalTo(copyMovePatchSibling))); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. BTW: this There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am going to add a card to the backlog in order to remove the boilerplate test code There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I created issue #7 for future discussions and reference on this topic |
||
assertThat(copyMovePatchSibling, is(equalTo(copyMovePatch))); | ||
} | ||
|
||
@Test | ||
public void inequality() throws IOException { | ||
assertThat(copyMovePatch, is(not(equalTo(withoutMoveOperation)))); | ||
assertThat(copyMovePatch, is(not(equalTo(reverseOperationOrder)))); | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Always a good idea to declare method arguments as final (especially in case of collections) which makes it explicit to the calling function that the list would not be modified in the called method.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Disagree. The
final
only states that the reference can't be reassigned within the block. The list is still mutable.Agree though on parameter declarations being implicitly
final
would be a good thing :) Though I think that the boilerplate doesn't satisfy the improvement, would support a source code check rather for a variable being reassigned, as i.e. Findbugs supports AFAIR.