I have now fixed the issue, and tested it on the file provided. It seems to compress better now, although the file contains sporadic changes, even if only a single line was added. The restore also works as expected, and the update works on my unittest. Could you please try the updated version and see if it works as expected for you as well? With regards to the "no else statement" (comment 7), I think that you discovered another bug, which I have also fixed. The else statement is there to ensure that the buffer is completely filled, so long chains of unmatched data gets written with as few commands as possible. So, on the first entry, the copy command is flushed and the force_buffer_refill is set, causing the buffer to refill. The bug was that IF the buffer was already full, the stream would read 0 bytes, and return a count of 0. This was then interpreted as if the stream was empty (it returns zero when empty). I have now fixed that with a check for this special case. I have also included an update to the ChecksumFileReader that splits the previous m_weakTable into two separate arrays, as that gives a faster lookup, than using a custom comparer. I also added support for very large files (files larger than blocksize * int.MaxValue, appx. 4TB). git-svn-id: https://duplicati.googlecode.com/svn/trunk@548 59da171f-624f-0410-aa54-27559c288bec
126 lines
5.7 KiB
C#
126 lines
5.7 KiB
C#
|
|
#if DEBUG
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Text;
|
|
|
|
namespace Duplicati.Library.SharpRSync
|
|
{
|
|
/// <summary>
|
|
/// Performs unittests by comparing the output of SharpRsync with the output of rdiff
|
|
/// </summary>
|
|
public class UnitTest
|
|
{
|
|
/// <summary>
|
|
/// Runs the test
|
|
/// </summary>
|
|
/// <param name="items">A list of items to test, Key is the current version, Value is the updated version</param>
|
|
/// <param name="useRdiff">True if rdiff should also be tested, false otherwise (requires that "rdiff" can be executed)</param>
|
|
public static void DoTest(List<KeyValuePair<string, string>> items, bool useRdiff)
|
|
{
|
|
string basedir = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
|
|
string testfolder = System.IO.Path.Combine(basedir, "UNITTEST");
|
|
|
|
try
|
|
{
|
|
foreach (KeyValuePair<string, string> item in items)
|
|
{
|
|
System.IO.Directory.CreateDirectory(testfolder);
|
|
|
|
//Step 1 generate signatures
|
|
string sharpSigfile = System.IO.Path.Combine(testfolder, "sharp.signature");
|
|
string rdiffSigfile = System.IO.Path.Combine(testfolder, "rdiff.signature");
|
|
|
|
string sharpDeltafile = System.IO.Path.Combine(testfolder, "sharp.delta");
|
|
string rdiffDeltafile = System.IO.Path.Combine(testfolder, "rdiff.delta");
|
|
|
|
string sharpPatchedfile = System.IO.Path.Combine(testfolder, "sharp.patched");
|
|
string rdiffPatchedfile = System.IO.Path.Combine(testfolder, "rdiff.patched");
|
|
|
|
DateTime start = DateTime.Now;
|
|
SharpRSync.Interface.GenerateSignature(item.Key, sharpSigfile);
|
|
Console.WriteLine("Signature generation for {0} with SharpRSync took {1}", item.Key, DateTime.Now - start);
|
|
|
|
if (useRdiff)
|
|
{
|
|
start = DateTime.Now;
|
|
System.Diagnostics.Process.Start("rdiff", string.Format("signature \"{0}\" \"{1}\"", item.Key, rdiffSigfile)).WaitForExit();
|
|
Console.WriteLine("Signature generation for {0} with rdiff took {1}", item.Key, DateTime.Now - start);
|
|
|
|
CompareFiles(sharpSigfile, rdiffSigfile, sharpSigfile);
|
|
}
|
|
|
|
|
|
start = DateTime.Now;
|
|
SharpRSync.Interface.GenerateDelta(sharpSigfile, item.Value, sharpDeltafile);
|
|
Console.WriteLine("Delta generation for {0} -> {1} with SharpRSync took {2}", item.Key, item.Value, DateTime.Now - start);
|
|
|
|
if (useRdiff)
|
|
{
|
|
start = DateTime.Now;
|
|
System.Diagnostics.Process.Start("rdiff", string.Format("delta \"{0}\" \"{1}\" \"{2}\"", rdiffSigfile, item.Value, rdiffDeltafile)).WaitForExit();
|
|
Console.WriteLine("Delta generation for {0} -> {1} with rdiff took {2}", item.Key, item.Value, DateTime.Now - start);
|
|
}
|
|
|
|
start = DateTime.Now;
|
|
SharpRSync.Interface.PatchFile(item.Key, sharpDeltafile, sharpPatchedfile);
|
|
Console.WriteLine("Patch generation for {0} with SharpRSync took {1}", item.Key, DateTime.Now - start);
|
|
|
|
if (useRdiff)
|
|
{
|
|
start = DateTime.Now;
|
|
System.Diagnostics.Process.Start("rdiff", string.Format("patch \"{0}\" \"{1}\" \"{2}\"", item.Key, rdiffDeltafile, rdiffPatchedfile)).WaitForExit();
|
|
Console.WriteLine("Patch generation for {0} with rdiff took {1}", item.Key, DateTime.Now - start);
|
|
CompareFiles(sharpPatchedfile, rdiffPatchedfile, sharpDeltafile);
|
|
}
|
|
|
|
CompareFiles(sharpPatchedfile, item.Value, sharpPatchedfile);
|
|
|
|
System.IO.Directory.Delete(testfolder, true);
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
try
|
|
{
|
|
if (System.IO.Directory.Exists(testfolder))
|
|
System.IO.Directory.Delete(testfolder, true);
|
|
}
|
|
catch { }
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Compares two files by reading all bytes, and comparing one by one
|
|
/// </summary>
|
|
/// <param name="f1">One file</param>
|
|
/// <param name="f2">Another file</param>
|
|
/// <param name="display">File display name</param>
|
|
/// <returns>True if they are equal, false otherwise</returns>
|
|
private static bool CompareFiles(string f1, string f2, string display)
|
|
{
|
|
using (System.IO.FileStream fs1 = System.IO.File.OpenRead(f1))
|
|
using (System.IO.FileStream fs2 = System.IO.File.OpenRead(f2))
|
|
if (fs1.Length != fs2.Length)
|
|
{
|
|
Console.WriteLine("Lengths differ: " + display + ", " + fs1.Length.ToString() + " vs. " + fs2.Length.ToString());
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
long len = fs1.Length;
|
|
for (long l = 0; l < len; l++)
|
|
if (fs1.ReadByte() != fs2.ReadByte())
|
|
{
|
|
Console.WriteLine("Mismatch in byte " + l.ToString() + " in file " + display);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif
|