Commit | Line | Data |
---|---|---|
d44e3c4f | 1 | /****************************************************************************** |
2 | * Copyright (c) 2000-2016 Ericsson Telecom AB | |
3 | * All rights reserved. This program and the accompanying materials | |
4 | * are made available under the terms of the Eclipse Public License v1.0 | |
5 | * which accompanies this distribution, and is available at | |
6 | * http://www.eclipse.org/legal/epl-v10.html | |
7 | * | |
8 | * Contributors: | |
9 | * Balasko, Jeno | |
10 | * Kovacs, Ferenc | |
11 | * Raduly, Csaba | |
12 | * | |
13 | ******************************************************************************/ | |
970ed795 EL |
14 | #include "TCov.hh" |
15 | ||
16 | #include "Component.hh" | |
17 | #include "Runtime.hh" | |
18 | ||
19 | #include <stdio.h> | |
20 | #include <string.h> | |
21 | #include <unistd.h> | |
22 | ||
23 | expstring_t TCov::comp(boolean withname) | |
24 | { | |
25 | enum { SINGLE, HC, MTC, PTC } whoami; | |
26 | if (TTCN_Runtime::is_single()) whoami = SINGLE; | |
27 | else if (TTCN_Runtime::is_hc()) whoami = HC; | |
28 | else if (TTCN_Runtime::is_mtc()) whoami = MTC; | |
29 | else whoami = PTC; | |
30 | expstring_t ret_val = NULL; | |
31 | switch (whoami) { | |
32 | case SINGLE: ret_val = mcopystr("single"); break; | |
33 | case HC: ret_val = mcopystr("hc"); break; | |
34 | case MTC: ret_val = mcopystr("mtc"); break; | |
35 | case PTC: | |
36 | default: { | |
37 | const char *compname = TTCN_Runtime::get_component_name(); | |
38 | if (withname && compname != NULL) ret_val = mcopystr(compname); | |
39 | else ret_val = mprintf("%d", self.is_bound() ? (component)self : (component)0); | |
40 | break; | |
41 | } | |
42 | } | |
43 | return ret_val; | |
44 | } | |
45 | ||
46 | int TCov::ver_major = 1; | |
47 | int TCov::ver_minor = 0; | |
48 | Vector<FileData *> TCov::m_file_data; | |
49 | pid_t TCov::mypid = getpid(); | |
50 | expstring_t TCov::mycomp = TCov::comp(); | |
51 | expstring_t TCov::mycomp_name = TCov::comp(TRUE); | |
52 | ||
53 | size_t TCov::has_file_name(const char *file_name) | |
54 | { | |
55 | size_t i = 0; | |
56 | for (; i < m_file_data.size(); ++i) | |
57 | if (!strcmp(file_name, m_file_data[i]->get_file_name())) | |
58 | return static_cast<int>(i); | |
59 | return i; | |
60 | } | |
61 | ||
62 | void TCov::close_file() | |
63 | { | |
64 | if (m_file_data.empty()) { | |
65 | Free(mycomp); | |
66 | Free(mycomp_name); | |
67 | mycomp = mycomp_name = NULL; | |
68 | return; | |
69 | } | |
70 | expstring_t file_name = mputprintf(NULL, "tcov-%s.tcd", mycomp); | |
71 | FILE *fp = fopen((const char *)file_name, "w"); | |
72 | expstring_t output = mputprintf(NULL, | |
73 | "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" \ | |
74 | "<?xml-stylesheet type=\"text/xsl\" href=\"tcov.xsl\"?>\n" \ | |
75 | "<titan_coverage xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " \ | |
76 | "xsi:schemaLocation=\"tcov.xsd\">\n" \ | |
77 | "\t<version major=\"%d\" minor=\"%d\" />\n" \ | |
78 | "\t<component id=\"%s\" name=\"%s\" />\n" \ | |
79 | "\t<files>\n", | |
80 | ver_major, ver_minor, mycomp, mycomp_name); | |
81 | for (size_t i = 0; i < m_file_data.size(); ++i) { | |
82 | const FileData *file_data = m_file_data[i]; | |
83 | output = mputprintf(output, "\t\t<file path=\"%s\">\n", file_data->get_file_name()); | |
84 | const Vector<FunctionData *>& function_data = file_data->get_function_data(); | |
85 | const Vector<LineData *>& line_data = file_data->get_line_data(); | |
86 | output = mputstr(output, "\t\t\t<functions>\n"); | |
87 | for (size_t j = 0; j < function_data.size(); ++j) { | |
88 | output = mputprintf(output, "\t\t\t\t<function name=\"%s\" count=\"%d\" />\n", | |
89 | function_data[j]->get_name(), function_data[j]->get_count()); | |
90 | } | |
91 | output = mputstr(output, "\t\t\t</functions>\n"); | |
92 | output = mputstr(output, "\t\t\t<lines>\n"); | |
93 | for (size_t j = 0; j < line_data.size(); ++j) { | |
94 | output = mputprintf(output, "\t\t\t\t<line no=\"%d\" count=\"%d\" />\n", | |
95 | line_data[j]->get_no(), line_data[j]->get_count()); | |
96 | } | |
97 | output = mputstr(output, | |
98 | "\t\t\t</lines>\n" \ | |
99 | "\t\t</file>\n"); | |
100 | } | |
101 | output = mputstr(output, | |
102 | "\t</files>\n" \ | |
103 | "</titan_coverage>\n"); | |
104 | fputs(output, fp); | |
105 | fclose(fp); | |
106 | Free(output); | |
107 | Free(file_name); | |
108 | for (size_t i = 0; i < m_file_data.size(); ++i) | |
109 | delete m_file_data[i]; | |
110 | m_file_data.clear(); | |
111 | Free(mycomp); | |
112 | Free(mycomp_name); | |
113 | mycomp = mycomp_name = NULL; | |
114 | } | |
115 | ||
116 | FileData::FileData(const char *file_name) | |
117 | { | |
118 | m_file_name = mcopystr(file_name); | |
119 | } | |
120 | ||
121 | FileData::~FileData() | |
122 | { | |
123 | Free(m_file_name); | |
124 | m_file_name = NULL; | |
125 | for (size_t i = 0; i < m_function_data.size(); ++i) | |
126 | delete m_function_data[i]; | |
127 | for (size_t i = 0; i < m_line_data.size(); ++i) | |
128 | delete m_line_data[i]; | |
129 | m_function_data.clear(); | |
130 | m_line_data.clear(); | |
131 | } | |
132 | ||
133 | void FileData::reset() | |
134 | { | |
135 | for (size_t i = 0; i < m_function_data.size(); ++i) | |
136 | m_function_data[i]->reset(); | |
137 | for (size_t i = 0; i < m_line_data.size(); ++i) | |
138 | m_line_data[i]->reset(); | |
139 | } | |
140 | ||
141 | size_t FileData::has_function_name(const char *function_name) | |
142 | { | |
143 | size_t i = 0; | |
144 | for (; i < m_function_data.size(); ++i) | |
145 | if (!strcmp(function_name, m_function_data[i]->get_name())) | |
146 | return static_cast<int>(i); | |
147 | return i; | |
148 | } | |
149 | ||
150 | size_t FileData::has_line_no(int line_no) | |
151 | { | |
152 | size_t i = 0; | |
153 | for (; i < m_line_data.size(); ++i) | |
154 | if (line_no == m_line_data[i]->get_no()) | |
155 | return static_cast<int>(i); | |
156 | return i; | |
157 | } | |
158 | ||
159 | void FileData::inc_function(const char *function_name, int /*line_no*/) | |
160 | { | |
161 | size_t i = has_function_name(function_name); | |
162 | if (i == m_function_data.size()) | |
163 | m_function_data.push_back(new FunctionData(function_name)); | |
164 | ++(*m_function_data[i]); | |
165 | } | |
166 | ||
167 | void FileData::inc_line(int line_no) | |
168 | { | |
169 | size_t i = has_line_no(line_no); | |
170 | if (i == m_line_data.size()) | |
171 | m_line_data.push_back(new LineData(line_no)); | |
172 | ++(*m_line_data[i]); | |
173 | } | |
174 | ||
175 | void FileData::init_function(const char *function_name) | |
176 | { | |
177 | size_t i = has_function_name(function_name); | |
178 | if (i == m_function_data.size()) m_function_data.push_back(new FunctionData(function_name)); | |
179 | } | |
180 | ||
181 | void FileData::init_line(int line_no) | |
182 | { | |
183 | size_t i = has_line_no(line_no); | |
184 | if (i == m_line_data.size()) m_line_data.push_back(new LineData(line_no)); | |
185 | } | |
186 | ||
187 | void TCov::pid_check() | |
188 | { | |
189 | pid_t p = getpid(); | |
190 | if (mypid != p) { | |
191 | mypid = p; | |
192 | Free(mycomp); | |
193 | Free(mycomp_name); | |
194 | mycomp = NULL; | |
195 | mycomp_name = NULL; | |
196 | mycomp = comp(); | |
197 | mycomp_name = comp(TRUE); | |
198 | for (size_t i = 0; i < m_file_data.size(); ++i) | |
199 | m_file_data[i]->reset(); | |
200 | } | |
201 | } | |
202 | ||
203 | void TCov::hit(const char *file_name, int line_no, const char *function_name) | |
204 | { | |
205 | pid_check(); | |
206 | size_t i = has_file_name(file_name); | |
207 | if (i == m_file_data.size()) | |
208 | m_file_data.push_back(new FileData(file_name)); | |
209 | if (function_name) | |
210 | m_file_data[i]->inc_function(function_name, line_no); | |
211 | m_file_data[i]->inc_line(line_no); | |
212 | } | |
213 | ||
214 | void TCov::init_file_lines(const char *file_name, const int line_nos[], size_t line_nos_len) | |
215 | { | |
216 | pid_check(); | |
217 | size_t i = has_file_name(file_name); | |
218 | if (i == m_file_data.size()) | |
219 | m_file_data.push_back(new FileData(file_name)); | |
220 | for (size_t j = 0; j < line_nos_len; ++j) | |
221 | m_file_data[i]->init_line(line_nos[j]); | |
222 | } | |
223 | ||
224 | void TCov::init_file_functions(const char *file_name, const char *function_names[], size_t function_names_len) | |
225 | { | |
226 | pid_check(); | |
227 | size_t i = has_file_name(file_name); | |
228 | if (i == m_file_data.size()) | |
229 | m_file_data.push_back(new FileData(file_name)); | |
230 | for (size_t j = 0; j < function_names_len; ++j) | |
231 | m_file_data[i]->init_function(function_names[j]); | |
232 | } |