blob: ea834404da969ad77563542cdda2a9ea011504d8 [file] [log] [blame]
// Copyright 2016 The Bazel Authors. All rights reserved.
//
// 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 "src/tools/singlejar/token_stream.h"
#include <stdio.h>
#include <stdlib.h>
#include <wchar.h>
#include <string>
#include "src/main/cpp/util/path_platform.h"
#include "src/tools/singlejar/test_util.h"
#include "googletest/include/gtest/gtest.h"
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
// Indirect command file contents (each string is a separate line):
static const char *lines[] = {
"-cmd1 foo", "bar", "'abcd'", "\"efg\"", "hi'x'",
"'\\jkl'", "\"\\xyz\"", "\"\\\"0\"", "cont\\", "inue x",
};
// Tokens that the tokenizer is expected to return from the
// indirect file above:
static const char *expected_tokens[] = {
"-cmd1", "foo", "bar", "abcd", "efg", "hix",
"\\jkl", "\\xyz", "\"0", "continue", "x",
};
// Simple '-foo -bar' command line.
TEST(TokenStreamTest, SimpleArgs) {
const char *args[] = {"-foo", "-bar"};
ArgTokenStream token_stream(ARRAY_SIZE(args), args);
EXPECT_EQ("-foo", token_stream.token());
bool flag_foo = false;
EXPECT_FALSE(token_stream.MatchAndSet("-bar", &flag_foo));
ASSERT_TRUE(token_stream.MatchAndSet("-foo", &flag_foo));
EXPECT_TRUE(flag_foo);
bool flag_bar = false;
ASSERT_TRUE(token_stream.MatchAndSet("-bar", &flag_bar));
EXPECT_TRUE(flag_bar);
EXPECT_TRUE(token_stream.AtEnd());
}
// '-foo @commandfile -bar' command line.
TEST(TokenStreamTest, CommandFile) {
const char *tempdir = getenv("TEST_TMPDIR");
ASSERT_NE(nullptr, tempdir);
std::string command_file_path = singlejar_test_util::OutputFilePath("tokens");
FILE *fp = fopen(command_file_path.c_str(), "w");
ASSERT_NE(nullptr, fp);
for (size_t i = 0; i < ARRAY_SIZE(lines); ++i) {
fprintf(fp, "%s\n", lines[i]);
}
fclose(fp);
std::string command_file_arg = std::string("@") + command_file_path;
const char *args[] = {"-before_file", "", "-after_file"};
args[1] = command_file_arg.c_str();
ArgTokenStream token_stream(ARRAY_SIZE(args), args);
bool flag = false;
ASSERT_TRUE(token_stream.MatchAndSet("-before_file", &flag));
EXPECT_TRUE(flag);
for (size_t i = 0; i < ARRAY_SIZE(expected_tokens); ++i) {
flag = false;
ASSERT_TRUE(token_stream.MatchAndSet(expected_tokens[i], &flag));
EXPECT_TRUE(flag);
}
ASSERT_TRUE(token_stream.MatchAndSet("-after_file", &flag));
EXPECT_TRUE(flag);
EXPECT_TRUE(token_stream.AtEnd());
}
#ifdef _WIN32
// '-foo @commandfile -bar' command line.
TEST(TokenStreamTest, CommandFileLongPath) {
const char *tempdir = getenv("TEST_TMPDIR");
ASSERT_NE(nullptr, tempdir);
std::wstring wpath;
std::string error;
std::string command_file_path =
singlejar_test_util::OutputFilePath(std::string(251, 'a'));
command_file_path += ".aaa\\";
ASSERT_TRUE(
blaze_util::AsAbsoluteWindowsPath(command_file_path, &wpath, &error))
<< error;
ASSERT_EQ(0, _wmkdir(wpath.c_str()));
command_file_path += std::string(251, 'b');
command_file_path += ".bbb\\";
ASSERT_TRUE(
blaze_util::AsAbsoluteWindowsPath(command_file_path, &wpath, &error))
<< error;
ASSERT_EQ(0, _wmkdir(wpath.c_str()));
command_file_path += std::string(251, 'c');
command_file_path += ".ccc";
ASSERT_TRUE(
blaze_util::AsAbsoluteWindowsPath(command_file_path, &wpath, &error))
<< error;
FILE *fp = _wfopen(wpath.c_str(), L"w");
ASSERT_NE(nullptr, fp);
for (size_t i = 0; i < ARRAY_SIZE(lines); ++i) {
fprintf(fp, "%s\n", lines[i]);
}
fclose(fp);
std::string command_file_arg = std::string("@") + command_file_path;
const char *args[] = {"-before_file", "", "-after_file"};
args[1] = command_file_arg.c_str();
ArgTokenStream token_stream(ARRAY_SIZE(args), args);
bool flag = false;
ASSERT_TRUE(token_stream.MatchAndSet("-before_file", &flag));
EXPECT_TRUE(flag);
for (size_t i = 0; i < ARRAY_SIZE(expected_tokens); ++i) {
flag = false;
ASSERT_TRUE(token_stream.MatchAndSet(expected_tokens[i], &flag));
EXPECT_TRUE(flag);
}
ASSERT_TRUE(token_stream.MatchAndSet("-after_file", &flag));
EXPECT_TRUE(flag);
EXPECT_TRUE(token_stream.AtEnd());
}
#endif
// '--arg1 optval1 --arg2' command line.
TEST(TokenStreamTest, OptargOne) {
const char *args[] = {"--arg1", "optval1", "--arg2", "--arg3", "optval3"};
ArgTokenStream token_stream(ARRAY_SIZE(args), args);
std::string optval;
EXPECT_FALSE(token_stream.MatchAndSet("--foo", &optval));
ASSERT_TRUE(token_stream.MatchAndSet("--arg1", &optval));
EXPECT_EQ("optval1", optval);
bool flag = true;
ASSERT_TRUE(token_stream.MatchAndSet("--arg2", &flag));
EXPECT_TRUE(flag);
ASSERT_TRUE(token_stream.MatchAndSet("--arg3", &optval));
EXPECT_EQ("optval3", optval);
EXPECT_TRUE(token_stream.AtEnd());
}
// '--arg1 value1 value2 --arg2' command line.
TEST(TokenStreamTest, OptargMulti) {
const char *args[] = {"--arg1", "value11", "value12",
"--arg2", "value21", "value22"};
ArgTokenStream token_stream(ARRAY_SIZE(args), args);
std::vector<std::string> optvals1;
EXPECT_FALSE(token_stream.MatchAndSet("--arg2", &optvals1));
ASSERT_TRUE(token_stream.MatchAndSet("--arg1", &optvals1));
ASSERT_EQ(2UL, optvals1.size());
EXPECT_EQ("value11", optvals1[0]);
EXPECT_EQ("value12", optvals1[1]);
std::vector<std::string> optvals2;
ASSERT_TRUE(token_stream.MatchAndSet("--arg2", &optvals2));
ASSERT_EQ(2UL, optvals2.size());
EXPECT_EQ("value21", optvals2[0]);
EXPECT_EQ("value22", optvals2[1]);
EXPECT_TRUE(token_stream.AtEnd());
}
// '--arg1 optval1,optsuff1 optval2,optstuff2 --arg2' command line.
TEST(TokenStreamTest, OptargMultiSplit) {
const char *args[] = {"--arg1", "optval1,optsuff1", "optval2,optsuff2",
"optvalnosuff"};
ArgTokenStream token_stream(ARRAY_SIZE(args), args);
std::vector<std::pair<std::string, std::string> > optvals1;
EXPECT_FALSE(token_stream.MatchAndSet("--foo", &optvals1));
ASSERT_TRUE(token_stream.MatchAndSet("--arg1", &optvals1));
ASSERT_EQ(3UL, optvals1.size());
EXPECT_EQ("optval1", optvals1[0].first);
EXPECT_EQ("optsuff1", optvals1[0].second);
EXPECT_EQ("optval2", optvals1[1].first);
EXPECT_EQ("optsuff2", optvals1[1].second);
EXPECT_EQ("optvalnosuff", optvals1[2].first);
EXPECT_EQ("", optvals1[2].second);
}