Ensure upload target URLs always end in a /.

HTTP uploads may not care, but rsync's behavior in

    (1) rsync -avz file rsync://example.com/module/foo

and

    (2) rsync -avz file rsync://example.com/module/foo/

are very different.  Example (1) copies file to *file* foo in the
module, overwriting the file if it exists; example (2) copies file into
*directory* foo in the module, creating that directory if it doesn't
exist.

(I don't recall an rsync client option to disable overwrites, but if
there is one, we should probably turn that on too.)
Add UploadTargets spec.
Upgrade to redis-rb 3.1.0.

I want this for weighted upload targets because script support in
redis-rb ~> 3.0 is much improved over the 2.x series.

However, some changes were required.  The changes reflected in this
commit:

1. Redis::Client#sismember returns true or false, not 1 or 0.
2. Redis::Client#sadd with a single item returns true or false, not
   1 or 0.  (Redis::Client#add with multiple items returns the
   number of items added.)
3. Redis::Client#hgetall now returns a Hash.
4. Redis::Client#zrange with with_scores set to true now returns an
   Array of Arrays, not a single Array with interleaved items and
   scores.
5. Redis::Client#eval now counts keys and argv length; there is no
   longer a need to explicitly specify the number of keys.

Finally, I replaced Tracker#unknown_items with a script because I
didn't want to mess about with the previous pipeline.
Fill in a missing expectation.