aboutsummaryrefslogtreecommitdiff
path: root/Foundation/GTMLoggerRingBufferWriterTest.m
diff options
context:
space:
mode:
authorGravatar thomasvl@gmail.com <thomasvl@gmail.com@7dc7ac4e-7543-0410-b95c-c1676fc8e2a3>2008-07-21 14:49:00 +0000
committerGravatar thomasvl@gmail.com <thomasvl@gmail.com@7dc7ac4e-7543-0410-b95c-c1676fc8e2a3>2008-07-21 14:49:00 +0000
commit4963c8a9d57501b5ffb0fe52fbfe60cd71b3b916 (patch)
treedd70e4aba13b245427788ccdb075e04f1af0951c /Foundation/GTMLoggerRingBufferWriterTest.m
parentef630a18e87e03f15a2ae2b7b90623d4a0183f89 (diff)
helps if I add the files before doing the commit
Diffstat (limited to 'Foundation/GTMLoggerRingBufferWriterTest.m')
-rw-r--r--Foundation/GTMLoggerRingBufferWriterTest.m364
1 files changed, 364 insertions, 0 deletions
diff --git a/Foundation/GTMLoggerRingBufferWriterTest.m b/Foundation/GTMLoggerRingBufferWriterTest.m
new file mode 100644
index 0000000..41b78e2
--- /dev/null
+++ b/Foundation/GTMLoggerRingBufferWriterTest.m
@@ -0,0 +1,364 @@
+//
+// GTMLoggerRingBufferWriterTest.m
+//
+// Copyright 2007-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 "GTMLoggerRingBufferWriter.h"
+#import "GTMLogger.h"
+
+
+// --------------------------------------------------
+// CountingWriter keeps a count of the number of times it has been
+// told to write something, and also keeps track of what it was
+// asked to log.
+
+@interface CountingWriter : NSObject<GTMLogWriter> {
+ @private
+ NSMutableArray *loggedContents_;
+}
+
+- (int)count;
+- (NSArray *)loggedContents;
+- (void)reset;
+
+@end // CountingWriter
+
+@implementation CountingWriter
+
+- (void)logMessage:(NSString *)msg level:(GTMLoggerLevel)level {
+ if (loggedContents_ == nil) loggedContents_ = [[NSMutableArray alloc] init];
+ [loggedContents_ addObject:msg];
+} // logMessage
+
+- (void)dealloc {
+ [loggedContents_ release];
+ [super dealloc];
+} // dealloc
+
+- (void)reset {
+ [loggedContents_ release];
+ loggedContents_ = nil;
+} // reset
+
+- (int)count {
+ return (int)[loggedContents_ count];
+} // count
+
+- (NSArray *)loggedContents {
+ return loggedContents_;
+} // loggedContents
+
+@end // CountingWriter
+
+
+@interface GTMLoggerRingBufferWriterTest : GTMTestCase {
+ @private
+ GTMLogger *logger_;
+ __weak CountingWriter *countingWriter_;
+}
+@end // GTMLoggerRingBufferWriterTest
+
+
+// --------------------------------------------------
+
+@implementation GTMLoggerRingBufferWriterTest
+
+// Utilty to compare the set of messages captured by a CountingWriter
+// with an array of expected messages. The messages are expected to
+// be in the same order in both places.
+
+- (void)compareWriter:(CountingWriter *)writer
+ withExpectedLogging:(NSArray *)expected
+ line:(int)line {
+ NSArray *loggedContents = [writer loggedContents];
+
+ STAssertEquals([expected count], [loggedContents count],
+ @"count mismatch from line %d", line);
+
+ for (unsigned int i = 0; i < [expected count]; i++) {
+ STAssertEqualObjects([expected objectAtIndex:i],
+ [loggedContents objectAtIndex:i],
+ @"logging mistmatch at index %d from line %d",
+ i, line);
+ }
+
+} // compareWithExpectedLogging
+
+
+- (void)setUp {
+ countingWriter_ = [[[CountingWriter alloc] init] autorelease];
+ logger_ = [[GTMLogger alloc] init];
+} // setUp
+
+
+- (void)tearDown {
+ [logger_ release];
+} // tearDown
+
+
+- (void)testCreation {
+
+ // Make sure initializers work.
+ GTMLoggerRingBufferWriter *writer =
+ [GTMLoggerRingBufferWriter ringBufferWriterWithCapacity:32
+ writer:countingWriter_];
+ STAssertEquals([writer capacity], 32, nil);
+ STAssertEquals([writer writer], countingWriter_, nil);
+ STAssertEquals([writer count], 0, nil);
+ STAssertEquals([writer droppedLogCount], 0, nil);
+ STAssertEquals([writer totalLogged], 0, nil);
+
+ // Try with invalid arguments. Should always get nil back.
+ writer =
+ [GTMLoggerRingBufferWriter ringBufferWriterWithCapacity:0
+ writer:countingWriter_];
+ STAssertNil(writer, nil);
+ writer =
+ [GTMLoggerRingBufferWriter ringBufferWriterWithCapacity:-1
+ writer:countingWriter_];
+ STAssertNil(writer, nil);
+ writer = [GTMLoggerRingBufferWriter ringBufferWriterWithCapacity:32
+ writer:nil];
+ STAssertNil(writer, nil);
+
+ writer = [[GTMLoggerRingBufferWriter alloc] init];
+ STAssertNil(writer, nil);
+
+} // testCreation
+
+
+- (void)testLogging {
+ GTMLoggerRingBufferWriter *writer =
+ [GTMLoggerRingBufferWriter ringBufferWriterWithCapacity:4
+ writer:countingWriter_];
+ [logger_ setWriter:writer];
+
+ // Shouldn't do anything if there are no contents.
+ [writer dumpContents];
+ STAssertEquals([writer count], 0, nil);
+ STAssertEquals([countingWriter_ count], 0, nil);
+
+ // Log a single item. Make sure the counts are accurate.
+ [logger_ logDebug:@"oop"];
+ STAssertEquals([writer count], 1, nil);
+ STAssertEquals([writer totalLogged], 1, nil);
+ STAssertEquals([writer droppedLogCount], 0, nil);
+ STAssertEquals([countingWriter_ count], 0, nil);
+
+ // Log a second item. Also make sure counts are accurate.
+ [logger_ logDebug:@"ack"];
+ STAssertEquals([writer count], 2, nil);
+ STAssertEquals([writer totalLogged], 2, nil);
+ STAssertEquals([writer droppedLogCount], 0, nil);
+ STAssertEquals([countingWriter_ count], 0, nil);
+
+ // Print them, and make sure the countingWriter sees the right stuff.
+ [writer dumpContents];
+ STAssertEquals([countingWriter_ count], 2, nil);
+ STAssertEquals([writer count], 2, nil); // Should not be zeroed.
+ STAssertEquals([writer totalLogged], 2, nil);
+
+ [self compareWriter:countingWriter_
+ withExpectedLogging:[NSArray arrayWithObjects:@"oop",@"ack", nil]
+ line:__LINE__];
+
+
+ // Wipe the slates clean.
+ [writer reset];
+ [countingWriter_ reset];
+ STAssertEquals([writer count], 0, nil);
+ STAssertEquals([writer totalLogged], 0, nil);
+
+ // An error log level should print the buffer and empty it.
+ [logger_ logDebug:@"oop"];
+ [logger_ logInfo:@"ack"];
+ STAssertEquals([writer droppedLogCount], 0, nil);
+ STAssertEquals([writer totalLogged], 2, nil);
+
+ [logger_ logError:@"blargh"];
+ STAssertEquals([countingWriter_ count], 3, nil);
+ STAssertEquals([writer droppedLogCount], 0, nil);
+
+ [self compareWriter:countingWriter_
+ withExpectedLogging:[NSArray arrayWithObjects:@"oop", @"ack",
+ @"blargh", nil]
+ line:__LINE__];
+
+
+ // An assert log level should do the same. This also fills the
+ // buffer to its limit without wrapping.
+ [countingWriter_ reset];
+ [logger_ logDebug:@"oop"];
+ [logger_ logInfo:@"ack"];
+ [logger_ logDebug:@"blargh"];
+ STAssertEquals([writer droppedLogCount], 0, nil);
+ STAssertEquals([writer count], 3, nil);
+ STAssertEquals([writer totalLogged], 3, nil);
+
+ [logger_ logAssert:@"ouch"];
+ STAssertEquals([countingWriter_ count], 4, nil);
+ STAssertEquals([writer droppedLogCount], 0, nil);
+ [self compareWriter:countingWriter_
+ withExpectedLogging:[NSArray arrayWithObjects:@"oop", @"ack",
+ @"blargh", @"ouch", nil]
+ line:__LINE__];
+
+
+ // Try with exactly one wrap around.
+ [countingWriter_ reset];
+ [logger_ logInfo:@"ack"];
+ [logger_ logDebug:@"oop"];
+ [logger_ logDebug:@"blargh"];
+ [logger_ logDebug:@"flong"]; // Fills buffer
+ STAssertEquals([writer droppedLogCount], 0, nil);
+ STAssertEquals([writer count], 4, nil);
+
+ [logger_ logAssert:@"ouch"]; // should drop "ack"
+ STAssertEquals([countingWriter_ count], 4, nil);
+
+ [self compareWriter:countingWriter_
+ withExpectedLogging:[NSArray arrayWithObjects:@"oop", @"blargh",
+ @"flong", @"ouch", nil]
+ line:__LINE__];
+
+
+ // Try with more than one wrap around.
+ [countingWriter_ reset];
+ [logger_ logInfo:@"ack"];
+ [logger_ logDebug:@"oop"];
+ [logger_ logDebug:@"blargh"];
+ [logger_ logDebug:@"flong"]; // Fills buffer
+ [logger_ logDebug:@"bloogie"]; // should drop "ack"
+ STAssertEquals([writer droppedLogCount], 1, nil);
+ STAssertEquals([writer count], 4, nil);
+
+ [logger_ logAssert:@"ouch"]; // should drop "oop"
+ STAssertEquals([countingWriter_ count], 4, nil);
+
+ [self compareWriter:countingWriter_
+ withExpectedLogging:[NSArray arrayWithObjects:@"blargh",
+ @"flong", @"bloogie", @"ouch", nil]
+ line:__LINE__];
+} // testBasics
+
+
+- (void)testCornerCases {
+ // make sure we work with small buffer sizes.
+
+ GTMLoggerRingBufferWriter *writer =
+ [GTMLoggerRingBufferWriter ringBufferWriterWithCapacity:1
+ writer:countingWriter_];
+ [logger_ setWriter:writer];
+
+ [logger_ logInfo:@"ack"];
+ STAssertEquals([countingWriter_ count], 0, nil);
+ STAssertEquals([writer count], 1, nil);
+ [writer dumpContents];
+ STAssertEquals([countingWriter_ count], 1, nil);
+
+ [self compareWriter:countingWriter_
+ withExpectedLogging:[NSArray arrayWithObjects:@"ack", nil]
+ line:__LINE__];
+
+ [logger_ logDebug:@"oop"]; // should drop "ack"
+ STAssertEquals([writer count], 1, nil);
+ STAssertEquals([writer droppedLogCount], 1, nil);
+
+ [countingWriter_ reset];
+ [logger_ logError:@"snoogy"]; // should drop "oop"
+ STAssertEquals([countingWriter_ count], 1, nil);
+
+ [self compareWriter:countingWriter_
+ withExpectedLogging:[NSArray arrayWithObjects:@"snoogy", nil]
+ line:__LINE__];
+
+} // testCornerCases
+
+
+
+// Run 10 threads, all logging through the same logger.
+
+static volatile int gStoppedThreads = 0; // Total number that have stopped.
+
+- (void)bangMe:(id)info {
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+ GTMLogger *logger = (GTMLogger *)info;
+
+ // Log a string.
+ for (int i = 0; i < 27; i++) {
+ [logger logDebug:@"oop"];
+ }
+
+ // log another string which should push the first string out.
+ // if we see any "oop"s in the logger output, then we know it got
+ // confused.
+ for (int i = 0; i < 15; i++) {
+ [logger logDebug:@"ack"];
+ }
+
+ [pool release];
+ @synchronized ([self class]) {
+ gStoppedThreads++;
+ }
+
+} // bangMe
+
+
+- (void)testThreading {
+ const int kThreadCount = 10;
+ const int kCapacity = 10;
+
+ GTMLoggerRingBufferWriter *writer =
+ [GTMLoggerRingBufferWriter ringBufferWriterWithCapacity:kCapacity
+ writer:countingWriter_];
+ [logger_ setWriter:writer];
+
+ for (int i = 0; i < kThreadCount; i++) {
+ [NSThread detachNewThreadSelector:@selector(bangMe:)
+ toTarget:self
+ withObject:logger_];
+ }
+
+ // The threads are running, so wait for them all to finish.
+ while (1) {
+ NSDate *quick = [NSDate dateWithTimeIntervalSinceNow:0.2];
+ [[NSRunLoop currentRunLoop] runUntilDate:quick];
+ @synchronized ([self class]) {
+ if (gStoppedThreads == kThreadCount) break;
+ }
+ }
+
+ // Now make sure we get back what's expected.
+ STAssertEquals([writer count], kThreadCount, nil);
+ STAssertEquals([countingWriter_ count], 0, nil); // Nothing should be logged
+ STAssertEquals([writer totalLogged], 420, nil);
+
+ [logger_ logError:@"bork"];
+ STAssertEquals([countingWriter_ count], kCapacity, nil);
+
+ NSArray *expected = [NSArray arrayWithObjects:
+ @"ack", @"ack", @"ack", @"ack", @"ack",
+ @"ack", @"ack", @"ack", @"ack", @"bork",
+ nil];
+ [self compareWriter:countingWriter_
+ withExpectedLogging:expected
+ line:__LINE__];
+
+} // testThreading
+
+@end // GTMLoggerRingBufferWriterTest