Merge branch 'mkirk/fix-tests'

This commit is contained in:
Michael Kirk 2018-11-11 11:15:16 -06:00
commit 197f06af77
14 changed files with 147 additions and 116 deletions

2
Pods

@ -1 +1 @@
Subproject commit 34b98cdc33f8cec77b845f5e513500fb85d423a2 Subproject commit 4a40f1590bbff2c9725a6925c077ad6e67bdda6e

View file

@ -964,7 +964,6 @@
34D920E620E179C200D51158 /* OWSMessageFooterView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSMessageFooterView.m; sourceTree = "<group>"; }; 34D920E620E179C200D51158 /* OWSMessageFooterView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSMessageFooterView.m; sourceTree = "<group>"; };
34D99C911F2937CC00D284D6 /* OWSAnalytics.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OWSAnalytics.swift; sourceTree = "<group>"; }; 34D99C911F2937CC00D284D6 /* OWSAnalytics.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OWSAnalytics.swift; sourceTree = "<group>"; };
34D99CE3217509C1000AFB39 /* AppEnvironment.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppEnvironment.swift; sourceTree = "<group>"; }; 34D99CE3217509C1000AFB39 /* AppEnvironment.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppEnvironment.swift; sourceTree = "<group>"; };
34DB0BEB2011548A007B313F /* OWSDatabaseConverterTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSDatabaseConverterTest.h; sourceTree = "<group>"; };
34DB0BEC2011548B007B313F /* OWSDatabaseConverterTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSDatabaseConverterTest.m; sourceTree = "<group>"; }; 34DB0BEC2011548B007B313F /* OWSDatabaseConverterTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSDatabaseConverterTest.m; sourceTree = "<group>"; };
34DBEFFF206BD5A400025978 /* OWSMessageTextView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSMessageTextView.m; sourceTree = "<group>"; }; 34DBEFFF206BD5A400025978 /* OWSMessageTextView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSMessageTextView.m; sourceTree = "<group>"; };
34DBF000206BD5A400025978 /* OWSMessageTextView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSMessageTextView.h; sourceTree = "<group>"; }; 34DBF000206BD5A400025978 /* OWSMessageTextView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSMessageTextView.h; sourceTree = "<group>"; };
@ -2386,7 +2385,6 @@
45E7A6A61E71CA7E00D44FB5 /* DisplayableTextFilterTest.swift */, 45E7A6A61E71CA7E00D44FB5 /* DisplayableTextFilterTest.swift */,
B660F6AD1C29868000687D6E /* FunctionalUtilTest.m */, B660F6AD1C29868000687D6E /* FunctionalUtilTest.m */,
455AC69D1F4F8B0300134004 /* ImageCacheTest.swift */, 455AC69D1F4F8B0300134004 /* ImageCacheTest.swift */,
34DB0BEB2011548A007B313F /* OWSDatabaseConverterTest.h */,
34DB0BEC2011548B007B313F /* OWSDatabaseConverterTest.m */, 34DB0BEC2011548B007B313F /* OWSDatabaseConverterTest.m */,
34843B25214327C9004DED45 /* OWSOrphanDataCleanerTest.m */, 34843B25214327C9004DED45 /* OWSOrphanDataCleanerTest.m */,
45666F571D9B2880008FE134 /* OWSScrubbingLogFormatterTest.m */, 45666F571D9B2880008FE134 /* OWSScrubbingLogFormatterTest.m */,

View file

@ -17,15 +17,20 @@
- (void)testParsing_good - (void)testParsing_good
{ {
NSString *pem = [self certificatesPem_good]; NSString *pem = [self certificatesPem_good];
CDSSigningCertificate *_Nullable certificate = [CDSSigningCertificate parseCertificateFromPem:pem]; NSError *error;
CDSSigningCertificate *_Nullable certificate = [CDSSigningCertificate parseCertificateFromPem:pem error:&error];
XCTAssertNotNil(certificate); XCTAssertNotNil(certificate);
XCTAssertNil(error);
} }
- (void)testParsing_bad - (void)testParsing_bad
{ {
NSString *pem = [self certificatesPem_bad]; NSString *pem = [self certificatesPem_bad];
NSError *error;
XCTAssertThrows([CDSSigningCertificate parseCertificateFromPem:pem]); CDSSigningCertificate *_Nullable certificate = [CDSSigningCertificate parseCertificateFromPem:pem error:&error];
XCTAssertNil(certificate);
XCTAssertNotNil(error);
XCTAssertEqual(error.code, CDSSigningCertificateError_InvalidDistinguishedName);
} }
- (void)testVerification_good - (void)testVerification_good
@ -33,9 +38,11 @@
NSString *pem = [self certificatesPem_good]; NSString *pem = [self certificatesPem_good];
NSData *signature = [self signature_good]; NSData *signature = [self signature_good];
NSString *bodyString = [self bodyString_good]; NSString *bodyString = [self bodyString_good];
CDSSigningCertificate *_Nullable certificate = [CDSSigningCertificate parseCertificateFromPem:pem]; NSError *error;
CDSSigningCertificate *_Nullable certificate = [CDSSigningCertificate parseCertificateFromPem:pem error:&error];
XCTAssertNotNil(certificate); XCTAssertNotNil(certificate);
XCTAssertNil(error);
BOOL result = [certificate verifySignatureOfBody:bodyString signature:signature]; BOOL result = [certificate verifySignatureOfBody:bodyString signature:signature];
XCTAssertTrue(result); XCTAssertTrue(result);
@ -46,11 +53,13 @@
NSString *pem = [self certificatesPem_good]; NSString *pem = [self certificatesPem_good];
NSData *signature = [self signature_good]; NSData *signature = [self signature_good];
NSString *bodyString = [self bodyString_bad]; NSString *bodyString = [self bodyString_bad];
CDSSigningCertificate *_Nullable certificate = [CDSSigningCertificate parseCertificateFromPem:pem];
XCTAssertNotNil(certificate);
XCTAssertThrows([certificate verifySignatureOfBody:bodyString signature:signature]); NSError *error;
CDSSigningCertificate *_Nullable certificate = [CDSSigningCertificate parseCertificateFromPem:pem error:&error];
XCTAssertNotNil(certificate);
XCTAssertNil(error);
XCTAssertFalse([certificate verifySignatureOfBody:bodyString signature:signature]);
} }
- (void)testVerification_badSignature - (void)testVerification_badSignature
@ -58,13 +67,17 @@
NSString *pem = [self certificatesPem_good]; NSString *pem = [self certificatesPem_good];
NSData *signature = [self signature_bad]; NSData *signature = [self signature_bad];
NSString *bodyString = [self bodyString_good]; NSString *bodyString = [self bodyString_good];
CDSSigningCertificate *_Nullable certificate = [CDSSigningCertificate parseCertificateFromPem:pem];
XCTAssertNotNil(certificate);
XCTAssertThrows([certificate verifySignatureOfBody:bodyString signature:signature]); NSError *error;
CDSSigningCertificate *_Nullable certificate = [CDSSigningCertificate parseCertificateFromPem:pem error:&error];
XCTAssertNotNil(certificate);
XCTAssertNil(error);
XCTAssertFalse([certificate verifySignatureOfBody:bodyString signature:signature]);
} }
#pragma mark - test values
- (NSString *)certificatesPem_good { - (NSString *)certificatesPem_good {
return @"-----BEGIN CERTIFICATE----- \ return @"-----BEGIN CERTIFICATE----- \
MIIEoTCCAwmgAwIBAgIJANEHdl0yo7CWMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNV \ MIIEoTCCAwmgAwIBAgIJANEHdl0yo7CWMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNV \

View file

@ -38,15 +38,6 @@
test([[(@[@1,@2]) filter:^(NSNumber* x) { return x.intValue == 2; }] isEqualToArray:(@[@2])]); test([[(@[@1,@2]) filter:^(NSNumber* x) { return x.intValue == 2; }] isEqualToArray:(@[@2])]);
} }
-(void) testKeyedBy {
test([[@[] keyedBy:^id(id value) { return @true; }] isEqual:@{}]);
test([[@[@1] keyedBy:^id(id value) { return @true; }] isEqual:@{@true : @1}]);
testThrows(([(@[@1, @2]) keyedBy:^id(id value) { return @true; }]));
test([[(@[@1, @2]) keyedBy:^id(id value) { return value; }] isEqual:(@{@1 : @1, @2 : @2})]);
testThrows([(@[@1, @1, @2, @3, @5]) keyedBy:^id(NSNumber* value) { return @(value.intValue/2); }]);
test([[(@[@3, @5, @7, @11, @13]) keyedBy:^id(NSNumber* value) { return @(value.intValue/2); }] isEqual:(@{@1 : @3, @2 : @5, @3 : @7, @5 : @11, @6 : @13})]);
}
-(void) testGroupBy { -(void) testGroupBy {
test([[@[] groupBy:^id(id value) { return @true; }] isEqual:@{}]); test([[@[] groupBy:^id(id value) { return @true; }] isEqual:@{}]);
test([[@[@1] groupBy:^id(id value) { return @true; }] isEqual:@{@true : @[@1]}]); test([[@[@1] groupBy:^id(id value) { return @true; }] isEqual:@{@true : @[@1]}]);

View file

@ -1,13 +0,0 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
#import "SignalBaseTest.h"
NS_ASSUME_NONNULL_BEGIN
@interface OWSDatabaseConverterTest : SignalBaseTest
@end
NS_ASSUME_NONNULL_END

View file

@ -2,7 +2,7 @@
// Copyright (c) 2018 Open Whisper Systems. All rights reserved. // Copyright (c) 2018 Open Whisper Systems. All rights reserved.
// //
#import "OWSDatabaseConverterTest.h" #import "SignalBaseTest.h"
#import <SignalCoreKit/NSData+OWS.h> #import <SignalCoreKit/NSData+OWS.h>
#import <SignalCoreKit/Randomness.h> #import <SignalCoreKit/Randomness.h>
#import <SignalServiceKit/OWSFileSystem.h> #import <SignalServiceKit/OWSFileSystem.h>
@ -39,6 +39,12 @@ NS_ASSUME_NONNULL_BEGIN
#pragma mark - #pragma mark -
@interface OWSDatabaseConverterTest : SignalBaseTest
@end
#pragma mark -
@implementation OWSDatabaseConverterTest @implementation OWSDatabaseConverterTest
- (NSData *)randomDatabasePassword - (NSData *)randomDatabasePassword

View file

@ -35,7 +35,6 @@
@implementation UtilTest @implementation UtilTest
-(void) testRemoveAllCharactersIn { -(void) testRemoveAllCharactersIn {
testThrows([@"" removeAllCharactersIn:nil]);
test([[@"" removeAllCharactersIn:NSCharacterSet.letterCharacterSet] isEqual:@""]); test([[@"" removeAllCharactersIn:NSCharacterSet.letterCharacterSet] isEqual:@""]);
test([[@"1" removeAllCharactersIn:NSCharacterSet.letterCharacterSet] isEqual:@"1"]); test([[@"1" removeAllCharactersIn:NSCharacterSet.letterCharacterSet] isEqual:@"1"]);

View file

@ -4,9 +4,24 @@
NS_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_BEGIN
typedef NS_ENUM(NSUInteger, CDSSigningCertificateErrorCode) {
// AssertionError's indicate either developer or some serious system error that should never happen.
//
// Do not use this for an "expected" error, e.g. something that could be induced by user input which
// we specifically need to handle gracefull.
CDSSigningCertificateError_AssertionError = 1,
CDSSigningCertificateError_InvalidPEMSupplied,
CDSSigningCertificateError_CouldNotExtractLeafCertificate,
CDSSigningCertificateError_InvalidDistinguishedName,
CDSSigningCertificateError_UntrustedCertificate
};
NSError *CDSSigningCertificateErrorMake(CDSSigningCertificateErrorCode code, NSString *localizedDescription);
@interface CDSSigningCertificate : NSObject @interface CDSSigningCertificate : NSObject
+ (nullable CDSSigningCertificate *)parseCertificateFromPem:(NSString *)certificatePem; + (nullable CDSSigningCertificate *)parseCertificateFromPem:(NSString *)certificatePem error:(NSError **)error;
- (BOOL)verifySignatureOfBody:(NSString *)body signature:(NSData *)theirSignature; - (BOOL)verifySignatureOfBody:(NSString *)body signature:(NSData *)theirSignature;

View file

@ -10,6 +10,13 @@
NS_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_BEGIN
NSError *CDSSigningCertificateErrorMake(CDSSigningCertificateErrorCode code, NSString *localizedDescription)
{
return [NSError errorWithDomain:@"CDSSigningCertificate"
code:code
userInfo:@{ NSLocalizedDescriptionKey : localizedDescription }];
}
@interface CDSSigningCertificate () @interface CDSSigningCertificate ()
@property (nonatomic) SecPolicyRef policy; @property (nonatomic) SecPolicyRef policy;
@ -49,15 +56,18 @@ NS_ASSUME_NONNULL_BEGIN
} }
} }
+ (nullable CDSSigningCertificate *)parseCertificateFromPem:(NSString *)certificatePem + (nullable CDSSigningCertificate *)parseCertificateFromPem:(NSString *)certificatePem error:(NSError **)error
{ {
OWSAssertDebug(certificatePem); OWSAssertDebug(certificatePem);
*error = nil;
CDSSigningCertificate *signingCertificate = [CDSSigningCertificate new]; CDSSigningCertificate *signingCertificate = [CDSSigningCertificate new];
NSArray<NSData *> *_Nullable anchorCertificates = [self anchorCertificates]; NSArray<NSData *> *_Nullable anchorCertificates = [self anchorCertificates];
if (anchorCertificates.count < 1) { if (anchorCertificates.count < 1) {
OWSFailDebug(@"Could not load anchor certificates."); OWSFailDebug(@"Could not load anchor certificates.");
*error = CDSSigningCertificateErrorMake(
CDSSigningCertificateError_AssertionError, @"Could not load anchor certificates.");
return nil; return nil;
} }
@ -65,6 +75,7 @@ NS_ASSUME_NONNULL_BEGIN
if (certificateDerDatas.count < 1) { if (certificateDerDatas.count < 1) {
OWSFailDebug(@"Could not parse PEM."); OWSFailDebug(@"Could not parse PEM.");
*error = CDSSigningCertificateErrorMake(CDSSigningCertificateError_InvalidPEMSupplied, @"Could not parse PEM.");
return nil; return nil;
} }
@ -72,10 +83,14 @@ NS_ASSUME_NONNULL_BEGIN
NSData *_Nullable leafCertificateData = [certificateDerDatas firstObject]; NSData *_Nullable leafCertificateData = [certificateDerDatas firstObject];
if (!leafCertificateData) { if (!leafCertificateData) {
OWSFailDebug(@"Could not extract leaf certificate data."); OWSFailDebug(@"Could not extract leaf certificate data.");
*error = CDSSigningCertificateErrorMake(
CDSSigningCertificateError_CouldNotExtractLeafCertificate, @"Could not extract leaf certificate data.");
return nil; return nil;
} }
if (![self verifyDistinguishedNameOfCertificate:leafCertificateData]) { if (![self verifyDistinguishedNameOfCertificate:leafCertificateData]) {
OWSFailDebug(@"Leaf certificate has invalid name."); OWSFailDebug(@"Leaf certificate has invalid name.");
*error = CDSSigningCertificateErrorMake(
CDSSigningCertificateError_InvalidDistinguishedName, @"Could not extract leaf certificate data.");
return nil; return nil;
} }
@ -83,7 +98,9 @@ NS_ASSUME_NONNULL_BEGIN
for (NSData *certificateDerData in certificateDerDatas) { for (NSData *certificateDerData in certificateDerDatas) {
SecCertificateRef certificate = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)(certificateDerData)); SecCertificateRef certificate = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)(certificateDerData));
if (!certificate) { if (!certificate) {
OWSFailDebug(@"Could not load DER."); OWSFailDebug(@"Could not create SecCertificate.");
*error = CDSSigningCertificateErrorMake(
CDSSigningCertificateError_AssertionError, @"Could not create SecCertificate.");
return nil; return nil;
} }
[certificates addObject:(__bridge_transfer id)certificate]; [certificates addObject:(__bridge_transfer id)certificate];
@ -93,6 +110,7 @@ NS_ASSUME_NONNULL_BEGIN
signingCertificate.policy = policy; signingCertificate.policy = policy;
if (!policy) { if (!policy) {
OWSFailDebug(@"Could not create policy."); OWSFailDebug(@"Could not create policy.");
*error = CDSSigningCertificateErrorMake(CDSSigningCertificateError_AssertionError, @"Could not create policy.");
return nil; return nil;
} }
@ -100,23 +118,30 @@ NS_ASSUME_NONNULL_BEGIN
OSStatus status = SecTrustCreateWithCertificates((__bridge CFTypeRef)certificates, policy, &trust); OSStatus status = SecTrustCreateWithCertificates((__bridge CFTypeRef)certificates, policy, &trust);
signingCertificate.trust = trust; signingCertificate.trust = trust;
if (status != errSecSuccess) { if (status != errSecSuccess) {
OWSFailDebug(@"trust could not be created."); OWSFailDebug(@"Creating trust did not succeed.");
*error = CDSSigningCertificateErrorMake(
CDSSigningCertificateError_AssertionError, @"Creating trust did not succeed.");
return nil; return nil;
} }
if (!trust) { if (!trust) {
OWSFailDebug(@"Could not create trust."); OWSFailDebug(@"Could not create trust.");
*error = CDSSigningCertificateErrorMake(CDSSigningCertificateError_AssertionError, @"Could not create trust.");
return nil; return nil;
} }
status = SecTrustSetNetworkFetchAllowed(trust, NO); status = SecTrustSetNetworkFetchAllowed(trust, NO);
if (status != errSecSuccess) { if (status != errSecSuccess) {
OWSFailDebug(@"trust fetch could not be configured."); OWSFailDebug(@"trust fetch could not be configured.");
*error = CDSSigningCertificateErrorMake(
CDSSigningCertificateError_AssertionError, @"trust fetch could not be configured.");
return nil; return nil;
} }
status = SecTrustSetAnchorCertificatesOnly(trust, YES); status = SecTrustSetAnchorCertificatesOnly(trust, YES);
if (status != errSecSuccess) { if (status != errSecSuccess) {
OWSFailDebug(@"trust anchor certs could not be configured."); OWSFailDebug(@"trust anchor certs could not be configured.");
*error = CDSSigningCertificateErrorMake(
CDSSigningCertificateError_AssertionError, @"trust anchor certs could not be configured.");
return nil; return nil;
} }
@ -124,7 +149,9 @@ NS_ASSUME_NONNULL_BEGIN
for (NSData *certificateData in anchorCertificates) { for (NSData *certificateData in anchorCertificates) {
SecCertificateRef certificate = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)(certificateData)); SecCertificateRef certificate = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)(certificateData));
if (!certificate) { if (!certificate) {
OWSFailDebug(@"Could not load DER."); OWSFailDebug(@"Could not create pinned SecCertificate.");
*error = CDSSigningCertificateErrorMake(
CDSSigningCertificateError_AssertionError, @"Could not create pinned SecCertificate.");
return nil; return nil;
} }
@ -133,6 +160,8 @@ NS_ASSUME_NONNULL_BEGIN
status = SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)pinnedCertificates); status = SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)pinnedCertificates);
if (status != errSecSuccess) { if (status != errSecSuccess) {
OWSFailDebug(@"The anchor certificates couldn't be set."); OWSFailDebug(@"The anchor certificates couldn't be set.");
*error = CDSSigningCertificateErrorMake(
CDSSigningCertificateError_AssertionError, @"The anchor certificates couldn't be set.");
return nil; return nil;
} }
@ -140,6 +169,8 @@ NS_ASSUME_NONNULL_BEGIN
status = SecTrustEvaluate(trust, &result); status = SecTrustEvaluate(trust, &result);
if (status != errSecSuccess) { if (status != errSecSuccess) {
OWSFailDebug(@"Could not evaluate certificates."); OWSFailDebug(@"Could not evaluate certificates.");
*error = CDSSigningCertificateErrorMake(
CDSSigningCertificateError_AssertionError, @"Could not evaluate certificates.");
return nil; return nil;
} }
@ -147,7 +178,9 @@ NS_ASSUME_NONNULL_BEGIN
// See the comments in the header where it is defined. // See the comments in the header where it is defined.
BOOL isValid = (result == kSecTrustResultUnspecified || result == kSecTrustResultProceed); BOOL isValid = (result == kSecTrustResultUnspecified || result == kSecTrustResultProceed);
if (!isValid) { if (!isValid) {
OWSFailDebug(@"Certificate evaluation failed."); OWSFailDebug(@"Certificate was not trusted.");
*error = CDSSigningCertificateErrorMake(
CDSSigningCertificateError_UntrustedCertificate, @"Certificate was not trusted.");
return nil; return nil;
} }
@ -155,6 +188,8 @@ NS_ASSUME_NONNULL_BEGIN
signingCertificate.publicKey = publicKey; signingCertificate.publicKey = publicKey;
if (!publicKey) { if (!publicKey) {
OWSFailDebug(@"Could not extract public key."); OWSFailDebug(@"Could not extract public key.");
*error = CDSSigningCertificateErrorMake(
CDSSigningCertificateError_AssertionError, @"Could not extract public key.");
return nil; return nil;
} }

View file

@ -509,7 +509,14 @@ NSErrorDomain const ContactDiscoveryServiceErrorDomain = @"SignalServiceKit.Cont
OWSAssertDebug(signature.length > 0); OWSAssertDebug(signature.length > 0);
OWSAssertDebug(quoteData); OWSAssertDebug(quoteData);
CDSSigningCertificate *_Nullable certificate = [CDSSigningCertificate parseCertificateFromPem:certificates]; NSError *error;
CDSSigningCertificate *_Nullable certificate =
[CDSSigningCertificate parseCertificateFromPem:certificates error:&error];
if (error) {
OWSFailDebug(@"error when parsing signing certificate. %@", error.localizedDescription);
return NO;
}
if (!certificate) { if (!certificate) {
OWSFailDebug(@"could not parse signing certificate."); OWSFailDebug(@"could not parse signing certificate.");
return NO; return NO;

View file

@ -10,16 +10,12 @@
/// Returns true when all of the items in this array match the given predicate. /// Returns true when all of the items in this array match the given predicate.
- (bool)all:(int (^)(id item))predicate; - (bool)all:(int (^)(id item))predicate;
/// Returns the first item in this array that matches the given predicate, or else returns nil if none match it.
- (id)firstMatchingElseNil:(int (^)(id item))predicate;
/// Returns an array of all the results of passing items from this array through the given projection function. /// Returns an array of all the results of passing items from this array through the given projection function.
- (NSArray *)map:(id (^)(id item))projection; - (NSArray *)map:(id (^)(id item))projection;
/// Returns an array of all the results of passing items from this array through the given projection function. /// Returns an array of all the results of passing items from this array through the given projection function.
- (NSArray *)filter:(int (^)(id item))predicate; - (NSArray *)filter:(int (^)(id item))predicate;
- (NSDictionary *)keyedBy:(id (^)(id))keySelector;
- (NSDictionary *)groupBy:(id (^)(id value))keySelector; - (NSDictionary *)groupBy:(id (^)(id value))keySelector;
@end @end

View file

@ -46,15 +46,6 @@
} }
return true; return true;
} }
- (id)firstMatchingElseNil:(int (^)(id item))predicate {
tskit_require(predicate != nil);
for (id e in self) {
if (predicate(e)) {
return e;
}
}
return nil;
}
- (NSArray *)map:(id (^)(id item))projection { - (NSArray *)map:(id (^)(id item))projection {
tskit_require(projection != nil); tskit_require(projection != nil);
@ -76,18 +67,6 @@
return r; return r;
} }
- (NSDictionary *)keyedBy:(id (^)(id value))keySelector {
tskit_require(keySelector != nil);
NSMutableDictionary *result = [NSMutableDictionary dictionary];
for (id value in self) {
result[keySelector(value)] = value;
}
tskit_require(result.count == self.count);
return result;
}
- (NSDictionary *)groupBy:(id (^)(id value))keySelector { - (NSDictionary *)groupBy:(id (^)(id value))keySelector {
tskit_require(keySelector != nil); tskit_require(keySelector != nil);

View file

@ -9,7 +9,7 @@
@interface TSPreKeyManager (Testing) @interface TSPreKeyManager (Testing)
+ (void)clearSignedPreKeyRecordsWithKeyId:(NSNumber *)keyId success:(void (^_Nullable)(void))successHandler; + (void)clearSignedPreKeyRecordsWithKeyId:(NSNumber *)keyId;
@end @end
@ -41,7 +41,10 @@
int secondsAgo = (i - days) * 24 * 60 * 60; int secondsAgo = (i - days) * 24 * 60 * 60;
NSAssert(secondsAgo <= 0, @"Time in past must be negative"); NSAssert(secondsAgo <= 0, @"Time in past must be negative");
NSDate *generatedAt = [NSDate dateWithTimeIntervalSinceNow:secondsAgo]; NSDate *generatedAt = [NSDate dateWithTimeIntervalSinceNow:secondsAgo];
SignedPreKeyRecord *record = [[SignedPreKeyRecord alloc] initWithId:i keyPair:[Curve25519 generateKeyPair] signature:nil generatedAt:generatedAt]; SignedPreKeyRecord *record = [[SignedPreKeyRecord alloc] initWithId:i
keyPair:[Curve25519 generateKeyPair]
signature:[NSData new]
generatedAt:generatedAt];
[[OWSPrimaryStorage sharedManager] storeSignedPreKey:i signedPreKeyRecord:record]; [[OWSPrimaryStorage sharedManager] storeSignedPreKey:i signedPreKeyRecord:record];
} }
@ -49,21 +52,12 @@
// Sanity check // Sanity check
XCTAssert(signedPreKeys.count == 21); XCTAssert(signedPreKeys.count == 21);
XCTestExpectation *expection = [self expectationWithDescription:@"successfully cleared old keys"]; [TSPreKeyManager clearSignedPreKeyRecordsWithKeyId:@(lastPreKeyId)];
[TSPreKeyManager XCTAssert([[OWSPrimaryStorage sharedManager] loadSignedPrekey:lastPreKeyId] != nil);
clearSignedPreKeyRecordsWithKeyId:[NSNumber numberWithInt:lastPreKeyId]
success:^{
XCTAssert(
[[OWSPrimaryStorage sharedManager] loadSignedPrekey:lastPreKeyId] != nil);
// We'll delete every key created 7 or more days ago. // We'll delete every key created 7 or more days ago.
NSArray<SignedPreKeyRecord *> *signedPreKeys = signedPreKeys = [[OWSPrimaryStorage sharedManager] loadSignedPreKeys];
[[OWSPrimaryStorage sharedManager] loadSignedPreKeys]; XCTAssert(signedPreKeys.count == 7);
XCTAssert(signedPreKeys.count == 7);
[expection fulfill];
}];
[self waitForExpectationsWithTimeout:5.0 handler:nil];
} }
- (void)testSignedPreKeyDeletionKeepsSomeOldKeys - (void)testSignedPreKeyDeletionKeepsSomeOldKeys
@ -80,7 +74,7 @@
NSDate *generatedAt = [NSDate dateWithTimeIntervalSinceNow:secondsAgo]; NSDate *generatedAt = [NSDate dateWithTimeIntervalSinceNow:secondsAgo];
SignedPreKeyRecord *record = [[SignedPreKeyRecord alloc] initWithId:i SignedPreKeyRecord *record = [[SignedPreKeyRecord alloc] initWithId:i
keyPair:[Curve25519 generateKeyPair] keyPair:[Curve25519 generateKeyPair]
signature:nil signature:[NSData new]
generatedAt:generatedAt]; generatedAt:generatedAt];
// we only retain accepted keys // we only retain accepted keys
[record markAsAcceptedByService]; [record markAsAcceptedByService];
@ -92,22 +86,14 @@
// Sanity check // Sanity check
XCTAssert(signedPreKeys.count == 11); XCTAssert(signedPreKeys.count == 11);
XCTestExpectation *expection = [self expectationWithDescription:@"successfully cleared old keys"]; [TSPreKeyManager clearSignedPreKeyRecordsWithKeyId:@(lastPreKeyId)];
[TSPreKeyManager
clearSignedPreKeyRecordsWithKeyId:[NSNumber numberWithInt:lastPreKeyId]
success:^{
XCTAssert(
[[OWSPrimaryStorage sharedManager] loadSignedPrekey:lastPreKeyId] != nil);
NSArray<SignedPreKeyRecord *> *signedPreKeys = XCTAssert([[OWSPrimaryStorage sharedManager] loadSignedPrekey:lastPreKeyId] != nil);
[[OWSPrimaryStorage sharedManager] loadSignedPreKeys];
// We need to keep 3 "old" keys, plus the "current" key signedPreKeys = [[OWSPrimaryStorage sharedManager] loadSignedPreKeys];
XCTAssert(signedPreKeys.count == 4);
[expection fulfill];
}];
[self waitForExpectationsWithTimeout:5.0 handler:nil]; // We need to keep 3 "old" keys, plus the "current" key
XCTAssert(signedPreKeys.count == 4);
} }
- (void)testOlderRecordsNotDeletedIfNoReplacement { - (void)testOlderRecordsNotDeletedIfNoReplacement {
@ -123,7 +109,10 @@
int secondsAgo = (i - days) * 24 * 60 * 60; int secondsAgo = (i - days) * 24 * 60 * 60;
NSAssert(secondsAgo <= 0, @"Time in past must be negative"); NSAssert(secondsAgo <= 0, @"Time in past must be negative");
NSDate *generatedAt = [NSDate dateWithTimeIntervalSinceNow:secondsAgo]; NSDate *generatedAt = [NSDate dateWithTimeIntervalSinceNow:secondsAgo];
SignedPreKeyRecord *record = [[SignedPreKeyRecord alloc] initWithId:i keyPair:[Curve25519 generateKeyPair] signature:nil generatedAt:generatedAt]; SignedPreKeyRecord *record = [[SignedPreKeyRecord alloc] initWithId:i
keyPair:[Curve25519 generateKeyPair]
signature:[NSData new]
generatedAt:generatedAt];
[[OWSPrimaryStorage sharedManager] storeSignedPreKey:i signedPreKeyRecord:record]; [[OWSPrimaryStorage sharedManager] storeSignedPreKey:i signedPreKeyRecord:record];
} }
@ -131,20 +120,12 @@
// Sanity check // Sanity check
XCTAssert(signedPreKeys.count == 4); XCTAssert(signedPreKeys.count == 4);
XCTestExpectation *expection = [self expectationWithDescription:@"successfully cleared old keys"]; [TSPreKeyManager clearSignedPreKeyRecordsWithKeyId:@(lastPreKeyId)];
[TSPreKeyManager XCTAssert([[OWSPrimaryStorage sharedManager] loadSignedPrekey:lastPreKeyId] != nil);
clearSignedPreKeyRecordsWithKeyId:[NSNumber numberWithInt:lastPreKeyId]
success:^{
XCTAssert(
[[OWSPrimaryStorage sharedManager] loadSignedPrekey:lastPreKeyId] != nil);
// All three records should still be stored.
NSArray<SignedPreKeyRecord *> *signedPreKeys =
[[OWSPrimaryStorage sharedManager] loadSignedPreKeys];
XCTAssert(signedPreKeys.count == 4);
[expection fulfill];
}];
[self waitForExpectationsWithTimeout:5.0 handler:nil]; // All three records should still be stored.
signedPreKeys = [[OWSPrimaryStorage sharedManager] loadSignedPreKeys];
XCTAssert(signedPreKeys.count == 4);
} }
#endif #endif

View file

@ -4,6 +4,10 @@
import XCTest import XCTest
/////
// Swift Test vs. Cocoapods issue #1
/////
//
// Cocoapods-generated test targets (like this one) // Cocoapods-generated test targets (like this one)
// fail to link if: // fail to link if:
// //
@ -14,3 +18,23 @@ import XCTest
// to our test target. // to our test target.
// //
// See: https://github.com/CocoaPods/CocoaPods/issues/7170 // See: https://github.com/CocoaPods/CocoaPods/issues/7170
/////
// Swift Test vs. Cocoapods issue #2
/////
//
// XCode's test runner doesn't copy swift framework's required by dependencies into
// the running test bundle.
// It sounds similar to this issue: https://github.com/CocoaPods/CocoaPods/issues/7985
//
// The error output looks like this:
// The bundle SignalServiceKit-Unit-Tests couldnt be loaded because it is damaged or missing necessary resources. Try reinstalling the bundle.
// [...]/SignalServiceKit-Unit-Tests.xctest/SignalServiceKit-Unit-Tests): Library not loaded: @rpath/libswiftAVFoundation.dylib
// Referenced from: /Users/[...]/Build/Products/Debug-iphonesimulator/SignalServiceKit/SignalServiceKit.framework/SignalServiceKit
// Reason: image not found)
// Program ended with exit code: 82
//
// A work around is to redundantly import any swift frameworks used by the dependencies of the test suite into this test file.
// The error message provides a hint, i.e. "Library not loaded: @rpath/libswiftAVFoundation.dylib" is fixed with `import AVFoundation`
import AVFoundation
import CloudKit