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@google.com) 18 */ 19 20 21function elem(id) { 22 return document.getElementById(id); 23} 24 25/** 26 * Are we actively profiling JstProcessor? 27 * @type boolean 28 */ 29var profiling = false; 30 31logHtml = 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 */ 40function 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 */ 51function 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 */ 75function 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 */ 90function 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 */ 103function 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 */ 122function 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 */ 143function 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 */ 156TestRun.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*/ 178function 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 */ 202function 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 220function 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