1 /* Copyright (c) 2008-2010, Google Inc. 2 * All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Neither the name of Google Inc. nor the names of its 11 * contributors may be used to endorse or promote products derived from 12 * this software without specific prior written permission. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 15 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 16 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 17 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 18 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 19 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 20 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27 // This file is part of ThreadSanitizer, a dynamic data race detector. 28 // Author: Evgeniy Stepanov. 29 30 // This file contains tests for suppressions implementation. 31 32 #include <gtest/gtest.h> 33 34 #include "suppressions.h" 35 36 #define VEC(arr) *(new vector<string>(arr, arr + sizeof(arr) / sizeof(*arr))) 37 38 class BaseSuppressionsTest : public ::testing::Test { 39 protected: 40 bool IsSuppressed(string tool, string warning_type, const vector<string>& f_m, 41 const vector<string>& f_d, const vector<string>& o) { 42 string result; 43 return supp_.StackTraceSuppressed( 44 tool, warning_type, f_m, f_d, o, &result); 45 } 46 47 bool IsSuppressed(const vector<string>& f_m, const vector<string>& f_d, 48 const vector<string>& o) { 49 return IsSuppressed("test_tool", "test_warning_type", f_m, f_d, o); 50 } 51 52 Suppressions supp_; 53 }; 54 55 class SuppressionsTest : public BaseSuppressionsTest { 56 protected: 57 virtual void SetUp() { 58 const string data = 59 "{\n" 60 " name\n" 61 " test_tool,tool2:test_warning_type\n" 62 " fun:function1\n" 63 " obj:object1\n" 64 " fun:function2\n" 65 "}"; 66 supp_.ReadFromString(data); 67 } 68 }; 69 70 71 TEST_F(SuppressionsTest, Simple) { 72 string m[] = {"aa", "bb", "cc"}; 73 string d[] = {"aaa", "bbb", "ccc"}; 74 string o[] = {"object1", "object2", "object3"}; 75 ASSERT_FALSE(IsSuppressed(VEC(m), VEC(d), VEC(o))); 76 } 77 78 TEST_F(SuppressionsTest, Simple2) { 79 string m[] = {"function1", "bb", "function2"}; 80 string d[] = {"aaa", "bbb", "ccc"}; 81 string o[] = {"object2", "object1", "object3"}; 82 ASSERT_TRUE(IsSuppressed(VEC(m), VEC(d), VEC(o))); 83 } 84 85 // A long stack trace is ok. 86 TEST_F(SuppressionsTest, LongTrace) { 87 string m[] = {"function1", "bb", "function2", "zz"}; 88 string d[] = {"aaa", "bbb", "ccc", "zzz"}; 89 string o[] = {"object2", "object1", "object3", "o4"}; 90 ASSERT_TRUE(IsSuppressed(VEC(m), VEC(d), VEC(o))); 91 } 92 93 // A stack trace template only matches at the top of the stack. 94 TEST_F(SuppressionsTest, OnlyMatchesAtTheTop) { 95 string m[] = {"zz", "function1", "bb", "function2"}; 96 string d[] = {"zzz", "aaa", "bbb", "ccc"}; 97 string o[] = {"o0", "object2", "object1", "object3"}; 98 ASSERT_FALSE(IsSuppressed(VEC(m), VEC(d), VEC(o))); 99 } 100 101 // A short stack trace is not. 102 TEST_F(SuppressionsTest, ShortTrace) { 103 string m[] = {"function1", "bb"}; 104 string d[] = {"aaa", "bbb"}; 105 string o[] = {"object2", "object1"}; 106 ASSERT_FALSE(IsSuppressed(VEC(m), VEC(d), VEC(o))); 107 } 108 109 class SuppressionsWithWildcardsTest : public BaseSuppressionsTest { 110 protected: 111 virtual void SetUp() { 112 const string data = 113 "{\n" 114 " name\n" 115 " test_tool,tool2:test_warning_type\n" 116 " fun:fun*1\n" 117 " obj:obj*t1\n" 118 " ...\n" 119 " fun:f?n*2\n" 120 "}"; 121 supp_.ReadFromString(data); 122 } 123 }; 124 125 TEST_F(SuppressionsWithWildcardsTest, Wildcards1) { 126 string m[] = {"function1", "bb", "function2"}; 127 string d[] = {"aaa", "bbb", "ccc"}; 128 string o[] = {"object2", "object1", "object3"}; 129 ASSERT_TRUE(IsSuppressed(VEC(m), VEC(d), VEC(o))); 130 } 131 132 TEST_F(SuppressionsWithWildcardsTest, Wildcards2) { 133 string m[] = {"some_other_function1", "bb", "function2"}; 134 string d[] = {"aaa", "bbb", "ccc"}; 135 string o[] = {"object2", "object1", "object3"}; 136 ASSERT_FALSE(IsSuppressed(VEC(m), VEC(d), VEC(o))); 137 } 138 139 TEST_F(SuppressionsWithWildcardsTest, Wildcards3) { 140 string m[] = {"fun1", "bb", "fanction2"}; 141 string d[] = {"aaa", "bbb", "ccc"}; 142 string o[] = {"object2", "objt1", "object3"}; 143 ASSERT_TRUE(IsSuppressed(VEC(m), VEC(d), VEC(o))); 144 } 145 146 // Tests "..." wildcard. 147 TEST_F(SuppressionsWithWildcardsTest, VerticalWildcards1) { 148 string m[] = {"fun1", "bb", "qq", "fanction2"}; 149 string d[] = {"aaa", "bbb", "ddd", "ccc"}; 150 string o[] = {"object2", "objt1", "object3", "object4"}; 151 ASSERT_TRUE(IsSuppressed(VEC(m), VEC(d), VEC(o))); 152 } 153 154 155 class MultipleStackTraceTest : public BaseSuppressionsTest { 156 protected: 157 virtual void SetUp() { 158 const string data = 159 "{\n" 160 " name\n" 161 " test_tool,tool2:test_warning_type\n" 162 " {\n" 163 " fun:fun*1\n" 164 " }\n" 165 " {\n" 166 " fun:fun*2\n" 167 " fun:fun*3\n" 168 " }\n" 169 " {\n" 170 " ...\n" 171 " fun:fun*4\n" 172 " obj:obj*5\n" 173 " }\n" 174 "}"; 175 supp_.ReadFromString(data); 176 } 177 }; 178 179 TEST_F(MultipleStackTraceTest, Simple1) { 180 string m[] = {"fun1", "bb", "qq", "fun2"}; 181 string d[] = {"aaa", "bbb", "ddd", "ccc"}; 182 string o[] = {"object1", "object2", "object3", "object4"}; 183 ASSERT_TRUE(IsSuppressed(VEC(m), VEC(d), VEC(o))); 184 } 185 186 TEST_F(MultipleStackTraceTest, SecondTemplateMatches) { 187 string m[] = {"fun2", "fun3", "qq", "fun2"}; 188 string d[] = {"aaa", "bbb", "ddd", "ccc"}; 189 string o[] = {"object1", "object2", "object3", "object4"}; 190 ASSERT_TRUE(IsSuppressed(VEC(m), VEC(d), VEC(o))); 191 } 192 193 TEST_F(MultipleStackTraceTest, ThirdTemplateMatches) { 194 string m[] = {"fun4", "bb", "qq", "fun2"}; 195 string d[] = {"aaa", "bbb", "ddd", "ccc"}; 196 string o[] = {"object1", "object5", "object3", "object4"}; 197 ASSERT_TRUE(IsSuppressed(VEC(m), VEC(d), VEC(o))); 198 } 199 200 TEST_F(MultipleStackTraceTest, NothingMatches) { 201 string m[] = {"_fun1", "bb", "qq", "fun2"}; 202 string d[] = {"aaa", "bbb", "ddd", "ccc"}; 203 string o[] = {"object1", "object2", "object3", "object4"}; 204 ASSERT_FALSE(IsSuppressed(VEC(m), VEC(d), VEC(o))); 205 } 206 207 TEST_F(MultipleStackTraceTest, TwoTemplatesMatch) { 208 string m[] = {"fun1", "bb", "fun4", "fun2"}; 209 string d[] = {"aaa", "bbb", "ddd", "ccc"}; 210 string o[] = {"object1", "object2", "object3", "object5"}; 211 ASSERT_TRUE(IsSuppressed(VEC(m), VEC(d), VEC(o))); 212 } 213 214 215 TEST_F(BaseSuppressionsTest, StartsWithVerticalWildcard) { 216 const string data = 217 "{\n" 218 " name\n" 219 " test_tool:test_warning_type\n" 220 " ...\n" 221 " fun:qq\n" 222 "}"; 223 ASSERT_GT(supp_.ReadFromString(data), 0); 224 string m[] = {"fun1", "bb", "qq", "function2"}; 225 string d[] = {"aaa", "bbb", "ddd", "ccc"}; 226 string o[] = {"object2", "objt1", "object3", "object4"}; 227 ASSERT_TRUE(IsSuppressed(VEC(m), VEC(d), VEC(o))); 228 } 229 230 TEST_F(BaseSuppressionsTest, StartsWithVerticalWildcard2) { 231 const string data = 232 "{\n" 233 " name\n" 234 " test_tool:test_warning_type\n" 235 " ...\n" 236 " fun:fun1\n" 237 "}"; 238 ASSERT_GT(supp_.ReadFromString(data), 0); 239 string m[] = {"fun1", "bb", "qq", "function2"}; 240 string d[] = {"aaa", "bbb", "ddd", "ccc"}; 241 string o[] = {"object2", "objt1", "object3", "object4"}; 242 ASSERT_TRUE(IsSuppressed(VEC(m), VEC(d), VEC(o))); 243 } 244 245 TEST_F(BaseSuppressionsTest, EndsWithVerticalWildcard) { 246 const string data = 247 "{\n" 248 " name\n" 249 " test_tool:test_warning_type\n" 250 " fun:fun1\n" 251 " ...\n" 252 "}"; 253 ASSERT_GT(supp_.ReadFromString(data), 0); 254 string m[] = {"fun1", "bb", "qq", "function2"}; 255 string d[] = {"aaa", "bbb", "ddd", "ccc"}; 256 string o[] = {"object2", "objt1", "object3", "object4"}; 257 ASSERT_TRUE(IsSuppressed(VEC(m), VEC(d), VEC(o))); 258 } 259 260 TEST_F(BaseSuppressionsTest, EndsWithVerticalWildcard2) { 261 const string data = 262 "{\n" 263 " name\n" 264 " test_tool:test_warning_type\n" 265 " fun:qq\n" 266 " ...\n" 267 "}"; 268 ASSERT_GT(supp_.ReadFromString(data), 0); 269 string m[] = {"fun1", "bb", "qq", "function2"}; 270 string d[] = {"aaa", "bbb", "ddd", "ccc"}; 271 string o[] = {"object2", "objt1", "object3", "object4"}; 272 ASSERT_FALSE(IsSuppressed(VEC(m), VEC(d), VEC(o))); 273 } 274 275 TEST_F(BaseSuppressionsTest, Complex) { 276 const string data = 277 "{\n" 278 " name\n" 279 " test_tool:test_warning_type\n" 280 " fun:qq\n" 281 " ...\n" 282 " obj:obj*3\n" 283 " ...\n" 284 " fun:function?\n" 285 "}"; 286 ASSERT_GT(supp_.ReadFromString(data), 0); 287 string m[] = {"fun1", "bb", "qq", "function2"}; 288 string d[] = {"aaa", "bbb", "ddd", "ccc"}; 289 string o[] = {"object2", "objt1", "object3", "object4"}; 290 ASSERT_FALSE(IsSuppressed(VEC(m), VEC(d), VEC(o))); 291 } 292 293 TEST_F(BaseSuppressionsTest, DemangledNames) { 294 const string data = 295 "{\n" 296 " name\n" 297 " test_tool:test_warning_type\n" 298 " fun:bb*w?\n" 299 "}"; 300 ASSERT_GT(supp_.ReadFromString(data), 0); 301 string m[] = {"fun1", "bb", "qq", "function2"}; 302 string d[] = {"bbbxxwz", "aaa", "ddd", "ccc"}; 303 string o[] = {"object2", "objt1", "object3", "object4"}; 304 ASSERT_TRUE(IsSuppressed(VEC(m), VEC(d), VEC(o))); 305 } 306 307 TEST_F(BaseSuppressionsTest, TrailingWhitespace) { 308 const string data = 309 "{\n" 310 " name\n" 311 " test_tool:test_warning_type\n" 312 " fun:bb*w? \n" 313 "}"; 314 ASSERT_GT(supp_.ReadFromString(data), 0); 315 string m[] = {"fun1", "bb", "qq", "function2"}; 316 string d[] = {"bbbxxwz", "aaa", "ddd", "ccc"}; 317 string o[] = {"object2", "objt1", "object3", "object4"}; 318 ASSERT_TRUE(IsSuppressed(VEC(m), VEC(d), VEC(o))); 319 } 320 321 TEST_F(BaseSuppressionsTest, ObjectiveC) { 322 const string data = 323 "{\n" 324 " name\n" 325 " test_tool:test_warning_type\n" 326 " fun:-[NSObject(NSKeyValueCoding) setValue:forKeyPath:]\n" 327 "}"; 328 ASSERT_GT(supp_.ReadFromString(data), 0); 329 string m[] = {"-[NSObject(NSKeyValueCoding) setValue:forKeyPath:]", "function2"}; 330 string d[] = {"bbbxxwz", "aaa", "ddd", "ccc"}; 331 string o[] = {"object2", "objt1", "object3", "object4"}; 332 ASSERT_TRUE(IsSuppressed(VEC(m), VEC(d), VEC(o))); 333 } 334 335 336 class FailingSuppressionsTest : public ::testing::Test { 337 protected: 338 int ErrorLineNo(string data) { 339 int result = supp_.ReadFromString(data); 340 if (result >= 0) 341 return -1; 342 else 343 return supp_.GetErrorLineNo(); 344 } 345 346 Suppressions supp_; 347 }; 348 349 TEST_F(FailingSuppressionsTest, NoOpeningBrace) { 350 const string data = 351 " name\n" 352 " test_tool:test_warning_type\n" 353 " fun:bb*w? \n" 354 "}"; 355 ASSERT_EQ(1, ErrorLineNo(data)); 356 } 357 358 TEST_F(FailingSuppressionsTest, Bad1) { 359 const string data = 360 "{\n" 361 " name\n" 362 " something_else\n" 363 " test_tool:test_warning_type\n" 364 " fun:bb*w? \n" 365 "}"; 366 ASSERT_EQ(3, ErrorLineNo(data)); 367 } 368 369 TEST_F(FailingSuppressionsTest, Bad2) { 370 const string data = 371 "{\n" 372 " name\n" 373 " test_tool:test_warning_type\n" 374 " extra\n" 375 " fun:bb*w? \n" 376 "}"; 377 ASSERT_EQ(4, ErrorLineNo(data)); 378 } 379 380 TEST_F(FailingSuppressionsTest, Bad3) { 381 const string data = 382 "{\n" 383 " name\n" 384 " test_tool:test_warning_type\n" 385 " fun:bb*w? \n" 386 " extra\n" 387 "}"; 388 ASSERT_EQ(5, ErrorLineNo(data)); 389 } 390 391 TEST_F(FailingSuppressionsTest, SomeWeirdTextAfterASuppression) { 392 const string data = 393 "{\n" 394 " name\n" 395 " test_tool:test_warning_type\n" 396 " fun:bb*w? \n" 397 "}\n" 398 "some_weird_text\n" 399 "after_a_suppression\n"; 400 ASSERT_EQ(6, ErrorLineNo(data)); 401 } 402 403 TEST_F(FailingSuppressionsTest, NoToolsLineInMultitraceSuppression) { 404 const string data = 405 "{\n" 406 " name\n" 407 " {\n" 408 " fun:fun*2\n" 409 " fun:fun*3\n" 410 " }\n" 411 " {\n" 412 " ...\n" 413 " fun:fun*4\n" 414 " obj:obj*5\n" 415 " }\n" 416 "}"; 417 ASSERT_EQ(3, ErrorLineNo(data)); 418 } 419 420 TEST_F(FailingSuppressionsTest, BadStacktrace1) { 421 const string data = 422 "{\n" 423 " name\n" 424 " test_tool:test_warning_type\n" 425 " {\n" 426 " fun:fun*2\n" 427 " fun:fun*3\n" 428 " }\n" 429 " {\n" 430 " zzz\n" 431 " fun:fun*4\n" 432 " obj:obj*5\n" 433 " }\n" 434 "}"; 435 ASSERT_EQ(9, ErrorLineNo(data)); 436 } 437 438 TEST_F(FailingSuppressionsTest, BadStacktrace2) { 439 const string data = 440 "{\n" 441 " name\n" 442 " test_tool:test_warning_type\n" 443 " {\n" 444 " fun:fun*2\n" 445 " fun:fun*3\n" 446 " }\n" 447 " {\n" 448 " {\n" 449 " fun:fun*4\n" 450 " obj:obj*5\n" 451 " }\n" 452 "}"; 453 ASSERT_EQ(9, ErrorLineNo(data)); 454 } 455 456 TEST_F(FailingSuppressionsTest, BadStacktrace3) { 457 const string data = 458 "{\n" 459 " name\n" 460 " test_tool:test_warning_type\n" 461 " {\n" 462 " fun:fun*2\n" 463 " fun:fun*3\n" 464 " }\n" 465 " {\n" 466 " fun:fun*4\n" 467 " obj:obj*5\n" 468 " }\n" 469 " zzz\n" 470 "}"; 471 ASSERT_EQ(12, ErrorLineNo(data)); 472 } 473 474 TEST_F(FailingSuppressionsTest, StacktraceWithParenthesis) { 475 const string data = 476 "{\n" 477 " name\n" 478 " test_tool:test_warning_type\n" 479 " {\n" 480 " fun:fun*2\n" 481 " fun:fun*3\n" 482 " }\n" 483 " {\n" 484 " fun:fun*4()\n" 485 " obj:obj*5\n" 486 " }\n" 487 "}"; 488 ASSERT_EQ(9, ErrorLineNo(data)); 489 } 490 491 TEST_F(FailingSuppressionsTest, StacktraceWithAngleBraces) { 492 const string data = 493 "{\n" 494 " name\n" 495 " test_tool:test_warning_type\n" 496 " {\n" 497 " fun:fun*2\n" 498 " fun:fun*3\n" 499 " }\n" 500 " {\n" 501 " fun:fun<int>*4\n" 502 " obj:obj*5\n" 503 " }\n" 504 "}"; 505 ASSERT_EQ(9, ErrorLineNo(data)); 506 } 507 508 509 TEST(WildcardTest, Simple) { 510 EXPECT_TRUE(StringMatch("abc", "abc")); 511 EXPECT_FALSE(StringMatch("abcd", "abc")); 512 EXPECT_FALSE(StringMatch("dabc", "abc")); 513 EXPECT_FALSE(StringMatch("ab", "abc")); 514 EXPECT_FALSE(StringMatch("", "abc")); 515 EXPECT_FALSE(StringMatch("abc", "")); 516 EXPECT_TRUE(StringMatch("", "")); 517 } 518 519 TEST(WildcardTest, SingleCharacterWildcard) { 520 EXPECT_TRUE(StringMatch("a?c", "abc")); 521 EXPECT_TRUE(StringMatch("?bc", "abc")); 522 EXPECT_TRUE(StringMatch("ab?", "abc")); 523 EXPECT_TRUE(StringMatch("a??", "abc")); 524 EXPECT_TRUE(StringMatch("???", "abc")); 525 EXPECT_TRUE(StringMatch("?", "a")); 526 EXPECT_FALSE(StringMatch("?zc", "abc")); 527 EXPECT_FALSE(StringMatch("?bz", "abc")); 528 EXPECT_FALSE(StringMatch("b?c", "abc")); 529 EXPECT_FALSE(StringMatch("az?", "abc")); 530 EXPECT_FALSE(StringMatch("abc?", "abc")); 531 EXPECT_FALSE(StringMatch("?abc", "abc")); 532 EXPECT_FALSE(StringMatch("?", "")); 533 EXPECT_FALSE(StringMatch("??", "")); 534 } 535 536 TEST(WildcardTest, MultiCharacterWildcard) { 537 EXPECT_TRUE(StringMatch("*x", "x")); 538 EXPECT_TRUE(StringMatch("x*", "x")); 539 EXPECT_TRUE(StringMatch("*x*", "x")); 540 541 EXPECT_TRUE(StringMatch("a*d", "abcd")); 542 EXPECT_TRUE(StringMatch("ab*d", "abcd")); 543 EXPECT_TRUE(StringMatch("*cd", "abcd")); 544 EXPECT_TRUE(StringMatch("*d", "abcd")); 545 EXPECT_TRUE(StringMatch("ab*", "abcd")); 546 EXPECT_TRUE(StringMatch("a*", "abcd")); 547 EXPECT_TRUE(StringMatch("*", "abcd")); 548 EXPECT_TRUE(StringMatch("ab*cd", "abcd")); 549 550 EXPECT_TRUE(StringMatch("ab**", "abcd")); 551 EXPECT_TRUE(StringMatch("**", "abcd")); 552 EXPECT_TRUE(StringMatch("***", "abcd")); 553 EXPECT_TRUE(StringMatch("**d", "abcd")); 554 EXPECT_TRUE(StringMatch("*c*", "abcd")); 555 EXPECT_TRUE(StringMatch("a*c*d*f", "abcdef")); 556 EXPECT_TRUE(StringMatch("a*c*e*", "abcdef")); 557 EXPECT_TRUE(StringMatch("*a*b*f", "abcdef")); 558 EXPECT_TRUE(StringMatch("*b*d*", "abcdef")); 559 560 EXPECT_FALSE(StringMatch("b*", "abcd")); 561 EXPECT_FALSE(StringMatch("*c", "abcd")); 562 EXPECT_FALSE(StringMatch("*a", "abcd")); 563 } 564 565 TEST(WildcardTest, WildcardCharactersInText) { 566 EXPECT_TRUE(StringMatch("?", "?")); 567 EXPECT_FALSE(StringMatch("a", "?")); 568 EXPECT_FALSE(StringMatch("ab", "a?")); 569 EXPECT_FALSE(StringMatch("ab", "?b")); 570 EXPECT_TRUE(StringMatch("a?", "a?")); 571 EXPECT_TRUE(StringMatch("?b", "?b")); 572 573 EXPECT_TRUE(StringMatch("*", "*")); 574 EXPECT_FALSE(StringMatch("a", "*")); 575 EXPECT_FALSE(StringMatch("ab", "a*")); 576 EXPECT_FALSE(StringMatch("ab", "*b")); 577 EXPECT_TRUE(StringMatch("a*", "a*")); 578 EXPECT_TRUE(StringMatch("*b", "*b")); 579 } 580 581 int main(int argc, char **argv) { 582 testing::InitGoogleTest(&argc, argv); 583 584 return RUN_ALL_TESTS(); 585 } 586