1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206
|
#import "ObjectTesting.h"
#import <Foundation/NSAutoreleasePool.h>
#import <Foundation/NSRegularExpression.h>
#import <Foundation/NSTextCheckingResult.h>
#import <Foundation/NSDate.h>
#import <Foundation/NSDictionary.h>
#import <Foundation/NSUserDefaults.h>
#import <Foundation/NSRunLoop.h>
#import <Foundation/NSThread.h>
#import <Foundation/NSValue.h>
#import <Foundation/NSError.h>
#import <Foundation/FoundationErrors.h>
@interface DegeneratePatternTest : NSObject
{
NSRegularExpression *expression;
NSString* input;
}
@end
@implementation DegeneratePatternTest
- (instancetype) init
{
if (nil == (self = [super init]))
{
return nil;
}
expression =
[[NSRegularExpression alloc] initWithPattern: @"^(([a-z])+.)+[A-Z]([a-z])+$"
options: 0
error: NULL];
ASSIGN(input, @"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!");
return self;
}
- (void) runTest: (id)obj
{
NSAutoreleasePool *pool = [NSAutoreleasePool new];
[expression matchesInString: input
options: 0
range: NSMakeRange(0, [input length])];
DESTROY(pool);
}
- (void) dealloc
{
DESTROY(expression);
DESTROY(input);
[super dealloc];
}
@end
int main()
{
NSAutoreleasePool *arp = [NSAutoreleasePool new];
START_SET("NSRegularExpression")
#if !(__APPLE__ || GS_USE_ICU)
SKIP("NSRegularExpression not built\nThe ICU library was not available when GNUstep-base was built")
#else
# ifdef GNUSTEP
// Ensure that a deterministic limit is set up for this process
NSUserDefaults *dflts = [NSUserDefaults standardUserDefaults];
NSDictionary *domain = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt: 1500], @"GSRegularExpressionWorkLimit", nil];
[dflts setVolatileDomain: domain
forName: @"GSTestDomain"];
# endif
id testObj = AUTORELEASE([[NSRegularExpression alloc]
initWithPattern: @"^a" options: 0 error: NULL]);
test_NSObject(@"NSRegularExpression",
[NSArray arrayWithObject: AUTORELEASE([[NSRegularExpression
alloc] initWithPattern: @"^a" options: 0 error: NULL])]);
test_NSCopying(@"NSRegularExpression",@"NSRegularExpression",
[NSArray arrayWithObject:testObj],NO,NO);
NSAutoreleasePool *iPool = [NSAutoreleasePool new];
{
PASS_EQUAL([testObj pattern], @"^a", "Correct pattern returned");
}
DESTROY(iPool);
/* Regression test: We had a double-free bug on retrieving pattern,
* which is also the reason for wrapping the previous one in an ARP */
PASS_RUNS([testObj pattern], "Calling -pattern twice runs");
// The pattern does not include a capture group $1, so this should return
// nil;
NSString *replacement = @"should be unset on return";
replacement = [testObj stringByReplacingMatchesInString: @"ab"
options: 0
range: NSMakeRange(0,2)
withTemplate: @"$1c"];
PASS(replacement == nil, "Replacement: returns nil on capture group error");
replacement = [testObj stringByReplacingMatchesInString: @"ab"
options: 0
range: NSMakeRange(0, 2)
withTemplate: @"c"];
PASS_EQUAL(replacement, @"cb", "Replacement correct");
NSMutableString *replMut = [NSMutableString stringWithString: @"ab"];
[testObj replaceMatchesInString: replMut
options: 0
range: NSMakeRange(0,2)
withTemplate: @"$1c"];
PASS_EQUAL(replMut, @"ab",
"Mutable replacement: Incorrect template does not change string");
replMut = [NSMutableString stringWithString: @"ab"];
[testObj replaceMatchesInString: replMut
options: 0
range: NSMakeRange(0,2)
withTemplate: @"c"];
PASS_EQUAL(replMut, @"cb",
"Mutable replacement: Correct replacement for template");
NSTextCheckingResult *r = [testObj firstMatchInString: @"ab"
options: 0
range: NSMakeRange(0,2)];
PASS(r != nil, "Found NSTextCheckingResult");
replacement = @"should be unset on return";
replacement = [testObj replacementStringForResult: r
inString: @"ab"
offset: 0
template: @"$1c"];
PASS(replacement == nil,
"Custom replacement: returns nil on capture group error");
replacement = nil;
replacement = [testObj replacementStringForResult: r
inString: @"ab"
offset: 0
template: @"c"];
PASS_EQUAL(replacement, @"c",
"Custom replacement: Returns correct replacement");
NSRegularExpression *testObj2 = AUTORELEASE([[NSRegularExpression alloc]
initWithPattern: @"bc" options: 0 error: NULL]);
r = [testObj2 firstMatchInString: @"abcdeabcde"
options: 0
range: NSMakeRange(5, 5)];
PASS(r != nil && NSEqualRanges([r range], NSMakeRange(6, 2)),
"Restricting the range for firstMatchInString: works");
/* To test whether we correctly bail out of processing degenerate patterns,
* we spin up a new thread and evaluate an expression there. The expectation
* is that the thread should terminate within a few seconds.
*
* NOTE: Since we cannot terminate the thread in case of a failure, this
* test should be run last.
*/
DegeneratePatternTest *test = [DegeneratePatternTest new];
NSThread *thread = [[NSThread alloc] initWithTarget: test
selector: @selector(runTest:)
object: nil];
[thread start];
[thread setName: @"PatternTestRunner"];
NSDate *started = [NSDate date];
NSRunLoop *rl = [NSRunLoop currentRunLoop];
/* We spin the runloop for a bit while we wait for the other thread to bail
* out */
while ([thread isExecuting] && abs([started timeIntervalSinceNow] < 10.0f))
{
[rl runMode: NSDefaultRunLoopMode
beforeDate: [NSDate dateWithTimeIntervalSinceNow: 0.01]];
}
PASS(NO == [thread isExecuting], "Faulty regular expression terminated");
/* Testing the error handling when an invalid pattern is passed
* The error should look like this:
*
* Error Domain=NSCocoaErrorDomain Code=2048 "The value “(abc” is
* invalid." UserInfo={NSInvalidValue=(abc}
*/
NSError *error = nil;
NSRegularExpression *testObj3 =
[[NSRegularExpression alloc] initWithPattern: @"(abc"
options: 0
error: &error];
PASS(testObj3 == nil, "Invalid pattern: returns nil");
PASS(error != nil, "Invalid pattern: error is set");
PASS_EQUAL([error domain], NSCocoaErrorDomain,
"Invalid pattern: error domain is NSCocoaErrorDomain");
PASS_EQUAL([error code], NSFormattingError,
"Invalid pattern: error code is NSFormattingError");
PASS_EQUAL([[error userInfo] objectForKey: @"NSInvalidValue"],
@"(abc", "Invalid pattern: error message is correct");
PASS_EQUAL([[error userInfo] objectForKey: NSLocalizedDescriptionKey],
@"The value “(abc” is invalid.",
"Invalid pattern: localized description is correct");
/* Testing exception handling when nil is passed as pattern */
PASS_EXCEPTION([NSRegularExpression regularExpressionWithPattern: nil
options: 0
error: NULL],
NSInvalidArgumentException,
"nil pattern: throws NSInvalidArgumentException");
#endif
END_SET("NSRegularExpression")
[arp release]; arp = nil;
return 0;
}
|