| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you 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 "benchmark/cli_option_parsing.h" |
| |
| #include <cstdint> |
| #include <string> |
| #include <utility> |
| #include <vector> |
| |
| #include "gtest/gtest.h" |
| #include "paimon/testing/utils/testharness.h" |
| |
| namespace paimon::testing { |
| namespace { |
| |
| struct ArgvHolder { |
| std::vector<std::string> args; |
| std::vector<char*> argv; |
| |
| explicit ArgvHolder(std::vector<std::string> in_args) : args(std::move(in_args)) { |
| argv.reserve(args.size()); |
| for (auto& arg : args) { |
| argv.push_back(arg.data()); |
| } |
| } |
| |
| int32_t argc() const { |
| return static_cast<int32_t>(argv.size()); |
| } |
| }; |
| |
| TEST(CliOptionParsingTest, ConsumeCliOptionWorks) { |
| std::string value; |
| ASSERT_TRUE(paimon::benchmark::ConsumeCliOption("--foo=bar", "--foo", &value)); |
| ASSERT_EQ(value, "bar"); |
| |
| value.clear(); |
| ASSERT_FALSE(paimon::benchmark::ConsumeCliOption("--foo", "--foo", &value)); |
| } |
| |
| TEST(CliOptionParsingTest, ParseCommaSeparatedColumnsWorks) { |
| ASSERT_OK_AND_ASSIGN(auto parsed, |
| paimon::benchmark::ParseCommaSeparatedColumns("id, name,age", "--cols")); |
| ASSERT_EQ(parsed.size(), 3U); |
| ASSERT_EQ(parsed[0], "id"); |
| ASSERT_EQ(parsed[1], "name"); |
| ASSERT_EQ(parsed[2], "age"); |
| } |
| |
| TEST(CliOptionParsingTest, ParseCommaSeparatedColumnsRejectsInvalidInput) { |
| ASSERT_NOK(paimon::benchmark::ParseCommaSeparatedColumns("", "--cols")); |
| ASSERT_NOK(paimon::benchmark::ParseCommaSeparatedColumns("id,", "--cols")); |
| ASSERT_NOK(paimon::benchmark::ParseCommaSeparatedColumns("id,,name", "--cols")); |
| } |
| |
| TEST(CliOptionParsingTest, ParseDelimitedOptionsWorks) { |
| ASSERT_OK_AND_ASSIGN( |
| auto parsed, paimon::benchmark::ParseDelimitedOptions("k1:v1;k2:v2", "--paimon_option")); |
| ASSERT_EQ(parsed.size(), 2U); |
| ASSERT_EQ(parsed[0], std::make_pair(std::string("k1"), std::string("v1"))); |
| ASSERT_EQ(parsed[1], std::make_pair(std::string("k2"), std::string("v2"))); |
| } |
| |
| TEST(CliOptionParsingTest, ParseDelimitedOptionsTrimsKeyAndValue) { |
| ASSERT_OK_AND_ASSIGN(auto parsed, paimon::benchmark::ParseDelimitedOptions(" k1 : v1 ; k2: v2 ", |
| "--paimon_option")); |
| ASSERT_EQ(parsed.size(), 2U); |
| ASSERT_EQ(parsed[0], std::make_pair(std::string("k1"), std::string("v1"))); |
| ASSERT_EQ(parsed[1], std::make_pair(std::string("k2"), std::string("v2"))); |
| } |
| |
| TEST(CliOptionParsingTest, ParseDelimitedOptionsRejectsInvalidInput) { |
| ASSERT_NOK(paimon::benchmark::ParseDelimitedOptions("", "--paimon_option")); |
| ASSERT_NOK(paimon::benchmark::ParseDelimitedOptions("k1:v1;", "--paimon_option")); |
| ASSERT_NOK(paimon::benchmark::ParseDelimitedOptions("k1:", "--paimon_option")); |
| ASSERT_NOK(paimon::benchmark::ParseDelimitedOptions(":v1", "--paimon_option")); |
| ASSERT_NOK(paimon::benchmark::ParseDelimitedOptions("k1: ", "--paimon_option")); |
| } |
| |
| TEST(CliOptionParsingTest, ParseStringOptionArgWorksForEqualsAndSeparatedForms) { |
| { |
| ArgvHolder argv_holder({"prog", "--foo=bar"}); |
| int32_t arg_index = 1; |
| std::string value; |
| ASSERT_OK_AND_ASSIGN(bool is_parsed, |
| paimon::benchmark::ParseStringOptionArg( |
| argv_holder.argc(), argv_holder.argv.data(), |
| argv_holder.args[arg_index], "--foo", &arg_index, &value)); |
| ASSERT_TRUE(is_parsed); |
| ASSERT_EQ(arg_index, 1); |
| ASSERT_EQ(value, "bar"); |
| } |
| |
| { |
| ArgvHolder argv_holder({"prog", "--foo", "bar"}); |
| int32_t arg_index = 1; |
| std::string value; |
| ASSERT_OK_AND_ASSIGN(bool is_parsed, |
| paimon::benchmark::ParseStringOptionArg( |
| argv_holder.argc(), argv_holder.argv.data(), |
| argv_holder.args[arg_index], "--foo", &arg_index, &value)); |
| ASSERT_TRUE(is_parsed); |
| ASSERT_EQ(arg_index, 2); |
| ASSERT_EQ(value, "bar"); |
| } |
| } |
| |
| TEST(CliOptionParsingTest, ParseStringOptionArgRejectsMissingValue) { |
| ArgvHolder argv_holder({"prog", "--foo"}); |
| int32_t arg_index = 1; |
| std::string value; |
| ASSERT_NOK(paimon::benchmark::ParseStringOptionArg(argv_holder.argc(), argv_holder.argv.data(), |
| argv_holder.args[arg_index], "--foo", |
| &arg_index, &value)); |
| } |
| |
| TEST(CliOptionParsingTest, ParseStringOptionArgIgnoresOtherOptions) { |
| ArgvHolder argv_holder({"prog", "--bar=baz"}); |
| int32_t arg_index = 1; |
| std::string value; |
| ASSERT_OK_AND_ASSIGN(bool is_parsed, |
| paimon::benchmark::ParseStringOptionArg( |
| argv_holder.argc(), argv_holder.argv.data(), |
| argv_holder.args[arg_index], "--foo", &arg_index, &value)); |
| ASSERT_FALSE(is_parsed); |
| ASSERT_EQ(arg_index, 1); |
| ASSERT_TRUE(value.empty()); |
| } |
| |
| TEST(CliOptionParsingTest, ParseCommaSeparatedOptionArgAndDelimitedRepeatableOptionArgWorks) { |
| { |
| ArgvHolder argv_holder({"prog", "--cols", "id,name"}); |
| int32_t arg_index = 1; |
| std::vector<std::string> columns; |
| ASSERT_OK_AND_ASSIGN(bool is_parsed, |
| paimon::benchmark::ParseCommaSeparatedOptionArg( |
| argv_holder.argc(), argv_holder.argv.data(), |
| argv_holder.args[arg_index], "--cols", &arg_index, &columns)); |
| ASSERT_TRUE(is_parsed); |
| ASSERT_EQ(arg_index, 2); |
| ASSERT_EQ(columns.size(), 2U); |
| ASSERT_EQ(columns[0], "id"); |
| ASSERT_EQ(columns[1], "name"); |
| } |
| |
| { |
| ArgvHolder argv_holder({"prog", "--paimon_option", "k1:v1;k2:v2"}); |
| int32_t arg_index = 1; |
| std::vector<std::pair<std::string, std::string>> options; |
| ASSERT_OK_AND_ASSIGN(bool is_parsed, paimon::benchmark::ParseDelimitedRepeatableOptionArg( |
| argv_holder.argc(), argv_holder.argv.data(), |
| argv_holder.args[arg_index], "--paimon_option", |
| &arg_index, &options)); |
| ASSERT_TRUE(is_parsed); |
| ASSERT_EQ(arg_index, 2); |
| ASSERT_EQ(options.size(), 2U); |
| ASSERT_EQ(options[0], std::make_pair(std::string("k1"), std::string("v1"))); |
| ASSERT_EQ(options[1], std::make_pair(std::string("k2"), std::string("v2"))); |
| } |
| } |
| |
| } // namespace |
| } // namespace paimon::testing |