Browsing: Mac OS Programming

Feb
14

Cocoa Distributed Objects are Too Easy!

A little background information: The post below I talked about creating iFishes, the Mac memory editor application. The big hurdle during the process of writing this application has been that in order to search another application’s memory, it must be run as root. And I’m not crazy enough to request a user for permission to run the entire iFishes application as root (too many security risks)!! So I cleverly (if I do say so myself) split the program into two, with one utility which runs as a background process which handles all the memory searching (and runs as root). The problem which this introduces is one which, coming from a windows world, is non-trivial: Interprocess Communication.

I immediately turned to Apple’s amazing developer portal for guidance. I was given a nicely formatted list of available options for process communication such as BSD sockets, shared memory, etc. It noted that if you’re using Cocoa, Distributed Objects is the way to go! So, trusting Apple, I said “Okay!”

Now let me say: Distributed objects are the coolest things ever. I said it. I usually try to stay away from absolute statements such as that, but it’s true. (Well to be honest, I would say they are on the same level as Core Animation)

Basically, distributed objects allow one process to “vend” one of it’s objects. Then another process can receive this vended object and use it as if it were in the same memory space! Example:

Process A has an object:

@interface MyObject : NSObject {}
- (void)someMethod;
@end

Let’s assume Process A “vends” this object. And that Process B receives this object. Now somewhere in process B it can just do this:

- (void)someRandomMethod {
    // Assuming distantObject is an instance variable created earlier from the vended
    // object from Process A
    [distantObject someMethod];
}

That’s it!!! Cocoa handles all the underlying messaging between the processes. Amazing. AMAZING.

time Posted at 4:22 PM | written Written by Mitchell Hashimoto | comments 2 Comments made.
Jan
18

AutoUW: A Preview of What’s To Come.

I mentioned back on new years that I had an automated registration tool for the university of washington coming. This is not a lie. I am here today to show you a bunch of preview screenshots of AutoUW and exactly how it works. AutoUW is easy to use and is very reliable. I used this tool this quarter to grab a couple of my classes and it worked wonders. AutoUW will not drop courses for you. This is for your own security. AutoUW will only add courses. :) When will it be available? Before next quarter. :) That is all.

To see all the screenshots and AutoUW in all its glory, then click read more at the end of this post!

Read more…

time Posted at 3:00 PM | written Written by Mitchell Hashimoto | comments 2 Comments made.
Jan
9

Unit Testing WebView Objects in Cocoa

Another subject which revealed no results in Google for me was how I was supposed to possibly test my models which interfaced with the web. My models use a WebView object to talk with various servers (for my UW auto registration program). Like I said in a previous post, I have implemented quite a bit of unit testing to make sure that my code continues to run smoothly. However recently when I was writing some more testing code, I realized the most important thing of all was not being unit tested: the MyUW interfacing.

Let me give a bit of a run through of what the process for using a WebView is, at least with my objects. I set my model to be a WebView’s delegate, make a request, and wait for the WebView to kick back a webView:didFinishLoadingForFrame: method. What this means is that all my web requests are asynchronous, and do not freeze up the main thread or GUI thread, which is why my program is able to run so smoothly. But this blessing is also a curse. Because the requests to my model return immediately (and a delegate call is made later to report the completion of a request), my tests also complete immediately.

For those not familiar with unit testing, let me show you a method from one of my unit tests which checks the MyUW authenticator:

- (void) testLoginDoesWorkWhenShouldWork
{	
	expectedResult = YES;
	[auth authenticateWithId:GOODUSER usingPassword:GOODPASS];
 
	// OH NO! How do I test the result?!
}

As you can see, the test ends… without being able to assert the result I needed to get. My first thought was to use a separate thread to run the authenticator class… which I tried. And this didn’t work. I was stumped! A bit more debugging revealed that the WebView was not even loading the URL!!! WHY?!! (These capitalizations do not even begin to correctly represent the frustration I was experiencing at this point.)

Now, let me tell you a strange fact about myself: When I have a problem, I have a very convenient way of solving it in my sleep. So when I woke up this morning, I was more or less not surprised that the solution was so clear in my head: Because the WebView is event-driven, I need to initialized a Run Loop, or else the events won’t be processed! And because this code is running within a unit test thread, and not within an NSApplication, I didn’t have the luxury of a run loop being made for me (NSApplication creates a run loop for you).

So here is the final code (more or less, I removed some method calls and copied them into this code to make it easier to read) which successfully tests the code:

- (void) testLoginDoesWorkWhenShouldWork
{	
	// 1.) Run the authentication with the expected result being a success
	expectedResult = YES;
	[auth authenticateWithId:GOODUSER usingPassword:GOODPASS];
 
	// 2.) Initialize and loop an NSRunLoop UNTIL WE GET THE RESULT
	// The gotResult flag is modified in the delegate method below...
	gotResult = NO;
	BOOL isRunning;
	do {
		NSDate* next = [NSDate dateWithTimeIntervalSinceNow:1.0];
		isRunning = [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode
											 beforeDate:next];
	} while (isRunning && !gotResult);
}
 
// This method is called by the MyUW authenticator object automatically
// when the authentication is complete. Result is a boolean which is... obviously...
// the result.
- (void) didFinishAuthenticating:(BOOL)result
{
	STAssertEquals(expectedResult, result, @"Authentication did not get the expected result.");
	gotResult = YES;
}

I hope this helps relieve some headache for people in the future.

time Posted at 1:03 PM | written Written by Mitchell Hashimoto | comments 1 Comment made.
Jan
7

Using OCMock with Xcode 3 in Leopard

I recently ran into another “programmer’s block” similar to when I was trying to get SVN working with mediatemple. So I am posting this to share my solution.

I am a big fan of unit testing, always have been, but I am not a test driven developer. I merely like including as many unit tests to test my code as possible. It makes me feel better about what I write. So, recently, with my ever-growing cocoa apps (see post below), I decided to begin including unit tests so that I feel better about the growth. Along with unit tests I needed mock objects to simulate a WebView for my models. Although the SenTeskingKit is included with XCode, OCMock, the mock object framework, is not.

Although I got unit testing working very easily following this guide here, I was having a lot of trouble getting the OCMock framework working. I first tried copying the framework into my project folder and linking it within the unit tests target, but that didn’t work. It would cause my app to hang. After checking the logs, I saw this:

/Developer/Tools/RunUnitTests:209: note: Running tests for architecture 'i386'
2008-01-07 18:50:59.461 AutoUW[2405:10b] Error loading /Users/mitchellh/Desktop/AutoUW/build/Debug/UnitTests.octest/Contents/MacOS/UnitTests:  dlopen(/Users/mitchellh/Desktop/AutoUW/build/Debug/UnitTests.octest/Contents/MacOS/UnitTests, 262): Library not loaded: /Library/Frameworks/OCMock.framework/Versions/A/OCMock
  Referenced from: /Users/mitchellh/Desktop/AutoUW/build/Debug/UnitTests.octest/Contents/MacOS/UnitTests
  Reason: image not found

Even though I was adding the project directory the fallback framework path, it wasn’t searching it. I’m still not sure why. But anyways, if you follow the error and just add the OCMock.framework file to the /Library/Frameworks directory and compile, it works fine.

I hope this helped anyone else that may be having this issue.

time Posted at 7:52 PM | written Written by Mitchell Hashimoto | comments 2 Comments made.