From 3295ecee421bbfab950bf5e4bb32e9cc95746f5e Mon Sep 17 00:00:00 2001
From: Valery Kharseko <vharseko@3a-systems.ru>
Date: Wed, 30 Sep 2026 12:25:59 +0000
Subject: [PATCH] [#1118] Register the shipped Referential Integrity plugin for the pre-operation types check-references needs, and refuse check-references without them (#1123)
---
opendj-server-legacy/src/test/java/org/opends/server/tools/upgrade/UpgradeUtilsTestCase.java | 114 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 113 insertions(+), 1 deletions(-)
diff --git a/opendj-server-legacy/src/test/java/org/opends/server/tools/upgrade/UpgradeUtilsTestCase.java b/opendj-server-legacy/src/test/java/org/opends/server/tools/upgrade/UpgradeUtilsTestCase.java
index fb9eed1..446a4ef 100644
--- a/opendj-server-legacy/src/test/java/org/opends/server/tools/upgrade/UpgradeUtilsTestCase.java
+++ b/opendj-server-legacy/src/test/java/org/opends/server/tools/upgrade/UpgradeUtilsTestCase.java
@@ -19,25 +19,33 @@
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
+import java.util.Locale;
+import org.forgerock.opendj.ldap.ByteString;
import org.forgerock.opendj.ldap.DN;
import org.forgerock.opendj.ldap.Entry;
+import org.forgerock.opendj.ldap.Filter;
import org.forgerock.opendj.ldap.schema.Schema;
import org.forgerock.opendj.ldif.LDIFEntryReader;
import org.forgerock.opendj.ldif.LDIFEntryWriter;
import org.opends.server.DirectoryServerTestCase;
import org.opends.server.TestCaseUtils;
+import org.opends.server.util.BuildVersion;
import org.opends.server.util.ChangeOperationType;
import org.opends.server.util.StaticUtils;
+import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
+import static org.opends.messages.ToolMessages.INFO_UPGRADE_TASK_ADD_REFERENTIAL_INTEGRITY_PRE_OPERATION_PLUGIN_TYPES;
import static org.testng.Assert.*;
/**
* Tests that the issue #851 upgrade task payloads, applied through
* {@link UpgradeUtils#updateConfigFile}, add the RFC 5805 transaction extended operation handler
- * entries exactly once and match the fresh-install template.
+ * entries exactly once and match the fresh-install template, and that the issue #1118 payload
+ * gives the Referential Integrity plugin the plugin types of the fresh-install template.
*/
@SuppressWarnings("javadoc")
@Test(groups = { "precommit", "tools" }, sequential = true)
@@ -46,6 +54,10 @@
/** Unknown config attributes must not fail parsing, as in the upgrade tool's own schema. */
private final Schema schema = Schema.getCoreSchema().asNonStrictSchema();
+ private static final String PLUGIN_TYPE = "ds-cfg-plugin-type";
+ private final DN referentialIntegrityPluginDN =
+ DN.valueOf("cn=Referential Integrity,cn=Plugins,cn=config", schema);
+
/** The config.ldif template a fresh install starts from. */
private File freshInstallTemplate()
{
@@ -88,11 +100,111 @@
}
}
+ @DataProvider
+ public Object[][] referentialIntegrityPluginTypesBeforeUpgrade()
+ {
+ return new Object[][] {
+ // The entry shipped before issue #1118.
+ { new String[] { "postOperationDelete", "postOperationModifyDN", "subordinateModifyDN",
+ "subordinateDelete" } },
+ // The same entry with one type already added by hand, in the lower case dsconfig writes.
+ { new String[] { "postOperationDelete", "postOperationModifyDN", "subordinateModifyDN",
+ "subordinateDelete", "preoperationadd" } },
+ };
+ }
+
+ /** Issue #1118: the task leaves the plugin with the plugin types a fresh install ships, each once. */
+ @Test(dataProvider = "referentialIntegrityPluginTypesBeforeUpgrade")
+ public void testAddReferentialIntegrityPluginTypesMirrorsFreshInstallTemplate(final String[] pluginTypes)
+ throws Exception
+ {
+ final File tempDir = TestCaseUtils.createTemporaryDirectory("upgradeTask1118");
+ try
+ {
+ final File config = new File(tempDir, "config.ldif");
+ writeConfigWithReferentialIntegrityPluginTypes(config, pluginTypes);
+
+ assertEquals(applyAddReferentialIntegrityPluginTypes(config), 1);
+ assertEquals(applyAddReferentialIntegrityPluginTypes(config), 1);
+
+ assertEquals(referentialIntegrityPluginTypes(config),
+ referentialIntegrityPluginTypes(freshInstallTemplate()));
+ }
+ finally
+ {
+ StaticUtils.recursiveDelete(tempDir);
+ }
+ }
+
+ /** Issue #1118: an upgrade from 5.1.x to 5.2.0 runs the task that adds the plugin types. */
+ @Test
+ public void testAddReferentialIntegrityPluginTypesTaskRunsOnUpgradeTo520() throws Exception
+ {
+ final List<String> summaries = new ArrayList<>();
+ for (final UpgradeTask task : Upgrade.getUpgradeTasks(BuildVersion.valueOf("5.1.2"), BuildVersion.valueOf("5.2.0")))
+ {
+ summaries.add(task.toString());
+ }
+ assertTrue(summaries.contains(INFO_UPGRADE_TASK_ADD_REFERENTIAL_INTEGRITY_PRE_OPERATION_PLUGIN_TYPES.get().toString()),
+ summaries.toString());
+ }
+
private int applyAdd(final File config, final String... ldifLines) throws Exception
{
return UpgradeUtils.updateConfigFile(config, null, ChangeOperationType.ADD, ldifLines);
}
+ private int applyAddReferentialIntegrityPluginTypes(final File config) throws Exception
+ {
+ return UpgradeUtils.updateConfigFile(config, Filter.valueOf(Upgrade.REFERENTIAL_INTEGRITY_PLUGIN_FILTER),
+ ChangeOperationType.MODIFY, Upgrade.ADD_REFERENTIAL_INTEGRITY_PRE_OPERATION_PLUGIN_TYPES);
+ }
+
+ private void writeConfigWithReferentialIntegrityPluginTypes(final File config, final String... pluginTypes)
+ throws Exception
+ {
+ int replaced = 0;
+ try (LDIFEntryReader reader =
+ new LDIFEntryReader(new FileInputStream(freshInstallTemplate())).setSchema(schema);
+ LDIFEntryWriter writer = new LDIFEntryWriter(new FileOutputStream(config)))
+ {
+ while (reader.hasNext())
+ {
+ final Entry entry = reader.readEntry();
+ if (entry.getName().equals(referentialIntegrityPluginDN))
+ {
+ entry.replaceAttribute(PLUGIN_TYPE, (Object[]) pluginTypes);
+ replaced++;
+ }
+ writer.writeEntry(entry);
+ }
+ }
+ assertEquals(replaced, 1, "fresh-install template no longer ships the Referential Integrity plugin");
+ }
+
+ /**
+ * The plugin types of the Referential Integrity plugin, lower-cased and sorted. Duplicates are
+ * kept: the schema used to read matches the unknown config attribute case-exactly, so two
+ * values differing only in case both show.
+ */
+ private List<String> referentialIntegrityPluginTypes(final File config) throws Exception
+ {
+ for (final Entry entry : readEntries(config))
+ {
+ if (entry.getName().equals(referentialIntegrityPluginDN))
+ {
+ final List<String> types = new ArrayList<>();
+ for (final ByteString value : entry.getAttribute(PLUGIN_TYPE))
+ {
+ types.add(value.toString().toLowerCase(Locale.ROOT));
+ }
+ Collections.sort(types);
+ return types;
+ }
+ }
+ throw new AssertionError("no entry " + referentialIntegrityPluginDN + " in " + config);
+ }
+
private void writeConfigWithoutTransactionEntries(final File config) throws Exception
{
final DN startDN = dnOf(Upgrade.START_TRANSACTION_HANDLER_ENTRY);
--
Gitblit v1.10.0