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