13af6ab5fSopenharmony_ci#!/usr/bin/env python3 23af6ab5fSopenharmony_ci# -*- coding: utf-8 -*- 33af6ab5fSopenharmony_ci# 43af6ab5fSopenharmony_ci# Copyright (c) 2021-2022 Huawei Device Co., Ltd. 53af6ab5fSopenharmony_ci# Licensed under the Apache License, Version 2.0 (the "License"); 63af6ab5fSopenharmony_ci# you may not use this file except in compliance with the License. 73af6ab5fSopenharmony_ci# You may obtain a copy of the License at 83af6ab5fSopenharmony_ci# 93af6ab5fSopenharmony_ci# http://www.apache.org/licenses/LICENSE-2.0 103af6ab5fSopenharmony_ci# 113af6ab5fSopenharmony_ci# Unless required by applicable law or agreed to in writing, software 123af6ab5fSopenharmony_ci# distributed under the License is distributed on an "AS IS" BASIS, 133af6ab5fSopenharmony_ci# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 143af6ab5fSopenharmony_ci# See the License for the specific language governing permissions and 153af6ab5fSopenharmony_ci# limitations under the License. 163af6ab5fSopenharmony_ci 173af6ab5fSopenharmony_cifrom glob import glob 183af6ab5fSopenharmony_cifrom os import path 193af6ab5fSopenharmony_ciimport os 203af6ab5fSopenharmony_ciimport re 213af6ab5fSopenharmony_ciimport shutil 223af6ab5fSopenharmony_ciimport subprocess 233af6ab5fSopenharmony_ci 243af6ab5fSopenharmony_ci 253af6ab5fSopenharmony_ciclass Test262Util: 263af6ab5fSopenharmony_ci def __init__(self): 273af6ab5fSopenharmony_ci self.header = re.compile( 283af6ab5fSopenharmony_ci r"\/\*---(?P<header>.+)---\*\/", re.DOTALL) 293af6ab5fSopenharmony_ci self.includes = re.compile(r"includes:\s+\[(?P<includes>.+)\]") 303af6ab5fSopenharmony_ci self.includes2 = re.compile(r"includes:(?P<includes>(\s+-[^-].+)+)") 313af6ab5fSopenharmony_ci self.flags = re.compile(r"flags:\s+\[(?P<flags>.+)\]") 323af6ab5fSopenharmony_ci self.negative = re.compile( 333af6ab5fSopenharmony_ci r"negative:.*phase:\s+(?P<phase>\w+).*type:\s+(?P<type>\w+)", 343af6ab5fSopenharmony_ci re.DOTALL) 353af6ab5fSopenharmony_ci self.async_ok = re.compile(r"Test262:AsyncTestComplete") 363af6ab5fSopenharmony_ci 373af6ab5fSopenharmony_ci def generate(self, revision, build_dir, harness_path, show_progress): 383af6ab5fSopenharmony_ci dest_path = path.join(build_dir, 'test262') 393af6ab5fSopenharmony_ci stamp_file = path.join(dest_path, 'test262.stamp') 403af6ab5fSopenharmony_ci 413af6ab5fSopenharmony_ci if path.isfile(stamp_file): 423af6ab5fSopenharmony_ci return dest_path 433af6ab5fSopenharmony_ci 443af6ab5fSopenharmony_ci test262_path = path.join(path.sep, 'tmp', 'test262-%s' % revision) 453af6ab5fSopenharmony_ci 463af6ab5fSopenharmony_ci if not path.exists(test262_path): 473af6ab5fSopenharmony_ci archive_file = path.join(path.sep, 'tmp', 'test262.zip') 483af6ab5fSopenharmony_ci 493af6ab5fSopenharmony_ci print("Downloading test262") 503af6ab5fSopenharmony_ci 513af6ab5fSopenharmony_ci cmd = ['wget', '-q', '-O', archive_file, 523af6ab5fSopenharmony_ci 'https://github.com/tc39/test262/archive/%s.zip' % revision] 533af6ab5fSopenharmony_ci 543af6ab5fSopenharmony_ci if show_progress: 553af6ab5fSopenharmony_ci cmd.append('--show-progress') 563af6ab5fSopenharmony_ci 573af6ab5fSopenharmony_ci return_code = subprocess.call(cmd) 583af6ab5fSopenharmony_ci 593af6ab5fSopenharmony_ci if return_code: 603af6ab5fSopenharmony_ci raise Exception('Downloading test262 repository failed.') 613af6ab5fSopenharmony_ci 623af6ab5fSopenharmony_ci print("Extracting archive") 633af6ab5fSopenharmony_ci if path.isdir(test262_path): 643af6ab5fSopenharmony_ci shutil.rmtree(test262_path) 653af6ab5fSopenharmony_ci 663af6ab5fSopenharmony_ci return_code = subprocess.call( 673af6ab5fSopenharmony_ci ['unzip', '-q', '-d', path.join(path.sep, 'tmp'), archive_file]) 683af6ab5fSopenharmony_ci 693af6ab5fSopenharmony_ci if return_code: 703af6ab5fSopenharmony_ci raise Exception( 713af6ab5fSopenharmony_ci 'Failed to unzip test262 repository') 723af6ab5fSopenharmony_ci 733af6ab5fSopenharmony_ci os.remove(archive_file) 743af6ab5fSopenharmony_ci 753af6ab5fSopenharmony_ci print("Generating tests") 763af6ab5fSopenharmony_ci src_path = path.join(test262_path, 'test') 773af6ab5fSopenharmony_ci 783af6ab5fSopenharmony_ci glob_expression = path.join(src_path, "**/*.js") 793af6ab5fSopenharmony_ci files = glob(glob_expression, recursive=True) 803af6ab5fSopenharmony_ci files = list(filter(lambda f: not f.endswith("FIXTURE.js"), files)) 813af6ab5fSopenharmony_ci 823af6ab5fSopenharmony_ci with open(harness_path, 'r') as fp: 833af6ab5fSopenharmony_ci harness = fp.read() 843af6ab5fSopenharmony_ci 853af6ab5fSopenharmony_ci harness = harness.replace('$SOURCE', '`%s`' % harness) 863af6ab5fSopenharmony_ci 873af6ab5fSopenharmony_ci for src_file in files: 883af6ab5fSopenharmony_ci dest_file = src_file.replace(src_path, dest_path) 893af6ab5fSopenharmony_ci os.makedirs(path.dirname(dest_file), exist_ok=True) 903af6ab5fSopenharmony_ci self.create_file(src_file, dest_file, harness, test262_path) 913af6ab5fSopenharmony_ci 923af6ab5fSopenharmony_ci with open(stamp_file, 'w') as fp: 933af6ab5fSopenharmony_ci pass 943af6ab5fSopenharmony_ci 953af6ab5fSopenharmony_ci return dest_path 963af6ab5fSopenharmony_ci 973af6ab5fSopenharmony_ci def create_file(self, input_file, output_file, harness, test262_dir): 983af6ab5fSopenharmony_ci with open(input_file, 'r') as fp: 993af6ab5fSopenharmony_ci input_str = fp.read() 1003af6ab5fSopenharmony_ci 1013af6ab5fSopenharmony_ci header = self.get_header(input_str) 1023af6ab5fSopenharmony_ci desc = self.parse_descriptor(header) 1033af6ab5fSopenharmony_ci 1043af6ab5fSopenharmony_ci out_str = header 1053af6ab5fSopenharmony_ci out_str += "\n" 1063af6ab5fSopenharmony_ci out_str += harness 1073af6ab5fSopenharmony_ci 1083af6ab5fSopenharmony_ci for include in desc['includes']: 1093af6ab5fSopenharmony_ci out_str += "//------------ %s start ------------\n" % include 1103af6ab5fSopenharmony_ci with open(path.join(test262_dir, 'harness', include), 'r') as fp: 1113af6ab5fSopenharmony_ci harness_str = fp.read() 1123af6ab5fSopenharmony_ci out_str += harness_str 1133af6ab5fSopenharmony_ci out_str += "//------------ %s end ------------\n" % include 1143af6ab5fSopenharmony_ci out_str += "\n" 1153af6ab5fSopenharmony_ci 1163af6ab5fSopenharmony_ci out_str += input_str 1173af6ab5fSopenharmony_ci with open(output_file, 'w') as o: 1183af6ab5fSopenharmony_ci o.write(out_str) 1193af6ab5fSopenharmony_ci 1203af6ab5fSopenharmony_ci def get_header(self, content): 1213af6ab5fSopenharmony_ci header_comment = self.header.search(content) 1223af6ab5fSopenharmony_ci assert header_comment 1233af6ab5fSopenharmony_ci return header_comment.group(0) 1243af6ab5fSopenharmony_ci 1253af6ab5fSopenharmony_ci def parse_descriptor(self, header): 1263af6ab5fSopenharmony_ci match = self.includes.search(header) 1273af6ab5fSopenharmony_ci includes = list(map(lambda e: e.strip(), match.group( 1283af6ab5fSopenharmony_ci 'includes').split(','))) if match else [] 1293af6ab5fSopenharmony_ci 1303af6ab5fSopenharmony_ci match = self.includes2.search(header) 1313af6ab5fSopenharmony_ci includes += list(map(lambda e: e.strip(), match.group( 1323af6ab5fSopenharmony_ci 'includes').split('-')))[1:] if match else [] 1333af6ab5fSopenharmony_ci 1343af6ab5fSopenharmony_ci includes.extend(['assert.js', 'sta.js']) 1353af6ab5fSopenharmony_ci 1363af6ab5fSopenharmony_ci match = self.flags.search(header) 1373af6ab5fSopenharmony_ci flags = list(map(lambda e: e.strip(), 1383af6ab5fSopenharmony_ci match.group('flags').split(','))) if match else [] 1393af6ab5fSopenharmony_ci 1403af6ab5fSopenharmony_ci if 'async' in flags: 1413af6ab5fSopenharmony_ci includes.extend(['doneprintHandle.js']) 1423af6ab5fSopenharmony_ci 1433af6ab5fSopenharmony_ci match = self.negative.search(header) 1443af6ab5fSopenharmony_ci negative_phase = match.group('phase') if match else 'pass' 1453af6ab5fSopenharmony_ci negative_type = match.group('type') if match else '' 1463af6ab5fSopenharmony_ci 1473af6ab5fSopenharmony_ci # negative_phase: pass, parse, resolution, runtime 1483af6ab5fSopenharmony_ci return { 1493af6ab5fSopenharmony_ci 'flags': flags, 1503af6ab5fSopenharmony_ci 'negative_phase': negative_phase, 1513af6ab5fSopenharmony_ci 'negative_type': negative_type, 1523af6ab5fSopenharmony_ci 'includes': includes, 1533af6ab5fSopenharmony_ci } 1543af6ab5fSopenharmony_ci 1553af6ab5fSopenharmony_ci @staticmethod 1563af6ab5fSopenharmony_ci def validate_parse_result(return_code, std_err, desc, out): 1573af6ab5fSopenharmony_ci is_negative = (desc['negative_phase'] == 'parse') 1583af6ab5fSopenharmony_ci 1593af6ab5fSopenharmony_ci if return_code == 0: # passed 1603af6ab5fSopenharmony_ci if is_negative: 1613af6ab5fSopenharmony_ci return False, False # negative test passed 1623af6ab5fSopenharmony_ci 1633af6ab5fSopenharmony_ci return True, True # positive test passed 1643af6ab5fSopenharmony_ci 1653af6ab5fSopenharmony_ci if return_code == 1: # failed 1663af6ab5fSopenharmony_ci return is_negative and (desc['negative_type'] in out), False 1673af6ab5fSopenharmony_ci 1683af6ab5fSopenharmony_ci return False, False # abnormal 1693af6ab5fSopenharmony_ci 1703af6ab5fSopenharmony_ci def validate_runtime_result(self, return_code, std_err, desc, out): 1713af6ab5fSopenharmony_ci is_negative = (desc['negative_phase'] == 'runtime') or ( 1723af6ab5fSopenharmony_ci desc['negative_phase'] == 'resolution') 1733af6ab5fSopenharmony_ci 1743af6ab5fSopenharmony_ci if return_code == 0: # passed 1753af6ab5fSopenharmony_ci if is_negative: 1763af6ab5fSopenharmony_ci return False # negative test passed 1773af6ab5fSopenharmony_ci 1783af6ab5fSopenharmony_ci passed = (len(std_err) == 0) 1793af6ab5fSopenharmony_ci if 'async' in desc['flags']: 1803af6ab5fSopenharmony_ci passed = passed and bool(self.async_ok.match(out)) 1813af6ab5fSopenharmony_ci return passed # positive test passed? 1823af6ab5fSopenharmony_ci 1833af6ab5fSopenharmony_ci if return_code == 1: # failed 1843af6ab5fSopenharmony_ci return is_negative and (desc['negative_type'] in std_err) 1853af6ab5fSopenharmony_ci 1863af6ab5fSopenharmony_ci return False # abnormal 187