Many of us are developing iPhone applications running in a simulator connected to a very fast Internet connection. Too bad the customers of these applications won’t be using the same environment.
It’s very important to be able to profile and debug your application while it’s running on a slow network. You’ll find lots of weird timing problems, bad connection error handling, timeouts that are too short, and other things that are likely to occur in real world conditions.
Initially, I did testing for Twitterrific by loading the latest version onto the device and then walking around outside away from my office Wi-Fi network. That was a good first step, but also one that didn’t allow me to run gdb or Instruments when a problem occurred.
And then one day it hit me: the iPhone Simulator is running on top of the Mac OS X network stack. An environment that I can manage with standard Unix command line tools. Here’s the result:
#!/bin/bash # configuration host1="twitter.com" host2="search.twitter.com" # usage if [ "$*" == "" ]; then echo "usage: $0 [full|fast|medium|slow|wwdc|off]" exit fi # remove any previous firewall rules sudo ipfw list 100 > /dev/null 2>&1 if [ $? -eq 0 ]; then sudo ipfw delete 100 > /dev/null 2>&1 fi sudo ipfw list 110 > /dev/null 2>&1 if [ $? -eq 0 ]; then sudo ipfw delete 110 > /dev/null 2>&1 fi sudo ipfw list 200 > /dev/null 2>&1 if [ $? -eq 0 ]; then sudo ipfw delete 200 > /dev/null 2>&1 fi sudo ipfw list 210 > /dev/null 2>&1 if [ $? -eq 0 ]; then sudo ipfw delete 210 > /dev/null 2>&1 fi # process the command line option if [ "$1" == "full" ]; then echo "full speed" elif [ "$1" == "off" ]; then # add rules to deny any connections to configured host if [ -n "$host1" ]; then sudo ipfw add 100 deny tcp from $host1 to me sudo ipfw add 110 deny tcp from me to $host1 fi if [ -n "$host2" ]; then sudo ipfw add 200 deny tcp from $host2 to me sudo ipfw add 210 deny tcp from me to $host2 fi else # create a pipe with limited bandwidth bandwidth="100Kbit" if [ "$1" == "fast" ]; then bandwidth="300Kbit" elif [ "$1" == "slow" ]; then bandwidth="10Kbit" elif [ "$1" == "wwdc" ]; then bandwidth="1Kbit" fi sudo ipfw pipe 1 config bw $bandwidth # add rules to use bandwidth limited pipe if [ -n "$host1" ]; then sudo ipfw add 100 pipe 1 tcp from $host1 to me sudo ipfw add 110 pipe 1 tcp from me to $host1 fi if [ -n "$host2" ]; then sudo ipfw add 200 pipe 1 tcp from $host2 to me sudo ipfw add 210 pipe 1 tcp from me to $host2 fi fi sudo ipfw list
You’ll notice a couple of configuration parameters:
host2. Unless you’re one of the hundreds of Twitter client developers, you’ll probably want to change those values.
Turning a connection “off” can be used to simulate a site being offline. Using the “wwdc” setting allows you to relive those exciting moments of waiting in line with thousands of other geeks banging on the SOMA EDGE network. To turn off the bandwidth limit, use the “full” setting. The other values can be used to alter the quality of the connection in the simulator and make it feel more like it’s on a cellular network.
(I actually uncovered a bug in the beta version of Twitterrific while waiting in line for the WWDC 2008 keynote, so don’t think that setting is purely a joke.)
This bandwidth trick can be extended for device testing. On your development machine, turn on Internet Sharing (in System Preferences > Sharing.) Then use your device to connect to that shared network. Any
ipfw rules you set will affect the device since all of its packets pass through the gateway you’ve established on your machine.
Another trick you can use to test your networking code is by opening the Networking preference panel and making your outbound connection inactive. Since the iPhone Simulator’s networking code sits on top of the System Configuration framework, any state changes will be passed onto your app running in the simulator. (If you’re using the Reachability class, this will make sense.)
And as I mentioned above, being able to do all these things from the comfort of your office chair and Xcode debugging environment has a lot of advantages. So slow down and do some real testing!