/*
* Copyright (c) 2011 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@
*/
//
// compaction.m
// Copyright (c) 2010-2011 Apple Inc. All rights reserved.
//
#import "BlackBoxTest.h"
@interface MovableObject : NSObject
@property(readonly) uintptr_t originalSelf;
@property(readonly) BOOL moved;
@end
@implementation MovableObject
- (id)init {
self = [super init];
if (self) {
originalSelf = (uintptr_t)self;
}
return self;
}
- (BOOL)moved {
return (uintptr_t)self != originalSelf;
}
@end
@interface SelfPinnedObject : MovableObject {
id extra[0];
}
@end
@implementation SelfPinnedObject
+ (id)new {
return [NSAllocateObject(self, sizeof(id), NULL) init];
}
- (id)init {
self = [super init];
extra[0] = self;
return self;
}
@end
@interface PinnedTest : BlackBoxTest {
SelfPinnedObject *pinned;
}
@end
@implementation PinnedTest
- (id)init {
self = [super init];
pinned = [SelfPinnedObject new];
return self;
}
- (NSString *)shouldSkip {
if (getenv("AUTO_ANALYZE_NOTIFICATION") == NULL)
return @"Need to turn on AUTO_ANALYZE_NOTIFICATION to check pinning.";
return nil;
}
- (void)performTest {
// first, analyze pinning, if object is pinned, then it won't bloody well move.
[self requestCompactionAnalysisWithCompletionCallback:^{
[self flushStderr];
uintptr_t address = (uintptr_t)pinned;
const char *path = getenv("AUTO_ANALYZE_NOTIFICATION");
printf("looking for pinnedObject FILE *f = fopen(path, "r");
char *line; size_t length;
while ((line = fgetln(f, &length)) != NULL) {
line[length - 1] = '\0';
char *tokens = line, *token;
while ((token = strsep(&tokens, " ")) != NULL) {
if (strcmp(token, "->") == 0) {
token = strsep(&tokens, " ");
if (strtoul(token, NULL, 0) == address) {
// scan for the reason.
NSString *reason = @"object was pinned.";
while ((token = strsep(&tokens, " ")) != NULL) {
if (token[0] == '<') {
reason = [NSString stringWithFormat:@"object was pinned, reason = break;
}
}
[self setTestResult:PASSED message:reason];
[self testFinished];
fclose(f);
return;
}
break;
}
}
}
fclose(f);
[self fail:@"object not pinned as expected."];
[self testFinished];
}];
}
- (void)processOutputLine:(NSString *)line {}
@end
@interface CompactionTest : BlackBoxTest {
MovableObject *movable;
NSUInteger hashValue;
}
@end
@implementation CompactionTest
- (id)init {
self = [super init];
movable = [MovableObject new];
hashValue = [movable hash];
return self;
}
- (NSString *)shouldSkip {
if (getenv("AUTO_COMPACTION_SCRAMBLE") == NULL)
return @"setenv AUTO_COMPACTION_SCRAMBLE=YES to force compaction.";
return nil;
}
- (void)performTest {
// now wait for a compaction to finish, and verify that the object moved.
[self requestCompactionWithCompletionCallback:^{
[self flushStderr];
if (movable.moved && (movable.hash == hashValue))
[self setTestResult:PASSED message:@"object was compacted, hash value stayed constant."];
else
[self fail:@"object not compacted."];
[self testFinished];
}];
}
- (void)processOutputLine:(NSString *)line {}
@end