blob: e6e38e24c1313b92823c4bfe384d0e856161942e [file] [log] [blame]
{% if table_entry_type == "Component" %}
<p>
&emsp;Filter: <input type="text" id="filter" size="30" /> (e.g. "crypto,VR")
</p>
{% endif %}
<table>
<thead>
<tr>
<th class="column-entry-bold">{{ table_entry_type }}</th>
<th class="column-entry-bold" onclick="sortTable(SORT_COLUMN.LINE)" title=
"Line coverage is the percentage of code lines which have been executed at least once. Only executable lines within function bodies are considered to be code lines.">
Line Coverage
</th>
<th class="column-entry-bold" onclick="sortTable(SORT_COLUMN.FUNCTION)" title=
"Function coverage is the percentage of functions which have been executed at least once. A function is considered to be executed if any of its instantiations are executed.">
Function Coverage
</th>
<th class="column-entry-bold" onclick="sortTable(SORT_COLUMN.REGION)" title=
"Region coverage is the percentage of code regions which have been executed at least once. A code region may span multiple lines (e.g in a large function body with no control flow). However, it's also possible for a single line to contain multiple code regions (e.g in 'return x || y &amp;&amp; z').">
Region Coverage
</th>
</tr>
</thead>
<tbody>
{% for entry in entries %}
<tr class="light-row">
<td>
{% if entry["is_dir"] == True %}
<pre><a href='{{ entry["href"] }}'>{{ entry["name"] }}/</a></pre>
{% else %}
<pre><a href='{{ entry["href"] }}'>{{ entry["name"] }}</a></pre>
{% endif %}
</td>
{% for feature in ("lines", "functions", "regions") %}
<td class='column-entry-{{ entry[feature]["color_class"] }}'>
<pre>{{ entry[feature]["percentage"] }}% ({{ entry[feature]["covered"] }}/{{ entry[feature]["total"] }})</pre>
</td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
{% if total_entry %}
<tfoot>
<tr class="light-row-bold">
<td>
<pre>Totals</pre>
</td>
{% for feature in ("lines", "functions", "regions") %}
<td class='column-entry-{{ total_entry[feature]["color_class"] }}'>
<pre>{{ total_entry[feature]["percentage"] }}% ({{ total_entry[feature]["covered"] }}/{{ total_entry[feature]["total"] }})</pre>
</td>
{% endfor %}
</tr>
</tfoot>
{% endif %}
</table>
<script>
const SORT_COLUMN = {
LINE: 2,
FUNCTION: 3,
REGION: 4,
}
const SORT_TYPES = {
UNSET: -1,
PERCENT: 0,
AGGREGATE: 1,
}
var SORT_ORDER = {
[SORT_COLUMN.LINE]: [SORT_TYPES.UNSET],
[SORT_COLUMN.FUNCTION]: [SORT_TYPES.UNSET],
[SORT_COLUMN.REGION]: [SORT_TYPES.UNSET],
}
function sortTable(columnNumber) {
SORT_ORDER[columnNumber] = ++SORT_ORDER[columnNumber] % 2;
let columnSortOrder = SORT_ORDER[columnNumber];
let tbody = document.getElementsByTagName("tbody")[0];
[].slice.call(tbody.rows).sort(function(a, b) {
let aColumn = a.cells[columnNumber-1].textContent;
let bColumn = b.cells[columnNumber-1].textContent;
let aColumnCompare, bColumnCompare;
if (columnSortOrder == SORT_TYPES.PERCENT) {
aColumnCompare = parseFloat(/([0-9.]+)%/.exec(aColumn)[1]);
bColumnCompare = parseFloat(/([0-9.]+)%/.exec(bColumn)[1]);
} else {
aColumnCompare = parseInt(/\/(\d+)/.exec(aColumn)[1]);
bColumnCompare = parseInt(/\/(\d+)/.exec(bColumn)[1]);
}
return (
aColumnCompare < bColumnCompare ? -1:
aColumnCompare > bColumnCompare ? 1 : 0);
}).forEach(function(value, index) {
tbody.appendChild(value);
});
}
{% if table_entry_type == "Component" %}
function filterInputChanged() {
let filter = document.getElementById("filter");
let filterString = filter.value;
// Update query paramater in URL.
let queryParams = new URLSearchParams(window.location.search);
queryParams.set('filter', filterString);
let newPath = window.location.pathname;
if (filterString)
newPath += '?' + queryParams.toString();
history.pushState(null, '', newPath);
filterRowsIfNeeded();
}
function filterRowsIfNeeded() {
let queryParams = new URLSearchParams(window.location.search);
let filterString = queryParams.get('filter') || "";
let filterValuesLower = filterString.toLowerCase().split(',');
let tbody = document.getElementsByTagName("tbody")[0];
let rows = tbody.getElementsByTagName("tr");
for (let row of rows) {
let td = row.getElementsByTagName("td");
let tdContent = row.innerText.toLowerCase();
// |match| should be true on empty search (show everything).
let match = !filterValuesLower;
for (let filterValueLower of filterValuesLower) {
if (tdContent.includes(filterValueLower)) {
match = true;
break
}
}
if (match && row.style.display == 'none')
row.style.display = 'table-row';
else if (!match)
row.style.display = 'none';
}
// Update filter value in input box (for cases when filter is provided
// as part of page load URL).
let filter = document.getElementById("filter");
if (filter.value != filterString)
filter.value = filterString;
}
window.onload = filterRowsIfNeeded;
var filter = document.getElementById("filter");
filter.onchange = filter.onkeyup = filterInputChanged;
{% endif %}
</script>