Skip to content

Commit

Permalink
[Reproducers] Serialize process arguments in ProcessInfo
Browse files Browse the repository at this point in the history
While debugging why TestProcessList.py failed during passive replay, I
remembered that we don't serialize the arguments for ProcessInfo. This
is necessary to make the test pass and to make platform process list -v
behave the same during capture and replay.

Differential revision: https://reviews.llvm.org/D79646
  • Loading branch information
JDevlieghere committed May 12, 2020
1 parent 9202df3 commit bad6154
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 0 deletions.
30 changes: 30 additions & 0 deletions lldb/include/lldb/Utility/Args.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "lldb/lldb-types.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/YAMLTraits.h"
#include <string>
#include <utility>
#include <vector>
Expand All @@ -34,6 +35,9 @@ class Args {
struct ArgEntry {
private:
friend class Args;
friend struct llvm::yaml::MappingTraits<Args>;
friend struct llvm::yaml::MappingTraits<Args::ArgEntry>;

std::unique_ptr<char[]> ptr;
char quote;

Expand Down Expand Up @@ -283,6 +287,8 @@ class Args {
char quote_char);

private:
friend struct llvm::yaml::MappingTraits<Args>;

std::vector<ArgEntry> m_entries;
std::vector<char *> m_argv;
};
Expand Down Expand Up @@ -373,4 +379,28 @@ class OptionsWithRaw {

} // namespace lldb_private

namespace llvm {
namespace yaml {
template <> struct MappingTraits<lldb_private::Args::ArgEntry> {
class NormalizedArgEntry {
public:
NormalizedArgEntry(IO &) {}
NormalizedArgEntry(IO &, lldb_private::Args::ArgEntry &entry)
: value(entry.ref()), quote(entry.quote) {}
lldb_private::Args::ArgEntry denormalize(IO &) {
return lldb_private::Args::ArgEntry(value, quote);
}
StringRef value;
char quote;
};
static void mapping(IO &io, lldb_private::Args::ArgEntry &v);
};
template <> struct MappingTraits<lldb_private::Args> {
static void mapping(IO &io, lldb_private::Args &v);
};
} // namespace yaml
} // namespace llvm

LLVM_YAML_IS_SEQUENCE_VECTOR(lldb_private::Args::ArgEntry)

#endif // LLDB_UTILITY_ARGS_H
17 changes: 17 additions & 0 deletions lldb/source/Utility/Args.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -684,3 +684,20 @@ void OptionsWithRaw::SetFromString(llvm::StringRef arg_string) {
m_suffix = std::string(original_args);
}
}

void llvm::yaml::MappingTraits<Args::ArgEntry>::mapping(IO &io,
Args::ArgEntry &v) {
MappingNormalization<NormalizedArgEntry, Args::ArgEntry> keys(io, v);
io.mapRequired("value", keys->value);
io.mapRequired("quote", keys->quote);
}

void llvm::yaml::MappingTraits<Args>::mapping(IO &io, Args &v) {
io.mapRequired("entries", v.m_entries);

// Recompute m_argv vector.
v.m_argv.clear();
for (auto &entry : v.m_entries)
v.m_argv.push_back(entry.data());
v.m_argv.push_back(nullptr);
}
1 change: 1 addition & 0 deletions lldb/source/Utility/ProcessInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,7 @@ void llvm::yaml::MappingTraits<ProcessInstanceInfo>::mapping(
IO &io, ProcessInstanceInfo &Info) {
io.mapRequired("executable", Info.m_executable);
io.mapRequired("arg0", Info.m_arg0);
io.mapRequired("args", Info.m_arguments);
io.mapRequired("arch", Info.m_arch);
io.mapRequired("uid", Info.m_uid);
io.mapRequired("gid", Info.m_gid);
Expand Down
21 changes: 21 additions & 0 deletions lldb/test/Shell/Reproducer/TestProcessList.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# UNSUPPORTED: system-freebsd

# Test that ProcessInfo is correctly serialized by comparing the output of
# 'platform process list -v' during capture and replay. The test assumes that
# there's at least two processes.

# RUN: %lldb -x -b -o 'platform process list -v' -o 'reproducer generate' --capture --capture-path %t.repro > %t.log
# RUN: %lldb --replay %t.repro >> %t.log
# RUN: cat %t.log | FileCheck %s

# CHECK: [[PROCS:[0-9]+]] matching processes were found
# CHECK: PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE ARGUMENTS
# CHECK-NEXT: ====== ====== ========== ========== ========== ========== ============================== ============================
# CHECK-NEXT: [[PID0:[0-9]+]] [[PROC0:.*]]
# CHECK-NEXT: [[PID1:[0-9]+]] [[PROC1:.*]]
# CHECK: Reproducer written to
# CHECK: [[PROCS]] matching processes were found
# CHECK: PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE ARGUMENTS
# CHECK-NEXT: ====== ====== ========== ========== ========== ========== ============================== ============================
# CHECK-NEXT: [[PID0]] [[PROC0]]
# CHECK-NEXT: [[PID1]] [[PROC1]]
31 changes: 31 additions & 0 deletions lldb/unittests/Utility/ArgsTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -282,3 +282,34 @@ TEST(ArgsTest, ReplaceArgumentAtIndexFarOutOfRange) {
EXPECT_EQ(3u, args.GetArgumentCount());
EXPECT_STREQ(args.GetArgumentAtIndex(2), "b");
}

TEST(ArgsTest, Yaml) {
std::string buffer;
llvm::raw_string_ostream os(buffer);

// Serialize.
Args args;
args.SetCommandString("this 'has' \"multiple\" args");
llvm::yaml::Output yout(os);
yout << args;
os.flush();

llvm::outs() << buffer;

// Deserialize.
Args deserialized;
llvm::yaml::Input yin(buffer);
yin >> deserialized;

EXPECT_EQ(4u, deserialized.GetArgumentCount());
EXPECT_STREQ(deserialized.GetArgumentAtIndex(0), "this");
EXPECT_STREQ(deserialized.GetArgumentAtIndex(1), "has");
EXPECT_STREQ(deserialized.GetArgumentAtIndex(2), "multiple");
EXPECT_STREQ(deserialized.GetArgumentAtIndex(3), "args");

llvm::ArrayRef<Args::ArgEntry> entries = deserialized.entries();
EXPECT_EQ(entries[0].GetQuoteChar(), '\0');
EXPECT_EQ(entries[1].GetQuoteChar(), '\'');
EXPECT_EQ(entries[2].GetQuoteChar(), '"');
EXPECT_EQ(entries[3].GetQuoteChar(), '\0');
}

0 comments on commit bad6154

Please sign in to comment.