LDIFDiffTestCase.java revision a41662c1136b2bb4a4198df89e0e87d2be3ef099
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
* or http://forgerock.org/license/CDDLv1.0.html.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at legal-notices/CDDLv1_0.txt.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information:
* Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*
*
* Copyright 2006-2010 Sun Microsystems, Inc.
* Portions Copyright 2013-2015 ForgeRock AS.
*/
package org.opends.server.tools;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import org.opends.server.TestCaseUtils;
import org.opends.server.core.DirectoryServer;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import static org.opends.server.protocols.ldap.LDAPResultCode.*;
import static org.testng.Assert.*;
/**
* A set of test cases for the LDIFDiff tool.
*/
public class LDIFDiffTestCase
extends ToolsTestCase
{
/**
* The path to the file that will be used if there are no differences between
* the source and target LDIF data sets.
*/
private String noDiffsFile =
System.getProperty(TestCaseUtils.PROPERTY_BUILD_ROOT) + File.separator +
"tests" + File.separator + "unit-tests-testng" + File.separator +
"resource" + File.separator + "ldif-diff" + File.separator +
"diff-nochanges.ldif";
/**
* Make sure that the server is running, since we need it for schema
* handling.
*
* @throws Exception If an unexpected problem occurs.
*/
@BeforeClass
public void startServer()
throws Exception
{
TestCaseUtils.startServer();
}
/** Calculates the checksum of a file. */
private long calcChecksum(String filename) throws Exception
{
return calcChecksum(new File(filename));
}
private long calcChecksum(File file) throws Exception
{
long checksum = 0L;
BufferedReader reader = new BufferedReader(new FileReader(file));
String line = null;
while ((line =reader.readLine()) != null)
{
checksum += line.hashCode();
}
reader.close();
return checksum;
}
/**
* Tests the LDIFDiff tool with an argument that will simply cause it to
* display usage information.
*/
@Test
public void testUsage()
{
String[] args = { "--help" };
assertEquals(LDIFDiff.mainDiff(args, true, System.out, System.err), 0);
args = new String[] { "-H" };
assertEquals(LDIFDiff.mainDiff(args, true, System.out, System.err), 0);
args = new String[] { "-?" };
assertEquals(LDIFDiff.mainDiff(args, true, System.out, System.err), 0);
}
/**
* Tests the LDIFDiff tool with an invalid set of arguments.
*/
@Test
public void testInvalidArguments()
{
String[] args =
{
"--invalid"
};
assertFalse(LDIFDiff.mainDiff(args, true, System.out, System.err) == 0);
}
/**
* Retrieves the names of the files that should be used when testing the
* ldif-diff tool. Each element of the outer array should be an array
* containing the following elements:
* <OL>
* <LI>The path to the source LDIF file</LI>
* <LI>The path to the target LDIF file</LI>
* <LI>The path to the diff file, or {@code null} if the diff is supposed
* to fail</LI>
* </OL>
*/
@DataProvider(name = "testdata")
public Object[][] getTestData()
{
String buildRoot = System.getProperty(TestCaseUtils.PROPERTY_BUILD_ROOT);
String ldifRoot = buildRoot + File.separator + "tests" + File.separator +
"unit-tests-testng" + File.separator + "resource" +
File.separator + "ldif-diff" + File.separator;
return new Object[][]
{
// Both files are empty.
new Object[] { ldifRoot + "source-empty.ldif",
ldifRoot + "target-empty.ldif",
noDiffsFile, noDiffsFile,
COMPARE_TRUE },
// Both files are the single-entry source.
new Object[] { ldifRoot + "source-singleentry.ldif",
ldifRoot + "source-singleentry.ldif",
noDiffsFile, noDiffsFile,
COMPARE_TRUE },
// Both files are the single-entry target.
new Object[] { ldifRoot + "target-singleentry.ldif",
ldifRoot + "target-singleentry.ldif",
noDiffsFile, noDiffsFile,
COMPARE_TRUE },
// Both files are the multiple-entry source.
new Object[] { ldifRoot + "source-multipleentries.ldif",
ldifRoot + "source-multipleentries.ldif",
noDiffsFile, noDiffsFile,
COMPARE_TRUE },
// Both files are the multiple-entry target.
new Object[] { ldifRoot + "target-multipleentries.ldif",
ldifRoot + "target-multipleentries.ldif",
noDiffsFile, noDiffsFile,
COMPARE_TRUE },
// The source is empty but the target has a single entry.
new Object[] { ldifRoot + "source-empty.ldif",
ldifRoot + "target-singleentry.ldif",
ldifRoot + "diff-emptytosingle.ldif",
ldifRoot + "diff-emptytosingle.ldif",
COMPARE_FALSE },
// The source has a single entry but the target is empty.
new Object[] { ldifRoot + "source-singleentry.ldif",
ldifRoot + "target-empty.ldif",
ldifRoot + "diff-singletoempty.ldif",
ldifRoot + "diff-singletoempty.ldif",
COMPARE_FALSE },
// Make a change to only a single entry in the source->target direction.
new Object[] { ldifRoot + "source-singleentry.ldif",
ldifRoot + "target-singleentry.ldif",
ldifRoot + "diff-singleentry.ldif",
ldifRoot + "diff-singleentry.ldif",
COMPARE_FALSE },
// Make a change to only a single entry in the target->source direction.
new Object[] { ldifRoot + "target-singleentry.ldif",
ldifRoot + "source-singleentry.ldif",
ldifRoot + "diff-singleentry-reverse.ldif",
ldifRoot + "diff-singleentry-reverse.ldif",
COMPARE_FALSE },
// Make changes to multiple entries in the source->target direction.
new Object[] { ldifRoot + "source-multipleentries.ldif",
ldifRoot + "target-multipleentries.ldif",
ldifRoot + "diff-multipleentries.ldif",
ldifRoot + "diff-multipleentries-singlevalue.ldif",
COMPARE_FALSE },
// Make changes to multiple entries in the target->source direction.
new Object[] { ldifRoot + "target-multipleentries.ldif",
ldifRoot + "source-multipleentries.ldif",
ldifRoot + "diff-multipleentries-reverse.ldif",
ldifRoot +
"diff-multipleentries-reverse-singlevalue.ldif",
COMPARE_FALSE },
// Go from one entry to multiple in the source->target direction.
new Object[] { ldifRoot + "source-singleentry.ldif",
ldifRoot + "target-multipleentries.ldif",
ldifRoot + "diff-singletomultiple.ldif",
ldifRoot + "diff-singletomultiple-singlevalue.ldif",
COMPARE_FALSE },
// Go from one entry to multiple in the target->source direction.
new Object[] { ldifRoot + "target-singleentry.ldif",
ldifRoot + "source-multipleentries.ldif",
ldifRoot + "diff-singletomultiple-reverse.ldif",
ldifRoot + "diff-singletomultiple-reverse.ldif",
COMPARE_FALSE },
// Go from multiple entries to one in the source->target direction.
new Object[] { ldifRoot + "source-multipleentries.ldif",
ldifRoot + "target-singleentry.ldif",
ldifRoot + "diff-multipletosingle.ldif",
ldifRoot + "diff-multipletosingle.ldif",
COMPARE_FALSE },
// Go from multiple entries to one in the target->source direction.
new Object[] { ldifRoot + "target-multipleentries.ldif",
ldifRoot + "source-singleentry.ldif",
ldifRoot + "diff-multipletosingle-reverse.ldif",
ldifRoot +
"diff-multipletosingle-reverse-singlevalue.ldif",
COMPARE_FALSE },
// The source file doesn't exist.
new Object[] { ldifRoot + "source-notfound.ldif",
ldifRoot + "target-singleentry.ldif",
null, null,
COMPARE_FALSE },
// The target file doesn't exist.
new Object[] { ldifRoot + "source-singleentry.ldif",
ldifRoot + "target-notfound.ldif",
null, null,
COMPARE_FALSE }
};
}
/**
* Tests the LDIFDiff tool with the provided information to ensure that the
* normal mode of operation works as expected. This is a bit tricky because
* the attributes and values will be written in an indeterminate order, so we
* can't just use string equality. We'll have to use a crude checksum
* mechanism to test whether they are equal. Combined with other methods in
* this class, this should be good enough.
*
* @param sourceFile The path to the file containing the source
* data set.
* @param targetFile The path to the file containing the target
* data set.
* @param normalDiffFile The path to the file containing the expected
* diff in "normal" form (at most one record per
* entry), or {@code null} if the diff is
* supposed to fail.
* @param singleValueDiffFile The path to the file containing the expected
* diff in "single-value" form, where each
* attribute-level change results in a separate
* entry per attribute value.
* @param resultCode The result code that should be returned with
* --useCompareResultCode flag
*
* @throws Exception If an unexpected problem occurs.
*/
@Test(dataProvider = "testdata")
public void testVerifyNormal(String sourceFile, String targetFile,
String normalDiffFile, String singleValueDiffFile, int resultCode)
throws Exception
{
File outputFile = File.createTempFile("difftest", "ldif");
outputFile.deleteOnExit();
String[] args =
{
"-s", sourceFile,
"-t", targetFile,
"-o", outputFile.getAbsolutePath(),
"-O"
};
String[] argsUseCompare =
{
"-s", sourceFile,
"-t", targetFile,
// No need to write to the outputFile
"--useCompareResultCode"
};
if (normalDiffFile == null)
{
// We expect this to fail, so just make sure that it does.
assertFalse(LDIFDiff.mainDiff(args, true, System.out, System.err) == 0);
outputFile.delete();
return;
}
assertEquals(LDIFDiff.mainDiff(args, true, System.out, System.err), 0);
assertEquals(calcChecksum(outputFile), calcChecksum(normalDiffFile));
assertEquals(LDIFDiff
.mainDiff(argsUseCompare, true, System.out, System.err), resultCode);
outputFile.delete();
}
/**
* Tests the LDIFDiff tool with the provided information to ensure that the
* single value changes mode of operation works as expected. This is a bit
* tricky because the attributes and values will be written in an
* indeterminate order, so we can't just use string equality. We'll have to
* use a crude checksum mechanism to test whether they are equal. Combined
* with other methods in this class, this should be good enough.
*
* @param sourceFile The path to the file containing the source
* data set.
* @param targetFile The path to the file containing the target
* data set.
* @param normalDiffFile The path to the file containing the expected
* diff in "normal" form (at most one record per
* entry), or {@code null} if the diff is
* supposed to fail.
* @param singleValueDiffFile The path to the file containing the expected
* diff in "single-value" form, where each
* attribute-level change results in a separate
* entry per attribute value.
* @param resultCode The result code that should be returned with
* --useCompareResultCode flag
*
* @throws Exception If an unexpected problem occurs.
*/
@Test(dataProvider = "testdata")
public void testVerifySingleValue(String sourceFile, String targetFile,
String normalDiffFile, String singleValueDiffFile, int resultCode)
throws Exception
{
File outputFile = File.createTempFile("difftest", "ldif");
outputFile.deleteOnExit();
String[] args =
{
"-s", sourceFile,
"-t", targetFile,
"-o", outputFile.getAbsolutePath(),
"-O",
"-S"
};
String[] argsUseCompare =
{
"-s", sourceFile,
"-t", targetFile,
// No need to write to the outputFile
"--useCompareResultCode"
};
if (singleValueDiffFile == null)
{
// We expect this to fail, so just make sure that it does.
assertFalse(LDIFDiff.mainDiff(args, true, System.out, System.err) == 0);
outputFile.delete();
return;
}
assertEquals(LDIFDiff.mainDiff(args, true, System.out, System.err), 0);
assertEquals(calcChecksum(outputFile), calcChecksum(singleValueDiffFile));
assertEquals(LDIFDiff
.mainDiff(argsUseCompare, true, System.out, System.err), resultCode);
outputFile.delete();
}
/**
* Tests the LDIFDiff tool by first identifying the differences between the
* source and the target and then using the LDIFModify tool to apply the
* identified changes to the source LDIF and verify that it matches the
* target.
*
* @param sourceFile The path to the file containing the source
* data set.
* @param targetFile The path to the file containing the target
* data set.
* @param normalDiffFile The path to the file containing the expected
* diff in "normal" form (at most one record per
* entry), or {@code null} if the diff is
* supposed to fail.
* @param singleValueDiffFile The path to the file containing the expected
* diff in "single-value" form, where each
* attribute-level change results in a separate
* entry per attribute value.
* @param resultCode The result code that should be returned with
* --useCompareResultCode flag
*
* @throws Exception If an unexpected problem occurs.
*/
@Test(dataProvider = "testdata")
public void testReconstructNormal(String sourceFile, String targetFile,
String normalDiffFile, String singleValueDiffFile, int resultCode)
throws Exception
{
// If the command is expected to fail, or if there aren't any differences,
// then bail out now.
if (normalDiffFile == null || normalDiffFile.equals(noDiffsFile))
{
return;
}
// Generate the diff file.
File diffOutputFile = File.createTempFile("difftest", "ldif");
diffOutputFile.deleteOnExit();
String[] args =
{
"-s", sourceFile,
"-t", targetFile,
"-o", diffOutputFile.getAbsolutePath()
};
String[] argsUseCompare =
{
"-s", sourceFile,
"-t", targetFile,
// No need to write to the outputFile
"--useCompareResultCode"
};
assertEquals(LDIFDiff.mainDiff(args, true, System.out, System.err), 0);
assertEquals(LDIFDiff
.mainDiff(argsUseCompare, true, System.out, System.err), resultCode);
// Use LDIFModify to generate a new target file.
File newTargetFile = File.createTempFile("difftest", "newtarget.ldif");
newTargetFile.deleteOnExit();
DirectoryServer.getInstance();
args = new String[]
{
"-c", DirectoryServer.getConfigFile(),
"-s", sourceFile,
"-m", diffOutputFile.getAbsolutePath(),
"-t", newTargetFile.getAbsolutePath()
};
assertEquals(LDIFModify.ldifModifyMain(args, true, System.out, System.err),
0);
// Use LDIFDiff again to verify that there are effectively no differences
// between the original target and the new target.
File newDiffFile = File.createTempFile("difftest", "newdiff.ldif");
newDiffFile.deleteOnExit();
args = new String[]
{
"-s", targetFile,
"-t", newTargetFile.getAbsolutePath(),
"-o", newDiffFile.getAbsolutePath()
};
argsUseCompare = new String[]
{
"-s", targetFile,
"-t", newTargetFile.getAbsolutePath(),
// No need to write to the outputFile
"--useCompareResultCode"
};
assertEquals(LDIFDiff.mainDiff(args, true, System.out, System.err), 0);
assertEquals(calcChecksum(newDiffFile), calcChecksum(noDiffsFile));
assertEquals(LDIFDiff
.mainDiff(argsUseCompare, true, System.out, System.err), COMPARE_TRUE);
diffOutputFile.delete();
newTargetFile.delete();
newDiffFile.delete();
}
/**
* Tests the LDIFDiff tool by first identifying the differences between the
* source and the target (using the single-value format) and then using the
* LDIFModify tool to apply the identified changes to the source LDIF and
* verify that it matches the target.
*
* @param sourceFile The path to the file containing the source
* data set.
* @param targetFile The path to the file containing the target
* data set.
* @param normalDiffFile The path to the file containing the expected
* diff in "normal" form (at most one record per
* entry), or {@code null} if the diff is
* supposed to fail.
* @param singleValueDiffFile The path to the file containing the expected
* diff in "single-value" form, where each
* attribute-level change results in a separate
* entry per attribute value.
* @param resultCode The result code that should be returned with
* --useCompareResultCode flag
*
* @throws Exception If an unexpected problem occurs.
*/
@Test(dataProvider = "testdata")
public void testReconstructSingleValue(String sourceFile, String targetFile,
String normalDiffFile, String singleValueDiffFile, int resultCode)
throws Exception
{
// If the command is expected to fail, or if there aren't any differences,
// then bail out now.
if (normalDiffFile == null || singleValueDiffFile.equals(noDiffsFile))
{
return;
}
// Generate the diff file.
File diffOutputFile = File.createTempFile("difftest", "ldif");
diffOutputFile.deleteOnExit();
String[] args =
{
"-s", sourceFile,
"-t", targetFile,
"-o", diffOutputFile.getAbsolutePath(),
"-S"
};
String[] argsUseCompare =
{
"-s", sourceFile,
"-t", targetFile,
// No need to write to the outputFile
"--useCompareResultCode"
};
assertEquals(LDIFDiff.mainDiff(args, true, System.out, System.err), 0);
assertEquals(LDIFDiff
.mainDiff(argsUseCompare, true, System.out, System.err), resultCode);
// Use LDIFModify to generate a new target file.
File newTargetFile = File.createTempFile("difftest", "newtarget.ldif");
newTargetFile.deleteOnExit();
DirectoryServer.getInstance();
args = new String[]
{
"-c", DirectoryServer.getConfigFile(),
"-s", sourceFile,
"-m", diffOutputFile.getAbsolutePath(),
"-t", newTargetFile.getAbsolutePath()
};
assertEquals(LDIFModify.ldifModifyMain(args, true, System.out, System.err),
0);
// Use LDIFDiff again to verify that there are effectively no differences
// between the original target and the new target.
File newDiffFile = File.createTempFile("difftest", "newdiff.ldif");
newDiffFile.deleteOnExit();
args = new String[]
{
"-s", targetFile,
"-t", newTargetFile.getAbsolutePath(),
"-o", newDiffFile.getAbsolutePath()
};
argsUseCompare = new String[]
{
"-s", targetFile,
"-t", newTargetFile.getAbsolutePath(),
// No need to write to the outputFile
"--useCompareResultCode"
};
assertEquals(LDIFDiff.mainDiff(args, true, System.out, System.err), 0);
assertEquals(calcChecksum(newDiffFile), calcChecksum(noDiffsFile));
assertEquals(LDIFDiff
.mainDiff(argsUseCompare, true, System.out, System.err), COMPARE_TRUE);
diffOutputFile.delete();
newTargetFile.delete();
newDiffFile.delete();
}
/**
* Retrieves the names of the files that should be used when testing the
* ldif-diff tool. Each element of the outer array should be an array
* containing the following elements:
* <OL>
* <LI>The path to the source LDIF file</LI>
* <LI>The path to the target LDIF file</LI>
* <LI>The path to the file with attributes to be ignored</LI>
* <LI>The path to the diff file</LI>
* </OL>
*/
@DataProvider(name = "ignoreattributesdata")
public Object[][] getIATestData()
{
String buildRoot = System.getProperty(TestCaseUtils.PROPERTY_BUILD_ROOT);
String ldifRoot = buildRoot + File.separator + "tests" + File.separator +
"unit-tests-testng" + File.separator + "resource" +
File.separator + "ldif-diff" + File.separator;
return new Object[][]
{
// Make changes to multiple entries in the target->source direction.
new Object[] { ldifRoot + "source-multipleentries.ldif",
ldifRoot + "target-multipleentries.ldif",
ldifRoot + "ignore-attributes",
ldifRoot + "diff-multipleentries-ignore-attributes.ldif" },
new Object[] { ldifRoot + "source-multipleentries.ldif",
ldifRoot + "target-multipleentries.ldif",
ldifRoot + "does-not-exist",
ldifRoot + "diff-multipleentries-ignore-attributes.ldif" }
};
}
/**
* Tests the LDIFDiff tool with the provided information to ensure that the
* normal mode of operation works as expected. This is a bit tricky because
* the attributes and values will be written in an indeterminate order, so we
* can't just use string equality. We'll have to use a crude checksum
* mechanism to test whether they are equal. Combined with other methods in
* this class, this should be good enough.
*
* @param sourceFile The path to the file containing the source
* data set.
* @param targetFile The path to the file containing the target
* data set.
* @param normalDiffFile The path to the file containing the expected
* diff in "normal" form (at most one record per
* entry), or {@code null} if the diff is
* supposed to fail.
* @throws Exception If an unexpected problem occurs.
*/
@Test(dataProvider = "ignoreattributesdata")
public void testVerifyIgnoreAttributes(String sourceFile, String targetFile,
String ignoreAttributesFile,
String normalDiffFile)
throws Exception
{
File outputFile = File.createTempFile("difftest", "ldif");
outputFile.deleteOnExit();
String[] args =
{
"-s", sourceFile,
"-t", targetFile,
"-a", ignoreAttributesFile,
"-o", outputFile.getAbsolutePath(),
"-O"
};
if (ignoreAttributesFile.endsWith("does-not-exist"))
{
// We expect this to fail, so just make sure that it does.
assertEquals(LDIFDiff.mainDiff(args, true, System.out, System.err), 1);
return;
}
assertEquals(LDIFDiff.mainDiff(args, true, System.out, System.err), 0);
assertEquals(calcChecksum(outputFile), calcChecksum(normalDiffFile));
outputFile.delete();
}
/**
* Retrieves the names of the files that should be used when testing the
* ldif-diff tool. Each element of the outer array should be an array
* containing the following elements:
* <OL>
* <LI>The path to the source LDIF file</LI>
* <LI>The path to the target LDIF file</LI>
* <LI>The path to the file with entries to be ignored</LI>
* <LI>The path to the diff file</LI>
* </OL>
*/
@DataProvider(name = "ignoreentriesdata")
public Object[][] getIETestData()
{
String buildRoot = System.getProperty(TestCaseUtils.PROPERTY_BUILD_ROOT);
String ldifRoot = buildRoot + File.separator + "tests" + File.separator +
"unit-tests-testng" + File.separator + "resource" +
File.separator + "ldif-diff" + File.separator;
return new Object[][]
{
// Make changes to multiple entries in the target->source direction.
new Object[] { ldifRoot + "source-multipleentries.ldif",
ldifRoot + "target-multipleentries.ldif",
ldifRoot + "ignore-entries",
ldifRoot + "diff-multipleentries-ignore-entries.ldif" },
new Object[] { ldifRoot + "source-multipleentries.ldif",
ldifRoot + "target-multipleentries.ldif",
ldifRoot + "does-not-exist",
ldifRoot + "diff-multipleentries-ignore-entries.ldif" }
};
}
/**
* Tests the LDIFDiff tool with the provided information to ensure that the
* normal mode of operation works as expected. This is a bit tricky because
* the attributes and values will be written in an indeterminate order, so we
* can't just use string equality. We'll have to use a crude checksum
* mechanism to test whether they are equal. Combined with other methods in
* this class, this should be good enough.
*
* @param sourceFile The path to the file containing the source
* data set.
* @param targetFile The path to the file containing the target
* data set.
* @param normalDiffFile The path to the file containing the expected
* diff in "normal" form (at most one record per
* entry), or {@code null} if the diff is
* supposed to fail.
* @throws Exception If an unexpected problem occurs.
*/
@Test(dataProvider = "ignoreentriesdata")
public void testVerifyIgnoreEntries(String sourceFile, String targetFile,
String ignoreEntriesFile,
String normalDiffFile)
throws Exception
{
File outputFile = File.createTempFile("difftest", "ldif");
outputFile.deleteOnExit();
String[] args =
{
"-s", sourceFile,
"-t", targetFile,
"-e", ignoreEntriesFile,
"-o", outputFile.getAbsolutePath(),
"-O"
};
if (ignoreEntriesFile.endsWith("does-not-exist"))
{
// We expect this to fail, so just make sure that it does.
assertEquals(LDIFDiff.mainDiff(args, true, System.out, System.err), 1);
return;
}
assertEquals(LDIFDiff.mainDiff(args, true, System.out, System.err), 0);
assertEquals(calcChecksum(outputFile), calcChecksum(normalDiffFile));
outputFile.delete();
}
}