diff options
Diffstat (limited to 'Foundation/GTMFileSystemKQueueTest.m')
-rw-r--r-- | Foundation/GTMFileSystemKQueueTest.m | 394 |
1 files changed, 394 insertions, 0 deletions
diff --git a/Foundation/GTMFileSystemKQueueTest.m b/Foundation/GTMFileSystemKQueueTest.m new file mode 100644 index 0000000..c2ded10 --- /dev/null +++ b/Foundation/GTMFileSystemKQueueTest.m @@ -0,0 +1,394 @@ +// +// GTMFileSystemKQueueTest.m +// +// Copyright 2008 Google Inc. +// +// 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. +// + +#import "GTMSenTestCase.h" +#import "GTMFileSystemKQueue.h" +#import "GTMUnitTestDevLog.h" + +@interface GTMFileSystemKQueueTest : GTMTestCase { + @private + NSString *testPath_; + NSString *testPath2_; +} +@end + + +// Helper class to serve as callback target of the kqueue test +@interface GTMFSKQTestHelper : NSObject { + @private + int writes_, renames_, deletes_; +} +@end + +@implementation GTMFSKQTestHelper + +- (void)callbackForQueue:(GTMFileSystemKQueue *)queue + events:(GTMFileSystemKQueueEvents)event { + if (event & kGTMFileSystemKQueueWriteEvent) { + ++writes_; + } + if (event & kGTMFileSystemKQueueDeleteEvent) { + ++deletes_; + } + if (event & kGTMFileSystemKQueueRenameEvent) { + ++renames_; + } +} +- (int)totals { + return writes_ + renames_ + deletes_; +} +- (int)writes { + return writes_; +} +- (int)renames { + return renames_; +} +- (int)deletes { + return deletes_; +} +@end + + +@implementation GTMFileSystemKQueueTest + +- (void)setUp { + NSString *temp = NSTemporaryDirectory(); + testPath_ + = [[temp stringByAppendingPathComponent: + @"GTMFileSystemKQueueTest.testfile"] retain]; + testPath2_ = [[testPath_ stringByAppendingPathExtension:@"2"] retain]; + + // make sure the files aren't in the way of the test + NSFileManager *fm = [NSFileManager defaultManager]; + [fm removeFileAtPath:testPath_ handler:nil]; + [fm removeFileAtPath:testPath2_ handler:nil]; +} + +- (void)tearDown { + // make sure we clean up the files from a failed test + NSFileManager *fm = [NSFileManager defaultManager]; + [fm removeFileAtPath:testPath_ handler:nil]; + [fm removeFileAtPath:testPath2_ handler:nil]; + + [testPath_ release]; + testPath_ = nil; + [testPath2_ release]; + testPath2_ = nil; +} + +- (void)testInit { + GTMFileSystemKQueue *testKQ; + GTMFSKQTestHelper *helper = [[[GTMFSKQTestHelper alloc] init] autorelease]; + STAssertNotNil(helper, nil); + + // init should fail + [GTMUnitTestDevLog expectString:@"Don't call init, use " + @"initWithPath:forEvents:acrossReplace:target:action:"]; + testKQ = [[[GTMFileSystemKQueue alloc] init] autorelease]; + STAssertNil(testKQ, nil); + + // no path + testKQ + = [[[GTMFileSystemKQueue alloc] initWithPath:nil + forEvents:kGTMFileSystemKQueueAllEvents + acrossReplace:YES + target:helper + action:@selector(callbackForQueue:events:)] autorelease]; + STAssertNil(testKQ, nil); + + // not events + testKQ + = [[[GTMFileSystemKQueue alloc] initWithPath:@"/var/log/system.log" + forEvents:0 + acrossReplace:YES + target:helper + action:@selector(callbackForQueue:events:)] autorelease]; + STAssertNil(testKQ, nil); + + // no target + testKQ + = [[[GTMFileSystemKQueue alloc] initWithPath:@"/var/log/system.log" + forEvents:kGTMFileSystemKQueueAllEvents + acrossReplace:YES + target:nil + action:@selector(callbackForQueue:events:)] autorelease]; + STAssertNil(testKQ, nil); + + // no handler + testKQ + = [[[GTMFileSystemKQueue alloc] initWithPath:@"/var/log/system.log" + forEvents:0 + acrossReplace:YES + target:helper + action:nil] autorelease]; + STAssertNil(testKQ, nil); + + + // path that doesn't exist + testKQ + = [[[GTMFileSystemKQueue alloc] initWithPath:@"/path/that/does/not/exist" + forEvents:kGTMFileSystemKQueueAllEvents + acrossReplace:YES + target:helper + action:@selector(callbackForQueue:events:)] autorelease]; + STAssertNil(testKQ, nil); +} + +- (void)spinForEvents:(GTMFSKQTestHelper *)helper { + // Spin the runloop for a second so that the helper callbacks fire + unsigned int attempts = 0; + int initialTotals = [helper totals]; + while (([helper totals] == initialTotals) && (attempts < 10)) { // Try for up to 2s + [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.2]]; + attempts++; + } +} + +- (void)testWriteAndDelete { + + NSFileManager *fm = [NSFileManager defaultManager]; + GTMFSKQTestHelper *helper = [[[GTMFSKQTestHelper alloc] init] autorelease]; + STAssertNotNil(helper, nil); + + STAssertTrue([fm createFileAtPath:testPath_ contents:nil attributes:nil], nil); + NSFileHandle *testFH = [NSFileHandle fileHandleForWritingAtPath:testPath_]; + STAssertNotNil(testFH, nil); + + // Start monitoring the file + GTMFileSystemKQueue *testKQ + = [[GTMFileSystemKQueue alloc] initWithPath:testPath_ + forEvents:kGTMFileSystemKQueueAllEvents + acrossReplace:YES + target:helper + action:@selector(callbackForQueue:events:)]; + STAssertNotNil(testKQ, nil); + STAssertEqualObjects([testKQ path], testPath_, nil); + + // Write to the file + [testFH writeData:[@"doh!" dataUsingEncoding:NSUnicodeStringEncoding]]; + + // Spin the runloop for a second so that the helper callbacks fire + [self spinForEvents:helper]; + STAssertEquals([helper totals], 1, nil); + + // Close and delete + [testFH closeFile]; + STAssertTrue([fm removeFileAtPath:testPath_ handler:nil], nil); + + [self spinForEvents:helper]; + STAssertEquals([helper totals], 2, nil); + + // Clean up the kqueue + [testKQ release]; + testKQ = nil; + + STAssertEquals([helper writes], 1, nil); + STAssertEquals([helper deletes], 1, nil); + STAssertEquals([helper renames], 0, nil); +} + +- (void)testWriteAndDeleteAndWrite { + + // One will pass YES to |acrossReplace|, the other will pass NO. + + NSFileManager *fm = [NSFileManager defaultManager]; + GTMFSKQTestHelper *helper = [[[GTMFSKQTestHelper alloc] init] autorelease]; + STAssertNotNil(helper, nil); + GTMFSKQTestHelper *helper2 = [[[GTMFSKQTestHelper alloc] init] autorelease]; + STAssertNotNil(helper, nil); + + // Create a temp file path + STAssertTrue([fm createFileAtPath:testPath_ contents:nil attributes:nil], nil); + NSFileHandle *testFH = [NSFileHandle fileHandleForWritingAtPath:testPath_]; + STAssertNotNil(testFH, nil); + + // Start monitoring the file + GTMFileSystemKQueue *testKQ + = [[GTMFileSystemKQueue alloc] initWithPath:testPath_ + forEvents:kGTMFileSystemKQueueAllEvents + acrossReplace:YES + target:helper + action:@selector(callbackForQueue:events:)]; + STAssertNotNil(testKQ, nil); + STAssertEqualObjects([testKQ path], testPath_, nil); + GTMFileSystemKQueue *testKQ2 + = [[GTMFileSystemKQueue alloc] initWithPath:testPath_ + forEvents:kGTMFileSystemKQueueAllEvents + acrossReplace:NO + target:helper2 + action:@selector(callbackForQueue:events:)]; + STAssertNotNil(testKQ2, nil); + STAssertEqualObjects([testKQ2 path], testPath_, nil); + + // Write to the file + [testFH writeData:[@"doh!" dataUsingEncoding:NSUnicodeStringEncoding]]; + + // Spin the runloop for a second so that the helper callbacks fire + [self spinForEvents:helper]; + STAssertEquals([helper totals], 1, nil); + STAssertEquals([helper2 totals], 1, nil); + + // Close and delete + [testFH closeFile]; + STAssertTrue([fm removeFileAtPath:testPath_ handler:nil], nil); + + // Recreate + STAssertTrue([fm createFileAtPath:testPath_ contents:nil attributes:nil], nil); + testFH = [NSFileHandle fileHandleForWritingAtPath:testPath_]; + STAssertNotNil(testFH, nil); + [testFH writeData:[@"ha!" dataUsingEncoding:NSUnicodeStringEncoding]]; + + // Spin the runloop for a second so that the helper callbacks fire + [self spinForEvents:helper]; + STAssertEquals([helper totals], 2, nil); + STAssertEquals([helper2 totals], 2, nil); + + // Write to it again + [testFH writeData:[@"continued..." dataUsingEncoding:NSUnicodeStringEncoding]]; + + // Spin the runloop for a second so that the helper callbacks fire + [self spinForEvents:helper]; + STAssertEquals([helper totals], 3, nil); + STAssertEquals([helper2 totals], 2, nil); + + // Close and delete + [testFH closeFile]; + STAssertTrue([fm removeFileAtPath:testPath_ handler:nil], nil); + + // Spin the runloop for a second so that the helper callbacks fire + [self spinForEvents:helper]; + STAssertEquals([helper totals], 4, nil); + STAssertEquals([helper2 totals], 2, nil); + + // Clean up the kqueue + [testKQ release]; + testKQ = nil; + [testKQ2 release]; + testKQ2 = nil; + + STAssertEquals([helper writes], 2, nil); + STAssertEquals([helper deletes], 2, nil); + STAssertEquals([helper renames], 0, nil); + STAssertEquals([helper2 writes], 1, nil); + STAssertEquals([helper2 deletes], 1, nil); + STAssertEquals([helper2 renames], 0, nil); +} + +- (void)testWriteAndRenameAndWrite { + + // One will pass YES to |acrossReplace|, the other will pass NO. + + NSFileManager *fm = [NSFileManager defaultManager]; + GTMFSKQTestHelper *helper = [[[GTMFSKQTestHelper alloc] init] autorelease]; + STAssertNotNil(helper, nil); + GTMFSKQTestHelper *helper2 = [[[GTMFSKQTestHelper alloc] init] autorelease]; + STAssertNotNil(helper2, nil); + + // Create a temp file path + STAssertTrue([fm createFileAtPath:testPath_ contents:nil attributes:nil], nil); + NSFileHandle *testFH = [NSFileHandle fileHandleForWritingAtPath:testPath_]; + STAssertNotNil(testFH, nil); + + // Start monitoring the file + GTMFileSystemKQueue *testKQ + = [[GTMFileSystemKQueue alloc] initWithPath:testPath_ + forEvents:kGTMFileSystemKQueueAllEvents + acrossReplace:YES + target:helper + action:@selector(callbackForQueue:events:)]; + STAssertNotNil(testKQ, nil); + STAssertEqualObjects([testKQ path], testPath_, nil); + GTMFileSystemKQueue *testKQ2 + = [[GTMFileSystemKQueue alloc] initWithPath:testPath_ + forEvents:kGTMFileSystemKQueueAllEvents + acrossReplace:NO + target:helper2 + action:@selector(callbackForQueue:events:)]; + STAssertNotNil(testKQ2, nil); + STAssertEqualObjects([testKQ2 path], testPath_, nil); + + // Write to the file + [testFH writeData:[@"doh!" dataUsingEncoding:NSUnicodeStringEncoding]]; + + // Spin the runloop for a second so that the helper callbacks fire + [self spinForEvents:helper]; + STAssertEquals([helper totals], 1, nil); + STAssertEquals([helper2 totals], 1, nil); + + // Move it and create the file again + STAssertTrue([fm movePath:testPath_ toPath:testPath2_ handler:nil], nil); + STAssertTrue([fm createFileAtPath:testPath_ contents:nil attributes:nil], nil); + NSFileHandle *testFHPrime + = [NSFileHandle fileHandleForWritingAtPath:testPath_]; + STAssertNotNil(testFHPrime, nil); + [testFHPrime writeData:[@"eh?" dataUsingEncoding:NSUnicodeStringEncoding]]; + + // Spin the runloop for a second so that the helper callbacks fire + [self spinForEvents:helper]; + STAssertEquals([helper totals], 2, nil); + STAssertEquals([helper2 totals], 2, nil); + + // Write to the new file + [testFHPrime writeData:[@"continue..." dataUsingEncoding:NSUnicodeStringEncoding]]; + + // Spin the runloop for a second so that the helper callbacks fire + [self spinForEvents:helper]; + STAssertEquals([helper totals], 3, nil); + STAssertEquals([helper2 totals], 2, nil); + + // Write to the old file + [testFH writeData:[@"continue old..." dataUsingEncoding:NSUnicodeStringEncoding]]; + + // Spin the runloop for a second so that the helper callbacks fire + [self spinForEvents:helper]; + STAssertEquals([helper totals], 3, nil); + STAssertEquals([helper2 totals], 3, nil); + + // and now close old + [testFH closeFile]; + STAssertTrue([fm removeFileAtPath:testPath2_ handler:nil], nil); + + // Spin the runloop for a second so that the helper callbacks fire + [self spinForEvents:helper]; + STAssertEquals([helper totals], 3, nil); + STAssertEquals([helper2 totals], 4, nil); + + // and now close new + [testFHPrime closeFile]; + STAssertTrue([fm removeFileAtPath:testPath_ handler:nil], nil); + + // Spin the runloop for a second so that the helper callbacks fire + [self spinForEvents:helper]; + STAssertEquals([helper totals], 4, nil); + STAssertEquals([helper2 totals], 4, nil); + + // Clean up the kqueue + [testKQ release]; + testKQ = nil; + [testKQ2 release]; + testKQ2 = nil; + + STAssertEquals([helper writes], 2, nil); + STAssertEquals([helper deletes], 1, nil); + STAssertEquals([helper renames], 1, nil); + STAssertEquals([helper2 writes], 2, nil); + STAssertEquals([helper2 deletes], 1, nil); + STAssertEquals([helper2 renames], 1, nil); +} + +@end |