NSRegularExpression: Improved Error and Exception handling to match macOS behaviour (#343)

* NSRegularExpression: Match macOS error handling

* Add test cases for error handling

* NSRegularExpression: Raise an NSInvalidArgumentException instead of NSInternalInconsistencyException

* Check if NSRegularExpression throws an exception
This commit is contained in:
Hugo Melder 2023-11-13 19:55:49 +01:00 committed by GitHub
parent ec051d1d30
commit ac38295f64
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 66 additions and 1 deletions

View file

@ -52,6 +52,8 @@
#import "Foundation/NSCoder.h"
#import "Foundation/NSUserDefaults.h"
#import "Foundation/NSNotification.h"
#import "Foundation/FoundationErrors.h"
#import "Foundation/NSError.h"
/**
@ -114,6 +116,15 @@ NSRegularExpressionOptionsToURegexpFlags(NSRegularExpressionOptions opts)
options: (NSRegularExpressionOptions)opts
error: (NSError**)e
{
// Raise an NSInvalidArgumentException to match macOS behaviour.
if (!aPattern) {
NSException *exp;
exp = [NSException exceptionWithName: NSInvalidArgumentException
reason: @"nil argument"];
[exp raise];
}
uint32_t flags = NSRegularExpressionOptionsToURegexpFlags(opts);
UText p = UTEXT_INITIALIZER;
UParseError pe = {0};
@ -131,7 +142,27 @@ NSRegularExpressionOptionsToURegexpFlags(NSRegularExpressionOptions opts)
utext_close(&p);
if (U_FAILURE(s))
{
// FIXME: Do something sensible with the error parameter.
// Match macOS behaviour if the pattern is invalid.
// Example:
// Domain=NSCocoaErrorDomain
// Code=2048 "The value “<PATTERN>” is invalid."
// UserInfo={NSInvalidValue=<PATTERN>}
if (e) {
NSDictionary *userInfo;
NSString *description;
description = [NSString stringWithFormat:
@"The value “%@” is invalid.",
aPattern];
userInfo = [NSDictionary dictionaryWithObjectsAndKeys:
aPattern, @"NSInvalidValue", description, NSLocalizedDescriptionKey, nil];
*e = [NSError errorWithDomain: NSCocoaErrorDomain
code: NSFormattingError
userInfo: userInfo];
}
[self release];
return nil;
}

View file

@ -9,6 +9,8 @@
#import <Foundation/NSRunLoop.h>
#import <Foundation/NSThread.h>
#import <Foundation/NSValue.h>
#import <Foundation/NSError.h>
#import <Foundation/FoundationErrors.h>
@interface DegeneratePatternTest : NSObject
{
@ -169,6 +171,38 @@ int main()
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")