def test_space_after_hash(self): directive = PreprocessorDirective("# define F", 1) res = SpaceAfterHashDiagnostic.apply(directive) self.assertTrue(res) directive = PreprocessorDirective("#\tdefine F", 1) res = SpaceAfterHashDiagnostic.apply(directive) self.assertTrue(res)
def test_include_guard_detection_ifndef(self): dirs = ( PreprocessorDirective("#ifndef HEADER_GUARD", 1), PreprocessorDirective("#define HEADER_GUARD", 2), PreprocessorDirective("#endif", 3), ) self.assertTrue(sense_for_include_guard(dirs))
def test_incorrectly_annotated_remote_endif(self): dirs = ( PreprocessorDirective("#ifdef A", 1), PreprocessorDirective("#endif incorrect but accepted", 1000), ) res = UnmarkedEndifDiagnostic.apply_to_lines(dirs) self.assertTrue(len(res) == 0)
def test_shallow_ifdef_nesting(self): dirs = ( PreprocessorDirective("#ifdef A", 1), PreprocessorDirective("#endif", 3) ) res = IfdefNestingDiagnostic.apply_to_lines(dirs) self.assertTrue(len(res) == 0)
def test_complex_if_condition_for_complex(self): directive = PreprocessorDirective("#if LINUX || WINDOWS", 1) res = ComplexIfConditionDiagnostic.apply(directive) self.assertTrue(res) directive = PreprocessorDirective("#if !LINUX && WINDOWS", 1) res = ComplexIfConditionDiagnostic.apply(directive) self.assertTrue(res)
def test_unmarked_remote_endif(self): dirs = ( PreprocessorDirective("#ifdef A", 1), PreprocessorDirective("#endif", 1000), ) res = UnmarkedEndifDiagnostic.apply_to_lines(dirs) self.assertTrue(len(res) == 1)
def test_inside_comment(self): # Should not treat the second hash as it is inside a comment directive = PreprocessorDirective(['#endif // #define A'], 1) self.assertFalse(directive.uses_macro_tricks()) directive = PreprocessorDirective(['#endif /* #define B */'], 2) self.assertFalse(directive.uses_macro_tricks())
def test_variadic(self): directive = PreprocessorDirective(['#define PP(x,...) printf(x)'], 1) self.assertTrue(directive.uses_macro_tricks()) # Mangle ellipsis ... so that it will not trigger the match directive = PreprocessorDirective( "#define eprintf(. . .) fprintf (stderr, __VA_ARGS__)", 1) self.assertTrue(directive.uses_macro_tricks())
def test_multiple_unbalanced_ifdefs(self): dirs = ( PreprocessorDirective("#ifdef A", 1), PreprocessorDirective("#ifdef B", 2), PreprocessorDirective("#ifdef C", 3), ) res = UnbalancedIfDiagnostic.apply_to_lines(dirs) self.assertTrue(len(res) == 3)
def test_multiple_unbalanced_endifs(self): dirs = ( PreprocessorDirective("#endif A", 1), PreprocessorDirective("#endif B", 2), PreprocessorDirective("#endif C", 3), ) res = UnbalancedEndifDiagnostic.apply_to_lines(dirs) # Only the first unbalanced #endif is reported self.assertTrue(len(res) == 1)
def test_suggest_inline_function_reject_suggestion(self): directive = PreprocessorDirective("#define MAX_INT 10000", 1) res = SuggestInlineDiagnostic.apply(directive) self.assertFalse(res) directive = PreprocessorDirective("#define A (a)", 1) res = SuggestInlineDiagnostic.apply(directive) self.assertFalse(res) directive = PreprocessorDirective("#define TIMESTAMP() do_nasty_global_stuff", 1) res = SuggestInlineDiagnostic.apply(directive) self.assertFalse(res)
def test_complex_if_condition_for_multiline(self): directive = PreprocessorDirective(["#if LINUX ||\\\n", "WINDOWS"], 1) res = ComplexIfConditionDiagnostic.apply(directive) self.assertIsInstance(res, ComplexIfConditionDiagnostic) directive = PreprocessorDirective( ["#if LINUX_IS_SO_COOL_IT_NEEDS_A_LONG_DEFINE \\\n", "/* This is harmless comment*/"], 1) res = ComplexIfConditionDiagnostic.apply(directive) self.assertFalse(res)
def test_complex_if_condition_for_simple(self): directive = PreprocessorDirective("#if CONDITION", 1) res = ComplexIfConditionDiagnostic.apply(directive) self.assertFalse(res) directive = PreprocessorDirective("#if OS == linux", 1) res = ComplexIfConditionDiagnostic.apply(directive) self.assertFalse(res) directive = PreprocessorDirective("#if !TRUE", 1) res = ComplexIfConditionDiagnostic.apply(directive) self.assertFalse(res)
def test_suggest_void_function_reject(self): directive = PreprocessorDirective("#define F() dobado", 1) res = SuggestVoidDiagnostic.apply(directive) self.assertFalse(res) directive = PreprocessorDirective("#define do something", 1) res = SuggestVoidDiagnostic.apply(directive) self.assertFalse(res) directive = PreprocessorDirective("#pragma random do something", 1) res = SuggestVoidDiagnostic.apply(directive) self.assertFalse(res)
def test_multiline_condition(self): directive = PreprocessorDirective(["#if expr1 \\", "&& second part expression"], 1) res = MultilineConditionalDiagnostic.apply(directive) self.assertIsInstance(res, MultilineConditionalDiagnostic) directive = PreprocessorDirective(["#ifdef \\", "WHY_IS_IT_ON_NEXT_LINE"], 2) res = MultilineConditionalDiagnostic.apply(directive) self.assertFalse(res)
def test_unknown_directive(self): directive = PreprocessorDirective("#unknown I am something unknown", 1) res = UnknownDirectiveDiagnostic.apply(directive) self.assertIsInstance(res, UnknownDirectiveDiagnostic) directive = PreprocessorDirective( "### I am decoration inside comment ###", 1, Context.COMMENT) res = UnknownDirectiveDiagnostic.apply(directive) self.assertIsNone(res)
def test_suggest_better_constant_accept_special(self): directive = PreprocessorDirective("#define A UINT64_C(1)", 1) res = SuggestConstantDiagnostic.apply(directive) self.assertIsInstance(res, SuggestConstantDiagnostic) directive = PreprocessorDirective("#define B BIT(999)", 2) res = SuggestConstantDiagnostic.apply(directive) self.assertIsInstance(res, SuggestConstantDiagnostic) directive = PreprocessorDirective("#define C UINT32_C(~0x1ff)", 1) res = SuggestConstantDiagnostic.apply(directive) self.assertIsInstance(res, SuggestConstantDiagnostic)
def test_suggest_inline_function_give_suggestion(self): directive = PreprocessorDirective("#define MAX(a,b) (a) > (b) ? (a):(b)", 1) res = SuggestInlineDiagnostic.apply(directive) self.assertTrue(res) directive = PreprocessorDirective("#define A( a ) /* nothing */", 1) res = SuggestInlineDiagnostic.apply(directive) self.assertTrue(res) directive = PreprocessorDirective("#define A( a) substitution", 1) res = SuggestInlineDiagnostic.apply(directive) self.assertTrue(res) directive = PreprocessorDirective("#define A(a , b) substitution", 1) res = SuggestInlineDiagnostic.apply(directive) self.assertTrue(res)
def test_suggest_void_function_accept(self): directive = PreprocessorDirective("#define F() do", 1) res = SuggestVoidDiagnostic.apply(directive) self.assertTrue(res) directive = PreprocessorDirective("#define F do", 1) res = SuggestVoidDiagnostic.apply(directive) self.assertTrue(res) directive = PreprocessorDirective("#define F(a,b,c) do", 1) res = SuggestVoidDiagnostic.apply(directive) self.assertTrue(res) directive = PreprocessorDirective("#define F (a, b, c) do", 1) res = SuggestVoidDiagnostic.apply(directive) self.assertTrue(res)
def test_include_guard_detection_missing_defined(self): dirs = ( PreprocessorDirective("#if !defined(HEADER_GUARD)", 1), PreprocessorDirective("#include <header>", 2), PreprocessorDirective("#endif", 3), ) self.assertFalse(sense_for_include_guard(dirs)) dirs = ( PreprocessorDirective("#if !defined(HEADER_GUARD)", 1), PreprocessorDirective("#endif", 3), ) self.assertFalse(sense_for_include_guard(dirs))
def test_suggest_better_constant_reject(self): directive = PreprocessorDirective("#define A", 1) res = SuggestConstantDiagnostic.apply(directive) self.assertFalse(res) directive = PreprocessorDirective("#define B() 1", 1) res = SuggestConstantDiagnostic.apply(directive) self.assertFalse(res) directive = PreprocessorDirective("#define C(x) 1", 1) res = SuggestConstantDiagnostic.apply(directive) self.assertFalse(res) directive = PreprocessorDirective("#ifdef D", 1) res = SuggestConstantDiagnostic.apply(directive) self.assertFalse(res) directive = PreprocessorDirective("#define E 1 + f(x)", 1) res = SuggestConstantDiagnostic.apply(directive) self.assertFalse(res) directive = PreprocessorDirective('#define F 2 - 3', 1) res = SuggestConstantDiagnostic.apply(directive) self.assertFalse(res) directive = PreprocessorDirective('#define G //comment', 1) res = SuggestConstantDiagnostic.apply(directive) self.assertFalse(res) directive = PreprocessorDirective('#define H \\', 1) res = SuggestConstantDiagnostic.apply(directive) self.assertFalse(res)
def test_annotated_remote_endif(self): dirs = ( PreprocessorDirective("#ifdef A", 1), PreprocessorDirective("#endif //A", 1000), ) res = UnmarkedEndifDiagnostic.apply_to_lines(dirs) self.assertTrue(len(res) == 0) dirs = ( PreprocessorDirective("#ifndef A", 1), # TODO the comment should (fuzzily) match #ifndef's condition, # but it is unimplemented PreprocessorDirective("#endif // some unrelated comment", 1000), ) res = UnmarkedEndifDiagnostic.apply_to_lines(dirs) self.assertTrue(len(res) == 0)
def test_suggest_better_constant_reject_too_complex(self): # Too complex to figure out the constant means the diagnostic will not # be reported for the following cases. Ideally, the diagnostic should be # improved to start recognizing at least some of these cases directive = PreprocessorDirective("#define A (400)", 1) res = SuggestConstantDiagnostic.apply(directive) self.assertIsNone(res) directive = PreprocessorDirective("#define B (uint64_t)400", 1) res = SuggestConstantDiagnostic.apply(directive) self.assertIsNone(res) directive = PreprocessorDirective("#define C (1 << 30)", 1) res = SuggestConstantDiagnostic.apply(directive) self.assertIsNone(res) directive = PreprocessorDirective("#define D ~UINT32_C(0x1ff)", 1) res = SuggestConstantDiagnostic.apply(directive) self.assertIsNone(res) directive = PreprocessorDirective("#define E 1234ULL)", 1) res = SuggestConstantDiagnostic.apply(directive) self.assertIsNone(res) directive = PreprocessorDirective("#define F 0777", 1) res = SuggestConstantDiagnostic.apply(directive) self.assertIsNone(res) directive = PreprocessorDirective("#define G 3+4", 1) res = SuggestConstantDiagnostic.apply(directive) self.assertIsNone(res)
def test_full_text_combining(self): directive = PreprocessorDirective(["aa\\", "bb"], 1) ft = directive.full_text self.assertEqual(ft, "aa bb") directive = PreprocessorDirective(["cc\\"], 2) ft = directive.full_text self.assertEqual(ft, "cc") directive = PreprocessorDirective(["dd\\\n", "ee"], 3) ft = directive.full_text self.assertEqual(ft, "dd ee") directive = PreprocessorDirective(["ff\t\\", "gg"], 4) ft = directive.full_text self.assertEqual(ft, "ff\tgg") directive = PreprocessorDirective(["hh", "jj"], 5) ft = directive.full_text self.assertEqual(ft, "hh jj")
def test_suggest_better_constant_accept(self): directive = PreprocessorDirective("#define A 1", 1) res = SuggestConstantDiagnostic.apply(directive) self.assertIsInstance(res, SuggestConstantDiagnostic) directive = PreprocessorDirective("#define B 0xabcd", 1) res = SuggestConstantDiagnostic.apply(directive) self.assertIsInstance(res, SuggestConstantDiagnostic) directive = PreprocessorDirective('#define C "string"', 1) res = SuggestConstantDiagnostic.apply(directive) self.assertIsInstance(res, SuggestConstantDiagnostic) directive = PreprocessorDirective('#define D -5', 1) res = SuggestConstantDiagnostic.apply(directive) self.assertIsInstance(res, SuggestConstantDiagnostic) directive = PreprocessorDirective('#define E "Longer string "', 1) res = SuggestConstantDiagnostic.apply(directive) self.assertIsInstance(res, SuggestConstantDiagnostic)
def test_too_long_define(self): directive = PreprocessorDirective(["#define SYMBOL \\", "one more line\\", "and one more\\", "it goes on and on\\", "I am getting tired\\", "now that is too long"], 1) res = TooLongDefineDiagnostic.apply(directive) self.assertIsInstance(res, TooLongDefineDiagnostic) directive = PreprocessorDirective(["#define SYMBOL \\", "one more line\\", "just not too long"], 2) res = TooLongDefineDiagnostic.apply(directive) self.assertFalse(res) directive = PreprocessorDirective(["#ifdef SYMBOL \\", "this is not a define\\", "why so many lines"], 3) res = TooLongDefineDiagnostic.apply(directive) self.assertFalse(res) # not a #define
def test_include_guard_detection_something_follows_endif(self): dirs = ( PreprocessorDirective("#if !defined(HEADER_GUARD)", 1), PreprocessorDirective("#define HEADER_GUARD", 2), PreprocessorDirective("#endif", 3), PreprocessorDirective("#define EXTRA 2", 10), ) self.assertFalse(sense_for_include_guard(dirs)) dirs = ( PreprocessorDirective("#ifndef HEADER_GUARD", 1), PreprocessorDirective("#define HEADER_GUARD", 2), PreprocessorDirective("#endif", 3), PreprocessorDirective("#define EXTRA 2", 10), ) self.assertFalse(sense_for_include_guard(dirs))
def test_ifdef_nesting_with_several_cplusplus(self): dirs = ( PreprocessorDirective("#ifdef __cplusplus", 1), PreprocessorDirective("#if C == B", 3), PreprocessorDirective("#ifdef D", 4), PreprocessorDirective("#endif // D", 11), PreprocessorDirective("#endif // C == B", 12), PreprocessorDirective("#endif // __cplusplus", 13), PreprocessorDirective("#ifdef __cplusplus", 20), PreprocessorDirective("#endif // second __cplusplus", 24), ) res = IfdefNestingDiagnostic.apply_to_lines(dirs) self.assertTrue(len(res) == 1)
def test_ifdef_nesting_with_header_guards(self): dirs = ( PreprocessorDirective("#ifndef A_H", 1), PreprocessorDirective("#define A_H", 2), PreprocessorDirective("#if C == B", 3), PreprocessorDirective("#ifdef D", 4), PreprocessorDirective("#endif // D", 11), PreprocessorDirective("#endif // C == B", 12), PreprocessorDirective("#endif // A_H", 13), ) res = IfdefNestingDiagnostic.apply_to_lines(dirs) self.assertTrue(len(res) == 0)
def test_include_guard_detection_mismatch_symbol(self): dirs = ( PreprocessorDirective("#ifndef HEADER_GUARD", 1), PreprocessorDirective("#define WRONG_SYMBOL", 2), PreprocessorDirective("#endif", 3), ) self.assertFalse(sense_for_include_guard(dirs)) dirs = ( PreprocessorDirective("#if !defined(HEADER_GUARD)", 1), PreprocessorDirective("#define WRONG_SYMBOL", 2), PreprocessorDirective("#endif", 3), ) self.assertFalse(sense_for_include_guard(dirs))