AssociativeRefRecovery.m   [plain text]


/*
 * Copyright (c) 2009 Apple Inc. All rights reserved.
 *
 * @APPLE_APACHE_LICENSE_HEADER_START@
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * 
 * @APPLE_APACHE_LICENSE_HEADER_END@
 */
//
//  AssociativeRefRecovery.m
//  auto
//
//  Created by Josh Behnke on 8/28/08.
//  Copyright 2008 Apple Inc. All rights reserved.
//

#import "AssociativeRefRecovery.h"
#import <auto_zone.h>
#import <malloc/malloc.h>

@implementation AssociativeRefRecovery
- (void)startTest
{
    id obj = [NSObject new];
    _foundation_ref = [self disguise:[NSObject new]];
    auto_zone_set_associative_ref([self auto_zone], obj, self, [self undisguise:_foundation_ref]);
    
    CFArrayRef cf = CFArrayCreate(NULL, NULL, 0, NULL);
    CFMakeCollectable(cf);
    _cf_bridged_ref = [self disguise:[NSObject new]];
    auto_zone_set_associative_ref([self auto_zone], (void *)cf, self, [self undisguise:_cf_bridged_ref]);

    void *block = malloc_zone_malloc([self auto_zone], 1);
    _non_object = [self disguise:[NSObject new]];
    auto_zone_set_associative_ref([self auto_zone], (void *)block, self, [self undisguise:_non_object]);
    auto_zone_release([self auto_zone], block);
    
    // Run a full collection
    [self requestFullCollection];
    _sync = [self setNextTestSelector:@selector(verifyResults)];
}

- (void)verifyResults
{
    if (!_foundation_ref_collected)
        [self fail:"failed to collect block associated with foundation object"];
    if (!_cf_bridged_ref_collected)
        [self fail:"failed to collect block associated with bridged CF object"];
    if (!_non_object_ref_collected)
        [self fail:"failed to collect block associated with non-object block"];
}

- (void)heapCollectionComplete
{
    [_sync signal];
    [super heapCollectionComplete];
}

- (void)endHeapScanWithGarbage:(void **)garbage_list count:(size_t)count
{
    if ([self block:[self undisguise:_foundation_ref] isInList:garbage_list count:count]) {
        _foundation_ref_collected = YES;
    }
    if ([self block:[self undisguise:_cf_bridged_ref] isInList:garbage_list count:count]) {
        _cf_bridged_ref_collected = YES;
    }
    if ([self block:[self undisguise:_non_object] isInList:garbage_list count:count]) {
        _non_object_ref_collected = YES;
    }
    [super endHeapScanWithGarbage:garbage_list count:count];
}


@end