blob: 65350f0f198076674b4aa0073d6455ee20cec31c [file] [log] [blame]
// Copyright 2017 The Effcee 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 "gmock/gmock.h"
#include "effcee.h"
namespace {
using effcee::Match;
using effcee::Options;
using ::testing::Eq;
using ::testing::HasSubstr;
const char* kNotFound = "error: expected string not found in input";
const char* kMissedSame =
"error: CHECK-SAME: is not on the same line as previous match";
const char* kNextOnSame =
"error: CHECK-NEXT: is on the same line as previous match";
const char* kNextTooLate =
"error: CHECK-NEXT: is not on the line after the previous match";
const char* kNotStrFound = "error: CHECK-NOT: string occurred!";
// Match free function
TEST(Match, FreeFunctionLinks) {
Match("", "");
Match("", "", effcee::Options());
}
// Simple checks
TEST(Match, OneSimpleCheckPass) {
const auto result = Match("Hello", "CHECK: Hello");
EXPECT_TRUE(result) << result.message();
}
TEST(Match, OneSimpleCheckFail) {
const auto result = Match("World", "CHECK: Hello");
EXPECT_FALSE(result) << result.message();
EXPECT_THAT(result.message(), HasSubstr(kNotFound));
EXPECT_THAT(result.message(), HasSubstr("CHECK: Hello"));
}
TEST(Match, TwoSimpleChecksPass) {
const auto result = Match("Hello\nWorld", "CHECK: Hello\nCHECK: World");
EXPECT_TRUE(result) << result.message();
}
TEST(Match, RepeatedCheckFails) {
const auto result = Match("Hello\nWorld", "CHECK: Hello\nCHECK: Hello");
EXPECT_FALSE(result) << result.message();
EXPECT_THAT(result.message(), HasSubstr(kNotFound));
}
TEST(Match, TwoSimpleChecksPassWithSurroundingText) {
const auto input = R"(Say
Hello
World
Today)";
const auto result = Match(input, "CHECK: Hello\nCHECK: World");
EXPECT_TRUE(result) << result.message();
}
TEST(Match, TwoSimpleChecksPassWithInterveningText) {
const auto input = R"(Hello
Between
World)";
const auto result = Match(input, "CHECK: Hello\nCHECK: World");
EXPECT_TRUE(result) << result.message();
}
TEST(Match, TwoSimpleChecksPassWhenInSequenceSameLine) {
const auto result = Match("HelloWorld", "CHECK: Hello\nCHECK: World");
EXPECT_TRUE(result) << result.message();
}
TEST(Match, TwoSimpleChecksFailWhenReversed) {
const auto result = Match("HelloWorld", "CHECK: World\nCHECK: Hello");
EXPECT_FALSE(result) << result.message();
EXPECT_THAT(result.message(), HasSubstr(kNotFound));
EXPECT_THAT(result.message(), HasSubstr("CHECK: Hello"));
}
TEST(Match, SimpleThenSamePasses) {
const auto result = Match("HelloWorld", "CHECK: Hello\nCHECK-SAME: World");
EXPECT_TRUE(result) << result.message();
}
TEST(Match, SimpleThenSamePassesWithInterveningOnSameLine) {
const auto result = Match("Hello...World", "CHECK: Hello\nCHECK-SAME: World");
EXPECT_TRUE(result) << result.message();
}
TEST(Match, SimpleThenSameFailsIfOnNextLine) {
const auto result = Match("Hello\nWorld", "CHECK: Hello\nCHECK-SAME: World");
EXPECT_FALSE(result) << result.message();
EXPECT_THAT(result.message(),HasSubstr(kMissedSame));
EXPECT_THAT(result.message(), HasSubstr("CHECK-SAME: World"));
}
TEST(Match, SimpleThenSameFailsIfOnMuchLaterLine) {
const auto result =
Match("Hello\n\nz\n\nWorld", "CHECK: Hello\nCHECK-SAME: World");
EXPECT_FALSE(result) << result.message();
EXPECT_THAT(result.message(), HasSubstr(kMissedSame));
EXPECT_THAT(result.message(), HasSubstr("CHECK-SAME: World"));
}
TEST(Match, SimpleThenSameFailsIfNeverMatched) {
const auto result = Match("Hello\nHome", "CHECK: Hello\nCHECK-SAME: World");
EXPECT_FALSE(result) << result.message();
EXPECT_THAT(result.message(), HasSubstr(kNotFound));
EXPECT_THAT(result.message(), HasSubstr("CHECK-SAME: World"));
}
TEST(Match, SimpleThenNextOnSameLineFails) {
const auto result = Match("HelloWorld", "CHECK: Hello\nCHECK-NEXT: World");
EXPECT_FALSE(result);
EXPECT_THAT(result.message(), HasSubstr(kNextOnSame));
EXPECT_THAT(result.message(), HasSubstr("CHECK-NEXT: World"));
}
TEST(Match, SimpleThenNextPassesIfOnNextLine) {
const auto result = Match("Hello\nWorld", "CHECK: Hello\nCHECK-NEXT: World");
EXPECT_TRUE(result) << result.message();
}
TEST(Match, SimpleThenNextFailsIfOnAfterNextLine) {
const auto result = Match("Hello\nfoo\nWorld", "CHECK: Hello\nCHECK-NEXT: World");
EXPECT_THAT(result.message(), HasSubstr(kNextTooLate));
EXPECT_THAT(result.message(), HasSubstr("CHECK-NEXT: World"));
}
TEST(Match, SimpleThenNextFailsIfNeverMatched) {
const auto result =
Match("Hello\nHome", "CHECK: Hello\nCHECK-NEXT: World");
EXPECT_FALSE(result) << result.message();
EXPECT_THAT(result.message(), HasSubstr(kNotFound));
EXPECT_THAT(result.message(), HasSubstr("CHECK-NEXT: World"));
}
// TODO: CHECK-NOT
TEST(Match, AloneNotNeverSeenPasses) {
const auto result = Match("Hello", "CHECK-NOT: Borg");
EXPECT_TRUE(result);
}
TEST(Match, LeadingNotNeverSeenPasses) {
const auto result = Match("Hello", "CHECK-NOT: Borg\nCHECK: Hello");
EXPECT_TRUE(result);
}
TEST(Match, BetweenNotNeverSeenPasses) {
const auto result =
Match("HelloWorld", "CHECK: Hello\nCHECK-NOT: Borg\nCHECK: World");
EXPECT_TRUE(result);
}
TEST(Match, BetweenNotDotsNeverSeenPasses) {
// The before and after matches occur on the same line.
const auto result =
Match("Hello...World", "CHECK: Hello\nCHECK-NOT: Borg\nCHECK: World");
EXPECT_TRUE(result);
}
TEST(Match, BetweenNotLinesNeverSeenPasses) {
// The before and after matches occur on different lines.
const auto result =
Match("Hello\nz\nWorld", "CHECK: Hello\nCHECK-NOT: Borg\nCHECK: World");
EXPECT_TRUE(result);
}
TEST(Match, NotBetweenMatchesPasses) {
const auto result =
Match("Hello\nWorld\nBorg\n", "CHECK: Hello\nCHECK-NOT: Borg\nCHECK: World");
EXPECT_TRUE(result);
}
TEST(Match, NotBeforeFirstMatchPasses) {
const auto result =
Match("Hello\nWorld\nBorg\n", "CHECK-NOT: World\nCHECK: Hello");
EXPECT_TRUE(result);
}
TEST(Match, NotAfterLastMatchPasses) {
const auto result =
Match("Hello\nWorld\nBorg\n", "CHECK: World\nCHECK-NOT: Hello");
EXPECT_TRUE(result);
}
TEST(Match, NotBeforeFirstMatchFails) {
const auto result =
Match("Hello\nWorld\n", "CHECK-NOT: Hello\nCHECK: World");
EXPECT_FALSE(result);
}
TEST(Match, NotBetweenMatchesFails) {
const auto result =
Match("Hello\nWorld\nBorg\n", "CHECK: Hello\nCHECK-NOT: World\nCHECK: Borg");
EXPECT_FALSE(result);
}
TEST(Match, NotAfterLastMatchFails) {
const auto result =
Match("Hello\nWorld\n", "CHECK: Hello\nCHECK-NOT: World");
EXPECT_FALSE(result);
}
TEST(Match, TrailingNotNeverSeenPasses) {
const auto result = Match("Hello", "CHECK: Hello\nCHECK-NOT: Borg");
EXPECT_TRUE(result);
}
TEST(Match, AloneNotSeenFails) {
const auto result = Match("Borg", "CHECK-NOT: Borg");
EXPECT_FALSE(result);
EXPECT_THAT(result.message(), HasSubstr(kNotStrFound));
EXPECT_THAT(result.message(), HasSubstr("CHECK-NOT: Borg"));
}
TEST(Match, LeadingNotSeenFails) {
const auto result = Match("Borg", "CHECK-NOT: Borg\nCHECK: Hello");
EXPECT_FALSE(result);
EXPECT_THAT(result.message(), HasSubstr(kNotStrFound));
EXPECT_THAT(result.message(), HasSubstr("CHECK-NOT: Borg"));
}
TEST(Match, BetweenNotSeenFails) {
const auto result =
Match("HelloBorgWorld", "CHECK: Hello\nCHECK-NOT: Borg\nCHECK: World");
EXPECT_FALSE(result);
EXPECT_THAT(result.message(), HasSubstr(kNotStrFound));
EXPECT_THAT(result.message(), HasSubstr("CHECK-NOT: Borg"));
}
TEST(Match, BetweenNotDotsSeenFails) {
const auto result =
Match("Hello.Borg.World", "CHECK: Hello\nCHECK-NOT: Borg\nCHECK: World");
EXPECT_FALSE(result);
EXPECT_THAT(result.message(), HasSubstr(kNotStrFound));
EXPECT_THAT(result.message(), HasSubstr("CHECK-NOT: Borg"));
}
TEST(Match, BetweenNotLinesSeenFails) {
const auto result = Match("Hello\nBorg\nWorld",
"CHECK: Hello\nCHECK-NOT: Borg\nCHECK: World");
EXPECT_FALSE(result);
EXPECT_THAT(result.message(), HasSubstr(kNotStrFound));
EXPECT_THAT(result.message(), HasSubstr("CHECK-NOT: Borg"));
}
TEST(Match, TrailingNotSeenFails) {
const auto result = Match("HelloBorg", "CHECK: Hello\nCHECK-NOT: Borg");
EXPECT_FALSE(result);
EXPECT_THAT(result.message(), HasSubstr(kNotStrFound));
EXPECT_THAT(result.message(), HasSubstr("CHECK-NOT: Borg"));
}
// WIP: CHECK-LABEL
TEST(Match, OneLabelCheckPass) {
const auto result = Match("Hello", "CHECK-LABEL: Hello");
EXPECT_TRUE(result) << result.message();
}
TEST(Match, OneLabelCheckFail) {
const auto result = Match("World", "CHECK-LABEL: Hello");
EXPECT_FALSE(result) << result.message();
EXPECT_THAT(result.message(), HasSubstr(kNotFound));
EXPECT_THAT(result.message(), HasSubstr("CHECK-LABEL: Hello"));
}
TEST(Match, TwoLabelChecksPass) {
const auto result =
Match("Hello\nWorld", "CHECK-LABEL: Hello\nCHECK-LABEL: World");
EXPECT_TRUE(result) << result.message();
}
TEST(Match, TwoLabelChecksPassWithSurroundingText) {
const auto input = R"(Say
Hello
World
Today)";
const auto result = Match(input, "CHECK-LABEL: Hello\nCHECK-LABEL: World");
EXPECT_TRUE(result) << result.message();
}
TEST(Match, TwoLabelChecksPassWithInterveningText) {
const auto input = R"(Hello
Between
World)";
const auto result = Match(input, "CHECK-LABEL: Hello\nCHECK-LABEL: World");
EXPECT_TRUE(result) << result.message();
}
TEST(Match, TwoLabelChecksPassWhenInSequenceSameLine) {
const auto result =
Match("HelloWorld", "CHECK-LABEL: Hello\nCHECK-LABEL: World");
EXPECT_TRUE(result) << result.message();
}
TEST(Match, TwoLabelChecksFailWhenReversed) {
const auto result =
Match("HelloWorld", "CHECK-LABEL: World\nCHECK-LABEL: Hello");
EXPECT_FALSE(result) << result.message();
EXPECT_THAT(result.message(), HasSubstr(kNotFound));
EXPECT_THAT(result.message(), HasSubstr("CHECK-LABEL: Hello"));
}
// WIP: Mixture of Simple and Label checks
TEST(Match, SimpleAndLabelChecksPass) {
const auto result = Match("Hello\nWorld", "CHECK: Hello\nCHECK-LABEL: World");
EXPECT_TRUE(result) << result.message();
}
TEST(Match, LabelAndSimpleChecksPass) {
const auto result = Match("Hello\nWorld", "CHECK-LABEL: Hello\nCHECK: World");
EXPECT_TRUE(result) << result.message();
}
TEST(Match, SimpleAndLabelChecksFails) {
const auto result = Match("Hello\nWorld", "CHECK: Hello\nCHECK-LABEL: Band");
EXPECT_FALSE(result) << result.message();
EXPECT_THAT(result.message(), HasSubstr(kNotFound));
EXPECT_THAT(result.message(), HasSubstr("CHECK-LABEL: Band"));
}
TEST(Match, LabelAndSimpleChecksFails) {
const auto result = Match("Hello\nWorld", "CHECK-LABEL: Hello\nCHECK: Band");
EXPECT_FALSE(result) << result.message();
EXPECT_THAT(result.message(), HasSubstr(kNotFound));
EXPECT_THAT(result.message(), HasSubstr("CHECK: Band"));
}
// DAG checks: Part 1: Tests simlar to simple checks tests
TEST(Match, OneDAGCheckPass) {
const auto result = Match("Hello", "CHECK-DAG: Hello");
EXPECT_TRUE(result) << result.message();
}
TEST(Match, OneDAGCheckFail) {
const auto result = Match("World", "CHECK-DAG: Hello");
EXPECT_FALSE(result) << result.message();
EXPECT_THAT(result.message(), HasSubstr(kNotFound));
EXPECT_THAT(result.message(), HasSubstr("CHECK-DAG: Hello"));
}
TEST(Match, TwoDAGChecksPass) {
const auto result = Match("Hello\nWorld", "CHECK-DAG: Hello\nCHECK-DAG: World");
EXPECT_TRUE(result) << result.message();
}
TEST(Match, TwoDAGChecksPassWithSurroundingText) {
const auto input = R"(Say
Hello
World
Today)";
const auto result = Match(input, "CHECK-DAG: Hello\nCHECK-DAG: World");
EXPECT_TRUE(result) << result.message();
}
TEST(Match, TwoDAGChecksPassWithInterveningText) {
const auto input = R"(Hello
Between
World)";
const auto result = Match(input, "CHECK-DAG: Hello\nCHECK-DAG: World");
EXPECT_TRUE(result) << result.message();
}
TEST(Match, TwoDAGChecksPassWhenInSequenceSameLine) {
const auto result = Match("HelloWorld", "CHECK-DAG: Hello\nCHECK-DAG: World");
EXPECT_TRUE(result) << result.message();
}
TEST(Match, DAGThenSamePasses) {
const auto result = Match("HelloWorld", "CHECK-DAG: Hello\nCHECK-SAME: World");
EXPECT_TRUE(result) << result.message();
}
TEST(Match, DAGThenSamePassesWithInterveningOnSameLine) {
const auto result = Match("Hello...World", "CHECK-DAG: Hello\nCHECK-SAME: World");
EXPECT_TRUE(result) << result.message();
}
TEST(Match, DAGThenSameFailsIfOnNextLine) {
const auto result = Match("Hello\nWorld", "CHECK-DAG: Hello\nCHECK-SAME: World");
EXPECT_FALSE(result) << result.message();
EXPECT_THAT(result.message(), HasSubstr(kMissedSame));
EXPECT_THAT(result.message(), HasSubstr("CHECK-SAME: World"));
}
TEST(Match, DAGThenSameFailsIfOnMuchLaterLine) {
const auto result =
Match("Hello\n\nz\n\nWorld", "CHECK-DAG: Hello\nCHECK-SAME: World");
EXPECT_FALSE(result) << result.message();
EXPECT_THAT(result.message(), HasSubstr(kMissedSame));
EXPECT_THAT(result.message(), HasSubstr("CHECK-SAME: World"));
}
TEST(Match, DAGThenSameFailsIfNeverMatched) {
const auto result = Match("Hello\nHome", "CHECK-DAG: Hello\nCHECK-SAME: World");
EXPECT_FALSE(result) << result.message();
EXPECT_THAT(result.message(), HasSubstr(kNotFound));
EXPECT_THAT(result.message(), HasSubstr("CHECK-SAME: World"));
}
TEST(Match, DAGThenNextOnSameLineFails) {
const auto result = Match("HelloWorld", "CHECK-DAG: Hello\nCHECK-NEXT: World");
EXPECT_FALSE(result);
EXPECT_THAT(result.message(), HasSubstr(kNextOnSame));
EXPECT_THAT(result.message(), HasSubstr("CHECK-NEXT: World"));
}
TEST(Match, DAGThenNextPassesIfOnNextLine) {
const auto result = Match("Hello\nWorld", "CHECK-DAG: Hello\nCHECK-NEXT: World");
EXPECT_TRUE(result) << result.message();
}
TEST(Match, DAGThenNextPassesIfOnAfterNextLine) {
const auto result = Match("Hello\nWorld", "CHECK-DAG: Hello\nCHECK-NEXT: World");
EXPECT_TRUE(result) << result.message();
}
TEST(Match, DAGThenNextFailsIfNeverMatched) {
const auto result =
Match("Hello\nHome", "CHECK-DAG: Hello\nCHECK-NEXT: World");
EXPECT_FALSE(result) << result.message();
EXPECT_THAT(result.message(), HasSubstr(kNotFound));
EXPECT_THAT(result.message(), HasSubstr("CHECK-NEXT: World"));
}
// DAG checks: Part 2: Out of order matching
TEST(Match, TwoDAGMatchedOutOfOrderPasses) {
const auto result = Match("Hello\nWorld", "CHECK-DAG: World\nCHECK-DAG: Hello");
EXPECT_TRUE(result) << result.message();
}
TEST(Match, ThreeDAGMatchedOutOfOrderPasses) {
const auto result =
Match("Hello\nWorld\nNow",
"CHECK-DAG: Now\nCHECK-DAG: World\nCHECK-DAG: Hello");
EXPECT_TRUE(result) << result.message();
}
TEST(Match, TwoDAGChecksPassWhenReversedMatchingSameLine) {
const auto result = Match("HelloWorld", "CHECK-DAG: World\nCHECK-DAG: Hello");
EXPECT_TRUE(result) << result.message();
}
TEST(Match, DAGChecksGreedilyConsumeInput) {
const auto result =
Match("Hello\nBlocker\nWorld\n",
"CHECK-DAG: Hello\nCHECK-DAG: World\nCHECK: Blocker");
EXPECT_FALSE(result) << result.message();
EXPECT_THAT(result.message(), HasSubstr(kNotFound));
EXPECT_THAT(result.message(), HasSubstr("CHECK-DAG: World"));
}
// DAG checks: Part 3: Interaction with Not checks
TEST(Match, DAGsAreSeparatedByNot) {
// In this case the search for "Before" consumes the entire input.
const auto result =
Match("After\nBlocker\nBefore\n",
"CHECK-DAG: Before\nCHECK-NOT: nothing\nCHECK-DAG: After");
EXPECT_FALSE(result) << result.message();
EXPECT_THAT(result.message(), HasSubstr(kNotFound));
EXPECT_THAT(result.message(), HasSubstr("CHECK-DAG: After"));
}
TEST(Match, TwoDAGsAreSeparatedByNot) {
const auto result = Match("After\nApres\nBlocker\nBefore\nAnte",
"CHECK-DAG: Ante\nCHECK-DAG: Before\nCHECK-NOT: "
"nothing\nCHECK-DAG: Apres\nCHECK-DAG: After");
EXPECT_FALSE(result) << result.message();
EXPECT_THAT(result.message(), HasSubstr(kNotFound));
EXPECT_THAT(result.message(), HasSubstr("CHECK-DAG: Apres"));
}
// DAG checks: Part 4: Interaction with simple checks
TEST(Match, DAGsAreTerminatedBySimple) {
const auto result =
Match("After\nsimple\nBefore\n",
"CHECK-DAG: Before\nCHECK: simple\nCHECK-DAG: After");
EXPECT_FALSE(result) << result.message();
EXPECT_THAT(result.message(), HasSubstr(kNotFound));
EXPECT_THAT(result.message(), HasSubstr("CHECK-DAG: Before"));
}
TEST(Match, TwoDAGsAreTerminatedBySimple) {
const auto result = Match("After\nApres\nBlocker\nBefore\nAnte",
"CHECK-DAG: Ante\nCHECK-DAG: Before\nCHECK: "
"Blocker\nCHECK-DAG: Apres\nCHECK-DAG: After");
EXPECT_FALSE(result) << result.message();
EXPECT_THAT(result.message(), HasSubstr(kNotFound));
EXPECT_THAT(result.message(), HasSubstr("CHECK-DAG: Ante"));
}
// Test detailed message text
TEST(Match, MessageStringNotFoundWhenNeverMatchedAnything) {
const char* input = R"(Begin
Hello
World)";
const char* checks = R"(
Hello
; CHECK: Needle
)";
const char* expected = R"(chklist:3:13: error: expected string not found in input
; CHECK: Needle
^
myin.txt:1:1: note: scanning from here
Begin
^
)";
const auto result =
Match(input, checks,
Options().SetInputName("myin.txt").SetChecksName("chklist"));
EXPECT_FALSE(result);
EXPECT_THAT(result.message(), Eq(expected)) << result.message();
}
TEST(Match, MessageStringNotFoundAfterInitialMatch) {
const char* input = R"(Begin
Hello
World)";
const char* checks = R"(
Hello
; CHECK-LABEL: Hel
; CHECK: Needle
)";
const char* expected = R"(chklist:4:13: error: expected string not found in input
; CHECK: Needle
^
myin.txt:2:4: note: scanning from here
Hello
^
)";
const auto result =
Match(input, checks,
Options().SetInputName("myin.txt").SetChecksName("chklist"));
EXPECT_FALSE(result);
EXPECT_THAT(result.message(), Eq(expected)) << result.message();
}
TEST(Match, MessageCheckNotStringFoundAtStart) {
const auto result =
Match(" Cheese", "CHECK-NOT: Cheese",
Options().SetInputName("in").SetChecksName("checks"));
EXPECT_FALSE(result);
const char* expected = R"(in:1:3: error: CHECK-NOT: string occurred!
Cheese
^
checks:1:12: note: CHECK-NOT: pattern specified here
CHECK-NOT: Cheese
^
)";
EXPECT_THAT(result.message(), Eq(expected)) << result.message();
}
TEST(Match, MessageCheckNotStringFoundAfterInitialMatch) {
const auto result =
Match("Cream Cheese", "CHECK: Cream\nCHECK-NOT: Cheese",
Options().SetInputName("in").SetChecksName("checks"));
EXPECT_FALSE(result);
const char* expected = R"(in:1:10: error: CHECK-NOT: string occurred!
Cream Cheese
^
checks:2:12: note: CHECK-NOT: pattern specified here
CHECK-NOT: Cheese
^
)";
EXPECT_THAT(result.message(), Eq(expected)) << result.message();
}
TEST(Match, MessageCheckSameFails) {
const char* input = R"(
Bees
Make
Delicious Honey
)";
const char* checks = R"(
CHECK: Make
CHECK-SAME: Honey
)";
const auto result = Match(
input, checks, Options().SetInputName("in").SetChecksName("checks"));
EXPECT_FALSE(result);
const char* expected = R"(checks:3:13: error: CHECK-SAME: is not on the same line as previous match
CHECK-SAME: Honey
^
in:4:11: note: 'next' match was here
Delicious Honey
^
in:3:5: note: previous match ended here
Make
^
)";
EXPECT_THAT(result.message(), Eq(expected)) << result.message();
}
TEST(Match, MessageCheckNextFailsSinceOnSameLine) {
const char* input = R"(
Bees
Make
Delicious Honey
)";
const char* checks = R"(
CHECK: Bees
CHECK-NEXT: Honey
)";
const auto result = Match(
input, checks, Options().SetInputName("in").SetChecksName("checks"));
EXPECT_FALSE(result);
const char* expected = R"(checks:3:13: error: CHECK-NEXT: is not on the line after the previous match
CHECK-NEXT: Honey
^
in:4:11: note: 'next' match was here
Delicious Honey
^
in:2:5: note: previous match ended here
Bees
^
in:3:1: note: non-matching line after previous match is here
Make
^
)";
EXPECT_THAT(result.message(), Eq(expected)) << result.message();
}
TEST(Match, MessageCheckNextFailsSinceLaterLine) {
const char* input = R"(
Bees Make Delicious Honey
)";
const char* checks = R"(
CHECK: Make
CHECK-NEXT: Honey
)";
const auto result = Match(
input, checks, Options().SetInputName("in").SetChecksName("checks"));
EXPECT_FALSE(result);
const char* expected = R"(checks:3:13: error: CHECK-NEXT: is on the same line as previous match
CHECK-NEXT: Honey
^
in:2:21: note: 'next' match was here
Bees Make Delicious Honey
^
in:2:10: note: previous match ended here
Bees Make Delicious Honey
^
)";
EXPECT_THAT(result.message(), Eq(expected)) << result.message();
}
TEST(Match, MessageUnresolvedDAG) {
const char* input = R"(
Bees
Make
Delicious Honey
)";
const char* checks = R"(
CHECK: ees
CHECK-DAG: Flowers
CHECK: Honey
)";
const auto result = Match(
input, checks, Options().SetInputName("in").SetChecksName("checks"));
EXPECT_FALSE(result);
const char* expected = R"(checks:3:12: error: expected string not found in input
CHECK-DAG: Flowers
^
in:2:5: note: scanning from here
Bees
^
in:4:11: note: next check matches here
Delicious Honey
^
)";
EXPECT_THAT(result.message(), Eq(expected)) << result.message();
}
// Regexp
TEST(Match, CheckRegexPass) {
const auto result = Match("Hello", "CHECK: He{{ll}}o");
EXPECT_TRUE(result) << result.message();
}
TEST(Match, CheckRegexWithFalseStartPass) {
// This examples has three false starts. That is, we match the first
// few parts of the pattern before we finally match it.
const auto result = Match("He Hel Hell Hello Helloo", "CHECK: He{{ll}}oo");
EXPECT_TRUE(result) << result.message();
}
TEST(Match, CheckRegexWithRangePass) {
const auto result = Match("Hello", "CHECK: He{{[a-z]+}}o");
EXPECT_TRUE(result) << result.message();
}
TEST(Match, CheckRegexMatchesEmptyPass) {
const auto result = Match("Heo", "CHECK: He{{[a-z]*}}o");
EXPECT_TRUE(result) << result.message();
}
TEST(Match, CheckThreeRegexPass) {
// This proves that we parsed the check correctly, finding matching pairs
// of regexp delimiters {{ and }}.
const auto result = Match("Hello World", "CHECK: He{{[a-z]+}}o{{ +}}{{[Ww]}}orld");
EXPECT_TRUE(result) << result.message();
}
TEST(Match, CheckRegexFail) {
const auto result = Match("Heo", "CHECK: He{{[a-z]*}}o");
EXPECT_TRUE(result) << result.message();
}
TEST(Match, MessageStringRegexRegexWithFalseStartFail) {
const char* input = "He Hel Hell Hello Hello";
const char* checks = "CHECK: He{{ll}}oo";
const char* expected = R"(chklist:1:8: error: expected string not found in input
CHECK: He{{ll}}oo
^
myin.txt:1:1: note: scanning from here
He Hel Hell Hello Hello
^
)";
const auto result =
Match(input, checks,
Options().SetInputName("myin.txt").SetChecksName("chklist"));
EXPECT_FALSE(result);
EXPECT_THAT(result.message(), Eq(expected)) << result.message();
}
TEST(Match, MessageStringRegexNotFoundWhenNeverMatchedAnything) {
const char* input = R"(Begin
Hello
World)";
const char* checks = R"(
Hello
; CHECK: He{{[0-9]+}}llo
)";
const char* expected = R"(chklist:3:13: error: expected string not found in input
; CHECK: He{{[0-9]+}}llo
^
myin.txt:1:1: note: scanning from here
Begin
^
)";
const auto result =
Match(input, checks,
Options().SetInputName("myin.txt").SetChecksName("chklist"));
EXPECT_FALSE(result);
EXPECT_THAT(result.message(), Eq(expected)) << result.message();
}
// Statefulness: variable definitions and uses
TEST(Match, VarDefFollowedByUsePass) {
const auto result =
Match("Hello\nHello", "CHECK: H[[X:[a-z]+]]o\nCHECK-NEXT: H[[X]]o");
EXPECT_TRUE(result) << result.message();
}
TEST(Match, VarDefFollowedByUseFail) {
const auto result =
Match("Hello\n\nWorld", "CHECK: H[[X:[a-z]+]]o\nCHECK: H[[X]]o");
EXPECT_FALSE(result) << result.message();
EXPECT_THAT(result.message(),
HasSubstr(":2:8: error: expected string not found in input"));
EXPECT_THAT(result.message(),
HasSubstr("note: with variable \"X\" equal to \"ell\""));
}
TEST(Match, VarDefFollowedByUseFailAfterDAG) {
const auto result =
Match("Hello\nWorld",
"CHECK: H[[X:[a-z]+]]o\nCHECK-DAG: box[[X]]\nCHECK: H[[X]]o");
EXPECT_FALSE(result) << result.message();
EXPECT_THAT(result.message(),
HasSubstr(":2:12: error: expected string not found in input"));
EXPECT_THAT(result.message(),
HasSubstr("note: with variable \"X\" equal to \"ell\""));
}
TEST(Match, VarDefFollowedByUseInNotCheck) {
const auto result =
Match("Hello\nHello", "CHECK: H[[X:[a-z]+]]o\nCHECK-NOT: H[[X]]o");
EXPECT_FALSE(result) << result.message();
EXPECT_THAT(result.message(), HasSubstr("CHECK-NOT: string occurred"));
EXPECT_THAT(result.message(),
HasSubstr("note: with variable \"X\" equal to \"ell\""));
}
TEST(Match, VarDefFollowedByUseInNextCheckRightLine) {
const auto result =
Match("Hello\nHello", "CHECK: H[[X:[a-z]+]]o\nCHECK-NEXT: Blad[[X]]");
EXPECT_FALSE(result) << result.message();
EXPECT_THAT(result.message(),
HasSubstr(":2:13: error: expected string not found in input"));
EXPECT_THAT(result.message(),
HasSubstr("note: with variable \"X\" equal to \"ell\""));
}
TEST(Match, VarDefFollowedByUseInNextCheckBadLine) {
const auto result =
Match("Hello\n\nHello", "CHECK: H[[X:[a-z]+]]o\nCHECK-NEXT: H[[X]]o");
EXPECT_FALSE(result) << result.message();
EXPECT_THAT(result.message(),
HasSubstr(":2:13: error: CHECK-NEXT: is not on the line after"));
EXPECT_THAT(result.message(),
HasSubstr("note: with variable \"X\" equal to \"ell\""));
}
TEST(Match, UndefinedVarNeverMatches) {
const auto result = Match("Hello HeXllo", "CHECK: He[[X]]llo");
EXPECT_FALSE(result) << result.message();
EXPECT_THAT(result.message(),
HasSubstr("note: uses undefined variable \"X\""));
}
TEST(Match, NoteSeveralUndefinedVariables) {
const auto result = Match("Hello HeXllo", "CHECK: He[[X]]l[[YZ]]lo[[Q]]");
EXPECT_FALSE(result) << result.message();
const char* substr = R"(
<stdin>:1:1: note: uses undefined variable "X"
Hello HeXllo
^
<stdin>:1:1: note: uses undefined variable "YZ"
Hello HeXllo
^
<stdin>:1:1: note: uses undefined variable "Q"
Hello HeXllo
^
)";
EXPECT_THAT(result.message(), HasSubstr(substr));
}
TEST(Match, OutOfOrderDefAndUseViaDAGChecks) {
// In this example the X variable should be set to 'l', and then match
// the earlier occurrence in 'Hello'.
const auto result = Match(
"Hello\nWorld", "CHECK-DAG: Wor[[X:[a-z]+]]d\nCHECK-DAG: He[[X]]lo");
EXPECT_FALSE(result) << result.message();
}
TEST(Match, VarDefRegexCountsParenthesesProperlyPass) {
const auto result = Match(
"FirstabababSecondcdcd\n1ababab2cdcd",
"CHECK: First[[X:(ab)+]]Second[[Y:(cd)+]]\nCHECK: 1[[X]]2[[Y]]");
EXPECT_TRUE(result) << result.message();
}
TEST(Match, VarDefRegexCountsParenthesesProperlyFail) {
const auto result =
Match("Firstababab1abab", "CHECK: First[[X:(ab)+]]\nCHECK: 1[[X]]");
EXPECT_FALSE(result) << result.message();
const char* substr = R"(<stdin>:2:8: error: expected string not found in input
CHECK: 1[[X]]
^
<stdin>:1:12: note: scanning from here
Firstababab1abab
^
<stdin>:1:12: note: with variable "X" equal to "ababab"
Firstababab1abab
^
)";
EXPECT_THAT(result.message(), HasSubstr(substr));
}
} // namespace