fix: use semantic instead of literal comparison in DefaultEqualityTester (#1665)

This fixes https://github.com/linkedin/datahub/issues/1663
Also change the signature of EqualityTester to compare only DataTemplates
This commit is contained in:
Mars Lan 2020-05-12 09:32:05 -07:00 committed by GitHub
parent 461e4f97a7
commit 2b9c8f7680
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 43 additions and 9 deletions

View File

@ -1,18 +1,19 @@
package com.linkedin.metadata.dao.equality;
import com.linkedin.data.template.DataTemplate;
import javax.annotation.Nonnull;
/**
* A {@link EqualityTester} that always returns false.
*/
public class AlwaysFalseEqualityTester<T> implements EqualityTester<T> {
public class AlwaysFalseEqualityTester<T extends DataTemplate> implements EqualityTester<T> {
/**
* Creates a new instance of {@link AlwaysFalseEqualityTester}.
*/
public static <CLASS> AlwaysFalseEqualityTester<CLASS> newInstance() {
return new AlwaysFalseEqualityTester<CLASS>();
public static <CLASS extends DataTemplate> AlwaysFalseEqualityTester<CLASS> newInstance() {
return new AlwaysFalseEqualityTester<>();
}
@Override

View File

@ -1,21 +1,24 @@
package com.linkedin.metadata.dao.equality;
import com.linkedin.data.template.DataTemplate;
import com.linkedin.data.template.DataTemplateUtil;
import javax.annotation.Nonnull;
/**
* A {@link EqualityTester} that relies on the default implementation of {@link Object#equals(Object)}.
* A {@link EqualityTester} that uses {@link DataTemplateUtil#areEqual(DataTemplate, DataTemplate)} to check for
* semantic equality.
*/
public class DefaultEqualityTester<T> implements EqualityTester<T> {
public class DefaultEqualityTester<T extends DataTemplate> implements EqualityTester<T> {
/**
* Creates a new instance of {@link DefaultEqualityTester}.
*/
public static <CLASS> DefaultEqualityTester<CLASS> newInstance() {
return new DefaultEqualityTester<CLASS>();
public static <CLASS extends DataTemplate> DefaultEqualityTester<CLASS> newInstance() {
return new DefaultEqualityTester<>();
}
@Override
public boolean equals(@Nonnull T o1, @Nonnull T o2) {
return o1.equals(o2);
return DataTemplateUtil.areEqual(o1, o2);
}
}

View File

@ -1,12 +1,13 @@
package com.linkedin.metadata.dao.equality;
import com.linkedin.data.template.DataTemplate;
import javax.annotation.Nonnull;
/**
* An interface for testing equality between two objects of the same type.
*/
public interface EqualityTester<T> {
public interface EqualityTester<T extends DataTemplate> {
boolean equals(@Nonnull T o1, @Nonnull T o2);
}

View File

@ -0,0 +1,29 @@
package com.linkedin.metadata.dao.equality;
import com.linkedin.metadata.dao.utils.RecordUtils;
import com.linkedin.testing.AspectBaz;
import java.io.IOException;
import org.testng.annotations.Test;
import static com.linkedin.metadata.utils.TestUtils.*;
import static com.linkedin.testing.TestUtils.*;
import static org.testng.Assert.*;
public class DefaultEqualityTesterTest {
@Test
public void testSemanticEquality() throws IOException, CloneNotSupportedException {
// "longField" is backed by Integer in DataMap when deserialized from JSON
AspectBaz fromJson = RecordUtils.toRecordTemplate(AspectBaz.class, loadJsonFromResource("baz.json"));
assertEquals(fromJson.data().get("longField").getClass(), Integer.class);
// Clone and change the value in DataMap to Long
AspectBaz cloned = fromJson.clone();
cloned.setLongField(1234L);
assertEquals(cloned.data().get("longField").getClass(), Long.class);
// The two should still be semantically equal
assertTrue(new DefaultEqualityTester().equals(fromJson, cloned));
}
}