January 2006 Archives

Unit Testing a Bundle in Xcode, Part 3

|

In part 2, I explained how to test a bundle by using a custom script in the "Run Script Phase". A slightly better approach is to use a test rig. From the Xcode documentation, a test rig is:

A tool that can take information from its environment and will be passed the path to a unit test bundle as its sole argument.

In part 2, the BundleTestRunner took two arguments, so it cannot be used as a test rig. This entry describes how to modify it so it takes one argument, and the rest of the information from the environment.

Unit Testing a Bundle in Xcode, Part 2

|

In a previous episode, I tried to setup Xcode to run unit tests from a bundle. While it worked, it didn't work in all cases. First off, I probably should have used load instead of initialize. But even that doesn't help. The problem is that loading the bundle before tests run works only when you reference functions or Objective-C classes from your test case. Access a plain-old ordinary C symbol, and you're hosed. This happens, for example, when using constants for notification names, which would be defined in a header like:

extern NSString * const MyNotification;

If you now try and use MyNotification from within a test, and build the unit test target, you'll get a runtime link edit error along the lines of: "Symbol not found: _MyNotification" (the compiler always adds an underscore in front of all symbol names). This is because functions are bound lazily, and global variables are not. Or more precisely, global variables cannot be loaded lazily. Extrapolating from information in Tech Note 2064, and after thinking about this, it makes sense. The dynamic link editor can setup stubs for functions: e.g. func() calls dyld_stub_func(), which then finds the _func symbol, and calls it. That's not really how it's done, but it's close (do an "nm <executble> | grep dyld" sometime). This level of indirection cannot be done for global variables (or function pointers).

Okay, so how to solve this. We need to find a way to get the global symbols into the unit test bundle before the unit tests run. It is possible, but it requires a little more work than last time. Xcode uses a trick of setting the DYLD_INSERT_LIBRARIES dyld environment variable to force loading a library before an application is run. Unfortunately, this cannot be used to load a bundle. I couldn't figure out how to get the OCUnit otest tool to do it, either. So I had to write my own unit test rig, which I'm calling BundleTestRunner.

Unit Testing a Bundle in Xcode

|

Apple's Xcode now has unit testing built in using OCUnit. While it's a little complicated to get set up, they do provide decent instructions on how to add unit tests to your projects. The recommended setup is to use what's called a "depenendent" target, where tests are executed at build time by doing some fancy bundle loading. Unfortunately, they only tell you how to do it for applications or frameworks. If you're writing a bundle, for example a Dashboard Widget plug-in, it is still possible to setup a dependent target, it just takes some more fussing around.

Update: This doesn't work in all cases. See part 2 for a better method.

Reading Keychain Passwords from the Command Line

|

Apple's Keychain is a nice way to store your passwords in an encrypted database. Apple provides the Keychain Access GUI application to view and manage passwords. You can do all sorts of cool stuff with it, like have multiple keychains for extra security. I just found out you can also view and manage passwords from the command line using the security(1) tool. It's got a lot of subcommands and options, but here's the syntax if you want to find the password for an IMAP email account:

% security find-internet-password -g -r imap -a <ACCOUNT> -s <SERVER>

You can replace "imap" with other protocols like "https" to access Web passwords. One issue is it will prompt you for access to the keychain using the standard "Deny", "Allow Once", "Always Allow" GUI dialog. This makes it somewhat useless during remote access. However, if you click on "Always Allow", then the command line tool can access the password to that account only for all future invocations without a dialog. A second issue is that it prints the password to standard error. So if your using it from a script, be sure to redirect standard error to standard output:

output = `security find-internet-password ... 2>&1`

Encap is a Unix tool that doesn't get the attention it deserves. I've used it on Linux servers for years, and is a staple in my OS X tool belt. To borrow from the Encap FAQ, Encap is a package management system for handling third-party packages on a Unix system. Through the magic of symbolic links, it allows you to install each package in its own directory, but still have everything accessible via the traditional location in /usr/local. This means you that you can upgrade Ruby or LightTPD while keeping older versions to fall back on, or you can even remove these packages without having to remember all the files they scattered throughout /usr/local. This article provides instructions for manually building and installing Ruby, Ruby on Rails, and LightTPD on Mac OS X 10.4 (Tiger) using epkg, an Encap package manager. This is a somewhat advanced topic, and you should be fairly familiar with Unix and the Terminal application.

Fun With Less

|

If you grok the Unix command line, you're probably familiar with the less command. If you're still using more, switch now. less has more advanced commands you can type while viewing, for example jump to the end of the file (">"), jump to the beginning of the file ("<"), or jump to a specific line number ("#G"). It's searching capabilities are much richer, too. It highlights the matched term, allows regular expressions, and can be put into case insensitive mode ("-i"). But one of the best goodies is lesspipe. lesspipe is input filter that allows to view files with binary content, compressed files, archives and files contained in archives. So, let's say you have a tarball with two files: hello.c and hello.txt. You can view the contents:

% less hello.tar.gz
==> use tar_file:contained_file to view a file in the archive
-rw-r--r-- dave/wheel      105 2006-01-06 11:18:01 hello.c
-rw-r--r-- dave/wheel        7 2006-01-06 11:16:22 hello.txt

This works for tar.bz2 and zip, archives, too. This saves you from having to remember the different flags needed to uncompress and list the archive, and you don't have to remember to pipe it to less, which is probably what you were going to do, anyway. You'll notice from the output that you can also view files inside the archive directly:

% less hello.tar.gz:hello.c  
#include <stdio.h>

int main(char * argc, char * argv[])
{
    printf("Hello World!\n");
    return 0;
}

You can use it on a file that's just compressed, too: less hello.c.gz. One of my favorite is to view man pages: less /usr/share/man/man1/ls.1. While obviously not useful for man pages in standard locations, you can use it to view a man page in the current directory without having to remember the flags to nroff. This is useful if you want to view a man page for a package you haven't installed yet, or if you are writing a man page. On OS X, it can view bom files, and it's even smart enough to look inside a pkg: less /Library/Receipts/Mail.pkg.

I just learned that it can colorize source code. But to do this, you need to use -r or -R to enable raw control characters: less -R hello.c. This is somewhat dangerous in that viewing a binary file can really mess up your terminal, by putting into some mode that you can't get it out of. But if you want to enable this all the time, you can put it into your LESS environment variable. My LESS is set to -i -M, so I can always be in case insensitive mode, and -M gives a more descriptive prompt.

Wordpress 2.0 Released.... Yawn

|

Wordpress 2.0 has been released, and I'm not that impressed. For me, the biggest missing feature is database independence, namely support for SQLite. Blogs are a perfect use case for SQLite: 99% reads, 1% writes. I don't have MySQL installed on my server, and I refuse to install it just for a blog. I say, quit your whining and use ADODb. In the meantime, I'll stick with MovableType. And if I ever decide to ditch it, I'll probably go with Typo. That is, if I could ever figure out how to get Ruby on Rails configured for a deployment environment. Hopefully, this will get easier with Apache's renewed interest in FastCGI.

About this Archive

This page is an archive of entries from January 2006 listed from newest to oldest.

December 2005 is the previous archive.

February 2006 is the next archive.

Find recent content on the main index or look in the archives to find all content.

Links

Powered by Movable Type 4.1