blob: f68c7f66903a191e1f35bd6743a1dee4d65f1070 [file] [log] [blame]
// 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 "common/analysis/line_linter.h"
#include <cstddef>
#include <memory>
#include <vector>
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "absl/strings/string_view.h"
#include "common/analysis/line_lint_rule.h"
#include "common/analysis/lint_rule_status.h"
#include "common/text/token_info.h"
namespace verible {
namespace {
using testing::IsEmpty;
using testing::SizeIs;
// Example lint rule for the purposes of testing LineLinter.
// Blank lines are considered bad for demonstration purposes.
class BlankLineRule : public LineLintRule {
public:
BlankLineRule() {}
void HandleLine(absl::string_view line) override {
if (line.empty()) {
const TokenInfo token(0, line);
violations_.insert(LintViolation(token, "some reason"));
}
}
LintRuleStatus Report() const override { return LintRuleStatus(violations_); }
private:
std::set<LintViolation> violations_;
};
std::unique_ptr<LineLintRule> MakeBlankLineRule() {
return std::unique_ptr<LineLintRule>(new BlankLineRule);
}
// This test verifies that LineLinter works with no rules.
TEST(LineLinterTest, NoRules) {
std::vector<absl::string_view> lines;
LineLinter linter;
linter.Lint(lines);
std::vector<LintRuleStatus> statuses = linter.ReportStatus();
EXPECT_THAT(statuses, IsEmpty());
}
// This test verifies that LineLinter works with a single rule.
TEST(LineLinterTest, OneRuleAcceptsLines) {
std::vector<absl::string_view> lines{{"abc", "def"}};
LineLinter linter;
linter.AddRule(MakeBlankLineRule());
linter.Lint(lines);
std::vector<LintRuleStatus> statuses = linter.ReportStatus();
EXPECT_THAT(statuses, SizeIs(1));
EXPECT_TRUE(statuses[0].isOk());
EXPECT_THAT(statuses[0].violations, IsEmpty());
}
// This test verifies that LineLinter can find violations.
TEST(LineLinterTest, OneRuleRejectsLine) {
std::vector<absl::string_view> lines{{"abc", "", "def"}};
LineLinter linter;
linter.AddRule(MakeBlankLineRule());
linter.Lint(lines);
std::vector<LintRuleStatus> statuses = linter.ReportStatus();
EXPECT_THAT(statuses, SizeIs(1));
EXPECT_FALSE(statuses[0].isOk());
EXPECT_THAT(statuses[0].violations, SizeIs(1));
}
// Mock rule that rejects empty files.
class EmptyFileRule : public LineLintRule {
public:
EmptyFileRule() {}
void HandleLine(absl::string_view line) override { ++lines_; }
void Finalize() override {
if (lines_ == 0) {
violations_.insert(
LintViolation(TokenInfo::EOFToken(), "insufficient bytes"));
}
}
LintRuleStatus Report() const override { return LintRuleStatus(violations_); }
size_t lines_ = 0;
private:
std::set<LintViolation> violations_;
};
std::unique_ptr<LineLintRule> MakeEmptyFileRule() {
return std::unique_ptr<LineLintRule>(new EmptyFileRule);
}
// This test verifies that LineLinter calls Finalize without error.
TEST(LineLinterTest, FinalizeAccepts) {
std::vector<absl::string_view> lines{{"x"}};
LineLinter linter;
linter.AddRule(MakeEmptyFileRule());
linter.Lint(lines);
std::vector<LintRuleStatus> statuses = linter.ReportStatus();
EXPECT_THAT(statuses, SizeIs(1));
EXPECT_TRUE(statuses[0].isOk());
EXPECT_THAT(statuses[0].violations, IsEmpty());
}
// This test verifies that LineLinter can report an error during Finalize.
TEST(LineLinterTest, FinalizeRejects) {
std::vector<absl::string_view> lines;
LineLinter linter;
linter.AddRule(MakeEmptyFileRule());
linter.Lint(lines);
std::vector<LintRuleStatus> statuses = linter.ReportStatus();
EXPECT_THAT(statuses, SizeIs(1));
EXPECT_FALSE(statuses[0].isOk());
EXPECT_THAT(statuses[0].violations, SizeIs(1));
}
} // namespace
} // namespace verible