1# Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5import logging, os, re
6from autotest_lib.client.bin import test, utils
7from autotest_lib.client.common_lib import error
8
9
10class hardware_StorageWearoutDetect(test.test):
11    """
12    Check wear out status for storage device available in SMART for SSD and
13    in ext_csd for eMMC version 5.0 or later. For previous version of eMMC,
14    it will be treat as data not available.
15
16    The test will be failed if:
17    - At least one SMART variable has value under its threshold
18      or
19    - eMMC wear out status variable is in 90-100% band or higher.
20    """
21
22    version = 1
23    STORAGE_INFO_PATH = '/var/log/storage_info.txt'
24    STORAGE_INFO_UPDATE_PATH = '/usr/share/userfeedback/scripts/storage_info'
25
26    # Example     "   Model Number:    LITEONIT LSS-32L6G-HP"
27    SSD_DETECT = r"\s*Model Number:\s*(?P<model>.*)\s*$"
28
29    # Example     "   Extended CSD rev 1.7 (MMC 5.0)"
30    MMC_DETECT = r"\s*Extended CSD rev.*MMC (?P<version>\d+.\d+)"
31
32    # Field meaning and example line that have failing attribute
33    # ID# ATTRIBUTE_NAME          FLAGS    VALUE WORST THRESH FAIL RAW_VALUE
34    # 184 End-to-End_Error        PO--CK   001   001   097    NOW  135
35    SSD_FAIL = r"""\s*(?P<param>\S+\s\S+)      # ID and attribute name
36                   \s+[P-][O-][S-][R-][C-][K-] # flags
37                   (\s+\d{3}){3}               # three 3-digits numbers
38                   \s+NOW                      # fail indicator"""
39
40    # Ex "Device life time estimation type A [DEVICE_LIFE_TIME_EST_TYP_A: 0x01]"
41    # 0x0a means 90-100% band, 0x0b means over 100% band -> find not digit
42    MMC_FAIL = r".*(?P<param>DEVICE_LIFE_TIME_EST_TYP_.): 0x0\D"
43
44
45    def run_once(self, use_cached_result=True):
46        """
47        Run the test
48
49        @param use_cached_result: Use the result that generated when machine
50                                  booted or generate new one.
51        """
52
53        if not use_cached_result:
54            if not os.path.exists(self.STORAGE_INFO_UPDATE_PATH):
55                msg = str('Test failed with error: %s not exist'
56                          % self.STORAGE_INFO_UPDATE_PATH)
57                raise error.TestFail(msg)
58            utils.system(self.STORAGE_INFO_UPDATE_PATH)
59
60        # Check that storage_info file exist.
61        if not os.path.exists(self.STORAGE_INFO_PATH):
62            msg = str('Test failed with error: %s not exist'
63                      % self.STORAGE_INFO_PATH)
64            raise error.TestFail(msg)
65
66        mmc_detect = False
67        ssd_detect = False
68        legacy_mmc = False
69        fail_msg = ''
70
71        with open(self.STORAGE_INFO_PATH) as f:
72            for line in f:
73                m = re.match(self.SSD_DETECT, line)
74                if m:
75                    model = m.group('model')
76                    ssd_detect = True
77                    logging.info('Found SSD model %s', model)
78
79                m = re.match(self.MMC_DETECT, line)
80                if m:
81                    version = m.group('version')
82                    if float(version) < 5.0:
83                        legacy_mmc = True
84                    mmc_detect = True
85                    logging.info('Found eMMC version %s', version)
86
87                m = re.match(self.SSD_FAIL, line, re.X)
88                if m:
89                    param = m.group('param')
90                    fail_msg += 'SSD failure ' + param
91
92                m = re.match(self.MMC_FAIL, line)
93                if m:
94                    param = m.group('param')
95                    fail_msg += 'MMC failure ' + param
96
97        if not ssd_detect and not mmc_detect:
98            raise error.TestFail('Can not detect storage device.')
99
100        if fail_msg:
101            msg = 'Detected wearout parameter:%s' % fail_msg
102            raise error.TestFail(msg)
103
104        if legacy_mmc:
105            msg = 'eMMC version %s detected. ' % version
106            msg += 'Wearout attributes are supported in eMMC 5.0 and later.'
107            logging.info(msg)
108