File: basic.m

package info (click to toggle)
gnustep-base 1.31.1-4
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 26,580 kB
  • sloc: objc: 239,446; ansic: 36,519; cpp: 122; sh: 112; makefile: 100; xml: 32
file content (206 lines) | stat: -rw-r--r-- 8,167 bytes parent folder | download | duplicates (2)
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;
}