Add a test of checking EC battery status report

This test checks if EC correctly report battery status to kernel.

BUG=chrome-os-partner:9188
TEST=Test passed.

Change-Id: Ib1d633de0078ecd6e7dff0a2e89d7aa04b1e4405
Reviewed-on: https://gerrit.chromium.org/gerrit/24169
Reviewed-by: Tom Wai-Hong Tam <waihong@chromium.org>
Tested-by: Vic Yang <victoryang@chromium.org>
Commit-Ready: Vic Yang <victoryang@chromium.org>
diff --git a/server/site_tests/firmware_ECBattery/control b/server/site_tests/firmware_ECBattery/control
new file mode 100644
index 0000000..779df18
--- /dev/null
+++ b/server/site_tests/firmware_ECBattery/control
@@ -0,0 +1,23 @@
+# Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+AUTHOR = "Chrome OS Team"
+NAME = "firmware_ECBattery"
+PURPOSE = "Servo based EC battery status report test"
+CRITERIA = "This test will fail if EC battery status report misbehalved."
+TIME = "LONG"
+TEST_CATEGORY = "Functional"
+TEST_CLASS = "firmware"
+TEST_TYPE = "server"
+
+DOC = """
+This test check battery status read from EC console and kernel sysfs match.
+"""
+
+def run_ecbattery(machine):
+    host = hosts.create_host(machine)
+    job.run_test("firmware_ECBattery", host=host, cmdline_args=args,
+                 use_faft=True, disable_sysinfo=True)
+
+parallel_simple(run_ecbattery, machines)
diff --git a/server/site_tests/firmware_ECBattery/firmware_ECBattery.py b/server/site_tests/firmware_ECBattery/firmware_ECBattery.py
new file mode 100644
index 0000000..0f8123c
--- /dev/null
+++ b/server/site_tests/firmware_ECBattery/firmware_ECBattery.py
@@ -0,0 +1,75 @@
+# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import logging
+
+from autotest_lib.client.common_lib import error
+from autotest_lib.server.cros.faftsequence import FAFTSequence
+
+class firmware_ECBattery(FAFTSequence):
+    """
+    Servo based EC thermal battery status report test.
+    """
+    version = 1
+
+    # Battery status path in sysfs
+    BATTERY_STATUS = '/sys/class/power_supply/BAT0/status'
+
+    # Battery voltage reading path in sysfs
+    BATTERY_VOLTAGE_READING = '/sys/class/power_supply/BAT0/voltage_now'
+
+    # Battery current reading path in sysfs
+    BATTERY_CURRENT_READING = '/sys/class/power_supply/BAT0/current_now'
+
+    # Maximum allowed error of voltage reading in mV
+    VOLTAGE_MV_ERROR_MARGIN = 300
+
+    # Maximum allowed error of current reading in mA
+    CURRENT_MA_ERROR_MARGIN = 300
+
+
+    def _check_voltage_match(self):
+        """Check if voltage reading from kernel and servo match.
+
+        Raises:
+          error.TestFail: Raised when the two reading mismatch by more than
+            VOLTAGE_MV_ERROR_MARGIN mV.
+        """
+        servo_reading = int(self.servo.get('ppvar_vbat_mv'))
+        # Kernel gives voltage value in uV. Convert to mV here.
+        kernel_reading = int(self.faft_client.run_shell_command_get_output(
+                'cat %s' % self.BATTERY_VOLTAGE_READING)[0]) / 1000
+        if abs(servo_reading - kernel_reading) > self.VOLTAGE_MV_ERROR_MARGIN:
+            raise error.TestFail(
+                    "Voltage reading from servo and kernel mismatch.")
+
+
+    def _check_current_match(self):
+        """Check if current reading from kernel and servo match.
+
+        Raises:
+          error.TestFail: Raised when the two reading mismatch by more than
+            CURRENT_MA_ERROR_MARGIN mA.
+        """
+        servo_reading = int(self.servo.get('ppvar_vbat_ma'))
+        # Kernel gives current value in uA. Convert to mA here.
+        kernel_reading = int(self.faft_client.run_shell_command_get_output(
+                'cat %s' % self.BATTERY_CURRENT_READING)[0]) / 1000
+        status = self.faft_client.run_shell_command_get_output(
+                'cat %s' % self.BATTERY_STATUS)[0]
+
+        # If battery is not discharging, servo gives negative value.
+        if status != "Discharging":
+            servo_reading = -servo_reading
+        if abs(servo_reading - kernel_reading) > self.CURRENT_MA_ERROR_MARGIN:
+            raise error.TestFail(
+                    "Current reading from servo and kernel mismatch.")
+
+
+    def run_once(self, host=None):
+        logging.info("Checking battery current reading...")
+        self._check_current_match()
+
+        logging.info("Checking battery voltage reading...")
+        self._check_voltage_match()