diff --git a/src/TestLogger/Core/TestCaseNameParser.cs b/src/TestLogger/Core/TestCaseNameParser.cs index 46bbf57..fdcc173 100644 --- a/src/TestLogger/Core/TestCaseNameParser.cs +++ b/src/TestLogger/Core/TestCaseNameParser.cs @@ -26,7 +26,8 @@ private enum NameParseState { Default, Parenthesis, - String + String, + Char, } /// @@ -85,6 +86,10 @@ public static ParsedName Parse(string fullyQualifiedName) { throw new Exception("Found invalid characters"); } + else if (thisChar == '\'') + { + throw new Exception("Found invalid characters"); + } else if (thisChar == ')') { if ((output.Count > 0) && (parenthesisCount == 0)) @@ -137,8 +142,7 @@ public static ParsedName Parse(string fullyQualifiedName) { parenthesisCount++; } - - if (thisChar == '(') + else if (thisChar == '(') { // If we found the beginning of the parenthesis block, we are back in // default state @@ -150,12 +154,14 @@ public static ParsedName Parse(string fullyQualifiedName) // an issue, so we are 'entering' string state, because of the reverse parsing. state = NameParseState.String; } + else if (thisChar == '\'') + { + state |= NameParseState.Char; + } output.Insert(0, thisChar); } - - // state == NameParseState.String - else + else if (state == NameParseState.String) { if (thisChar == '"' && fullyQualifiedName.ElementAtOrDefault(i - 1) != '\\') { @@ -164,6 +170,17 @@ public static ParsedName Parse(string fullyQualifiedName) state = NameParseState.Parenthesis; } + output.Insert(0, thisChar); + } + else if (state == NameParseState.Char) + { + if (thisChar == '\'' && fullyQualifiedName.ElementAtOrDefault(i - 1) != '\\') + { + // If this is a single quote that has not been escaped, switch the state. If it + // had been escaped, we would still be in a char. + state = NameParseState.Parenthesis; + } + output.Insert(0, thisChar); } } diff --git a/test/TestLogger.UnitTests/TestCaseNameParserTests.cs b/test/TestLogger.UnitTests/TestCaseNameParserTests.cs index 3bfa2f5..44dce9b 100644 --- a/test/TestLogger.UnitTests/TestCaseNameParserTests.cs +++ b/test/TestLogger.UnitTests/TestCaseNameParserTests.cs @@ -36,6 +36,15 @@ public class TestCaseNameParserTests [DataRow("z.a.b((\"arg\",1))", "z", "a", "b((\"arg\",1))")] [DataRow("z.a.b((0,1),(2,3))", "z", "a", "b((0,1),(2,3))")] [DataRow("z.a.b((0,(0,1)),(0,1))", "z", "a", "b((0,(0,1)),(0,1))")] + + // See nunit.testlogger #90 + [DataRow("z.y.x.ape.bar('A',False)", "z.y.x", "ape", "bar('A',False)")] + [DataRow("z.y.x.ape.bar('\"',False)", "z.y.x", "ape", "bar('\"',False)")] + [DataRow("z.y.x.ape.bar('(',False)", "z.y.x", "ape", "bar('(',False)")] + [DataRow("z.y.x.ape.bar(')',False)", "z.y.x", "ape", "bar(')',False)")] + [DataRow("z.y.x.ape.bar('.',False)", "z.y.x", "ape", "bar('.',False)")] + [DataRow("z.y.x.ape.bar('\\'',False)", "z.y.x", "ape", "bar('\\'',False)")] + [DataRow("z.y.x.ape.bar('\\\\',False)", "z.y.x", "ape", "bar('\\\\',False)")] public void Parse_ParsesAllParseableInputs_WithoutConsoleOutput(string testCaseName, string expectedNamespace, string expectedType, string expectedMethod) { using (var sw = new StringWriter()) @@ -94,6 +103,8 @@ public void Parse_ParsesAllParseableInputsWithoutNamespace_WithConsoleOutput(str [DataRow("z.y.X\\x")] [DataRow("z.y.x\\")] [DataRow("z.y.X\\)")] + [DataRow("z.y.X\')")] + [DataRow("z.y.\'x")] [DataRow("z.y.x))")] [DataRow("z.y.x()x")] [DataRow("z.y.x.")] @@ -126,4 +137,4 @@ public void Parse_FailsGracefullyOnNonParseableInputs_WithConsoleOutput(string t } } } -} \ No newline at end of file +}