Home | History | Annotate | Download | only in jstemplate
      1 // Copyright 2006 Google Inc.
      2 //
      3 // Licensed under the Apache License, Version 2.0 (the "License");
      4 // you may not use this file except in compliance with the License.
      5 // You may obtain a copy of the License at
      6 //
      7 // http://www.apache.org/licenses/LICENSE-2.0
      8 //
      9 // Unless required by applicable law or agreed to in writing, software
     10 // distributed under the License is distributed on an "AS IS" BASIS,
     11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
     12 // implied. See the License for the specific language governing
     13 // permissions and limitations under the License.
     14 /**
     15  * @pageoverview Some logic for the jstemplates test pages.
     16  *
     17  * @author Steffen Meschkat (mesch (a] google.com)
     18  */
     19 
     20 
     21 function elem(id) {
     22   return document.getElementById(id);
     23 }
     24 
     25 /**
     26  * Are we actively profiling JstProcessor?
     27  * @type boolean
     28  */
     29 var profiling = false;
     30 
     31 logHtml = function(html) {
     32   elem('log').innerHTML += html + '<br/>';
     33 };
     34 
     35 
     36 /**
     37  * Initializer for interactive test: copies the value from the actual
     38  * template HTML into a text area to make the HTML source visible.
     39  */
     40 function jsinit() {
     41   elem('template').value = elem('tc').innerHTML;
     42 }
     43 
     44 
     45 /**
     46  * Interactive test.
     47  *
     48  * @param {boolean} reprocess If true, reprocesses the output of the
     49  * previous invocation.
     50  */
     51 function jstest(reprocess) {
     52   var jstext = elem('js').value;
     53   var input = jsEval(jstext);
     54   var t;
     55   if (reprocess) {
     56     t = elem('out');
     57   } else {
     58     elem('tc').innerHTML = elem('template').value;
     59     t = jstGetTemplate('t');
     60     elem('out').innerHTML = '';
     61     elem('out').appendChild(t);
     62   }
     63   if (profiling) Profiler.reset();
     64   jstProcess(new JsEvalContext(input), t);
     65   if (profiling) Profiler.dump();
     66   elem('html').value = elem('out').innerHTML;
     67 }
     68 
     69 
     70 /**
     71  * Performance test: jst initial processing.
     72  *
     73  * @param {Object} data Test data to apply the template to.
     74  */
     75 function perf1(data) {
     76   elem('out').innerHTML = '';
     77   var t = jstGetTemplate('t1');
     78   elem('out').appendChild(t);
     79   if (profiling) Profiler.reset();
     80   jstProcess(new JsEvalContext(data), t);
     81   if (profiling) Profiler.dump();
     82 }
     83 
     84 
     85 /**
     86  * Performance test: jst reprocessing or previous processing output.
     87  *
     88  * @param {Object} data Test data to apply the template to.
     89  */
     90 function perf1a(data) {
     91   if (profiling) Profiler.reset();
     92   jstProcess(new JsEvalContext(data), elemOrDie('out'));
     93   if (profiling) Profiler.dump();
     94 }
     95 
     96 
     97 /**
     98  * Performance test: jst initial processing, with display:none during
     99  * processing.
    100  *
    101  * @param {Object} data Test data to apply the template to.
    102  */
    103 function perf1b(data) {
    104   var o = elem('out');
    105   o.innerHTML = '';
    106   var t = jstGetTemplate('t1');
    107   o.appendChild(t);
    108   displayNone(o);
    109   if (profiling) Profiler.reset();
    110   jstProcess(new JsEvalContext(data), t);
    111   if (profiling) Profiler.dump();
    112   displayDefault(o);
    113 }
    114 
    115 
    116 /**
    117  * Performance test: create output procedurally as string and assign
    118  * to innerHTML.
    119  *
    120  * @param {Object} data Test data to apply the template to.
    121  */
    122 function perf2(data) {
    123   var t = [];
    124   t.push("<table><tr><th>item</th><th>label</th><th>address</th></tr>");
    125   for (var i = 0; i < data.entries.length; ++i) {
    126     var e = data.entries[i];
    127     t.push("<tr><td>" + i + "</td><td>" + e.label + "</td><td>" +
    128            e.address + "</td></tr>");
    129   }
    130   t.push("</table>");
    131   elem("out").innerHTML = t.join('');
    132 }
    133 
    134 
    135 /**
    136  * A test runner for a test. Does the timing. @constructor
    137  *
    138  * @param {number} times number of iterations the test is executed.
    139  * @param {Function} test The test to execute.
    140  * @param {Function} result Function will be called with the execution
    141  * time as argument.
    142  */
    143 function TestRun(times, test, result) {
    144   this.count_ = 0;
    145   this.times_ = times;
    146   this.test_ = test;
    147   this.result_ = result;
    148   this.start_ = (new Date).valueOf();
    149   this.run_();
    150 }
    151 
    152 
    153 /**
    154  * Executes the test run.
    155  */
    156 TestRun.prototype.run_ = function() {
    157   if (this.count_ < this.times_) {
    158     this.test_(this.count_);
    159     this.count_ += 1;
    160     objectSetTimeout(this, this.run_, 0);
    161   } else {
    162     this.stop_ = (new Date).valueOf();
    163     this.result_(this.stop_ - this.start_);
    164   }
    165 };
    166 
    167 
    168 /**
    169  * Creates a testrun function for test count invocations of function
    170  * f, whose runtime will be output to the element with is given in
    171  * result.
    172  *
    173  * @param {Object} data The test data object.
    174  * @param {Function} f
    175  * @param {number} count
    176  * @param {string} result
    177 */
    178 function createTestRun(count, test) {
    179   var data = {
    180     entries: []
    181   };
    182   for (var i = 0; i < count; ++i) {
    183     data.entries.push({ label: "label" + i, address: "address" + i });
    184   }
    185   // This function is passed to the TimeoutSequence, and receives the
    186   // TimeoutSequence as argument on invocation.
    187   return function(s) {
    188     new TestRun(1, function(i) {
    189       window[test](data);
    190     }, function(time) {
    191       elem(test + '-' + count).innerHTML = time + 'ms';
    192       s.run();
    193     });
    194   };
    195 }
    196 
    197 /**
    198  * Runs all tests the given number of times. Invoked from the HTML page.
    199  *
    200  * @param {number} count
    201  */
    202 function jsperf(count) {
    203   elemOrDie('log').innerHTML = '';
    204   profiling = !!elemOrDie('profile').checked;
    205   if (profiling && !JstProcessor.profiling_) {
    206     JstProcessor.profiling_ = true;
    207     Profiler.monitorAll(proto(JstProcessor), false);
    208   }
    209 
    210   var s = new TimeoutSequence(null, null, true);
    211 
    212   s.add(createTestRun(count, "perf1"));
    213   s.add(createTestRun(count, "perf1b"));
    214   s.add(createTestRun(count, "perf1a"));
    215   s.add(createTestRun(count, "perf2"));
    216 
    217   s.run();
    218 }
    219 
    220 function run(test, count) {
    221   var data = {
    222     entries: []
    223   };
    224   for (var i = 0; i < count; ++i) {
    225     data.entries.push({ label: "label" + i, address: "address" + i });
    226   }
    227   new TestRun(1, function() {
    228     window[test](data);
    229   }, function(time) {
    230     elem(test + '-' + count).innerHTML = time + 'ms';
    231   });
    232 }
    233