Add new hardware_MemoryIntegrity test / refactor related test

This test call hardware_StorageFio to write data once to the ramfs
then idle/suspend for an hour before verify the data integrity.

Also refactor hardware_RamFio and hardware_Memtester to share
the existing code.

BUG=chromium:357856
TEST=Tested in peach_pit. Test passed.

Change-Id: I3a52cb8d32b31fec3f4f6ad3a8c562bc7bb7d17f
Reviewed-on: https://chromium-review.googlesource.com/193065
Reviewed-by: Gwendal Grignou <[email protected]>
Commit-Queue: Puthikorn Voravootivat <[email protected]>
Tested-by: Puthikorn Voravootivat <[email protected]>
diff --git a/client/bin/base_utils.py b/client/bin/base_utils.py
index c5dac1b..7dcb372 100644
--- a/client/bin/base_utils.py
+++ b/client/bin/base_utils.py
@@ -372,6 +372,15 @@
 def freememtotal():
     return read_from_meminfo('MemFree')
 
+def usable_memtotal():
+    # Assume 30MB reserved by the OS
+    reserved = 30 * 1024
+    ret = read_from_meminfo('MemFree')
+    ret += read_from_meminfo('Buffers')
+    ret += read_from_meminfo('Cached')
+    ret = max(0, ret - reserved)
+    return ret
+
 
 def rounded_memtotal():
     # Get total of all physical mem, in kbytes
@@ -392,7 +401,7 @@
     #   tighter spread between min and max possible deductions
 
     # increase mem size by at least min deduction, without rounding
-    min_kbytes   = int(usable_kbytes / (1.0 - mindeduct))
+    min_kbytes = int(usable_kbytes / (1.0 - mindeduct))
     # increase mem size further by 2**n rounding, by 0..roundKb or more
     round_kbytes = int(usable_kbytes / (1.0 - maxdeduct)) - min_kbytes
     # find least binary roundup 2**n that covers worst-cast roundKb
@@ -457,7 +466,7 @@
     for item in object.__dict__.iteritems():
         print item
         try:
-            (key,value) = item
+            (key, value) = item
             dump_object(value)
         except:
             continue
@@ -510,7 +519,7 @@
 
     f.close()
     return "Elapsed: %0.2fs User: %0.2fs System: %0.2fs CPU: %0.0f%%" % \
-          (elapsed/count, user/count, system/count, cpu/count)
+          (elapsed / count, user / count, system / count, cpu / count)
 
 
 def running_config():
diff --git a/client/site_tests/hardware_Memtester/hardware_Memtester.py b/client/site_tests/hardware_Memtester/hardware_Memtester.py
index 0896937..59d3e73 100644
--- a/client/site_tests/hardware_Memtester/hardware_Memtester.py
+++ b/client/site_tests/hardware_Memtester/hardware_Memtester.py
@@ -16,30 +16,21 @@
 
     version = 1
 
-    # Region in /proc/meminfo to used for testing
-    USABLE_MEM = ['MemFree:', 'Buffers:', 'Cached:']
-
-    # Size reserved for os, etc. when specified size=0
-    RESERVED_SIZE = 30 * 1024
-
     def run_once(self, size=0, loop=10):
         """
         Executes the test and logs the output.
 
-        @param size: size to test in KB. 0 means all available minus 30 MB
+        @param size: size to test in KB. 0 means all usable
         @param loop: number of iteration to test memory
         """
         if size == 0:
-            with open('/proc/meminfo', 'r') as f:
-                for lines in f.readlines():
-                    items = lines.split()
-                    if items[0] in self.USABLE_MEM:
-                        size += int(items[1])
-            # minus 30 MB (arbitrary chosen) for OS use
-            size -= self.RESERVED_SIZE
+            size = utils.usable_memtotal()
+        elif size > utils.memtotal():
+            raise error.TestFail('Specified size is more than total memory.')
 
         if size <= 0:
-            error.testFail('Size is less than zero.')
+            raise error.TestFail('Size must be more than zero.')
+
 
         logging.info('Memory test size: %dK', size)
 
diff --git a/client/site_tests/hardware_RamFio/hardware_RamFio.py b/client/site_tests/hardware_RamFio/hardware_RamFio.py
index 4cefbbc..40866d9 100644
--- a/client/site_tests/hardware_RamFio/hardware_RamFio.py
+++ b/client/site_tests/hardware_RamFio/hardware_RamFio.py
@@ -16,34 +16,28 @@
 
     DEFAULT_SIZE = 1024 * 1024 * 1024
 
-    # Region in /proc/meminfo that usable
-    USABLE_MEM = ['MemFree:', 'Buffers:', 'Cached:']
-
-    def get_usable_memory(self):
-        size = 0
-        with open('/proc/meminfo', 'r') as f:
-                for lines in f.readlines():
-                    items = lines.split()
-                    if items[0] in self.USABLE_MEM:
-                        size += int(items[1])
-        # meminfo report in KB unit
-        return size * 1024
-
-    def run_once(self, size=DEFAULT_SIZE, requirements=None):
+    def run_once(self, size=DEFAULT_SIZE, requirements=None, dry_run=False):
         """
         Call hardware_StorageFio to test on ram drive
 
+        @param size: size to test in byte
+                     0 means all usable memory
         @param requirements: requirement to pass to hardware_StorageFio
         """
 
-        free_mem = self.get_usable_memory()
-
         # assume 20% overhead with ramfs
-        needed_size = size * 1.2
-        if free_mem < needed_size:
-            raise error.TestFail(str('Not enough memory. Need: %d, Have: %d' %
-                           (needed_size, free_mem)))
+        usable_mem = int(utils.usable_memtotal() * 1024 * 0.8)
 
+        if size == 0:
+            size = usable_mem
+        elif usable_mem < size:
+            raise error.TestFail(str('Not enough memory. Want: %d, Usable: %d' %
+                           (size, usable_mem)))
+
+        self.write_perf_keyval({'Size' : size})
+
+        if dry_run:
+            return
 
         utils.run('mkdir -p /tmp/ramdisk')
         utils.run('mount -t ramfs ramfs /tmp/ramdisk')