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