// // Copyright © 2018 Ranorex All rights reserved // using System; using System.IO; using System.Text; using System.Text.RegularExpressions; using Ranorex.Core.Testing; namespace Ranorex.AutomationHelpers.UserCodeCollections { /// /// A collection of useful file methods. /// [UserCodeCollection] public static class FileLibrary { private const string libraryName = "FileLibrary"; private const string newLineRegexPattern = "(\r\n)|(\n)|(\r)"; /// /// Creates a log file containing a custom text in the output folder. /// /// Text that the log file should contain /// Prefix used for the log filename /// Extension of the log file [UserCodeMethod] public static void WriteToFile(string text, string filenamePrefix, string fileExtension) { var now = System.DateTime.Now; var strTimestamp = now.ToString("yyyyMMdd_HHmmss"); var filename = filenamePrefix + "_" + strTimestamp + "." + fileExtension; Report.Info(filename); try { //Create the File using (FileStream fs = File.Create(filename)) { var info = new UTF8Encoding(true).GetBytes(text); fs.Write(info, 0, info.Length); } } catch (Exception ex) { Utils.ReportException(ex, libraryName); } } /// /// Opens an existing file and adds a new line of text at the end of it. /// /// The text to add to the file. /// The Full qualified path to load the file including filename and extension. /// If true, adds the text on a newline. Otherwise, adds it without a line break. [UserCodeMethod] public static void AppendStringToExistingFile(string text, string path, bool addNewLine) { Report.Info("Add new text to file: " + path); if (addNewLine) { File.AppendAllText(path, Environment.NewLine + text); } else { File.AppendAllText(path, text); } } /// /// Checks if files in a directory exist. /// /// The relative or absolute path to search for the files /// The pattern to search for in the filename /// Number of expected files to be found /// Defines the search timeout in seconds [UserCodeMethod] public static void CheckFilesExist(string path, string pattern, int expectedCount, int timeout) { var listofFiles = Directory.GetFiles(path, pattern); var start = System.DateTime.Now; while (listofFiles.Length != expectedCount && System.DateTime.Now < start.AddSeconds(timeout)) { listofFiles = Directory.GetFiles(path, pattern); } Report.Info("Check if '" + expectedCount + "' file(s) with pattern '" + pattern + "' exist in the directory '" + path + "'. Search time " + timeout + " seconds."); Validate.AreEqual(listofFiles.Length, expectedCount); } /// /// Deletes files. /// /// The relative or absolute path to search for the files /// The pattern to search for in the filename [UserCodeMethod] public static void DeleteFiles(string path, string pattern) { var listofFiles = Directory.GetFiles(path, pattern); if (listofFiles.Length == 0) { Report.Warn("No files have been found in '" + path + "' with the pattern '" + pattern + "'."); } foreach (string file in listofFiles) { try { File.Delete(file); Report.Info("File has been deleted: " + file.ToString()); } catch (Exception ex) { Utils.ReportException(ex, libraryName); } } } /// /// Repeatedly checks if files in a directory exist. /// /// The relative or absolute path to search for the files /// The pattern to search for in the filename /// Defines the search timeout in milliseconds /// Sets the interval in milliseconds at which the files are checked for the pattern [UserCodeMethod] public static void WaitForFile(string path, string pattern, int duration, int interval) { path = GetPathForFile(path); var bFound = Directory.GetFiles(path, pattern).Length > 0; var start = System.DateTime.Now; while (!bFound && (System.DateTime.Now < start + TimeSpan.FromMilliseconds(duration))) { bFound = Directory.GetFiles(path, pattern).Length > 0; if (bFound) { break; } Delay.Duration(Duration.FromMilliseconds(interval), false); } if (bFound) { Report.Success("Validation", "File with pattern '" + pattern + "' was found in directory '" + path + "'."); } else { Report.Failure("Validation", "File with pattern '" + pattern + "' wasn't found in directory '" + path + "'."); } } /// /// Compares content of two binary files. /// /// The relative or absolute path of the first file /// The relative or absolute path of the second file [UserCodeMethod] public static void ValidateFilesBinaryEqual(string filePath1, string filePath2) { try { filePath1 = GetPathForFile(filePath1); filePath2 = GetPathForFile(filePath2); if (!FilesExist(filePath1, filePath2)) { return; } var fi1 = new FileInfo(filePath1); var fi2 = new FileInfo(filePath2); if (fi1.Length != fi2.Length) { Report.Failure("Files '" + filePath1 + "' and '" + filePath2 + "' are not equal because they differ in size."); return; } const int bufferSize = 65536; using (var fs1 = new FileStream(filePath1, FileMode.Open, FileAccess.Read, FileShare.Read, bufferSize)) using (var fs2 = new FileStream(filePath2, FileMode.Open, FileAccess.Read, FileShare.Read, bufferSize)) { var tempBufferSize = sizeof(Int64); var tempBuffer1 = new byte[tempBufferSize]; var tempBuffer2 = new byte[tempBufferSize]; for (var i = 0L; i < (fi1.Length / tempBufferSize) + 1; i++) { fs1.Read(tempBuffer1, 0, tempBufferSize); fs2.Read(tempBuffer2, 0, tempBufferSize); if (BitConverter.ToInt64(tempBuffer1, 0) != BitConverter.ToInt64(tempBuffer2, 0)) { Report.Failure("Files '" + filePath1 + "' and '" + filePath2 + "' are not equal."); return; } } } Report.Success("Files '" + filePath1 + "' and '" + filePath2 + "' are equal."); } catch (Exception ex) { Utils.ReportException(ex, libraryName); } } /// /// Compares content of two text files. /// /// The relative or absolute path of the first file /// The relative or absolute path of the second file [UserCodeMethod] public static void ValidateFilesTextEqual(string filePath1, string filePath2) { ValidateFilesTextEqual(filePath1, filePath2, true); } /// /// Compares content of two text files. /// /// The relative or absolute path of the first file /// The relative or absolute path of the second file /// If true, line endings will be normalized before comparison. /// Original files will not be changed. [UserCodeMethod] public static void ValidateFilesTextEqual(string filePath1, string filePath2, bool normalizeLineEndings) { try { filePath1 = GetPathForFile(filePath1); filePath2 = GetPathForFile(filePath2); if (!FilesExist(filePath1, filePath2)) { return; } var fileContent1 = File.ReadAllText(filePath1); if (normalizeLineEndings) { fileContent1 = Regex.Replace(fileContent1, newLineRegexPattern, "\r\n"); } var fileContent2 = File.ReadAllText(filePath2); if (normalizeLineEndings) { fileContent2 = Regex.Replace(fileContent2, newLineRegexPattern, "\r\n"); } if (fileContent1 != fileContent2) { Report.Failure("Files '" + filePath1 + "' and '" + filePath2 + "' are not equal."); ValidateFileContentLineByLine(fileContent1, fileContent2); return; } Report.Success("Files '" + filePath1 + "' and '" + filePath2 + "' are equal."); } catch (Exception ex) { Utils.ReportException(ex, libraryName); } } /// /// Checks line by line if strings are identical. /// Line separator is "\r\n" /// /// The string with the content of file 1 using \r\n as line separator. /// The string with the content of file 2 using \r\n as line separator. [UserCodeMethod] public static void ValidateFileContentLineByLine(string fileContent1, string fileContent2) { string[] stringSeparators = new string[] { "\r\n" }; string[] lines1 = fileContent1.Split(stringSeparators, StringSplitOptions.None); string[] lines2 = fileContent2.Split(stringSeparators, StringSplitOptions.None); if (lines1.Length!=lines2.Length) { Report.Error("Files have different length. They will be compared line by line until the length of the smallest one."); Report.Info("Number of lines in file 1: " + lines1.Length); Report.Info("Number of lines in file 2: " + lines2.Length); } var minLength = Math.Min(lines1.Length, lines2.Length); bool differencesHaveBeenFound = false; string differencesThatHaveBeenFound = ""; for (int i = 0; i < minLength; i++) { if (lines1[i]!=lines2[i]) { differencesThatHaveBeenFound += "File 1: " + lines1[i] + "\r\n" + "File 2: " + lines2[i] + "\r\n \r\n"; differencesHaveBeenFound = true; } } if (differencesHaveBeenFound) { Report.Error("The differences below have been found between both files."); Report.Info(differencesThatHaveBeenFound); } } /// /// Checks if file contains text specified. /// /// The relative or absolute path to the file /// The text to search for [UserCodeMethod] public static void ValidateFileContainsText(string filePath, string text) { ValidateFileContainsText(filePath, text, "utf-8"); } /// /// Checks if file contains text specified. /// /// The relative or absolute path to the file /// The text to search for /// Encoding of a file [UserCodeMethod] public static void ValidateFileContainsText(string filePath, string text, string fileEncoding) { try { var encoding = Encoding.GetEncoding(fileEncoding); filePath = GetPathForFile(filePath); if (!FilesExist(filePath)) { return; } var textFound = false; if (Regex.IsMatch(text, newLineRegexPattern)) { if (File.ReadAllText(filePath, encoding).Contains(text)) { Report.Success("Text '" + text + "' was found in file " + filePath + "'."); textFound = true; } } else { using (StreamReader sr = new StreamReader(filePath, encoding)) { var line = ""; var i = 1; while ((line = sr.ReadLine()) != null) { if (line.IndexOf(text, StringComparison.OrdinalIgnoreCase) != -1) { Report.Success("Text '" + text + "' was found on line " + i + ": '" + line + "'."); textFound = true; } ++i; } } } if (!textFound) { Report.Failure("Text '" + text + "' was not found in file '" + filePath + "'."); } } catch (Exception ex) { Utils.ReportException(ex, libraryName); } } private static string GetPathForFile(string path) { return path.StartsWith(".") ? Path.GetFullPath(Path.Combine(Environment.CurrentDirectory, path)) : path; } private static bool FilesExist(params string[] filePaths) { bool filesExist = true; foreach (string filePath in filePaths) { if (!File.Exists(filePath)) { Report.Error("The file '" + filePath + "' does not exist."); filesExist = false; } } return filesExist; } } }