Home | History | Annotate | Download | only in src
      1 <!DOCTYPE HTML>
      2 <html>
      3 <!--
      4 Copyright (c) 2012 The Chromium Authors. All rights reserved.
      5 Use of this source code is governed by a BSD-style license that can be
      6 found in the LICENSE file.
      7 -->
      8 <head i18n-values="dir:textdirection;">
      9 <title>TimelineAnalysisView tests</title>
     10 <script src="base.js"></script>
     11 <style>
     12   .view {
     13     border: 1px solid black;
     14     margin: 10px;
     15   }
     16   .find-dialog {
     17     border: 1px solid black;
     18     margin: 10px;
     19   }
     20 </style>
     21 </head>
     22 <body>
     23   <script>
     24     base.require('unittest');
     25     base.require('tracing_controller');
     26     base.require('test_utils');
     27     base.require('model');
     28     base.require('importer.trace_event_importer');
     29     base.require('timeline_analysis_view');
     30     base.require('filter');
     31     base.require('tracks.counter_track');
     32     base.require('tracks.slice_track');
     33     base.require('tracks.thread_track');
     34     base.require('timeline_track_view'); /* TODO(nduca): reduce dependency */
     35   </script>
     36   <script>
     37     'use strict';
     38 
     39     var Counter = tracing.model.Counter;
     40     var Thread = tracing.model.Thread;
     41     var AnalysisView = tracing.TimelineAnalysisView;
     42     var Model = tracing.Model;
     43     var ThreadTrack = tracing.tracks.ThreadTrack;
     44     var Selection = tracing.Selection;
     45     var TitleFilter = tracing.TitleFilter;
     46     var CounterTrack = tracing.tracks.CounterTrack;
     47     var SliceTrack = tracing.tracks.SliceTrack;
     48     var newSliceNamed = test_utils.newSliceNamed;
     49     var newSliceCategory = test_utils.newSliceCategory;
     50 
     51     function createSelectionWithSingleSlice(withCategory) {
     52       var model = new Model();
     53       var t53 = model.getOrCreateProcess(52).getOrCreateThread(53);
     54       if (withCategory)
     55         t53.pushSlice(newSliceCategory('foo', 'b', 0, 0.002));
     56       else
     57         t53.pushSlice(newSliceNamed('b', 0, 0.002));
     58 
     59       var t53track = new ThreadTrack();
     60       t53track.thread = t53;
     61 
     62       var selection = new Selection();
     63       t53track.addAllObjectsMatchingFilterToSelection(
     64         new TitleFilter('b'), selection);
     65       assertEquals(1, selection.length);
     66 
     67       return selection;
     68     }
     69 
     70     function createSelectionWithTwoSlices() {
     71       var events = [
     72         {name: 'a', args: {}, pid: 52, ts: 520, cat: 'foo', tid: 53, ph: 'B'},
     73         {name: 'a', args: {}, pid: 52, ts: 560, cat: 'foo', tid: 53, ph: 'E'},
     74         {name: 'aa', args: {}, pid: 52, ts: 640, cat: 'foo', tid: 53, ph: 'B'},
     75         {name: 'aa', args: {}, pid: 52, ts: 700, cat: 'foo', tid: 53, ph: 'E'}
     76       ];
     77       var model = new Model(events);
     78 
     79       var t53track = new ThreadTrack();
     80       t53track.thread = model.processes[52].threads[53];
     81 
     82       var selection = new Selection();
     83       t53track.addAllObjectsMatchingFilterToSelection(
     84         new TitleFilter('a'), selection);
     85       assertEquals(2, selection.length);
     86 
     87       return selection;
     88     }
     89 
     90     function createSelectionWithTwoSlicesSameTitle() {
     91       var events = [
     92         {name: 'c', args: {}, pid: 52, ts: 620, cat: 'foo', tid: 53, ph: 'B'},
     93         {name: 'c', args: {}, pid: 52, ts: 660, cat: 'foo', tid: 53, ph: 'E'},
     94         {name: 'c', args: {}, pid: 52, ts: 740, cat: 'foo', tid: 53, ph: 'B'},
     95         {name: 'c', args: {}, pid: 52, ts: 800, cat: 'foo', tid: 53, ph: 'E'}
     96       ];
     97       var model = new Model(events);
     98 
     99       var t53track = new ThreadTrack();
    100       t53track.thread = model.processes[52].threads[53];
    101 
    102       var selection = new Selection();
    103       t53track.addAllObjectsMatchingFilterToSelection(
    104         new TitleFilter('c'), selection);
    105       assertEquals(2, selection.length);
    106 
    107       return selection;
    108     }
    109 
    110     function createSelectionWithCounters(numSamples) {
    111       if (numSamples > 2 || numSamples < 1)
    112         throw new Error('This function only supports 1 or 2 samples');
    113       var events = [
    114         {name: 'ctr', args: {'value': 0}, pid: 1, ts: 0, cat: 'foo', tid: 1,
    115          ph: 'C', id: 0},
    116         {name: 'ctr', args: {'value': 10}, pid: 1, ts: 10, cat: 'foo', tid: 1,
    117          ph: 'C', id: 0}
    118       ];
    119       var model = new Model(events);
    120       var p = model.processes[1];
    121       var ctr = model.processes[1].counters['foo.ctr[0]'];
    122       assertEquals('ctr[0]', ctr.name);
    123       assertEquals(2, ctr.numSamples);
    124       assertEquals(1, ctr.numSeries);
    125       assertArrayEquals([0, 0.01], ctr.timestamps);
    126       assertArrayEquals([0, 10], ctr.samples);
    127 
    128       var selection = new Selection();
    129       var t1track = new ThreadTrack();
    130       selection.addCounterSample(t1track, ctr, 1);
    131 
    132       if (numSamples == 1)
    133         return selection;
    134 
    135       selection.addCounterSample(t1track, ctr, 0);
    136       return selection;
    137     }
    138 
    139     function createSelectionWithTwoSeriesSingleCounter() {
    140       var events = [
    141         {name: 'ctr', args: {'bytesallocated': 0, 'bytesfree': 25}, pid: 1,
    142          ts: 0, cat: 'foo', tid: 1, ph: 'C', id: 0},
    143         {name: 'ctr', args: {'bytesallocated': 10, 'bytesfree': 15}, pid: 1,
    144          ts: 10, cat: 'foo', tid: 1, ph: 'C', id: 0},
    145         {name: 'ctr', args: {'bytesallocated': 20, 'bytesfree': 5}, pid: 1,
    146          ts: 20, cat: 'foo', tid: 1, ph: 'C', id: 0}
    147       ];
    148       var model = new Model(events);
    149       var p = model.processes[1];
    150       var ctr = model.processes[1].counters['foo.ctr[0]'];
    151       assertEquals('ctr[0]', ctr.name);
    152       assertEquals(3, ctr.numSamples);
    153       assertEquals(2, ctr.numSeries);
    154 
    155       var selection = new Selection();
    156       var t1track = new ThreadTrack();
    157       selection.addCounterSample(t1track, ctr, 1);
    158 
    159       return selection;
    160     }
    161 
    162     function createSelectionWithTwoSeriesTwoCounters() {
    163       var ctr1 = new Counter(null, 0, '', 'ctr1');
    164       ctr1.seriesNames.push('bytesallocated', 'bytesfree');
    165       ctr1.seriesColors.push(0, 1);
    166       ctr1.timestamps.push(0, 10, 20);
    167       ctr1.samples.push(0, 25, 10, 15, 20, 5);
    168 
    169       var ctr2 = new Counter(null, 0, '', 'ctr2');
    170       ctr2.seriesNames.push('bytesallocated', 'bytesfree');
    171       ctr2.seriesColors.push(0, 1);
    172       ctr2.timestamps.push(0, 10, 20);
    173       ctr2.samples.push(0, 25, 10, 15, 20, 5);
    174 
    175       var selection = new Selection();
    176       var t1track = new ThreadTrack();
    177       selection.addCounterSample(t1track, ctr1, 1);
    178       selection.addCounterSample(t1track, ctr2, 2);
    179 
    180       return selection;
    181     }
    182 
    183     function createSelectionWithTwoCountersDiffSeriesDiffHits() {
    184       var ctr1 = new Counter(null, 0, '', 'a');
    185       ctr1.seriesNames.push('bytesallocated');
    186       ctr1.seriesColors.push(0);
    187       ctr1.timestamps.push(0, 10, 20);
    188       ctr1.samples.push(0, 25, 10);
    189       assertEquals('a', ctr1.name);
    190       assertEquals(3, ctr1.numSamples);
    191       assertEquals(1, ctr1.numSeries);
    192 
    193       var ctr2 = new Counter(null, 0, '', 'b');
    194       ctr2.seriesNames.push('bytesallocated', 'bytesfree');
    195       ctr2.seriesColors.push(0, 1);
    196       ctr2.timestamps.push(0, 10, 20, 30);
    197       ctr2.samples.push(0, 25, 10, 15, 20, 5, 25, 0);
    198       assertEquals('b', ctr2.name);
    199       assertEquals(4, ctr2.numSamples);
    200       assertEquals(2, ctr2.numSeries);
    201 
    202       var selection = new Selection();
    203       var t1track = new ThreadTrack();
    204       selection.addCounterSample(t1track, ctr1, 1);
    205       selection.addCounterSample(t1track, ctr2, 2);
    206 
    207       return selection;
    208     }
    209 
    210     function createSelectionWithSingleSliceSingleCounter() {
    211       var model = new Model();
    212       var thread = model.getOrCreateProcess(1).getOrCreateThread(1);
    213       thread.pushSlice(newSliceNamed('b', 1, 5));
    214 
    215       var ctr1 = model.getOrCreateProcess(1).getOrCreateCounter('cat', 'ctr1');
    216       ctr1.seriesNames.push('bytesallocated', 'bytesfree');
    217       ctr1.seriesColors.push(0, 1);
    218       ctr1.timestamps.push(0, 10, 20);
    219       ctr1.samples.push(0, 25, 10, 15, 20, 5);
    220       assertEquals('ctr1', ctr1.name);
    221       assertEquals(3, ctr1.numSamples);
    222       assertEquals(2, ctr1.numSeries);
    223 
    224       var ctr1track = new CounterTrack();
    225       ctr1track.counter = ctr1;
    226 
    227       var threadTrack = new SliceTrack();
    228       threadTrack.slices = thread.slices;
    229 
    230       var selection = new Selection();
    231       selection.addCounterSample(ctr1track, ctr1, 1);
    232       threadTrack.addAllObjectsMatchingFilterToSelection(
    233         new TitleFilter('b'), selection);
    234       assertEquals(2, selection.length);
    235       return selection;
    236     }
    237 
    238     function createSelectionWithNormallyDistributedSamples(numSlices) {
    239       // Distance between start times is normally distributed, with mu = 16ms
    240       // and sigma = 3ms.
    241       var startTimes = [
    242         0, 18.4362262859, 32.5378088645, 44.8978868054,
    243         63.4772725504, 77.438888345, 92.0102867913, 99.6208686689,
    244         119.150576393, 137.54545468, 153.991587743, 175.456095568,
    245         193.395772651, 205.691644582, 218.740054982, 239.308480724,
    246         250.880949151, 268.528689601, 281.950478133, 296.791635722,
    247         315.862427391, 333.954888221, 342.392899581, 362.364373939,
    248         377.593380892, 392.296896748, 415.779941407, 435.517713864,
    249         454.581222491, 470.329018858, 488.37029095, 502.283017166,
    250         521.15141113, 534.36224697, 554.425018316, 574.89913248,
    251         589.60294439, 604.780562233, 615.481610668, 630.055628965,
    252         645.908449096, 661.776084055, 673.276049017, 689.776401428,
    253         704.440135004, 716.33262401, 732.380086528, 743.970715322,
    254         756.506690025, 772.391485532, 794.636984401, 803.801415494,
    255         819.006502926, 837.610127549, 854.551103283, 875.170613672,
    256         891.508235124, 905.263299017, 929.309555683, 943.417968804,
    257         957.289319239, 972.302910569, 986.669355637, 1002.71558868,
    258         1013.83359637, 1030.16840733, 1040.39503139, 1057.61583325,
    259         1075.64709686, 1086.67671319, 1100.4617455, 1118.4871842,
    260         1129.98143488, 1144.52318588, 1160.36966285, 1179.50049042,
    261         1195.03088169, 1215.98199401, 1226.66591838, 1245.83650314,
    262         1268.18058265, 1285.11047342, 1301.71570575, 1316.40723345,
    263         1329.94342488, 1343.7569577, 1358.28267513, 1371.17560308,
    264         1386.42247119, 1401.51767749, 1417.52489051, 1440.98712348,
    265         1457.80113781, 1475.66079406, 1494.64137536, 1509.52941903,
    266         1524.54762552, 1545.42960714, 1565.19444597, 1580.56308936,
    267         1596.72211651];
    268 
    269       var durations = [
    270         1.56308936, 1.4362262859, 1.5378088645, 1.8978868054,
    271         1.4772725504, 1.438888345, 1.0102867913, 1.6208686689,
    272         1.150576393, 1.54545468, 1.991587743, 1.456095568,
    273         1.395772651, 1.691644582, 1.740054982, 1.308480724,
    274         1.880949151, 1.528689601, 1.950478133, 1.791635722,
    275         1.862427391, 1.954888221, 1.392899581, 1.364373939,
    276         1.593380892, 1.296896748, 1.779941407, 1.517713864,
    277         1.581222491, 1.329018858, 1.37029095, 1.283017166,
    278         1.15141113, 1.36224697, 1.425018316, 1.89913248,
    279         1.60294439, 1.780562233, 1.481610668, 1.055628965,
    280         1.908449096, 1.776084055, 1.276049017, 1.776401428,
    281         1.440135004, 1.33262401, 1.380086528, 1.970715322,
    282         1.506690025, 1.391485532, 1.636984401, 1.801415494,
    283         1.006502926, 1.610127549, 1.551103283, 1.170613672,
    284         1.508235124, 1.263299017, 1.309555683, 1.417968804,
    285         1.289319239, 1.302910569, 1.669355637, 1.71558868,
    286         1.83359637, 1.16840733, 1.39503139, 1.61583325,
    287         1.64709686, 1.67671319, 1.4617455, 1.4871842,
    288         1.98143488, 1.52318588, 1.36966285, 1.50049042,
    289         1.03088169, 1.98199401, 1.66591838, 1.83650314,
    290         1.18058265, 1.11047342, 1.71570575, 1.40723345,
    291         1.94342488, 1.7569577, 1.28267513, 1.17560308,
    292         1.42247119, 1.51767749, 1.52489051, 1.98712348,
    293         1.80113781, 1.66079406, 1.64137536, 1.52941903,
    294         1.54762552, 1.42960714, 1.19444597, 1.56308936,
    295         1.72211651];
    296 
    297       var events = [];
    298 
    299       var model = new Model();
    300       var thread = model.getOrCreateProcess(52).getOrCreateThread(53);
    301 
    302       for (var i = 0; i < startTimes.length; ++i) {
    303         for (var j = 0; j < numSlices; ++j) {
    304           var name = 'slice' + String(numSlices - 1 - j);
    305           thread.slices.push(newSliceNamed(name, startTimes[i], durations[i]));
    306         }
    307       }
    308 
    309       var t53track = new ThreadTrack();
    310       t53track.thread = model.processes[52].threads[53];
    311 
    312       var selection = new Selection();
    313       t53track.addAllObjectsMatchingFilterToSelection(
    314         new TitleFilter('slice'), selection);
    315       assertEquals(101 * numSlices, selection.length);
    316 
    317       return selection;
    318     }
    319 
    320     function testAnalysisViewWithSingleSlice() {
    321       var selection = createSelectionWithSingleSlice();
    322 
    323       var analysisEl = new AnalysisView();
    324       analysisEl.selection = selection;
    325       this.addHTMLOutput(undefined, analysisEl);
    326     }
    327 
    328     function testAnalysisViewWithSingleSliceCategory() {
    329       var selection = createSelectionWithSingleSlice(true);
    330 
    331       var analysisEl = new AnalysisView();
    332       analysisEl.selection = selection;
    333       this.addHTMLOutput(undefined, analysisEl);
    334     }
    335 
    336     function testAnalysisViewWithMultipleSlices() {
    337       var selection = createSelectionWithTwoSlices();
    338 
    339       var analysisEl = new AnalysisView();
    340       analysisEl.selection = selection;
    341       this.addHTMLOutput(undefined, analysisEl);
    342     }
    343 
    344     function testAnalysisViewWithMultipleSlicesSameTitle() {
    345       var selection = createSelectionWithTwoSlicesSameTitle();
    346 
    347       var analysisEl = new AnalysisView();
    348       analysisEl.selection = selection;
    349       this.addHTMLOutput(undefined, analysisEl);
    350     }
    351 
    352     function testAnalysisViewWithSingleCounterWithTwoSeries() {
    353       var selection = createSelectionWithTwoSeriesSingleCounter();
    354 
    355       var analysisEl = new AnalysisView();
    356       analysisEl.selection = selection;
    357       this.addHTMLOutput(undefined, analysisEl);
    358     }
    359 
    360     function testAnalysisViewWithTwoCountersWithTwoSeries() {
    361       var selection = createSelectionWithTwoSeriesTwoCounters();
    362 
    363       var analysisEl = new AnalysisView();
    364       analysisEl.selection = selection;
    365       this.addHTMLOutput(undefined, analysisEl);
    366     }
    367 
    368     function testAnalysisViewWithSingleSliceSingleCounter() {
    369       var selection = createSelectionWithSingleSliceSingleCounter();
    370 
    371       var analysisEl = new AnalysisView();
    372       analysisEl.selection = selection;
    373       this.addHTMLOutput(undefined, analysisEl);
    374     }
    375 
    376     function testSelectionWithNormallyDistributedSamples() {
    377       var numSlices = 1;
    378       var selection = createSelectionWithNormallyDistributedSamples(numSlices);
    379 
    380       var analysisEl = new AnalysisView();
    381       analysisEl.selection = selection;
    382       this.addHTMLOutput(undefined, analysisEl);
    383     }
    384 
    385     function StubAnalysisResults() {
    386       this.tables = [];
    387     }
    388     StubAnalysisResults.prototype = {
    389       __proto__: Object.protoype,
    390 
    391       appendTable: function(parent, className) {
    392         var table = {
    393           className: className,
    394           rows: []
    395         };
    396         table.className = className;
    397         this.tables.push(table);
    398         return table;
    399       },
    400 
    401       appendTableHeader: function(table, label) {
    402         if (table.tableHeader)
    403           throw new Error('Only one summary header allowed.');
    404         table.tableHeader = label;
    405       },
    406 
    407       appendSummaryRow: function(table, label, opt_text) {
    408         table.rows.push({label: label,
    409                          text: opt_text});
    410       },
    411 
    412       appendSpacingRow: function(table) {
    413         table.rows.push({spacing: true});
    414       },
    415 
    416       appendSummaryRowTime: function(table, label, time) {
    417         table.rows.push({label: label,
    418                          time: time});
    419       },
    420 
    421       appendDataRow: function(table, label, duration, occurences, details) {
    422         table.rows.push({label: label,
    423                          duration: duration,
    424                          occurences: occurences,
    425                          details: details});
    426       }
    427     };
    428 
    429     function testAnalyzeSelectionWithSingleSlice() {
    430       var selection = createSelectionWithSingleSlice();
    431 
    432       var results = new StubAnalysisResults();
    433       tracing.analyzeSelection_(results, selection);
    434       assertEquals(1, results.tables.length);
    435       var table = results.tables[0];
    436       assertEquals('Selected slice:', table.tableHeader);
    437       assertEquals(3, table.rows.length);
    438 
    439       assertEquals('b', table.rows[0].text);
    440       assertEquals(0, table.rows[1].time);
    441       assertAlmostEquals(0.002, table.rows[2].time);
    442     }
    443 
    444     function testAnalyzeSelectionWithFalsyArgs() {
    445       var model = new Model();
    446       var t53 = model.getOrCreateProcess(52).getOrCreateThread(53);
    447       var slice = newSliceNamed('b', 0, 0.002);
    448       slice.args.bar = 0;
    449       slice.args.foo = false;
    450       t53.pushSlice(slice);
    451       var t53track = new ThreadTrack();
    452       t53track.thread = t53;
    453       var selection = new Selection();
    454       t53track.addAllObjectsMatchingFilterToSelection(
    455         new TitleFilter('b'), selection);
    456       assertEquals(1, selection.length);
    457 
    458       var analysisEl = new AnalysisView();
    459       analysisEl.selection = selection;
    460       this.addHTMLOutput(undefined, analysisEl);
    461       var rows = analysisEl.querySelectorAll('tr');
    462       assertEquals(rows.length, 7);
    463       assertEquals(' bar', rows[5].children[0].textContent);
    464       assertEquals('0', rows[5].children[1].textContent);
    465       assertEquals(' foo', rows[6].children[0].textContent);
    466       assertEquals('false', rows[6].children[1].textContent);
    467     }
    468 
    469     function testAnalyzeSelectionWithSingleSliceCategory() {
    470       var selection = createSelectionWithSingleSlice(true);
    471 
    472       var results = new StubAnalysisResults();
    473       tracing.analyzeSelection_(results, selection);
    474       assertEquals(1, results.tables.length);
    475       var table = results.tables[0];
    476       assertEquals('Selected slice:', table.tableHeader);
    477       assertEquals(4, table.rows.length);
    478 
    479       assertEquals('b', table.rows[0].text);
    480       assertEquals('foo', table.rows[1].text);
    481       assertEquals(0, table.rows[2].time);
    482       assertAlmostEquals(0.002, table.rows[3].time);
    483     }
    484 
    485     function testAnalyzeSelectionWithTwoSlices() {
    486       var selection = createSelectionWithTwoSlices();
    487 
    488       var results = new StubAnalysisResults();
    489       tracing.analyzeSelection_(results, selection);
    490       assertEquals(1, results.tables.length);
    491       var table = results.tables[0];
    492       assertEquals('Slices:', table.tableHeader);
    493       assertEquals(6, table.rows.length);
    494 
    495       assertEquals('a', table.rows[0].label);
    496       assertEquals(1, table.rows[0].occurences);
    497       assertAlmostEquals(0.04, table.rows[0].duration);
    498       assertEquals('aa', table.rows[1].label);
    499       assertEquals(1, table.rows[1].occurences);
    500       assertAlmostEquals(0.06, table.rows[1].duration);
    501       assertEquals('*Totals', table.rows[2].label);
    502       assertEquals(2, table.rows[2].occurences);
    503       assertAlmostEquals(0.1, table.rows[2].duration);
    504 
    505       assertEquals('Selection start', table.rows[4].label);
    506       assertAlmostEquals(0, table.rows[4].time);
    507 
    508       assertEquals('Selection extent', table.rows[5].label);
    509       assertAlmostEquals(0.18, table.rows[5].time);
    510     }
    511 
    512     function testAnalyzeSelectionWithTwoSlicesSameTitle() {
    513       var selection = createSelectionWithTwoSlicesSameTitle();
    514 
    515       var results = new StubAnalysisResults();
    516       tracing.analyzeSelection_(results, selection);
    517       assertEquals(1, results.tables.length);
    518       var table = results.tables[0];
    519 
    520       assertEquals('Slices:', table.tableHeader);
    521       assertEquals(5, table.rows.length);
    522 
    523       assertEquals('c', table.rows[0].label);
    524       assertEquals('2', table.rows[0].occurences);
    525       assertAlmostEquals(0.04, table.rows[0].details.min);
    526       assertAlmostEquals(0.05, table.rows[0].details.avg);
    527       assertAlmostEquals(0.06, table.rows[0].details.max);
    528       assertAlmostEquals(0.1, table.rows[0].duration);
    529       assertEquals('*Totals', table.rows[1].label);
    530       assertAlmostEquals(0.1, table.rows[1].duration);
    531       assertEquals('Selection start', table.rows[3].label);
    532       assertAlmostEquals(0, table.rows[3].time);
    533       assertEquals('Selection extent', table.rows[4].label);
    534       assertAlmostEquals(0.18, table.rows[4].time);
    535     }
    536 
    537     function testAnalyzeSelectionWithSingleCounter() {
    538       var selection = createSelectionWithCounters(1);
    539 
    540       var results = new StubAnalysisResults();
    541       tracing.analyzeSelection_(results, selection);
    542       assertEquals(1, results.tables.length);
    543       var table = results.tables[0];
    544       assertEquals('Selected counter:', table.tableHeader);
    545       assertEquals(3, table.rows.length);
    546 
    547       assertEquals('Title', table.rows[0].label);
    548       assertEquals('Timestamp', table.rows[1].label);
    549       assertEquals('value', table.rows[2].label);
    550       assertEquals(10, table.rows[2].text);
    551     }
    552 
    553     function testAnalyzeSelectionWithBasicTwoSeriesTwoCounters() {
    554       var selection = createSelectionWithTwoSeriesTwoCounters();
    555 
    556       var results = new StubAnalysisResults();
    557       tracing.analyzeSelection_(results, selection);
    558       assertEquals(1, results.tables.length);
    559       var table = results.tables[0];
    560       assertEquals('Counters:', table.tableHeader);
    561       assertEquals(4, table.rows.length);
    562 
    563       assertEquals('ctr1: bytesallocated', table.rows[0].label);
    564       assertEquals('ctr1: bytesfree', table.rows[1].label);
    565       assertEquals('ctr2: bytesallocated', table.rows[2].label);
    566       assertEquals('ctr2: bytesfree', table.rows[3].label);
    567     }
    568 
    569     function testAnalyzeSelectionWithComplexSeriesTwoCounters() {
    570       var selection = createSelectionWithTwoCountersDiffSeriesDiffHits();
    571 
    572       var results = new StubAnalysisResults();
    573       tracing.analyzeSelection_(results, selection);
    574       assertEquals(1, results.tables.length);
    575       var table = results.tables[0];
    576       assertEquals('Counters:', table.tableHeader);
    577       assertEquals(3, table.rows.length);
    578 
    579       assertEquals('a: bytesallocated', table.rows[0].label);
    580       assertEquals('b: bytesallocated', table.rows[1].label);
    581       assertEquals('b: bytesfree', table.rows[2].label);
    582     }
    583 
    584     function testAnalyzeSelectionWithCounterAndSlices() {
    585       var selection = createSelectionWithSingleSliceSingleCounter();
    586 
    587       var results = new StubAnalysisResults();
    588       tracing.analyzeSelection_(results, selection);
    589       assertEquals(2, results.tables.length);
    590       var sliceTable = results.tables[0];
    591       var counterTable = results.tables[1];
    592 
    593       assertEquals('Selected slice:', sliceTable.tableHeader);
    594       assertEquals(3, sliceTable.rows.length);
    595 
    596       assertEquals('Selected counter:', counterTable.tableHeader);
    597       assertEquals(4, counterTable.rows.length);
    598     }
    599 
    600     function testAnalyzeSelectionWithNormallyDistributedSamples() {
    601       var numSlices = 2;
    602       var selection = createSelectionWithNormallyDistributedSamples(numSlices);
    603 
    604       var results = new StubAnalysisResults();
    605       tracing.analyzeSelection_(results, selection);
    606       assertEquals(1, results.tables.length);
    607 
    608       assertEquals('slice0', results.tables[0].rows[0].label);
    609       assertEquals(
    610           63, Math.round(results.tables[0].rows[0].details.frequency));
    611       assertEquals(
    612           16, Math.round(results.tables[0].rows[0].details.frequency_stddev));
    613       assertEquals(
    614           250, Math.round(results.tables[0].rows[0].details.avg_stddev * 1000));
    615 
    616 
    617       assertEquals('slice1', results.tables[0].rows[1].label);
    618       assertEquals(
    619           63, Math.round(results.tables[0].rows[1].details.frequency));
    620       assertEquals(
    621           16, Math.round(results.tables[0].rows[1].details.frequency_stddev));
    622       assertEquals(
    623           250, Math.round(results.tables[0].rows[1].details.avg_stddev * 1000));
    624     }
    625   </script>
    626 </body>
    627 </html>
    628