Imported Upstream version 6.10.0.49

Former-commit-id: 1d6753294b2993e1fbf92de9366bb9544db4189b
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2020-01-16 16:38:04 +00:00
parent d94e79959b
commit 468663ddbb
48518 changed files with 2789335 additions and 61176 deletions

View File

@@ -0,0 +1,13 @@
add_lldb_unittest(InterpreterTests
TestArgs.cpp
TestCompletion.cpp
LINK_LIBS
lldbInterpreter
lldbUtilityHelpers
)
target_link_libraries(InterpreterTests
PRIVATE
${PYTHON_LIBRARY}
)

View File

@@ -0,0 +1,362 @@
//===-- ArgsTest.cpp --------------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "gtest/gtest.h"
#include "lldb/Interpreter/Args.h"
#include "lldb/Utility/StringList.h"
#include <limits>
#include <sstream>
using namespace lldb_private;
TEST(ArgsTest, TestSingleArg) {
Args args;
args.SetCommandString("arg");
EXPECT_EQ(1u, args.GetArgumentCount());
EXPECT_STREQ(args.GetArgumentAtIndex(0), "arg");
}
TEST(ArgsTest, TestSingleQuotedArgWithSpace) {
Args args;
args.SetCommandString("\"arg with space\"");
EXPECT_EQ(1u, args.GetArgumentCount());
EXPECT_STREQ(args.GetArgumentAtIndex(0), "arg with space");
}
TEST(ArgsTest, TestSingleArgWithQuotedSpace) {
Args args;
args.SetCommandString("arg\\ with\\ space");
EXPECT_EQ(1u, args.GetArgumentCount());
EXPECT_STREQ(args.GetArgumentAtIndex(0), "arg with space");
}
TEST(ArgsTest, TestMultipleArgs) {
Args args;
args.SetCommandString("this has multiple args");
EXPECT_EQ(4u, args.GetArgumentCount());
EXPECT_STREQ(args.GetArgumentAtIndex(0), "this");
EXPECT_STREQ(args.GetArgumentAtIndex(1), "has");
EXPECT_STREQ(args.GetArgumentAtIndex(2), "multiple");
EXPECT_STREQ(args.GetArgumentAtIndex(3), "args");
}
TEST(ArgsTest, TestOverwriteArgs) {
Args args;
args.SetCommandString("this has multiple args");
EXPECT_EQ(4u, args.GetArgumentCount());
args.SetCommandString("arg");
EXPECT_EQ(1u, args.GetArgumentCount());
EXPECT_STREQ(args.GetArgumentAtIndex(0), "arg");
}
TEST(ArgsTest, TestAppendArg) {
Args args;
args.SetCommandString("first_arg");
EXPECT_EQ(1u, args.GetArgumentCount());
args.AppendArgument(llvm::StringRef("second_arg"));
EXPECT_EQ(2u, args.GetArgumentCount());
EXPECT_STREQ(args.GetArgumentAtIndex(0), "first_arg");
EXPECT_STREQ(args.GetArgumentAtIndex(1), "second_arg");
}
TEST(ArgsTest, TestInsertArg) {
Args args;
args.AppendArgument("1");
args.AppendArgument("2");
args.AppendArgument("3");
args.InsertArgumentAtIndex(1, "1.5");
args.InsertArgumentAtIndex(4, "3.5");
ASSERT_EQ(5u, args.GetArgumentCount());
EXPECT_STREQ("1", args.GetArgumentAtIndex(0));
EXPECT_STREQ("1.5", args.GetArgumentAtIndex(1));
EXPECT_STREQ("2", args.GetArgumentAtIndex(2));
EXPECT_STREQ("3", args.GetArgumentAtIndex(3));
EXPECT_STREQ("3.5", args.GetArgumentAtIndex(4));
}
TEST(ArgsTest, TestArgv) {
Args args;
EXPECT_EQ(nullptr, args.GetArgumentVector());
args.AppendArgument("1");
EXPECT_NE(nullptr, args.GetArgumentVector()[0]);
EXPECT_EQ(nullptr, args.GetArgumentVector()[1]);
args.AppendArgument("2");
EXPECT_NE(nullptr, args.GetArgumentVector()[0]);
EXPECT_NE(nullptr, args.GetArgumentVector()[1]);
EXPECT_EQ(nullptr, args.GetArgumentVector()[2]);
args.AppendArgument("3");
EXPECT_NE(nullptr, args.GetArgumentVector()[0]);
EXPECT_NE(nullptr, args.GetArgumentVector()[1]);
EXPECT_NE(nullptr, args.GetArgumentVector()[2]);
EXPECT_EQ(nullptr, args.GetArgumentVector()[3]);
args.InsertArgumentAtIndex(1, "1.5");
EXPECT_NE(nullptr, args.GetArgumentVector()[0]);
EXPECT_NE(nullptr, args.GetArgumentVector()[1]);
EXPECT_NE(nullptr, args.GetArgumentVector()[2]);
EXPECT_NE(nullptr, args.GetArgumentVector()[3]);
EXPECT_EQ(nullptr, args.GetArgumentVector()[4]);
args.InsertArgumentAtIndex(4, "3.5");
EXPECT_NE(nullptr, args.GetArgumentVector()[0]);
EXPECT_NE(nullptr, args.GetArgumentVector()[1]);
EXPECT_NE(nullptr, args.GetArgumentVector()[2]);
EXPECT_NE(nullptr, args.GetArgumentVector()[3]);
EXPECT_NE(nullptr, args.GetArgumentVector()[4]);
EXPECT_EQ(nullptr, args.GetArgumentVector()[5]);
}
TEST(ArgsTest, StringListConstructor) {
StringList list;
list << "foo" << "bar" << "baz";
Args args(list);
ASSERT_EQ(3u, args.GetArgumentCount());
EXPECT_EQ("foo", args[0].ref);
EXPECT_EQ("bar", args[1].ref);
EXPECT_EQ("baz", args[2].ref);
}
TEST(ArgsTest, GetQuotedCommandString) {
Args args;
const char *str = "process launch -o stdout.txt -- \"a b c\"";
args.SetCommandString(str);
std::string stdstr;
ASSERT_TRUE(args.GetQuotedCommandString(stdstr));
EXPECT_EQ(str, stdstr);
}
TEST(ArgsTest, BareSingleQuote) {
Args args;
args.SetCommandString("a\\'b");
EXPECT_EQ(1u, args.GetArgumentCount());
EXPECT_STREQ("a'b", args.GetArgumentAtIndex(0));
}
TEST(ArgsTest, DoubleQuotedItem) {
Args args;
args.SetCommandString("\"a b c\"");
EXPECT_EQ(1u, args.GetArgumentCount());
EXPECT_STREQ("a b c", args.GetArgumentAtIndex(0));
}
TEST(ArgsTest, AppendArguments) {
Args args;
const char *argv[] = {"1", "2", nullptr};
const char *argv2[] = {"3", "4", nullptr};
args.AppendArguments(argv);
ASSERT_EQ(2u, args.GetArgumentCount());
EXPECT_STREQ("1", args.GetArgumentVector()[0]);
EXPECT_STREQ("2", args.GetArgumentVector()[1]);
EXPECT_EQ(nullptr, args.GetArgumentVector()[2]);
EXPECT_STREQ("1", args.GetArgumentAtIndex(0));
EXPECT_STREQ("2", args.GetArgumentAtIndex(1));
args.AppendArguments(argv2);
ASSERT_EQ(4u, args.GetArgumentCount());
EXPECT_STREQ("1", args.GetArgumentVector()[0]);
EXPECT_STREQ("2", args.GetArgumentVector()[1]);
EXPECT_STREQ("3", args.GetArgumentVector()[2]);
EXPECT_STREQ("4", args.GetArgumentVector()[3]);
EXPECT_EQ(nullptr, args.GetArgumentVector()[4]);
EXPECT_STREQ("1", args.GetArgumentAtIndex(0));
EXPECT_STREQ("2", args.GetArgumentAtIndex(1));
EXPECT_STREQ("3", args.GetArgumentAtIndex(2));
EXPECT_STREQ("4", args.GetArgumentAtIndex(3));
}
TEST(ArgsTest, GetArgumentArrayRef) {
Args args("foo bar");
auto ref = args.GetArgumentArrayRef();
ASSERT_EQ(2u, ref.size());
EXPECT_STREQ("foo", ref[0]);
EXPECT_STREQ("bar", ref[1]);
}
TEST(ArgsTest, StringToBoolean) {
bool success = false;
EXPECT_TRUE(Args::StringToBoolean(llvm::StringRef("true"), false, nullptr));
EXPECT_TRUE(Args::StringToBoolean(llvm::StringRef("on"), false, nullptr));
EXPECT_TRUE(Args::StringToBoolean(llvm::StringRef("yes"), false, nullptr));
EXPECT_TRUE(Args::StringToBoolean(llvm::StringRef("1"), false, nullptr));
EXPECT_TRUE(Args::StringToBoolean(llvm::StringRef("true"), false, &success));
EXPECT_TRUE(success);
EXPECT_TRUE(Args::StringToBoolean(llvm::StringRef("on"), false, &success));
EXPECT_TRUE(success);
EXPECT_TRUE(Args::StringToBoolean(llvm::StringRef("yes"), false, &success));
EXPECT_TRUE(success);
EXPECT_TRUE(Args::StringToBoolean(llvm::StringRef("1"), false, &success));
EXPECT_TRUE(success);
EXPECT_FALSE(Args::StringToBoolean(llvm::StringRef("false"), true, nullptr));
EXPECT_FALSE(Args::StringToBoolean(llvm::StringRef("off"), true, nullptr));
EXPECT_FALSE(Args::StringToBoolean(llvm::StringRef("no"), true, nullptr));
EXPECT_FALSE(Args::StringToBoolean(llvm::StringRef("0"), true, nullptr));
EXPECT_FALSE(Args::StringToBoolean(llvm::StringRef("false"), true, &success));
EXPECT_TRUE(success);
EXPECT_FALSE(Args::StringToBoolean(llvm::StringRef("off"), true, &success));
EXPECT_TRUE(success);
EXPECT_FALSE(Args::StringToBoolean(llvm::StringRef("no"), true, &success));
EXPECT_TRUE(success);
EXPECT_FALSE(Args::StringToBoolean(llvm::StringRef("0"), true, &success));
EXPECT_TRUE(success);
EXPECT_FALSE(Args::StringToBoolean(llvm::StringRef("10"), false, &success));
EXPECT_FALSE(success);
EXPECT_TRUE(Args::StringToBoolean(llvm::StringRef("10"), true, &success));
EXPECT_FALSE(success);
EXPECT_TRUE(Args::StringToBoolean(llvm::StringRef(""), true, &success));
EXPECT_FALSE(success);
}
TEST(ArgsTest, StringToChar) {
bool success = false;
EXPECT_EQ('A', Args::StringToChar("A", 'B', nullptr));
EXPECT_EQ('B', Args::StringToChar("B", 'A', nullptr));
EXPECT_EQ('A', Args::StringToChar("A", 'B', &success));
EXPECT_TRUE(success);
EXPECT_EQ('B', Args::StringToChar("B", 'A', &success));
EXPECT_TRUE(success);
EXPECT_EQ('A', Args::StringToChar("", 'A', &success));
EXPECT_FALSE(success);
EXPECT_EQ('A', Args::StringToChar("ABC", 'A', &success));
EXPECT_FALSE(success);
}
TEST(ArgsTest, StringToScriptLanguage) {
bool success = false;
EXPECT_EQ(lldb::eScriptLanguageDefault,
Args::StringToScriptLanguage(llvm::StringRef("default"),
lldb::eScriptLanguageNone, nullptr));
EXPECT_EQ(lldb::eScriptLanguagePython,
Args::StringToScriptLanguage(llvm::StringRef("python"),
lldb::eScriptLanguageNone, nullptr));
EXPECT_EQ(lldb::eScriptLanguageNone,
Args::StringToScriptLanguage(llvm::StringRef("none"),
lldb::eScriptLanguagePython, nullptr));
EXPECT_EQ(lldb::eScriptLanguageDefault,
Args::StringToScriptLanguage(llvm::StringRef("default"),
lldb::eScriptLanguageNone, &success));
EXPECT_TRUE(success);
EXPECT_EQ(lldb::eScriptLanguagePython,
Args::StringToScriptLanguage(llvm::StringRef("python"),
lldb::eScriptLanguageNone, &success));
EXPECT_TRUE(success);
EXPECT_EQ(lldb::eScriptLanguageNone,
Args::StringToScriptLanguage(llvm::StringRef("none"),
lldb::eScriptLanguagePython,
&success));
EXPECT_TRUE(success);
EXPECT_EQ(lldb::eScriptLanguagePython,
Args::StringToScriptLanguage(llvm::StringRef("invalid"),
lldb::eScriptLanguagePython,
&success));
EXPECT_FALSE(success);
}
TEST(ArgsTest, StringToVersion) {}
// Environment Variable Tests
class EnvVarFixture: public ::testing::Test {
protected:
void SetUp() {
args.AppendArgument(llvm::StringRef("Arg1=foo"));
args.AppendArgument(llvm::StringRef("Arg2"));
args.AppendArgument(llvm::StringRef("Arg3=bar"));
}
size_t GetIndexForEnvVar(llvm::StringRef envvar_name) {
size_t argument_index = std::numeric_limits<size_t>::max();
EXPECT_TRUE(args.ContainsEnvironmentVariable(envvar_name,
&argument_index));
EXPECT_LT(argument_index, args.GetArgumentCount());
return argument_index;
}
Args args;
};
TEST_F(EnvVarFixture, TestContainsEnvironmentVariableNoValue) {
EXPECT_TRUE(args.ContainsEnvironmentVariable(llvm::StringRef("Arg2")));
}
TEST_F(EnvVarFixture, TestContainsEnvironmentVariableWithValue) {
EXPECT_TRUE(args.ContainsEnvironmentVariable(llvm::StringRef("Arg3")));
}
TEST_F(EnvVarFixture, TestContainsEnvironmentVariableNonExistentVariable) {
auto nonexistent_envvar = llvm::StringRef("ThisEnvVarShouldNotExist");
EXPECT_FALSE(args.ContainsEnvironmentVariable(nonexistent_envvar));
}
TEST_F(EnvVarFixture, TestReplaceEnvironmentVariableInitialNoValueWithNoValue) {
auto envvar_name = llvm::StringRef("Arg2");
auto argument_index = GetIndexForEnvVar(envvar_name);
args.AddOrReplaceEnvironmentVariable(envvar_name, llvm::StringRef(""));
EXPECT_TRUE(args.ContainsEnvironmentVariable(envvar_name));
EXPECT_EQ(envvar_name, args.GetArgumentAtIndex(argument_index));
}
TEST_F(EnvVarFixture, TestReplaceEnvironmentVariableInitialNoValueWithValue) {
auto envvar_name = llvm::StringRef("Arg2");
auto argument_index = GetIndexForEnvVar(envvar_name);
auto new_value = llvm::StringRef("NewValue");
args.AddOrReplaceEnvironmentVariable(envvar_name, new_value);
EXPECT_TRUE(args.ContainsEnvironmentVariable(envvar_name));
std::stringstream stream;
stream << envvar_name.str() << '=' << new_value.str();
EXPECT_EQ(llvm::StringRef(stream.str()),
args.GetArgumentAtIndex(argument_index));
}
TEST_F(EnvVarFixture, TestReplaceEnvironmentVariableInitialValueWithNoValue) {
auto envvar_name = llvm::StringRef("Arg1");
auto argument_index = GetIndexForEnvVar(envvar_name);
args.AddOrReplaceEnvironmentVariable(envvar_name, llvm::StringRef(""));
EXPECT_TRUE(args.ContainsEnvironmentVariable(envvar_name));
EXPECT_EQ(envvar_name, args.GetArgumentAtIndex(argument_index));
}
TEST_F(EnvVarFixture, TestReplaceEnvironmentVariableInitialValueWithValue) {
auto envvar_name = llvm::StringRef("Arg1");
auto argument_index = GetIndexForEnvVar(envvar_name);
auto new_value = llvm::StringRef("NewValue");
args.AddOrReplaceEnvironmentVariable(envvar_name, new_value);
EXPECT_TRUE(args.ContainsEnvironmentVariable(envvar_name));
std::stringstream stream;
stream << envvar_name.str() << '=' << new_value.str();
EXPECT_EQ(llvm::StringRef(stream.str()),
args.GetArgumentAtIndex(argument_index));
}

View File

@@ -0,0 +1,306 @@
//===-- TestCompletion.cpp --------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "gtest/gtest.h"
#include "lldb/Interpreter/CommandCompletions.h"
#include "lldb/Utility/StringList.h"
#include "lldb/Utility/TildeExpressionResolver.h"
#include "TestingSupport/MockTildeExpressionResolver.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
namespace fs = llvm::sys::fs;
namespace path = llvm::sys::path;
using namespace llvm;
using namespace lldb_private;
#define ASSERT_NO_ERROR(x) \
if (std::error_code ASSERT_NO_ERROR_ec = x) { \
SmallString<128> MessageStorage; \
raw_svector_ostream Message(MessageStorage); \
Message << #x ": did not return errc::success.\n" \
<< "error number: " << ASSERT_NO_ERROR_ec.value() << "\n" \
<< "error message: " << ASSERT_NO_ERROR_ec.message() << "\n"; \
GTEST_FATAL_FAILURE_(MessageStorage.c_str()); \
} else { \
}
namespace {
class CompletionTest : public testing::Test {
protected:
/// Unique temporary directory in which all created filesystem entities must
/// be placed. It is removed at the end of the test suite.
static SmallString<128> BaseDir;
static SmallString<128> OriginalWorkingDir;
static SmallString<128> DirFoo;
static SmallString<128> DirFooA;
static SmallString<128> DirFooB;
static SmallString<128> DirFooC;
static SmallString<128> DirBar;
static SmallString<128> DirBaz;
static SmallString<128> DirTestFolder;
static SmallString<128> FileAA;
static SmallString<128> FileAB;
static SmallString<128> FileAC;
static SmallString<128> FileFoo;
static SmallString<128> FileBar;
static SmallString<128> FileBaz;
void SetUp() override { llvm::sys::fs::set_current_path(OriginalWorkingDir); }
static void SetUpTestCase() {
llvm::sys::fs::current_path(OriginalWorkingDir);
ASSERT_NO_ERROR(fs::createUniqueDirectory("FsCompletion", BaseDir));
const char *DirNames[] = {"foo", "fooa", "foob", "fooc",
"bar", "baz", "test_folder"};
const char *FileNames[] = {"aa1234.tmp", "ab1234.tmp", "ac1234.tmp",
"foo1234.tmp", "bar1234.tmp", "baz1234.tmp"};
SmallString<128> *Dirs[] = {&DirFoo, &DirFooA, &DirFooB, &DirFooC,
&DirBar, &DirBaz, &DirTestFolder};
for (auto Dir : llvm::zip(DirNames, Dirs)) {
auto &Path = *std::get<1>(Dir);
Path = BaseDir;
path::append(Path, std::get<0>(Dir));
ASSERT_NO_ERROR(fs::create_directory(Path));
}
SmallString<128> *Files[] = {&FileAA, &FileAB, &FileAC,
&FileFoo, &FileBar, &FileBaz};
for (auto File : llvm::zip(FileNames, Files)) {
auto &Path = *std::get<1>(File);
Path = BaseDir;
path::append(Path, std::get<0>(File));
int FD;
ASSERT_NO_ERROR(fs::createUniqueFile(Path, FD, Path));
::close(FD);
}
}
static void TearDownTestCase() {
ASSERT_NO_ERROR(fs::remove_directories(BaseDir));
}
static bool HasEquivalentFile(const Twine &Path, const StringList &Paths) {
for (size_t I = 0; I < Paths.GetSize(); ++I) {
if (fs::equivalent(Path, Paths[I]))
return true;
}
return false;
}
static bool ContainsExactString(const Twine &Str, const StringList &Paths) {
SmallString<16> Storage;
StringRef Rendered = Str.toStringRef(Storage);
for (size_t I = 0; I < Paths.GetSize(); ++I) {
if (Paths[I] == Rendered)
return true;
}
return false;
}
void DoDirCompletions(const Twine &Prefix,
StandardTildeExpressionResolver &Resolver,
StringList &Results) {
// When a partial name matches, it returns all matches. If it matches both
// a full name AND some partial names, it returns all of them.
uint32_t Count =
CommandCompletions::DiskDirectories(Prefix + "foo", Results, Resolver);
ASSERT_EQ(4u, Count);
ASSERT_EQ(Count, Results.GetSize());
EXPECT_TRUE(HasEquivalentFile(DirFoo, Results));
EXPECT_TRUE(HasEquivalentFile(DirFooA, Results));
EXPECT_TRUE(HasEquivalentFile(DirFooB, Results));
EXPECT_TRUE(HasEquivalentFile(DirFooC, Results));
// If it matches only partial names, it still works as expected.
Count = CommandCompletions::DiskDirectories(Twine(Prefix) + "b", Results,
Resolver);
ASSERT_EQ(2u, Count);
ASSERT_EQ(Count, Results.GetSize());
EXPECT_TRUE(HasEquivalentFile(DirBar, Results));
EXPECT_TRUE(HasEquivalentFile(DirBaz, Results));
}
};
SmallString<128> CompletionTest::BaseDir;
SmallString<128> CompletionTest::OriginalWorkingDir;
SmallString<128> CompletionTest::DirFoo;
SmallString<128> CompletionTest::DirFooA;
SmallString<128> CompletionTest::DirFooB;
SmallString<128> CompletionTest::DirFooC;
SmallString<128> CompletionTest::DirBar;
SmallString<128> CompletionTest::DirBaz;
SmallString<128> CompletionTest::DirTestFolder;
SmallString<128> CompletionTest::FileAA;
SmallString<128> CompletionTest::FileAB;
SmallString<128> CompletionTest::FileAC;
SmallString<128> CompletionTest::FileFoo;
SmallString<128> CompletionTest::FileBar;
SmallString<128> CompletionTest::FileBaz;
}
TEST_F(CompletionTest, DirCompletionAbsolute) {
// All calls to DiskDirectories() return only directories, even when
// there are files which also match. The tests below all check this
// by asserting an exact result count, and verifying against known
// folders.
std::string Prefixes[] = {(Twine(BaseDir) + "/").str(), ""};
StandardTildeExpressionResolver Resolver;
StringList Results;
// When a directory is specified that doesn't end in a slash, it searches
// for that directory, not items under it.
size_t Count =
CommandCompletions::DiskDirectories(BaseDir, Results, Resolver);
ASSERT_EQ(1u, Count);
ASSERT_EQ(Count, Results.GetSize());
EXPECT_TRUE(HasEquivalentFile(BaseDir, Results));
// When the same directory ends with a slash, it finds all children.
Count = CommandCompletions::DiskDirectories(Prefixes[0], Results, Resolver);
ASSERT_EQ(7u, Count);
ASSERT_EQ(Count, Results.GetSize());
EXPECT_TRUE(HasEquivalentFile(DirFoo, Results));
EXPECT_TRUE(HasEquivalentFile(DirFooA, Results));
EXPECT_TRUE(HasEquivalentFile(DirFooB, Results));
EXPECT_TRUE(HasEquivalentFile(DirFooC, Results));
EXPECT_TRUE(HasEquivalentFile(DirBar, Results));
EXPECT_TRUE(HasEquivalentFile(DirBaz, Results));
EXPECT_TRUE(HasEquivalentFile(DirTestFolder, Results));
DoDirCompletions(Twine(BaseDir) + "/", Resolver, Results);
llvm::sys::fs::set_current_path(BaseDir);
DoDirCompletions("", Resolver, Results);
}
TEST_F(CompletionTest, FileCompletionAbsolute) {
// All calls to DiskFiles() return both files and directories The tests below
// all check this by asserting an exact result count, and verifying against
// known folders.
StandardTildeExpressionResolver Resolver;
StringList Results;
// When an item is specified that doesn't end in a slash but exactly matches
// one item, it returns that item.
size_t Count = CommandCompletions::DiskFiles(Twine(BaseDir) + "/fooa",
Results, Resolver);
ASSERT_EQ(1u, Count);
ASSERT_EQ(Count, Results.GetSize());
EXPECT_TRUE(HasEquivalentFile(DirFooA, Results));
// The previous check verified a directory match. But it should work for
// files too.
Count =
CommandCompletions::DiskFiles(Twine(BaseDir) + "/aa", Results, Resolver);
ASSERT_EQ(1u, Count);
ASSERT_EQ(Count, Results.GetSize());
EXPECT_TRUE(HasEquivalentFile(FileAA, Results));
// When it ends with a slash, it should find all files and directories.
Count =
CommandCompletions::DiskFiles(Twine(BaseDir) + "/", Results, Resolver);
ASSERT_EQ(13u, Count);
ASSERT_EQ(Count, Results.GetSize());
EXPECT_TRUE(HasEquivalentFile(DirFoo, Results));
EXPECT_TRUE(HasEquivalentFile(DirFooA, Results));
EXPECT_TRUE(HasEquivalentFile(DirFooB, Results));
EXPECT_TRUE(HasEquivalentFile(DirFooC, Results));
EXPECT_TRUE(HasEquivalentFile(DirBar, Results));
EXPECT_TRUE(HasEquivalentFile(DirBaz, Results));
EXPECT_TRUE(HasEquivalentFile(DirTestFolder, Results));
EXPECT_TRUE(HasEquivalentFile(FileAA, Results));
EXPECT_TRUE(HasEquivalentFile(FileAB, Results));
EXPECT_TRUE(HasEquivalentFile(FileAC, Results));
EXPECT_TRUE(HasEquivalentFile(FileFoo, Results));
EXPECT_TRUE(HasEquivalentFile(FileBar, Results));
EXPECT_TRUE(HasEquivalentFile(FileBaz, Results));
// When a partial name matches, it returns all file & directory matches.
Count =
CommandCompletions::DiskFiles(Twine(BaseDir) + "/foo", Results, Resolver);
ASSERT_EQ(5u, Count);
ASSERT_EQ(Count, Results.GetSize());
EXPECT_TRUE(HasEquivalentFile(DirFoo, Results));
EXPECT_TRUE(HasEquivalentFile(DirFooA, Results));
EXPECT_TRUE(HasEquivalentFile(DirFooB, Results));
EXPECT_TRUE(HasEquivalentFile(DirFooC, Results));
EXPECT_TRUE(HasEquivalentFile(FileFoo, Results));
}
TEST_F(CompletionTest, DirCompletionUsername) {
MockTildeExpressionResolver Resolver("James", BaseDir);
Resolver.AddKnownUser("Kirk", DirFooB);
Resolver.AddKnownUser("Lars", DirFooC);
Resolver.AddKnownUser("Jason", DirFoo);
Resolver.AddKnownUser("Larry", DirFooA);
// Just resolving current user's home directory by itself should return the
// directory.
StringList Results;
size_t Count = CommandCompletions::DiskDirectories("~", Results, Resolver);
ASSERT_EQ(1u, Count);
ASSERT_EQ(Count, Results.GetSize());
EXPECT_TRUE(ContainsExactString(Twine("~") + path::get_separator(), Results));
// With a slash appended, it should return all items in the directory.
Count = CommandCompletions::DiskDirectories("~/", Results, Resolver);
ASSERT_EQ(7u, Count);
ASSERT_EQ(Count, Results.GetSize());
EXPECT_TRUE(
ContainsExactString(Twine("~/foo") + path::get_separator(), Results));
EXPECT_TRUE(
ContainsExactString(Twine("~/fooa") + path::get_separator(), Results));
EXPECT_TRUE(
ContainsExactString(Twine("~/foob") + path::get_separator(), Results));
EXPECT_TRUE(
ContainsExactString(Twine("~/fooc") + path::get_separator(), Results));
EXPECT_TRUE(
ContainsExactString(Twine("~/bar") + path::get_separator(), Results));
EXPECT_TRUE(
ContainsExactString(Twine("~/baz") + path::get_separator(), Results));
EXPECT_TRUE(ContainsExactString(
Twine("~/test_folder") + path::get_separator(), Results));
// With ~username syntax it should return one match if there is an exact
// match.
// It shouldn't translate to the actual directory, it should keep the form the
// user typed.
Count = CommandCompletions::DiskDirectories("~Lars", Results, Resolver);
ASSERT_EQ(1u, Count);
ASSERT_EQ(Count, Results.GetSize());
EXPECT_TRUE(
ContainsExactString(Twine("~Lars") + path::get_separator(), Results));
// But with a username that is not found, no results are returned.
Count = CommandCompletions::DiskDirectories("~Dave", Results, Resolver);
ASSERT_EQ(0u, Count);
ASSERT_EQ(Count, Results.GetSize());
// And if there are multiple matches, it should return all of them.
Count = CommandCompletions::DiskDirectories("~La", Results, Resolver);
ASSERT_EQ(2u, Count);
ASSERT_EQ(Count, Results.GetSize());
EXPECT_TRUE(
ContainsExactString(Twine("~Lars") + path::get_separator(), Results));
EXPECT_TRUE(
ContainsExactString(Twine("~Larry") + path::get_separator(), Results));
}