//
//
//
//
// $Revision$
//
using System;
using System.CodeDom.Compiler;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Security.Cryptography;
using System.Text;
using System.Xml;
using Microsoft.CSharp;
using NUnit.Framework;
namespace Debugger.Tests
{
public class DebuggerTestsBase
{
string expetedOutputEnvVar = "SD_TESTS_DEBUGGER_XML_OUT";
protected NDebugger debugger;
protected Process process;
protected string log;
protected string lastLogMessage;
protected string testName;
protected XmlDocument testDoc;
protected XmlElement testNode;
protected XmlElement snapshotNode;
protected int shapshotID;
public StackFrame SelectedStackFrame {
get {
return process.SelectedStackFrame;
}
}
public void Continue()
{
process.Continue();
}
[TestFixtureSetUp]
public virtual void TestFixtureSetUp()
{
debugger = new NDebugger();
debugger.MTA2STA.CallMethod = CallMethod.Manual;
}
[TestFixtureTearDown]
public virtual void TestFixtureTearDown()
{
}
[SetUp]
public virtual void SetUp()
{
System.Threading.Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;
testName = null;
expandProperties = new List();
ignoreProperties = new List();
ignoreProperties.AddRange(new string [] {
"*.GetType",
"*.GetHashCode",
"*.GetEnumerator",
"*.AppDomain",
"*.Process",
"MemberInfo.DebugModule",
"MemberInfo.IsStatic",
"MemberInfo.IsPublic",
"MemberInfo.IsAssembly",
"MemberInfo.IsFamily",
"MemberInfo.IsPrivate",
"MemberInfo.MetadataToken",
"MemberInfo.MemberType",
"Type.DeclaringType",
"Type.IsAbstract",
"Type.IsAnsiClass",
"Type.IsAutoLayout",
"Type.IsLayoutSequential",
"Type.IsNestedPublic",
"Type.IsSealed",
"Type.IsSerializable",
"Type.IsVisible",
"Type.IsNotPublic",
"Type.Name",
"Type.Namespace",
"Type.UnderlyingSystemType",
"MethodBase.CallingConvention",
"MethodBase.GetMethodBody",
"MethodBase.GetMethodImplementationFlags",
"MethodBase.GetParameters",
"MethodBase.IsFinal",
"MethodBase.IsHideBySig",
"MethodBase.IsVirtual",
"MethodBase.IsSpecialName",
"MethodBase.ReturnParameter",
"MethodBase.ParameterCount",
"PropertyInfo.CanRead",
"PropertyInfo.CanWrite",
"PropertyInfo.GetGetMethod",
"PropertyInfo.GetSetMethod",
});
testDoc = new XmlDocument();
testDoc.AppendChild(testDoc.CreateXmlDeclaration("1.0","utf-8",null));
testDoc.AppendChild(testDoc.CreateElement("DebuggerTests"));
testNode = testDoc.CreateElement("Test");
testDoc.DocumentElement.AppendChild(testNode);
}
[TearDown]
public virtual void TearDown()
{
}
protected void EndTest()
{
if (!process.HasExited) {
process.AsyncContinue();
process.WaitForExit();
}
CheckXmlOutput();
}
protected void CheckXmlOutput()
{
string startMark = "#if EXPECTED_OUTPUT\r\n";
string endMark = "#endif // EXPECTED_OUTPUT";
MemoryStream newXmlStream = new MemoryStream();
XmlWriterSettings settings = new XmlWriterSettings();
settings.Encoding = Encoding.UTF8;
settings.Indent = true;
settings.NewLineOnAttributes = true;
XmlWriter writer = XmlTextWriter.Create(newXmlStream, settings);
testDoc.Save(writer);
newXmlStream.Seek(0, SeekOrigin.Begin);
string actualXml = new StreamReader(newXmlStream).ReadToEnd() + "\r\n";
string sourceCode = GetResource(testName);
int startIndex = sourceCode.IndexOf(startMark);
int endIndex = sourceCode.IndexOf(endMark);
if (startIndex == -1 || endIndex == -1) {
Assert.Fail("Test " + testName + " failed. Expected XML output not found.");
}
string expectedXml = sourceCode.Substring(startIndex + startMark.Length, endIndex - (startIndex + startMark.Length));
if (actualXml != expectedXml) {
// Update the source code file with the new output
string path = Environment.GetEnvironmentVariable(expetedOutputEnvVar);
if (path != null) {
string filename = Path.Combine(path, testName);
string newSourceCode = File.ReadAllText(filename, Encoding.UTF8);
startIndex = newSourceCode.IndexOf(startMark);
endIndex = newSourceCode.IndexOf(endMark);
newSourceCode =
newSourceCode.Substring(0, startIndex + startMark.Length) +
actualXml +
newSourceCode.Substring(endIndex);
File.WriteAllText(filename, newSourceCode, Encoding.UTF8);
}
//Assert.Fail("Test " + testName + " failed. XML output differs from expected.");
Assert.AreEqual(expectedXml, actualXml, "Test " + testName + " failed. XML output differs from expected.");
}
}
protected void StartTest()
{
string testName = Path.GetFileName(new System.Diagnostics.StackTrace(true).GetFrame(1).GetFileName());
StartTest(testName, true);
}
protected void StartTestNoWait()
{
string testName = Path.GetFileName(new System.Diagnostics.StackTrace(true).GetFrame(1).GetFileName());
StartTest(testName, false);
}
void StartTest(string testName, bool wait)
{
this.testName = testName;
string exeFilename = CompileTest(testName);
testNode.SetAttribute("name", testName);
shapshotID = 0;
log = "";
lastLogMessage = null;
process = debugger.Start(exeFilename, Path.GetDirectoryName(exeFilename), testName);
process.LogMessage += delegate(object sender, MessageEventArgs e) {
log += e.Message;
lastLogMessage = e.Message;
LogEvent("LogMessage", e.Message.Replace("\r",@"\r").Replace("\n",@"\n"));
};
process.Modules.Added += delegate(object sender, CollectionItemEventArgs e) {
LogEvent("ModuleLoaded", e.Item.Filename + (e.Item.HasSymbols ? " (Has symbols)" : " (No symbols)"));
};
process.Paused += delegate(object sender, ProcessEventArgs e) {
LogEvent("DebuggingPaused", e.Process.PauseSession.PausedReason.ToString() + " " + e.Process.SelectedStackFrame.NextStatement.ToString());
};
// process.DebuggingResumed += delegate(object sender, ProcessEventArgs e) {
// LogEvent("DebuggingResumed", e.Process.PausedReason.ToString());
// };
process.ExceptionThrown += delegate(object sender, ExceptionEventArgs e) {
StringBuilder msg = new StringBuilder();
if (process.SelectedThread.InterceptCurrentException()) {
msg.Append(e.Exception.ToString());
} else {
// For example, happens on stack overflow
msg.Append("Could not intercept: ");
msg.Append(e.Exception.ToString());
}
LogEvent("ExceptionThrown", msg.ToString());
};
process.Exited += delegate(object sender, EventArgs e) {
LogEvent("ProcessExited", null);
};
LogEvent("ProcessStarted", null);
if (wait) {
process.WaitForPause();
}
}
protected XmlElement LogEvent(string name, string content)
{
XmlElement eventNode = testDoc.CreateElement(name);
if (content != null) {
eventNode.AppendChild(testDoc.CreateTextNode(content));
}
testNode.AppendChild(eventNode);
return eventNode;
}
public void ObjectDump(object obj)
{
Serialize(testNode, obj, 16, new List