Refactor WaitFor (#221)

* Refactor WaitFor

This commit modifies WaitFor in a few ways:

It replaces time.Now().Second() with time.Now().Unix() in order to
account for rolling minutes (for example, when WaitFor starts at 59
seconds, every timeout check will result in a negative number).

A "retry" timer has also been added. This will cause the predicate
to be retried every n seconds if there hasn't been a response. This
is to account for server or network issues that would cause the
predicate to be lost or hang indefinitely.

A combination of using both timeout and retry can be effective in
handling faulty requests as well as a master kill switch to stop.

* Remove Retry from WaitFor

This removes the retry parameter and re-uses the timeout to kill
possible hanging predicates.
diff --git a/testing/util_test.go b/testing/util_test.go
index 5985bc3..ae3e448 100644
--- a/testing/util_test.go
+++ b/testing/util_test.go
@@ -1,22 +1,58 @@
 package testing
 
 import (
+	"errors"
 	"os"
 	"path/filepath"
 	"strings"
 	"testing"
+	"time"
 
 	"github.com/gophercloud/gophercloud"
 	th "github.com/gophercloud/gophercloud/testhelper"
 )
 
 func TestWaitFor(t *testing.T) {
-	err := gophercloud.WaitFor(5, func() (bool, error) {
+	err := gophercloud.WaitFor(2, func() (bool, error) {
 		return true, nil
 	})
 	th.CheckNoErr(t, err)
 }
 
+func TestWaitForTimeout(t *testing.T) {
+	if testing.Short() {
+		t.Skip("skipping test in short mode.")
+	}
+
+	err := gophercloud.WaitFor(1, func() (bool, error) {
+		return false, nil
+	})
+	th.AssertEquals(t, "A timeout occurred", err.Error())
+}
+
+func TestWaitForError(t *testing.T) {
+	if testing.Short() {
+		t.Skip("skipping test in short mode.")
+	}
+
+	err := gophercloud.WaitFor(2, func() (bool, error) {
+		return false, errors.New("Error has occurred")
+	})
+	th.AssertEquals(t, "Error has occurred", err.Error())
+}
+
+func TestWaitForPredicateExceed(t *testing.T) {
+	if testing.Short() {
+		t.Skip("skipping test in short mode.")
+	}
+
+	err := gophercloud.WaitFor(1, func() (bool, error) {
+		time.Sleep(4 * time.Second)
+		return false, errors.New("Just wasting time")
+	})
+	th.AssertEquals(t, "A timeout occurred", err.Error())
+}
+
 func TestNormalizeURL(t *testing.T) {
 	urls := []string{
 		"NoSlashAtEnd",