Implement pluggable discovery adapters and standalone tests

This pull request adds a `Locator` interface for server discovery, extracts the etcd discovery implementation into an `EtcdLocator`, and adds a `StaticLocator` adapter. The config loading mechanism has also been refactored, making it possible to run the tests without etcd, memcached, or a standalone Simple Push server.

* The router now uses a buffered channel (`bucket_size`) instead of partitioning contacts into buckets.
* The etcd key prefix and minimum refresh interval are exposed as `EtcdLocatorConf.Dir` and `.RefreshInterval`, respectively.
* `EtcdLocator` now uses the normalized key (prefix + hostname) consistently, and accounts for non-default HTTPS ports when constructing the key.
* The `PluginLoaders` map associates plugin types (i.e., logger, proprietary pinger, metrics, storage adapter, router, locator, server, and handlers) with initialization functions. This is used by `TestServer` to specify configuration options programmatically. The `*Conf` structures have also been flattened where appropriate.
* The `Host` and `Port` options have been consolidated into `Addr`. If `Addr` is omitted, the server and router will listen on random ports.
* `Server` and `Router` now initialize their own `net.Listener`s, avoiding a race condition where the tests would begin running before the server was ready.

Closes #30. @bbangert, @jrconlin, @rafrombrc r?
Hmm, pondering this some more...even if the test harness hands an `http.Server` to the `Application`, it won't know *when* the listener is ready. I think attaching the listener during initialization guarantees that the server is ready to receive incoming connections by the time `Application.Run()` is called. The first `client.Dial()` call will just block until the two Goroutines in `Run()` call `http.Serve()`, which kicks off the `Accept()` loops.

But because `http.Server.ListenAndServe()` attaches the listener and calls `Serve()` all at once, we can't know when the listener is ready—`Serve()` won't exit the loop unless there's an error. We could call `time.Sleep()` in the tests and assume that the listener has been attached after 1-2 seconds, but that's fragile. We could also retry failed `client.Dial()` attempts—if we get an error, check for `err.(*net.OpError).Err == syscall.ECONNREFUSED` and try again, but that seems worse.

Does that make sense at all? I suspect I'm overthinking this; there has to be a better way.