<html>
<head><title>301 Moved Permanently</title></head> <body> <center><h1>301 Moved Permanently</h1></center> </body> </html>
This commit is contained in:
parent
a68f405674
commit
601e474bd9
2 changed files with 51 additions and 54 deletions
|
@ -6,7 +6,7 @@ import astunparse
|
||||||
import sys
|
import sys
|
||||||
import random
|
import random
|
||||||
from deap import creator, base, tools, algorithms
|
from deap import creator, base, tools, algorithms
|
||||||
from instrumentor import compute_distances
|
from operators import compute_distances
|
||||||
|
|
||||||
# hyperparameters
|
# hyperparameters
|
||||||
NPOP = 300
|
NPOP = 300
|
||||||
|
@ -22,6 +22,7 @@ MAX_STRING_LENGTH = 10
|
||||||
|
|
||||||
IN_DIR: str = os.path.join(os.path.dirname(__file__), 'benchmark')
|
IN_DIR: str = os.path.join(os.path.dirname(__file__), 'benchmark')
|
||||||
OUT_DIR: str = os.path.join(os.path.dirname(__file__), 'instrumented')
|
OUT_DIR: str = os.path.join(os.path.dirname(__file__), 'instrumented')
|
||||||
|
SUFFIX: str = "_instrumented"
|
||||||
|
|
||||||
distances_true: dict[int, int] = {}
|
distances_true: dict[int, int] = {}
|
||||||
distances_false: dict[int, int] = {}
|
distances_false: dict[int, int] = {}
|
||||||
|
@ -30,10 +31,6 @@ archive_true_branches: dict[int, str] = {}
|
||||||
archive_false_branches: dict[int, str] = {}
|
archive_false_branches: dict[int, str] = {}
|
||||||
|
|
||||||
|
|
||||||
def cgi_decode_instrumented(s: str) -> str:
|
|
||||||
return "" # make mypy happy
|
|
||||||
|
|
||||||
|
|
||||||
class BranchTransformer(ast.NodeTransformer):
|
class BranchTransformer(ast.NodeTransformer):
|
||||||
branch_num: int
|
branch_num: int
|
||||||
instrumented_name: Optional[str]
|
instrumented_name: Optional[str]
|
||||||
|
@ -44,7 +41,12 @@ class BranchTransformer(ast.NodeTransformer):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def to_instrumented_name(name: str):
|
def to_instrumented_name(name: str):
|
||||||
return name + "_instrumented"
|
return name + SUFFIX
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def to_original_name(name: str):
|
||||||
|
assert name.endswith(SUFFIX)
|
||||||
|
return name[:len(name) - len(SUFFIX)]
|
||||||
|
|
||||||
def visit_Assert(self, ast_node):
|
def visit_Assert(self, ast_node):
|
||||||
# Disable recursion in asserts, i.e. do not instrument assert conditions
|
# Disable recursion in asserts, i.e. do not instrument assert conditions
|
||||||
|
@ -128,11 +130,12 @@ def get_fitness_cgi(individual):
|
||||||
distances_true = {}
|
distances_true = {}
|
||||||
distances_false = {}
|
distances_false = {}
|
||||||
|
|
||||||
|
# TODO: fix this
|
||||||
# Run the function under test
|
# Run the function under test
|
||||||
try:
|
# try:
|
||||||
cgi_decode_instrumented(x)
|
# cgi_decode_instrumented(x)
|
||||||
except BaseException:
|
# except BaseException:
|
||||||
pass
|
# pass
|
||||||
|
|
||||||
# Sum up branch distances
|
# Sum up branch distances
|
||||||
fitness = 0.0
|
fitness = 0.0
|
||||||
|
@ -215,13 +218,13 @@ def generate():
|
||||||
|
|
||||||
ArgType = str
|
ArgType = str
|
||||||
Arg = tuple[str, ArgType]
|
Arg = tuple[str, ArgType]
|
||||||
|
Params = dict[str, any]
|
||||||
SignatureDict = dict[str, list[Arg]]
|
SignatureDict = dict[str, list[Arg]]
|
||||||
|
|
||||||
|
|
||||||
functions: SignatureDict = {}
|
functions: SignatureDict = {}
|
||||||
|
|
||||||
|
|
||||||
def instrument(source_path: str, target_path: str):
|
def instrument(source_path: str, target_path: str, save_instrumented=True):
|
||||||
global functions
|
global functions
|
||||||
|
|
||||||
with open(source_path, "r") as f:
|
with open(source_path, "r") as f:
|
||||||
|
@ -232,8 +235,9 @@ def instrument(source_path: str, target_path: str):
|
||||||
BranchTransformer().visit(node)
|
BranchTransformer().visit(node)
|
||||||
node = ast.fix_missing_locations(node) # Make sure the line numbers are ok before printing
|
node = ast.fix_missing_locations(node) # Make sure the line numbers are ok before printing
|
||||||
|
|
||||||
with open(target_path, "w") as f:
|
if save_instrumented:
|
||||||
print(astunparse.unparse(node), file=f)
|
with open(target_path, "w") as f:
|
||||||
|
print(astunparse.unparse(node), file=f)
|
||||||
|
|
||||||
current_module = sys.modules[__name__]
|
current_module = sys.modules[__name__]
|
||||||
code = compile(node, filename="<ast>", mode="exec")
|
code = compile(node, filename="<ast>", mode="exec")
|
||||||
|
@ -259,24 +263,20 @@ def instrument(source_path: str, target_path: str):
|
||||||
functions[f.name] = arg_types
|
functions[f.name] = arg_types
|
||||||
|
|
||||||
|
|
||||||
def invoke_signature(fun_name: str, arg_values: dict[str]) -> any:
|
def invoke_signature(f_name: str, f_args: Params) -> any:
|
||||||
global functions
|
global functions
|
||||||
|
|
||||||
current_module = sys.modules[__name__]
|
current_module = sys.modules[__name__]
|
||||||
|
|
||||||
if fun_name not in functions:
|
if f_name not in functions:
|
||||||
raise ValueError(f"Function '{fun_name}' not loaded")
|
raise ValueError(f"Function '{f_name}' not loaded")
|
||||||
|
|
||||||
args = functions[fun_name]
|
f_args_signature = functions[f_name]
|
||||||
for arg_name, arg_type in args:
|
for arg_name, arg_type in f_args_signature:
|
||||||
if arg_name not in arg_values:
|
if arg_name not in f_args:
|
||||||
raise ValueError(f"Required argument '{arg_name}' not provided")
|
raise ValueError(f"Required argument '{arg_name}' not provided")
|
||||||
|
|
||||||
|
return getattr(current_module, f_name)(**f_args)
|
||||||
arg_str = ",".join([f"{k}={v}" for k, v in arg_values.items()])
|
|
||||||
print(f"Calling {fun_name}({arg_str})")
|
|
||||||
|
|
||||||
return getattr(current_module, fun_name)(**arg_values)
|
|
||||||
|
|
||||||
|
|
||||||
def find_py_files(search_dir: str):
|
def find_py_files(search_dir: str):
|
||||||
|
@ -286,24 +286,41 @@ def find_py_files(search_dir: str):
|
||||||
yield os.path.join(cwd, file)
|
yield os.path.join(cwd, file)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def load_benchmark(save_instrumented=True):
|
||||||
|
for file in find_py_files(IN_DIR):
|
||||||
|
instrument(file, os.path.join(OUT_DIR, os.path.basename(file)), save_instrumented=save_instrumented)
|
||||||
|
|
||||||
|
|
||||||
|
def run_all_example():
|
||||||
global functions
|
global functions
|
||||||
|
|
||||||
for file in find_py_files(IN_DIR):
|
for f_name, f_args_signature in functions.items():
|
||||||
instrument(file, os.path.join(OUT_DIR, os.path.basename(file)))
|
|
||||||
|
|
||||||
for function, arg_signatures in functions.items():
|
|
||||||
args = {}
|
args = {}
|
||||||
for arg_name, arg_type in arg_signatures:
|
for arg_name, arg_type in f_args_signature:
|
||||||
|
# Generate some dummy values appropriate for each type
|
||||||
|
|
||||||
if arg_type == 'int':
|
if arg_type == 'int':
|
||||||
args[arg_name] = 42
|
args[arg_name] = 42
|
||||||
elif arg_type == 'str':
|
elif arg_type == 'str':
|
||||||
args[arg_name] = 'hello world'
|
args[arg_name] = 'hello world'
|
||||||
else:
|
else:
|
||||||
args[arg_name] = None
|
raise ValueError(f"Arg type '{arg_type}' for '{arg_name}' not supported")
|
||||||
|
|
||||||
invoke_signature(function, args)
|
out = invoke_signature(f_name, args)
|
||||||
|
print(call_statement(f_name, args), "=", out)
|
||||||
|
|
||||||
|
|
||||||
|
def call_statement(f_name: str, f_args: Params, ) -> str:
|
||||||
|
arg_list: list[str] = []
|
||||||
|
for k, v in f_args.items():
|
||||||
|
if type(v) == str:
|
||||||
|
arg_list.append(f"{k}='{v}'") # quote strings
|
||||||
|
else:
|
||||||
|
arg_list.append(f"{k}={v}")
|
||||||
|
|
||||||
|
return f"{f_name}({', '.join(arg_list)})"
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
main()
|
load_benchmark(save_instrumented=True)
|
||||||
|
run_all_example()
|
|
@ -25,26 +25,6 @@ class CmpOp(Generic[T]):
|
||||||
self.false_dist = false_dist
|
self.false_dist = false_dist
|
||||||
|
|
||||||
|
|
||||||
# @dataclass
|
|
||||||
# class InstrState:
|
|
||||||
# min_true_dist: Optional[int]
|
|
||||||
# min_false_dist: Optional[int]
|
|
||||||
#
|
|
||||||
# def __init__(self):
|
|
||||||
# self.min_true_dist = None
|
|
||||||
# self.min_false_dist = None
|
|
||||||
#
|
|
||||||
# def update(self, op: CmpOp[U], lhs: U, rhs: U):
|
|
||||||
# true_dist = op.true_dist(lhs, rhs)
|
|
||||||
# self.min_true_dist = true_dist if self.min_true_dist is None else min(true_dist, self.min_true_dist)
|
|
||||||
#
|
|
||||||
# false_dist = op.false_dist(lhs, rhs)
|
|
||||||
# self.min_false_dist = false_dist if self.min_false_dist is None else min(false_dist, self.min_false_dist)
|
|
||||||
#
|
|
||||||
#
|
|
||||||
# instrumentation_states: defaultdict[int, InstrState] = defaultdict(InstrState)
|
|
||||||
|
|
||||||
|
|
||||||
# Operands for these must both be integers or strings of length 1
|
# Operands for these must both be integers or strings of length 1
|
||||||
int_str_ops: list[CmpOp[int | str]] = [
|
int_str_ops: list[CmpOp[int | str]] = [
|
||||||
CmpOp(operator='<',
|
CmpOp(operator='<',
|
Reference in a new issue