1 //===- unittests/Analysis/FlowSensitive/DebugSupportTest.cpp --------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "clang/Analysis/FlowSensitive/DebugSupport.h" 10 #include "TestingSupport.h" 11 #include "clang/Analysis/FlowSensitive/Value.h" 12 #include "gmock/gmock.h" 13 #include "gtest/gtest.h" 14 15 namespace { 16 17 using namespace clang; 18 using namespace dataflow; 19 20 using test::ConstraintContext; 21 using testing::StrEq; 22 23 TEST(BoolValueDebugStringTest, AtomicBoolean) { 24 // B0 25 ConstraintContext Ctx; 26 auto B = Ctx.atom(); 27 28 auto Expected = R"(B0)"; 29 debugString(*B); 30 EXPECT_THAT(debugString(*B), StrEq(Expected)); 31 } 32 33 TEST(BoolValueDebugStringTest, Negation) { 34 // !B0 35 ConstraintContext Ctx; 36 auto B = Ctx.neg(Ctx.atom()); 37 38 auto Expected = R"((not 39 B0))"; 40 EXPECT_THAT(debugString(*B), StrEq(Expected)); 41 } 42 43 TEST(BoolValueDebugStringTest, Conjunction) { 44 // B0 ^ B1 45 ConstraintContext Ctx; 46 auto B = Ctx.conj(Ctx.atom(), Ctx.atom()); 47 48 auto Expected = R"((and 49 B0 50 B1))"; 51 EXPECT_THAT(debugString(*B), StrEq(Expected)); 52 } 53 54 TEST(BoolValueDebugStringTest, Disjunction) { 55 // B0 v B1 56 ConstraintContext Ctx; 57 auto B = Ctx.disj(Ctx.atom(), Ctx.atom()); 58 59 auto Expected = R"((or 60 B0 61 B1))"; 62 EXPECT_THAT(debugString(*B), StrEq(Expected)); 63 } 64 65 TEST(BoolValueDebugStringTest, Implication) { 66 // B0 => B1, implemented as !B0 v B1 67 ConstraintContext Ctx; 68 auto B = Ctx.disj(Ctx.neg(Ctx.atom()), Ctx.atom()); 69 70 auto Expected = R"((or 71 (not 72 B0) 73 B1))"; 74 EXPECT_THAT(debugString(*B), StrEq(Expected)); 75 } 76 77 TEST(BoolValueDebugStringTest, Iff) { 78 // B0 <=> B1, implemented as (!B0 v B1) ^ (B0 v !B1) 79 ConstraintContext Ctx; 80 auto B0 = Ctx.atom(); 81 auto B1 = Ctx.atom(); 82 auto B = Ctx.conj(Ctx.disj(Ctx.neg(B0), B1), Ctx.disj(B0, Ctx.neg(B1))); 83 84 auto Expected = R"((and 85 (or 86 (not 87 B0) 88 B1) 89 (or 90 B0 91 (not 92 B1))))"; 93 EXPECT_THAT(debugString(*B), StrEq(Expected)); 94 } 95 96 TEST(BoolValueDebugStringTest, Xor) { 97 // (B0 ^ !B1) V (!B0 ^ B1) 98 ConstraintContext Ctx; 99 auto B0 = Ctx.atom(); 100 auto B1 = Ctx.atom(); 101 auto B = Ctx.disj(Ctx.conj(B0, Ctx.neg(B1)), Ctx.conj(Ctx.neg(B0), B1)); 102 103 auto Expected = R"((or 104 (and 105 B0 106 (not 107 B1)) 108 (and 109 (not 110 B0) 111 B1)))"; 112 EXPECT_THAT(debugString(*B), StrEq(Expected)); 113 } 114 115 TEST(BoolValueDebugStringTest, NestedBoolean) { 116 // B0 ^ (B1 v (B2 ^ (B3 v B4))) 117 ConstraintContext Ctx; 118 auto B = Ctx.conj( 119 Ctx.atom(), 120 Ctx.disj(Ctx.atom(), 121 Ctx.conj(Ctx.atom(), Ctx.disj(Ctx.atom(), Ctx.atom())))); 122 123 auto Expected = R"((and 124 B0 125 (or 126 B1 127 (and 128 B2 129 (or 130 B3 131 B4)))))"; 132 EXPECT_THAT(debugString(*B), StrEq(Expected)); 133 } 134 135 TEST(BoolValueDebugStringTest, AtomicBooleanWithName) { 136 // True 137 ConstraintContext Ctx; 138 auto True = cast<AtomicBoolValue>(Ctx.atom()); 139 auto B = True; 140 141 auto Expected = R"(True)"; 142 EXPECT_THAT(debugString(*B, {{True, "True"}}), StrEq(Expected)); 143 } 144 145 TEST(BoolValueDebugStringTest, ComplexBooleanWithNames) { 146 // (Cond ^ Then ^ !Else) v (!Cond ^ !Then ^ Else) 147 ConstraintContext Ctx; 148 auto Cond = cast<AtomicBoolValue>(Ctx.atom()); 149 auto Then = cast<AtomicBoolValue>(Ctx.atom()); 150 auto Else = cast<AtomicBoolValue>(Ctx.atom()); 151 auto B = Ctx.disj(Ctx.conj(Cond, Ctx.conj(Then, Ctx.neg(Else))), 152 Ctx.conj(Ctx.neg(Cond), Ctx.conj(Ctx.neg(Then), Else))); 153 154 auto Expected = R"((or 155 (and 156 Cond 157 (and 158 Then 159 (not 160 Else))) 161 (and 162 (not 163 Cond) 164 (and 165 (not 166 Then) 167 Else))))"; 168 EXPECT_THAT(debugString(*B, {{Cond, "Cond"}, {Then, "Then"}, {Else, "Else"}}), 169 StrEq(Expected)); 170 } 171 172 TEST(BoolValueDebugStringTest, ComplexBooleanWithSomeNames) { 173 // (False && B0) v (True v B1) 174 ConstraintContext Ctx; 175 auto True = cast<AtomicBoolValue>(Ctx.atom()); 176 auto False = cast<AtomicBoolValue>(Ctx.atom()); 177 auto B = Ctx.disj(Ctx.conj(False, Ctx.atom()), Ctx.disj(True, Ctx.atom())); 178 179 auto Expected = R"((or 180 (and 181 False 182 B0) 183 (or 184 True 185 B1)))"; 186 EXPECT_THAT(debugString(*B, {{True, "True"}, {False, "False"}}), 187 StrEq(Expected)); 188 } 189 190 } // namespace 191