Skip to content
Permalink
Browse files

Added an ability to run tests from interactive console

  • Loading branch information...
vorov2 committed May 15, 2019
1 parent 0c0f1e3 commit fcafa84f382ebdf1688996f230b753fda94baa67
@@ -12,7 +12,7 @@ public sealed class DyaOptions
private const string LINKER = "Linker settings";
private const string GENERAL = "General settings";

[Binding(Help = "A full path to the .dy file which should be executed.", Category = COMPILER)]
[Binding(Help = "A full path to the .dy file which should be executed (or to the file or directory with files in '-test' mode).", Category = COMPILER)]
public string FileName { get; set; }

[Binding("debug", Help = "Compile in debug mode.", Category = COMPILER)]
@@ -27,6 +27,12 @@ public sealed class DyaOptions
[Binding("nologo", Help = "Do not show logo.", Category = GENERAL)]
public bool NoLogo { get; set; }

[Binding("test", Help = "Run unit tests from a file (or files if a path to a directory is specified). Usage: dya [path to file or directory] -test.", Category = GENERAL)]
public bool Test { get; set; }

[Binding("appveyor")]
public bool AppVeyour { get; set; }

[Binding("i", Help = "Stay in interactive mode after executing a file.", Category = GENERAL)]
public bool StayInInteractive { get; set; }

@@ -44,6 +44,9 @@
<None Update="dya.sh">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Tests\tests.dy">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>

</Project>
@@ -22,7 +22,12 @@ public static int Main(string[] args)
ctx = new InteractiveContext(options);
dispatcher = new CommandDispatcher(ctx);

if (options.FileName != null)
if (options.Test)
{
Printer.LineFeed();
return RunTests(options) ? OK : ERR;
}
else if (options.FileName != null)
{
Printer.LineFeed();

@@ -40,6 +45,17 @@ public static int Main(string[] args)
return OK;
}

private static bool RunTests(DyaOptions options)
{
if (string.IsNullOrEmpty(options.FileName))
{
Printer.Error("File name not specified.");
return false;
}

return TestRunner.RunTests(options.FileName, options.AppVeyour);
}

private static void RunInteractive()
{
var sb = new StringBuilder();
@@ -1,11 +1,15 @@
{
"profiles": {
"Dyalect.Console": {
"commandName": "Project"
},
"Run file": {
"commandName": "Project",
"commandLineArgs": "\"..\\Dyalect.UnitTests\\Playground\\test.dy\""
},
"Run tests": {
"commandName": "Project",
"commandLineArgs": "Tests\\ -test"
},
"Interactive": {
"commandName": "Project"
}
}
}
@@ -0,0 +1,159 @@
using Dyalect.Compiler;
using Dyalect.Linker;
using Dyalect.Parser;
using Dyalect.Runtime;
using Dyalect.Runtime.Types;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;

namespace Dyalect
{
public static class TestRunner
{
sealed class FunSet
{
public string FileName { get; set; }

public ExecutionContext Context { get; set; }

public Dictionary<string, DyFunction> Funs { get; set; }
}

private static List<string> commands = new List<string>();

public static bool RunTests(string fileName, bool appveyor)
{
try
{
var funs = Compile(fileName);
Printer.Output($"Running tests from {funs.Count} file(s)...");

if (funs == null)
return false;

Run(funs, appveyor);
return true;
}
catch (Exception ex)
{
Printer.Error($"Failure! {ex.Message}");
return false;
}
}

private static void Run(IList<FunSet> funs, bool appveyor)
{
var passed = 0;
var failed = 0;
var i = 0;
var fi = 0;

foreach (var funSet in funs)
{
Printer.LineFeed();
Printer.Output($"{++fi}. {funSet.FileName}:");
var padLen = funSet.Funs.Count.ToString().Length;

foreach (var fn in funSet.Funs)
{
Console.Write($"[{(++i).ToString().PadLeft(padLen, '0')}] ");

try
{
var res = fn.Value.Call(funSet.Context).ToObject();
Success(fn.Key);
passed++;
}
catch (Exception ex)
{
Failed(fn.Key, ex.Message);
failed++;
}
}
}

Printer.SupplementaryOutput(new string('-', 60));
Printer.Output($"{passed} passed, {failed} failed");

if (appveyor)
Submit();
}

private static void Submit()
{
Printer.LineFeed();
Printer.Output("Submitting test results...");

try
{
foreach (var c in commands)
Process.Start("appveyor", c);

Printer.Output("Ok");
}
catch (Exception ex)
{
Printer.Error($"Failure! {ex.Message}");
}
}

private static void Failed(string name, string reason)
{
commands.Add($"AddTest {name} -Outcome Failed -Framework DUnit -FileName tests.dy");
Printer.Output($"{name}: Failed");
}

private static void Success(string name)
{
commands.Add($"AddTest {name} -Outcome Passed -Framework DUnit -FileName tests.dy");
Printer.Output($"{name}: Success");
}

private static IList<FunSet> Compile(string fileName)
{
var funColl = new List<FunSet>();
IEnumerable<string> files = null;

if (File.Exists(fileName))
files = new string[] { fileName };
else if (Directory.Exists(fileName))
files = Directory.EnumerateFiles(fileName, "*.dy");
else
{
Printer.Error($"File or directory {fileName} not found.");
return null;
}

foreach (var file in files)
{
var linker = new DyLinker(FileLookup.Create(file), BuilderOptions.Default);
var cres = linker.Make(SourceBuffer.FromFile(file));
var funs = new FunSet();
funs.Funs = new Dictionary<string, DyFunction>(StringComparer.OrdinalIgnoreCase);
funs.FileName = file;

if (!cres.Success)
throw new DyBuildException(cres.Messages);

var ctx = DyMachine.CreateExecutionContext(cres.Value);
funs.Context = ctx;
DyMachine.Execute(ctx);

foreach (var v in DyMachine.DumpVariables(ctx))
{
if (v.Value is DyFunction fn)
{
funs.Funs.Remove(v.Name);
funs.Funs.Add(v.Name, fn);
}
}

funColl.Add(funs);
}

return funColl;
}
}
}
File renamed without changes.
@@ -26,6 +26,10 @@ public static string Generate(Type type, string prefix = "-", int defPad = 0)
foreach (var ac in props)
{
var attr = Attribute.GetCustomAttribute(ac, typeof(BindingAttribute)) as BindingAttribute;

if (attr == null || attr.Help == null)
continue;

var ln = new List<string>();

foreach (var n in attr.Names)
@@ -28,4 +28,25 @@
<ProjectReference Include="..\Dyalect\Dyalect.csproj" />
</ItemGroup>

<ItemGroup>
<None Update="Playground\fizzbuzz.dy">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Playground\langtonsant.dy">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Playground\library.dy">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Playground\test.dy">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Playground\test1.dy">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Playground\test2.dy">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>

</Project>
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

This file was deleted.

This file was deleted.

0 comments on commit fcafa84

Please sign in to comment.
You can’t perform that action at this time.