Home | History | Annotate | Download | only in jsp
      1 <%--
      2   ~ Copyright (c) 2016 Google Inc. All Rights Reserved.
      3   ~
      4   ~ Licensed under the Apache License, Version 2.0 (the "License"); you
      5   ~ may not use this file except in compliance with the License. You may
      6   ~ obtain a copy of the License at
      7   ~
      8   ~     http://www.apache.org/licenses/LICENSE-2.0
      9   ~
     10   ~ Unless required by applicable law or agreed to in writing, software
     11   ~ distributed under the License is distributed on an "AS IS" BASIS,
     12   ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
     13   ~ implied. See the License for the specific language governing
     14   ~ permissions and limitations under the License.
     15   --%>
     16 <%@ page contentType='text/html;charset=UTF-8' language='java' %>
     17 <%@ taglib prefix='fn' uri='http://java.sun.com/jsp/jstl/functions' %>
     18 <%@ taglib prefix='c' uri='http://java.sun.com/jsp/jstl/core'%>
     19 
     20 <html>
     21   <%@ include file="header.jsp" %>
     22   <link rel="stylesheet" href="/css/show_coverage.css">
     23   <script src="https://apis.google.com/js/api.js" type="text/javascript"></script>
     24   <body>
     25     <script type="text/javascript">
     26         var coverageVectors = ${coverageVectors};
     27         $(document).ready(function() {
     28             // Initialize AJAX for CORS
     29             $.ajaxSetup({
     30                 xhrFields : {
     31                     withCredentials: true
     32                 }
     33             });
     34 
     35             // Initialize auth2 client and scope for requests to Gerrit
     36             gapi.load('auth2', function() {
     37                 var auth2 = gapi.auth2.init({
     38                     client_id: ${clientId},
     39                     scope: ${gerritScope}
     40                 });
     41                 auth2.then(displayEntries);
     42             });
     43         });
     44 
     45         /* Open a window to Gerrit so that user can login.
     46            Minimize the previously clicked entry.
     47         */
     48         var gerritLogin = function(element) {
     49             window.open(${gerritURI}, "Ratting", "toolbar=0,status=0");
     50             element.click();
     51         }
     52 
     53         /* Loads source code for a particular entry and displays it with
     54            coverage information as the accordion entry expands.
     55         */
     56         var onClick = function() {
     57             // Remove source code from the accordion entry that was open before
     58             var self = $(this);
     59             var prev = self.parent().siblings('li.active');
     60             if (prev.length > 0) {
     61                 prev.find('.table-container').empty();
     62             }
     63             var url = self.parent().attr('url');
     64             var i = self.parent().attr('index');
     65             var container = self.parent().find('.table-container');
     66             container.html('<div class="center-align">Loading...</div>');
     67             if (self.parent().hasClass('active')) {
     68                 // Remove the code from display
     69                 container.empty();
     70             } else {
     71                 /* Fetch and display the code.
     72                    Note: a coverageVector may be shorter than sourceContents due
     73                    to non-executable (i.e. comments or language-specific syntax)
     74                    lines in the code. Trailing source lines that have no
     75                    coverage information are assumed to be non-executable.
     76                 */
     77                 $.ajax({
     78                     url: url,
     79                     dataType: 'text'
     80                 }).promise().done(function(src) {
     81                     src = atob(src);
     82                     if (!src) return;
     83                     srcLines = src.split('\n');
     84                     covered = 0;
     85                     total = 0;
     86                     var table = $('<table class="table"></table>');
     87                     var rows = srcLines.forEach(function(line, j) {
     88                         var count = coverageVectors[i][j];
     89                         var row = $('<tr></tr>');
     90                         if (typeof count == 'undefined' || count < 0) {
     91                             count = "--";
     92                         } else if (count == 0) {
     93                             row.addClass('uncovered');
     94                             total += 1;
     95                         } else {
     96                             row.addClass('covered');
     97                             total += 1;
     98                         }
     99                         row.append('<td class="count">' + String(count) + '</td>');
    100                         row.append('<td class="line_no">' + String(j+1) + '</td>');
    101                         code = $('<td class="code"></td>');
    102                         code.text(String(line));
    103                         code.appendTo(row);
    104                         row.appendTo(table);
    105                     });
    106                     container.empty();
    107                     container.append(table);
    108                 }).fail(function(error) {
    109                     if (error.status == 0) {  // origin error, refresh cookie
    110                         container.empty();
    111                         container.html('<div class="center-align">' +
    112                                        '<span class="login-button">' +
    113                                        'Click to authorize Gerrit access' +
    114                                        '</span></div>');
    115                         container.find('.login-button').click(function() {
    116                             gerritLogin(self);
    117                         });
    118                     } else {
    119                         container.html('<div class="center-align">' +
    120                                        'Not found.</div>');
    121                     }
    122                 });
    123             }
    124         }
    125 
    126         /* Appends a row to the display with test name and aggregated coverage
    127            information. On expansion, source code is loaded with coverage
    128            highlighted by calling 'onClick'.
    129         */
    130         var displayEntries = function() {
    131             var sourceFilenames = ${sourceFiles};
    132             var sectionMap = ${sectionMap};
    133             var gerritURI = ${gerritURI};
    134             var projects = ${projects};
    135             var commits = ${commits};
    136             var indicators = ${indicators};
    137             Object.keys(sectionMap).forEach(function(section) {
    138                 var indices = sectionMap[section];
    139                 var html = String();
    140                 indices.forEach(function(i) {
    141                     var url = gerritURI + '/projects/' +
    142                               encodeURIComponent(projects[i]) + '/commits/' +
    143                               encodeURIComponent(commits[i]) + '/files/' +
    144                               encodeURIComponent(sourceFilenames[i]) +
    145                               '/content';
    146                     html += '<li url="' + url + '" index="' + i + '">' +
    147                             '<div class="collapsible-header">' +
    148                             '<i class="material-icons">library_books</i>' +
    149                             '<b>' + projects[i] + '/</b>' +
    150                             sourceFilenames[i] + indicators[i] + '</div>';
    151                     html += '<div class="collapsible-body row">' +
    152                             '<div class="html-container">' +
    153                             '<div class="table-container"></div>' +
    154                             '</div></div></li>';
    155                 });
    156                 if (html) {
    157                     html = '<h4 class="section-title"><b>Coverage:</b> ' +
    158                            section + '</h4><ul class="collapsible popout" ' +
    159                            'data-collapsible="accordion">' + html + '</ul>';
    160                     $('#coverage-container').append(html);
    161                 }
    162             });
    163             $('.collapsible.popout').collapsible({
    164                accordion : true
    165             }).find('.collapsible-header').click(onClick);
    166         }
    167     </script>
    168     <div id='coverage-container' class='wide container'>
    169     </div>
    170     <%@ include file="footer.jsp" %>
    171   </body>
    172 </html>
    173