/// <summary> /// Copy constructor /// </summary> /// <param name="previousDefine">Defines instance to be copied</param> public Defines(Defines previousDefine) { if (previousDefine == null) throw new ArgumentNullException("previousDefine"); SubstitutionTokens = new Dictionary<string, object>(previousDefine.SubstitutionTokens); NonSubstitutionTokens = new HashSet<string>(previousDefine.NonSubstitutionTokens); }
public void ConditionalInclusionsComplexExpressionEvaluationFail() { #region setup var definesHandler = new Defines(); //no defines supplied var filter = new ConditionalInclusionsFilter(new ExpressionEvaluation()); const string nameSpace = "BoostTestAdapterNunit.Resources.SourceFiltering."; const string unfilteredSourceCodeResourceName = "ConditionalInclusionsComplexEvaluationFail.cpp"; string sourceCodeOriginal = TestHelper.ReadEmbeddedResource(nameSpace + unfilteredSourceCodeResourceName); string sourceCodeExpected = sourceCodeOriginal; var cppSourceFile = new CppSourceFile() { FileName = nameSpace + unfilteredSourceCodeResourceName, SourceCode = sourceCodeOriginal }; #endregion #region excercise filter.Filter(cppSourceFile, definesHandler); #endregion #region verify Assert.AreEqual(sourceCodeExpected, cppSourceFile.SourceCode); //no filtering should be done due to inability to evaluate an expression #endregion }
/// <summary> /// Given 2 strings, filters the left-hand string and checks whether the filtered output matches that of the right-hand string. /// </summary> /// <param name="filter">The source filter to apply</param> /// <param name="defines">The preprocessor definitions which are to be used by the source filter</param> /// <param name="lhs">The left-hand string whose value will be filtered</param> /// <param name="rhs">The right-hand string whose value is used to compare the filtered result</param> protected void FilterAndCompare(ISourceFilter filter, Defines defines, string lhs, string rhs) { var cppSourceFile = new CppSourceFile(){SourceCode = lhs}; filter.Filter(cppSourceFile, defines); Assert.AreEqual(cppSourceFile.SourceCode, rhs); }
private void ApplySourceFilter(CppSourceFile cppSourceFile, Defines definesHandler) { foreach( var filter in _sourceFilters ) { filter.Filter(cppSourceFile, definesHandler); } }
/// <summary> /// Applies the quoted strings filter action on the supplied sourceCode string /// </summary> /// <param name="cppSourceFile">CppSourceFile object containing the source file information</param> /// <param name="definesHandler">not used for this filter</param> public void Filter(CppSourceFile cppSourceFile, Defines definesHandler) { /* * It is important not to the change order of the filters. */ cppSourceFile.SourceCode = stringLiteralsRegex.Replace(cppSourceFile.SourceCode, new MatchEvaluator(ComputeReplacement)); cppSourceFile.SourceCode = quotedStringsRegex.Replace(cppSourceFile.SourceCode, ""); }
/// <summary> /// Given 2 embedded resources locations, filters the left-hand resource and checks whether the filtered output matches that of the right-hand resource. /// </summary> /// <param name="filter">The source filter to apply</param> /// <param name="defines">The preprocessor definitions which are to be used by the source filter</param> /// <param name="lhsEmbeddedResource">The left-hand embedded resource fully qualified location whose content will be filtered</param> /// <param name="rhsEmbeddedResource">The right-hand embedded resource fully qualified location whose content is used to compare the filtered result</param> protected void FilterAndCompareResources(ISourceFilter filter, Defines defines, string lhsEmbeddedResource, string rhsEmbeddedResource) { FilterAndCompare( filter, defines, TestHelper.ReadEmbeddedResource(lhsEmbeddedResource), TestHelper.ReadEmbeddedResource(rhsEmbeddedResource) ); }
/// <summary> /// Given a parameter list of strings, generates a Defines structure /// where pairs of strings are treated as a definition and its value. /// </summary> /// <param name="definitions">The string pair definitions array from which to generate the Defines structue</param> /// <returns>A Defines structure built out of string pairs available in the definitions array</returns> private Defines GenerateDefines(string[] definitions) { Assert.That(definitions.Length % 2, Is.EqualTo(0)); Defines definesHandler = new Defines(); for (int i = 1; i < definitions.Length; i += 2) { definesHandler.Define(definitions[i - 1], definitions[i]); } return definesHandler; }
public void ConditionalInclusionsIfTests() { #region setup var definesHandler = new Defines(); definesHandler.Define("DEBUG", ""); definesHandler.Define("NDEBUG", ""); definesHandler.Define("DEBUGGER", ""); var expectedPreprocessorDefines = new HashSet<string>() { "DEBUG", "NDEBUG", "DEBUGGER", "DLEVEL" }; var filter = new ConditionalInclusionsFilter( new ExpressionEvaluation() ); const string nameSpace = "BoostTestAdapterNunit.Resources.SourceFiltering."; const string unfilteredSourceCodeResourceName = "ConditionalInclusionsIfTests_UnFilteredSourceCode.cpp"; const string filteredSourceCodeResourceName = "ConditionalInclusionsIfTests_FilteredSourceCode.cpp"; string sourceCodeOriginal = TestHelper.ReadEmbeddedResource(nameSpace + unfilteredSourceCodeResourceName); string sourceCodeExpected = TestHelper.ReadEmbeddedResource(nameSpace + filteredSourceCodeResourceName); var cppSourceFile = new CppSourceFile() { FileName = nameSpace + unfilteredSourceCodeResourceName, SourceCode = sourceCodeOriginal }; #endregion #region excercise filter.Filter(cppSourceFile, definesHandler); #endregion #region verify Assert.AreEqual(sourceCodeExpected, cppSourceFile.SourceCode); Assert.AreEqual(expectedPreprocessorDefines, definesHandler.NonSubstitutionTokens); Assert.AreEqual(0, definesHandler.SubstitutionTokens.Count); #endregion }
/// <summary> /// Evaluates an expression /// </summary> /// <param name="expression">expression to be evaluated</param> /// <param name="definesHandler">reference to the defines handler </param> /// <returns></returns> public EvaluationResult EvaluateExpression(string expression, Defines definesHandler) { this._definesHandler = definesHandler; Expression e = new Expression(expression, EvaluateOptions.NoCache); e.EvaluateParameter += EvaluateParam; e.EvaluateFunction += EvaluateFunction; EvaluationResult evaluationResult = EvaluationResult.UnDetermined; try { object result = e.Evaluate(); evaluationResult = Convert.ToBoolean(result, CultureInfo.InvariantCulture) ? EvaluationResult.IsTrue : EvaluationResult.IsFalse; } catch { evaluationResult = EvaluationResult.UnDetermined; } return evaluationResult; }
// (/\*(?:.+?)\*/) // // Options: Case insensitive; Exact spacing; Dot matches line breaks; ^$ don't match at line breaks; Numbered capture // // Match the regex below and capture its match into backreference number 1 «(/\*(?:.+?)\*/)» // Match the character “/” literally «/» // Match the character “*” literally «\*» // Match the regular expression below «(?:.+?)» // Match any single character «.+?» // Between one and unlimited times, as few times as possible, expanding as needed (lazy) «+?» // Match the character “*” literally «\*» // Match the character “/” literally «/» #region ISourceFilter /// <summary> /// Filters any multiline comments from the source code. /// </summary> /// <param name="cppSourceFile">CppSourceFile object containing the source file information</param> /// <param name="definesHandler">not used for this filter</param> public void Filter(CppSourceFile cppSourceFile, Defines definesHandler) { Utility.Code.Require(cppSourceFile, "cppSourceFile"); cppSourceFile.SourceCode = multiLineCommentRegex.Replace(cppSourceFile.SourceCode, ComputeMultiLineCommentReplacement); }
private void GetBoostTests(IDictionary<string, ProjectInfo> solutionInfo, ITestCaseDiscoverySink discoverySink) { if (solutionInfo != null) { foreach (KeyValuePair<string, ProjectInfo> info in solutionInfo) { string source = info.Key; ProjectInfo projectInfo = info.Value; foreach (var sourceFile in projectInfo.CppSourceFiles) { try { using (var sr = new StreamReader(sourceFile)) { try { var cppSourceFile = new CppSourceFile() { FileName = sourceFile, SourceCode = sr.ReadToEnd() }; // Filter out any false positives and quickly reject files which do not contain any Boost Unit Test eye-catchers if ( ShouldConsiderSourceFile(cppSourceFile.SourceCode) ) { /* * it is important that the pre-processor defines at project level are not modified * because every source file in the project has to have the same starting point. */ //call to cpy ctor Defines definitions = new Defines(projectInfo.DefinesHandler); ApplySourceFilter(cppSourceFile, definitions); DiscoverBoostTests(cppSourceFile, source, discoverySink); } } catch (Exception ex) { Logger.Error( "Exception raised while discovering tests from \"{0}\" of project \"{1}\", ({2})", sourceFile, projectInfo.ProjectExe, ex.Message); Logger.Error(ex.StackTrace); } } } catch { Logger.Error("Unable to open file \"{0}\" of project \"{1}\".", sourceFile, projectInfo.ProjectExe); } } } } else { Logger.Error("the solutionInfo object was found to be null whilst"); } }
/// <summary> /// Filters any single line comments from the source code /// </summary> /// <param name="cppSourceFile">CppSourceFile object containing the source file information</param> /// <param name="definesHandler">not used for this filter</param> public void Filter(CppSourceFile cppSourceFile, Defines definesHandler) { Utility.Code.Require(cppSourceFile, "cppSourceFile"); cppSourceFile.SourceCode = singleLineCommentRegex.Replace(cppSourceFile.SourceCode, ""); }
/// <summary> /// Identifies the project's configured preprocessor definitions /// </summary> /// <param name="definitions">The preprocessor definitions in use by this project</param> /// <returns>this</returns> public FakeProjectBuilder Defines(Defines definitions) { this._definitions = definitions; return this; }
/// <summary> /// Filters any multiline comments from the source code. /// </summary> /// <param name="cppSourceFile">CppSourceFile object containing the source file information</param> /// <param name="definesHandler">not used for this filter</param> public void Filter(CppSourceFile cppSourceFile, Defines definesHandler) { cppSourceFile.SourceCode = multiLineCommentRegex.Replace(cppSourceFile.SourceCode, ComputeMultiLineCommentReplacement); }
//Options: Case insensitive; Exact spacing; Dot matches line breaks; ^$ don't match at line breaks; Numbered capture // //Match the regex below and capture its match into backreference number 1 «(\r\n?|\n)» // Match this alternative (attempting the next alternative only if this one fails) «\r\n?» // Match the carriage return character «\r» // Match the line feed character «\n?» // Between zero and one times, as many times as possible, giving back as needed (greedy) «?» // Or match this alternative (the entire group fails if this one fails to match) «\n» // Match the line feed character «\n» #region ISourceFilter /// <summary> /// Applies the quoted strings filter action on the supplied sourceCode string /// </summary> /// <param name="cppSourceFile">CppSourceFile object containing the source file information</param> /// <param name="definesHandler">not used for this filter</param> public void Filter(CppSourceFile cppSourceFile, Defines definesHandler) { Utility.Code.Require(cppSourceFile, "cppSourceFile"); cppSourceFile.SourceCode = stringLiteralsRegex.Replace(cppSourceFile.SourceCode, ComputeReplacement); }
public void Apply(CppSourceFile cppSourceFile, Defines definesHandler) { Utility.Code.Require(cppSourceFile, "cppSourceFile"); DefinesHandler = definesHandler; string[] sourceLines = LinefeedRegex.Split(cppSourceFile.SourceCode); _parserState.Clear(); AddState(ParserState.NormalState); //initial state SourceLineType sourceLineType; string expression; string subtitutionText; int lineNumber = 0; try { for (; lineNumber < sourceLines.Length; lineNumber++) { Inspect(sourceLines[lineNumber], out sourceLineType, out expression, out subtitutionText); _conditionalInclusionsMachineState.Process(ref sourceLines[lineNumber], sourceLineType, expression, subtitutionText); } /* * Once the parsing is complete we just check that the parserState is back to Normal State. * If not it is either because we parsed bad code (i.e. the code structure was not consistent to start with) * or we've got a problem (programmatically) with our state engine */ //sanity check if (_parserState.Peek() != ParserState.NormalState) { Logger.Error("The conditionals filter state machine failed to return to normal state. The source file \"{0}\" will not be filtered for conditionals.", cppSourceFile.FileName); //the source code for the specific file is left unfiltered in case the state machine did not return to a normal state. } else { //State machine returned to normal state so we can apply the filtering done by the conditional inclusions machine cppSourceFile.SourceCode = string.Join(Environment.NewLine, sourceLines); } } catch (Exception ex) { Logger.Error( "The conditionals filter encountered error: {0} whilst processing line number {1} of source file \"{2}\". The source file will not be filtered for conditionals", ex.Message, lineNumber + 1, cppSourceFile.FileName); } }
public void ConditionalInclusionsComplexExpressionEvaluationSuccess() { #region setup var definesHandler = new Defines(); var expectedNonSubstitutionTokens = new HashSet<string>() { "VERSION", "HALF", "THIRD", "DEBUG", "SIN", "MAX", "CUBE", "fPRINT", "ASSERT", }; var expectedSubtitutionTokens = new Dictionary<string, object>() { {"LEVEL", "19"}, {"EVER", ";;"}, {"BIG", "(512)"}, {"PRINT", "cout << #x"}, }; var filter = new ConditionalInclusionsFilter(new ExpressionEvaluation()); const string nameSpace = "BoostTestAdapterNunit.Resources.SourceFiltering."; const string unfilteredSourceCodeResourceName = "ConditionalInclusionsComplexEvaluationSuccess_UnfilteredSourceCode.cpp"; const string filteredSourceCodeResourceName = "ConditionalInclusionsComplexEvaluationSuccess_FilteredSourceCode.cpp"; string sourceCodeOriginal = TestHelper.ReadEmbeddedResource(nameSpace + unfilteredSourceCodeResourceName); string sourceCodeExpected = TestHelper.ReadEmbeddedResource(nameSpace + filteredSourceCodeResourceName); var cppSourceFile = new CppSourceFile() { FileName = nameSpace + unfilteredSourceCodeResourceName, SourceCode = sourceCodeOriginal }; #endregion #region excercise filter.Filter(cppSourceFile, definesHandler); #endregion #region verify Assert.AreEqual(sourceCodeExpected, cppSourceFile.SourceCode); Assert.AreEqual(expectedNonSubstitutionTokens, definesHandler.NonSubstitutionTokens); Assert.AreEqual(expectedSubtitutionTokens, definesHandler.SubstitutionTokens); #endregion }
/// <summary> /// Filters any single line comments from the source code /// </summary> /// <param name="cppSourceFile">CppSourceFile object containing the source file information</param> /// <param name="definesHandler">not used for this filter</param> public void Filter(CppSourceFile cppSourceFile, Defines definesHandler) { cppSourceFile.SourceCode = singleLineCommentRegex.Replace(cppSourceFile.SourceCode, ""); }
/// <summary> /// Applies the filter action onto the source code /// </summary> /// <param name="cppSourceFile">source file information</param> /// <param name="definesHandler">pre-processor defines</param> public void Filter(CppSourceFile cppSourceFile, Defines definesHandler) { _conditionalInclusionsMachine.Apply(cppSourceFile, definesHandler); }
/// <summary> /// Acquires the pre-processor definitions used by the project /// </summary> /// <param name="projectInfo">The Visual Studio project</param> /// <returns>The pre-processor definitions specified within the project</returns> private static Defines GetDefines(ProjectInfo projectInfo) { /* * it is important that the pre-processor defines at project level are not modified * because every source file in the project has to have the same starting point. */ //call to cpy ctor Defines defines = new Defines(projectInfo.DefinesHandler); // Additional Boost definitions // NOTE These definitions are generally assumed to be available since // we are operating in a BOOST Test context if (!defines.IsDefined("BOOST_VERSION")) { defines.Define("BOOST_VERSION", "0"); } return defines; }