From 251f9586274ce5f121b0bb596fbb21e1ecd39442 Mon Sep 17 00:00:00 2001
From: Jean-Noël Rouvignac <jean-noel.rouvignac@forgerock.com>
Date: Fri, 09 Sep 2016 12:52:10 +0000
Subject: [PATCH] OPENDJ-3281 Modify operations may not be replayed if case is mixed on attribute values
---
opendj-server-legacy/src/test/java/org/opends/server/replication/plugin/AttrHistoricalMultipleTest.java | 53 +++++-----
opendj-server-legacy/src/main/java/org/opends/server/replication/plugin/AttrHistorical.java | 11 +-
opendj-server-legacy/src/main/java/org/opends/server/replication/plugin/AttrHistoricalSingle.java | 27 ++++-
opendj-server-legacy/src/main/java/org/opends/server/replication/plugin/AttrHistoricalMultiple.java | 47 +++++---
opendj-server-legacy/src/test/java/org/opends/server/replication/plugin/AttrValueHistoricalTest.java | 56 +++++++---
opendj-server-legacy/src/main/java/org/opends/server/replication/plugin/AttrValueHistorical.java | 41 +++++++-
opendj-server-legacy/src/main/java/org/opends/server/replication/plugin/EntryHistorical.java | 2
opendj-server-legacy/src/test/java/org/opends/server/replication/plugin/AttrHistoricalSingleTest.java | 10 +
8 files changed, 164 insertions(+), 83 deletions(-)
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/replication/plugin/AttrHistorical.java b/opendj-server-legacy/src/main/java/org/opends/server/replication/plugin/AttrHistorical.java
index 60276aa..7b83f30 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/replication/plugin/AttrHistorical.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/replication/plugin/AttrHistorical.java
@@ -20,8 +20,8 @@
import java.util.Set;
import org.forgerock.opendj.ldap.ByteString;
-import org.opends.server.replication.common.CSN;
import org.forgerock.opendj.ldap.schema.AttributeType;
+import org.opends.server.replication.common.CSN;
import org.opends.server.types.Entry;
import org.opends.server.types.Modification;
@@ -59,12 +59,12 @@
/**
* Create a new object from a provided attribute type. Historical is empty.
*
- * @param type the provided attribute type.
+ * @param attrType the provided attribute type.
* @return a new AttributeInfo object.
*/
- public static AttrHistorical createAttributeHistorical(AttributeType type)
+ public static AttrHistorical createAttributeHistorical(AttributeType attrType)
{
- return type.isSingleValue() ? new AttrHistoricalSingle() : new AttrHistoricalMultiple();
+ return attrType.isSingleValue() ? new AttrHistoricalSingle(attrType) : new AttrHistoricalMultiple();
}
/**
@@ -85,8 +85,9 @@
* Assign the provided information to this object.
*
* @param histKey the key to assign.
+ * @param attrType the associated attribute type.
* @param value the associated value or null if there is no value;
* @param csn the associated CSN.
*/
- public abstract void assign(HistAttrModificationKey histKey, ByteString value, CSN csn);
+ public abstract void assign(HistAttrModificationKey histKey, AttributeType attrType, ByteString value, CSN csn);
}
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/replication/plugin/AttrHistoricalMultiple.java b/opendj-server-legacy/src/main/java/org/opends/server/replication/plugin/AttrHistoricalMultiple.java
index cabbce4..463a382 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/replication/plugin/AttrHistoricalMultiple.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/replication/plugin/AttrHistoricalMultiple.java
@@ -147,21 +147,25 @@
*/
void delete(Attribute attr, CSN csn)
{
+ AttributeType attrType = attr.getAttributeDescription().getAttributeType();
for (ByteString val : attr)
{
- delete(val, csn);
+ delete(val, attrType, csn);
}
}
/**
- * Update the historical of this attribute after a delete value.
- *
- * @param val value that was deleted
- * @param csn time when the delete was done
- */
- void delete(ByteString val, CSN csn)
+ * Update the historical of this attribute after a delete value.
+ *
+ * @param val
+ * value that was deleted
+ * @param attrType
+ * @param csn
+ * time when the delete was done
+ */
+ void delete(ByteString val, AttributeType attrType, CSN csn)
{
- update(csn, new AttrValueHistorical(val, null, csn));
+ update(csn, new AttrValueHistorical(val, attrType, null, csn));
}
/**
@@ -174,9 +178,10 @@
*/
private void add(Attribute attr, CSN csn)
{
+ AttributeType attrType = attr.getAttributeDescription().getAttributeType();
for (ByteString val : attr)
{
- add(val, csn);
+ add(val, attrType, csn);
}
}
@@ -185,12 +190,13 @@
*
* @param addedValue
* values that was added
+ * @param attrType
* @param csn
* time when the value was added
*/
- void add(ByteString addedValue, CSN csn)
+ void add(ByteString addedValue, AttributeType attrType, CSN csn)
{
- update(csn, new AttrValueHistorical(addedValue, csn, null));
+ update(csn, new AttrValueHistorical(addedValue, attrType, csn, null));
}
private void update(CSN csn, AttrValueHistorical valInfo)
@@ -425,13 +431,14 @@
// we are processing DELETE of some attribute values
AttributeBuilder builder = new AttributeBuilder(modAttr);
+ AttributeType attrType = modAttr.getAttributeDescription().getAttributeType();
for (ByteString val : modAttr)
{
boolean deleteIt = true; // true if the delete must be done
boolean addedInCurrentOp = false;
// update historical information
- AttrValueHistorical valInfo = new AttrValueHistorical(val, null, csn);
+ AttrValueHistorical valInfo = new AttrValueHistorical(val, attrType, null, csn);
AttrValueHistorical oldValInfo = valuesHist.get(valInfo);
if (oldValInfo != null)
{
@@ -516,10 +523,12 @@
return false;
}
- AttributeBuilder builder = new AttributeBuilder(m.getAttribute());
- for (ByteString addVal : m.getAttribute())
+ Attribute attribute = m.getAttribute();
+ AttributeBuilder builder = new AttributeBuilder(attribute);
+ AttributeType attrType = attribute.getAttributeDescription().getAttributeType();
+ for (ByteString addVal : attribute)
{
- AttrValueHistorical valInfo = new AttrValueHistorical(addVal, csn, null);
+ AttrValueHistorical valInfo = new AttrValueHistorical(addVal, attrType, csn, null);
AttrValueHistorical oldValInfo = valuesHist.get(valInfo);
if (oldValInfo == null)
{
@@ -582,21 +591,21 @@
}
@Override
- public void assign(HistAttrModificationKey histKey, ByteString value, CSN csn)
+ public void assign(HistAttrModificationKey histKey, AttributeType attrType, ByteString value, CSN csn)
{
switch (histKey)
{
case ADD:
if (value != null)
{
- add(value, csn);
+ add(value, attrType, csn);
}
break;
case DEL:
if (value != null)
{
- delete(value, csn);
+ delete(value, attrType, csn);
}
break;
@@ -604,7 +613,7 @@
delete(csn);
if (value != null)
{
- add(value, csn);
+ add(value, attrType, csn);
}
break;
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/replication/plugin/AttrHistoricalSingle.java b/opendj-server-legacy/src/main/java/org/opends/server/replication/plugin/AttrHistoricalSingle.java
index 6fd69bc..9543edb 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/replication/plugin/AttrHistoricalSingle.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/replication/plugin/AttrHistoricalSingle.java
@@ -24,9 +24,9 @@
import org.forgerock.opendj.ldap.ByteString;
import org.forgerock.opendj.ldap.ModificationType;
+import org.forgerock.opendj.ldap.schema.AttributeType;
import org.opends.server.replication.common.CSN;
import org.opends.server.types.Attribute;
-import org.forgerock.opendj.ldap.schema.AttributeType;
import org.opends.server.types.Entry;
import org.opends.server.types.Modification;
@@ -38,18 +38,31 @@
*/
public class AttrHistoricalSingle extends AttrHistorical
{
- /** Last time when the attribute was deleted. */
- private CSN deleteTime;
- /** Last time when a value was added. */
- private CSN addTime;
/** Last added value. */
private ByteString value;
+ /** Attribute type for this historical value */
+ private AttributeType attributeType;
+ /** Last time when a value was added. */
+ private CSN addTime;
+ /** Last time when the attribute was deleted. */
+ private CSN deleteTime;
/**
* Last operation applied. This is only used for multiple mods on the same
* single valued attribute in the same modification.
*/
private HistAttrModificationKey lastMod;
+ /**
+ * Builds an {@link AttrHistoricalSingle} object.
+ *
+ * @param attributeType
+ * the attribute type for this historical value
+ */
+ public AttrHistoricalSingle(AttributeType attributeType)
+ {
+ this.attributeType = attributeType;
+ }
+
@Override
public CSN getDeleteTime()
{
@@ -61,7 +74,7 @@
{
if (addTime != null)
{
- return Collections.singleton(new AttrValueHistorical(value, addTime, null));
+ return Collections.singleton(new AttrValueHistorical(value, attributeType, addTime, null));
}
return Collections.emptySet();
}
@@ -262,7 +275,7 @@
}
@Override
- public void assign(HistAttrModificationKey histKey, ByteString value, CSN csn)
+ public void assign(HistAttrModificationKey histKey, AttributeType attrType, ByteString value, CSN csn)
{
switch (histKey)
{
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/replication/plugin/AttrValueHistorical.java b/opendj-server-legacy/src/main/java/org/opends/server/replication/plugin/AttrValueHistorical.java
index 4422c20..463e2fb 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/replication/plugin/AttrValueHistorical.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/replication/plugin/AttrValueHistorical.java
@@ -12,30 +12,38 @@
* information: "Portions Copyright [year] [name of copyright owner]".
*
* Copyright 2006-2010 Sun Microsystems, Inc.
- * Portions Copyright 2013-2015 ForgeRock AS.
+ * Portions Copyright 2013-2016 ForgeRock AS.
*/
package org.opends.server.replication.plugin;
+import static org.forgerock.util.Reject.*;
+
import org.forgerock.opendj.ldap.ByteString;
+import org.forgerock.opendj.ldap.DecodeException;
+import org.forgerock.opendj.ldap.schema.AttributeType;
import org.opends.server.replication.common.CSN;
/** AttrValueHistorical is the historical information of the modification of one attribute value. */
public class AttrValueHistorical
{
+ private AttributeType attributeType;
private ByteString value;
+ private ByteString normalizedValue;
private CSN valueDeleteTime;
private CSN valueUpdateTime;
/**
* Build an AttrValueHistorical for a provided attribute value, providing
* the last time the provided value is either updated or deleted.
- * @param value the provided attributeValue
+ * @param value the provided attribute value
+ * @param attributeType the provided attribute type
* @param csnUpdate last time when this value was updated
* @param csnDelete last time when this value for deleted
*/
- public AttrValueHistorical(ByteString value, CSN csnUpdate, CSN csnDelete)
+ public AttrValueHistorical(ByteString value, AttributeType attributeType, CSN csnUpdate, CSN csnDelete)
{
this.value = value;
+ this.attributeType = checkNotNull(attributeType);
this.valueUpdateTime = csnUpdate;
this.valueDeleteTime = csnDelete;
}
@@ -46,7 +54,14 @@
if (obj instanceof AttrValueHistorical)
{
AttrValueHistorical objVal = (AttrValueHistorical) obj;
- return value.equals(objVal.getAttributeValue());
+ try
+ {
+ return getNormalizedValue().equals(objVal.getNormalizedValue());
+ }
+ catch (DecodeException e)
+ {
+ return value.equals(objVal.getAttributeValue());
+ }
}
return false;
}
@@ -54,7 +69,23 @@
@Override
public int hashCode()
{
- return value.hashCode();
+ try
+ {
+ return getNormalizedValue().hashCode();
+ }
+ catch (DecodeException e)
+ {
+ return value.hashCode();
+ }
+ }
+
+ private ByteString getNormalizedValue() throws DecodeException
+ {
+ if (normalizedValue == null)
+ {
+ normalizedValue = attributeType.getEqualityMatchingRule().normalizeAttributeValue(value);
+ }
+ return normalizedValue;
}
/**
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/replication/plugin/EntryHistorical.java b/opendj-server-legacy/src/main/java/org/opends/server/replication/plugin/EntryHistorical.java
index 0cb9c59..59d0ab3 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/replication/plugin/EntryHistorical.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/replication/plugin/EntryHistorical.java
@@ -581,7 +581,7 @@
attrInfo = AttrHistorical.createAttributeHistorical(attrDesc.getAttributeType());
newHistorical.attributesHistorical.put(attrDesc, attrInfo);
}
- attrInfo.assign(histVal.getHistKey(), histVal.getAttributeValue(), csn);
+ attrInfo.assign(histVal.getHistKey(), attrDesc.getAttributeType(), histVal.getAttributeValue(), csn);
}
}
}
diff --git a/opendj-server-legacy/src/test/java/org/opends/server/replication/plugin/AttrHistoricalMultipleTest.java b/opendj-server-legacy/src/test/java/org/opends/server/replication/plugin/AttrHistoricalMultipleTest.java
index 31b211f..1e13c7f 100644
--- a/opendj-server-legacy/src/test/java/org/opends/server/replication/plugin/AttrHistoricalMultipleTest.java
+++ b/opendj-server-legacy/src/test/java/org/opends/server/replication/plugin/AttrHistoricalMultipleTest.java
@@ -25,12 +25,12 @@
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
-import java.util.Set;
import org.forgerock.i18n.LocalizableMessageBuilder;
import org.forgerock.opendj.ldap.ByteString;
import org.forgerock.opendj.ldap.ModificationType;
import org.forgerock.opendj.ldap.schema.AttributeType;
+import org.forgerock.opendj.ldap.schema.CoreSchema;
import org.opends.server.TestCaseUtils;
import org.opends.server.core.DirectoryServer;
import org.opends.server.replication.ReplicationTestCase;
@@ -113,52 +113,54 @@
/** Create a AttrInfo and check the methods. */
@Test(dataProvider = "attrInfo")
- public void attrInfo(ByteString att, CSN deleteTime, CSN updateTime) throws Exception
+ public void attrInfo(ByteString attrValue, CSN deleteTime, CSN updateTime) throws Exception
{
+ AttributeType attrType = CoreSchema.getDescriptionAttributeType();
// Create an empty AttrInfo
AttrHistoricalMultiple attrInfo1 = new AttrHistoricalMultiple();
// Check
- attrInfo1.add(att, updateTime);
- Set<AttrValueHistorical> values1 = attrInfo1.getValuesHistorical();
- assertEquals(values1.size(), 1);
- AttrValueHistorical valueInfo1 = new AttrValueHistorical(att, updateTime, null);
- assertTrue(values1.contains(valueInfo1));
+ attrInfo1.add(attrValue, attrType, updateTime);
+ assertThat(attrInfo1.getValuesHistorical())
+ .containsOnly(new AttrValueHistorical(attrValue, attrType, updateTime, null));
// Check constructor with parameter
- AttrValueHistorical valueInfo2 = new AttrValueHistorical(att, updateTime, deleteTime);
+ AttrValueHistorical valueInfo2 = new AttrValueHistorical(attrValue, attrType, updateTime, deleteTime);
AttrHistoricalMultiple attrInfo2 = new AttrHistoricalMultiple(
- deleteTime, updateTime, Collections.singletonMap(valueInfo2, valueInfo2));
+ deleteTime, updateTime, Collections.singleton(valueInfo2));
// Check equality
//assertTrue(attrInfo1.getDeleteTime().compareTo(attrInfo2.getDeleteTime())==0);
// Check constructor with time parameter and not Value
AttrHistoricalMultiple attrInfo3 = new AttrHistoricalMultiple(deleteTime, updateTime, null);
- attrInfo3.add(att, updateTime);
- Set<AttrValueHistorical> values3 = attrInfo3.getValuesHistorical();
- assertEquals(values3.size(), 1);
- valueInfo1 = new AttrValueHistorical(att, updateTime, null);
- assertTrue(values3.contains(valueInfo1));
+ attrInfo3.add(attrValue, attrType, updateTime);
+ assertThat(attrInfo3.getValuesHistorical())
+ .containsOnly(new AttrValueHistorical(attrValue, attrType, updateTime, null));
// Check duplicate
- AttrHistoricalMultiple attrInfo4 = attrInfo3.duplicate();
- Set<AttrValueHistorical> values4 = attrInfo4.getValuesHistorical();
+ AttrHistoricalMultiple attrInfo4 = duplicate(attrInfo3);
assertEquals(attrInfo4.getDeleteTime().compareTo(attrInfo3.getDeleteTime()), 0);
- assertEquals(values4.size(), values3.size());
+ assertThat(attrInfo4.getValuesHistorical()).isEqualTo(attrInfo3.getValuesHistorical());
// Check
- attrInfo4.delete(att, updateTime);
+ attrInfo4.delete(attrValue, attrType, updateTime);
assertEquals(attrInfo4.getValuesHistorical().size(), 1);
// Check
AttributeType type = DirectoryServer.getSchema().getAttributeType(ATTRIBUTE_NAME);
- attrInfo3.delete(Attributes.create(type, att), updateTime) ;
+ attrInfo3.delete(Attributes.create(type, attrValue), updateTime);
assertEquals(attrInfo3.getValuesHistorical().size(), 1);
// Check
attrInfo2.delete(updateTime);
- assertEquals(attrInfo2.getValuesHistorical().size(), 0);
+ assertThat(attrInfo2.getValuesHistorical()).isEmpty();
+ }
+
+ private AttrHistoricalMultiple duplicate(AttrHistoricalMultiple attrMul)
+ {
+ return new AttrHistoricalMultiple(
+ attrMul.getDeleteTime(), attrMul.getLastUpdateTime(), attrMul.getValuesHistorical());
}
@Test
@@ -253,22 +255,23 @@
assertAttributeValues(entry, "X");
}
+ /** Use case: user changes the case of a family name for example. */
@Test
public void replay_addThenDeleteThenAdd_differentCaseWithCaseIgnoreAttributeType() throws Exception
{
CSN[] t = newCSNs(3);
- mod = newModification(ADD, "X");
+ mod = newModification(ADD, "x");
replayOperation(t[0], entry, mod, SUCCESS);
- assertAttributeValues(entry, "X");
+ assertAttributeValues(entry, "x");
- mod = newModification(DELETE, "x");
+ mod = newModification(DELETE, "X");
replayOperation(t[1], entry, mod, SUCCESS);
assertNoAttributeValue(entry);
mod = newModification(ADD, "X");
- replayOperationSuppressMod(t[2], entry, mod, CONFLICT);
- assertAttributeValues(entry);
+ replayOperation(t[2], entry, mod, SUCCESS);
+ assertAttributeValues(entry, "X");
}
@Test
diff --git a/opendj-server-legacy/src/test/java/org/opends/server/replication/plugin/AttrHistoricalSingleTest.java b/opendj-server-legacy/src/test/java/org/opends/server/replication/plugin/AttrHistoricalSingleTest.java
index 625a9d7..2afb988 100644
--- a/opendj-server-legacy/src/test/java/org/opends/server/replication/plugin/AttrHistoricalSingleTest.java
+++ b/opendj-server-legacy/src/test/java/org/opends/server/replication/plugin/AttrHistoricalSingleTest.java
@@ -25,6 +25,8 @@
import org.forgerock.i18n.LocalizableMessageBuilder;
import org.forgerock.opendj.ldap.ByteString;
import org.forgerock.opendj.ldap.ModificationType;
+import org.forgerock.opendj.ldap.schema.AttributeType;
+import org.forgerock.opendj.ldap.schema.Schema;
import org.opends.server.TestCaseUtils;
import org.opends.server.replication.ReplicationTestCase;
import org.opends.server.replication.common.CSN;
@@ -54,7 +56,8 @@
@BeforeMethod
public void localSetUp() throws Exception
{
- attrHist = new AttrHistoricalSingle();
+ AttributeType attrType = Schema.getDefaultSchema().getAttributeType(ATTRIBUTE_NAME);
+ attrHist = new AttrHistoricalSingle(attrType);
csn = csnGen.newCSN();
entry = TestCaseUtils.makeEntry(
"dn: uid=test.user",
@@ -213,8 +216,9 @@
@Test
public void replay_deleteDubious() throws Exception
{
- HistoricalAttributeValue histAttrVal = new HistoricalAttributeValue("display:" + csn + ":add:X");
- attrHist.assign(histAttrVal.getHistKey(), histAttrVal.getAttributeValue(), csn);
+ AttributeType attrType = Schema.getDefaultSchema().getAttributeType(ATTRIBUTE_NAME);
+ HistoricalAttributeValue histAttrVal = new HistoricalAttributeValue(ATTRIBUTE_NAME + ":" + csn + ":add:X");
+ attrHist.assign(histAttrVal.getHistKey(), attrType, histAttrVal.getAttributeValue(), csn);
mod = newModification(ADD, "X");
entry.applyModification(mod);
assertAttributeValue(entry, "X");
diff --git a/opendj-server-legacy/src/test/java/org/opends/server/replication/plugin/ValueInfoTest.java b/opendj-server-legacy/src/test/java/org/opends/server/replication/plugin/AttrValueHistoricalTest.java
similarity index 65%
rename from opendj-server-legacy/src/test/java/org/opends/server/replication/plugin/ValueInfoTest.java
rename to opendj-server-legacy/src/test/java/org/opends/server/replication/plugin/AttrValueHistoricalTest.java
index 1042bc2..1d3a85f 100644
--- a/opendj-server-legacy/src/test/java/org/opends/server/replication/plugin/ValueInfoTest.java
+++ b/opendj-server-legacy/src/test/java/org/opends/server/replication/plugin/AttrValueHistoricalTest.java
@@ -12,29 +12,27 @@
* information: "Portions Copyright [year] [name of copyright owner]".
*
* Copyright 2006-2010 Sun Microsystems, Inc.
- * Portions Copyright 2013-2015 ForgeRock AS.
+ * Portions Copyright 2013-2016 ForgeRock AS.
*/
package org.opends.server.replication.plugin;
+import static org.assertj.core.api.Assertions.*;
+import static org.testng.Assert.*;
+
+import org.forgerock.opendj.ldap.ByteString;
+import org.forgerock.opendj.ldap.schema.AttributeType;
+import org.forgerock.opendj.ldap.schema.CoreSchema;
import org.opends.server.replication.ReplicationTestCase;
import org.opends.server.replication.common.CSN;
-import org.forgerock.opendj.ldap.ByteString;
import org.opends.server.util.TimeThread;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
-import static org.testng.Assert.*;
-
-/**
- * Test of ValueInfo.
- */
+/** Test of AttrValueHistorical. */
@SuppressWarnings("javadoc")
-public class ValueInfoTest extends ReplicationTestCase
+public class AttrValueHistoricalTest extends ReplicationTestCase
{
-
- /**
- * Build some data for the ValueInfo test below.
- */
+ /** Build some data for the ValueInfo test below. */
@DataProvider(name = "valueInfo")
public Object[][] createData() {
ByteString att1 = ByteString.valueOfUtf8("string");
@@ -56,16 +54,15 @@
{att3,upd3,del3}};
}
- /**
- * Create a ValueInfo and check the methods.
- */
+ /** Create a ValueInfo and check the methods. */
@Test(dataProvider = "valueInfo")
public void valueInfo(ByteString value, CSN csnUpdate, CSN csnDelete) throws Exception
{
- AttrValueHistorical valInfo1 = new AttrValueHistorical(value, csnUpdate, csnDelete);
- AttrValueHistorical valInfo2 = new AttrValueHistorical(value, csnUpdate, csnUpdate);
+ AttributeType attrType = CoreSchema.getDescriptionAttributeType();
+ AttrValueHistorical valInfo1 = new AttrValueHistorical(value, attrType, csnUpdate, csnDelete);
+ AttrValueHistorical valInfo2 = new AttrValueHistorical(value, attrType, csnUpdate, csnUpdate);
AttrValueHistorical valInfo3 = new AttrValueHistorical(ByteString.valueOfUtf8("Test"),
- csnUpdate, csnUpdate);
+ attrType, csnUpdate, csnUpdate);
// Check equals
assertFalse(valInfo1.equals(new Object()));
@@ -87,4 +84,27 @@
assertEquals(valInfo1.getAttributeValue(), value);
assertEquals(valInfo1.isUpdate(), csnUpdate != null);
}
+
+ @Test
+ public void testEqualsHashCode()
+ {
+ final AttrValueHistorical histVal1 = newAttrValueHistorical("description");
+ final AttrValueHistorical histVal2 = newAttrValueHistorical("Description");
+ final AttrValueHistorical histVal3 = newAttrValueHistorical("another description");
+
+ assertThat(histVal1).isEqualTo(histVal1);
+ assertThat(histVal1).isEqualTo(histVal2);
+ assertThat(histVal2).isEqualTo(histVal1);
+
+ assertThat(histVal1).isNotEqualTo(histVal3);
+
+ assertThat(histVal1.hashCode()).isEqualTo(histVal2.hashCode());
+ assertThat(histVal1.hashCode()).isNotEqualTo(histVal3.hashCode());
+ }
+
+ private AttrValueHistorical newAttrValueHistorical(String pp)
+ {
+ AttributeType attrType = CoreSchema.getDescriptionAttributeType();
+ return new AttrValueHistorical(ByteString.valueOfUtf8(pp), attrType, null, null);
+ }
}
--
Gitblit v1.10.0