fuchsia: Make ImageAnnotationReader[Test] work

Ports the test away from fork() to MultiprocessExec.

Requires a Fuchsia SDK that includes the fix in
https://fuchsia-review.googlesource.com/c/zircon/+/125081.

Bug: crashpad:196, crashpad:215
Change-Id: Ia8d382cebe8d2ffc8d877e5249baf0e58aee248c
Reviewed-on: https://chromium-review.googlesource.com/927355
Commit-Queue: Scott Graham <scottmg@chromium.org>
Reviewed-by: Mark Mentovai <mark@chromium.org>
This commit is contained in:
Scott Graham 2018-02-20 16:10:20 -08:00 committed by Commit Bot
parent 01105719d7
commit 3dd85dc126
2 changed files with 89 additions and 66 deletions

View File

@ -106,8 +106,6 @@ static_library("snapshot") {
if (crashpad_is_linux || crashpad_is_android) {
sources += [
"crashpad_types/image_annotation_reader.cc",
"crashpad_types/image_annotation_reader.h",
"linux/cpu_context_linux.cc",
"linux/cpu_context_linux.h",
"linux/debug_rendezvous.cc",
@ -134,6 +132,8 @@ static_library("snapshot") {
sources += [
"crashpad_types/crashpad_info_reader.cc",
"crashpad_types/crashpad_info_reader.h",
"crashpad_types/image_annotation_reader.cc",
"crashpad_types/image_annotation_reader.h",
"elf/elf_dynamic_array_reader.cc",
"elf/elf_dynamic_array_reader.h",
"elf/elf_image_reader.cc",
@ -307,7 +307,6 @@ source_set("snapshot_test") {
if (crashpad_is_linux || crashpad_is_android) {
sources += [
"crashpad_types/image_annotation_reader_test.cc",
"linux/debug_rendezvous_test.cc",
"linux/exception_snapshot_linux_test.cc",
"linux/process_reader_test.cc",
@ -320,6 +319,7 @@ source_set("snapshot_test") {
if (crashpad_is_linux || crashpad_is_android || crashpad_is_fuchsia) {
sources += [
"crashpad_types/crashpad_info_reader_test.cc",
"crashpad_types/image_annotation_reader_test.cc",
"elf/elf_image_reader_test.cc",
"elf/elf_image_reader_test_note.S",
"elf/test_exported_symbols.sym",

View File

@ -26,11 +26,12 @@
#include "client/annotation_list.h"
#include "client/simple_string_dictionary.h"
#include "gtest/gtest.h"
#include "test/multiprocess.h"
#include "test/multiprocess_exec.h"
#include "test/process_type.h"
#include "util/file/file_io.h"
#include "util/misc/as_underlying_type.h"
#include "util/misc/from_pointer_cast.h"
#include "util/process/process_memory_linux.h"
#include "util/process/process_memory_native.h"
namespace crashpad {
namespace test {
@ -60,67 +61,64 @@ void ExpectAnnotationList(const std::vector<AnnotationSnapshot>& list,
}
}
class AnnotationTest {
public:
AnnotationTest()
: expected_simple_map_(),
test_annotations_(),
expected_annotation_list_() {
expected_simple_map_.SetKeyValue("key", "value");
expected_simple_map_.SetKeyValue("key2", "value2");
void BuildTestStructures(
std::vector<std::unique_ptr<Annotation>>* annotations_storage,
SimpleStringDictionary* into_map,
AnnotationList* into_annotation_list) {
into_map->SetKeyValue("key", "value");
into_map->SetKeyValue("key2", "value2");
static constexpr char kAnnotationName[] = "test annotation";
static constexpr char kAnnotationValue[] = "test annotation value";
test_annotations_.push_back(std::make_unique<Annotation>(
Annotation::Type::kString,
kAnnotationName,
reinterpret_cast<void*>(const_cast<char*>(kAnnotationValue))));
test_annotations_.back()->SetSize(sizeof(kAnnotationValue));
expected_annotation_list_.Add(test_annotations_.back().get());
static constexpr char kAnnotationName[] = "test annotation";
static constexpr char kAnnotationValue[] = "test annotation value";
annotations_storage->push_back(std::make_unique<Annotation>(
Annotation::Type::kString,
kAnnotationName,
reinterpret_cast<void*>(const_cast<char*>(kAnnotationValue))));
annotations_storage->back()->SetSize(sizeof(kAnnotationValue));
into_annotation_list->Add(annotations_storage->back().get());
static constexpr char kAnnotationName2[] = "test annotation2";
static constexpr char kAnnotationValue2[] = "test annotation value2";
test_annotations_.push_back(std::make_unique<Annotation>(
Annotation::Type::kString,
kAnnotationName2,
reinterpret_cast<void*>(const_cast<char*>(kAnnotationValue2))));
test_annotations_.back()->SetSize(sizeof(kAnnotationValue2));
expected_annotation_list_.Add(test_annotations_.back().get());
}
static constexpr char kAnnotationName2[] = "test annotation2";
static constexpr char kAnnotationValue2[] = "test annotation value2";
annotations_storage->push_back(std::make_unique<Annotation>(
Annotation::Type::kString,
kAnnotationName2,
reinterpret_cast<void*>(const_cast<char*>(kAnnotationValue2))));
annotations_storage->back()->SetSize(sizeof(kAnnotationValue2));
into_annotation_list->Add(annotations_storage->back().get());
}
~AnnotationTest() = default;
void ExpectAnnotations(ProcessType process,
bool is_64_bit,
VMAddress simple_map_address,
VMAddress annotation_list_address) {
ProcessMemoryNative memory;
ASSERT_TRUE(memory.Initialize(process));
void ExpectAnnotations(pid_t pid, bool is_64_bit) {
ProcessMemoryLinux memory;
ASSERT_TRUE(memory.Initialize(pid));
ProcessMemoryRange range;
ASSERT_TRUE(range.Initialize(&memory, is_64_bit));
ProcessMemoryRange range;
ASSERT_TRUE(range.Initialize(&memory, is_64_bit));
SimpleStringDictionary expected_simple_map;
std::vector<std::unique_ptr<Annotation>> storage;
AnnotationList expected_annotations;
BuildTestStructures(&storage, &expected_simple_map, &expected_annotations);
ImageAnnotationReader reader(&range);
ImageAnnotationReader reader(&range);
std::map<std::string, std::string> simple_map;
ASSERT_TRUE(reader.SimpleMap(
FromPointerCast<VMAddress>(&expected_simple_map_), &simple_map));
ExpectSimpleMap(simple_map, expected_simple_map_);
std::map<std::string, std::string> simple_map;
ASSERT_TRUE(reader.SimpleMap(simple_map_address, &simple_map));
ExpectSimpleMap(simple_map, expected_simple_map);
std::vector<AnnotationSnapshot> annotation_list;
ASSERT_TRUE(reader.AnnotationsList(
FromPointerCast<VMAddress>(&expected_annotation_list_),
&annotation_list));
ExpectAnnotationList(annotation_list, expected_annotation_list_);
}
private:
SimpleStringDictionary expected_simple_map_;
std::vector<std::unique_ptr<Annotation>> test_annotations_;
AnnotationList expected_annotation_list_;
DISALLOW_COPY_AND_ASSIGN(AnnotationTest);
};
std::vector<AnnotationSnapshot> annotation_list;
ASSERT_TRUE(
reader.AnnotationsList(annotation_list_address, &annotation_list));
ExpectAnnotationList(annotation_list, expected_annotations);
}
TEST(ImageAnnotationReader, ReadFromSelf) {
AnnotationTest test;
SimpleStringDictionary map;
std::vector<std::unique_ptr<Annotation>> storage;
AnnotationList annotations;
BuildTestStructures(&storage, &map, &annotations);
#if defined(ARCH_CPU_64_BITS)
constexpr bool am_64_bit = true;
@ -128,14 +126,35 @@ TEST(ImageAnnotationReader, ReadFromSelf) {
constexpr bool am_64_bit = false;
#endif
test.ExpectAnnotations(getpid(), am_64_bit);
ExpectAnnotations(GetSelfProcess(),
am_64_bit,
FromPointerCast<VMAddress>(&map),
FromPointerCast<VMAddress>(&annotations));
}
class ReadFromChildTest : public Multiprocess {
public:
ReadFromChildTest() : Multiprocess(), annotation_test_() {}
CRASHPAD_CHILD_TEST_MAIN(ReadAnnotationsFromChildTestMain) {
SimpleStringDictionary map;
std::vector<std::unique_ptr<Annotation>> storage;
AnnotationList annotations;
BuildTestStructures(&storage, &map, &annotations);
~ReadFromChildTest() {}
VMAddress simple_map_address = FromPointerCast<VMAddress>(&map);
VMAddress annotations_address = FromPointerCast<VMAddress>(&annotations);
FileHandle out = StdioFileHandle(StdioStream::kStandardOutput);
CheckedWriteFile(out, &simple_map_address, sizeof(simple_map_address));
CheckedWriteFile(out, &annotations_address, sizeof(annotations_address));
CheckedReadFileAtEOF(StdioFileHandle(StdioStream::kStandardInput));
return 0;
}
class ReadFromChildTest : public MultiprocessExec {
public:
ReadFromChildTest() : MultiprocessExec() {
SetChildTestMainFunction("ReadAnnotationsFromChildTestMain");
}
~ReadFromChildTest() = default;
private:
void MultiprocessParent() {
@ -144,13 +163,17 @@ class ReadFromChildTest : public Multiprocess {
#else
constexpr bool am_64_bit = false;
#endif
annotation_test_.ExpectAnnotations(ChildPID(), am_64_bit);
VMAddress simple_map_address;
VMAddress annotations_address;
ASSERT_TRUE(ReadFileExactly(
ReadPipeHandle(), &simple_map_address, sizeof(simple_map_address)));
ASSERT_TRUE(ReadFileExactly(
ReadPipeHandle(), &annotations_address, sizeof(annotations_address)));
ExpectAnnotations(
ChildProcess(), am_64_bit, simple_map_address, annotations_address);
}
void MultiprocessChild() { CheckedReadFileAtEOF(ReadPipeHandle()); }
AnnotationTest annotation_test_;
DISALLOW_COPY_AND_ASSIGN(ReadFromChildTest);
};