/// <summary> /// Executes the specified command. Assume working directory is TestFiles\MsiInput\ dir. /// </summary> /// <param name="commandLineArguments">The command line arguments (everything after the exe name).</param> /// <param name="testName">The name of hte test (used to formulate the expectedEntries output dir).</param> /// <param name="actualEntriesOutputDir">The output directory where the actual extraction is expected to occur.</param> private void TestExtraction(string commandLineArguments, string testName, string actualEntriesOutputDir, bool useInProcessForDebugging) { string consoleOutput; var actualOutDir = new DirectoryInfo(actualEntriesOutputDir); if (actualOutDir.Exists) { DeleteDirectoryRecursive(actualOutDir); } int exitCode; if (useInProcessForDebugging) { exitCode = base.RunCommandLineInProccess(commandLineArguments); } else { exitCode = base.RunCommandLine(commandLineArguments, out consoleOutput); } var actualEntries = FileEntryGraph.GetActualEntries(actualEntriesOutputDir, "Actual Entries"); var actualEntriesFile = GetActualOutputFile(testName); actualEntries.Save(actualEntriesFile); Console.WriteLine("Actual entries saved to " + actualEntriesFile.FullName); var expectedEntries = GetExpectedEntriesForMsi(testName); AssertAreEqual(expectedEntries, actualEntries); }
/// <summary> /// Extracts some or all of the files from the specified MSI and returns a <see cref="FileEntryGraph"/> representing the files that were extracted. /// </summary> /// <param name="msiFileName">The msi file to extract or null to extract all files.</param> /// <param name="fileNamesToExtractOrNull">The files to extract from the MSI or null to extract all files.</param> /// <param name="outputDir">A relative directory to extract output to or an empty string to use the default output directory.</param> /// <param name="skipReturningFileEntryGraph">True to return the <see cref="FileEntryGraph"/>. Otherwise null will be returned.</param> protected FileEntryGraph ExtractFilesFromMsi(string msiFileName, string[] fileNamesToExtractOrNull, Path outputDir, bool returnFileEntryGraph) { outputDir = GetTestOutputDir(outputDir, msiFileName); if (FileSystem.Exists(outputDir)) { FileSystem.RemoveDirectory(outputDir, true); } Debug.Assert(!FileSystem.Exists(outputDir), "Directory still exists!"); FileSystem.CreateDirectory(outputDir); //ExtractViaCommandLine(outputDir, msiFileName); ExtractInProcess(msiFileName, outputDir.PathString, fileNamesToExtractOrNull); if (returnFileEntryGraph) { // build actual file entries extracted var actualEntries = FileEntryGraph.GetActualEntries(outputDir.PathString, msiFileName); // dump to actual dir (for debugging and updating tests) actualEntries.Save(GetActualOutputFile(msiFileName)); return(actualEntries); } else { return(null); } }
/// <summary> /// Executes the specified command. Assume working directory is TestFiles\MsiInput\ dir. /// </summary> /// <param name="commandLineArguments">The command line arguments (everything after the exe name).</param> /// <param name="testName">The name of hte test (used to formulate the expectedEntries output dir).</param> /// <param name="actualEntriesOutputDir">The output directory where the actual extraction is expected to occur.</param> private void TestExtraction(string commandLineArguments, string testName, string actualEntriesOutputDir, bool useInProcessForDebugging) { string consoleOutput; var actualOutDir = new LessIO.Path(actualEntriesOutputDir).FullPath; if (actualOutDir.Exists) { FileSystem.RemoveDirectory(actualOutDir, true); } int exitCode; if (useInProcessForDebugging) { exitCode = base.RunCommandLineInProccess(commandLineArguments); } else { exitCode = base.RunCommandLine(commandLineArguments, out consoleOutput); } Assert.Equal(0, exitCode); var actualEntries = FileEntryGraph.GetActualEntries(actualOutDir.FullPathString, "Actual Entries"); var actualEntriesFile = GetActualOutputFile(testName); actualEntries.Save(actualEntriesFile); //Console.WriteLine("Actual entries saved to " + actualEntriesFile.FullName); var expectedEntries = GetExpectedEntriesForMsi(testName); AssertAreEqual(expectedEntries, actualEntries); }
/// <summary> /// Loads a <see cref="FileEntryGraph"/> from the specified file. /// </summary> /// <param name="file">The file to load a new <see cref="FileEntryGraph"/> from.</param> /// <param name="forFileName">The initial value for the returned objects <see cref="FileEntryGraph.ForFileName"/></param> /// <returns>The newly loaded <see cref="FileEntryGraph"/>.</returns> public static FileEntryGraph Load(FileInfo file, string forFileName) { var graph = new FileEntryGraph(forFileName); using (var f = file.OpenText()) { f.ReadLine();//headings while (!f.EndOfStream) { var line = f.ReadLine().Split(','); if (line.Length != 5) throw new IOException("Expected 5 fields!"); /* FIX for github issue #23: * The problem was that old ExpectedOutput files were all prefixed with C:\projects\lessmsi\src\Lessmsi.Tests\bin\Debug\<msiFileNameWithoutExtension> (something like C:\projects\lessmsi\src\Lessmsi.Tests\bin\Debug\NUnit-2.5.2.9222\SourceDir\PFiles\NUnit 2.5.2\fit-license.txt) * We need to remove Since we don't reasonably know what the original msi filename was, we do know it was the subdirectory of C:\projects\lessmsi\src\Lessmsi.Tests\bin\Debug\. So we should remove C:\projects\lessmsi\src\Lessmsi.Tests\bin\Debug\ and the next subdirectory from the path. * HACK: A better fix would undoubtedly be to cleanup those old file swith code like this and remove this hack from this code forever! */ var path = line[0]; const string oldRootPath = @"C:\projects\lessmsi\src\Lessmsi.Tests\bin\Debug\"; if (path.StartsWith(oldRootPath, StringComparison.InvariantCultureIgnoreCase)) { //this is an old file that would trigger github issue #23, so we'll fix it here... // first remove the old root path: path = path.Substring(oldRootPath.Length); // now romove the msi filename (which we don't know, but we know it is the next subdirectory of the old root): var lengthOfSubDirectoryName = path.IndexOf('\\', 0); path = path.Substring(lengthOfSubDirectoryName); } graph.Add(new FileEntry(path, Int64.Parse(line[1]), DeserializeDate(line[2]), DeserializeDate(line[3]), DeserializeAttributes(line[4])) ); } } return graph; }
protected static void AssertAreEqual(FileEntryGraph expected, FileEntryGraph actual) { string msg; if (!FileEntryGraph.CompareEntries(expected, actual, out msg)) { throw new Exception("FileEntryGraph entries are not the equal"); } }
protected static void AssertAreEqual(FileEntryGraph expected, FileEntryGraph actual) { string msg; if (!FileEntryGraph.CompareEntries(expected, actual, out msg)) { Assert.Fail(msg); } }
/// <summary> /// Loads a <see cref="FileEntryGraph"/> from the specified file. /// </summary> /// <param name="file">The file to load a new <see cref="FileEntryGraph"/> from.</param> /// <param name="forFileName">The initial value for the returned objects <see cref="FileEntryGraph.ForFileName"/></param> /// <returns>The newly loaded <see cref="FileEntryGraph"/>.</returns> public static FileEntryGraph Load(FileInfo file, string forFileName) { var graph = new FileEntryGraph(forFileName); using (var f = file.OpenText()) { f.ReadLine();//headings while (!f.EndOfStream) { var line = f.ReadLine().Split(','); if (line.Length != 2) throw new IOException("Expected two fields!"); graph.Add(new FileEntry(line[0], Int64.Parse(line[1]))); } } return graph; }
/// <summary> /// Loads a <see cref="FileEntryGraph"/> from the specified file. /// </summary> /// <param name="file">The file to load a new <see cref="FileEntryGraph"/> from.</param> /// <param name="forFileName">The initial value for the returned objects <see cref="FileEntryGraph.ForFileName"/></param> /// <returns>The newly loaded <see cref="FileEntryGraph"/>.</returns> public static FileEntryGraph Load(FileInfo file, string forFileName) { var graph = new FileEntryGraph(forFileName); using (var f = file.OpenText()) { f.ReadLine();//headings while (!f.EndOfStream) { var line = f.ReadLine().Split(','); if (line.Length != 5) { throw new IOException("Expected 5 fields!"); } graph.Add(new FileEntry(line[0], Int64.Parse(line[1]), DeserializeDate(line[2]), DeserializeDate(line[3]), DeserializeAttributes(line[4]))); } } return(graph); }
public static bool CompareEntries(FileEntryGraph a, FileEntryGraph b, out string errorMessage) { if (a.Entries.Count != b.Entries.Count) { errorMessage = string.Format("Entries for '{0}' and '{1}' have a different number of file entries ({2}, {3} respectively).", a.ForFileName, b.ForFileName, a.Entries.Count, b.Entries.Count); return false; } for (int i = 0; i < Math.Max(a.Entries.Count, b.Entries.Count); i++) { if (!a.Entries[i].Equals(b.Entries[i])) { errorMessage = string.Format("'{0}'!='{1}' at index '{2}'.", a.Entries[i].Path, b.Entries[i].Path, i); return false; } } errorMessage = ""; return true; }
public static bool CompareEntries(FileEntryGraph a, FileEntryGraph b, out string errorMessage) { if (a.Entries.Count != b.Entries.Count) { errorMessage = string.Format("Entries for '{0}' and '{1}' have a different number of file entries ({2}, {3} respectively).", a.ForFileName, b.ForFileName, a.Entries.Count, b.Entries.Count); return(false); } for (int i = 0; i < Math.Max(a.Entries.Count, b.Entries.Count); i++) { if (!a.Entries[i].Equals(b.Entries[i])) { errorMessage = string.Format("'{0}'!='{1}' at index '{2}'.", a.Entries[i].Path, b.Entries[i].Path, i); return(false); } } errorMessage = ""; return(true); }
/// <summary> /// Gets a <see cref="FileEntryGraph"/> representing the files in the specified outputDir (where an MSI was extracted). /// </summary> public static FileEntryGraph GetActualEntries(string outputDir, string forFileName) { var actualEntries = new FileEntryGraph(forFileName); var dir = new DirectoryInfo(outputDir); var dirsToProcess = new Stack<DirectoryInfo>(); dirsToProcess.Push(dir); while (dirsToProcess.Count > 0) { dir = dirsToProcess.Pop(); foreach (var file in dir.GetFiles()) { actualEntries.Add(new FileEntry(file, outputDir)); } foreach (var subDir in dir.GetDirectories()) { dirsToProcess.Push(subDir); } } return actualEntries; }
/// <summary> /// Gets a <see cref="FileEntryGraph"/> representing the files in the specified outputDir (where an MSI was extracted). /// </summary> public static FileEntryGraph GetActualEntries(string outputDir, string forFileName) { var actualEntries = new FileEntryGraph(forFileName); var dir = new DirectoryInfo(outputDir); var dirsToProcess = new Stack <DirectoryInfo>(); dirsToProcess.Push(dir); while (dirsToProcess.Count > 0) { dir = dirsToProcess.Pop(); foreach (var file in dir.GetFiles()) { actualEntries.Add(new FileEntry(file, outputDir)); } foreach (var subDir in dir.GetDirectories()) { dirsToProcess.Push(subDir); } } return(actualEntries); }
/// <summary> /// Extracts some or all of the files from the specified MSI and returns a <see cref="FileEntryGraph"/> representing the files that were extracted. /// </summary> /// <param name="msiFileName">The msi file to extract or null to extract all files.</param> protected FileEntryGraph ExtractFilesFromMsi(string msiFileName, string[] fileNamesToExtractOrNull) { // build command line string outputDir = Path.Combine(AppPath, "MsiOutputTemp"); outputDir = Path.Combine(outputDir, "_" + msiFileName); if (Directory.Exists(outputDir)) { DeleteDirectoryRecursive(new DirectoryInfo(outputDir)); Directory.Delete(outputDir, true); } Directory.CreateDirectory(outputDir); //ExtractViaCommandLine(outputDir, msiFileName); ExtractInProcess(msiFileName, outputDir, fileNamesToExtractOrNull); // build actual file entries extracted var actualEntries = FileEntryGraph.GetActualEntries(outputDir, msiFileName); // dump to actual dir (for debugging and updating tests) actualEntries.Save(GetActualOutputFile(msiFileName)); return(actualEntries); }
/// <summary> /// Loads a <see cref="FileEntryGraph"/> from the specified file. /// </summary> /// <param name="file">The file to load a new <see cref="FileEntryGraph"/> from.</param> /// <param name="forFileName">The initial value for the returned objects <see cref="FileEntryGraph.ForFileName"/></param> /// <returns>The newly loaded <see cref="FileEntryGraph"/>.</returns> public static FileEntryGraph Load(FileInfo file, string forFileName) { var graph = new FileEntryGraph(forFileName); using (var f = file.OpenText()) { f.ReadLine();//headings while (!f.EndOfStream) { var line = f.ReadLine().Split(','); if (line.Length != 5) { throw new IOException("Expected 5 fields!"); } /* FIX for github issue #23: * The problem was that old ExpectedOutput files were all prefixed with C:\projects\lessmsi\src\Lessmsi.Tests\bin\Debug\<msiFileNameWithoutExtension> (something like C:\projects\lessmsi\src\Lessmsi.Tests\bin\Debug\NUnit-2.5.2.9222\SourceDir\PFiles\NUnit 2.5.2\fit-license.txt) * We need to remove Since we don't reasonably know what the original msi filename was, we do know it was the subdirectory of C:\projects\lessmsi\src\Lessmsi.Tests\bin\Debug\. So we should remove C:\projects\lessmsi\src\Lessmsi.Tests\bin\Debug\ and the next subdirectory from the path. * HACK: A better fix would undoubtedly be to cleanup those old file swith code like this and remove this hack from this code forever! */ var path = line[0]; const string oldRootPath = @"C:\projects\lessmsi\src\Lessmsi.Tests\bin\Debug\"; if (path.StartsWith(oldRootPath, StringComparison.InvariantCultureIgnoreCase)) { //this is an old file that would trigger github issue #23, so we'll fix it here... // first remove the old root path: path = path.Substring(oldRootPath.Length); // now romove the msi filename (which we don't know, but we know it is the next subdirectory of the old root): var lengthOfSubDirectoryName = path.IndexOf('\\', 0); path = path.Substring(lengthOfSubDirectoryName); } graph.Add(new FileEntry(path, Int64.Parse(line[1]), DeserializeDate(line[2]), DeserializeDate(line[3]), DeserializeAttributes(line[4]))); } } return(graph); }
/// <summary> /// Loads the expected entries for the specified MSI file from the standard location. /// </summary> /// <param name="forMsi">The msi filename (no path) to load entries for.</param> /// <returns>The <see cref="FileEntryGraph"/> representing the files that are expected to be extracted from the MSI.</returns> protected FileEntryGraph GetExpectedEntriesForMsi(string forMsi) { return(FileEntryGraph.Load(GetExpectedOutputFile(forMsi), forMsi)); }