blob: df5228d3dd785cf0d814150051e714a558fb4995 [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/text/config_utils.h"
#include <cstdint>
#include <string>
#include <vector>
#include "absl/status/status.h"
#include "absl/strings/match.h"
#include "absl/strings/string_view.h"
#include "gtest/gtest.h"
namespace verible {
namespace config {
TEST(ConfigUtilsTest, ComplainInvalidParameter) {
absl::Status s;
// singular ...
s = ParseNameValues("baz:123", {{"foo", nullptr}});
EXPECT_FALSE(s.ok());
EXPECT_EQ(s.message(),
"baz: unknown parameter; supported "
"parameter is 'foo'");
// plural.
s = ParseNameValues("baz:123", {{"foo", nullptr}, {"bar", nullptr}});
EXPECT_FALSE(s.ok());
EXPECT_EQ(s.message(),
"baz: unknown parameter; supported "
"parameters are 'foo', 'bar'");
s = ParseNameValues("foo:123", {{"foo", nullptr}, {"bar", nullptr}});
EXPECT_TRUE(s.ok());
}
TEST(ConfigUtilsTest, ParseInteger) {
absl::Status s;
int value = -1;
s = ParseNameValues("baz:42", {{"baz", SetInt(&value, 0, 100)}});
EXPECT_TRUE(s.ok());
EXPECT_EQ(value, 42);
s = ParseNameValues("baz:fourtytwo", {{"baz", SetInt(&value, 0, 100)}});
EXPECT_FALSE(s.ok());
// would be cool though :)
EXPECT_EQ(s.message(), "baz: 'fourtytwo': Cannot parse integer");
s = ParseNameValues("baz:142", {{"baz", SetInt(&value, 0, 100)}});
EXPECT_FALSE(s.ok());
EXPECT_EQ(s.message(), "baz: 142 out of range [0...100]");
s = ParseNameValues("baz:-1", {{"baz", SetInt(&value, 0, 100)}});
EXPECT_FALSE(s.ok());
EXPECT_EQ(s.message(), "baz: -1 out of range [0...100]");
s = ParseNameValues("baz:-12345", {{"baz", SetInt(&value)}});
EXPECT_TRUE(s.ok());
EXPECT_EQ(value, -12345);
}
TEST(ConfigUtilsTest, ParseBool) {
absl::Status s;
bool value = false;
for (auto config : {"baz", "baz:TrUe", "baz:on", "baz:1"}) {
s = ParseNameValues(config, {{"baz", SetBool(&value)}});
EXPECT_TRUE(s.ok());
EXPECT_TRUE(value);
}
for (auto config : {"baz:fAlse", "baz:off", "baz:0"}) {
s = ParseNameValues(config, {{"baz", SetBool(&value)}});
EXPECT_TRUE(s.ok());
EXPECT_FALSE(value);
}
s = ParseNameValues("baz:foobar", {{"baz", SetBool(&value)}});
EXPECT_FALSE(s.ok());
EXPECT_TRUE(
absl::StartsWith(s.message(), "baz: Boolean value should be one of"));
}
TEST(ConfigUtilsTest, ParseString) {
absl::Status s;
std::string str;
s = ParseNameValues("baz:hello", {{"baz", SetString(&str)}});
EXPECT_TRUE(s.ok());
EXPECT_EQ(str, "hello");
s = ParseNameValues("baz:hello",
{{"baz", SetStringOneOf(&str, {"hello", "world"})}});
EXPECT_TRUE(s.ok());
EXPECT_EQ(str, "hello");
// Selection from multiple strings
s = ParseNameValues("baz:greetings",
{{"baz", SetStringOneOf(&str, {"hello", "world"})}});
EXPECT_FALSE(s.ok());
EXPECT_EQ(s.message(),
"baz: Value can only be one of ['hello', 'world']; "
"got 'greetings'");
// Selection from one string
s = ParseNameValues("baz:greetings",
{{"baz", SetStringOneOf(&str, {"hello"})}});
EXPECT_FALSE(s.ok());
EXPECT_EQ(s.message(), "baz: Value can only be 'hello'; got 'greetings'");
}
TEST(ConfigUtilsTest, ParseNamedBitmap) {
const std::vector<absl::string_view> kBitNames = {"ZERO", "ONE", "TWO"};
const std::pair<absl::string_view, uint32_t> kTestCases[] = {
{"baz:ONE", 1 << 1},
{"baz:", 0},
{"baz:ZERO|TWO", (1 << 0) | (1 << 2)},
{"baz:ZERO||TWO", (1 << 0) | (1 << 2)}, // Allowing empty value
{"baz:ZERO| |TWO", (1 << 0) | (1 << 2)}, // .. even with space
{"baz: ZERO | TWO", (1 << 0) | (1 << 2)}, // Whitespace around ok.
{"baz:zErO|TwO", (1 << 0) | (1 << 2)}, // case-insensitive
{"baz:TWO|ZERO", (1 << 0) | (1 << 2)}, // Sequence does not matter
{"baz:ZERO|ONE|TWO", (1 << 0) | (1 << 1) | (1 << 2)},
};
absl::Status s;
for (const auto& testcase : kTestCases) {
uint32_t bitmap = 0x12345678;
s = ParseNameValues(testcase.first,
{{"baz", SetNamedBits(&bitmap, kBitNames)}});
EXPECT_TRUE(s.ok()) << "case: '" << testcase.first << "' ->" << s.message();
EXPECT_EQ(bitmap, testcase.second);
}
{
uint32_t bitmap = 0x12345678;
s = ParseNameValues("baz:ONE|invalid",
{{"baz", SetNamedBits(&bitmap, kBitNames)}});
EXPECT_FALSE(s.ok());
EXPECT_EQ(s.message(),
"baz: 'invalid' is not in the available "
"choices {ZERO, ONE, TWO}");
EXPECT_EQ(bitmap, 0x12345678); // on parse failure, variable not modified.
}
}
TEST(ConfigUtilsTest, ParseMultipleParameters) {
absl::Status s;
int answer;
bool panic;
s = ParseNameValues("answer:42;panic:off", {{"answer", SetInt(&answer)},
{"panic", SetBool(&panic)}});
EXPECT_TRUE(s.ok());
EXPECT_FALSE(panic);
EXPECT_EQ(answer, 42);
s = ParseNameValues("answer:43;panic:on", {{"answer", SetInt(&answer)},
{"panic", SetBool(&panic)}});
EXPECT_TRUE(s.ok()) << s.message();
EXPECT_TRUE(panic);
EXPECT_EQ(answer, 43);
}
} // namespace config
} // namespace verible