551 lines
19 KiB
C#
551 lines
19 KiB
C#
// IonicTestClass.cs
|
|
// ------------------------------------------------------------------
|
|
//
|
|
// Copyright (c) 2009 Dino Chiesa.
|
|
// All rights reserved.
|
|
//
|
|
// This code module is part of DotNetZip, a zipfile class library.
|
|
//
|
|
// ------------------------------------------------------------------
|
|
//
|
|
// This code is licensed under the Microsoft Public License.
|
|
// See the file License.txt for the license details.
|
|
// More info on: http://dotnetzip.codeplex.com
|
|
//
|
|
// ------------------------------------------------------------------
|
|
//
|
|
// last saved (in emacs):
|
|
// Time-stamp: <2011-July-26 10:04:54>
|
|
//
|
|
// ------------------------------------------------------------------
|
|
//
|
|
// This module defines the base class for DotNetZip test classes.
|
|
//
|
|
// ------------------------------------------------------------------
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Text;
|
|
using System.Text.RegularExpressions;
|
|
using System.Net;
|
|
using System.Linq;
|
|
using System.IO;
|
|
using Ionic.Zip;
|
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
|
|
|
namespace Ionic.Zip.Tests.Utilities
|
|
{
|
|
[TestClass]
|
|
public class IonicTestClass
|
|
{
|
|
protected System.Random _rnd;
|
|
protected System.Collections.Generic.List<string> _FilesToRemove;
|
|
protected static string CurrentDir = null;
|
|
protected string TopLevelDir = null;
|
|
private string _wzunzip = null;
|
|
private string _wzzip = null;
|
|
private string _sevenzip = null;
|
|
private string _zipit = null;
|
|
private string _infozipzip = null;
|
|
private string _infozipunzip = null;
|
|
private bool? _ZipitIsPresent;
|
|
private bool? _WinZipIsPresent;
|
|
private bool? _SevenZipIsPresent;
|
|
private bool? _InfoZipIsPresent;
|
|
|
|
protected Ionic.CopyData.Transceiver _txrx;
|
|
|
|
|
|
public IonicTestClass()
|
|
{
|
|
_rnd = new System.Random();
|
|
_FilesToRemove = new System.Collections.Generic.List<string>();
|
|
}
|
|
|
|
#region Context
|
|
private TestContext testContextInstance;
|
|
|
|
/// <summary>
|
|
///Gets or sets the test context which provides
|
|
///information about and functionality for the current test run.
|
|
///</summary>
|
|
public TestContext TestContext
|
|
{
|
|
get
|
|
{
|
|
return testContextInstance;
|
|
}
|
|
set
|
|
{
|
|
testContextInstance = value;
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
#region Test Init and Cleanup
|
|
//
|
|
// You can use the following additional attributes as you write your tests:
|
|
//
|
|
// Use ClassInitialize to run code before running the first test in the class
|
|
[ClassInitialize]
|
|
public static void BaseClassInitialize(TestContext testContext)
|
|
{
|
|
CurrentDir = Directory.GetCurrentDirectory();
|
|
Assert.AreNotEqual<string>(Path.GetFileName(CurrentDir), "Temp", "at startup");
|
|
}
|
|
|
|
//
|
|
// Use ClassCleanup to run code after all tests in a class have run
|
|
// [ClassCleanup()]
|
|
// public static void MyClassCleanup() { }
|
|
//
|
|
|
|
|
|
// Use TestInitialize to run code before running each test
|
|
[TestInitialize()]
|
|
public void MyTestInitialize()
|
|
{
|
|
if (CurrentDir == null) CurrentDir = Directory.GetCurrentDirectory();
|
|
TestUtilities.Initialize(out TopLevelDir);
|
|
_FilesToRemove.Add(TopLevelDir);
|
|
Directory.SetCurrentDirectory(TopLevelDir);
|
|
}
|
|
|
|
// Use TestCleanup to run code after each test has run
|
|
[TestCleanup()]
|
|
public void MyTestCleanup()
|
|
{
|
|
// The CWD of the monitoring process is the CurrentDir,
|
|
// therefore this test must shut down the monitoring process
|
|
// FIRST, to allow the deletion of the directory.
|
|
if (_txrx!=null)
|
|
{
|
|
try
|
|
{
|
|
_txrx.Send("stop");
|
|
_txrx = null;
|
|
}
|
|
catch { }
|
|
}
|
|
|
|
TestUtilities.Cleanup(CurrentDir, _FilesToRemove);
|
|
}
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
internal string Exec(string program, string args)
|
|
{
|
|
return Exec(program, args, true);
|
|
}
|
|
|
|
internal string Exec(string program, string args, bool waitForExit)
|
|
{
|
|
return Exec(program, args, waitForExit, true);
|
|
}
|
|
|
|
internal string Exec(string program, string args, bool waitForExit, bool emitOutput)
|
|
{
|
|
if (program == null)
|
|
throw new ArgumentException("program");
|
|
|
|
if (args == null)
|
|
throw new ArgumentException("args");
|
|
|
|
// Microsoft.VisualStudio.TestTools.UnitTesting
|
|
this.TestContext.WriteLine("running command: {0} {1}", program, args);
|
|
|
|
string output;
|
|
int rc = TestUtilities.Exec_NoContext(program, args, waitForExit, out output);
|
|
|
|
if (rc != 0)
|
|
throw new Exception(String.Format("Non-zero RC {0}: {1}", program, output));
|
|
|
|
if (emitOutput)
|
|
this.TestContext.WriteLine("output: {0}", output);
|
|
else
|
|
this.TestContext.WriteLine("A-OK. (output suppressed)");
|
|
|
|
return output;
|
|
}
|
|
|
|
|
|
public class AsyncReadState
|
|
{
|
|
public System.IO.Stream s;
|
|
public byte[] buf= new byte[1024];
|
|
}
|
|
|
|
|
|
internal int ExecRedirectStdOut(string program, string args, string outFile)
|
|
{
|
|
if (program == null)
|
|
throw new ArgumentException("program");
|
|
|
|
if (args == null)
|
|
throw new ArgumentException("args");
|
|
|
|
this.TestContext.WriteLine("running command: {0} {1}", program, args);
|
|
|
|
Stream fs = File.Create(outFile);
|
|
try
|
|
{
|
|
System.Diagnostics.Process p = new System.Diagnostics.Process
|
|
{
|
|
StartInfo =
|
|
{
|
|
FileName = program,
|
|
CreateNoWindow = true,
|
|
Arguments = args,
|
|
WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden,
|
|
UseShellExecute = false,
|
|
RedirectStandardOutput = true,
|
|
RedirectStandardError = true,
|
|
}
|
|
};
|
|
|
|
p.Start();
|
|
|
|
var stdout = p.StandardOutput.BaseStream;
|
|
var rs = new AsyncReadState { s = stdout };
|
|
Action<System.IAsyncResult> readAsync1 = null;
|
|
var readAsync = new Action<System.IAsyncResult>( (ar) => {
|
|
AsyncReadState state = (AsyncReadState) ar.AsyncState;
|
|
int n = state.s.EndRead(ar);
|
|
if (n > 0)
|
|
{
|
|
fs.Write(state.buf, 0, n);
|
|
state.s.BeginRead(state.buf,
|
|
0,
|
|
state.buf.Length,
|
|
new System.AsyncCallback(readAsync1),
|
|
state);
|
|
}
|
|
});
|
|
readAsync1 = readAsync; // ??
|
|
|
|
// kickoff
|
|
stdout.BeginRead(rs.buf,
|
|
0,
|
|
rs.buf.Length,
|
|
new System.AsyncCallback(readAsync),
|
|
rs);
|
|
|
|
p.WaitForExit();
|
|
|
|
this.TestContext.WriteLine("Process exited, rc={0}", p.ExitCode);
|
|
|
|
return p.ExitCode;
|
|
}
|
|
finally
|
|
{
|
|
if (fs != null)
|
|
fs.Dispose();
|
|
}
|
|
}
|
|
|
|
|
|
protected string sevenZip
|
|
{
|
|
get { return SevenZipIsPresent ? _sevenzip : null; }
|
|
}
|
|
|
|
protected string zipit
|
|
{
|
|
get { return ZipitIsPresent ? _zipit : null; }
|
|
}
|
|
|
|
protected string infoZip
|
|
{
|
|
get { return InfoZipIsPresent ? _infozipzip : null; }
|
|
}
|
|
|
|
protected string infoZipUnzip
|
|
{
|
|
get { return InfoZipIsPresent ? _infozipunzip : null; }
|
|
}
|
|
|
|
protected string wzzip
|
|
{
|
|
get { return WinZipIsPresent ? _wzzip : null; }
|
|
}
|
|
|
|
protected string wzunzip
|
|
{
|
|
get { return WinZipIsPresent ? _wzunzip : null; }
|
|
}
|
|
|
|
protected bool ZipitIsPresent
|
|
{
|
|
get
|
|
{
|
|
if (_ZipitIsPresent == null)
|
|
{
|
|
string sourceDir = CurrentDir;
|
|
for (int i = 0; i < 3; i++)
|
|
sourceDir = Path.GetDirectoryName(sourceDir);
|
|
|
|
_zipit =
|
|
Path.Combine(sourceDir, "Tools\\Zipit\\bin\\Debug\\Zipit.exe");
|
|
|
|
_ZipitIsPresent = new Nullable<bool>(File.Exists(_zipit));
|
|
}
|
|
return _ZipitIsPresent.Value;
|
|
}
|
|
}
|
|
|
|
protected bool WinZipIsPresent
|
|
{
|
|
get
|
|
{
|
|
if (_WinZipIsPresent == null)
|
|
{
|
|
string progfiles = null;
|
|
if (_wzunzip == null || _wzzip == null)
|
|
{
|
|
progfiles = System.Environment.GetEnvironmentVariable("ProgramFiles(x86)");
|
|
_wzunzip = Path.Combine(progfiles, "winzip\\wzunzip.exe");
|
|
_wzzip = Path.Combine(progfiles, "winzip\\wzzip.exe");
|
|
}
|
|
_WinZipIsPresent = new Nullable<bool>(File.Exists(_wzunzip) && File.Exists(_wzzip));
|
|
}
|
|
return _WinZipIsPresent.Value;
|
|
}
|
|
}
|
|
|
|
protected bool SevenZipIsPresent
|
|
{
|
|
get
|
|
{
|
|
if (_SevenZipIsPresent == null)
|
|
{
|
|
string progfiles = null;
|
|
if (_sevenzip == null)
|
|
{
|
|
progfiles = System.Environment.GetEnvironmentVariable("ProgramFiles");
|
|
_sevenzip = Path.Combine(progfiles, "7-zip\\7z.exe");
|
|
}
|
|
_SevenZipIsPresent = new Nullable<bool>(File.Exists(_sevenzip));
|
|
}
|
|
return _SevenZipIsPresent.Value;
|
|
}
|
|
}
|
|
|
|
|
|
protected bool InfoZipIsPresent
|
|
{
|
|
get
|
|
{
|
|
if (_InfoZipIsPresent == null)
|
|
{
|
|
string progfiles = null;
|
|
if (_infozipzip == null)
|
|
{
|
|
progfiles = System.Environment.GetEnvironmentVariable("ProgramFiles(x86)");
|
|
_infozipzip = Path.Combine(progfiles, "infozip.org\\zip.exe");
|
|
_infozipunzip = Path.Combine(progfiles, "infozip.org\\unzip.exe");
|
|
}
|
|
_InfoZipIsPresent = new Nullable<bool>(File.Exists(_infozipzip) &&
|
|
File.Exists(_infozipunzip));
|
|
}
|
|
return _InfoZipIsPresent.Value;
|
|
}
|
|
}
|
|
|
|
internal string BasicVerifyZip(string zipfile)
|
|
{
|
|
return BasicVerifyZip(zipfile, null);
|
|
}
|
|
|
|
|
|
internal string BasicVerifyZip(string zipfile, string password)
|
|
{
|
|
return BasicVerifyZip(zipfile, password, true);
|
|
}
|
|
|
|
internal string BasicVerifyZip(string zipfile, string password, bool emitOutput)
|
|
{
|
|
return BasicVerifyZip(zipfile, password, emitOutput, null);
|
|
}
|
|
|
|
|
|
internal string BasicVerifyZip(string zipfile, string password, bool emitOutput,
|
|
EventHandler<ExtractProgressEventArgs> extractProgress)
|
|
{
|
|
// basic verification of the zip file - can it be extracted?
|
|
// The extraction tool will verify checksums and passwords, as appropriate
|
|
#if NOT
|
|
if (WinZipIsPresent)
|
|
{
|
|
TestContext.WriteLine("Verifying zip file {0} with WinZip", zipfile);
|
|
string args = (password == null)
|
|
? String.Format("-t {0}", zipfile)
|
|
: String.Format("-s{0} -t {1}", password, zipfile);
|
|
|
|
string wzunzipOut = this.Exec(wzunzip, args, true, emitOutput);
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
TestContext.WriteLine("Verifying zip file {0} with DotNetZip", zipfile);
|
|
ReadOptions options = new ReadOptions();
|
|
if (emitOutput)
|
|
options.StatusMessageWriter = new StringWriter();
|
|
|
|
string extractDir = "verify";
|
|
int c = 0;
|
|
while (Directory.Exists(extractDir + c)) c++;
|
|
extractDir += c;
|
|
|
|
using (ZipFile zip2 = ZipFile.Read(zipfile, options))
|
|
{
|
|
zip2.Password = password;
|
|
if (extractProgress != null)
|
|
zip2.ExtractProgress += extractProgress;
|
|
zip2.ExtractAll(extractDir);
|
|
}
|
|
// emit output, as desired
|
|
if (emitOutput)
|
|
TestContext.WriteLine("{0}",options.StatusMessageWriter.ToString());
|
|
|
|
return extractDir;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
internal static void CreateFilesAndChecksums(string subdir,
|
|
out string[] filesToZip,
|
|
out Dictionary<string, byte[]> checksums)
|
|
{
|
|
CreateFilesAndChecksums(subdir, 0, 0, out filesToZip, out checksums);
|
|
}
|
|
|
|
|
|
internal static void CreateFilesAndChecksums(string subdir,
|
|
int numFiles,
|
|
int baseSize,
|
|
out string[] filesToZip,
|
|
out Dictionary<string, byte[]> checksums)
|
|
{
|
|
// create a bunch of files
|
|
filesToZip = TestUtilities.GenerateFilesFlat(subdir, numFiles, baseSize);
|
|
DateTime atMidnight = new DateTime(DateTime.Now.Year,
|
|
DateTime.Now.Month,
|
|
DateTime.Now.Day);
|
|
DateTime fortyFiveDaysAgo = atMidnight - new TimeSpan(45, 0, 0, 0);
|
|
|
|
// get checksums for each one
|
|
checksums = new Dictionary<string, byte[]>();
|
|
|
|
var rnd = new System.Random();
|
|
foreach (var f in filesToZip)
|
|
{
|
|
if (rnd.Next(3) == 0)
|
|
File.SetLastWriteTime(f, fortyFiveDaysAgo);
|
|
else
|
|
File.SetLastWriteTime(f, atMidnight);
|
|
|
|
var key = Path.GetFileName(f);
|
|
var chk = TestUtilities.ComputeChecksum(f);
|
|
checksums.Add(key, chk);
|
|
}
|
|
}
|
|
|
|
protected static void CreateLargeFilesWithChecksums
|
|
(string subdir,
|
|
int numFiles,
|
|
Action<int,int,Int64> update,
|
|
out string[] filesToZip,
|
|
out Dictionary<string,byte[]> checksums)
|
|
{
|
|
var rnd = new System.Random();
|
|
// create a bunch of files
|
|
filesToZip = TestUtilities.GenerateFilesFlat(subdir,
|
|
numFiles,
|
|
256 * 1024,
|
|
3 * 1024 * 1024,
|
|
update);
|
|
|
|
var dates = new DateTime[rnd.Next(6) + 7];
|
|
// midnight
|
|
dates[0] = new DateTime(DateTime.Now.Year,
|
|
DateTime.Now.Month,
|
|
DateTime.Now.Day);
|
|
|
|
for (int i=1; i < dates.Length; i++)
|
|
{
|
|
dates[i] = DateTime.Now -
|
|
new TimeSpan(rnd.Next(300),
|
|
rnd.Next(23),
|
|
rnd.Next(60),
|
|
rnd.Next(60));
|
|
}
|
|
|
|
// get checksums for each one
|
|
checksums = new Dictionary<string, byte[]>();
|
|
|
|
foreach (var f in filesToZip)
|
|
{
|
|
File.SetLastWriteTime(f, dates[rnd.Next(dates.Length)]);
|
|
var key = Path.GetFileName(f);
|
|
var chk = TestUtilities.ComputeChecksum(f);
|
|
checksums.Add(key, chk);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
protected void VerifyChecksums(string extractDir,
|
|
System.Collections.Generic.IEnumerable<String> filesToCheck,
|
|
Dictionary<string, byte[]> checksums)
|
|
{
|
|
TestContext.WriteLine("");
|
|
TestContext.WriteLine("Verify checksums...");
|
|
int count = 0;
|
|
foreach (var fqPath in filesToCheck)
|
|
{
|
|
var f = Path.GetFileName(fqPath);
|
|
var extractedFile = Path.Combine(extractDir, f);
|
|
Assert.IsTrue(File.Exists(extractedFile), "File does not exist ({0})", extractedFile);
|
|
var chk = TestUtilities.ComputeChecksum(extractedFile);
|
|
Assert.AreEqual<String>(TestUtilities.CheckSumToString(checksums[f]),
|
|
TestUtilities.CheckSumToString(chk),
|
|
String.Format("Checksums for file {0} do not match.", f));
|
|
count++;
|
|
}
|
|
|
|
if (checksums.Count < count)
|
|
{
|
|
TestContext.WriteLine("There are {0} more extracted files than checksums", count - checksums.Count);
|
|
foreach (var file in filesToCheck)
|
|
{
|
|
if (!checksums.ContainsKey(file))
|
|
TestContext.WriteLine("Missing: {0}", Path.GetFileName(file));
|
|
}
|
|
}
|
|
|
|
if (checksums.Count > count)
|
|
{
|
|
TestContext.WriteLine("There are {0} more checksums than extracted files", checksums.Count - count);
|
|
foreach (var file in checksums.Keys)
|
|
{
|
|
var selection = from f in filesToCheck where Path.GetFileName(f).Equals(file) select f;
|
|
|
|
if (selection.Count() == 0)
|
|
TestContext.WriteLine("Missing: {0}", Path.GetFileName(file));
|
|
}
|
|
}
|
|
|
|
|
|
Assert.AreEqual<Int32>(checksums.Count, count, "There's a mismatch between the checksums and the filesToCheck.");
|
|
}
|
|
}
|
|
|
|
|
|
}
|