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; package com.linkedin.metadata.dao.equality;
import com.linkedin.data.template.DataTemplate;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
/** /**
* A {@link EqualityTester} that always returns false. * 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}. * Creates a new instance of {@link AlwaysFalseEqualityTester}.
*/ */
public static <CLASS> AlwaysFalseEqualityTester<CLASS> newInstance() { public static <CLASS extends DataTemplate> AlwaysFalseEqualityTester<CLASS> newInstance() {
return new AlwaysFalseEqualityTester<CLASS>(); return new AlwaysFalseEqualityTester<>();
} }
@Override @Override

View File

@ -1,21 +1,24 @@
package com.linkedin.metadata.dao.equality; package com.linkedin.metadata.dao.equality;
import com.linkedin.data.template.DataTemplate;
import com.linkedin.data.template.DataTemplateUtil;
import javax.annotation.Nonnull; 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}. * Creates a new instance of {@link DefaultEqualityTester}.
*/ */
public static <CLASS> DefaultEqualityTester<CLASS> newInstance() { public static <CLASS extends DataTemplate> DefaultEqualityTester<CLASS> newInstance() {
return new DefaultEqualityTester<CLASS>(); return new DefaultEqualityTester<>();
} }
@Override @Override
public boolean equals(@Nonnull T o1, @Nonnull T o2) { 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; package com.linkedin.metadata.dao.equality;
import com.linkedin.data.template.DataTemplate;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
/** /**
* An interface for testing equality between two objects of the same type. * 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); 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));
}
}