public void VerifyValidRuleDetection()
        {
            var validRule = new AsaRule("Regular Rule")
            {
                Expression = "0 AND 1",
                Target     = "FileSystemObject",
                Flag       = ANALYSIS_RESULT_TYPE.FATAL,
                Clauses    = new List <Clause>()
                {
                    new Clause("Path", OPERATION.EQ)
                    {
                        Label = "0",
                        Data  = new List <string>()
                        {
                            "TestPath2"
                        }
                    },
                    new Clause("IsExecutable", OPERATION.EQ)
                    {
                        Label = "1",
                        Data  = new List <string>()
                        {
                            "True"
                        }
                    }
                }
            };

            var analyzer = new AsaAnalyzer();

            Assert.IsTrue(analyzer.IsRuleValid(validRule));

            validRule = new AsaRule("Extraneous Parenthesis")
            {
                Expression = "(0 AND 1)",
                Target     = "FileSystemObject",
                Flag       = ANALYSIS_RESULT_TYPE.FATAL,
                Clauses    = new List <Clause>()
                {
                    new Clause("Path", OPERATION.EQ)
                    {
                        Label = "0",
                        Data  = new List <string>()
                        {
                            "TestPath2"
                        }
                    },
                    new Clause("IsExecutable", OPERATION.EQ)
                    {
                        Label = "1",
                        Data  = new List <string>()
                        {
                            "True"
                        }
                    }
                }
            };

            Assert.IsTrue(analyzer.IsRuleValid(validRule));

            validRule = new AsaRule("Deeply Nested Expression")
            {
                Expression = "(0 AND 1) OR (2 XOR (3 AND (4 NAND 5)) OR 6)",
                Target     = "FileSystemObject",
                Flag       = ANALYSIS_RESULT_TYPE.FATAL,
                Clauses    = new List <Clause>()
                {
                    new Clause("Path", OPERATION.EQ)
                    {
                        Label = "0",
                        Data  = new List <string>()
                        {
                            "TestPath2"
                        }
                    },
                    new Clause("IsExecutable", OPERATION.EQ)
                    {
                        Label = "1",
                        Data  = new List <string>()
                        {
                            "True"
                        }
                    },
                    new Clause("IsExecutable", OPERATION.IS_NULL)
                    {
                        Label = "2"
                    },
                    new Clause("IsExecutable", OPERATION.IS_NULL)
                    {
                        Label = "3"
                    },
                    new Clause("IsExecutable", OPERATION.IS_NULL)
                    {
                        Label = "4"
                    },
                    new Clause("IsExecutable", OPERATION.IS_NULL)
                    {
                        Label = "5"
                    },
                    new Clause("IsExecutable", OPERATION.IS_NULL)
                    {
                        Label = "6"
                    }
                }
            };

            Assert.IsTrue(analyzer.IsRuleValid(validRule));

            validRule = new AsaRule("StringsForClauseLabels")
            {
                Expression = "FOO AND BAR OR BA$_*",
                Target     = "FileSystemObject",
                Flag       = ANALYSIS_RESULT_TYPE.FATAL,
                Clauses    = new List <Clause>()
                {
                    new Clause("IsExecutable", OPERATION.IS_NULL)
                    {
                        Label = "FOO"
                    },
                    new Clause("IsExecutable", OPERATION.IS_NULL)
                    {
                        Label = "BAR"
                    },
                    new Clause("IsExecutable", OPERATION.IS_NULL)
                    {
                        Label = "BA$_*"
                    }
                }
            };

            Assert.IsTrue(analyzer.IsRuleValid(validRule));
        }
        public void VerifyCustomRuleValidation()
        {
            var RuleName = "CustomRuleValidation";
            var supportedCustomOperation = new AsaRule(RuleName)
            {
                Target  = "FileSystemObject",
                Flag    = ANALYSIS_RESULT_TYPE.FATAL,
                Clauses = new List <Clause>()
                {
                    new Clause("Path", OPERATION.CUSTOM)
                    {
                        CustomOperation = "FOO",
                        Data            = new List <string>()
                        {
                            TestPathOne
                        }
                    },
                }
            };

            var unsupportedCustomOperation = new AsaRule(RuleName)
            {
                Target  = "FileSystemObject",
                Flag    = ANALYSIS_RESULT_TYPE.FATAL,
                Clauses = new List <Clause>()
                {
                    new Clause("Path", OPERATION.CUSTOM)
                    {
                        CustomOperation = "BAR",
                        Data            = new List <string>()
                        {
                            TestPathOne
                        }
                    },
                }
            };


            var analyzer = new AsaAnalyzer();

            analyzer.CustomOperationValidationDelegate = parseFooOperations;

            IEnumerable <Violation> parseFooOperations(Rule r, Clause c)
            {
                switch (c.CustomOperation)
                {
                case "FOO":
                    if (!c.Data.Any())
                    {
                        yield return(new Violation("FOO Operation expects data", r, c));
                    }
                    break;

                default:
                    yield return(new Violation($"{c.CustomOperation} is unexpected", r, c));

                    break;
                }
            };

            Assert.IsTrue(analyzer.IsRuleValid(supportedCustomOperation));
            Assert.IsFalse(analyzer.IsRuleValid(unsupportedCustomOperation));
        }
        public void VerifyInvalidRuleDetection()
        {
            var invalidRule = new AsaRule("Unbalanced Parentheses")
            {
                Expression = "( 0 AND 1",
                Target     = "FileSystemObject",
                Flag       = ANALYSIS_RESULT_TYPE.FATAL,
                Clauses    = new List <Clause>()
                {
                    new Clause("Path", OPERATION.EQ)
                    {
                        Label = "0",
                        Data  = new List <string>()
                        {
                            "TestPath2"
                        }
                    },
                    new Clause("IsExecutable", OPERATION.EQ)
                    {
                        Label = "1",
                        Data  = new List <string>()
                        {
                            "True"
                        }
                    }
                }
            };
            var analyzer = new AsaAnalyzer();

            Assert.IsFalse(analyzer.IsRuleValid(invalidRule));

            invalidRule = new AsaRule("ClauseInParenthesesLabel")
            {
                Expression = "WITH(PARENTHESIS)",
                Target     = "FileSystemObject",
                Flag       = ANALYSIS_RESULT_TYPE.FATAL,
                Clauses    = new List <Clause>()
                {
                    new Clause("Path", OPERATION.IS_NULL)
                    {
                        Label = "WITH(PARENTHESIS)"
                    }
                }
            };

            Assert.IsFalse(analyzer.IsRuleValid(invalidRule));

            invalidRule = new AsaRule("CharactersBetweenParentheses")
            {
                Expression = "(W(I",
                Target     = "FileSystemObject",
                Flag       = ANALYSIS_RESULT_TYPE.FATAL,
                Clauses    = new List <Clause>()
                {
                    new Clause("Path", OPERATION.IS_NULL)
                    {
                        Label = "W(I"
                    }
                }
            };

            Assert.IsFalse(analyzer.IsRuleValid(invalidRule));

            invalidRule = new AsaRule("CharactersBeforeOpenParentheses")
            {
                Expression = "W(I",
                Target     = "FileSystemObject",
                Flag       = ANALYSIS_RESULT_TYPE.FATAL,
                Clauses    = new List <Clause>()
                {
                    new Clause("Path", OPERATION.IS_NULL)
                    {
                        Label = "W(I"
                    }
                }
            };

            Assert.IsFalse(analyzer.IsRuleValid(invalidRule));

            invalidRule = new AsaRule("CharactersBetweenClosedParentheses")
            {
                Expression = "(0 AND W)I)",
                Target     = "FileSystemObject",
                Flag       = ANALYSIS_RESULT_TYPE.FATAL,
                Clauses    = new List <Clause>()
                {
                    new Clause("Path", OPERATION.IS_NULL)
                    {
                        Label = "W)I"
                    },
                    new Clause("Path", OPERATION.IS_NULL)
                    {
                        Label = "0"
                    }
                }
            };

            Assert.IsFalse(analyzer.IsRuleValid(invalidRule));

            invalidRule = new AsaRule("CharactersAfterClosedParentheses")
            {
                Expression = "0 AND W)I",
                Target     = "FileSystemObject",
                Flag       = ANALYSIS_RESULT_TYPE.FATAL,
                Clauses    = new List <Clause>()
                {
                    new Clause("Path", OPERATION.IS_NULL)
                    {
                        Label = "W)I"
                    },
                    new Clause("Path", OPERATION.IS_NULL)
                    {
                        Label = "0"
                    }
                }
            };

            Assert.IsFalse(analyzer.IsRuleValid(invalidRule));

            invalidRule = new AsaRule("MultipleConsecutiveNots")
            {
                Expression = "0 AND NOT NOT 1",
                Target     = "FileSystemObject",
                Flag       = ANALYSIS_RESULT_TYPE.FATAL,
                Clauses    = new List <Clause>()
                {
                    new Clause("Path", OPERATION.IS_NULL)
                    {
                        Label = "1"
                    },
                    new Clause("Path", OPERATION.IS_NULL)
                    {
                        Label = "0"
                    }
                }
            };

            Assert.IsFalse(analyzer.IsRuleValid(invalidRule));

            invalidRule = new AsaRule("CloseParenthesesWithNot")
            {
                Expression = "(0 AND NOT) 1",
                Target     = "FileSystemObject",
                Flag       = ANALYSIS_RESULT_TYPE.FATAL,
                Clauses    = new List <Clause>()
                {
                    new Clause("Path", OPERATION.IS_NULL)
                    {
                        Label = "1"
                    },
                    new Clause("Path", OPERATION.IS_NULL)
                    {
                        Label = "0"
                    }
                }
            };

            Assert.IsFalse(analyzer.IsRuleValid(invalidRule));

            invalidRule = new AsaRule("WhiteSpaceLabel")
            {
                Expression = "0 AND   ",
                Target     = "FileSystemObject",
                Flag       = ANALYSIS_RESULT_TYPE.FATAL,
                Clauses    = new List <Clause>()
                {
                    new Clause("Path", OPERATION.IS_NULL)
                    {
                        Label = "0"
                    }
                }
            };

            Assert.IsFalse(analyzer.IsRuleValid(invalidRule));

            invalidRule = new AsaRule("InvalidOperator")
            {
                Expression = "0 XAND 1",
                Target     = "FileSystemObject",
                Flag       = ANALYSIS_RESULT_TYPE.FATAL,
                Clauses    = new List <Clause>()
                {
                    new Clause("Path", OPERATION.IS_NULL)
                    {
                        Label = "1"
                    },
                    new Clause("Path", OPERATION.IS_NULL)
                    {
                        Label = "0"
                    }
                }
            };

            Assert.IsFalse(analyzer.IsRuleValid(invalidRule));

            invalidRule = new AsaRule("InvalidNotOperator")
            {
                Expression = "0 NOT AND 1",
                Target     = "FileSystemObject",
                Flag       = ANALYSIS_RESULT_TYPE.FATAL,
                Clauses    = new List <Clause>()
                {
                    new Clause("Path", OPERATION.IS_NULL)
                    {
                        Label = "1"
                    },
                    new Clause("Path", OPERATION.IS_NULL)
                    {
                        Label = "0"
                    }
                }
            };

            Assert.IsFalse(analyzer.IsRuleValid(invalidRule));

            invalidRule = new AsaRule("EndsWithOperator")
            {
                Expression = "0 AND",
                Target     = "FileSystemObject",
                Flag       = ANALYSIS_RESULT_TYPE.FATAL,
                Clauses    = new List <Clause>()
                {
                    new Clause("Path", OPERATION.IS_NULL)
                    {
                        Label = "0"
                    }
                }
            };

            Assert.IsFalse(analyzer.IsRuleValid(invalidRule));

            invalidRule = new AsaRule("UnusedLabel")
            {
                Expression = "0",
                Target     = "FileSystemObject",
                Flag       = ANALYSIS_RESULT_TYPE.FATAL,
                Clauses    = new List <Clause>()
                {
                    new Clause("Path", OPERATION.IS_NULL)
                    {
                        Label = "1"
                    },
                    new Clause("Path", OPERATION.IS_NULL)
                    {
                        Label = "0"
                    }
                }
            };

            Assert.IsFalse(analyzer.IsRuleValid(invalidRule));

            invalidRule = new AsaRule("MissingLabel")
            {
                Target  = "FileSystemObject",
                Flag    = ANALYSIS_RESULT_TYPE.FATAL,
                Clauses = new List <Clause>()
                {
                    new Clause("Path", OPERATION.IS_NULL)
                    {
                        Label = "0"
                    },
                    new Clause("Path", OPERATION.IS_NULL)
                }
            };

            Assert.IsFalse(analyzer.IsRuleValid(invalidRule));

            invalidRule = new AsaRule("ExpressionRequiresLabels")
            {
                Expression = "0 AND 1",
                Target     = "FileSystemObject",
                Flag       = ANALYSIS_RESULT_TYPE.FATAL,
                Clauses    = new List <Clause>()
                {
                    new Clause("Path", OPERATION.IS_NULL),
                    new Clause("Path", OPERATION.IS_NULL)
                }
            };

            Assert.IsFalse(analyzer.IsRuleValid(invalidRule));

            invalidRule = new AsaRule("OutOfOrder")
            {
                Expression = "0 1 AND",
                Target     = "FileSystemObject",
                Flag       = ANALYSIS_RESULT_TYPE.FATAL,
                Clauses    = new List <Clause>()
                {
                    new Clause("Path", OPERATION.EQ)
                    {
                        Label = "0",
                        Data  = new List <string>()
                        {
                            "TestPath2"
                        }
                    },
                    new Clause("IsExecutable", OPERATION.IS_TRUE)
                    {
                        Label = "1"
                    }
                }
            };

            Assert.IsFalse(analyzer.IsRuleValid(invalidRule));

            invalidRule = new AsaRule("StartWithOperator")
            {
                Expression = "OR 0 1",
                Target     = "FileSystemObject",
                Flag       = ANALYSIS_RESULT_TYPE.FATAL,
                Clauses    = new List <Clause>()
                {
                    new Clause("Path", OPERATION.EQ)
                    {
                        Label = "0",
                        Data  = new List <string>()
                        {
                            "TestPath2"
                        }
                    },
                    new Clause("IsExecutable", OPERATION.EQ)
                    {
                        Label = "1",
                        Data  = new List <string>()
                        {
                            "True"
                        }
                    }
                }
            };

            Assert.IsFalse(analyzer.IsRuleValid(invalidRule));

            invalidRule = new AsaRule("Case Sensitivity")
            {
                Expression = "Variable",
                Target     = "FileSystemObject",
                Flag       = ANALYSIS_RESULT_TYPE.FATAL,
                Clauses    = new List <Clause>()
                {
                    new Clause("Path", OPERATION.IS_NULL)
                    {
                        Label = "VARIABLE"
                    }
                }
            };

            Assert.IsFalse(analyzer.IsRuleValid(invalidRule));

            invalidRule = new AsaRule("OPERATION.Custom without CustomOperation")
            {
                Target  = "FileSystemObject",
                Flag    = ANALYSIS_RESULT_TYPE.FATAL,
                Clauses = new List <Clause>()
                {
                    new Clause("Path", OPERATION.CUSTOM)
                    {
                        Label = "VARIABLE"
                    }
                }
            };

            Assert.IsFalse(analyzer.IsRuleValid(invalidRule));
        }