using System;
using System.Linq;
using System.Diagnostics;
using Kaleida.ServiceMonitor.Model.Parsing;
using Kaleida.ServiceMonitor.Model.StructuredSource;
using NUnit.Framework;
namespace Kaleida.UnitTests.Model.Parsing
{
[TestFixture]
public class ParserTests
{
[Test]
public void TestEmptyString()
{
var script = ParseAndLog("");
Assert.AreEqual(0, script.Operations.Count);
Assert.AreEqual(0, script.Comments.Count);
Assert.AreEqual(0, script.Directives.Count);
}
[Test]
public void TestRequestWithNoArguments()
{
var script = ParseAndLog("my-action");
Assert.AreEqual(1, script.Operations.Count);
AssertAction(script.Operations[0].RequestAction, "my-action");
AssertAction(script.Operations[0].HandlerAction, "do-nothing");
}
[Test]
public void TestRequestWithOneArgument()
{
var script = ParseAndLog("my-action \"arg1\"");
Assert.AreEqual(1, script.Operations.Count);
AssertAction(script.Operations[0].RequestAction, "my-action", "arg1");
AssertAction(script.Operations[0].HandlerAction, "do-nothing");
}
[Test]
public void TestArgumentContainingQuotationMarks()
{
var script = ParseAndLog("my-action \"\"\"Hello\"\", she said\"");
Assert.AreEqual(1, script.Operations.Count);
AssertAction(script.Operations[0].RequestAction, "my-action", "\"Hello\", she said");
}
[Test]
public void TestRequestWithMultipleArgument()
{
var script = ParseAndLog("my-action \"arg1\", \"arg2\", \"arg3\"");
Assert.AreEqual(1, script.Operations.Count);
AssertAction(script.Operations[0].RequestAction, "my-action", "arg1", "arg2", "arg3");
AssertAction(script.Operations[0].HandlerAction, "do-nothing");
}
[Test]
public void TestRequestWithNoArgsAndResponseWithNoArgs()
{
var script = ParseAndLog("my-action my-handler");
Assert.AreEqual(1, script.Operations.Count);
AssertAction(script.Operations[0].RequestAction, "my-action");
AssertAction(script.Operations[0].HandlerAction, "my-handler");
}
[Test]
public void TestRequestWithNoArgsAndResponseWithOneArg()
{
var script = ParseAndLog("my-action my-handler \"a\"");
Assert.AreEqual(1, script.Operations.Count);
AssertAction(script.Operations[0].RequestAction, "my-action");
AssertAction(script.Operations[0].HandlerAction, "my-handler", "a");
}
[Test]
public void TestRequestWithNoArgsAndResponseWithMultipleArgs()
{
var script = ParseAndLog("my-action my-handler \"a\", \"b\", \"c\"");
Assert.AreEqual(1, script.Operations.Count);
AssertAction(script.Operations[0].RequestAction, "my-action");
AssertAction(script.Operations[0].HandlerAction, "my-handler", "a", "b", "c");
}
[Test]
public void TestMultipleCommandsContainingSimpleRequest()
{
var script = ParseAndLog("my-action1\r\n" +
"my-action2\r\n");
Assert.AreEqual(2, script.Operations.Count);
}
[Test]
public void TestDuplicateNewLines()
{
var script = ParseAndLog("my-action1\r\n\r\n\r\n" +
"my-action2\r\n\r\n");
Assert.AreEqual(2, script.Operations.Count);
}
[Test]
public void TestMultipleCommandsWithMixedEndings()
{
var script = ParseAndLog("my-action1\r" +
"my-action2\r\n" +
"my-action3\n");
Assert.AreEqual(3, script.Operations.Count);
AssertAction(script.Operations[0].RequestAction, "my-action1");
AssertAction(script.Operations[1].RequestAction, "my-action2");
AssertAction(script.Operations[2].RequestAction, "my-action3");
}
[Test]
public void TestMultipleCommandsWithFull()
{
var script = ParseAndLog("my-action1 \"a\", \"b\", \"c\" my-handler1 \"1\", \"2\", \"3\"\r\n" +
"my-action2 \"p\", \"q\", \"r\" my-handler2 \"4\", \"5\", \"6\"\r\n" +
"my-action3 \"x\", \"y\", \"z\" my-handler3 \"7\", \"8\", \"9\"\r\n");
Assert.AreEqual(3, script.Operations.Count);
}
[Test]
public void TestSingleCommandWithLineBreak()
{
var script = ParseAndLog("my-action1\r\n");
Assert.AreEqual(1, script.Operations.Count);
}
[Test]
public void TestSingleDirective()
{
var script = ParseAndLog("#MyDirective");
Assert.AreEqual(1, script.Directives.Count);
Assert.AreEqual("MyDirective", script.Directives[0].Text);
}
[Test]
public void TestSingleDirectiveWithArguments()
{
var script = ParseAndLog("#MyDirective \"1\", \"2\"");
Assert.AreEqual(1, script.Directives.Count);
Assert.AreEqual("MyDirective", script.Directives[0].Text);
Assert.AreEqual(2, script.Directives[0].Arguments.Count);
Assert.AreEqual("1", script.Directives[0].Arguments[0]);
Assert.AreEqual("2", script.Directives[0].Arguments[1]);
}
[Test]
public void TestDirectivesWithinOtherLines()
{
var script = ParseAndLog("my-action1\r\n" +
"#MyDirective\r\n" +
"my-action2\r\n" +
"#MyOtherDirective\r\n");
Assert.AreEqual(2, script.Directives.Count);
Assert.AreEqual("MyDirective", script.Directives[0].Text);
Assert.AreEqual("MyOtherDirective", script.Directives[1].Text);
}
[Test]
public void TestSingleComment()
{
var script = ParseAndLog("// This is a comment");
Assert.AreEqual(1, script.Comments.Count);
Assert.AreEqual(" This is a comment", script.Comments[0]);
}
[Test]
public void TestCommentsWithinOtherLines()
{
var script = ParseAndLog("my-action1\r\n" +
"// This is a comment\r\n" +
"my-action2\r\n" +
"// another comment\r\n");
Assert.AreEqual(2, script.Comments.Count);
Assert.AreEqual(" This is a comment", script.Comments[0]);
Assert.AreEqual(" another comment", script.Comments[1]);
}
[Test]
public void TestCommentsDirectivesAndCommandsCanAppearInAnyOrder()
{
var script1 = ParseAndLog("// comment\r\n" + "my-action1 \r\n" + "#MyDirective\r\n");
Assert.AreEqual(1, script1.Comments.Count());
Assert.AreEqual(1, script1.Directives.Count());
Assert.AreEqual(1, script1.Operations.Count());
var script2 = ParseAndLog("my-action1 \r\n" + "// comment\r\n" + "#MyDirective\r\n");
Assert.AreEqual(1, script2.Comments.Count());
Assert.AreEqual(1, script2.Directives.Count());
Assert.AreEqual(1, script2.Operations.Count());
var script3 = ParseAndLog("#MyDirective\r\n" + "my-action1 \r\n" + "// comment\r\n");
Assert.AreEqual(1, script3.Comments.Count());
Assert.AreEqual(1, script3.Directives.Count());
Assert.AreEqual(1, script3.Operations.Count());
}
[Test]
public void TestWithNewLineAtStart()
{
var text = @"
ping ""localhost""";
var script = ParseAndLog(text);
Assert.AreEqual(1, script.Operations.Count());
}
[Test]
public void TestWithSingleSpaceOnLine()
{
var text = @"ping ""localhost""
ping ""myServer""";
var script = ParseAndLog(text);
Assert.AreEqual(2, script.Operations.Count());
}
[Test]
[ExpectedException(typeof(InvalidOperationException), ExpectedMessage = "Script contains syntax errors")]
public void TestBadlyFormedThrowsException()
{
ParseAndLog("(");
}
[Test]
public void TestSingleEmptyGroup()
{
var script = ParseAndLog("{}");
Assert.AreEqual(0, script.Operations.Count);
Assert.AreEqual(0, script.Comments.Count);
Assert.AreEqual(0, script.Directives.Count);
}
[Test]
public void TestSingleGroup()
{
var script = ParseAndLog("{\r\nmy-action1\r\nmy-action2\r\n}");
Assert.AreEqual(2, script.Operations.Count);
Assert.AreEqual(0, script.Comments.Count);
Assert.AreEqual(0, script.Directives.Count);
}
[Test]
public void TestMultipleGroupsAtTopLevel()
{
var script = ParseAndLog("{\r\nmy-action1\r\n}\r\n{\r\nmy-action2\r\n}");
}
private void AssertAction(ActionDefinition action, string expectedName, params string[] expectedArgs)
{
Assert.AreEqual(expectedName, action.Name, "Expected name");
Assert.AreEqual(expectedArgs.Count(), action.Arguments.Count(), "Expected argument count");
for (int i = 0; i < expectedArgs.Length; i++)
{
Assert.AreEqual(expectedArgs[i], action.Arguments[i]);
}
}
private static ScriptDefinition ParseAndLog(string scriptSource)
{
Trace.Write("Syntax tree:\r\n" + scriptSource.GetSyntaxTree().Describe() + "\r\n\r\n");
var script = scriptSource.Parse();
Trace.Write(script.ToString());
return script;
}
}
}