1#
2# Copyright (C) 2017 The Android Open Source Project
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8#      http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15#
16
17import logging
18
19from parse import with_pattern
20from vts.testcases.kernel.api.proc import KernelProcFileTestBase
21
22
23@with_pattern(r'[^ ^\t^\n^:^\0]+')
24def token_name(text):
25    return text
26
27@with_pattern(r'[ ]*[0-9]+')
28def token_lu(text):
29    return int(text)
30
31@with_pattern(r'(kB)?')
32def token_kb(text):
33    return text
34
35class ProcMemInfoTest(KernelProcFileTestBase.KernelProcFileTestBase):
36    '''/proc/meminfo reports statistics about memory usage on the system.
37
38    No new fields should be added to the upstream implementation.
39    '''
40
41    REQUIRED_FIELDS = {
42        "MemTotal",
43        "MemFree",
44        "MemAvailable",
45        "Buffers",
46        "Cached",
47        "SwapCached",
48        "Active",
49        "Inactive",
50        "Active(anon)",
51        "Inactive(anon)",
52        "Active(file)",
53        "Inactive(file)",
54        "Unevictable",
55        "Mlocked",
56        "SwapTotal",
57        "SwapFree",
58        "Dirty",
59        "Writeback",
60        "AnonPages",
61        "Mapped",
62        "Shmem",
63        "Slab",
64        "SReclaimable",
65        "SUnreclaim",
66        "KernelStack",
67        "PageTables",
68        "NFS_Unstable",
69        "Bounce",
70        "WritebackTmp",
71        "CommitLimit",
72        "Committed_AS",
73        "VmallocTotal",
74        "VmallocUsed",
75        "VmallocChunk",
76    }
77
78    def parse_contents(self, contents):
79        lines = contents.split('\n')
80        if lines[-1] != '':
81            raise SyntaxError("missing final newline")
82        return [self.parse_line("{:name}: {:lu}{:^kb}", line,
83            dict(name=token_name, lu=token_lu, kb=token_kb)) for line in lines[:-1]]
84
85    def result_correct(self, parse_result):
86        required_fields = self.REQUIRED_FIELDS.copy()
87        for line in parse_result:
88            if line[0] in required_fields:
89                required_fields.remove(line[0])
90        if len(required_fields) > 0:
91            logging.error("Required fields not present: %s", str(required_fields))
92            return False
93        return True
94
95    def get_path(self):
96        return "/proc/meminfo"
97