blob: 42b7eb650d84507e43452bebd8234147c9c43791 [file]
/*
* 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 "cli/cli_args.h"
#include <gtest/gtest.h>
#include <sstream>
#include "cli/run_cli.h"
TEST(RunCliTest, VersionFlagPrintsVersionAndReturnsOk) {
std::ostringstream out;
std::ostringstream err;
int code = tsfile_cli::run_cli({"--version"}, out, err);
EXPECT_EQ(code, 0);
EXPECT_NE(out.str().find("tsfile"), std::string::npos);
EXPECT_TRUE(err.str().empty());
}
TEST(RunCliTest, NoArgsPrintsUsageToErrAndReturnsUsageError) {
std::ostringstream out;
std::ostringstream err;
int code = tsfile_cli::run_cli({}, out, err);
EXPECT_EQ(code, 1);
EXPECT_NE(err.str().find("Usage"), std::string::npos);
}
TEST(RunCliTest, UnknownCommandIsUsageError) {
std::ostringstream out;
std::ostringstream err;
int code = tsfile_cli::run_cli({"frobnicate", "x.tsfile"}, out, err);
EXPECT_EQ(code, 1);
EXPECT_NE(err.str().find("Unknown command"), std::string::npos);
}
TEST(RunCliTest, LeadingOptionBeforeCommandIsClearError) {
std::ostringstream out;
std::ostringstream err;
int code =
tsfile_cli::run_cli({"-f", "json", "meta", "data.tsfile"}, out, err);
EXPECT_EQ(code, 1);
EXPECT_NE(err.str().find("command must come before options"),
std::string::npos)
<< err.str();
}
TEST(ParseArgsTest, CommandAndFilePositional) {
auto p = tsfile_cli::parse_args({"ls", "data.tsfile"});
EXPECT_TRUE(p.error.empty());
EXPECT_EQ(p.command, "ls");
EXPECT_EQ(p.file, "data.tsfile");
}
TEST(ParseArgsTest, FormatFlagParsed) {
auto p = tsfile_cli::parse_args({"cat", "-f", "json", "data.tsfile"});
EXPECT_TRUE(p.error.empty());
EXPECT_EQ(p.format, tsfile_cli::ParsedArgs::Format::kJson);
}
TEST(ParseArgsTest, MeasurementsSplitOnComma) {
auto p = tsfile_cli::parse_args({"cat", "-m", "s1,s2,s3", "data.tsfile"});
ASSERT_EQ(p.measurements.size(), 3u);
EXPECT_EQ(p.measurements[1], "s2");
}
TEST(ParseArgsTest, LimitOffsetAndTimeRange) {
auto p =
tsfile_cli::parse_args({"head", "-n", "5", "--offset", "2", "--start",
"100", "--end", "200", "data.tsfile"});
EXPECT_EQ(p.limit, 5);
EXPECT_EQ(p.offset, 2);
EXPECT_TRUE(p.has_start);
EXPECT_EQ(p.start, 100);
EXPECT_TRUE(p.has_end);
EXPECT_EQ(p.end, 200);
}
TEST(ParseArgsTest, TagFilterParsed) {
auto p = tsfile_cli::parse_args(
{"cat", "--tag-filter", "id1", "eq", "dev_a", "data.tsfile"});
EXPECT_TRUE(p.error.empty());
EXPECT_TRUE(p.has_tag_filter);
EXPECT_EQ(p.tag_filter_op, tsfile_cli::ParsedArgs::TagFilterOp::kEq);
EXPECT_EQ(p.tag_filter_column, "id1");
EXPECT_EQ(p.tag_filter_value, "dev_a");
}
TEST(ParseArgsTest, TagBetweenParsed) {
auto p = tsfile_cli::parse_args(
{"cat", "--tag-between", "id1", "dev_a", "dev_c", "data.tsfile"});
EXPECT_TRUE(p.error.empty());
EXPECT_TRUE(p.has_tag_filter);
EXPECT_EQ(p.tag_filter_op, tsfile_cli::ParsedArgs::TagFilterOp::kBetween);
EXPECT_EQ(p.tag_filter_column, "id1");
EXPECT_EQ(p.tag_filter_value, "dev_a");
EXPECT_EQ(p.tag_filter_value2, "dev_c");
}
TEST(ParseArgsTest, DuplicateTagFilterIsError) {
auto p = tsfile_cli::parse_args({"cat", "--tag-filter", "id1", "eq",
"dev_a", "--tag-between", "id1", "a", "z",
"data.tsfile"});
EXPECT_FALSE(p.error.empty());
}
TEST(ParseArgsTest, UnknownFlagIsError) {
auto p = tsfile_cli::parse_args({"ls", "--bogus", "data.tsfile"});
EXPECT_FALSE(p.error.empty());
}
TEST(ParseArgsTest, BadFormatValueIsError) {
auto p = tsfile_cli::parse_args({"cat", "-f", "yaml", "data.tsfile"});
EXPECT_FALSE(p.error.empty());
}
TEST(ParseArgsTest, MissingFileIsAllowedAtParseTime) {
auto p = tsfile_cli::parse_args({"ls"});
EXPECT_TRUE(p.error.empty());
EXPECT_EQ(p.command, "ls");
EXPECT_TRUE(p.file.empty());
}
TEST(ParseArgsTest, WriteFlagsParsed) {
auto p = tsfile_cli::parse_args({"write", "--table", "t1", "--columns",
"s1:INT64:field", "-o", "out.tsfile", "-v",
"--header-match", "in.csv"});
EXPECT_TRUE(p.error.empty());
EXPECT_EQ(p.command, "write");
EXPECT_EQ(p.table, "t1");
EXPECT_EQ(p.columns, "s1:INT64:field");
EXPECT_EQ(p.output, "out.tsfile");
EXPECT_TRUE(p.verbose);
EXPECT_TRUE(p.header_match);
EXPECT_EQ(p.file, "in.csv");
}
TEST(ParseArgsTest, OutputFlagNeedsValue) {
auto p = tsfile_cli::parse_args({"write", "-o"});
EXPECT_FALSE(p.error.empty());
}
TEST(ParseArgsTest, DashIsStdinPositional) {
auto p =
tsfile_cli::parse_args({"write", "--table", "t1", "--columns",
"s1:INT64:field", "-o", "out.tsfile", "-"});
EXPECT_TRUE(p.error.empty());
EXPECT_EQ(p.file, "-");
}
TEST(ParseArgsTest, SeedFlagParsed) {
auto p = tsfile_cli::parse_args(
{"sample", "-m", "s1", "-n", "3", "--seed", "42", "data.tsfile"});
EXPECT_TRUE(p.error.empty());
EXPECT_EQ(p.command, "sample");
EXPECT_EQ(p.limit, 3);
EXPECT_TRUE(p.has_seed);
EXPECT_EQ(p.seed, 42);
}
TEST(ParseArgsTest, BadSeedValueIsError) {
auto p = tsfile_cli::parse_args(
{"sample", "--seed", "not_a_number", "data.tsfile"});
EXPECT_FALSE(p.error.empty());
EXPECT_NE(p.error.find("Invalid --seed"), std::string::npos);
}
TEST(RunCliTest, SelectIsNoLongerKnownCommand) {
std::ostringstream out;
std::ostringstream err;
int code = tsfile_cli::run_cli({"select", "x.tsfile"}, out, err);
EXPECT_EQ(code, 1);
EXPECT_NE(err.str().find("Unknown command"), std::string::npos);
}
TEST(RunCliTest, SeedOnCatIsUsageError) {
std::ostringstream out;
std::ostringstream err;
int code =
tsfile_cli::run_cli({"cat", "--seed", "7", "x.tsfile"}, out, err);
EXPECT_EQ(code, 1);
EXPECT_NE(err.str().find("--seed is only valid for sample"),
std::string::npos);
}
TEST(RunCliTest, OffsetOnSampleIsUsageError) {
std::ostringstream out;
std::ostringstream err;
int code =
tsfile_cli::run_cli({"sample", "--offset", "2", "x.tsfile"}, out, err);
EXPECT_EQ(code, 1);
EXPECT_NE(err.str().find("--offset is not valid for sample"),
std::string::npos);
}