From 078d1b4458dd429ac5afb33498ea69269b7a80c4 Mon Sep 17 00:00:00 2001 From: Seonghyun Kim Date: Thu, 29 Jun 2023 18:14:01 +0900 Subject: [PATCH] Update source and test driver for running test262 on windows Signed-off-by: Seonghyun Kim --- .github/workflows/es-actions.yml | 34 +++++--- src/util/SpinLock.h | 4 + third_party/GCutil | 2 +- tools/run-tests.py | 58 +++++++------ tools/test/test262/make_excludelist.py | 2 +- tools/test/test262/monkeyYaml.py | 29 ++++--- tools/test/test262/parseTestRecord.py | 6 +- tools/test/test262/test262.py | 114 ++++++++++++------------- 8 files changed, 137 insertions(+), 112 deletions(-) diff --git a/.github/workflows/es-actions.yml b/.github/workflows/es-actions.yml index 3fa379920..7e3624755 100644 --- a/.github/workflows/es-actions.yml +++ b/.github/workflows/es-actions.yml @@ -43,40 +43,52 @@ jobs: ninja -Cout/mac/x64 ./tools/run-tests.py --engine="./out/mac/x64/escargot" new-es - build-on-windows: + test-on-windows: runs-on: windows-2022 steps: - uses: actions/checkout@v3 with: submodules: true + - uses: szenius/set-timezone@v1.2 + with: + timezoneWindows: "Pacific Standard Time" - uses: lukka/get-cmake@latest - uses: GuillaumeFalourd/setup-windows10-sdk-action@v1.11 with: sdk-version: 20348 - - uses: ilammy/msvc-dev-cmd@v1.12.1 + - name: Copy octane + run: | + copy test\octane\*.js + dir + - uses: actions/checkout@v3 + - uses: actions/setup-python@v4 with: - arch: x86 - sdk: "10.0.20348.0" + python-version: '3.11' - name: Install msvc redist package run: | (new-object System.Net.WebClient).DownloadFile('https://github.com/abbodi1406/vcredist/releases/download/v0.73.0/VisualCppRedist_AIO_x86_x64.exe','VisualCppRedist_AIO_x86_x64.exe') .\VisualCppRedist_AIO_x86_x64.exe /y - - name: Copy octane - run: | - copy test\octane\*.js - dir + - uses: ilammy/msvc-dev-cmd@v1.12.1 + with: + arch: x86 + sdk: "10.0.20348.0" - name: Build Win32 Release run: | - CMake -G "Visual Studio 16 2019" -DCMAKE_SYSTEM_NAME=Windows -DCMAKE_SYSTEM_VERSION:STRING="10.0" -DCMAKE_SYSTEM_PROCESSOR=x86 -DESCARGOT_ARCH=x86 -DESCARGOT_MODE=release -Bout/win32_release_ninja/ -DESCARGOT_HOST=windows -DESCARGOT_OUTPUT=shell -DESCARGOT_LIBICU_SUPPORT=ON -DESCARGOT_LIBICU_SUPPORT_WITH_DLOPEN=OFF -DESCARGOT_TEST=ON -G Ninja -DCMAKE_C_COMPILER=cl -DCMAKE_CXX_COMPILER=cl -DCMAKE_BUILD_TYPE=release + CMake -G "Visual Studio 16 2019" -DCMAKE_SYSTEM_NAME=Windows -DCMAKE_SYSTEM_VERSION:STRING="10.0" -DCMAKE_SYSTEM_PROCESSOR=x86 -DESCARGOT_ARCH=x86 -DESCARGOT_MODE=release -Bout/win32_release_ninja/ -DESCARGOT_HOST=windows -DESCARGOT_OUTPUT=shell -DESCARGOT_LIBICU_SUPPORT=ON -DESCARGOT_LIBICU_SUPPORT_WITH_DLOPEN=OFF -DESCARGOT_THREADING=ON -DESCARGOT_TCO=ON -DESCARGOT_TEST=ON -G Ninja -DCMAKE_C_COMPILER=cl -DCMAKE_CXX_COMPILER=cl -DCMAKE_BUILD_TYPE=release CMake --build out/win32_release_ninja/ --config Release - .\out\win32_release_ninja\escargot.exe run.js + - name: Run test262 on win32 + run: | + set GC_FREE_SPACE_DIVISOR=1 + set PYTHONUTF8=1 + python tools\run-tests.py --engine=%cd%\out\win32_release_ninja\escargot.exe test262-without-intl402 + shell: cmd - uses: ilammy/msvc-dev-cmd@v1.12.1 with: arch: x64 sdk: "10.0.20348.0" - name: Build Win64 Release run: | - CMake -G "Visual Studio 16 2019" -DCMAKE_SYSTEM_NAME=Windows -DCMAKE_SYSTEM_VERSION:STRING="10.0" -DCMAKE_SYSTEM_PROCESSOR=x64 -DESCARGOT_ARCH=x64 -DESCARGOT_MODE=release -Bout/win64_release_ninja/ -DESCARGOT_HOST=windows -DESCARGOT_OUTPUT=shell -DESCARGOT_LIBICU_SUPPORT=ON -DESCARGOT_LIBICU_SUPPORT_WITH_DLOPEN=OFF -DESCARGOT_TEST=ON -G Ninja -DCMAKE_C_COMPILER=cl -DCMAKE_CXX_COMPILER=cl -DCMAKE_BUILD_TYPE=release + CMake -G "Visual Studio 16 2019" -DCMAKE_SYSTEM_NAME=Windows -DCMAKE_SYSTEM_VERSION:STRING="10.0" -DCMAKE_SYSTEM_PROCESSOR=x64 -DESCARGOT_ARCH=x64 -DESCARGOT_MODE=release -Bout/win64_release_ninja/ -DESCARGOT_HOST=windows -DESCARGOT_OUTPUT=shell -DESCARGOT_LIBICU_SUPPORT=ON -DESCARGOT_LIBICU_SUPPORT_WITH_DLOPEN=OFF -DESCARGOT_THREADING=ON -DESCARGOT_TCO=ON -DESCARGOT_TEST=ON -G Ninja -DCMAKE_C_COMPILER=cl -DCMAKE_CXX_COMPILER=cl -DCMAKE_BUILD_TYPE=release CMake --build out/win64_release_ninja/ --config Release .\out\win64_release_ninja\escargot.exe run.js - if: ${{ failure() }} diff --git a/src/util/SpinLock.h b/src/util/SpinLock.h index d2daf73c5..d005fa778 100644 --- a/src/util/SpinLock.h +++ b/src/util/SpinLock.h @@ -31,7 +31,11 @@ class SpinLock { public: SpinLock() +#if defined(COMPILER_MSVC) + : m_locked() +#else : m_locked(ATOMIC_FLAG_INIT) +#endif { } diff --git a/third_party/GCutil b/third_party/GCutil index 0d6fe0e6d..c4804a317 160000 --- a/third_party/GCutil +++ b/third_party/GCutil @@ -1 +1 @@ -Subproject commit 0d6fe0e6da3ef58b60554d425bf141f63997bc03 +Subproject commit c4804a317fa3cc481279f1724ede5c53439b06dc diff --git a/tools/run-tests.py b/tools/run-tests.py index 8c732241c..639008578 100755 --- a/tools/run-tests.py +++ b/tools/run-tests.py @@ -169,9 +169,7 @@ def run_internal_test(engine, arch): run(['python', 'driver.py', engine, 'internal-test-cases.txt'], cwd=INTERNAL_DIR) - -@runner('test262', default=True) -def run_test262(engine, arch): +def copy_test262_files(): TEST262_OVERRIDE_DIR = join(PROJECT_SOURCE_DIR, 'tools', 'test', 'test262') TEST262_DIR = join(PROJECT_SOURCE_DIR, 'test', 'test262') @@ -182,7 +180,11 @@ def run_test262(engine, arch): copy(join(TEST262_OVERRIDE_DIR, 'parseTestRecord.py'), join(TEST262_DIR, 'tools', 'packaging', 'parseTestRecord.py')) copy(join(TEST262_OVERRIDE_DIR, 'test262.py'), join(TEST262_DIR, 'tools', 'packaging', 'test262.py')) # for parallel running (we should re-implement this for es6 suite) - stdout = run(['pypy', join('tools', 'packaging', 'test262.py'), +@runner('test262', default=True) +def run_test262(engine, arch): + copy_test262_files() + TEST262_DIR = join(PROJECT_SOURCE_DIR, 'test', 'test262') + stdout = run(['python', join('tools', 'packaging', 'test262.py'), '--command', engine, '--summary'], cwd=TEST262_DIR, @@ -193,18 +195,31 @@ def run_test262(engine, arch): if summary.find('- All tests succeeded') < 0: raise Exception('test262 failed') print('test262: All tests passed') - -@runner('test262-strict', default=True) -def run_test262_strict(engine, arch): - TEST262_OVERRIDE_DIR = join(PROJECT_SOURCE_DIR, 'tools', 'test', 'test262') + +@runner('test262-without-intl402', default=False) +def run_test262_without_intl402(engine, arch): + copy_test262_files() TEST262_DIR = join(PROJECT_SOURCE_DIR, 'test', 'test262') + stdout = run(['python', join('tools', 'packaging', 'test262.py'), + '--skip', 'Temporal', '--skip', 'intl402', + '--command', engine, + '--summary'], + cwd=TEST262_DIR, + env={'TZ': 'US/Pacific'}, + stdout=PIPE) - copy(join(TEST262_OVERRIDE_DIR, 'excludelist.orig.xml'), join(TEST262_DIR, 'excludelist.xml')) - copy(join(TEST262_OVERRIDE_DIR, 'test262.py'), join(TEST262_DIR, 'tools', 'packaging', 'test262.py')) # for parallel running (we should re-implement this for es6 suite) + summary = stdout.decode("utf-8").split('=== Test262 Summary ===')[1] + if summary.find('- All tests succeeded') < 0: + raise Exception('test262 failed') + print('test262: All tests passed') +@runner('test262-strict', default=False) +def run_test262_strict(engine, arch): + copy_test262_files() + TEST262_DIR = join(PROJECT_SOURCE_DIR, 'test', 'test262') out = open('test262-strict_out', 'w') - run(['pypy', join('tools', 'packaging', 'test262.py'), + run(['python', join('tools', 'packaging', 'test262.py'), '--command', engine, '--full-summary', '--strict_only'], @@ -225,17 +240,13 @@ def run_test262_strict(engine, arch): print('test262-strict: All tests passed') -@runner('test262-nonstrict', default=True) +@runner('test262-nonstrict', default=False) def run_test262_nonstrict(engine, arch): - TEST262_OVERRIDE_DIR = join(PROJECT_SOURCE_DIR, 'tools', 'test', 'test262') + copy_test262_files() TEST262_DIR = join(PROJECT_SOURCE_DIR, 'test', 'test262') - - copy(join(TEST262_OVERRIDE_DIR, 'excludelist.orig.xml'), join(TEST262_DIR, 'excludelist.xml')) - copy(join(TEST262_OVERRIDE_DIR, 'test262.py'), join(TEST262_DIR, 'tools', 'packaging', 'test262.py')) # for parallel running (we should re-implement this for es6 suite) - out = open('test262-nonstrict_out', 'w') - run(['pypy', join('tools', 'packaging', 'test262.py'), + run(['python', join('tools', 'packaging', 'test262.py'), '--command', engine, '--full-summary', '--non_strict_only'], @@ -262,17 +273,10 @@ def compile_test_data_runner(): @runner('test262-dump', default=False) def run_test262_dump(engine, arch): - TEST262_OVERRIDE_DIR = join(PROJECT_SOURCE_DIR, 'tools', 'test', 'test262') + copy_test262_files() TEST262_DIR = join(PROJECT_SOURCE_DIR, 'test', 'test262') - copy(join(TEST262_OVERRIDE_DIR, 'excludelist.orig.xml'), join(TEST262_DIR, 'excludelist.xml')) - copy(join(TEST262_OVERRIDE_DIR, 'cth.js'), join(TEST262_DIR, 'harness', 'cth.js')) - copy(join(TEST262_OVERRIDE_DIR, 'testIntl.js'), join(TEST262_DIR, 'harness', 'testIntl.js')) - - copy(join(TEST262_OVERRIDE_DIR, 'parseTestRecord.py'), join(TEST262_DIR, 'tools', 'packaging', 'parseTestRecord.py')) - copy(join(TEST262_OVERRIDE_DIR, 'test262.py'), join(TEST262_DIR, 'tools', 'packaging', 'test262.py')) # for parallel running (we should re-implement this for es6 suite) - - stdout = run(['pypy', join('tools', 'packaging', 'test262.py'), + stdout = run(['python', join('tools', 'packaging', 'test262.py'), '--command', engine, '--summary'], cwd=TEST262_DIR, diff --git a/tools/test/test262/make_excludelist.py b/tools/test/test262/make_excludelist.py index ee50d16ec..c8db62416 100755 --- a/tools/test/test262/make_excludelist.py +++ b/tools/test/test262/make_excludelist.py @@ -14,7 +14,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -from __future__ import print_function + import os import re diff --git a/tools/test/test262/monkeyYaml.py b/tools/test/test262/monkeyYaml.py index 26ac194b4..7125899f6 100644 --- a/tools/test/test262/monkeyYaml.py +++ b/tools/test/test262/monkeyYaml.py @@ -14,12 +14,16 @@ mYamlMultilineList = re.compile(r"^ *- (.*)$") def load(str): + return myReadDict(str.splitlines())[1] + +def myReadDict(lines, indent=""): dict = None key = None emptyLines = 0 - - lines = str.splitlines() while lines: + if not lines[0].startswith(indent): + break + line = lines.pop(0) if myIsAllSpaces(line): emptyLines += 1 @@ -31,7 +35,7 @@ def load(str): dict = {} key = result.group(1).strip() value = result.group(2).strip() - (lines, value) = myReadValue(lines, value) + (lines, value) = myReadValue(lines, value, indent) dict[key] = value else: if dict and key and key in dict: @@ -40,17 +44,20 @@ def load(str): else: raise Exception("monkeyYaml is confused at " + line) emptyLines = 0 - return dict + return lines, dict -def myReadValue(lines, value): - if value == ">": +def myReadValue(lines, value, indent): + if value == ">" or value == "|": (lines, value) = myMultiline(lines, value) value = value + "\n" return (lines, value) - if lines and not value and myMaybeList(lines[0]): - return myMultilineList(lines, value) - else: - return lines, myReadOneLine(value) + if lines and not value: + if myMaybeList(lines[0]): + return myMultilineList(lines, value) + indentMatch = re.match("(" + indent + r"\s+)", lines[0]) + if indentMatch: + return myReadDict(lines, indentMatch.group(1)) + return lines, myReadOneLine(value) def myMaybeList(value): return mYamlMultilineList.match(value) @@ -64,7 +71,7 @@ def myMultilineList(lines, value): leading = myLeadingSpaces(line) if myIsAllSpaces(line): pass - elif leading < indent: + elif indent is not None and leading < indent: lines.insert(0, line) break; else: diff --git a/tools/test/test262/parseTestRecord.py b/tools/test/test262/parseTestRecord.py index 4fe7c9789..b33003a8d 100644 --- a/tools/test/test262/parseTestRecord.py +++ b/tools/test/test262/parseTestRecord.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # Copyright 2011 by Google, Inc. All rights reserved. # This code is governed by the BSD license found in the LICENSE file. @@ -81,7 +81,7 @@ def yamlAttrParser(testRecord, attrs, name): parsed = yamlLoad(body) if (parsed is None): - print "Failed to parse yaml in name %s"%(name) + print("Failed to parse yaml in name %s"%(name)) return for key in parsed: @@ -101,7 +101,7 @@ def parseTestRecord(src, name): # we need to skip hashbang before copyright comment if len(src) > 1 and (src[0] == '#' or src[0] == '\\'): src = src[src.find("// Copyright"):] - elif src[:25].rfind("#!") is not -1: + elif src[:25].rfind("#!") != -1: src = src[src.find("// Copyright"):] match = matchParts(src, name) diff --git a/tools/test/test262/test262.py b/tools/test/test262/test262.py index 1f4e5cae2..cc0782597 100755 --- a/tools/test/test262/test262.py +++ b/tools/test/test262/test262.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # Copyright 2009 the Sputnik authors. All rights reserved. # This code is governed by the BSD license found in the LICENSE file. @@ -23,24 +23,16 @@ import shutil import json import stat -import signal import xml.etree.ElementTree as xmlj import unicodedata from collections import Counter +is_windows = sys.platform.startswith('win') from parseTestRecord import parseTestRecord, stripHeader from packagerConfig import * -class Alarm(Exception): - pass - -def alarm_handler(signum, frame): - raise Alarm - -signal.signal(signal.SIGALRM, alarm_handler) - class Test262Error(Exception): def __init__(self, message): self.message = message @@ -48,11 +40,9 @@ def __init__(self, message): def ReportError(s): raise Test262Error(s) - - if not os.path.exists(EXCLUDED_FILENAME): - print "Cannot generate (JSON) test262 tests without a file," + \ - " %s, showing which tests have been disabled!" % EXCLUDED_FILENAME + print("Cannot generate (JSON) test262 tests without a file," + \ + " %s, showing which tests have been disabled!" % EXCLUDED_FILENAME) sys.exit(1) EXCLUDE_LIST = xml.dom.minidom.parse(EXCLUDED_FILENAME) EXCLUDE_REASON = EXCLUDE_LIST.getElementsByTagName("reason") @@ -95,6 +85,7 @@ def BuildOptions(): result.add_option("--print-handle", default="print", help="Command to print from console") result.add_option("--list-includes", default=False, action="store_true", help="List includes required by tests") + result.add_option("--skip", default=[], action="append", help="skip testcase pattern") return result @@ -131,11 +122,16 @@ def Open(self): text = self.text) def Write(self, str): - os.write(self.fd, str) + os.write(self.fd, str.encode("utf-8")) def Read(self): - f = file(self.name) - result = f.read() + f = open(self.name) + try: + result = f.read() + except UnicodeDecodeError: + f.Close() + f = open(self.name, encoding="utf-16") + result = f.read() f.close() return result @@ -148,7 +144,7 @@ def Dispose(self): try: self.Close() os.unlink(self.name) - except OSError, e: + except OSError as e: logging.error("Error disposing temp file: %s", str(e)) @@ -165,20 +161,20 @@ def ReportOutcome(self, long_format): mode = self.case.GetMode() if self.HasUnexpectedOutcome(): if self.case.IsNegative(): - print "=== %s was expected to fail in %s, but didn't ===" % (name, mode) - print "--- expected error: %s ---\n" % self.case.GetNegative() + print("=== %s was expected to fail in %s, but didn't ===" % (name, mode)) + print("--- expected error: %s ---\n" % self.case.GetNegative()) else: if long_format: - print "=== %s failed in %s ===" % (name, mode) + print("=== %s failed in %s ===" % (name, mode)) else: - print "%s in %s: " % (name, mode) + print("%s in %s: " % (name, mode)) self.WriteOutput(sys.stdout) if long_format: - print "===" + print("===") elif self.case.IsNegative(): - print "%s failed in %s as expected" % (name, mode) + print("%s failed in %s as expected" % (name, mode)) else: - print "%s passed in %s" % (name, mode) + print("%s passed in %s" % (name, mode)) def WriteOutput(self, target): out = self.stdout.strip() @@ -192,8 +188,8 @@ def WriteOutput(self, target): def SafeFormat(self, msg): try: msg = msg.encode(encoding='ascii', errors='strict') - msg = msg.replace('\u000Bx', '?') - msg = msg.replace('\u000Cx', '?') + msg = msg.replace('\\u000Bx', '?') + msg = msg.replace('\\u000Cx', '?') except: return 'Output contained invalid characters' @@ -373,20 +369,17 @@ def Execute(self, command): shell = IsWindows(), stdout = stdout.fd, stderr = stderr.fd, - env = my_env + env = my_env, + encoding = "utf-8" ) - signal.alarm(120) # raise Alarm in 2 minutes - try: - code = process.wait() - signal.alarm(0) # reset the alarm - except Alarm: + code = process.wait(180) + except TimeoutExpired: process.kill() process.wait() code = -1 - # code = process.wait() out = stdout.Read() err = stderr.Read() finally: @@ -454,7 +447,7 @@ def Run(self, command_template): return result def Print(self): - print self.GetSource() + print(self.GetSource()) def validate(self): flags = self.testRecord.get("flags") @@ -509,7 +502,7 @@ def CaseRunner(case): class TestSuite(object): - def __init__(self, root, strict_only, non_strict_only, unmarked_default, print_handle): + def __init__(self, root, strict_only, non_strict_only, unmarked_default, print_handle, skip_patterns): # TODO: derive from packagerConfig.py self.test_root = path.join(root, 'test') if len(ESCARGOT_DUMP262DATA): @@ -523,6 +516,7 @@ def __init__(self, root, strict_only, non_strict_only, unmarked_default, print_h self.print_handle = print_handle self.include_cache = { } self.total_test_number = 0 + self.skip_patterns = skip_patterns def Validate(self): if not path.exists(self.test_root): @@ -578,11 +572,14 @@ def EnumerateTests(self, tests): name = rel_path.split(path.sep)[:-1] + [basename] file_path = rel_path[0:rel_path.rindex('.')] if file_path in EXCLUDE_LIST: - #print 'Excluded: ' + rel_path skip = True elif EXCLUDE_LIST.count(basename) >= 1: - #print 'Excluded: ' + basename skip = True + else: + for s in self.skip_patterns: + if s in full_path: + skip = True + break if not self.non_strict_only: strict_case = TestCase(self, len(cases), name, full_path, True) @@ -609,9 +606,9 @@ def PrintSummary(self, progress, logfile): def write(s): if logfile: self.logf.write(s + "\n") - print s + print(s) - print + print() write("=== Test262 Summary ==="); count = progress.count succeeded = progress.succeeded @@ -626,13 +623,13 @@ def write(s): 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() write("Test262 Failed Tests") for result in positive: write(" %s in %s" % (result.case.GetName(), result.case.GetMode())) write("Failed Tests End") if len(negative) > 0: - print + print() write("Test262 Expected to fail but passed") for result in negative: write(" %s in %s" % (result.case.GetName(), result.case.GetMode())) @@ -643,9 +640,9 @@ def PrintFull(self, progress, logfile): def write(s): if logfile: self.logf.write(s + "\n") - print s + print(s) - print + print() write("=== Test262 Summary ==="); count = progress.count succeeded = progress.succeeded @@ -658,13 +655,13 @@ def write(s): positive = [c for c in progress.succeeded_tests if not c.case.IsNegative()] negative = [c for c in progress.succeeded_tests if c.case.IsNegative()] if len(positive) > 0: - print + print() write("Test262 Succeeded Tests") for result in positive: write(" %s in %s (pass)" % (result.case.GetName(), result.case.GetMode())) write("Succeeded Tests End") if len(negative) > 0: - print + print() write("Test262 Expected to fail") for result in negative: write(" %s in %s (pass)" % (result.case.GetName(), result.case.GetMode())) @@ -673,13 +670,13 @@ def write(s): 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() write("Test262 Failed Tests") for result in positive: write(" %s in %s (fail)" % (result.case.GetName(), result.case.GetMode())) write("Failed Tests End") if len(negative) > 0: - print + print() write("Test262 Expected to fail but passed") for result in negative: write(" %s in %s (fail)" % (result.case.GetName(), result.case.GetMode())) @@ -689,7 +686,7 @@ def PrintFailureOutput(self, progress, logfile): for result in progress.failed_tests: if logfile: self.WriteLog(result) - print + print() result.ReportOutcome(False) def Run(self, command_template, tests, print_summary, print_full, logname, junitfile): @@ -708,12 +705,12 @@ def Run(self, command_template, tests, print_summary, print_full, logname, junit TestSuitesElement.append(TestSuiteElement) TestSuiteElement.attrib["name "] = "test262" for x in range(len(EXCLUDE_LIST)): - if self.ShouldRun (unicode(EXCLUDE_LIST[x].encode('utf-8','ignore')), tests): + if self.ShouldRun (str(EXCLUDE_LIST[x].encode('utf-8','ignore')), tests): SkipCaseElement = xmlj.Element("testcase") - SkipCaseElement.attrib["classname"] = unicode(EXCLUDE_LIST[x]).encode('utf-8','ignore') - SkipCaseElement.attrib["name"] = unicode(EXCLUDE_LIST[x]).encode('utf-8','ignore') + SkipCaseElement.attrib["classname"] = str(EXCLUDE_LIST[x]).encode('utf-8','ignore') + SkipCaseElement.attrib["name"] = str(EXCLUDE_LIST[x]).encode('utf-8','ignore') SkipElement = xmlj.Element("skipped") - SkipElement.attrib["message"] = unicode(EXCLUDE_REASON[x].firstChild.nodeValue) + SkipElement.attrib["message"] = str(EXCLUDE_REASON[x].firstChild.nodeValue) SkipCaseElement.append(SkipElement) TestSuiteElement.append(SkipCaseElement) @@ -769,7 +766,7 @@ def Run(self, command_template, tests, print_summary, print_full, logname, junit print print "Use --full-summary to see output from failed tests" ''' - print + print() return progress.failed def WriteLog(self, result): @@ -801,7 +798,7 @@ def ListIncludes(self, tests): includes = case.GetIncludeList() includes_dict.update(includes) - print includes_dict + print(includes_dict) def Main(): @@ -813,7 +810,8 @@ def Main(): options.strict_only, options.non_strict_only, options.unmarked_default, - options.print_handle) + options.print_handle, + options.skip) test_suite.Validate() if options.loglevel == 'debug': logging.basicConfig(level=logging.DEBUG) @@ -841,6 +839,6 @@ def Main(): try: code = Main() sys.exit(code) - except Test262Error, e: - print "Error: %s" % e.message + except Test262Error as e: + print("Error: %s" % e.message) sys.exit(1)