1#!/usr/bin/env python 2# Copyright 2014 the V8 project authors. All rights reserved. 3# Use of this source code is governed by a BSD-style license that can be 4# found in the LICENSE file. 5 6import json 7import optparse 8import os 9import random 10import shutil 11import subprocess 12import sys 13 14 15BLACKLIST = [ 16 # Skip special d8 functions. 17 "load", "os", "print", "read", "readline", "quit" 18] 19 20 21def GetRandomObject(): 22 return random.choice([ 23 "0", "1", "2.5", "0x1000", "\"string\"", "{foo: \"bar\"}", "[1, 2, 3]", 24 "function() { return 0; }" 25 ]) 26 27 28g_var_index = 0 29 30 31def GetVars(result, num, first = []): 32 global g_var_index 33 variables = [] 34 for i in range(num): 35 variables.append("__v_%d" % g_var_index) 36 g_var_index += 1 37 for var in variables: 38 result.append("var %s = %s;" % (var, GetRandomObject())) 39 return ", ".join(first + variables) 40 41 42# Wraps |string| in try..catch. 43def TryCatch(result, string, exception_behavior = ""): 44 result.append("try { %s } catch(e) { %s }" % (string, exception_behavior)) 45 46 47def BuildTests(function, full_name, options): 48 assert function["type"] == "function" 49 global g_var_index 50 g_var_index = 0 51 result = ["// AUTO-GENERATED BY tools/generate-builtins-tests.py.\n"] 52 result.append("// Function call test:") 53 length = function["length"] 54 TryCatch(result, "%s(%s);" % (full_name, GetVars(result, length))) 55 56 if "prototype" in function: 57 proto = function["prototype"] 58 result.append("\n// Constructor test:") 59 TryCatch(result, 60 "var recv = new %s(%s);" % (full_name, GetVars(result, length)), 61 "var recv = new Object();") 62 63 getters = [] 64 methods = [] 65 for prop in proto: 66 proto_property = proto[prop] 67 proto_property_type = proto_property["type"] 68 if proto_property_type == "getter": 69 getters.append(proto_property) 70 result.append("recv.__defineGetter__(\"%s\", " 71 "function() { return %s; });" % 72 (proto_property["name"], GetVars(result, 1))) 73 if proto_property_type == "number": 74 result.append("recv.__defineGetter__(\"%s\", " 75 "function() { return %s; });" % 76 (proto_property["name"], GetVars(result, 1))) 77 if proto_property_type == "function": 78 methods.append(proto_property) 79 if getters: 80 result.append("\n// Getter tests:") 81 for getter in getters: 82 result.append("print(recv.%s);" % getter["name"]) 83 if methods: 84 result.append("\n// Method tests:") 85 for method in methods: 86 args = GetVars(result, method["length"], ["recv"]) 87 call = "%s.prototype.%s.call(%s)" % (full_name, method["name"], args) 88 TryCatch(result, call) 89 90 filename = os.path.join(options.outdir, "%s.js" % (full_name)) 91 with open(filename, "w") as f: 92 f.write("\n".join(result)) 93 f.write("\n") 94 95 96def VisitObject(obj, path, options): 97 obj_type = obj["type"] 98 obj_name = "%s%s" % (path, obj["name"]) 99 if obj_type == "function": 100 BuildTests(obj, obj_name, options) 101 if "properties" in obj: 102 for prop_name in obj["properties"]: 103 prop = obj["properties"][prop_name] 104 VisitObject(prop, "%s." % (obj_name), options) 105 106 107def ClearGeneratedFiles(options): 108 if os.path.exists(options.outdir): 109 shutil.rmtree(options.outdir) 110 111 112def GenerateTests(options): 113 ClearGeneratedFiles(options) # Re-generate everything. 114 output = subprocess.check_output( 115 "%s %s" % (options.d8, options.script), shell=True).strip() 116 objects = json.loads(output) 117 118 os.makedirs(options.outdir) 119 for obj_name in objects: 120 if obj_name in BLACKLIST: continue 121 obj = objects[obj_name] 122 VisitObject(obj, "", options) 123 124 125def BuildOptions(): 126 result = optparse.OptionParser() 127 result.add_option("--d8", help="d8 binary to use", 128 default="out/ia32.release/d8") 129 result.add_option("--outdir", help="directory where to place generated tests", 130 default="test/mjsunit/builtins-gen") 131 result.add_option("--script", help="builtins detector script to run in d8", 132 default="tools/detect-builtins.js") 133 return result 134 135 136def Main(): 137 parser = BuildOptions() 138 (options, args) = parser.parse_args() 139 if len(args) != 1 or args[0] == "help": 140 parser.print_help() 141 return 1 142 action = args[0] 143 144 if action == "generate": 145 GenerateTests(options) 146 return 0 147 148 if action == "clear": 149 ClearGeneratedFiles(options) 150 return 0 151 152 print("Unknown action: %s" % action) 153 parser.print_help() 154 return 1 155 156 157if __name__ == "__main__": 158 sys.exit(Main()) 159