mirror of
https://github.com/gnustep/libs-base.git
synced 2025-05-31 16:50:58 +00:00
More leak management fixes
This commit is contained in:
parent
90082eccac
commit
cd3e69245d
9 changed files with 119 additions and 79 deletions
|
@ -219,9 +219,9 @@ extern "C" {
|
||||||
* set to YES).<br />
|
* set to YES).<br />
|
||||||
* Your class then has two options for performing clean-up when the process
|
* Your class then has two options for performing clean-up when the process
|
||||||
* ends:
|
* ends:
|
||||||
* <p>1. Use the +leaked: method to register addresses whose contents are to
|
* <p>1. Use the +leak: at: method to register addresses whose contents are
|
||||||
* be either ignored or released depending on the clean-up setting in force
|
* to be either ignored or released depending on the clean-up setting in
|
||||||
* when the program exits.
|
* force when the program exits.
|
||||||
* This mechanism is simple and should be sufficient for many classes.
|
* This mechanism is simple and should be sufficient for many classes.
|
||||||
* </p>
|
* </p>
|
||||||
* <p>2. Implement a +atExit method to be run when the process ends and,
|
* <p>2. Implement a +atExit method to be run when the process ends and,
|
||||||
|
@ -241,36 +241,30 @@ extern "C" {
|
||||||
*/
|
*/
|
||||||
+ (BOOL) isExiting;
|
+ (BOOL) isExiting;
|
||||||
|
|
||||||
/** This method informs the system that anObject should be retained to
|
/** This method stored anObject at anAddress (retaining it) and notes
|
||||||
* persist until the process exits. If clean-up is enabled the object
|
* that the object should persist until the process exits. If clean-up
|
||||||
* should be released upon process exit.
|
* is enabled the object should be released (and the address content
|
||||||
* If this method is called while the process is already existing it
|
* zeroed out) upon process exit.
|
||||||
* returns nil, otherwise it returnes the retained argument.
|
* If this method is called while the process is already exiting it
|
||||||
* Raises an exception if anObject has already been leaked or if it is
|
* simply zeros out the memory location then returns nil, otherwise
|
||||||
* nil (unless the process is exiting).
|
* it returns the object stored at the memory location.
|
||||||
|
* Raises an exception if anObject is nil or anAddress is NULL (unless
|
||||||
|
* the process is already exiting).
|
||||||
|
*/
|
||||||
|
+ (id) leak: (id)anObject at: (id*)anAddress;
|
||||||
|
|
||||||
|
/** DEPRECATED ... use +leak: at: instead.
|
||||||
*/
|
*/
|
||||||
+ (id) NS_RETURNS_RETAINED leak: (id)anObject;
|
+ (id) NS_RETURNS_RETAINED leak: (id)anObject;
|
||||||
|
|
||||||
/** This method informs the system that the object at anAddress has been
|
/** DEPRECATED ... use +leak: at: instead.
|
||||||
* retained to persist until the process exits. If clean-up is enabled
|
|
||||||
* the object should be released (and the address content zeroed out)
|
|
||||||
* upon process exit.
|
|
||||||
* If this method is called while the process is already existing it releases
|
|
||||||
* the object and zeros out the memory location then returns nil, otherwise
|
|
||||||
* it returns the object found at the memory location.
|
|
||||||
* Raises an exception if anAddress (or the object at anAddress) has already
|
|
||||||
* been leaked or if it is nil (unless the process is exiting).
|
|
||||||
*/
|
|
||||||
+ (void) leaked: (id*)anAddress;
|
|
||||||
|
|
||||||
/** DEPRECATED ... use +leaked: instead.
|
|
||||||
*/
|
*/
|
||||||
+ (id) NS_RETURNS_RETAINED leakAt: (id*)anAddress;
|
+ (id) NS_RETURNS_RETAINED leakAt: (id*)anAddress;
|
||||||
|
|
||||||
/** Sets the receiver to have its +atExit method called at the point when
|
/** Sets the receiver to have its +atExit method called at the point when
|
||||||
* the process terminates.<br />
|
* the process terminates.<br />
|
||||||
* Returns YES on success and NO on failure (if the class does not implement
|
* Returns YES on success and NO on failure (if the class does not implement
|
||||||
* the method or if it is already registered to call it).<br />
|
* +atExit or if it is already registered to call it).<br />
|
||||||
* Implemented as a call to +registerAtExit: with the selector for the +atExit
|
* Implemented as a call to +registerAtExit: with the selector for the +atExit
|
||||||
* method as its argument.
|
* method as its argument.
|
||||||
*/
|
*/
|
||||||
|
@ -279,7 +273,7 @@ extern "C" {
|
||||||
/** Sets the receiver to have the specified method called at the point when
|
/** Sets the receiver to have the specified method called at the point when
|
||||||
* the process terminates.<br />
|
* the process terminates.<br />
|
||||||
* Returns YES on success and NO on failure (if the class does not implement
|
* Returns YES on success and NO on failure (if the class does not implement
|
||||||
* the method ir if it is already registered to call it).
|
* the method or if it is already registered to call a method at exit).
|
||||||
*/
|
*/
|
||||||
+ (BOOL) registerAtExit: (SEL)aSelector;
|
+ (BOOL) registerAtExit: (SEL)aSelector;
|
||||||
|
|
||||||
|
|
|
@ -180,6 +180,10 @@ handleExit()
|
||||||
BOOL unknownThread;
|
BOOL unknownThread;
|
||||||
|
|
||||||
isExiting = YES;
|
isExiting = YES;
|
||||||
|
/* We turn off zombies during exiting so that we don't leak deallocated
|
||||||
|
* objects during cleanup.
|
||||||
|
*/
|
||||||
|
// NSZombieEnabled = NO;
|
||||||
unknownThread = GSRegisterCurrentThread();
|
unknownThread = GSRegisterCurrentThread();
|
||||||
ENTER_POOL
|
ENTER_POOL
|
||||||
|
|
||||||
|
@ -193,6 +197,7 @@ handleExit()
|
||||||
Method method;
|
Method method;
|
||||||
IMP msg;
|
IMP msg;
|
||||||
|
|
||||||
|
fprintf(stderr, "*** +[%s %s]\n", class_getName(tmp->obj), sel_getName(tmp->sel));
|
||||||
method = class_getClassMethod(tmp->obj, tmp->sel);
|
method = class_getClassMethod(tmp->obj, tmp->sel);
|
||||||
msg = method_getImplementation(method);
|
msg = method_getImplementation(method);
|
||||||
if (0 != msg)
|
if (0 != msg)
|
||||||
|
@ -200,13 +205,18 @@ handleExit()
|
||||||
(*msg)(tmp->obj, tmp->sel);
|
(*msg)(tmp->obj, tmp->sel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (YES == shouldCleanUp)
|
else if (shouldCleanUp)
|
||||||
{
|
{
|
||||||
if (tmp->at)
|
if (tmp->at)
|
||||||
{
|
{
|
||||||
tmp->obj = *(tmp->at);
|
if (tmp->obj != *(tmp->at))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "*** leaked value %p at %p changed to %p\n", tmp->obj, (const void*)tmp->at, *(tmp->at));
|
||||||
|
tmp->obj = *(tmp->at);
|
||||||
|
}
|
||||||
*(tmp->at) = nil;
|
*(tmp->at) = nil;
|
||||||
}
|
}
|
||||||
|
fprintf(stderr, "*** -[%s release] %p %p\n", class_getName(object_getClass(tmp->obj)), tmp->obj, (const void*)tmp->at);
|
||||||
[tmp->obj release];
|
[tmp->obj release];
|
||||||
}
|
}
|
||||||
free(tmp);
|
free(tmp);
|
||||||
|
@ -227,35 +237,22 @@ handleExit()
|
||||||
return isExiting;
|
return isExiting;
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (id) leakAt: (id*)anAddress
|
+ (id) leak: (id)anObject at: (id*)anAddress
|
||||||
{
|
|
||||||
struct exitLink *l;
|
|
||||||
|
|
||||||
l = (struct exitLink*)malloc(sizeof(struct exitLink));
|
|
||||||
l->at = anAddress;
|
|
||||||
l->obj = [*anAddress retain];
|
|
||||||
l->sel = 0;
|
|
||||||
setup();
|
|
||||||
[exitLock lock];
|
|
||||||
l->next = exited;
|
|
||||||
exited = l;
|
|
||||||
[exitLock unlock];
|
|
||||||
return l->obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
+ (void) leaked: (id*)anAddress
|
|
||||||
{
|
{
|
||||||
struct exitLink *l;
|
struct exitLink *l;
|
||||||
|
|
||||||
NSAssert(anAddress != NULL, NSInvalidArgumentException);
|
|
||||||
if (isExiting)
|
if (isExiting)
|
||||||
{
|
{
|
||||||
[*anAddress release];
|
if (anAddress)
|
||||||
*anAddress = nil;
|
{
|
||||||
|
[*anAddress release];
|
||||||
|
*anAddress = nil;
|
||||||
|
}
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
NSAssert([*anAddress isKindOfClass: [NSObject class]],
|
NSAssert([anObject isKindOfClass: [NSObject class]],
|
||||||
NSInvalidArgumentException);
|
NSInvalidArgumentException);
|
||||||
|
NSAssert(anAddress != NULL, NSInvalidArgumentException);
|
||||||
setup();
|
setup();
|
||||||
[exitLock lock];
|
[exitLock lock];
|
||||||
for (l = exited; l != NULL; l = l->next)
|
for (l = exited; l != NULL; l = l->next)
|
||||||
|
@ -266,16 +263,17 @@ handleExit()
|
||||||
[NSException raise: NSInvalidArgumentException
|
[NSException raise: NSInvalidArgumentException
|
||||||
format: @"Repeated use of leak address %p", anAddress];
|
format: @"Repeated use of leak address %p", anAddress];
|
||||||
}
|
}
|
||||||
if (*anAddress != nil && *anAddress == l->obj)
|
if (anObject != nil && anObject == l->obj)
|
||||||
{
|
{
|
||||||
[exitLock unlock];
|
[exitLock unlock];
|
||||||
[NSException raise: NSInvalidArgumentException
|
[NSException raise: NSInvalidArgumentException
|
||||||
format: @"Repeated use of leak object %p", *anAddress];
|
format: @"Repeated use of leak object %p", anObject];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ASSIGN(*anAddress, anObject);
|
||||||
l = (struct exitLink*)malloc(sizeof(struct exitLink));
|
l = (struct exitLink*)malloc(sizeof(struct exitLink));
|
||||||
l->at = anAddress;
|
l->at = anAddress;
|
||||||
l->obj = *anAddress;
|
l->obj = anObject;
|
||||||
l->sel = 0;
|
l->sel = 0;
|
||||||
l->next = exited;
|
l->next = exited;
|
||||||
exited = l;
|
exited = l;
|
||||||
|
@ -283,6 +281,22 @@ handleExit()
|
||||||
return l->obj;
|
return l->obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
+ (id) leakAt: (id*)anAddress
|
||||||
|
{
|
||||||
|
struct exitLink *l;
|
||||||
|
|
||||||
|
l = (struct exitLink*)malloc(sizeof(struct exitLink));
|
||||||
|
l->at = anAddress;
|
||||||
|
l->obj = [*anAddress retain];
|
||||||
|
l->sel = 0;
|
||||||
|
setup();
|
||||||
|
[exitLock lock];
|
||||||
|
l->next = exited;
|
||||||
|
exited = l;
|
||||||
|
[exitLock unlock];
|
||||||
|
return l->obj;
|
||||||
|
}
|
||||||
|
|
||||||
+ (id) leak: (id)anObject
|
+ (id) leak: (id)anObject
|
||||||
{
|
{
|
||||||
struct exitLink *l;
|
struct exitLink *l;
|
||||||
|
@ -344,10 +358,16 @@ handleExit()
|
||||||
[exitLock lock];
|
[exitLock lock];
|
||||||
for (l = exited; l != 0; l = l->next)
|
for (l = exited; l != 0; l = l->next)
|
||||||
{
|
{
|
||||||
if (l->obj == self && sel_isEqual(l->sel, sel))
|
if (l->obj == self)
|
||||||
{
|
{
|
||||||
[exitLock unlock];
|
if (sel_isEqual(l->sel, sel))
|
||||||
return NO; // Already registered
|
{
|
||||||
|
fprintf(stderr,
|
||||||
|
"*** +[%s registerAtExit: %s] already registered for %s.\n",
|
||||||
|
class_getName(self), sel_getName(sel), sel_getName(l->sel));
|
||||||
|
[exitLock unlock];
|
||||||
|
return NO; // Already registered
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
l = (struct exitLink*)malloc(sizeof(struct exitLink));
|
l = (struct exitLink*)malloc(sizeof(struct exitLink));
|
||||||
|
@ -502,6 +522,12 @@ handleExit()
|
||||||
*/
|
*/
|
||||||
@implementation NSObject(GSCleanup)
|
@implementation NSObject(GSCleanup)
|
||||||
|
|
||||||
|
+ (id) leak: (id)anObject at: (id*)anAddress
|
||||||
|
{
|
||||||
|
ASSIGN(*anAddress, anObject);
|
||||||
|
return *anAddress;
|
||||||
|
}
|
||||||
|
|
||||||
+ (id) leakAt: (id*)anAddress
|
+ (id) leakAt: (id*)anAddress
|
||||||
{
|
{
|
||||||
[*anAddress retain];
|
[*anAddress retain];
|
||||||
|
|
|
@ -223,8 +223,7 @@ GSDomainFromDefaultLocale(void)
|
||||||
*/
|
*/
|
||||||
if (saved == nil)
|
if (saved == nil)
|
||||||
{
|
{
|
||||||
saved = [dict copy];
|
[NSObject leak: AUTORELEASE([dict copy]) at: &saved];
|
||||||
[NSObject leaked: &saved];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -48,7 +48,6 @@ static NSNull *null = 0;
|
||||||
if (null == 0)
|
if (null == 0)
|
||||||
{
|
{
|
||||||
null = (NSNull*)NSAllocateObject(self, 0, NSDefaultMallocZone());
|
null = (NSNull*)NSAllocateObject(self, 0, NSDefaultMallocZone());
|
||||||
[[NSObject leakAt: &null] release];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -171,13 +171,13 @@ extern void GSLogZombie(id o, SEL sel)
|
||||||
}
|
}
|
||||||
if (c == 0)
|
if (c == 0)
|
||||||
{
|
{
|
||||||
NSLog(@"*** -[??? %@]: message sent to deallocated instance %p",
|
fprintf(stderr, "*** -[??? %s]: message sent to deallocated instance %p",
|
||||||
NSStringFromSelector(sel), o);
|
sel_getName(sel), o);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
NSLog(@"*** -[%@ %@]: message sent to deallocated instance %p",
|
fprintf(stderr, "*** -[%s %s]: message sent to deallocated instance %p",
|
||||||
c, NSStringFromSelector(sel), o);
|
class_getName(c), sel_getName(sel), o);
|
||||||
}
|
}
|
||||||
if (GSPrivateEnvironmentFlag("CRASH_ON_ZOMBIE", NO) == YES)
|
if (GSPrivateEnvironmentFlag("CRASH_ON_ZOMBIE", NO) == YES)
|
||||||
{
|
{
|
||||||
|
@ -814,7 +814,7 @@ NSDeallocateObject(id anObject)
|
||||||
(*finalize_imp)(anObject, finalize_sel);
|
(*finalize_imp)(anObject, finalize_sel);
|
||||||
|
|
||||||
AREM(aClass, (id)anObject);
|
AREM(aClass, (id)anObject);
|
||||||
if (NSZombieEnabled == YES)
|
if (NSZombieEnabled)
|
||||||
{
|
{
|
||||||
#ifdef OBJC_CAP_ARC
|
#ifdef OBJC_CAP_ARC
|
||||||
if (0 != zombieMap)
|
if (0 != zombieMap)
|
||||||
|
@ -1086,12 +1086,14 @@ static id gs_weak_load(id obj)
|
||||||
|
|
||||||
+ (void) _atExit
|
+ (void) _atExit
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
NSMapTable *m = nil;
|
NSMapTable *m = nil;
|
||||||
GS_MUTEX_LOCK(allocationLock);
|
GS_MUTEX_LOCK(allocationLock);
|
||||||
m = zombieMap;
|
m = zombieMap;
|
||||||
zombieMap = nil;
|
zombieMap = nil;
|
||||||
GS_MUTEX_UNLOCK(allocationLock);
|
GS_MUTEX_UNLOCK(allocationLock);
|
||||||
DESTROY(m);
|
DESTROY(m);
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -180,6 +180,13 @@ debugWrite(id handle, int len, const unsigned char *ptr)
|
||||||
static NSMutableArray *pairCache = nil;
|
static NSMutableArray *pairCache = nil;
|
||||||
static NSLock *pairLock = nil;
|
static NSLock *pairLock = nil;
|
||||||
|
|
||||||
|
+ (void) atExit
|
||||||
|
{
|
||||||
|
[[NSNotificationCenter defaultCenter] removeObserver: self];
|
||||||
|
DESTROY(pairLock);
|
||||||
|
DESTROY(pairCache);
|
||||||
|
}
|
||||||
|
|
||||||
+ (void) initialize
|
+ (void) initialize
|
||||||
{
|
{
|
||||||
if (pairCache == nil)
|
if (pairCache == nil)
|
||||||
|
@ -196,6 +203,7 @@ static NSLock *pairLock = nil;
|
||||||
[[NSNotificationCenter defaultCenter] addObserver: self
|
[[NSNotificationCenter defaultCenter] addObserver: self
|
||||||
selector: @selector(purge:)
|
selector: @selector(purge:)
|
||||||
name: @"GSHousekeeping" object: nil];
|
name: @"GSHousekeeping" object: nil];
|
||||||
|
[self registerAtExit];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -468,19 +476,36 @@ typedef struct {
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
+ (void) atExit
|
||||||
|
{
|
||||||
|
if (placeholder)
|
||||||
|
{
|
||||||
|
id o = placeholder;
|
||||||
|
|
||||||
|
placeholder = nil;
|
||||||
|
NSDeallocateObject(o);
|
||||||
|
}
|
||||||
|
fprintf(stderr, "Registered retain count %d\n", (int)[registered retainCount]);
|
||||||
|
DESTROY(registered);
|
||||||
|
DESTROY(regLock);
|
||||||
|
}
|
||||||
|
|
||||||
+ (void) initialize
|
+ (void) initialize
|
||||||
{
|
{
|
||||||
if (registered == nil)
|
static BOOL beenHere = NO;
|
||||||
|
|
||||||
|
if (NO == beenHere)
|
||||||
{
|
{
|
||||||
|
beenHere = YES;
|
||||||
abstractClass = [NSURLProtocol class];
|
abstractClass = [NSURLProtocol class];
|
||||||
placeholderClass = [NSURLProtocolPlaceholder class];
|
placeholderClass = [NSURLProtocolPlaceholder class];
|
||||||
|
|
||||||
|
[self registerAtExit];
|
||||||
|
|
||||||
placeholder = (NSURLProtocol*)NSAllocateObject(placeholderClass, 0,
|
placeholder = (NSURLProtocol*)NSAllocateObject(placeholderClass, 0,
|
||||||
NSDefaultMallocZone());
|
NSDefaultMallocZone());
|
||||||
[[NSObject leakAt: &placeholder] release];
|
|
||||||
registered = [NSMutableArray new];
|
registered = [NSMutableArray new];
|
||||||
[[NSObject leakAt: ®istered] release];
|
|
||||||
regLock = [NSLock new];
|
regLock = [NSLock new];
|
||||||
[[NSObject leakAt: ®Lock] release];
|
|
||||||
[self registerClass: [_NSHTTPURLProtocol class]];
|
[self registerClass: [_NSHTTPURLProtocol class]];
|
||||||
[self registerClass: [_NSHTTPSURLProtocol class]];
|
[self registerClass: [_NSHTTPSURLProtocol class]];
|
||||||
[self registerClass: [_NSFTPURLProtocol class]];
|
[self registerClass: [_NSFTPURLProtocol class]];
|
||||||
|
|
|
@ -18,7 +18,7 @@ int main()
|
||||||
httpURL = [NSURL URLWithString: @"http://www.gnustep.org"];
|
httpURL = [NSURL URLWithString: @"http://www.gnustep.org"];
|
||||||
foobarURL = [NSURL URLWithString: @"foobar://localhost/madeupscheme"];
|
foobarURL = [NSURL URLWithString: @"foobar://localhost/madeupscheme"];
|
||||||
|
|
||||||
TEST_FOR_CLASS(@"NSURLHandle", [NSURLHandle alloc],
|
TEST_FOR_CLASS(@"NSURLHandle", AUTORELEASE([NSURLHandle alloc]),
|
||||||
"NSURLHandle +alloc returns an NSURLHandle");
|
"NSURLHandle +alloc returns an NSURLHandle");
|
||||||
|
|
||||||
PASS_EXCEPTION([DummyHandle cachedHandleForURL: httpURL];,
|
PASS_EXCEPTION([DummyHandle cachedHandleForURL: httpURL];,
|
||||||
|
@ -29,14 +29,11 @@ int main()
|
||||||
|
|
||||||
PASS([cls canInitWithURL: httpURL] == YES,
|
PASS([cls canInitWithURL: httpURL] == YES,
|
||||||
"Appropriate subclass found for +URLHandleClassForURL:");
|
"Appropriate subclass found for +URLHandleClassForURL:");
|
||||||
handle1 = [[cls alloc] initWithURL: httpURL cached: YES];
|
handle1 = AUTORELEASE([[cls alloc] initWithURL: httpURL cached: YES]);
|
||||||
handle2 = [NSURLHandle cachedHandleForURL: httpURL];
|
handle2 = [NSURLHandle cachedHandleForURL: httpURL];
|
||||||
|
|
||||||
PASS(handle2 != nil, "Available handle returned from cache");
|
PASS(handle2 != nil, "Available handle returned from cache");
|
||||||
|
|
||||||
[handle1 autorelease];
|
|
||||||
[cls autorelease];
|
|
||||||
|
|
||||||
#if !defined(GNUSTEP_BASE_LIBRARY)
|
#if !defined(GNUSTEP_BASE_LIBRARY)
|
||||||
PASS(NO, "URLHandleClassForURL: seems to hang on MacOS-X when given an unknown URL scheme ... you may want to check to see if it has been fixed");
|
PASS(NO, "URLHandleClassForURL: seems to hang on MacOS-X when given an unknown URL scheme ... you may want to check to see if it has been fixed");
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -11,10 +11,10 @@ int main()
|
||||||
|
|
||||||
httpURL = [NSURL URLWithString: @"http://www.gnustep.org"];
|
httpURL = [NSURL URLWithString: @"http://www.gnustep.org"];
|
||||||
|
|
||||||
TEST_FOR_CLASS(@"NSURLProtocol", [NSURLProtocol alloc],
|
TEST_FOR_CLASS(@"NSURLProtocol", AUTORELEASE([NSURLProtocol alloc]),
|
||||||
"NSURLProtocol +alloc returns an NSURLProtocol");
|
"NSURLProtocol +alloc returns an NSURLProtocol");
|
||||||
|
|
||||||
mutable = [[NSMutableURLRequest requestWithURL: httpURL] retain];
|
mutable = [NSMutableURLRequest requestWithURL: httpURL];
|
||||||
PASS_EXCEPTION([NSURLProtocol canInitWithRequest: mutable], nil,
|
PASS_EXCEPTION([NSURLProtocol canInitWithRequest: mutable], nil,
|
||||||
"NSURLProtocol +canInitWithRequest throws an exeception (subclasses should be used)");
|
"NSURLProtocol +canInitWithRequest throws an exeception (subclasses should be used)");
|
||||||
|
|
||||||
|
@ -22,13 +22,12 @@ int main()
|
||||||
TEST_FOR_CLASS(@"NSURLRequest", canon,
|
TEST_FOR_CLASS(@"NSURLRequest", canon,
|
||||||
"NSURLProtocol +canonicalRequestForRequest: returns an NSURLProtocol");
|
"NSURLProtocol +canonicalRequestForRequest: returns an NSURLProtocol");
|
||||||
|
|
||||||
copy = [mutable copy];
|
copy = AUTORELEASE([mutable copy]);
|
||||||
PASS([NSURLProtocol requestIsCacheEquivalent: mutable toRequest: copy],
|
PASS([NSURLProtocol requestIsCacheEquivalent: mutable toRequest: copy],
|
||||||
"NSURLProtocol +requestIsCacheEquivalent:toRequest returns YES with a request and its copy");
|
"NSURLProtocol +requestIsCacheEquivalent:toRequest returns YES with a request and its copy");
|
||||||
[copy setHTTPMethod: @"POST"];
|
[copy setHTTPMethod: @"POST"];
|
||||||
PASS([NSURLProtocol requestIsCacheEquivalent: mutable toRequest: copy] == NO,
|
PASS([NSURLProtocol requestIsCacheEquivalent: mutable toRequest: copy] == NO,
|
||||||
"NSURLProtocol +requestIsCacheEquivalent:toRequest returns NO after a method change");
|
"NSURLProtocol +requestIsCacheEquivalent:toRequest returns NO after a method change");
|
||||||
[copy release];
|
|
||||||
|
|
||||||
[arp release]; arp = nil;
|
[arp release]; arp = nil;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -13,7 +13,7 @@ int main()
|
||||||
httpURL = [NSURL URLWithString: @"http://www.gnustep.org"];
|
httpURL = [NSURL URLWithString: @"http://www.gnustep.org"];
|
||||||
foobarURL = [NSURL URLWithString: @"foobar://localhost/madeupscheme"];
|
foobarURL = [NSURL URLWithString: @"foobar://localhost/madeupscheme"];
|
||||||
|
|
||||||
TEST_FOR_CLASS(@"NSURLRequest", [NSURLRequest alloc],
|
TEST_FOR_CLASS(@"NSURLRequest", AUTORELEASE([NSURLRequest alloc]),
|
||||||
"NSURLRequest +alloc returns an NSURLRequest");
|
"NSURLRequest +alloc returns an NSURLRequest");
|
||||||
|
|
||||||
request = [NSURLRequest requestWithURL: httpURL];
|
request = [NSURLRequest requestWithURL: httpURL];
|
||||||
|
@ -28,7 +28,7 @@ int main()
|
||||||
PASS(request != nil,
|
PASS(request != nil,
|
||||||
"NSURLRequest +requestWithURL returns a request from an invalid URL (unknown scheme)");
|
"NSURLRequest +requestWithURL returns a request from an invalid URL (unknown scheme)");
|
||||||
|
|
||||||
mutable = [request mutableCopy];
|
mutable = AUTORELEASE([request mutableCopy]);
|
||||||
PASS(mutable != nil && [mutable isKindOfClass:[NSMutableURLRequest class]],
|
PASS(mutable != nil && [mutable isKindOfClass:[NSMutableURLRequest class]],
|
||||||
"NSURLRequest -mutableCopy returns a mutable request");
|
"NSURLRequest -mutableCopy returns a mutable request");
|
||||||
[mutable setHTTPMethod: @"POST"];
|
[mutable setHTTPMethod: @"POST"];
|
||||||
|
@ -53,9 +53,8 @@ int main()
|
||||||
[mutable setValue: nil forHTTPHeaderField: @"gnustep"];
|
[mutable setValue: nil forHTTPHeaderField: @"gnustep"];
|
||||||
expected = [NSDictionary dictionaryWithObjectsAndKeys:@"object", @"key", nil];
|
expected = [NSDictionary dictionaryWithObjectsAndKeys:@"object", @"key", nil];
|
||||||
PASS_EQUAL([mutable allHTTPHeaderFields], expected, "Remove header field");
|
PASS_EQUAL([mutable allHTTPHeaderFields], expected, "Remove header field");
|
||||||
[mutable release];
|
|
||||||
|
|
||||||
mutable = [NSMutableURLRequest new];
|
mutable = AUTORELEASE([NSMutableURLRequest new]);
|
||||||
PASS(mutable != nil && [mutable isKindOfClass:[NSMutableURLRequest class]],
|
PASS(mutable != nil && [mutable isKindOfClass:[NSMutableURLRequest class]],
|
||||||
"NSURLRequest +new returns a mutable request");
|
"NSURLRequest +new returns a mutable request");
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue