// 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);
}
}
}
}
}