using System;
using System.Text;
using System.Collections.Specialized;
using System.IO;
using System.CodeDom.Compiler;
using System.Reflection;
using Microsoft.CSharp;
namespace Nutt.Actions{
/// <summary>
/// Holds all details for Nutt action, and has a triger method.
/// </summary>
public class NuttAction
{
public string ClassSource;
public string TestSource;
public NCover.Message Info = new NCover.Message(StubInfo);
public System.Windows.Forms.ProgressBar progress;
static CSharpCodeProvider cSharpCompiler;
static ICodeCompiler compiler;
static CompilerParameters compileParameters;
static NuttAction()
{
cSharpCompiler = new CSharpCodeProvider();
compiler = cSharpCompiler.CreateCompiler();
compileParameters = new CompilerParameters();
}
private static void StubInfo(string x) {}
public string ClassFilename
{
set
{
ClassSource = new StreamReader(value).ReadToEnd();
}
}
public string TestFilename
{
set
{
TestSource = new StreamReader(value).ReadToEnd();
}
}
public void Execute()
{
//Check classfile compiles...
if (Compiles(new string[] { ClassSource, TestSource } ))
{
Info("Starting testing...");
Mutator mutor = new Mutator(ClassSource);
progress.Minimum = 0;
progress.Maximum = mutor.Lines.Length;
while (mutor.HasNext)
{
string source = mutor.NextMutatedSource;
progress.Value = mutor.CurrentLine;
if (Compiles(new string[] { source, TestSource }))
{
Info("X" + mutor.Lines[mutor.CurrentLine]);
}
else
{
Info(" " + mutor.Lines[mutor.CurrentLine]);
}
}
}
else
{
Info("Doesn't compile");
}
//check unit test compiles...
}
public class Mutator
{
public readonly string[] Lines;
int _missLine = -1;
public Mutator(string source)
{
Lines = source.Split('\n');
}
public int CurrentLine
{
get
{
return _missLine;
}
}
public bool HasNext
{
get
{
SkipUnsuitable();
return _missLine + 1 < Lines.Length;
}
}
private void SkipUnsuitable()
{
string nextLine = Lines[ _missLine + 1 ].Trim();
while ( nextLine == String.Empty || nextLine.StartsWith("//"))
{
_missLine++;
if (_missLine + 1 >= Lines.Length)
{
return;
}
nextLine = Lines[ _missLine + 1 ].Trim();
}
}
public string NextMutatedSource
{
get
{
StringBuilder builder = new StringBuilder();
_missLine++;
for(int i = 0; i < Lines.Length; i++)
{
if (i == _missLine)
{
continue;//skip
}
builder.Append(Lines[i]);
}
return builder.ToString();
}
}
}
/// <summary>
/// Checks code compiles.
/// </summary>
/// <param name="code">Code must contain only one Type with one method in it</param>
/// <param name="expectedValue">Value that the function should return.</param>
private bool Compiles(string [] code)
{
compileParameters.GenerateInMemory = true;
compileParameters.TreatWarningsAsErrors = true;
// Info(typeof(NUnit.Framework.Assert).Assembly.GetReferencedAssemblies()[0]);
compileParameters.ReferencedAssemblies.Add(@"C:\tools\eclipse3M6\workspace\ncover\lib\nunit.framework.dll");
CompilerResults resultsOfCompile = compiler.CompileAssemblyFromSourceBatch(compileParameters, code);
// foreach (string outline in resultsOfCompile.Output)
// {
// Info(outline);
// }
return resultsOfCompile.Errors.Count == 0;
//Assert.AreEqual(0, resultsOfCompile.Errors.Count);
//Assert.AreEqual(0, resultsOfCompile.Output.Count);
//Assembly assembly = resultsOfCompile.CompiledAssembly;
//Assert.IsNotNull(assembly);
// Type type = assembly.GetType(typeName);
// return GetNormalMethod(type).Invoke(null, new object[]{});
}
}
}
|