autotest: Provide a way to suspend indefinitely.

Currently the method exposed to suspend remote DUT is confusing.
It expects the suspend to last exactly for 'timeout' secs. This does not
serve certain use cases. For example consider a test that would want
to test resume on power button press and sets a backup alarm to handle
the failure scenario. The method currently exposed would throw an
autoserv error complaining the suspend didn't last long enough. Make
this check optional (and True by default to not mess with the current
implementation).

BUG=chromium:820668
TEST=Test the current behaviour holds and if check_for_early_resume is
False, suspend method does not raises exception anymore.

Change-Id: I00c5021d58463460b95e43c4c94b9a2ae20a1248
Reviewed-on: https://chromium-review.googlesource.com/1129545
Commit-Ready: Ravi Chandra Sadineni <ravisadineni@chromium.org>
Tested-by: Ravi Chandra Sadineni <ravisadineni@chromium.org>
Reviewed-by: Dan Erat <derat@chromium.org>
diff --git a/server/hosts/cros_host.py b/server/hosts/cros_host.py
index 9e56aa3..396f699 100644
--- a/server/hosts/cros_host.py
+++ b/server/hosts/cros_host.py
@@ -1280,18 +1280,27 @@
                     duration, fields=metric_fields)
 
 
-    def suspend(self, **dargs):
+    def suspend(self, suspend_time=60,
+                suspend_cmd=None, allow_early_resume=False):
         """
         This function suspends the site host.
+
+        @param suspend_time: How long to suspend as integer seconds.
+        @param suspend_cmd: Suspend command to execute.
+        @param allow_early_resume: If False and if device resumes before
+                                   |suspend_time|, throw an error.
+
+        @exception AutoservSuspendError Host resumed earlier than
+                                         |suspend_time|.
         """
-        suspend_time = dargs.get('suspend_time', 60)
-        dargs['timeout'] = suspend_time
-        if 'suspend_cmd' not in dargs:
-            dargs['suspend_cmd'] = ' && '.join([
+
+        if suspend_cmd is None:
+            suspend_cmd = ' && '.join([
                 'echo 0 > /sys/class/rtc/rtc0/wakealarm',
                 'echo +%d > /sys/class/rtc/rtc0/wakealarm' % suspend_time,
                 'powerd_dbus_suspend --delay=0'])
-        super(CrosHost, self).suspend(**dargs)
+        super(CrosHost, self).suspend(suspend_time, suspend_cmd,
+                                      allow_early_resume);
 
 
     def upstart_status(self, service_name):
diff --git a/server/hosts/remote.py b/server/hosts/remote.py
index 0d4994f..b6aff79 100644
--- a/server/hosts/remote.py
+++ b/server/hosts/remote.py
@@ -165,13 +165,20 @@
         else:
             reboot()
 
-    def suspend(self, timeout, suspend_cmd, **dargs):
+    def suspend(self, timeout, suspend_cmd,
+                allow_early_resume=False):
         """
         Suspend the remote host.
 
         Args:
-                timeout - How long to wait for the suspend.
-                susped_cmd - suspend command to execute.
+                timeout - How long to wait for the suspend in integer seconds.
+                suspend_cmd - suspend command to execute.
+                allow_early_resume - Boolean that indicate whether resume
+                                     before |timeout| is ok.
+        Raises:
+                error.AutoservSuspendError - If |allow_early_resume| is False
+                                             and if device resumes before
+                                             |timeout|.
         """
         # define a function for the supend and run it in a group
         def suspend():
@@ -207,7 +214,8 @@
         start_time = time.time()
         self.log_op(self.OP_SUSPEND, suspend)
         lasted = time.time() - start_time
-        if (lasted < timeout):
+        logging.info("Device resumed after %d secs", lasted)
+        if (lasted < timeout and not allow_early_resume):
             raise error.AutoservSuspendError(
                 "Suspend did not last long enough: %d instead of %d" % (
                     lasted, timeout))