/// <summary> /// Asserts general test properties /// </summary> /// <param name="tests">The enumeration of discovered tests</param> /// <param name="qualifiedName">The qualified test name which is to be tested</param> /// <param name="source">The source from which the test should have been discovered</param> /// <param name="info">Optional source file information related to the test under question</param> private void AssertVSTestCaseProperties(IEnumerable<VSTestCase> tests, QualifiedNameBuilder qualifiedName, string source, SourceFileInfo info) { VSTestCase test = tests.FirstOrDefault((_test) => (_test.FullyQualifiedName == qualifiedName.ToString())); Assert.That(test, Is.Not.Null); Assert.That(test.DisplayName, Is.EqualTo(qualifiedName.Peek())); Assert.That(test.Source, Is.EqualTo(source)); Assert.That(test.ExecutorUri, Is.EqualTo(BoostTestExecutor.ExecutorUri)); if (info != null) { Assert.That(test.CodeFilePath, Is.EqualTo(info.File)); Assert.That(test.LineNumber, Is.EqualTo(info.LineNumber)); } Assert.That(test.Traits.Count(), Is.EqualTo(1)); Trait trait = test.Traits.First(); Assert.That(trait.Name, Is.EqualTo(VSTestModel.TestSuiteTrait)); string suite = qualifiedName.Pop().ToString(); if (string.IsNullOrEmpty(suite)) { suite = qualifiedName.MasterTestSuite; } Assert.That(trait.Value, Is.EqualTo(suite)); }
/// <summary> /// Creates a new TestCase object. /// </summary> /// <param name="sourceExe">Name of the project executable</param> /// <param name="sourceInfo">.cpp file path and TestCase line number</param> /// <param name="suite">The suite in which testcase is present</param> /// <param name="testCaseName">Name of the testcase</param> /// <param name="isEnabled">The enabling status of the testcase</param> /// <returns>The created TestCase object</returns> public static TestCase CreateTestCase(string sourceExe, SourceFileInfo sourceInfo, QualifiedNameBuilder suite, string testCaseName, bool isEnabled = true) { suite.Push(testCaseName); string qualifiedName = suite.ToString(); suite.Pop(); var testCase = new TestCase(qualifiedName, BoostTestExecutor.ExecutorUri, sourceExe) { CodeFilePath = sourceInfo.File, LineNumber = sourceInfo.LineNumber, DisplayName = testCaseName, }; GroupViaTraits(suite.ToString(), testCase, isEnabled); return testCase; }
/// <summary> /// Parse SourceFileInfo from the provided node. /// </summary> /// <param name="node">The Xml node which contains source file information.</param> /// <returns>A SourceFileInfo populated from the provided Xml node.</returns> private static SourceFileInfo ParseSourceInfo(XmlNode node) { SourceFileInfo info = null; XmlAttribute file = node.Attributes[Xml.File]; if (file != null) { info = new SourceFileInfo(file.Value); } if (info != null) { XmlAttribute line = node.Attributes[Xml.Line]; if (line != null) { info.LineNumber = int.Parse(line.Value, CultureInfo.InvariantCulture); } } return info; }
public void ReadXml(XmlReader reader) { base.ReadXmlAttributes(reader); string file = reader.GetAttribute(Xml.File); if (!string.IsNullOrEmpty(file)) { this.Source = new SourceFileInfo(file); this.Source.LineNumber = int.Parse(reader.GetAttribute(Xml.Line), CultureInfo.InvariantCulture); } reader.MoveToElement(); bool empty = reader.IsEmptyElement; reader.ReadStartElement(Xml.TestCase); if (!empty) { reader.ReadEndElement(); } }
/// <summary> /// Discovers Boost Test from the provided C++ source file. Notifies test discovery via the provided discoverySink. /// </summary> /// <param name="cppSourceFile">The C++ source file to scan for Boost Tests</param> /// <param name="source">The associated test source EXE</param> /// <param name="discoverySink">The discoverySink to which identified tests will be notified to</param> private static void DiscoverBoostTests(CppSourceFile cppSourceFile, string source, ITestCaseDiscoverySink discoverySink) { string[] code = cppSourceFile.SourceCode.TrimEnd(new[] { ' ', '\n', '\r' }).Split('\n'); SourceFileInfo sourceInfo = new SourceFileInfo(cppSourceFile.FileName, 0); QualifiedNameBuilder suite = new QualifiedNameBuilder(); // Push the equivalent of the Master Test Suite suite.Push(QualifiedNameBuilder.DefaultMasterTestSuiteName); var templateLists = new Dictionary<string, List<string>>(); for (sourceInfo.LineNumber = 1; sourceInfo.LineNumber <= code.Length; ++sourceInfo.LineNumber) { string line = code[sourceInfo.LineNumber - 1]; string[] splitMacro = SplitMacro(line); string desiredMacro = splitMacro[0].Trim(); // serge: BOOST multiline test macros are supported now /* * Currently the below is not able to handle BOOST UTF signatures spread over multiple lines. */ switch (desiredMacro) { case Constants.TypedefListIdentifier: case Constants.TypedefMplListIdentifier: case Constants.TypedefBoostMplListIdentifier: { var dataTypes = new List<string>(); int i; for (i = 1; i < splitMacro.Length - 2; ++i) { dataTypes.Add(splitMacro[i].Trim()); } templateLists.Add(splitMacro[i].Trim(), dataTypes); break; } case Constants.TestCaseTemplateIdentifier: { int newLineNumber = ScrollLines(sourceInfo.LineNumber, code, ref line); if (sourceInfo.LineNumber != newLineNumber) { // recalc splitMacro splitMacro = SplitMacro(line); sourceInfo.LineNumber = newLineNumber; } string listName = splitMacro[3].Trim(); //third parameter is the corresponding boost::mpl::list name if (templateLists.ContainsKey(listName)) { foreach (var dataType in templateLists[listName]) { string testCaseName = splitMacro[1].Trim(); //first parameter is the test case name string testCaseNameWithDataType = testCaseName + "<" + dataType + ">"; var testCase = TestCaseUtils.CreateTestCase(source, sourceInfo, suite, testCaseNameWithDataType); TestCaseUtils.AddTestCase(testCase, discoverySink); } } break; } case Constants.FixtureTestSuiteIdentifier: case Constants.AutoTestSuiteIdentifier: { int newLineNumber = ScrollLines(sourceInfo.LineNumber, code, ref line); if (sourceInfo.LineNumber != newLineNumber) { // recalc splitMacro splitMacro = SplitMacro(line); sourceInfo.LineNumber = newLineNumber; } suite.Push(splitMacro[1].Trim()); break; } case Constants.FixtureTestCaseIdentifier: case Constants.AutoTestCaseIdentifier: { int newLineNumber = ScrollLines(sourceInfo.LineNumber, code, ref line); if (sourceInfo.LineNumber != newLineNumber) { // recalc splitMacro splitMacro = SplitMacro(line); sourceInfo.LineNumber = newLineNumber; } string testCaseName = splitMacro[1].Trim(); var testCase = TestCaseUtils.CreateTestCase(source, sourceInfo, suite, testCaseName); TestCaseUtils.AddTestCase(testCase, discoverySink); break; } case Constants.AutoTestSuiteEndIdentifier: { suite.Pop(); break; } default: break; } } }
/// <summary> /// Constructor accepting a SourceFileInfo object /// </summary> /// <param name="source">Source file information related to this log message. May be null.</param> public LogEntryMemoryLeak(SourceFileInfo source) : base(source) { }
/// <summary> /// Constructor accepting an exception detail message and a SourceFileInfo object /// </summary> /// <param name="detail">detail message of type string</param> /// <param name="source">Source file information related to this log message. May be null.</param> public LogEntryException(string detail, SourceFileInfo source) : base(source) { this.Detail = detail; }
/// <summary> /// Parses the declaration of a templated test case /// </summary> /// <param name="splitMacro">The current source line split into tokens</param> /// <param name="definedTemplates">A collection of templated lists defined prior to this test case declaration/definition</param> /// <param name="sourceInfo">Source file and line information/param> /// <param name="code">The entire code split by line</param> /// <param name="line">The current source code line which is being evaluated</param> /// <returns>A tuple consisting of the test case name and the list of defined templated types</returns> private static KeyValuePair<string, IEnumerable<string>> ParseTemplateTestCase(string[] splitMacro, Dictionary<string, IEnumerable<string>> definedTemplates, SourceFileInfo sourceInfo, string[] code, ref string line) { splitMacro = ParseTestDeclaration(splitMacro, sourceInfo, code, ref line); //third parameter is the corresponding boost::mpl::list name string listName = splitMacro[3].Trim(); string testCaseName = splitMacro[1].Trim(); IEnumerable<string> templatedDataTypes = Enumerable.Empty<string>(); if (definedTemplates.ContainsKey(listName)) { templatedDataTypes = definedTemplates[listName]; } return new KeyValuePair<string, IEnumerable<string>>(testCaseName, templatedDataTypes); }
/// <summary> /// Builds a new TestSuite. Starts a new context in which /// newly created TestUnits will be parented to this TestSuite. /// </summary> /// <param name="name">Test Suite Name</param> /// <param name="id">Test Suite Id</param> /// <param name="source">Test Suite source file debug information</param> /// <returns>this</returns> public TestFrameworkBuilder TestSuite(string name, int? id, SourceFileInfo source) { return this.TestSuite(name, id, source, true); }
/// <summary> /// Builds a new TestCase. /// </summary> /// <param name="name">Test Case Name</param> /// <param name="id">Test Case Id</param> /// <param name="source">Test Case source file debug information</param> /// <param name="labels">Test Case labels</param> /// <returns>this</returns> public TestFrameworkBuilder TestCase(string name, int? id, SourceFileInfo source, IEnumerable<string> labels) { return this.TestCase(name, id, source, labels, true); }
/// <summary> /// Builds a new TestCase. /// </summary> /// <param name="name">Test Case Name</param> /// <param name="id">Test Case Id</param> /// <param name="source">Test Case source file debug information</param> /// <param name="labels">Test Case labels</param> /// <returns>this</returns> public TestFrameworkBuilder TestCase(string name, int? id, SourceFileInfo source, IEnumerable<string> labels) { TestCase testCase = new TestCase(name, this.Parent); testCase.Id = id; testCase.Source = source; testCase.Labels = labels; return this; }
/// <summary> /// Asserts test case details /// </summary> /// <param name="unit">The test case to test</param> /// <param name="id">The expected Id of the test case</param> /// <param name="info">The expected source file information of the test case</param> /// <param name="parent">The expected parent of the test case</param> private void AssertTestCase(TestUnit unit, int id, SourceFileInfo info, TestUnit parent) { AssertTestUnit(unit, typeof(TestCase), id, parent); TestCase test = ((TestCase) unit); Assert.That(test.Children, Is.Empty); SourceFileInfo unitInfo = test.Source; if (info == null) { Assert.That(unitInfo, Is.Null); } else { Assert.That(unitInfo.File, Is.EqualTo(info.File)); Assert.That(unitInfo.LineNumber, Is.EqualTo(info.LineNumber)); } }
/// <summary> /// Parses the beginning declaration of a fixture or auto test case /// </summary> /// <param name="splitMacro">The current source line split into tokens</param> /// <param name="sourceInfo">Source file and line information/param> /// <param name="code">The entire code split by line</param> /// <param name="line">The current source code line which is being evaluated</param> /// <returns>The name of the test case</returns> private static string ParseTestCase(string[] splitMacro, SourceFileInfo sourceInfo, string[] code, ref string line) { splitMacro = ParseTestDeclaration(splitMacro, sourceInfo, code, ref line); return splitMacro[1].Trim(); }
/// <summary> /// Compares 2 SourceFileInfo for equivalence. Issues an assertion failure if leak information is not equivalent. /// </summary> /// <param name="lhs">The left-hand side SourceFileInfo instance</param> /// <param name="rhs">The right-hand side SourceFileInfo instance</param> private void AssertSourceInfoDetails(SourceFileInfo lhs, SourceFileInfo rhs) { if (lhs == null) { Assert.That(rhs, Is.Null); } else { Assert.That(lhs.File, Is.EqualTo(rhs.File)); Assert.That(lhs.LineNumber, Is.EqualTo(rhs.LineNumber)); } }
/// <summary> /// Tests the provided LogEntryException's properties against the expected values /// </summary> /// <param name="entry">The LogEntryException to test</param> /// <param name="checkpointInfo">The expected source file information for the exception</param> /// <param name="checkpointMessage">The expected checkpoint message</param> private void AssertLogEntryExceptionDetails(LogEntryException entry, SourceFileInfo checkpointInfo, string checkpointMessage) { AssertSourceInfoDetails(checkpointInfo, entry.LastCheckpoint); Assert.That(entry.CheckpointDetail, Is.EqualTo(checkpointMessage)); }
/// <summary> /// Tests the provided LogEntry's general properties against the expected values /// </summary> /// <param name="entry">The LogEntryException to test</param> /// <param name="entryType">The expected log entry type</param> /// <param name="message">The expected log message</param> /// <param name="info">The expected source file information for the log entry</param> private void AssertLogEntryDetails(LogEntry entry, string entryType, string message, SourceFileInfo info) { Assert.That(entry.ToString(), Is.EqualTo(entryType)); Assert.That(entry.Detail, Is.EqualTo(message)); AssertSourceInfoDetails(entry.Source, info); }
/// <summary> /// Constructor accepting a detail message and a SourceFileInfo object /// </summary> /// <param name="detail">detail message of type string</param> /// <param name="source">Source file information related to this log message. May be null.</param> public LogEntryWarning(string detail, SourceFileInfo source) : base(source) { this.Detail = detail; }
/// <summary> /// Constructor accepting a detail message and a SourceFileInfo object /// </summary> /// <param name="detail">detail message of type string</param> /// <param name="source">Source file information related to this log message. May be null.</param> public LogEntryFatalError(string detail, SourceFileInfo source) : base(source) { this.Detail = detail; }
/// <summary> /// Constructor accepting a detail message and a SourceFileInfo object /// </summary> /// <param name="detail">detail message of type string</param> /// <param name="source">Source file information related to this log message. May be null.</param> public LogEntryError(string detail, SourceFileInfo source) : this(detail, source, Enumerable.Empty<string>()) { }
/// <summary> /// Parses the <em>entire</em> test case/suite declaration /// </summary> /// <param name="splitMacro">The current source line split into tokens</param> /// <param name="sourceInfo">Source file and line information/param> /// <param name="code">The entire code split by line</param> /// <param name="line">The current source code line which is being evaluated</param> /// <returns>An array of string components which are of interest for test component evaluation</returns> private static string[] ParseTestDeclaration(string[] splitMacro, SourceFileInfo sourceInfo, string[] code, ref string line) { int newLineNumber = ScrollLines(sourceInfo.LineNumber, code, ref line); if (sourceInfo.LineNumber != newLineNumber) { // re calculate splitMacro splitMacro = SplitMacro(line); sourceInfo.LineNumber = newLineNumber; } return splitMacro; }
/// <summary> /// Constructor accepting a SourceFileInfo /// </summary> /// <param name="source">Source file information related to this log message. May be null.</param> protected LogEntry(SourceFileInfo source) : this() { this.Source = source; }
/// <summary> /// Constructor accepting a detail message, a SourceFileInfo object and error context frames /// </summary> /// <param name="detail">detail message of type string</param> /// <param name="source">Source file information related to this log message. May be null.</param> /// <param name="contextFrames">Error context frame information related to this error message. May be empty.</param> public LogEntryError(string detail, SourceFileInfo source, IEnumerable<string> contextFrames) : base(source) { this.Detail = detail; this.ContextFrames = contextFrames; }
/// <summary> /// Builds a new TestCase. /// </summary> /// <param name="name">Test Case Name</param> /// <param name="id">Test Case Id</param> /// <param name="source">Test Case source file debug information</param> /// <returns>this</returns> public TestFrameworkBuilder TestCase(string name, int? id, SourceFileInfo source) { return this.TestCase(name, id, source, Enumerable.Empty<string>()); }
/// <summary> /// Builds a new TestCase. /// </summary> /// <param name="name">Test Case Name</param> /// <param name="id">Test Case Id</param> /// <param name="source">Test Case source file debug information</param> /// <returns>this</returns> public TestFrameworkBuilder TestCase(string name, int? id, SourceFileInfo source) { TestCase testCase = new TestCase(name, this.Parent); testCase.Id = id; testCase.Source = source; return this; }
/// <summary> /// Builds a new TestCase. /// </summary> /// <param name="name">Test Case Name</param> /// <param name="id">Test Case Id</param> /// <param name="source">Test Case source file debug information</param> /// <param name="labels">Test Case labels</param> /// <param name="enabled">Test Case enabled or disabled</param> /// <returns>this</returns> public TestFrameworkBuilder TestCase(string name, int? id, SourceFileInfo source, IEnumerable<string> labels, bool enabled) { TestCase testCase = new TestCase(name, this.Parent); testCase.Id = id; testCase.Source = source; testCase.Labels = ((labels == null)? Enumerable.Empty<string>() : labels); testCase.DefaultEnabled = enabled; return this; }
/// <summary> /// Verifies that both source file information are equal /// </summary> /// <param name="actual">The actual SourceFileInfo to be compared against</param> /// <param name="expected">The expected SourceFileInfo 'actual' should match</param> private static void VerifySoureFileInfo(SourceFileInfo actual, SourceFileInfo expected) { Assert.That(actual.File, Is.EqualTo(expected.File)); Assert.That(actual.LineNumber, Is.EqualTo(expected.LineNumber)); }
public TestFrameworkBuilder TestSuite(string name, int? id, SourceFileInfo source, bool enabled) { TestSuite testSuite = new TestSuite(name, this.Parent); testSuite.Id = id; testSuite.Source = source; this.Parent = testSuite; testSuite.DefaultEnabled = enabled; return this; }
private static void DiscoverBoostTests(CppSourceFile cppSourceFile, string source, ITestCaseDiscoverySink discoverySink) { string[] code = cppSourceFile.SourceCode.TrimEnd(new[] { ' ', '\n', '\r' }).Split('\n'); SourceFileInfo sourceInfo = new SourceFileInfo(cppSourceFile.FileName, 0); QualifiedNameBuilder suite = new QualifiedNameBuilder(); // Push the equivalent of the Master Test Suite suite.Push(QualifiedNameBuilder.DefaultMasterTestSuiteName); var templateLists = new Dictionary<string, IEnumerable<string>>(); for (sourceInfo.LineNumber = 1; sourceInfo.LineNumber <= code.Length; ++sourceInfo.LineNumber) { string line = code[sourceInfo.LineNumber - 1]; string[] splitMacro = SplitMacro(line); string desiredMacro = splitMacro[0].Trim(); switch (desiredMacro) { case Constants.TypedefListIdentifier: case Constants.TypedefMplListIdentifier: case Constants.TypedefBoostMplListIdentifier: { var templateList = ParseTemplateList(splitMacro); templateLists.Add(templateList.Key, templateList.Value); break; } case Constants.TestCaseTemplateIdentifier: { var templateTest = ParseTemplateTestCase(splitMacro, templateLists, sourceInfo, code, ref line); foreach (string testCaseDataType in templateTest.Value) { string testCaseNameWithDataType = templateTest.Key + '<' + testCaseDataType + '>'; var testCase = TestCaseUtils.CreateTestCase(source, sourceInfo, suite, testCaseNameWithDataType); TestCaseUtils.AddTestCase(testCase, discoverySink); } break; } case Constants.FixtureTestSuiteIdentifier: case Constants.AutoTestSuiteIdentifier: { string suiteName = ParseBeginTestSuite(splitMacro, sourceInfo, code, ref line); suite.Push(suiteName); break; } case Constants.FixtureTestCaseIdentifier: case Constants.AutoTestCaseIdentifier: case Constants.DataTestCaseIdentifier: { string testCaseName = ParseTestCase(splitMacro, sourceInfo, code, ref line); var testCase = TestCaseUtils.CreateTestCase(source, sourceInfo, suite, testCaseName); TestCaseUtils.AddTestCase(testCase, discoverySink); break; } case Constants.FixtureDataTestCaseIdentifier: { string testCaseName = ParseDataTestCaseF(splitMacro, sourceInfo, code, ref line); var testCase = TestCaseUtils.CreateTestCase(source, sourceInfo, suite, testCaseName); TestCaseUtils.AddTestCase(testCase, discoverySink); break; } case Constants.AutoTestSuiteEndIdentifier: { suite.Pop(); break; } default: break; } } }