// 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/util/subcommand.h"

#include <iostream>
#include <sstream>
#include <string>
#include <vector>

#include "absl/strings/match.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"

namespace verible {
namespace {

TEST(SubcommandRegistryTest, NoNewCommands) {
  SubcommandRegistry registry;
  const std::string command_list = registry.ListCommands();
  EXPECT_TRUE(absl::StrContains(command_list, "help"));
  // Make sure the internal 'error' command is not shown in help.
  EXPECT_FALSE(absl::StrContains(command_list, "error"));
}

TEST(SubcommandRegistryTest, HelpNoArgsTest) {
  SubcommandRegistry registry;
  // Test built-in help command.
  const SubcommandEntry& help(registry.GetSubcommandEntry("help"));
  std::istringstream ins;
  std::ostringstream outs, errs;
  std::vector<absl::string_view> args;
  const SubcommandArgsRange range(args.begin(), args.end());
  const auto status = help.main(range, ins, outs, errs);
  EXPECT_TRUE(status.ok()) << "Unexpected error:\n" << status.message();
  EXPECT_TRUE(outs.str().empty()) << outs.str();
  EXPECT_TRUE(absl::StrContains(errs.str(), "available commands:"));
}

TEST(SubcommandRegistryTest, HelpHelpCommand) {
  SubcommandRegistry registry;
  // Test built-in help command.
  const SubcommandEntry& help(registry.GetSubcommandEntry("help"));
  std::istringstream ins;
  std::ostringstream outs, errs;
  std::vector<absl::string_view> args{"help"};
  const SubcommandArgsRange range(args.begin(), args.end());

  const auto status = help.main(range, ins, outs, errs);
  EXPECT_TRUE(status.ok()) << "Unexpected error:\n" << status.message();
  EXPECT_TRUE(outs.str().empty()) << outs.str();
  EXPECT_TRUE(absl::StrContains(errs.str(), "Prints command help."));
}

static const SubcommandEntry fizz_func{
    [](const SubcommandArgsRange, std::istream&, std::ostream& outs,
       std::ostream&) {
      outs << 42;
      return absl::OkStatus();
    },
    "fizz does almost nothing",
    true,  // public
};

TEST(SubcommandRegistryTest, RegisterCommandPublicOk) {
  SubcommandRegistry registry;
  {
    const auto status = registry.RegisterCommand("fizz", fizz_func);
    EXPECT_TRUE(status.ok()) << "Unexpected error:\n" << status.message();
    EXPECT_TRUE(absl::StrContains(registry.ListCommands(), "fizz"));
  }

  std::vector<absl::string_view> args;
  const SubcommandArgsRange range(args.begin(), args.end());
  const SubcommandEntry& fizz_entry(registry.GetSubcommandEntry("fizz"));

  std::istringstream ins;
  std::ostringstream outs, errs;
  const auto status = fizz_entry.main(range, ins, outs, errs);
  EXPECT_TRUE(status.ok()) << "Unexpected error:\n" << status.message();
  EXPECT_EQ(outs.str(), "42");
}

TEST(SubcommandRegistryTest, ShowRegisteredCommandsOnWrongCommandRequest) {
  SubcommandRegistry registry;
  {
    const auto status = registry.RegisterCommand("fizz", fizz_func);
    EXPECT_TRUE(absl::StrContains(registry.ListCommands(), "fizz"));
  }

  const SubcommandEntry& cmd(registry.GetSubcommandEntry("wrong_command"));

  std::vector<absl::string_view> args{"foo", "bar"};
  const SubcommandArgsRange range(args.begin(), args.end());
  std::istringstream ins;
  std::ostringstream outs, errs;
  const auto status = cmd.main(range, ins, outs, errs);
  EXPECT_FALSE(status.ok()) << status.message();
  EXPECT_TRUE(absl::StrContains(errs.str(), "available commands"));
  EXPECT_TRUE(absl::StrContains(errs.str(), "fizz"));
}

static const SubcommandEntry buzz_func{
    [](const SubcommandArgsRange, std::istream&, std::ostream& outs,
       std::ostream&) {
      outs << 99;
      return absl::OkStatus();
    },
    "buzz does almost nothing",
    false,  // hidden
};

TEST(SubcommandRegistryTest, RegisterCommandHiddenOk) {
  SubcommandRegistry registry;
  {
    const auto status = registry.RegisterCommand("buzz", buzz_func);
    EXPECT_TRUE(status.ok()) << "Unexpected error:\n" << status.message();
    EXPECT_FALSE(absl::StrContains(registry.ListCommands(), "buzz"));
  }

  std::vector<absl::string_view> args;
  const SubcommandArgsRange range(args.begin(), args.end());
  const SubcommandEntry& buzz_entry(registry.GetSubcommandEntry("buzz"));

  std::istringstream ins;
  std::ostringstream outs, errs;
  const auto status = buzz_entry.main(range, ins, outs, errs);
  EXPECT_TRUE(status.ok()) << "Unexpected error:\n" << status.message();
  EXPECT_EQ(outs.str(), "99");
}

TEST(SubcommandRegistryTest, RegisterCommandErrorAlreadyRegistered) {
  SubcommandRegistry registry;
  // "help" is already a registered command
  const auto status = registry.RegisterCommand("help", fizz_func);
  EXPECT_FALSE(status.ok());
  EXPECT_TRUE(
      absl::StrContains(status.message(), "has already been registered"));
}

TEST(SubcommandRegistryTest, RegisterCommandMultipleCommands) {
  SubcommandRegistry registry;
  {
    {
      const auto status = registry.RegisterCommand("buzz", buzz_func);
      EXPECT_TRUE(status.ok()) << "Unexpected error:\n" << status.message();
    }
    {
      const auto status = registry.RegisterCommand("fizz", fizz_func);
      EXPECT_TRUE(status.ok()) << "Unexpected error:\n" << status.message();
    }
    const std::string command_list = registry.ListCommands();
    EXPECT_TRUE(absl::StrContains(command_list, "fizz"));
    EXPECT_FALSE(absl::StrContains(command_list, "buzz"));
  }

  // Run each subcommand once.
  std::vector<absl::string_view> args;
  const SubcommandArgsRange range(args.begin(), args.end());
  {
    const SubcommandEntry& fizz_entry(registry.GetSubcommandEntry("fizz"));
    std::istringstream ins;
    std::ostringstream outs, errs;
    const auto status = fizz_entry.main(range, ins, outs, errs);
    EXPECT_TRUE(status.ok()) << "Unexpected error:\n" << status.message();
    EXPECT_EQ(outs.str(), "42");
  }
  {
    const SubcommandEntry& buzz_entry(registry.GetSubcommandEntry("buzz"));
    std::istringstream ins;
    std::ostringstream outs, errs;
    const auto status = buzz_entry.main(range, ins, outs, errs);
    EXPECT_TRUE(status.ok()) << "Unexpected error:\n" << status.message();
    EXPECT_EQ(outs.str(), "99");
  }
}

}  // namespace
}  // namespace verible
