session-ios/Signal/src/ViewControllers/DebugUI/DebugUIStress.m

531 lines
36 KiB
Mathematica
Raw Normal View History

//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
#import "DebugUIStress.h"
#import "OWSMessageSender.h"
#import "OWSTableViewController.h"
#import "SignalApp.h"
#import "ThreadUtil.h"
2018-09-25 19:09:55 +02:00
#import <SignalCoreKit/Cryptography.h>
2018-09-21 21:41:10 +02:00
#import <SignalCoreKit/NSDate+OWS.h>
#import <SignalCoreKit/Randomness.h>
2017-12-19 03:50:51 +01:00
#import <SignalMessaging/Environment.h>
#import <SignalServiceKit/OWSDynamicOutgoingMessage.h>
#import <SignalServiceKit/OWSPrimaryStorage.h>
#import <SignalServiceKit/SignalServiceKit-Swift.h>
#import <SignalServiceKit/TSGroupThread.h>
#import <SignalServiceKit/TSThread.h>
NS_ASSUME_NONNULL_BEGIN
@implementation DebugUIStress
#pragma mark - Factory Methods
- (NSString *)name
{
return @"Stress";
}
- (nullable OWSTableSection *)sectionForThread:(nullable TSThread *)thread
{
OWSAssertDebug(thread);
NSMutableArray<OWSTableItem *> *items = [NSMutableArray new];
2018-08-30 16:03:14 +02:00
#ifdef DEBUG
[items addObject:[OWSTableItem itemWithTitle:@"Send empty message"
actionBlock:^{
[DebugUIStress sendStressMessage:thread block:^(SignalRecipient *recipient) {
return [NSData new];
}];
}]];
[items addObject:[OWSTableItem itemWithTitle:@"Send random noise message"
actionBlock:^{
[DebugUIStress
sendStressMessage:thread
block:^(SignalRecipient *recipient) {
NSUInteger contentLength = arc4random_uniform(32);
return [Cryptography generateRandomBytes:contentLength];
}];
}]];
[items addObject:[OWSTableItem itemWithTitle:@"Send no payload message"
actionBlock:^{
[DebugUIStress sendStressMessage:thread
block:^(SignalRecipient *recipient) {
SSKProtoContentBuilder *contentBuilder =
[SSKProtoContentBuilder new];
return [[contentBuilder buildIgnoringErrors]
serializedDataIgnoringErrors];
}];
}]];
[items addObject:[OWSTableItem itemWithTitle:@"Send empty null message"
actionBlock:^{
[DebugUIStress sendStressMessage:thread
block:^(SignalRecipient *recipient) {
SSKProtoContentBuilder *contentBuilder =
[SSKProtoContentBuilder new];
SSKProtoNullMessageBuilder *nullMessageBuilder =
[SSKProtoNullMessageBuilder new];
contentBuilder.nullMessage =
[nullMessageBuilder buildIgnoringErrors];
return [[contentBuilder buildIgnoringErrors]
serializedDataIgnoringErrors];
}];
}]];
[items addObject:[OWSTableItem itemWithTitle:@"Send random null message"
actionBlock:^{
[DebugUIStress
sendStressMessage:thread
block:^(SignalRecipient *recipient) {
SSKProtoContentBuilder *contentBuilder =
[SSKProtoContentBuilder new];
SSKProtoNullMessageBuilder *nullMessageBuilder =
[SSKProtoNullMessageBuilder new];
NSUInteger contentLength = arc4random_uniform(32);
nullMessageBuilder.padding =
[Cryptography generateRandomBytes:contentLength];
contentBuilder.nullMessage =
[nullMessageBuilder buildIgnoringErrors];
return [[contentBuilder buildIgnoringErrors]
serializedDataIgnoringErrors];
}];
}]];
[items addObject:[OWSTableItem itemWithTitle:@"Send empty sync message"
actionBlock:^{
[DebugUIStress sendStressMessage:thread
block:^(SignalRecipient *recipient) {
SSKProtoContentBuilder *contentBuilder =
[SSKProtoContentBuilder new];
SSKProtoSyncMessageBuilder *syncMessageBuilder =
[SSKProtoSyncMessageBuilder new];
contentBuilder.syncMessage =
[syncMessageBuilder buildIgnoringErrors];
return [[contentBuilder buildIgnoringErrors]
serializedDataIgnoringErrors];
}];
}]];
[items addObject:[OWSTableItem itemWithTitle:@"Send empty sync sent message"
actionBlock:^{
[DebugUIStress sendStressMessage:thread
block:^(SignalRecipient *recipient) {
SSKProtoContentBuilder *contentBuilder =
[SSKProtoContentBuilder new];
SSKProtoSyncMessageBuilder *syncMessageBuilder =
[SSKProtoSyncMessageBuilder new];
SSKProtoSyncMessageSentBuilder *sentBuilder =
[SSKProtoSyncMessageSentBuilder new];
syncMessageBuilder.sent =
[sentBuilder buildIgnoringErrors];
contentBuilder.syncMessage =
[syncMessageBuilder buildIgnoringErrors];
return [[contentBuilder buildIgnoringErrors]
serializedDataIgnoringErrors];
}];
}]];
[items addObject:[OWSTableItem itemWithTitle:@"Send whitespace text data message"
actionBlock:^{
[DebugUIStress
sendStressMessage:thread
block:^(SignalRecipient *recipient) {
SSKProtoContentBuilder *contentBuilder =
[SSKProtoContentBuilder new];
SSKProtoDataMessageBuilder *dataBuilder =
[SSKProtoDataMessageBuilder new];
dataBuilder.body = @" ";
[DebugUIStress ensureGroupOfDataBuilder:dataBuilder
thread:thread];
contentBuilder.dataMessage =
[dataBuilder buildIgnoringErrors];
return [[contentBuilder buildIgnoringErrors]
serializedDataIgnoringErrors];
}];
}]];
[items
addObject:[OWSTableItem
itemWithTitle:@"Send bad attachment data message"
actionBlock:^{
[DebugUIStress
sendStressMessage:thread
block:^(SignalRecipient *recipient) {
SSKProtoContentBuilder *contentBuilder = [SSKProtoContentBuilder new];
SSKProtoDataMessageBuilder *dataBuilder =
[SSKProtoDataMessageBuilder new];
SSKProtoAttachmentPointerBuilder *attachmentPointer =
[SSKProtoAttachmentPointerBuilder new];
[attachmentPointer setId:arc4random_uniform(32) + 1];
[attachmentPointer setContentType:@"1"];
[attachmentPointer setSize:arc4random_uniform(32) + 1];
[attachmentPointer setDigest:[Cryptography generateRandomBytes:1]];
[attachmentPointer setFileName:@" "];
[DebugUIStress ensureGroupOfDataBuilder:dataBuilder thread:thread];
contentBuilder.dataMessage = [dataBuilder buildIgnoringErrors];
return
[[contentBuilder buildIgnoringErrors] serializedDataIgnoringErrors];
}];
}]];
[items addObject:[OWSTableItem itemWithTitle:@"Send normal text data message"
actionBlock:^{
[DebugUIStress
sendStressMessage:thread
block:^(SignalRecipient *recipient) {
SSKProtoContentBuilder *contentBuilder =
[SSKProtoContentBuilder new];
SSKProtoDataMessageBuilder *dataBuilder =
[SSKProtoDataMessageBuilder new];
dataBuilder.body = @"alice";
[DebugUIStress ensureGroupOfDataBuilder:dataBuilder
thread:thread];
contentBuilder.dataMessage =
[dataBuilder buildIgnoringErrors];
return [[contentBuilder buildIgnoringErrors]
serializedDataIgnoringErrors];
}];
}]];
[items addObject:[OWSTableItem itemWithTitle:@"Send N text messages with same timestamp"
actionBlock:^{
uint64_t timestamp = [NSDate ows_millisecondTimeStamp];
for (int i = 0; i < 3; i++) {
[DebugUIStress
sendStressMessage:thread
timestamp:timestamp
block:^(SignalRecipient *recipient) {
SSKProtoContentBuilder *contentBuilder =
[SSKProtoContentBuilder new];
SSKProtoDataMessageBuilder *dataBuilder =
[SSKProtoDataMessageBuilder new];
dataBuilder.body = [NSString stringWithFormat:@"%@ %d",
[NSUUID UUID].UUIDString,
i];
[DebugUIStress ensureGroupOfDataBuilder:dataBuilder
thread:thread];
contentBuilder.dataMessage =
[dataBuilder buildIgnoringErrors];
return [[contentBuilder buildIgnoringErrors]
serializedDataIgnoringErrors];
}];
}
}]];
[items addObject:[OWSTableItem
itemWithTitle:@"Send text message with current timestamp"
actionBlock:^{
uint64_t timestamp = [NSDate ows_millisecondTimeStamp];
[DebugUIStress
sendStressMessage:thread
timestamp:timestamp
block:^(SignalRecipient *recipient) {
SSKProtoContentBuilder *contentBuilder =
[SSKProtoContentBuilder new];
SSKProtoDataMessageBuilder *dataBuilder =
[SSKProtoDataMessageBuilder new];
dataBuilder.body =
[[NSUUID UUID].UUIDString stringByAppendingString:@" now"];
[DebugUIStress ensureGroupOfDataBuilder:dataBuilder thread:thread];
contentBuilder.dataMessage = [dataBuilder buildIgnoringErrors];
return [[contentBuilder buildIgnoringErrors]
serializedDataIgnoringErrors];
}];
}]];
[items addObject:[OWSTableItem
itemWithTitle:@"Send text message with future timestamp"
actionBlock:^{
uint64_t timestamp = [NSDate ows_millisecondTimeStamp];
timestamp += kHourInMs;
[DebugUIStress
sendStressMessage:thread
timestamp:timestamp
block:^(SignalRecipient *recipient) {
SSKProtoContentBuilder *contentBuilder =
[SSKProtoContentBuilder new];
SSKProtoDataMessageBuilder *dataBuilder =
[SSKProtoDataMessageBuilder new];
dataBuilder.body =
[[NSUUID UUID].UUIDString stringByAppendingString:@" now"];
[DebugUIStress ensureGroupOfDataBuilder:dataBuilder thread:thread];
contentBuilder.dataMessage = [dataBuilder buildIgnoringErrors];
return [[contentBuilder buildIgnoringErrors]
serializedDataIgnoringErrors];
}];
}]];
[items addObject:[OWSTableItem
itemWithTitle:@"Send text message with past timestamp"
actionBlock:^{
uint64_t timestamp = [NSDate ows_millisecondTimeStamp];
timestamp -= kHourInMs;
[DebugUIStress
sendStressMessage:thread
timestamp:timestamp
block:^(SignalRecipient *recipient) {
SSKProtoContentBuilder *contentBuilder =
[SSKProtoContentBuilder new];
SSKProtoDataMessageBuilder *dataBuilder =
[SSKProtoDataMessageBuilder new];
dataBuilder.body =
[[NSUUID UUID].UUIDString stringByAppendingString:@" now"];
[DebugUIStress ensureGroupOfDataBuilder:dataBuilder thread:thread];
contentBuilder.dataMessage = [dataBuilder buildIgnoringErrors];
return [[contentBuilder buildIgnoringErrors]
serializedDataIgnoringErrors];
}];
}]];
[items addObject:[OWSTableItem itemWithTitle:@"Send N text messages with same timestamp"
actionBlock:^{
SSKProtoContentBuilder *contentBuilder = [SSKProtoContentBuilder new];
SSKProtoDataMessageBuilder *dataBuilder = [SSKProtoDataMessageBuilder new];
dataBuilder.body = @"alice";
contentBuilder.dataMessage = [dataBuilder buildIgnoringErrors];
[DebugUIStress ensureGroupOfDataBuilder:dataBuilder thread:thread];
NSData *data =
[[contentBuilder buildIgnoringErrors] serializedDataIgnoringErrors];
uint64_t timestamp = [NSDate ows_millisecondTimeStamp];
for (int i = 0; i < 3; i++) {
[DebugUIStress sendStressMessage:thread
timestamp:timestamp
block:^(SignalRecipient *recipient) {
return data;
}];
}
}]];
[items
addObject:[OWSTableItem
itemWithTitle:@"Send malformed sync sent message 1"
actionBlock:^{
[DebugUIStress
sendStressMessage:thread
block:^(SignalRecipient *recipient) {
SSKProtoContentBuilder *contentBuilder = [SSKProtoContentBuilder new];
SSKProtoSyncMessageBuilder *syncMessageBuilder =
[SSKProtoSyncMessageBuilder new];
SSKProtoSyncMessageSentBuilder *sentBuilder =
[SSKProtoSyncMessageSentBuilder new];
sentBuilder.destination = @"abc";
sentBuilder.timestamp = arc4random_uniform(32) + 1;
SSKProtoDataMessageBuilder *dataBuilder =
[SSKProtoDataMessageBuilder new];
sentBuilder.message = [dataBuilder buildIgnoringErrors];
syncMessageBuilder.sent = [sentBuilder buildIgnoringErrors];
contentBuilder.syncMessage = [syncMessageBuilder buildIgnoringErrors];
return
[[contentBuilder buildIgnoringErrors] serializedDataIgnoringErrors];
}];
}]];
[items
addObject:[OWSTableItem
itemWithTitle:@"Send malformed sync sent message 2"
actionBlock:^{
[DebugUIStress
sendStressMessage:thread
block:^(SignalRecipient *recipient) {
SSKProtoContentBuilder *contentBuilder = [SSKProtoContentBuilder new];
SSKProtoSyncMessageBuilder *syncMessageBuilder =
[SSKProtoSyncMessageBuilder new];
SSKProtoSyncMessageSentBuilder *sentBuilder =
[SSKProtoSyncMessageSentBuilder new];
sentBuilder.destination = @"abc";
sentBuilder.timestamp = 0;
SSKProtoDataMessageBuilder *dataBuilder =
[SSKProtoDataMessageBuilder new];
sentBuilder.message = [dataBuilder buildIgnoringErrors];
syncMessageBuilder.sent = [sentBuilder buildIgnoringErrors];
contentBuilder.syncMessage = [syncMessageBuilder buildIgnoringErrors];
return
[[contentBuilder buildIgnoringErrors] serializedDataIgnoringErrors];
}];
}]];
[items
addObject:[OWSTableItem
itemWithTitle:@"Send malformed sync sent message 3"
actionBlock:^{
[DebugUIStress
sendStressMessage:thread
block:^(SignalRecipient *recipient) {
SSKProtoContentBuilder *contentBuilder = [SSKProtoContentBuilder new];
SSKProtoSyncMessageBuilder *syncMessageBuilder =
[SSKProtoSyncMessageBuilder new];
SSKProtoSyncMessageSentBuilder *sentBuilder =
[SSKProtoSyncMessageSentBuilder new];
sentBuilder.destination = @"abc";
sentBuilder.timestamp = 0;
SSKProtoDataMessageBuilder *dataBuilder =
[SSKProtoDataMessageBuilder new];
dataBuilder.body = @" ";
sentBuilder.message = [dataBuilder buildIgnoringErrors];
syncMessageBuilder.sent = [sentBuilder buildIgnoringErrors];
contentBuilder.syncMessage = [syncMessageBuilder buildIgnoringErrors];
return
[[contentBuilder buildIgnoringErrors] serializedDataIgnoringErrors];
}];
}]];
[items
addObject:[OWSTableItem
itemWithTitle:@"Send malformed sync sent message 4"
actionBlock:^{
[DebugUIStress
sendStressMessage:thread
block:^(SignalRecipient *recipient) {
SSKProtoContentBuilder *contentBuilder = [SSKProtoContentBuilder new];
SSKProtoSyncMessageBuilder *syncMessageBuilder =
[SSKProtoSyncMessageBuilder new];
SSKProtoSyncMessageSentBuilder *sentBuilder =
[SSKProtoSyncMessageSentBuilder new];
sentBuilder.destination = @"abc";
sentBuilder.timestamp = 0;
SSKProtoDataMessageBuilder *dataBuilder =
[SSKProtoDataMessageBuilder new];
dataBuilder.body = @" ";
SSKProtoGroupContextBuilder *groupBuilder =
[SSKProtoGroupContextBuilder new];
[groupBuilder setId:[Cryptography generateRandomBytes:1]];
dataBuilder.group = [groupBuilder buildIgnoringErrors];
sentBuilder.message = [dataBuilder buildIgnoringErrors];
syncMessageBuilder.sent = [sentBuilder buildIgnoringErrors];
contentBuilder.syncMessage = [syncMessageBuilder buildIgnoringErrors];
return
[[contentBuilder buildIgnoringErrors] serializedDataIgnoringErrors];
}];
}]];
[items
addObject:[OWSTableItem
itemWithTitle:@"Send malformed sync sent message 5"
actionBlock:^{
[DebugUIStress
sendStressMessage:thread
block:^(SignalRecipient *recipient) {
SSKProtoContentBuilder *contentBuilder = [SSKProtoContentBuilder new];
SSKProtoSyncMessageBuilder *syncMessageBuilder =
[SSKProtoSyncMessageBuilder new];
SSKProtoSyncMessageSentBuilder *sentBuilder =
[SSKProtoSyncMessageSentBuilder new];
sentBuilder.destination = @"abc";
sentBuilder.timestamp = 0;
SSKProtoDataMessageBuilder *dataBuilder =
[SSKProtoDataMessageBuilder new];
dataBuilder.body = @" ";
SSKProtoGroupContextBuilder *groupBuilder =
[SSKProtoGroupContextBuilder new];
[groupBuilder setId:[Cryptography generateRandomBytes:1]];
dataBuilder.group = [groupBuilder buildIgnoringErrors];
sentBuilder.message = [dataBuilder buildIgnoringErrors];
syncMessageBuilder.sent = [sentBuilder buildIgnoringErrors];
contentBuilder.syncMessage = [syncMessageBuilder buildIgnoringErrors];
return
[[contentBuilder buildIgnoringErrors] serializedDataIgnoringErrors];
}];
}]];
[items addObject:[OWSTableItem itemWithTitle:@"Send empty sync sent message 6"
actionBlock:^{
[DebugUIStress sendStressMessage:thread
block:^(SignalRecipient *recipient) {
SSKProtoContentBuilder *contentBuilder =
[SSKProtoContentBuilder new];
SSKProtoSyncMessageBuilder *syncMessageBuilder =
[SSKProtoSyncMessageBuilder new];
SSKProtoSyncMessageSentBuilder *sentBuilder =
[SSKProtoSyncMessageSentBuilder new];
sentBuilder.destination = @"abc";
syncMessageBuilder.sent =
[sentBuilder buildIgnoringErrors];
contentBuilder.syncMessage =
[syncMessageBuilder buildIgnoringErrors];
return [[contentBuilder buildIgnoringErrors]
serializedDataIgnoringErrors];
}];
}]];
if ([thread isKindOfClass:[TSGroupThread class]]) {
TSGroupThread *groupThread = (TSGroupThread *)thread;
[items addObject:[OWSTableItem itemWithTitle:@"Hallucinate twin group"
actionBlock:^{
[DebugUIStress hallucinateTwinGroup:groupThread];
}]];
}
2018-08-30 16:03:14 +02:00
#endif
return [OWSTableSection sectionWithTitle:self.name items:items];
}
2018-08-30 16:03:14 +02:00
#ifdef DEBUG
+ (void)ensureGroupOfDataBuilder:(SSKProtoDataMessageBuilder *)dataBuilder thread:(TSThread *)thread
{
OWSAssertDebug(dataBuilder);
OWSAssertDebug(thread);
if (![thread isKindOfClass:[TSGroupThread class]]) {
return;
}
TSGroupThread *groupThread = (TSGroupThread *)thread;
SSKProtoGroupContextBuilder *groupBuilder = [SSKProtoGroupContextBuilder new];
[groupBuilder setType:SSKProtoGroupContextTypeDeliver];
[groupBuilder setId:groupThread.groupModel.groupId];
[dataBuilder setGroup:groupBuilder.buildIgnoringErrors];
}
+ (void)sendStressMessage:(TSOutgoingMessage *)message
{
OWSAssertDebug(message);
2018-09-17 15:27:58 +02:00
OWSMessageSender *messageSender = SSKEnvironment.shared.messageSender;
2017-11-15 19:21:31 +01:00
[messageSender enqueueMessage:message
2017-11-08 20:04:51 +01:00
success:^{
OWSLogInfo(@"Successfully sent message.");
2017-11-08 20:04:51 +01:00
}
failure:^(NSError *error) {
OWSLogWarn(@"Failed to deliver message with error: %@", error);
2017-11-08 20:04:51 +01:00
}];
}
+ (void)sendStressMessage:(TSThread *)thread
block:(DynamicOutgoingMessageBlock)block
{
OWSAssertDebug(thread);
OWSAssertDebug(block);
2017-09-22 20:21:15 +02:00
OWSDynamicOutgoingMessage *message =
[[OWSDynamicOutgoingMessage alloc] initWithPlainTextDataBlock:block thread:thread];
[self sendStressMessage:message];
}
+ (void)sendStressMessage:(TSThread *)thread timestamp:(uint64_t)timestamp block:(DynamicOutgoingMessageBlock)block
{
OWSAssertDebug(thread);
OWSAssertDebug(block);
OWSDynamicOutgoingMessage *message =
2017-09-22 20:21:15 +02:00
[[OWSDynamicOutgoingMessage alloc] initWithPlainTextDataBlock:block timestamp:timestamp thread:thread];
[self sendStressMessage:message];
}
// Creates a new group (by cloning the current group) without informing the,
// other members. This can be used to test "group info requests", etc.
+ (void)hallucinateTwinGroup:(TSGroupThread *)groupThread
{
__block TSGroupThread *thread;
[OWSPrimaryStorage.dbReadWriteConnection
2017-12-19 03:34:22 +01:00
readWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
TSGroupModel *groupModel =
[[TSGroupModel alloc] initWithTitle:[groupThread.groupModel.groupName stringByAppendingString:@" Copy"]
memberIds:groupThread.groupModel.groupMemberIds
2017-12-19 03:34:22 +01:00
image:groupThread.groupModel.groupImage
2018-07-27 20:40:58 +02:00
groupId:[Randomness generateRandomBytes:16]];
2017-12-19 03:34:22 +01:00
thread = [TSGroupThread getOrCreateThreadWithGroupModel:groupModel transaction:transaction];
}];
OWSAssertDebug(thread);
Faster conversation presentation. There are multiple places in the codebase we present a conversation. We used to have some very conservative machinery around how this was done, for fear of failing to present the call view controller, which would have left a hidden call in the background. We've since addressed that concern more thoroughly via the separate calling UIWindow. As such, the remaining presentation machinery is overly complex and inflexible for what we need. Sometimes we want to animate-push the conversation. (tap on home, tap on "send message" in contact card/group members) Sometimes we want to dismiss a modal, to reveal the conversation behind it (contact picker, group creation) Sometimes we want to present the conversation with no animation (becoming active from a notification) We also want to ensure that we're never pushing more than one conversation view controller, which was previously a problem since we were "pushing" a newly constructed VC in response to these myriad actions. It turned out there were certain code paths that caused multiple actions to be fired in rapid succession which pushed multiple ConversationVC's. The built-in method: `setViewControllers:animated` easily ensures we only have one ConversationVC on the stack, while being composable enough to faciliate the various more efficient animations we desire. The only thing lost with the complex methods is that the naive `presentViewController:` can fail, e.g. if another view is already presented. E.g. if an alert appears *just* before the user taps compose, the contact picker will fail to present. Since we no longer depend on this for presenting the CallViewController, this isn't catostrophic, and in fact, arguable preferable, since we want the user to read and dismiss any alert explicitly. // FREEBIE
2018-08-18 22:54:35 +02:00
[SignalApp.sharedApp presentConversationForThread:thread animated:YES];
}
2018-08-30 16:03:14 +02:00
#endif
@end
NS_ASSUME_NONNULL_END