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 18import math 19import os 20import struct 21import unittest 22 23from vts.utils.python.coverage import arc_summary 24from vts.utils.python.coverage import block_summary 25from vts.utils.python.coverage import function_summary 26from vts.utils.python.coverage import gcno_parser 27from vts.utils.python.coverage.parser_test import MockStream 28 29 30class 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 218if __name__ == "__main__": 219 unittest.main() 220