Add automatic tests for Tick Processor, take two.

Now tests can be run from any directory. Location of test data is now determined using test file location provided by 'testcfg.py' script.

Tested under Linux, Mac, and Windows.

Review URL: http://codereview.chromium.org/155161


git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@2407 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent b8eb6189
...@@ -29,10 +29,12 @@ import test ...@@ -29,10 +29,12 @@ import test
import os import os
from os.path import join, dirname, exists from os.path import join, dirname, exists
import re import re
import tempfile
FLAGS_PATTERN = re.compile(r"//\s+Flags:(.*)") FLAGS_PATTERN = re.compile(r"//\s+Flags:(.*)")
FILES_PATTERN = re.compile(r"//\s+Files:(.*)") FILES_PATTERN = re.compile(r"//\s+Files:(.*)")
SELF_SCRIPT_PATTERN = re.compile(r"//\s+Env: TEST_FILE_NAME")
class MjsunitTestCase(test.TestCase): class MjsunitTestCase(test.TestCase):
...@@ -42,6 +44,7 @@ class MjsunitTestCase(test.TestCase): ...@@ -42,6 +44,7 @@ class MjsunitTestCase(test.TestCase):
self.file = file self.file = file
self.config = config self.config = config
self.mode = mode self.mode = mode
self.self_script = False
def GetLabel(self): def GetLabel(self):
return "%s %s" % (self.mode, self.GetName()) return "%s %s" % (self.mode, self.GetName())
...@@ -55,19 +58,43 @@ class MjsunitTestCase(test.TestCase): ...@@ -55,19 +58,43 @@ class MjsunitTestCase(test.TestCase):
flags_match = FLAGS_PATTERN.search(source) flags_match = FLAGS_PATTERN.search(source)
if flags_match: if flags_match:
result += flags_match.group(1).strip().split() result += flags_match.group(1).strip().split()
files_match = FILES_PATTERN.search(source);
additional_files = [] additional_files = []
if files_match: files_match = FILES_PATTERN.search(source);
additional_files += files_match.group(1).strip().split() # Accept several lines of 'Files:'
while True:
if files_match:
additional_files += files_match.group(1).strip().split()
files_match = FILES_PATTERN.search(source, files_match.end())
else:
break
for a_file in additional_files: for a_file in additional_files:
result.append(join(dirname(self.config.root), '..', a_file)) result.append(join(dirname(self.config.root), '..', a_file))
framework = join(dirname(self.config.root), 'mjsunit', 'mjsunit.js') framework = join(dirname(self.config.root), 'mjsunit', 'mjsunit.js')
if SELF_SCRIPT_PATTERN.search(source):
result.append(self.CreateSelfScript())
result += [framework, self.file] result += [framework, self.file]
return result return result
def GetSource(self): def GetSource(self):
return open(self.file).read() return open(self.file).read()
def CreateSelfScript(self):
(fd_self_script, self_script) = tempfile.mkstemp(suffix=".js")
def MakeJsConst(name, value):
return "var %(name)s=\'%(value)s\';\n" % \
{'name': name, \
'value': value.replace('\\', '\\\\').replace('\'', '\\\'') }
try:
os.write(fd_self_script, MakeJsConst('TEST_FILE_NAME', self.file))
except IOError, e:
test.PrintError("write() " + str(e))
os.close(fd_self_script)
self.self_script = self_script
return self_script
def Cleanup(self):
if self.self_script:
test.CheckedUnlink(self.self_script)
class MjsunitTestConfiguration(test.TestConfiguration): class MjsunitTestConfiguration(test.TestConfiguration):
......
Statistical profiling result from v8.log, (13 ticks, 2 unaccounted, 0 excluded).
[Unknown]:
ticks total nonlib name
2 15.4%
[Shared libraries]:
ticks total nonlib name
2 15.4% 0.0% /lib32/libm-2.7.so
1 7.7% 0.0% ffffe000-fffff000
[JavaScript]:
ticks total nonlib name
1 7.7% 10.0% LazyCompile: exp native math.js:41
[C++]:
ticks total nonlib name
2 15.4% 20.0% v8::internal::Runtime_Math_exp(v8::internal::Arguments)
1 7.7% 10.0% v8::internal::JSObject::LocalLookupRealNamedProperty(v8::internal::String*, v8::internal::LookupResult*)
1 7.7% 10.0% v8::internal::HashTable<v8::internal::StringDictionaryShape, v8::internal::String*>::FindEntry(v8::internal::String*)
1 7.7% 10.0% fegetexcept
1 7.7% 10.0% exp
[GC]:
ticks total nonlib name
0 0.0%
[Bottom up (heavy) profile]:
Note: percentage shows a share of a particular caller in the total
amount of its parent calls.
Callers occupying less than 2.0% are not shown.
ticks parent name
2 15.4% v8::internal::Runtime_Math_exp(v8::internal::Arguments)
2 100.0% LazyCompile: exp native math.js:41
2 100.0% Script: exp.js
2 15.4% /lib32/libm-2.7.so
2 100.0% LazyCompile: exp native math.js:41
2 100.0% Script: exp.js
1 7.7% v8::internal::JSObject::LocalLookupRealNamedProperty(v8::internal::String*, v8::internal::LookupResult*)
1 100.0% Script: exp.js
1 7.7% v8::internal::HashTable<v8::internal::StringDictionaryShape, v8::internal::String*>::FindEntry(v8::internal::String*)
1 100.0% Script: exp.js
1 7.7% ffffe000-fffff000
1 7.7% fegetexcept
1 100.0% LazyCompile: exp native math.js:41
1 100.0% Script: exp.js
1 7.7% exp
1 100.0% LazyCompile: exp native math.js:41
1 100.0% Script: exp.js
1 7.7% LazyCompile: exp native math.js:41
1 100.0% Script: exp.js
Statistical profiling result from v8.log, (13 ticks, 0 unaccounted, 13 excluded).
[Shared libraries]:
ticks total nonlib name
[JavaScript]:
ticks total nonlib name
[C++]:
ticks total nonlib name
[GC]:
ticks total nonlib name
0 0.0%
[Bottom up (heavy) profile]:
Note: percentage shows a share of a particular caller in the total
amount of its parent calls.
Callers occupying less than 2.0% are not shown.
ticks parent name
Statistical profiling result from v8.log, (13 ticks, 2 unaccounted, 0 excluded).
[Shared libraries]:
ticks total nonlib name
2 18.2% 0.0% /lib32/libm-2.7.so
1 9.1% 0.0% ffffe000-fffff000
[JavaScript]:
ticks total nonlib name
1 9.1% 12.5% LazyCompile: exp native math.js:41
[C++]:
ticks total nonlib name
2 18.2% 25.0% v8::internal::Runtime_Math_exp(v8::internal::Arguments)
1 9.1% 12.5% v8::internal::JSObject::LocalLookupRealNamedProperty(v8::internal::String*, v8::internal::LookupResult*)
1 9.1% 12.5% v8::internal::HashTable<v8::internal::StringDictionaryShape, v8::internal::String*>::FindEntry(v8::internal::String*)
1 9.1% 12.5% fegetexcept
1 9.1% 12.5% exp
[GC]:
ticks total nonlib name
0 0.0%
[Bottom up (heavy) profile]:
Note: percentage shows a share of a particular caller in the total
amount of its parent calls.
Callers occupying less than 2.0% are not shown.
ticks parent name
2 18.2% v8::internal::Runtime_Math_exp(v8::internal::Arguments)
2 100.0% LazyCompile: exp native math.js:41
2 100.0% Script: exp.js
2 18.2% /lib32/libm-2.7.so
2 100.0% LazyCompile: exp native math.js:41
2 100.0% Script: exp.js
1 9.1% v8::internal::JSObject::LocalLookupRealNamedProperty(v8::internal::String*, v8::internal::LookupResult*)
1 100.0% Script: exp.js
1 9.1% v8::internal::HashTable<v8::internal::StringDictionaryShape, v8::internal::String*>::FindEntry(v8::internal::String*)
1 100.0% Script: exp.js
1 9.1% ffffe000-fffff000
1 9.1% fegetexcept
1 100.0% LazyCompile: exp native math.js:41
1 100.0% Script: exp.js
1 9.1% exp
1 100.0% LazyCompile: exp native math.js:41
1 100.0% Script: exp.js
1 9.1% LazyCompile: exp native math.js:41
1 100.0% Script: exp.js
shared-library,"shell",0x08048000,0x081ee000
shared-library,"/lib32/libm-2.7.so",0xf7db6000,0xf7dd9000
shared-library,"ffffe000-fffff000",0xffffe000,0xfffff000
profiler,"begin",1
code-creation,Stub,0xf540a100,474,"CEntryStub"
code-creation,Script,0xf541cd80,736,"exp.js"
code-creation,Stub,0xf541d0e0,47,"RuntimeStub_Math_exp"
code-creation,LazyCompile,0xf541d120,145,"exp native math.js:41"
code-creation,LoadIC,0xf541d280,117,"j"
code-creation,LoadIC,0xf541d360,63,"i"
tick,0x80f82d1,0xffdfe880,0,0xf541ce5c
tick,0x80f89a1,0xffdfecf0,0,0xf541ce5c
tick,0x8123b5c,0xffdff1a0,0,0xf541d1a1,0xf541ceea
tick,0x8123b65,0xffdff1a0,0,0xf541d1a1,0xf541ceea
tick,0xf541d2be,0xffdff1e4,0
tick,0xf541d320,0xffdff1dc,0
tick,0xf541d384,0xffdff1d8,0
tick,0xf7db94da,0xffdff0ec,0,0xf541d1a1,0xf541ceea
tick,0xf7db951c,0xffdff0f0,0,0xf541d1a1,0xf541ceea
tick,0xf7dbc508,0xffdff14c,0,0xf541d1a1,0xf541ceea
tick,0xf7dbff21,0xffdff198,0,0xf541d1a1,0xf541ceea
tick,0xf7edec90,0xffdff0ec,0,0xf541d1a1,0xf541ceea
tick,0xffffe402,0xffdff488,0
profiler,"end"
Statistical profiling result from v8.log, (13 ticks, 2 unaccounted, 0 excluded).
[Unknown]:
ticks total nonlib name
2 15.4%
[Shared libraries]:
ticks total nonlib name
2 15.4% 0.0% /lib32/libm-2.7.so
1 7.7% 0.0% ffffe000-fffff000
[JavaScript]:
ticks total nonlib name
1 7.7% 10.0% LoadIC: j
1 7.7% 10.0% LoadIC: i
1 7.7% 10.0% LazyCompile: exp native math.js:41
[C++]:
ticks total nonlib name
2 15.4% 20.0% v8::internal::Runtime_Math_exp(v8::internal::Arguments)
1 7.7% 10.0% v8::internal::JSObject::LocalLookupRealNamedProperty(v8::internal::String*, v8::internal::LookupResult*)
1 7.7% 10.0% v8::internal::HashTable<v8::internal::StringDictionaryShape, v8::internal::String*>::FindEntry(v8::internal::String*)
1 7.7% 10.0% fegetexcept
1 7.7% 10.0% exp
[GC]:
ticks total nonlib name
0 0.0%
[Bottom up (heavy) profile]:
Note: percentage shows a share of a particular caller in the total
amount of its parent calls.
Callers occupying less than 2.0% are not shown.
ticks parent name
2 15.4% v8::internal::Runtime_Math_exp(v8::internal::Arguments)
2 100.0% LazyCompile: exp native math.js:41
2 100.0% Script: exp.js
2 15.4% /lib32/libm-2.7.so
2 100.0% LazyCompile: exp native math.js:41
2 100.0% Script: exp.js
1 7.7% v8::internal::JSObject::LocalLookupRealNamedProperty(v8::internal::String*, v8::internal::LookupResult*)
1 100.0% Script: exp.js
1 7.7% v8::internal::HashTable<v8::internal::StringDictionaryShape, v8::internal::String*>::FindEntry(v8::internal::String*)
1 100.0% Script: exp.js
1 7.7% ffffe000-fffff000
1 7.7% fegetexcept
1 100.0% LazyCompile: exp native math.js:41
1 100.0% Script: exp.js
1 7.7% exp
1 100.0% LazyCompile: exp native math.js:41
1 100.0% Script: exp.js
1 7.7% LoadIC: j
1 7.7% LoadIC: i
1 7.7% LazyCompile: exp native math.js:41
1 100.0% Script: exp.js
This diff is collapsed.
...@@ -20,4 +20,5 @@ fi ...@@ -20,4 +20,5 @@ fi
$d8_exec $tools_path/splaytree.js $tools_path/codemap.js \ $d8_exec $tools_path/splaytree.js $tools_path/codemap.js \
$tools_path/csvparser.js $tools_path/consarray.js \ $tools_path/csvparser.js $tools_path/consarray.js \
$tools_path/profile.js $tools_path/profile_view.js \ $tools_path/profile.js $tools_path/profile_view.js \
$tools_path/logreader.js $tools_path/tickprocessor.js -- $@ 2>/dev/null $tools_path/logreader.js $tools_path/tickprocessor.js \
$tools_path/tickprocessor-driver.js -- $@ 2>/dev/null
...@@ -356,11 +356,15 @@ class TestCase(object): ...@@ -356,11 +356,15 @@ class TestCase(object):
def RunCommand(self, command): def RunCommand(self, command):
full_command = self.context.processor(command) full_command = self.context.processor(command)
output = Execute(full_command, self.context, self.context.timeout) output = Execute(full_command, self.context, self.context.timeout)
self.Cleanup()
return TestOutput(self, full_command, output) return TestOutput(self, full_command, output)
def Run(self): def Run(self):
return self.RunCommand(self.GetCommand()) return self.RunCommand(self.GetCommand())
def Cleanup(self):
return
class TestOutput(object): class TestOutput(object):
...@@ -473,6 +477,13 @@ def PrintError(str): ...@@ -473,6 +477,13 @@ def PrintError(str):
sys.stderr.write('\n') sys.stderr.write('\n')
def CheckedUnlink(name):
try:
os.unlink(name)
except OSError, e:
PrintError("os.unlink() " + str(e))
def Execute(args, context, timeout=None): def Execute(args, context, timeout=None):
(fd_out, outname) = tempfile.mkstemp() (fd_out, outname) = tempfile.mkstemp()
(fd_err, errname) = tempfile.mkstemp() (fd_err, errname) = tempfile.mkstemp()
...@@ -487,11 +498,6 @@ def Execute(args, context, timeout=None): ...@@ -487,11 +498,6 @@ def Execute(args, context, timeout=None):
os.close(fd_err) os.close(fd_err)
output = file(outname).read() output = file(outname).read()
errors = file(errname).read() errors = file(errname).read()
def CheckedUnlink(name):
try:
os.unlink(name)
except OSError, e:
PrintError("os.unlink() " + str(e))
CheckedUnlink(outname) CheckedUnlink(outname)
CheckedUnlink(errname) CheckedUnlink(errname)
return CommandOutput(exit_code, timed_out, output, errors) return CommandOutput(exit_code, timed_out, output, errors)
......
// Copyright 2009 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Tick Processor's code flow.
function processArguments(args) {
var processor = new ArgumentsProcessor(args);
if (processor.parse()) {
return processor.result();
} else {
processor.printUsageAndExit();
}
}
var params = processArguments(arguments);
var tickProcessor = new TickProcessor(
params.platform == 'unix' ? new UnixCppEntriesProvider(params.nm) :
new WindowsCppEntriesProvider(),
params.separateIc,
params.ignoreUnknown,
params.stateFilter);
tickProcessor.processLogFile(params.logFileName);
tickProcessor.printStatistics();
...@@ -288,7 +288,11 @@ TickProcessor.prototype.printStatistics = function() { ...@@ -288,7 +288,11 @@ TickProcessor.prototype.printStatistics = function() {
function padLeft(s, len) { function padLeft(s, len) {
s = s.toString(); s = s.toString();
if (s.length < len) { if (s.length < len) {
s = (new Array(len - s.length + 1).join(' ')) + s; var padLength = len - s.length;
if (!(padLength in padLeft)) {
padLeft[padLength] = new Array(padLength + 1).join(' ');
}
s = padLeft[padLength] + s;
} }
return s; return s;
}; };
...@@ -511,25 +515,11 @@ WindowsCppEntriesProvider.prototype.unmangleName = function(name) { ...@@ -511,25 +515,11 @@ WindowsCppEntriesProvider.prototype.unmangleName = function(name) {
}; };
function padRight(s, len) { function ArgumentsProcessor(args) {
s = s.toString(); this.args_ = args;
if (s.length < len) { this.result_ = ArgumentsProcessor.DEFAULTS;
s = s + (new Array(len - s.length + 1).join(' '));
}
return s;
};
function processArguments(args) { this.argsDispatch_ = {
var result = {
logFileName: 'v8.log',
platform: 'unix',
stateFilter: null,
ignoreUnknown: false,
separateIc: false,
nm: 'nm'
};
var argsDispatch = {
'-j': ['stateFilter', TickProcessor.VmStates.JS, '-j': ['stateFilter', TickProcessor.VmStates.JS,
'Show only ticks from JS VM state'], 'Show only ticks from JS VM state'],
'-g': ['stateFilter', TickProcessor.VmStates.GC, '-g': ['stateFilter', TickProcessor.VmStates.GC,
...@@ -551,63 +541,82 @@ function processArguments(args) { ...@@ -551,63 +541,82 @@ function processArguments(args) {
'--nm': ['nm', 'nm', '--nm': ['nm', 'nm',
'Specify the \'nm\' executable to use (e.g. --nm=/my_dir/nm)'] 'Specify the \'nm\' executable to use (e.g. --nm=/my_dir/nm)']
}; };
argsDispatch['--js'] = argsDispatch['-j']; this.argsDispatch_['--js'] = this.argsDispatch_['-j'];
argsDispatch['--gc'] = argsDispatch['-g']; this.argsDispatch_['--gc'] = this.argsDispatch_['-g'];
argsDispatch['--compiler'] = argsDispatch['-c']; this.argsDispatch_['--compiler'] = this.argsDispatch_['-c'];
argsDispatch['--other'] = argsDispatch['-o']; this.argsDispatch_['--other'] = this.argsDispatch_['-o'];
argsDispatch['--external'] = argsDispatch['-e']; this.argsDispatch_['--external'] = this.argsDispatch_['-e'];
};
function printUsageAndExit() {
print('Cmdline args: [options] [log-file-name]\n' +
'Default log file name is "v8.log".\n');
print('Options:');
for (var arg in argsDispatch) {
var synonims = [arg];
var dispatch = argsDispatch[arg];
for (var synArg in argsDispatch) {
if (arg !== synArg && dispatch === argsDispatch[synArg]) {
synonims.push(synArg);
delete argsDispatch[synArg];
}
}
print(' ' + padRight(synonims.join(', '), 20) + dispatch[2]);
}
quit(2);
}
while (args.length) { ArgumentsProcessor.DEFAULTS = {
var arg = args[0]; logFileName: 'v8.log',
platform: 'unix',
stateFilter: null,
ignoreUnknown: false,
separateIc: false,
nm: 'nm'
};
ArgumentsProcessor.prototype.parse = function() {
while (this.args_.length) {
var arg = this.args_[0];
if (arg.charAt(0) != '-') { if (arg.charAt(0) != '-') {
break; break;
} }
args.shift(); this.args_.shift();
var userValue = null; var userValue = null;
var eqPos = arg.indexOf('='); var eqPos = arg.indexOf('=');
if (eqPos != -1) { if (eqPos != -1) {
userValue = arg.substr(eqPos + 1); userValue = arg.substr(eqPos + 1);
arg = arg.substr(0, eqPos); arg = arg.substr(0, eqPos);
} }
if (arg in argsDispatch) { if (arg in this.argsDispatch_) {
var dispatch = argsDispatch[arg]; var dispatch = this.argsDispatch_[arg];
result[dispatch[0]] = userValue == null ? dispatch[1] : userValue; this.result_[dispatch[0]] = userValue == null ? dispatch[1] : userValue;
} else { } else {
printUsageAndExit(); return false;
} }
} }
if (args.length >= 1) { if (this.args_.length >= 1) {
result.logFileName = args.shift(); this.result_.logFileName = this.args_.shift();
} }
return result; return true;
}; };
var params = processArguments(arguments); ArgumentsProcessor.prototype.result = function() {
var tickProcessor = new TickProcessor( return this.result_;
params.platform == 'unix' ? new UnixCppEntriesProvider(params.nm) : };
new WindowsCppEntriesProvider(),
params.separateIc,
params.ignoreUnknown, ArgumentsProcessor.prototype.printUsageAndExit = function() {
params.stateFilter);
tickProcessor.processLogFile(params.logFileName); function padRight(s, len) {
tickProcessor.printStatistics(); s = s.toString();
if (s.length < len) {
s = s + (new Array(len - s.length + 1).join(' '));
}
return s;
}
print('Cmdline args: [options] [log-file-name]\n' +
'Default log file name is "' +
ArgumentsProcessor.DEFAULTS.logFileName + '".\n');
print('Options:');
for (var arg in this.argsDispatch_) {
var synonims = [arg];
var dispatch = this.argsDispatch_[arg];
for (var synArg in this.argsDispatch_) {
if (arg !== synArg && dispatch === this.argsDispatch_[synArg]) {
synonims.push(synArg);
delete this.argsDispatch_[synArg];
}
}
print(' ' + padRight(synonims.join(', '), 20) + dispatch[2]);
}
quit(2);
};
...@@ -2,4 +2,4 @@ ...@@ -2,4 +2,4 @@
SET tools_dir=%~dp0 SET tools_dir=%~dp0
%tools_dir%..\d8 %tools_dir%splaytree.js %tools_dir%codemap.js %tools_dir%csvparser.js %tools_dir%consarray.js %tools_dir%profile.js %tools_dir%profile_view.js %tools_dir%logreader.js %tools_dir%tickprocessor.js -- --windows %* %tools_dir%..\d8 %tools_dir%splaytree.js %tools_dir%codemap.js %tools_dir%csvparser.js %tools_dir%consarray.js %tools_dir%profile.js %tools_dir%profile_view.js %tools_dir%logreader.js %tools_dir%tickprocessor.js %tools_dir%tickprocessor-driver.js -- --windows %*
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment