// 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
