| // Copyright 2017-2020 The Verible Authors. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| #include "verilog/analysis/verilog_equivalence.h" |
| |
| #include <iostream> |
| #include <memory> |
| #include <vector> |
| |
| #include "gmock/gmock.h" |
| #include "gtest/gtest.h" |
| #include "absl/status/status.h" |
| #include "absl/strings/match.h" |
| #include "absl/strings/string_view.h" |
| #include "absl/types/span.h" |
| #include "common/text/token_info.h" |
| #include "common/util/logging.h" |
| |
| #undef EXPECT_OK |
| #define EXPECT_OK(value) EXPECT_TRUE((value).ok()) |
| |
| #undef ASSERT_OK |
| #define ASSERT_OK(value) ASSERT_TRUE((value).ok()) |
| |
| namespace verilog { |
| namespace { |
| |
| TEST(DiffStatusTest, Print) { |
| // check a few enums |
| { |
| std::ostringstream stream; |
| stream << DiffStatus::kDifferent; |
| EXPECT_EQ(stream.str(), "different"); |
| } |
| { |
| std::ostringstream stream; |
| stream << DiffStatus::kEquivalent; |
| EXPECT_EQ(stream.str(), "equivalent"); |
| } |
| } |
| |
| static DiffStatus FlipStatus(DiffStatus status) { |
| switch (status) { |
| case DiffStatus::kLeftError: |
| return DiffStatus::kRightError; |
| case DiffStatus::kRightError: |
| return DiffStatus::kLeftError; |
| default: |
| return status; |
| } |
| } |
| |
| static void ExpectCompareWithErrstream( |
| std::function<DiffStatus(absl::string_view, absl::string_view, |
| std::ostream*)> |
| func, |
| DiffStatus expect_compare, absl::string_view left, absl::string_view right, |
| std::ostream* errstream = &std::cout) { |
| EXPECT_EQ(func(left, right, errstream), expect_compare) |
| << "left:\n" |
| << left << "\nright:\n" |
| << right; |
| { // commutative comparison check (should be same) |
| std::ostringstream errstream; |
| EXPECT_EQ(func(right, left, &errstream), FlipStatus(expect_compare)) |
| << "(commutative) " << errstream.str(); |
| } |
| } |
| |
| TEST(FormatEquivalentTest, Spaces) { |
| const std::vector<const char*> kTestCases = { |
| "", |
| " ", |
| "\n", |
| "\t", |
| }; |
| for (size_t i = 0; i < kTestCases.size(); ++i) { |
| for (size_t j = i + 1; j < kTestCases.size(); ++j) { |
| ExpectCompareWithErrstream(FormatEquivalent, DiffStatus::kEquivalent, |
| kTestCases[i], kTestCases[j]); |
| } |
| } |
| } |
| |
| TEST(FormatEquivalentTest, ShortSequences) { |
| const char* kTestCases[] = { |
| "1", |
| "2", |
| "1;", |
| "1 ;", |
| }; |
| ExpectCompareWithErrstream(FormatEquivalent, DiffStatus::kDifferent, |
| kTestCases[0], kTestCases[1]); |
| ExpectCompareWithErrstream(FormatEquivalent, DiffStatus::kDifferent, |
| kTestCases[0], kTestCases[2]); |
| ExpectCompareWithErrstream(FormatEquivalent, DiffStatus::kDifferent, |
| kTestCases[0], kTestCases[3]); |
| ExpectCompareWithErrstream(FormatEquivalent, DiffStatus::kDifferent, |
| kTestCases[1], kTestCases[2]); |
| ExpectCompareWithErrstream(FormatEquivalent, DiffStatus::kDifferent, |
| kTestCases[1], kTestCases[3]); |
| ExpectCompareWithErrstream(FormatEquivalent, DiffStatus::kEquivalent, |
| kTestCases[2], kTestCases[3]); |
| } |
| |
| TEST(FormatEquivalentTest, Identifiers) { |
| const char* kTestCases[] = { |
| "foo bar;", |
| " foo\t\tbar ; ", |
| "foobar;", // only 2 tokens |
| "foo bar\n;\n", |
| }; |
| ExpectCompareWithErrstream(FormatEquivalent, DiffStatus::kEquivalent, |
| kTestCases[0], kTestCases[1]); |
| ExpectCompareWithErrstream(FormatEquivalent, DiffStatus::kDifferent, |
| kTestCases[0], kTestCases[2]); |
| ExpectCompareWithErrstream(FormatEquivalent, DiffStatus::kEquivalent, |
| kTestCases[0], kTestCases[3]); |
| ExpectCompareWithErrstream(FormatEquivalent, DiffStatus::kDifferent, |
| kTestCases[1], kTestCases[2]); |
| ExpectCompareWithErrstream(FormatEquivalent, DiffStatus::kEquivalent, |
| kTestCases[1], kTestCases[3]); |
| ExpectCompareWithErrstream(FormatEquivalent, DiffStatus::kDifferent, |
| kTestCases[2], kTestCases[3]); |
| } |
| |
| TEST(FormatEquivalentTest, Keyword) { |
| const char* kTestCases[] = { |
| "wire foo;", |
| " wire \n\t\t foo ;\n", |
| }; |
| ExpectCompareWithErrstream(FormatEquivalent, DiffStatus::kEquivalent, |
| kTestCases[0], kTestCases[1]); |
| } |
| |
| TEST(FormatEquivalentTest, Comments) { |
| const char* kTestCases[] = { |
| "// comment1\n", // |
| "// comment1 \n", // |
| "// comment1\n", // |
| " // comment1\n", // same as [2] |
| "// comment2\n", // |
| "/* comment1 */\n", // |
| "/* comment1 */\n", // |
| }; |
| auto span = absl::MakeSpan(kTestCases); |
| // At some point in the future when token-reflowing is implemented, these |
| // will need to become smarter checks. |
| // For now, they only check for exact match. |
| for (size_t i = 0; i < span.size(); ++i) { |
| for (size_t j = i + 1; j < span.size(); ++j) { |
| if (i == 2 && j == 3) { |
| ExpectCompareWithErrstream(FormatEquivalent, DiffStatus::kEquivalent, |
| kTestCases[i], kTestCases[j]); |
| } else { |
| ExpectCompareWithErrstream(FormatEquivalent, DiffStatus::kDifferent, |
| kTestCases[i], kTestCases[j]); |
| } |
| } |
| } |
| } |
| |
| TEST(FormatEquivalentTest, DiagnosticLength) { |
| const char* kTestCases[] = { |
| "module foo\n", |
| "module foo;\n", |
| }; |
| { |
| std::ostringstream errs; |
| ExpectCompareWithErrstream(FormatEquivalent, DiffStatus::kDifferent, |
| kTestCases[0], kTestCases[1], &errs); |
| EXPECT_TRUE(absl::StartsWith( |
| errs.str(), "Mismatch in token sequence lengths: 3 vs. 4")); |
| EXPECT_TRUE(absl::StrContains(errs.str(), "First mismatched token [2]:")); |
| } |
| { |
| std::ostringstream errs; |
| ExpectCompareWithErrstream(FormatEquivalent, DiffStatus::kDifferent, |
| kTestCases[1], kTestCases[0], &errs); |
| EXPECT_TRUE(absl::StartsWith( |
| errs.str(), "Mismatch in token sequence lengths: 4 vs. 3")); |
| EXPECT_TRUE(absl::StrContains(errs.str(), "First mismatched token [2]:")); |
| } |
| } |
| |
| TEST(FormatEquivalentTest, MismatchNumberOfTokens) { |
| { |
| std::ostringstream errs; |
| ExpectCompareWithErrstream(FormatEquivalent, DiffStatus::kDifferent, |
| "module ", "module extra_token", &errs); |
| EXPECT_TRUE(absl::StrContains( |
| errs.str(), "Mismatch in token sequence lengths: 2 vs. 3")) |
| << "full message:\n" |
| << errs.str(); |
| EXPECT_TRUE(absl::StrContains(errs.str(), "extra_token")) |
| << "full message:\n" |
| << errs.str(); |
| } |
| { |
| std::ostringstream errs; |
| ExpectCompareWithErrstream(FormatEquivalent, DiffStatus::kDifferent, |
| "module extra_token;", "module ", &errs); |
| EXPECT_TRUE(absl::StrContains( |
| errs.str(), "Mismatch in token sequence lengths: 4 vs. 2")) |
| << "full message:\n" |
| << errs.str(); |
| EXPECT_TRUE(absl::StrContains(errs.str(), "extra_token")) |
| << "full message:\n" |
| << errs.str(); |
| } |
| } |
| |
| TEST(FormatEquivalentTest, MismatchTokenType) { |
| std::ostringstream errs; |
| ExpectCompareWithErrstream(FormatEquivalent, DiffStatus::kDifferent, |
| "module k1;", "module 1;", &errs); |
| EXPECT_TRUE(absl::StrContains(errs.str(), "Mismatched token enums.")) |
| << "full message:\n" |
| << errs.str(); |
| EXPECT_TRUE(absl::StrContains(errs.str(), "First mismatched token [1]:")) |
| << "full message:\n" |
| << errs.str(); |
| EXPECT_TRUE(absl::StrContains(errs.str(), "SymbolIdentifier")) |
| << "full message:\n" |
| << errs.str(); |
| EXPECT_TRUE(absl::StrContains(errs.str(), "TK_DecNumber")) |
| << "full message:\n" |
| << errs.str(); |
| } |
| |
| TEST(FormatEquivalentTest, DiagnosticMismatch) { |
| const char* kTestCases[] = { |
| "module foo;\n", |
| "module bar;\n", |
| "module foo,\n", |
| }; |
| { |
| std::ostringstream errs; |
| ExpectCompareWithErrstream(FormatEquivalent, DiffStatus::kDifferent, |
| kTestCases[0], kTestCases[1], &errs); |
| EXPECT_TRUE(absl::StrContains(errs.str(), "First mismatched token [1]:")) |
| << "full message:\n" |
| << errs.str(); |
| EXPECT_TRUE(absl::StrContains(errs.str(), "foo")) << "full message:\n" |
| << errs.str(); |
| EXPECT_TRUE(absl::StrContains(errs.str(), "bar")) << "full message:\n" |
| << errs.str(); |
| } |
| { |
| std::ostringstream errs; |
| ExpectCompareWithErrstream(FormatEquivalent, DiffStatus::kDifferent, |
| kTestCases[0], kTestCases[2], &errs); |
| EXPECT_TRUE(absl::StrContains(errs.str(), "First mismatched token [2]:")) |
| << "full message:\n" |
| << errs.str(); |
| EXPECT_TRUE(absl::StrContains(errs.str(), "','")) << "full message:\n" |
| << errs.str(); |
| EXPECT_TRUE(absl::StrContains(errs.str(), "';'")) << "full message:\n" |
| << errs.str(); |
| } |
| } |
| |
| TEST(FormatEquivalentTest, LexErrorOnLeft) { |
| std::ostringstream errs; |
| ExpectCompareWithErrstream(FormatEquivalent, DiffStatus::kLeftError, |
| "hello 123badid\n", "hello good_id", &errs); |
| EXPECT_TRUE(absl::StrContains(errs.str(), "error from left input")) |
| << "full message:\n" |
| << errs.str(); |
| EXPECT_TRUE(absl::StrContains(errs.str(), "123badid")) << "full message:\n" |
| << errs.str(); |
| } |
| |
| TEST(FormatEquivalentTest, LexErrorOnLeftInMacroArg) { |
| std::ostringstream errs; |
| ExpectCompareWithErrstream(FormatEquivalent, DiffStatus::kLeftError, |
| "`hello(234badid)\n", "`hello(good_id)", &errs); |
| EXPECT_TRUE(absl::StrContains(errs.str(), "error from left input")) |
| << "full message:\n" |
| << errs.str(); |
| EXPECT_TRUE(absl::StrContains(errs.str(), "234badid")) << "full message:\n" |
| << errs.str(); |
| } |
| |
| TEST(FormatEquivalentTest, LexErrorOnLeftInMacroDefinitionBody) { |
| std::ostringstream errs; |
| ExpectCompareWithErrstream(FormatEquivalent, DiffStatus::kLeftError, |
| "`define hello 345badid\n", |
| "`define hello good_id\n", &errs); |
| EXPECT_TRUE(absl::StrContains(errs.str(), "error from left input")) |
| << "full message:\n" |
| << errs.str(); |
| EXPECT_TRUE(absl::StrContains(errs.str(), "345badid")) << "full message:\n" |
| << errs.str(); |
| } |
| |
| TEST(FormatEquivalentTest, LexErrorOnRight) { |
| std::ostringstream errs; |
| ExpectCompareWithErrstream(FormatEquivalent, DiffStatus::kRightError, |
| "hello good_id\n", "hello 432_bad_id\n", &errs); |
| EXPECT_TRUE(absl::StrContains(errs.str(), "error from right input")) |
| << "full message:\n" |
| << errs.str(); |
| EXPECT_TRUE(absl::StrContains(errs.str(), "432_bad_id")) << "full message:\n" |
| << errs.str(); |
| } |
| |
| TEST(FormatEquivalentTest, LexErrorOnRightInMacroArg) { |
| std::ostringstream errs; |
| ExpectCompareWithErrstream(FormatEquivalent, DiffStatus::kRightError, |
| "`hello(good_id)\n", "`hello(543_bad_id)\n", |
| &errs); |
| EXPECT_TRUE(absl::StrContains(errs.str(), "error from right input")) |
| << "full message:\n" |
| << errs.str(); |
| EXPECT_TRUE(absl::StrContains(errs.str(), "543_bad_id")) << "full message:\n" |
| << errs.str(); |
| } |
| |
| TEST(FormatEquivalentTest, LexErrorOnRightInMacroDefinitionBody) { |
| std::ostringstream errs; |
| ExpectCompareWithErrstream(FormatEquivalent, DiffStatus::kRightError, |
| "`define hello good_id\n", |
| "`define hello 654_bad_id\n", &errs); |
| EXPECT_TRUE(absl::StrContains(errs.str(), "error from right input")) |
| << "full message:\n" |
| << errs.str(); |
| EXPECT_TRUE(absl::StrContains(errs.str(), "654_bad_id")) << "full message:\n" |
| << errs.str(); |
| } |
| |
| struct ObfuscationTestCase { |
| absl::string_view before; |
| absl::string_view after; |
| DiffStatus expect_match; |
| }; |
| |
| TEST(ObfuscationEquivalentTest, Various) { |
| const ObfuscationTestCase kTestCases[] = { |
| {"", "", DiffStatus::kEquivalent}, |
| {"\n", "\n", DiffStatus::kEquivalent}, |
| {"\n", "\n\n", DiffStatus::kDifferent}, |
| {"\n", "\t", |
| DiffStatus::kDifferent}, // whitespace must match to be be equivalent |
| {" ", "\t", |
| DiffStatus::kDifferent}, // whitespace must match to be be equivalent |
| {" ", "\t", |
| DiffStatus::kDifferent}, // whitespace must match to be be equivalent |
| {" ", "\n", |
| DiffStatus::kDifferent}, // whitespace must match to be be equivalent |
| {"aabbcc\n", "doremi\n", DiffStatus::kEquivalent}, |
| {"aabbcc\n", "dorem\n", DiffStatus::kDifferent}, |
| {"11\n", "22\n", DiffStatus::kDifferent}, |
| {"\"11\"\n", "\"22\"\n", DiffStatus::kDifferent}, |
| {"wire\n", "wire\n", DiffStatus::kEquivalent}, |
| {"wire\n", "logic\n", DiffStatus::kDifferent}, |
| {"wire w;\n", "wire w;\n", DiffStatus::kEquivalent}, |
| {"wire w;", "wire w;\n", DiffStatus::kDifferent}, |
| {"wire xxx;\n", "wire yyy;\n", |
| DiffStatus::kEquivalent}, // identifiers changed |
| {"$zzz;\n", "$yyy;\n", DiffStatus::kEquivalent}, // identifiers changed |
| {"$zzz();\n", "$yyy();\n", |
| DiffStatus::kEquivalent}, // identifiers changed |
| {"$zzz;\n", "$yyyy;\n", DiffStatus::kDifferent}, |
| {"ff(gg, hh) + ii\n", "pp(qq, rr) + ss\n", DiffStatus::kEquivalent}, |
| {"ff(gg, hh) + ii\n", "pp(qq, rr) - ss\n", DiffStatus::kDifferent}, |
| {"ff(gg, hh) + ii\n", "pp[qq, rr] + ss\n", DiffStatus::kDifferent}, |
| {"ff(gg, hh) + ii\n", "pp(qq, rr) + ss\n", DiffStatus::kDifferent}, |
| {"ff(gg, hh) + ii\n", "pp(qq, rrr) + ss\n", DiffStatus::kDifferent}, |
| {"ff(gg, hh) + ii\n", "pp(12, rr) + ss\n", DiffStatus::kDifferent}, |
| {"ff(gg, hh) + ii\n", "pp(qq, rr)+ss\n", DiffStatus::kDifferent}, |
| {"`define FOO\n", "`define BAR\n", DiffStatus::kEquivalent}, |
| {"`define FOO\n", "`define BARR\n", DiffStatus::kDifferent}, |
| {"`define FOO\n", "`define BAR\n", DiffStatus::kDifferent}, |
| {"`define FOO\n", "`define BAR \n", DiffStatus::kDifferent}, |
| {"`define FOO xx\n", "`define BAR yy\n", DiffStatus::kEquivalent}, |
| {"`define FOO xx\n", "`define BAR yyz\n", DiffStatus::kDifferent}, |
| {"`define FOO \\\nxx\n", "`define BAR \\\nyy\n", DiffStatus::kEquivalent}, |
| {"`define FOO \\\nxxx\n", "`define BAR \\\nyy\n", DiffStatus::kDifferent}, |
| {"`define FOO \\\nxx\n", "`define BAR \\\n\tyy\n", |
| DiffStatus::kDifferent}, |
| {"`define FOO \\\nxx\n", "`define BAR \\\n\nyy\n", |
| DiffStatus::kDifferent}, |
| {"`define FOO \\\nxx\n", "`define BAR \\\nyy\n\n", |
| DiffStatus::kDifferent}, |
| /* TODO(b/150174736): recursive lexing looks erroneous |
| {"`define FOO \\\n`define INNERFOO \\\nxx\n\n", // `define inside `define |
| "`define BAR \\\n`define INNERBAR \\\nyy\n\n", DiffStatus::kEquivalent}, |
| */ |
| {"`ifdef FOO\n`endif\n", "`ifdef BAR\n`endif\n", DiffStatus::kEquivalent}, |
| {"`ifndef FOO\n`endif\n", "`ifndef BAR\n`endif\n", |
| DiffStatus::kEquivalent}, |
| {"`ifdef FOO\n`endif\n", "`ifndef BAR\n`endif\n", DiffStatus::kDifferent}, |
| {"`ifdef FOO\n`elsif BLEH\n`endif\n", "`ifdef BAR\n`elsif BLAH\n`endif\n", |
| DiffStatus::kEquivalent}, |
| {"`ifdef FOOO\n`endif\n", "`ifdef BAR\n`endif\n", DiffStatus::kDifferent}, |
| {"`ifdef FOO\n`elsif BLEH\n`endif\n", |
| "`ifdef BAR\n`elsif BLAHH\n`endif\n", DiffStatus::kDifferent}, |
| {"`FOO\n", "`BAR\n", DiffStatus::kEquivalent}, |
| {"`FOO;\n", "`BAR;\n", DiffStatus::kEquivalent}, |
| {"`FOO()\n", "`BAR()\n", DiffStatus::kEquivalent}, |
| {"`FOO(77)\n", "`BAR(77)\n", DiffStatus::kEquivalent}, |
| {"`FOO();\n", "`BAR();\n", DiffStatus::kEquivalent}, |
| {"`FOO()\n", "`BAAR()\n", DiffStatus::kDifferent}, |
| {"`FOO()\n", " `BAR()\n", DiffStatus::kDifferent}, |
| {"`FOO()\n", "`BAR ()\n", DiffStatus::kDifferent}, |
| {"`FOO()\n", "`BAR( )\n", DiffStatus::kDifferent}, |
| {"`FOO(77)\n", "`BAR(78)\n", DiffStatus::kDifferent}, |
| {"`FOO(`BLAH)\n", "`BAR(`BLEH)\n", DiffStatus::kEquivalent}, |
| {"`FOO(`BLAH)\n", "`BAR(`BLE)\n", DiffStatus::kDifferent}, |
| {"`FOO(`BLAH + `BLIPP)\n", "`BAR(`BLEH + `BLOOP)\n", |
| DiffStatus::kEquivalent}, |
| {"`FOO(`BLAH + `BLIPP)\n", "`BAR(`BLEH +`BLOOP)\n", |
| DiffStatus::kDifferent}, |
| {"`FOO(`BLAH + `BLIPP)\n", "`BAR(`BLEH + `BLOP)\n", |
| DiffStatus::kDifferent}, |
| {"`FOO(`BLAH + `BLIPP)\n", "`BAR(`BLEH * `BLOOP)\n", |
| DiffStatus::kDifferent}, |
| {"`FOO(`BLAH(`BLIPP))\n", "`BAR(`BLEH(`BLOOP))\n", |
| DiffStatus::kEquivalent}, |
| {"`FOO(`BLAH(`BLIP))\n", "`BAR(`BLEH(`BLOOP))\n", DiffStatus::kDifferent}, |
| {"`FOO(`BLAH(`BLIPP))\n", "`BAR(`BLEH(`BLOOP ))\n", |
| DiffStatus::kDifferent}, |
| {"`FOO(`BLAH(`BLIPP))\n", "`BAR(`BLEH( `BLOOP))\n", |
| DiffStatus::kDifferent}, |
| {"`FOO(`BLAH(`BLIPP))\n", "`BAR(`BLEH (`BLOOP))\n", |
| DiffStatus::kDifferent}, |
| {"`FOO(`BLAH(`BLIPP))\n", "`BAR( `BLEH(`BLOOP))\n", |
| DiffStatus::kDifferent}, |
| {"`FOO(`BLAH(`BLIPP))\n", "`BAR(`BLEH(`BLOOP) )\n", |
| DiffStatus::kDifferent}, |
| {"\\FOO;!@#$% ", "\\BAR;%$#@! ", |
| DiffStatus::kEquivalent}, // escaped identifier |
| {"\\FOO;!@#$% ", "\\BARR;%$#@! ", |
| DiffStatus::kDifferent}, // escaped identifier (!= length) |
| // token concatenation |
| {"abc``xyz", "qrs``tuv", DiffStatus::kEquivalent}, |
| {"abc``xyz", "qrs``123", DiffStatus::kDifferent}, |
| {"abc``xyz", "789``tuv", DiffStatus::kDifferent}, |
| {"`define CAT(ab, xy) ab``xy\n", "`define DOG(qr, tu) qr``tu\n", |
| DiffStatus::kEquivalent}, |
| {"`define CAT(ab, xy) ab``xy\n", "`define DOG(qr, tuv) qr``tuv\n", |
| DiffStatus::kDifferent}, |
| {"`define CAT(ab, xy) ab``xy\n", "`define DOG(qrs, tu) qrs``tu\n", |
| DiffStatus::kDifferent}, |
| {"`CAT(aa``bb, cc``dd)\n", "`DOG(jj``kk, ll``mm)\n", |
| DiffStatus::kEquivalent}, |
| {"`CAT(aa``bb, cc``dd)\n", "`DOG(jj``kk, llr``mm)\n", |
| DiffStatus::kDifferent}, |
| {"`CAT(aa``bb, cc``dd)\n", "`DOG(jj``kk, ll``mms)\n", |
| DiffStatus::kDifferent}, |
| }; |
| for (const auto& test : kTestCases) { |
| ExpectCompareWithErrstream(ObfuscationEquivalent, test.expect_match, |
| test.before, test.after); |
| } |
| } |
| |
| TEST(ObfuscationEquivalentTest, LexErrorOnLeft) { |
| std::ostringstream errs; |
| ExpectCompareWithErrstream(ObfuscationEquivalent, DiffStatus::kLeftError, |
| "hello 123badid\n", "hello good_id", &errs); |
| EXPECT_TRUE(absl::StrContains(errs.str(), "error from left input")) |
| << "full message:\n" |
| << errs.str(); |
| EXPECT_TRUE(absl::StrContains(errs.str(), "123badid")) << "full message:\n" |
| << errs.str(); |
| } |
| |
| TEST(ObfuscationEquivalentTest, LexErrorOnRight) { |
| std::ostringstream errs; |
| ExpectCompareWithErrstream(ObfuscationEquivalent, DiffStatus::kRightError, |
| "hello good_id\n", "hello 432_bad_id", &errs); |
| EXPECT_TRUE(absl::StrContains(errs.str(), "error from right input")) |
| << "full message:\n" |
| << errs.str(); |
| EXPECT_TRUE(absl::StrContains(errs.str(), "432_bad_id")) << "full message:\n" |
| << errs.str(); |
| } |
| |
| } // namespace |
| } // namespace verilog |