mirror of
https://github.com/chromium/crashpad.git
synced 2025-03-20 18:53:47 +00:00
ios: Add more tests for extra_memory_ranges and custom user streams.
Adds two end-to-end tests for iOS, testing the newly ported custom user streams and extra memory ranges. Change-Id: Ia0721e394898aac5bec7b58d3750818615cca0c5 Reviewed-on: https://chromium-review.googlesource.com/c/crashpad/crashpad/+/6362132 Commit-Queue: Justin Cohen <justincohen@chromium.org> Reviewed-by: Joshua Peraza <jperaza@chromium.org>
This commit is contained in:
parent
3eba16f1ca
commit
cfe842c074
@ -538,7 +538,7 @@ class CrashpadClient {
|
|||||||
//! added to the minidump.
|
//! added to the minidump.
|
||||||
static void ProcessIntermediateDumps(
|
static void ProcessIntermediateDumps(
|
||||||
const std::map<std::string, std::string>& annotations = {},
|
const std::map<std::string, std::string>& annotations = {},
|
||||||
const UserStreamDataSources* user_stream_sources = {});
|
const UserStreamDataSources* user_stream_sources = nullptr);
|
||||||
|
|
||||||
//! \brief Requests that the handler convert a single intermediate dump at \a
|
//! \brief Requests that the handler convert a single intermediate dump at \a
|
||||||
//! file generated by DumpWithoutCrashAndDeferProcessingAtPath into a
|
//! file generated by DumpWithoutCrashAndDeferProcessingAtPath into a
|
||||||
|
@ -110,35 +110,35 @@ TEST_F(InProcessHandlerTest, TestPendingFileLimit) {
|
|||||||
|
|
||||||
// Only process other app files.
|
// Only process other app files.
|
||||||
CreateFiles(0, 20);
|
CreateFiles(0, 20);
|
||||||
handler().ProcessIntermediateDumps({}, {});
|
handler().ProcessIntermediateDumps({}, nullptr);
|
||||||
VerifyRemainingFileCount(0, 0);
|
VerifyRemainingFileCount(0, 0);
|
||||||
ClearFiles();
|
ClearFiles();
|
||||||
|
|
||||||
// Only process our app files.
|
// Only process our app files.
|
||||||
CreateFiles(20, 20);
|
CreateFiles(20, 20);
|
||||||
handler().ProcessIntermediateDumps({}, {});
|
handler().ProcessIntermediateDumps({}, nullptr);
|
||||||
VerifyRemainingFileCount(0, 20);
|
VerifyRemainingFileCount(0, 20);
|
||||||
ClearFiles();
|
ClearFiles();
|
||||||
|
|
||||||
// Process all of our files and 10 remaining.
|
// Process all of our files and 10 remaining.
|
||||||
CreateFiles(10, 30);
|
CreateFiles(10, 30);
|
||||||
handler().ProcessIntermediateDumps({}, {});
|
handler().ProcessIntermediateDumps({}, nullptr);
|
||||||
VerifyRemainingFileCount(0, 20);
|
VerifyRemainingFileCount(0, 20);
|
||||||
ClearFiles();
|
ClearFiles();
|
||||||
|
|
||||||
// Process 20 our files, leaving 10 remaining, and all other files remaining.
|
// Process 20 our files, leaving 10 remaining, and all other files remaining.
|
||||||
CreateFiles(30, 10);
|
CreateFiles(30, 10);
|
||||||
handler().ProcessIntermediateDumps({}, {});
|
handler().ProcessIntermediateDumps({}, nullptr);
|
||||||
VerifyRemainingFileCount(10, 10);
|
VerifyRemainingFileCount(10, 10);
|
||||||
ClearFiles();
|
ClearFiles();
|
||||||
|
|
||||||
CreateFiles(0, 0);
|
CreateFiles(0, 0);
|
||||||
handler().ProcessIntermediateDumps({}, {});
|
handler().ProcessIntermediateDumps({}, nullptr);
|
||||||
VerifyRemainingFileCount(0, 0);
|
VerifyRemainingFileCount(0, 0);
|
||||||
ClearFiles();
|
ClearFiles();
|
||||||
|
|
||||||
CreateFiles(10, 0);
|
CreateFiles(10, 0);
|
||||||
handler().ProcessIntermediateDumps({}, {});
|
handler().ProcessIntermediateDumps({}, nullptr);
|
||||||
VerifyRemainingFileCount(0, 0);
|
VerifyRemainingFileCount(0, 0);
|
||||||
ClearFiles();
|
ClearFiles();
|
||||||
}
|
}
|
||||||
|
@ -104,6 +104,12 @@ bool IsMacOSVersion143OrGreaterAndiOS16OrLess() {
|
|||||||
|
|
||||||
- (void)setUp {
|
- (void)setUp {
|
||||||
app_ = [[XCUIApplication alloc] init];
|
app_ = [[XCUIApplication alloc] init];
|
||||||
|
if ([self.name isEqualToString:@"-[CPTestTestCase testExtensionStreams]"]) {
|
||||||
|
app_.launchArguments = @[ @"--test-extension-streams" ];
|
||||||
|
} else if ([self.name isEqualToString:
|
||||||
|
@"-[CPTestTestCase testCrashWithExtraMemory]"]) {
|
||||||
|
app_.launchArguments = @[ @"--test-extra_memory" ];
|
||||||
|
}
|
||||||
[app_ launch];
|
[app_ launch];
|
||||||
rootObject_ = [EDOClientService rootObjectWithPort:12345];
|
rootObject_ = [EDOClientService rootObjectWithPort:12345];
|
||||||
[rootObject_ clearPendingReports];
|
[rootObject_ clearPendingReports];
|
||||||
@ -397,12 +403,47 @@ bool IsMacOSVersion143OrGreaterAndiOS16OrLess() {
|
|||||||
XCTAssertFalse(reader.Pop(ringBufferEntry));
|
XCTAssertFalse(reader.Pop(ringBufferEntry));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)testCrashWithExtraMemory {
|
||||||
|
#if TARGET_OS_SIMULATOR
|
||||||
|
// This test will fail on older (<iOS17 simulators) when running on macOS 14.3
|
||||||
|
// or newer due to a bug in Simulator. crbug.com/328282286
|
||||||
|
if (crashpad::IsMacOSVersion143OrGreaterAndiOS16OrLess()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
[rootObject_ crashKillAbort];
|
||||||
|
[self verifyCrashReportException:EXC_SOFT_SIGNAL];
|
||||||
|
|
||||||
|
NSDictionary* dict = [rootObject_ getExtraMemory];
|
||||||
|
BOOL found = NO;
|
||||||
|
for (NSString* key in dict) {
|
||||||
|
if ([dict[key] isEqualToString:@"hello world"]) {
|
||||||
|
found = YES;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
XCTAssertTrue(found);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)testExtensionStreams {
|
||||||
|
#if TARGET_OS_SIMULATOR
|
||||||
|
// This test will fail on older (<iOS17 simulators) when running on macOS 14.3
|
||||||
|
// or newer due to a bug in Simulator. crbug.com/328282286
|
||||||
|
if (crashpad::IsMacOSVersion143OrGreaterAndiOS16OrLess()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
[rootObject_ crashKillAbort];
|
||||||
|
[self verifyCrashReportException:EXC_SOFT_SIGNAL];
|
||||||
|
XCTAssertTrue([rootObject_ hasExtensionStream]);
|
||||||
|
}
|
||||||
|
|
||||||
- (void)testDumpWithoutCrash {
|
- (void)testDumpWithoutCrash {
|
||||||
[rootObject_ generateDumpWithoutCrash:10 threads:3];
|
[rootObject_ generateDumpWithoutCrash:10 threads:3];
|
||||||
|
|
||||||
// The app should not crash
|
// The app should not crash
|
||||||
XCTAssertTrue(app_.state == XCUIApplicationStateRunningForeground);
|
XCTAssertTrue(app_.state == XCUIApplicationStateRunningForeground);
|
||||||
|
|
||||||
XCTAssertEqual([rootObject_ pendingReportCount], 30);
|
XCTAssertEqual([rootObject_ pendingReportCount], 30);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,6 +44,7 @@ static_library("app_host_sources") {
|
|||||||
":app_shared_sources",
|
":app_shared_sources",
|
||||||
"../../../build:apple_enable_arc",
|
"../../../build:apple_enable_arc",
|
||||||
"../../../client",
|
"../../../client",
|
||||||
|
"../../../minidump:test_support",
|
||||||
"../../../snapshot",
|
"../../../snapshot",
|
||||||
"../../../test",
|
"../../../test",
|
||||||
"../../../third_party/edo",
|
"../../../third_party/edo",
|
||||||
|
@ -41,6 +41,7 @@
|
|||||||
#include "client/ring_buffer_annotation.h"
|
#include "client/ring_buffer_annotation.h"
|
||||||
#include "client/simple_string_dictionary.h"
|
#include "client/simple_string_dictionary.h"
|
||||||
#include "client/simulate_crash.h"
|
#include "client/simulate_crash.h"
|
||||||
|
#include "minidump/test/minidump_user_extension_stream_util.h"
|
||||||
#include "snapshot/minidump/process_snapshot_minidump.h"
|
#include "snapshot/minidump/process_snapshot_minidump.h"
|
||||||
#include "test/file.h"
|
#include "test/file.h"
|
||||||
#import "test/ios/host/cptest_crash_view_controller.h"
|
#import "test/ios/host/cptest_crash_view_controller.h"
|
||||||
@ -55,6 +56,36 @@ using Report = crashpad::CrashReportDatabase::Report;
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
class ReadToString : public crashpad::MemorySnapshot::Delegate {
|
||||||
|
public:
|
||||||
|
std::string result;
|
||||||
|
|
||||||
|
bool MemorySnapshotDelegateRead(void* data, size_t size) override {
|
||||||
|
result = std::string(reinterpret_cast<const char*>(data), size);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static constexpr char kExpectedStreamData[] = "Injected extension stream!";
|
||||||
|
|
||||||
|
class TestUserStreamDataSource : public crashpad::UserStreamDataSource {
|
||||||
|
public:
|
||||||
|
TestUserStreamDataSource() {}
|
||||||
|
|
||||||
|
TestUserStreamDataSource(const TestUserStreamDataSource&) = delete;
|
||||||
|
TestUserStreamDataSource& operator=(const TestUserStreamDataSource&) = delete;
|
||||||
|
|
||||||
|
std::unique_ptr<crashpad::MinidumpUserExtensionStreamDataSource>
|
||||||
|
ProduceStreamData(crashpad::ProcessSnapshot* process_snapshot) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::unique_ptr<crashpad::MinidumpUserExtensionStreamDataSource>
|
||||||
|
TestUserStreamDataSource::ProduceStreamData(
|
||||||
|
crashpad::ProcessSnapshot* process_snapshot) {
|
||||||
|
return std::make_unique<crashpad::test::BufferExtensionStreamDataSource>(
|
||||||
|
0xCAFEBABE, kExpectedStreamData, sizeof(kExpectedStreamData));
|
||||||
|
}
|
||||||
|
|
||||||
constexpr crashpad::Annotation::Type kRingBufferType =
|
constexpr crashpad::Annotation::Type kRingBufferType =
|
||||||
crashpad::Annotation::UserDefinedType(42);
|
crashpad::Annotation::UserDefinedType(42);
|
||||||
|
|
||||||
@ -138,6 +169,8 @@ UIWindow* GetAnyWindow() {
|
|||||||
@implementation CPTestApplicationDelegate {
|
@implementation CPTestApplicationDelegate {
|
||||||
crashpad::CrashpadClient client_;
|
crashpad::CrashpadClient client_;
|
||||||
crashpad::ScopedFileHandle raw_logging_file_;
|
crashpad::ScopedFileHandle raw_logging_file_;
|
||||||
|
crashpad::SimpleAddressRangeBag extra_ranges_;
|
||||||
|
std::unique_ptr<std::string> extra_memory_string_;
|
||||||
}
|
}
|
||||||
|
|
||||||
@synthesize window = _window;
|
@synthesize window = _window;
|
||||||
@ -173,7 +206,19 @@ UIWindow* GetAnyWindow() {
|
|||||||
annotations,
|
annotations,
|
||||||
crashpad::CrashpadClient::
|
crashpad::CrashpadClient::
|
||||||
ProcessPendingReportsObservationCallback())) {
|
ProcessPendingReportsObservationCallback())) {
|
||||||
client_.ProcessIntermediateDumps();
|
crashpad::UserStreamDataSources user_stream_data_sources;
|
||||||
|
if ([arguments containsObject:@"--test-extension-streams"]) {
|
||||||
|
user_stream_data_sources.push_back(
|
||||||
|
std::make_unique<TestUserStreamDataSource>());
|
||||||
|
}
|
||||||
|
client_.ProcessIntermediateDumps({}, &user_stream_data_sources);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ([arguments containsObject:@"--test-extra_memory"]) {
|
||||||
|
crashpad::CrashpadInfo::GetCrashpadInfo()->set_extra_memory_ranges(
|
||||||
|
&extra_ranges_);
|
||||||
|
extra_memory_string_ = std::make_unique<std::string>("hello world");
|
||||||
|
extra_ranges_.Insert((void*)extra_memory_string_->c_str(), 11);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
|
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
|
||||||
@ -284,6 +329,43 @@ UIWindow* GetAnyWindow() {
|
|||||||
return [dict passByValue];
|
return [dict passByValue];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (NSDictionary*)getExtraMemory {
|
||||||
|
auto process_snapshot = GetProcessSnapshotMinidumpFromSinglePending();
|
||||||
|
if (!process_snapshot)
|
||||||
|
return @{};
|
||||||
|
|
||||||
|
NSDictionary* dict = [@{} mutableCopy];
|
||||||
|
|
||||||
|
for (auto memory : process_snapshot->ExtraMemory()) {
|
||||||
|
ReadToString delegate;
|
||||||
|
if (memory->Size() > 0 && memory->Read(&delegate) &&
|
||||||
|
!delegate.result.empty()) {
|
||||||
|
NSString* key = [@(memory->Address()) stringValue];
|
||||||
|
NSString* value = @(delegate.result.c_str());
|
||||||
|
if (value.length) {
|
||||||
|
[dict setValue:value forKey:key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return [dict passByValue];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)hasExtensionStream {
|
||||||
|
auto process_snapshot = GetProcessSnapshotMinidumpFromSinglePending();
|
||||||
|
if (!process_snapshot)
|
||||||
|
return NO;
|
||||||
|
|
||||||
|
auto streams = process_snapshot->CustomMinidumpStreams();
|
||||||
|
for (const auto& stream : streams) {
|
||||||
|
if (stream->stream_type() == 0xCAFEBABE) {
|
||||||
|
return memcmp(kExpectedStreamData,
|
||||||
|
stream->data().data(),
|
||||||
|
sizeof(kExpectedStreamData)) == 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
- (NSDictionary*)getProcessAnnotations {
|
- (NSDictionary*)getProcessAnnotations {
|
||||||
auto process_snapshot = GetProcessSnapshotMinidumpFromSinglePending();
|
auto process_snapshot = GetProcessSnapshotMinidumpFromSinglePending();
|
||||||
if (!process_snapshot)
|
if (!process_snapshot)
|
||||||
|
@ -43,11 +43,19 @@
|
|||||||
- (bool)pendingReportExceptionInfo:(NSNumber**)exception_info;
|
- (bool)pendingReportExceptionInfo:(NSNumber**)exception_info;
|
||||||
|
|
||||||
// Return an NSDictionary with a dictionary named "simplemap", an array named
|
// Return an NSDictionary with a dictionary named "simplemap", an array named
|
||||||
// "vector" and an array named "objects", representing the combination of all
|
// "vector" an array named "objects", and an array named "ringbuffers",
|
||||||
// modules AnnotationsSimpleMap, AnnotationsVector and AnnotationObjects
|
// representing the combination of all modules AnnotationsSimpleMap,
|
||||||
// (strings only) respectively.
|
// AnnotationsVector and AnnotationObjects (String and RingBuffer type)
|
||||||
|
// respectively.
|
||||||
- (NSDictionary*)getAnnotations;
|
- (NSDictionary*)getAnnotations;
|
||||||
|
|
||||||
|
// Return an NSDictionary with a dictionary representing all key value pairs of
|
||||||
|
// ExtraMemory MemorySnapshots where the data can be converted to an NSString.
|
||||||
|
- (NSDictionary*)getExtraMemory;
|
||||||
|
|
||||||
|
// Returns YES if a minidump contains the expected custom stream data.
|
||||||
|
- (BOOL)hasExtensionStream;
|
||||||
|
|
||||||
// Return an NSDictionary representing the ProcessSnapshotMinidump
|
// Return an NSDictionary representing the ProcessSnapshotMinidump
|
||||||
// AnnotationsSimpleMap.
|
// AnnotationsSimpleMap.
|
||||||
- (NSDictionary*)getProcessAnnotations;
|
- (NSDictionary*)getProcessAnnotations;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user