/// <summary>
/// Create 2 large zip64 zip files - one from DNZ, one from WinZip. Each
/// test that updates a zip file should use both. There are slight
/// differences between a zip from DNZ and one from WinZip, specifically
/// regarding metadata. These differences should be inconsequential for
/// updates of zips, and that is what some of the zip64 tests seek to
/// verify.
/// </summary>
private string[] _CreateHugeZipfiles()
{
string[] zipsToCreate = { "Zip64Test-createdBy-WZ.zip",
"Zip64Test-createdBy-DNZ.zip" };
// lock in case more than one test calls this at a time.
lock (LOCK)
{
TestContext.WriteLine("CreateHugeZipFiles");
TestContext.WriteLine("Start - " + DateTime.Now.ToString("G"));
// STEP 1:
// look for existing directories, and re-use the large zip files
// there, if it exists, and if it is large enough.
string testDir = null;
var filesToAdd = new List<string>();
var oldDirs = Directory.GetDirectories(homeDir, "*.Zip64Tests");
string zipFileToCreate = null;
List<int> found = null;
// first pass to check if any dirs, have both files,
// second pass to check if any dirs have one file plus fodder files.
for (int pass=0; pass < 2; pass++)
{
foreach (var dir in oldDirs)
{
found = new List<int>();
for (int m=0; m < zipsToCreate.Length; m++)
{
zipFileToCreate = Path.Combine(dir, zipsToCreate[m]);
if (File.Exists(zipFileToCreate))
{
TestContext.WriteLine("File exists: {0}", zipFileToCreate);
FileInfo fi = new FileInfo(zipFileToCreate);
if (fi.Length < (long)System.UInt32.MaxValue)
{
TestContext.WriteLine("deleting file (too small): {0}", zipFileToCreate);
File.Delete(zipFileToCreate);
}
else found.Add(m);
}
}
int fc = found.Count();
switch (fc)
{
case 0:
case 1:
// check for fodder files
testDir = dir;
string fdir = Path.Combine(dir,"dir");
if (Directory.Exists(fdir))
{
var fodderFiles = Directory.GetFiles(fdir, "*.txt");
if (fodderFiles == null || fodderFiles.Length <= 6)
try { Directory.Delete(dir, true); } catch { }
}
else try { Directory.Delete(dir, true); } catch { }
break;
case 2:
// found both large zips, so use them.
zipsToCreate[0] = Path.Combine(dir, zipsToCreate[0]);
zipsToCreate[1] = Path.Combine(dir, zipsToCreate[1]);
TestContext.WriteLine("Using the existing zips in: {0}", dir);
return zipsToCreate;
}
if (pass == 1 && Directory.Exists(dir) && fc==1)
{
// on pass 2, take 1st dir with at least one zip
break;
}
}
}
// remember the current directory so we can restore later
string originalDir = Directory.GetCurrentDirectory();
// CurrentDir is the dir that holds the test temp directory (or directorIES)
Directory.SetCurrentDirectory(CurrentDir);
if (!Directory.Exists(testDir))
{
// create the dir if it does not exist
string pname = Path.GetFileName(TestUtilities.GenerateUniquePathname("Zip64Tests"));
testDir = Path.Combine(homeDir, pname);
Directory.CreateDirectory(testDir);
Directory.SetCurrentDirectory(testDir);
}
else
{
Directory.SetCurrentDirectory(testDir);
string fdir = Path.Combine(testDir,"dir");
filesToAdd.AddRange(Directory.GetFiles(fdir, "*.txt"));
}
TestContext.WriteLine("Creating new zip files...");
// create a huge ZIP64 archive with a true 64-bit offset.
_txrx = TestUtilities.StartProgressMonitor("Zip64_Setup",
"Zip64 Test Setup",
"Creating files");
//Directory.SetCurrentDirectory(testDir);
// create a directory with some files in it, to zip
string dirToZip = "dir";
Directory.CreateDirectory(dirToZip);
_txrx.Send("pb 0 step");
System.Threading.Thread.Sleep(120);
_txrx.Send("bars 3");
System.Threading.Thread.Sleep(220);
_txrx.Send("pb 0 max 4");
System.Threading.Thread.Sleep(220);
int numFilesToAdd = _rnd.Next(4) + 7;
_txrx.Send("pb 1 max " + numFilesToAdd);
// These params define the size range for the large, random text
// files that are created below. Creating files this size takes
// about 1 minute per file
_sizeBase = 0x16000000;
_sizeRandom = 0x20000000;
//_sizeBase = 0x160000;
//_sizeRandom = 0x200000;
if (filesToAdd.Count() == 0)
{
int n;
var buf = new byte[2048];
for (int i = 0; i < numFilesToAdd; i++)
{
System.Threading.Thread.Sleep(220);
_txrx.Send("title Zip64 Create Huge Zip files"); // in case it was missed
System.Threading.Thread.Sleep(220);
int fnameLength = _rnd.Next(25) + 6;
string filename = TestUtilities.GenerateRandomName(fnameLength) +
".txt";
_txrx.Send(String.Format("status create {0} ({1}/{2})", filename, i+1, numFilesToAdd));
int totalSize = _sizeBase + _rnd.Next(_sizeRandom);
System.Threading.Thread.Sleep(220);
_txrx.Send(String.Format("pb 2 max {0}", totalSize));
System.Threading.Thread.Sleep(220);
_txrx.Send("pb 2 value 0");
int writtenSoFar = 0;
int cycles = 0;
using (var input = new Ionic.Zip.Tests.Utilities.RandomTextInputStream(totalSize))
{
using (var output = File.Create(Path.Combine(dirToZip,filename)))
{
while ((n = input.Read(buf,0,buf.Length)) > 0)
{
output.Write(buf,0,n);
writtenSoFar+=n;
cycles++;
if (cycles % 640 == 0)
{
_txrx.Send(String.Format("pb 2 value {0}", writtenSoFar));
}
}
}
}
filesToAdd.Add(filename);
_txrx.Send("pb 1 step");
}
}
_txrx.Send("pb 0 step");
System.Threading.Thread.Sleep(220);
_txrx.Send("pb 1 value 0");
// Add links to a few very large files into the same directory. We
// do this because creating such large files from nothing would take
// a very very long time.
if (CreateLinksToLargeFiles(dirToZip))
return null;
Directory.SetCurrentDirectory(testDir); // again
if (found == null || !found.Contains(0))
{
// create a zip file, using WinZip
// This will take 50 minutes or so, no progress updates possible.
System.Threading.Thread.Sleep(220);
_txrx.Send("title Zip64 Create Huge Zip files"); // in case it was missed
System.Threading.Thread.Sleep(220);
_txrx.Send("pb 2 value 0");
zipFileToCreate = zipsToCreate[0];
zipsToCreate[0] = Path.Combine(testDir, zipsToCreate[0]);
// wzzip.exe will create a zip64 file automatically, as necessary.
// There is no explicit switch required.
// switches:
// -a add
// -r recurse
// -p store folder names
// -yx store extended timestamps
var sb1 = new System.Text.StringBuilder();
sb1.Append("-a -p -r -yx \"")
.Append(zipFileToCreate)
.Append("\" \"")
.Append(dirToZip)
.Append("\" ");
string args = sb1.ToString();
System.Threading.Thread.Sleep(220);
_txrx.Send("status wzzip.exe " + args);
TestContext.WriteLine("Exec: wzzip {0}", args);
string wzzipOut = this.Exec(wzzip, args);
TestContext.WriteLine("Done with wzzip.exe");
_txrx.Send("status wzzip.exe: Done");
}
if (found == null || !found.Contains(1))
{
// Create a zip file using DotNetZip
// This will take 50 minutes or so.
// pb1 and pb2 will be set in the {Add,Save}Progress handlers
_txrx.Send("pb 0 step");
System.Threading.Thread.Sleep(120);
_txrx.Send("status Saving the zip...");
System.Threading.Thread.Sleep(120);
_txrx.Send(String.Format("pb 1 max {0}", numFilesToAdd + Directory.GetFiles(dirToZip).Length));
_testTitle = "Zip64 Create Huge Zip files"; // used in Zip64_SaveProgress
_pb1Set = false;
zipFileToCreate = Path.Combine(testDir, zipsToCreate[1]);
zipsToCreate[1] = zipFileToCreate;
using (ZipFile zip = new ZipFile())
{
zip.SaveProgress += Zip64SaveProgress;
zip.AddProgress += Zip64AddProgress;
zip.UpdateDirectory(dirToZip, "");
foreach (var e in zip)
{
if (e.FileName.EndsWith(".pst") ||
e.FileName.EndsWith(".ost") ||
e.FileName.EndsWith(".zip"))
e.CompressionMethod = CompressionMethod.None;
}
zip.UseZip64WhenSaving = Zip64Option.Always;
// use large buffer to speed up save for large files:
zip.BufferSize = 1024 * 756;
zip.CodecBufferSize = 1024 * 128;
zip.Save(zipFileToCreate);
}
}
_txrx.Send("pb 0 step");
System.Threading.Thread.Sleep(120);
// Delete the fodder dir only if we have both zips.
// This is helpful when modifying or editing this method.
// With repeated runs you don't have to re-create all the data
// each time.
if (File.Exists(zipsToCreate[0]) && File.Exists(zipsToCreate[1]))
Directory.Delete(dirToZip, true);
_txrx.Send("pb 0 step");
System.Threading.Thread.Sleep(120);
_txrx.Send("stop");
// restore the cwd:
Directory.SetCurrentDirectory(originalDir);
TestContext.WriteLine("All done - " +
DateTime.Now.ToString("G"));
return zipsToCreate;
}
}