Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
T
test262
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Container Registry
Model registry
Operate
Environments
Monitor
Incidents
Service Desk
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
pmaksimo
test262
Commits
84fe57d3
Commit
84fe57d3
authored
13 years ago
by
Mark Miller
Browse files
Options
Downloads
Patches
Plain Diff
Adding Sputnik's command-line runner to Google's contributions, in
preparation for deriving a test262 command-line runner.
parent
274b5514
No related branches found
Branches containing commit
No related tags found
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
external/contributions/Google/sputniktests/tools/sputnik.py
+524
-0
524 additions, 0 deletions
external/contributions/Google/sputniktests/tools/sputnik.py
with
524 additions
and
0 deletions
external/contributions/Google/sputniktests/tools/sputnik.py
0 → 100644
+
524
−
0
View file @
84fe57d3
#!/usr/bin/python
# Copyright 2009 the Sputnik authors. All rights reserved.
# This code is governed by the BSD license found in the LICENSE file.
import
logging
import
optparse
import
os
from
os
import
path
import
platform
import
re
import
subprocess
import
sys
import
tempfile
import
time
class
SputnikError
(
Exception
):
def
__init__
(
self
,
message
):
self
.
message
=
message
def
ReportError
(
s
):
raise
SputnikError
(
s
)
def
BuildOptions
():
result
=
optparse
.
OptionParser
()
result
.
add_option
(
"
--command
"
,
default
=
None
,
help
=
"
The command-line to run
"
)
result
.
add_option
(
"
--tests
"
,
default
=
path
.
abspath
(
'
.
'
),
help
=
"
Path to the tests
"
)
result
.
add_option
(
"
--cat
"
,
default
=
False
,
action
=
"
store_true
"
,
help
=
"
Print test source code
"
)
result
.
add_option
(
"
--summary
"
,
default
=
False
,
action
=
"
store_true
"
,
help
=
"
Print summary after running tests
"
)
result
.
add_option
(
"
--full-summary
"
,
default
=
False
,
action
=
"
store_true
"
,
help
=
"
Print summary and test output after running tests
"
)
result
.
add_option
(
"
--enable-strict-mode
"
,
default
=
False
,
action
=
"
store_true
"
,
help
=
"
Run the mode also in ES5 strict mode
"
)
return
result
def
ValidateOptions
(
options
):
if
not
options
.
command
:
ReportError
(
"
A --command must be specified.
"
)
if
not
path
.
exists
(
options
.
tests
):
ReportError
(
"
Couldn
'
t find test path
'
%s
'"
%
options
.
tests
)
_PLACEHOLDER_PATTERN
=
re
.
compile
(
r
"
\{\{(\w+)\}\}
"
)
_INCLUDE_PATTERN
=
re
.
compile
(
r
"
\$INCLUDE\(\"(.*)\"\);
"
)
_SPECIAL_CALL_PATTERN
=
re
.
compile
(
r
"
\$([A-Z]+)(?=\()
"
)
_SPECIAL_CALLS
=
{
'
ERROR
'
:
'
testFailed
'
,
'
FAIL
'
:
'
testFailed
'
,
'
PRINT
'
:
'
testPrint
'
}
def
IsWindows
():
p
=
platform
.
system
()
return
(
p
==
'
Windows
'
)
or
(
p
==
'
Microsoft
'
)
def
StripHeader
(
str
):
while
str
.
startswith
(
'
//
'
)
and
"
\n
"
in
str
:
str
=
str
[
str
.
index
(
"
\n
"
)
+
1
:]
return
str
.
lstrip
()
class
TempFile
(
object
):
def
__init__
(
self
,
suffix
=
""
,
prefix
=
"
tmp
"
,
text
=
False
):
self
.
suffix
=
suffix
self
.
prefix
=
prefix
self
.
text
=
text
self
.
fd
=
None
self
.
name
=
None
self
.
is_closed
=
False
self
.
Open
()
def
Open
(
self
):
(
self
.
fd
,
self
.
name
)
=
tempfile
.
mkstemp
(
suffix
=
self
.
suffix
,
prefix
=
self
.
prefix
,
text
=
self
.
text
)
def
Write
(
self
,
str
):
os
.
write
(
self
.
fd
,
str
)
def
Read
(
self
):
f
=
file
(
self
.
name
)
result
=
f
.
read
()
f
.
close
()
return
result
def
Close
(
self
):
if
not
self
.
is_closed
:
self
.
is_closed
=
True
os
.
close
(
self
.
fd
)
def
Dispose
(
self
):
try
:
self
.
Close
()
os
.
unlink
(
self
.
name
)
except
OSError
,
e
:
logging
.
error
(
"
Error disposing temp file: %s
"
,
str
(
e
))
class
TestResult
(
object
):
def
__init__
(
self
,
exit_code
,
stdout
,
stderr
,
case
):
self
.
exit_code
=
exit_code
self
.
stdout
=
stdout
self
.
stderr
=
stderr
self
.
case
=
case
def
ReportOutcome
(
self
,
long_format
):
name
=
self
.
case
.
GetName
()
if
self
.
HasUnexpectedOutcome
():
if
self
.
case
.
IsNegative
():
print
"
%s was expected to fail but didn
'
t
"
%
name
elif
(
self
.
case
.
strict_mode
and
self
.
case
.
IsStrictModeNegative
()):
print
"
%s was expected to fail in strict mode, but didn
'
t
"
%
name
else
:
if
long_format
:
print
"
=== %s failed ===
"
%
name
else
:
print
"
%s:
"
%
name
out
=
self
.
stdout
.
strip
()
if
len
(
out
)
>
0
:
print
"
--- output ---
"
print
out
err
=
self
.
stderr
.
strip
()
if
len
(
err
)
>
0
:
print
"
--- errors ---
"
print
err
if
long_format
:
print
"
===
"
elif
self
.
case
.
IsNegative
():
print
"
%s failed as expected
"
%
name
elif
self
.
case
.
strict_mode
:
if
self
.
case
.
IsStrictModeNegative
():
print
"
%s failed in strict mode as expected
"
%
name
else
:
print
"
%s passed in strict mode
"
%
name
else
:
print
"
%s passed
"
%
name
def
HasFailed
(
self
):
return
self
.
exit_code
!=
0
def
HasUnexpectedOutcome
(
self
):
if
self
.
case
.
IsNegative
():
return
not
self
.
HasFailed
()
if
self
.
case
.
IsStrictModeNegative
():
return
not
self
.
HasFailed
()
else
:
return
self
.
HasFailed
()
class
TestCase
(
object
):
def
__init__
(
self
,
suite
,
name
,
full_path
,
strict_mode
=
False
):
self
.
suite
=
suite
self
.
name
=
name
self
.
full_path
=
full_path
self
.
contents
=
None
self
.
is_negative
=
None
self
.
strict_mode
=
strict_mode
self
.
is_strict_mode_negative
=
None
def
GetName
(
self
):
return
path
.
join
(
*
self
.
name
)
def
GetPath
(
self
):
return
self
.
name
def
GetRawContents
(
self
):
if
self
.
contents
is
None
:
f
=
open
(
self
.
full_path
)
self
.
contents
=
f
.
read
()
f
.
close
()
return
self
.
contents
def
IsNegative
(
self
):
if
self
.
is_negative
is
None
:
self
.
is_negative
=
(
"
@negative
"
in
self
.
GetRawContents
())
return
self
.
is_negative
def
IsStrictModeNegative
(
self
):
if
self
.
strict_mode
and
self
.
is_strict_mode_negative
is
None
:
self
.
is_strict_mode_negative
=
(
"
@strict_mode_negative
"
in
self
.
GetRawContents
())
return
self
.
is_strict_mode_negative
def
GetSource
(
self
):
source
=
self
.
suite
.
GetInclude
(
"
framework.js
"
,
False
)
source
+=
StripHeader
(
self
.
GetRawContents
())
def
IncludeFile
(
match
):
return
self
.
suite
.
GetInclude
(
match
.
group
(
1
))
source
=
_INCLUDE_PATTERN
.
sub
(
IncludeFile
,
source
)
def
SpecialCall
(
match
):
key
=
match
.
group
(
1
)
return
_SPECIAL_CALLS
.
get
(
key
,
match
.
group
(
0
))
if
self
.
strict_mode
:
source
=
'"
use strict
"
;
\n
var strict_mode = true;
\n
'
+
_SPECIAL_CALL_PATTERN
.
sub
(
SpecialCall
,
source
)
else
:
source
=
"
var strict_mode = false;
\n
"
+
_SPECIAL_CALL_PATTERN
.
sub
(
SpecialCall
,
source
)
return
source
def
InstantiateTemplate
(
self
,
template
,
params
):
def
GetParameter
(
match
):
key
=
match
.
group
(
1
)
return
params
.
get
(
key
,
match
.
group
(
0
))
return
_PLACEHOLDER_PATTERN
.
sub
(
GetParameter
,
template
)
def
RunTestIn
(
self
,
command_template
,
tmp
):
tmp
.
Write
(
self
.
GetSource
())
tmp
.
Close
()
command
=
self
.
InstantiateTemplate
(
command_template
,
{
'
path
'
:
tmp
.
name
})
(
code
,
out
,
err
)
=
self
.
Execute
(
command
)
return
TestResult
(
code
,
out
,
err
,
self
)
def
Execute
(
self
,
command
):
if
IsWindows
():
args
=
'"
%s
"'
%
command
else
:
args
=
command
.
split
(
"
"
)
stdout
=
TempFile
(
prefix
=
"
sputnik-out-
"
)
stderr
=
TempFile
(
prefix
=
"
sputnik-err-
"
)
try
:
logging
.
info
(
"
exec: %s
"
,
str
(
args
))
process
=
subprocess
.
Popen
(
args
,
shell
=
IsWindows
(),
stdout
=
stdout
.
fd
,
stderr
=
stderr
.
fd
)
code
=
process
.
wait
()
out
=
stdout
.
Read
()
err
=
stderr
.
Read
()
finally
:
stdout
.
Dispose
()
stderr
.
Dispose
()
return
(
code
,
out
,
err
)
def
Run
(
self
,
command_template
):
tmp
=
TempFile
(
suffix
=
"
.js
"
,
prefix
=
"
sputnik-
"
,
text
=
True
)
try
:
result
=
self
.
RunTestIn
(
command_template
,
tmp
)
finally
:
tmp
.
Dispose
()
return
result
def
Print
(
self
):
print
self
.
GetSource
()
class
ProgressIndicator
(
object
):
def
__init__
(
self
,
count
):
self
.
count
=
count
self
.
succeeded
=
0
self
.
failed
=
0
self
.
failed_tests
=
[]
def
HasRun
(
self
,
result
):
result
.
ReportOutcome
(
True
)
if
result
.
HasUnexpectedOutcome
():
self
.
failed
+=
1
self
.
failed_tests
.
append
(
result
)
else
:
self
.
succeeded
+=
1
def
MakePlural
(
n
):
if
(
n
==
1
):
return
(
n
,
""
)
else
:
return
(
n
,
"
s
"
)
class
TestSuite
(
object
):
def
__init__
(
self
,
root
,
stric_mode
):
self
.
test_root
=
path
.
join
(
root
,
'
tests
'
,
'
Conformance
'
)
self
.
lib_root
=
path
.
join
(
root
,
'
lib
'
)
self
.
strict_mode
=
stric_mode
self
.
include_cache
=
{
}
def
Validate
(
self
):
if
not
path
.
exists
(
self
.
test_root
):
ReportError
(
"
No test repository found
"
)
if
not
path
.
exists
(
self
.
lib_root
):
ReportError
(
"
No test library found
"
)
def
IsHidden
(
self
,
path
):
return
path
.
startswith
(
'
.
'
)
or
path
==
'
CVS
'
def
IsTestCase
(
self
,
path
):
return
path
.
endswith
(
'
.js
'
)
def
ShouldRun
(
self
,
rel_path
,
tests
):
if
len
(
tests
)
==
0
:
return
True
for
test
in
tests
:
if
test
in
rel_path
:
return
True
return
False
def
GetTimeZoneInfoInclude
(
self
):
dst_attribs
=
GetDaylightSavingsAttribs
()
if
not
dst_attribs
:
return
None
lines
=
[]
for
key
in
sorted
(
dst_attribs
.
keys
()):
lines
.
append
(
'
var $DST_%s = %s;
'
%
(
key
,
str
(
dst_attribs
[
key
])))
localtz
=
time
.
timezone
/
-
3600
lines
.
append
(
'
var $LocalTZ = %i;
'
%
localtz
)
return
"
\n
"
.
join
(
lines
)
def
GetSpecialInclude
(
self
,
name
):
if
name
==
"
environment.js
"
:
return
self
.
GetTimeZoneInfoInclude
()
else
:
return
None
def
GetInclude
(
self
,
name
,
strip_header
=
True
):
key
=
(
name
,
strip_header
)
if
not
key
in
self
.
include_cache
:
value
=
self
.
GetSpecialInclude
(
name
)
if
value
:
self
.
include_cache
[
key
]
=
value
else
:
static
=
path
.
join
(
self
.
lib_root
,
name
)
if
path
.
exists
(
static
):
f
=
open
(
static
)
contents
=
f
.
read
()
if
strip_header
:
contents
=
StripHeader
(
contents
)
self
.
include_cache
[
key
]
=
contents
+
"
\n
"
f
.
close
()
else
:
self
.
include_cache
[
key
]
=
""
return
self
.
include_cache
[
key
]
def
EnumerateTests
(
self
,
tests
):
logging
.
info
(
"
Listing tests in %s
"
,
self
.
test_root
)
cases
=
[]
for
root
,
dirs
,
files
in
os
.
walk
(
self
.
test_root
):
for
f
in
[
x
for
x
in
dirs
if
self
.
IsHidden
(
x
)]:
dirs
.
remove
(
f
)
dirs
.
sort
()
for
f
in
sorted
(
files
):
if
self
.
IsTestCase
(
f
):
full_path
=
path
.
join
(
root
,
f
)
if
full_path
.
startswith
(
self
.
test_root
):
rel_path
=
full_path
[
len
(
self
.
test_root
)
+
1
:]
else
:
logging
.
warning
(
"
Unexpected path %s
"
,
full_path
)
rel_path
=
full_path
if
self
.
ShouldRun
(
rel_path
,
tests
):
basename
=
path
.
basename
(
full_path
)[:
-
3
]
name
=
rel_path
.
split
(
path
.
sep
)[:
-
1
]
+
[
basename
]
cases
.
append
(
TestCase
(
self
,
name
,
full_path
,
False
))
if
self
.
strict_mode
:
cases
.
append
(
TestCase
(
self
,
name
,
full_path
,
True
))
logging
.
info
(
"
Done listing tests
"
)
return
cases
def
PrintSummary
(
self
,
progress
):
print
print
"
=== Summary ===
"
count
=
progress
.
count
succeeded
=
progress
.
succeeded
failed
=
progress
.
failed
print
"
- Ran %i test%s
"
%
MakePlural
(
count
)
if
progress
.
failed
==
0
:
print
"
- All tests succeeded
"
else
:
percent
=
((
100.0
*
succeeded
)
/
count
,)
print
"
- Passed %i test%s (%.1f%%)
"
%
(
MakePlural
(
succeeded
)
+
percent
)
percent
=
((
100.0
*
failed
)
/
count
,)
print
"
- Failed %i test%s (%.1f%%)
"
%
(
MakePlural
(
failed
)
+
percent
)
positive
=
[
c
for
c
in
progress
.
failed_tests
if
not
c
.
case
.
IsNegative
()]
negative
=
[
c
for
c
in
progress
.
failed_tests
if
c
.
case
.
IsNegative
()]
if
len
(
positive
)
>
0
:
print
print
"
Failed tests
"
for
result
in
positive
:
print
"
%s
"
%
result
.
case
.
GetName
()
if
len
(
negative
)
>
0
:
print
print
"
Expected to fail but passed ---
"
for
result
in
negative
:
print
"
%s
"
%
result
.
case
.
GetName
()
def
PrintFailureOutput
(
self
,
progress
):
for
result
in
progress
.
failed_tests
:
print
result
.
ReportOutcome
(
False
)
def
Run
(
self
,
command_template
,
tests
,
print_summary
,
full_summary
):
if
not
"
{{path}}
"
in
command_template
:
command_template
+=
"
{{path}}
"
cases
=
self
.
EnumerateTests
(
tests
)
if
len
(
cases
)
==
0
:
ReportError
(
"
No tests to run
"
)
progress
=
ProgressIndicator
(
len
(
cases
))
for
case
in
cases
:
result
=
case
.
Run
(
command_template
)
progress
.
HasRun
(
result
)
if
print_summary
:
self
.
PrintSummary
(
progress
)
if
full_summary
:
self
.
PrintFailureOutput
(
progress
)
else
:
print
print
"
Use --full-summary to see output from failed tests
"
print
def
Print
(
self
,
tests
):
cases
=
self
.
EnumerateTests
(
tests
)
if
len
(
cases
)
>
0
:
cases
[
0
].
Print
()
def
GetDaylightSavingsTimes
():
# Is the given floating-point time in DST?
def
IsDst
(
t
):
return
time
.
localtime
(
t
)[
-
1
]
# Binary search to find an interval between the two times no greater than
# delta where DST switches, returning the midpoint.
def
FindBetween
(
start
,
end
,
delta
):
while
end
-
start
>
delta
:
middle
=
(
end
+
start
)
/
2
if
IsDst
(
middle
)
==
IsDst
(
start
):
start
=
middle
else
:
end
=
middle
return
(
start
+
end
)
/
2
now
=
time
.
time
()
one_month
=
(
30
*
24
*
60
*
60
)
# First find a date with different daylight savings. To avoid corner cases
# we try four months before and after today.
after
=
now
+
4
*
one_month
before
=
now
-
4
*
one_month
if
IsDst
(
now
)
==
IsDst
(
before
)
and
IsDst
(
now
)
==
IsDst
(
after
):
logging
.
warning
(
"
Was unable to determine DST info.
"
)
return
None
# Determine when the change occurs between now and the date we just found
# in a different DST.
if
IsDst
(
now
)
!=
IsDst
(
before
):
first
=
FindBetween
(
before
,
now
,
1
)
else
:
first
=
FindBetween
(
now
,
after
,
1
)
# Determine when the change occurs between three and nine months from the
# first.
second
=
FindBetween
(
first
+
3
*
one_month
,
first
+
9
*
one_month
,
1
)
# Find out which switch is into and which if out of DST
if
IsDst
(
first
-
1
)
and
not
IsDst
(
first
+
1
):
start
=
second
end
=
first
else
:
start
=
first
end
=
second
return
(
start
,
end
)
def
GetDaylightSavingsAttribs
():
times
=
GetDaylightSavingsTimes
()
if
not
times
:
return
None
(
start
,
end
)
=
times
def
DstMonth
(
t
):
return
time
.
localtime
(
t
)[
1
]
-
1
def
DstHour
(
t
):
return
time
.
localtime
(
t
-
1
)[
3
]
+
1
def
DstSunday
(
t
):
if
time
.
localtime
(
t
)[
2
]
>
15
:
return
"'
last
'"
else
:
return
"'
first
'"
def
DstMinutes
(
t
):
return
(
time
.
localtime
(
t
-
1
)[
4
]
+
1
)
%
60
attribs
=
{
}
attribs
[
'
start_month
'
]
=
DstMonth
(
start
)
attribs
[
'
end_month
'
]
=
DstMonth
(
end
)
attribs
[
'
start_sunday
'
]
=
DstSunday
(
start
)
attribs
[
'
end_sunday
'
]
=
DstSunday
(
end
)
attribs
[
'
start_hour
'
]
=
DstHour
(
start
)
attribs
[
'
end_hour
'
]
=
DstHour
(
end
)
attribs
[
'
start_minutes
'
]
=
DstMinutes
(
start
)
attribs
[
'
end_minutes
'
]
=
DstMinutes
(
end
)
return
attribs
def
Main
():
parser
=
BuildOptions
()
(
options
,
args
)
=
parser
.
parse_args
()
ValidateOptions
(
options
)
test_suite
=
TestSuite
(
options
.
tests
,
options
.
enable_strict_mode
)
test_suite
.
Validate
()
if
options
.
cat
:
test_suite
.
Print
(
args
)
else
:
test_suite
.
Run
(
options
.
command
,
args
,
options
.
summary
or
options
.
full_summary
,
options
.
full_summary
)
if
__name__
==
'
__main__
'
:
try
:
Main
()
sys
.
exit
(
0
)
except
SputnikError
,
e
:
print
"
Error: %s
"
%
e
.
message
sys
.
exit
(
1
)
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment