1#!/usr/bin/env python
2#
3# Copyright (C) 2016 The Android Open Source Project
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9#      http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16#
17import os
18import unittest
19
20from vts.utils.python.coverage import arc_summary
21from vts.utils.python.coverage import block_summary
22from vts.utils.python.coverage import file_summary
23from vts.utils.python.coverage import function_summary
24from vts.utils.python.coverage import gcda_parser
25from vts.utils.python.coverage import gcno_parser
26from vts.utils.python.coverage.parser_test import MockStream
27
28
29class GCDAParserTest(unittest.TestCase):
30    """Tests for GCDA parser of vts.utils.python.coverage.
31    """
32
33    GOLDEN_GCNO_PATH = 'testdata/sample.gcno'
34    GOLDEN_GCDA_PATH = 'testdata/sample.gcda'
35
36    def setUp(self):
37        """Creates a stream for each test.
38      """
39        self.stream = MockStream(gcda_parser.GCDAParser.MAGIC)
40
41    def testReadFunction(self):
42        """Verifies that the correct function is read and returned.
43        """
44        ident = 100
45        checksum = 0
46        fs = file_summary.FileSummary()
47        func = function_summary.FunctionSummary(ident, 'test', 'test.c', 0)
48        fs.functions[ident] = func
49        self.stream = MockStream.concat_int(self.stream, ident)
50        self.stream = MockStream.concat_int(self.stream, 0)
51        self.stream = MockStream.concat_int(self.stream, 0)
52        self.stream = MockStream.concat_string(self.stream, 'test')
53        length = 5
54        parser = gcda_parser.GCDAParser(self.stream)
55        parser.file_summary = fs
56        func = parser.ReadFunction(5)
57        assert (func.ident == ident)
58
59    def testReadCountsNormal(self):
60        """Verifies that counts are read correctly.
61
62        Verifies that arcs are marked as resolved and count is correct.
63        """
64        n = 5
65        fs = file_summary.FileSummary()
66        func = function_summary.FunctionSummary(0, 'test', 'test.c', 0)
67        blocks = [block_summary.BlockSummary(i, 0) for i in range(n)]
68        func.blocks = blocks
69        fs.functions[func.ident] = func
70        for i in range(1, n):
71            arc = arc_summary.ArcSummary(blocks[0], blocks[i], 0)
72            blocks[0].exit_arcs.append(arc)
73            blocks[i].entry_arcs.append(arc)
74            self.stream = MockStream.concat_int64(self.stream, i)
75        parser = gcda_parser.GCDAParser(self.stream)
76        parser.file_summary = fs
77        parser.ReadCounts(func)
78        for i, arc in zip(range(1, n), blocks[0].exit_arcs):
79            self.assertEqual(i, arc.count)
80            self.assertTrue(arc.resolved)
81
82    def testReadCountsFakeOrOnTree(self):
83        """Verifies that counts are read correctly when there are skipped arcs.
84
85        Verifies that the fake arc and the arc on the tree are skipped while other
86        arcs are read and resolved correctly.
87        """
88        n = 10
89        fs = file_summary.FileSummary()
90        func = function_summary.FunctionSummary(0, 'test', 'test.c', 0)
91        blocks = [block_summary.BlockSummary(i, 0) for i in range(n)]
92        func.blocks = blocks
93        fs.functions[func.ident] = func
94
95        arc = arc_summary.ArcSummary(blocks[0], blocks[1],
96                                     arc_summary.ArcSummary.GCOV_ARC_FAKE)
97        blocks[0].exit_arcs.append(arc)
98        blocks[1].entry_arcs.append(arc)
99
100        arc = arc_summary.ArcSummary(blocks[0], blocks[2],
101                                     arc_summary.ArcSummary.GCOV_ARC_ON_TREE)
102        blocks[0].exit_arcs.append(arc)
103        blocks[2].entry_arcs.append(arc)
104
105        for i in range(3, n):
106            arc = arc_summary.ArcSummary(blocks[0], blocks[i], 0)
107            blocks[0].exit_arcs.append(arc)
108            blocks[i].entry_arcs.append(arc)
109            self.stream = MockStream.concat_int64(self.stream, i)
110
111        parser = gcda_parser.GCDAParser(self.stream)
112        parser.file_summary = fs
113        parser.ReadCounts(func)
114        self.assertFalse(blocks[0].exit_arcs[0].resolved)
115        self.assertFalse(blocks[0].exit_arcs[1].resolved)
116        for i, arc in zip(range(3, n), blocks[0].exit_arcs[2:]):
117            self.assertEqual(i, arc.count)
118            self.assertTrue(arc.resolved)
119
120    def testSampleFile(self):
121        """Asserts correct parsing of sample GCDA file.
122
123        Verifies the block coverage counts for each function.
124        """
125        dir_path = os.path.dirname(os.path.realpath(__file__))
126        gcno_path = os.path.join(dir_path, self.GOLDEN_GCNO_PATH)
127        gcda_path = os.path.join(dir_path, self.GOLDEN_GCDA_PATH)
128        summary = gcno_parser.ParseGcnoFile(gcno_path)
129        gcda_parser.ParseGcdaFile(gcda_path, summary)
130        # Function: main
131        expected_list = [2, 0, 2, 2, 2, 0, 2, 2, 500, 502, 2, 2]
132        for index, expected in zip(range(len(expected_list)), expected_list):
133            self.assertEqual(summary.functions[3].blocks[index].count,
134                             expected)
135
136        # Function: testFunctionName
137        expected_list = [2, 2, 2, 2, 2]
138        for index, expected in zip(range(len(expected_list)), expected_list):
139            self.assertEqual(summary.functions[4].blocks[index].count,
140                             expected)
141
142
143if __name__ == "__main__":
144    unittest.main()
145