Home | History | Annotate | Download | only in coverage
      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 #
     17 
     18 import math
     19 import os
     20 import struct
     21 import unittest
     22 
     23 from vts.utils.python.coverage import arc_summary
     24 from vts.utils.python.coverage import block_summary
     25 from vts.utils.python.coverage import function_summary
     26 from vts.utils.python.coverage import gcno_parser
     27 from vts.utils.python.coverage.parser_test import MockStream
     28 
     29 
     30 class GCNOParserTest(unittest.TestCase):
     31     """Tests for GCNO parser of vts.utils.python.coverage.
     32 
     33     Ensures error handling, byte order detection, and correct
     34     parsing of functions, blocks, arcs, and lines.
     35     """
     36 
     37     GOLDEN_GCNO_PATH = 'testdata/sample.gcno'
     38 
     39     def setUp(self):
     40         """Creates a stream for each test.
     41         """
     42         self.stream = MockStream()
     43 
     44     def testReadFunction(self):
     45         """Asserts that the function is read correctly.
     46 
     47         Verifies that ident, name, source file name,
     48         and first line number are all read correctly.
     49         """
     50         ident = 102010
     51         self.stream = MockStream.concat_int(self.stream, ident)
     52         self.stream = MockStream.concat_int(self.stream, 0)
     53         self.stream = MockStream.concat_int(self.stream, 0)
     54         name = "TestFunction"
     55         src_file_name = "TestSouceFile.c"
     56         first_line_number = 102
     57         self.stream = MockStream.concat_string(self.stream, name)
     58         self.stream = MockStream.concat_string(self.stream, src_file_name)
     59         self.stream = MockStream.concat_int(self.stream, first_line_number)
     60         parser = gcno_parser.GCNOParser(self.stream)
     61         summary = parser.ReadFunction()
     62         self.assertEqual(name, summary.name)
     63         self.assertEqual(ident, summary.ident)
     64         self.assertEqual(src_file_name, summary.src_file_name)
     65         self.assertEqual(first_line_number, summary.first_line_number)
     66 
     67     def testReadBlocks(self):
     68         """Asserts that blocks are correctly read from the stream.
     69 
     70         Tests correct values for flag and index.
     71         """
     72         n_blocks = 10
     73         func = function_summary.FunctionSummary(0, "func", "src.c", 1)
     74         for i in range(n_blocks):
     75             self.stream = MockStream.concat_int(self.stream, 3 * i)
     76         parser = gcno_parser.GCNOParser(self.stream)
     77         parser.ReadBlocks(n_blocks, func)
     78         self.assertEqual(len(func.blocks), n_blocks)
     79         for i in range(n_blocks):
     80             self.assertEqual(func.blocks[i].flag, 3 * i)
     81             self.assertEqual(func.blocks[i].index, i)
     82 
     83     def testReadArcsNormal(self):
     84         """Asserts that arcs are correctly read from the stream.
     85 
     86         Does not test the use of flags. Validates that arcs are
     87         created in both blocks and the source/destination are
     88         correct for each.
     89         """
     90         n_blocks = 50
     91         func = function_summary.FunctionSummary(0, "func", "src.c", 1)
     92         func.blocks = [block_summary.BlockSummary(i, 3 * i)
     93                        for i in range(n_blocks)]
     94         src_block_index = 0
     95         skip = 2
     96         self.stream = MockStream.concat_int(self.stream, src_block_index)
     97         for i in range(src_block_index + 1, n_blocks, skip):
     98             self.stream = MockStream.concat_int(self.stream, i)
     99             self.stream = MockStream.concat_int(
    100                 self.stream, 0)  #  no flag applied to the arc
    101         parser = gcno_parser.GCNOParser(self.stream)
    102         n_arcs = len(range(src_block_index + 1, n_blocks, skip))
    103         parser.ReadArcs(n_arcs * 2 + 1, func)
    104         j = 0
    105         for i in range(src_block_index + 1, n_blocks, skip):
    106             self.assertEqual(
    107                 func.blocks[src_block_index].exit_arcs[j].src_block.index,
    108                 src_block_index)
    109             self.assertEqual(
    110                 func.blocks[src_block_index].exit_arcs[j].dst_block.index, i)
    111             self.assertEqual(func.blocks[i].entry_arcs[0].src_block.index,
    112                              src_block_index)
    113             self.assertEqual(func.blocks[i].entry_arcs[0].dst_block.index, i)
    114             j += 1
    115 
    116     def testReadArcFlags(self):
    117         """Asserts that arc flags are correctly interpreted.
    118         """
    119         n_blocks = 5
    120         func = function_summary.FunctionSummary(0, "func", "src.c", 1)
    121         func.blocks = [block_summary.BlockSummary(i, 3 * i)
    122                        for i in range(n_blocks)]
    123         self.stream = MockStream.concat_int(self.stream,
    124                                             0)  #  source block index
    125 
    126         self.stream = MockStream.concat_int(self.stream, 1)  #  normal arc
    127         self.stream = MockStream.concat_int(self.stream, 0)
    128 
    129         self.stream = MockStream.concat_int(self.stream, 2)  #  on-tree arc
    130         self.stream = MockStream.concat_int(
    131             self.stream, arc_summary.ArcSummary.GCOV_ARC_ON_TREE)
    132 
    133         self.stream = MockStream.concat_int(self.stream, 3)  #  fake arc
    134         self.stream = MockStream.concat_int(
    135             self.stream, arc_summary.ArcSummary.GCOV_ARC_FAKE)
    136 
    137         self.stream = MockStream.concat_int(self.stream, 4)  #  fallthrough arc
    138         self.stream = MockStream.concat_int(
    139             self.stream, arc_summary.ArcSummary.GCOV_ARC_FALLTHROUGH)
    140 
    141         parser = gcno_parser.GCNOParser(self.stream)
    142         parser.ReadArcs(4 * 2 + 1, func)
    143 
    144         self.assertFalse(func.blocks[0].exit_arcs[0].on_tree)
    145         self.assertFalse(func.blocks[0].exit_arcs[0].fake)
    146         self.assertFalse(func.blocks[0].exit_arcs[0].fallthrough)
    147 
    148         self.assertTrue(func.blocks[0].exit_arcs[1].on_tree)
    149         self.assertFalse(func.blocks[0].exit_arcs[1].fake)
    150         self.assertFalse(func.blocks[0].exit_arcs[1].fallthrough)
    151 
    152         self.assertFalse(func.blocks[0].exit_arcs[2].on_tree)
    153         self.assertTrue(func.blocks[0].exit_arcs[2].fake)
    154         self.assertFalse(func.blocks[0].exit_arcs[2].fallthrough)
    155 
    156         self.assertFalse(func.blocks[0].exit_arcs[3].on_tree)
    157         self.assertFalse(func.blocks[0].exit_arcs[3].fake)
    158         self.assertTrue(func.blocks[0].exit_arcs[3].fallthrough)
    159 
    160     def testReadLines(self):
    161         """Asserts that lines are read correctly.
    162 
    163         Blocks must have correct references to the lines contained
    164         in the block.
    165         """
    166         self.stream = MockStream.concat_int(self.stream, 2)  #  block number
    167         self.stream = MockStream.concat_int(self.stream, 0)  #  dummy
    168         name = "src.c"
    169         name_length = int(
    170             math.ceil(1.0 * len(name) / MockStream.BYTES_PER_WORD)) + 1
    171         self.stream = MockStream.concat_string(self.stream, name)
    172         n_arcs = 5
    173         for i in range(1, n_arcs + 1):
    174             self.stream = MockStream.concat_int(self.stream, i)
    175 
    176         n_blocks = 5
    177         func = function_summary.FunctionSummary(0, "func", name, 1)
    178         func.blocks = [block_summary.BlockSummary(i, 3 * i)
    179                        for i in range(n_blocks)]
    180         parser = gcno_parser.GCNOParser(self.stream)
    181         parser.ReadLines(n_arcs + name_length + 3, func)
    182         self.assertEqual(len(func.blocks[2].lines), 5)
    183         self.assertEqual(func.blocks[2].lines, range(1, 6))
    184 
    185     def testSampleFile(self):
    186         """Asserts correct parsing of sample GCNO file.
    187 
    188         Verifies the blocks and lines for each function in
    189         the file.
    190         """
    191         dir_path = os.path.dirname(os.path.realpath(__file__))
    192         file_path = os.path.join(dir_path, self.GOLDEN_GCNO_PATH)
    193         summary = gcno_parser.ParseGcnoFile(file_path)
    194         self.assertEqual(len(summary.functions), 2)
    195 
    196         # Check function: testFunctionName
    197         func = summary.functions[4]
    198         self.assertEqual(func.name, 'testFunctionName')
    199         self.assertEqual(func.src_file_name, 'sample.c')
    200         self.assertEqual(func.first_line_number, 35)
    201         self.assertEqual(len(func.blocks), 5)
    202         expected_list = [[], [], [35, 40, 41], [42], []]
    203         for index, expected in zip(range(5), expected_list):
    204             self.assertEqual(func.blocks[index].lines, expected)
    205 
    206         # Check function: main
    207         func = summary.functions[3]
    208         self.assertEqual(func.name, 'main')
    209         self.assertEqual(func.first_line_number, 5)
    210         self.assertEqual(len(func.blocks), 12)
    211         self.assertEqual(func.blocks[0].lines, [])
    212         expected_list = [[], [], [5, 11, 12, 13], [15], [17], [18], [20],
    213                          [23, 24, 25], [26, 25], [], [29], [31]]
    214         for index, expected in zip(range(12), expected_list):
    215             self.assertEqual(func.blocks[index].lines, expected)
    216 
    217 
    218 if __name__ == "__main__":
    219     unittest.main()
    220