// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. namespace WixTestTools { using System; using System.IO; using System.Text; using System.Text.RegularExpressions; using Xunit; /// /// The LogVerifier can verify a log file for given regular expressions. /// public class LogVerifier { // Member Variables private readonly string logFile; /// /// Prevent creation of LogVerifier without log file /// private LogVerifier() { } /// /// Constructor for log files where the exact file name is known. /// /// The full path to the log file public LogVerifier(string fileName) { if (null == fileName) { throw new ArgumentNullException("fileName"); } if (!File.Exists(fileName)) { throw new ArgumentException(String.Format(@"File doesn't exist:{0}", fileName), "fileName"); } this.logFile = fileName; } /// /// Constructor for log files where the exact file name is known. /// /// The directory in which the log file is located. /// The name of the log file. public LogVerifier(string directory, string fileName) : this(Path.Combine(directory, fileName)) { } /// /// Scans a log file line by line until the regex pattern is matched or eof is reached. /// This method would be used in the case where the log file is very large, the regex doesn't /// span multiple lines, and only one match is required. /// /// A regular expression /// True if a match is found, False otherwise. public bool LineByLine(Regex regex) { string line; StreamReader sr = new StreamReader(this.logFile); // Read from a file stream line by line. while ((line = sr.ReadLine()) != null) { if (regex.Match(line).Success) { sr.Close(); sr.Dispose(); return true; } } return false; } /// /// Scans a log file line by line until the regex pattern is matched or eof is reached. /// This method would be used in the case where the log file is very large, the regex doesn't /// span multiple lines, and only one match is required. /// No RegexOptions are used and matches are case sensitive. /// /// A regular expression string. /// True if a match is found, False otherwise. public bool LineByLine(string regex) { return this.LineByLine(new Regex(regex)); } /// /// Scans a log file for matches to the regex. /// /// A regular expression /// The number of matches public int EntireFileAtOnce(Regex regex) { string logFileText = this.ReadLogFile(); return regex.Matches(logFileText).Count; } /// /// Scans a log file for matches to the regex. /// /// A regular expression /// The number of matches public bool EntireFileAtOncestr(string regex) { string logFileText = this.ReadLogFile(); return logFileText.Contains(regex); } /// /// Scans a log file for matches to the regex string. /// Only the Multiline RegexOption is used and matches are case sensitive. /// /// A regular expression /// The number of matches public int EntireFileAtOnce(string regex) { return this.EntireFileAtOnce(new Regex(regex, RegexOptions.Multiline)); } /// /// Scans a log file for matches to the regex string. /// /// A regular expression /// Specify whether to perform case sensitive matches /// The number of matches public int EntireFileAtOnce(string regex, bool ignoreCase) { if (!ignoreCase) { return this.EntireFileAtOnce(new Regex(regex, RegexOptions.Multiline)); } else { return this.EntireFileAtOnce(new Regex(regex, RegexOptions.Multiline | RegexOptions.IgnoreCase)); } } /// /// Search through the log and Assert.Fail() if a specified string is not found. /// /// Search expression /// Perform case insensitive match public void AssertTextInLog(string regex, bool ignoreCase) { Assert.True(this.EntireFileAtOncestr(regex), String.Format("The log does not contain a match to the regular expression \"{0}\" ", regex)); } /// /// Search through the log and Assert.Fail() if a specified string is not found. /// /// Search expression /// Perform case insensitive match public void AssertTextInLog(Regex regex, bool ignoreCase) { Assert.True(this.EntireFileAtOnce(regex) >= 1, String.Format("The log does not contain a match to the regular expression \"{0}\" ", regex.ToString())); } /// /// Search through the log and Assert.Fail() if a specified string is not found. /// /// Search expression /// Perform case insensitive match public void AssertTextInLog(string regex) { this.AssertTextInLog(regex, true); } /// /// Search through the log and Assert.Fail() if a specified string is not found. /// /// Search expression /// Perform case insensitive match public void AssertTextInLog(Regex regex) { this.AssertTextInLog(regex, true); } /// /// Search through the log and Assert.Fail() if a specified string is found. /// /// Search expression /// Perform case insensitive match public void AssertTextNotInLog(Regex regex, bool ignoreCase) { Assert.True(this.EntireFileAtOnce(regex) < 1, String.Format("The log contain a match to the regular expression \"{0}\" ", regex.ToString())); } /// /// Search through the log and Assert.Fail() if a specified string is not found. /// /// Search expression /// Perform case insensitive match public void AssertTextNotInLog(string regex, bool ignoreCase) { Assert.False(this.EntireFileAtOncestr(regex), String.Format("The log does not contain a match to the regular expression \"{0}\" ", regex)); } /// /// Checks if a meesage is in a file /// /// The full path to the log file /// Search expression /// True if the message was found, false otherwise public static bool MessageInLogFile(string logFileName, string message) { LogVerifier logVerifier = new LogVerifier(logFileName); return logVerifier.EntireFileAtOncestr(message); } /// /// Checks if a meesage is in a file /// /// The full path to the log file /// Search expression (regex) /// True if the message was found, false otherwise public static bool MessageInLogFileRegex(string logFileName, string regexMessage) { LogVerifier logVerifier = new LogVerifier(logFileName); return logVerifier.EntireFileAtOnce(regexMessage) > 0; } /// /// Read in the entire log file at once. /// /// Contents of log file. private string ReadLogFile() { // Retry a few times. for (int retry = 0; ; ++retry) { try { using (StreamReader sr = new StreamReader(this.logFile)) { return sr.ReadToEnd(); } } catch // we'll catch everything a few times until we give up. { if (retry > 4) { throw; } System.Threading.Thread.Sleep(1000); } } } } }