testgenie-py 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. testgen/__init__.py +0 -0
  2. testgen/analyzer/__init__.py +0 -0
  3. testgen/analyzer/ast_analyzer.py +149 -0
  4. testgen/analyzer/contracts/__init__.py +0 -0
  5. testgen/analyzer/contracts/contract.py +13 -0
  6. testgen/analyzer/contracts/no_exception_contract.py +16 -0
  7. testgen/analyzer/contracts/nonnull_contract.py +15 -0
  8. testgen/analyzer/fuzz_analyzer.py +106 -0
  9. testgen/analyzer/random_feedback_analyzer.py +291 -0
  10. testgen/analyzer/reinforcement_analyzer.py +75 -0
  11. testgen/analyzer/test_case_analyzer.py +46 -0
  12. testgen/analyzer/test_case_analyzer_context.py +58 -0
  13. testgen/controller/__init__.py +0 -0
  14. testgen/controller/cli_controller.py +194 -0
  15. testgen/controller/docker_controller.py +169 -0
  16. testgen/docker/Dockerfile +22 -0
  17. testgen/docker/poetry.lock +361 -0
  18. testgen/docker/pyproject.toml +22 -0
  19. testgen/generator/__init__.py +0 -0
  20. testgen/generator/code_generator.py +66 -0
  21. testgen/generator/doctest_generator.py +208 -0
  22. testgen/generator/generator.py +55 -0
  23. testgen/generator/pytest_generator.py +77 -0
  24. testgen/generator/test_generator.py +26 -0
  25. testgen/generator/unit_test_generator.py +84 -0
  26. testgen/inspector/__init__.py +0 -0
  27. testgen/inspector/inspector.py +61 -0
  28. testgen/main.py +13 -0
  29. testgen/models/__init__.py +0 -0
  30. testgen/models/analysis_context.py +56 -0
  31. testgen/models/function_metadata.py +61 -0
  32. testgen/models/generator_context.py +63 -0
  33. testgen/models/test_case.py +8 -0
  34. testgen/presentation/__init__.py +0 -0
  35. testgen/presentation/cli_view.py +12 -0
  36. testgen/q_table/global_q_table.json +1 -0
  37. testgen/reinforcement/__init__.py +0 -0
  38. testgen/reinforcement/abstract_state.py +7 -0
  39. testgen/reinforcement/agent.py +153 -0
  40. testgen/reinforcement/environment.py +215 -0
  41. testgen/reinforcement/statement_coverage_state.py +33 -0
  42. testgen/service/__init__.py +0 -0
  43. testgen/service/analysis_service.py +260 -0
  44. testgen/service/cfg_service.py +55 -0
  45. testgen/service/generator_service.py +169 -0
  46. testgen/service/service.py +389 -0
  47. testgen/sqlite/__init__.py +0 -0
  48. testgen/sqlite/db.py +84 -0
  49. testgen/sqlite/db_service.py +219 -0
  50. testgen/tree/__init__.py +0 -0
  51. testgen/tree/node.py +7 -0
  52. testgen/tree/tree_utils.py +79 -0
  53. testgen/util/__init__.py +0 -0
  54. testgen/util/coverage_utils.py +168 -0
  55. testgen/util/coverage_visualizer.py +154 -0
  56. testgen/util/file_utils.py +110 -0
  57. testgen/util/randomizer.py +122 -0
  58. testgen/util/utils.py +143 -0
  59. testgen/util/z3_utils/__init__.py +0 -0
  60. testgen/util/z3_utils/ast_to_z3.py +99 -0
  61. testgen/util/z3_utils/branch_condition.py +72 -0
  62. testgen/util/z3_utils/constraint_extractor.py +36 -0
  63. testgen/util/z3_utils/variable_finder.py +10 -0
  64. testgen/util/z3_utils/z3_test_case.py +94 -0
  65. testgenie_py-0.1.0.dist-info/METADATA +24 -0
  66. testgenie_py-0.1.0.dist-info/RECORD +68 -0
  67. testgenie_py-0.1.0.dist-info/WHEEL +4 -0
  68. testgenie_py-0.1.0.dist-info/entry_points.txt +3 -0
testgen/util/utils.py ADDED
@@ -0,0 +1,143 @@
1
+
2
+ import ast
3
+ import string
4
+ import sys
5
+ import random
6
+ from typing import List
7
+
8
+ from atheris import FuzzedDataProvider
9
+
10
+ from testgen.util.file_utils import load_and_parse_file_for_tree
11
+
12
+
13
+ def get_func(module, func_name:str):
14
+ return getattr(module, func_name)
15
+
16
+ def extract_parameter_types(func_node):
17
+ """Extract parameter types from a function node."""
18
+ param_types = {}
19
+ for arg in func_node.args.args:
20
+ param_name = arg.arg
21
+ if arg.annotation:
22
+ param_type = ast.unparse(arg.annotation)
23
+ param_types[param_name] = param_type
24
+ else:
25
+ if param_name != 'self':
26
+ param_types[param_name] = None
27
+ return param_types
28
+
29
+ def generate_random_inputs(param_types):
30
+ """Generate inputs for fuzzing based on parameter types."""
31
+ inputs = {}
32
+ for param, param_type in param_types.items():
33
+ if param_type == "int":
34
+ # Try using sys.maxsize for minsize and maxsize
35
+ minsize = -sys.maxsize - 1
36
+ maxsize = sys.maxsize
37
+ random_integer = random.randint(minsize, maxsize)
38
+ inputs[param] = random_integer
39
+ elif param_type == "bool":
40
+ random_choice = random.choice([True, False])
41
+ inputs[param] = random_choice
42
+ elif param_type == "float":
43
+ random_float = random.random()
44
+ inputs[param] = random_float
45
+ # TODO: Random String and Random bytes; Random objects?
46
+ elif param_type == "str":
47
+ inputs[param] = "abc"
48
+ #elif param_type == "bytes":
49
+ # inputs[param] = fdp.ConsumeBytes(10)
50
+ else:
51
+ inputs[param] = None
52
+ return inputs
53
+
54
+ def generate_extreme_inputs(param_types):
55
+ inputs = {}
56
+ for param, param_type in param_types.items():
57
+ if param_type == "int":
58
+ # int is unbounded in Python, but sys.maxsize is the max value representable by a signed word
59
+ inputs[param] = sys.maxsize
60
+ if param_type == "bool":
61
+ random_choice = random.choice([1, 0])
62
+ inputs[param] = random_choice
63
+ if param_type == "float":
64
+ random_choice = random.choice([sys.float_info.min, sys.float_info.max])
65
+ inputs[param] = random_choice
66
+ if param_type == "str":
67
+ inputs[param] = ''.join(random.choice([string.ascii_letters, string.digits, string.punctuation, string.whitespace]) for _ in range(100))
68
+
69
+ def generate_inputs_from_fuzz_data(fdp: FuzzedDataProvider, param_types):
70
+ """Generate fuzzed inputs based on parameter types."""
71
+ inputs = []
72
+ for param_type in param_types.values():
73
+ if param_type == "int":
74
+ inputs.append(fdp.ConsumeInt(4))
75
+ elif param_type == "bool":
76
+ inputs.append(fdp.ConsumeBool())
77
+ elif param_type == "float":
78
+ inputs.append(fdp.ConsumeFloat())
79
+ elif param_type == "str":
80
+ inputs.append(fdp.ConsumeString(10))
81
+ elif param_type == "bytes":
82
+ inputs.append(fdp.ConsumeBytes(10))
83
+ else:
84
+ inputs.append(None)
85
+ return tuple(inputs)
86
+
87
+ def get_functions(tree) -> List[ast.FunctionDef]:
88
+ functions = []
89
+ for node in tree.body:
90
+ if isinstance(node, ast.FunctionDef):
91
+ functions.append(node)
92
+ if isinstance(node, ast.ClassDef):
93
+ for class_node in node.body:
94
+ if isinstance(class_node, ast.FunctionDef):
95
+ functions.append(class_node)
96
+ return functions
97
+
98
+ def get_function_boundaries(file_name: str, func_name: str) -> tuple:
99
+ tree = load_and_parse_file_for_tree(file_name)
100
+ for i, node in enumerate(tree.body):
101
+ if isinstance(node, ast.FunctionDef) and node.name == func_name:
102
+ func_start = node.lineno
103
+
104
+ if i == len(tree.body) - 1:
105
+ max_lines = [line.lineno for line in ast.walk(node) if hasattr(line, 'lineno') and line.lineno]
106
+ func_end = max(max_lines) if max_lines else func_start
107
+ else:
108
+ next_node = tree.body[i + 1]
109
+ if hasattr(next_node, 'lineno'):
110
+ func_end = next_node.lineno - 1
111
+ else:
112
+ max_lines = [line.lineno for line in ast.walk(node) if hasattr(line, 'lineno') and line.lineno]
113
+ func_end = max(max_lines) if max_lines else func_start
114
+
115
+ return func_start, func_end
116
+
117
+ # For classes
118
+ for node in tree.body:
119
+ if isinstance(node, ast.ClassDef):
120
+ for i, method in enumerate(node.body):
121
+ if isinstance(method, ast.FunctionDef) and method.name == func_name:
122
+ func_start = method.lineno
123
+
124
+ # Find end of method
125
+ if i == len(node.body) - 1:
126
+ max_lines = [line.lineno for line in ast.walk(method)
127
+ if hasattr(line, 'lineno') and line.lineno]
128
+ func_end = max(max_lines) if max_lines else func_start
129
+ else:
130
+ next_method = node.body[i + 1]
131
+ if hasattr(next_method, 'lineno'):
132
+ func_end = next_method.lineno - 1
133
+ else:
134
+ max_lines = [line.lineno for line in ast.walk(method)
135
+ if hasattr(line, 'lineno') and line.lineno]
136
+ func_end = max(max_lines) if max_lines else func_start
137
+
138
+ return func_start, func_end
139
+
140
+ raise ValueError(f"Function {func_name} not found in {file_name}")
141
+
142
+
143
+
File without changes
@@ -0,0 +1,99 @@
1
+ import ast
2
+ from typing import Dict
3
+ import z3
4
+
5
+ class ASTToZ3(ast.NodeVisitor):
6
+ def __init__(self, param_types: Dict[str, str]):
7
+ self.param_types = param_types
8
+ self.z3_vars = {}
9
+
10
+ def create_z3_var(self, name: str, type_hint: str = None):
11
+ if name in self.z3_vars:
12
+ return self.z3_vars[name]
13
+
14
+ if type_hint == "int" or type_hint is None:
15
+ z3_var = z3.Int(name)
16
+ elif type_hint == "float":
17
+ z3_var = z3.Real(name)
18
+ elif type_hint == "bool":
19
+ z3_var = z3.Bool(name)
20
+ elif type_hint == "str":
21
+ z3_var = z3.String(name)
22
+ else:
23
+ z3_var = z3.Int(name)
24
+
25
+ self.z3_vars[name] = z3_var
26
+ return z3_var
27
+
28
+ def visit_Name(self, node):
29
+ if node.id in self.param_types:
30
+ return self.create_z3_var(node.id, self.param_types[node.id])
31
+ return self.create_z3_var(node.id)
32
+
33
+ def visit_Constant(self, node):
34
+ return node.value
35
+
36
+ def visit_BinOp(self, node):
37
+ left = self.visit(node.left)
38
+ right = self.visit(node.right)
39
+
40
+ if isinstance(node.op, ast.Add):
41
+ return left + right
42
+ elif isinstance(node.op, ast.Sub):
43
+ return left - right
44
+ elif isinstance(node.op, ast.Mult):
45
+ return left * right
46
+ elif isinstance(node.op, ast.Div):
47
+ return left / right
48
+ elif isinstance(node.op, ast.Mod):
49
+ return left % right
50
+ else:
51
+ raise NotImplementedError(f"Operation {node.op} not implemented")
52
+
53
+ def visit_Compare(self, node):
54
+ left = self.visit(node.left)
55
+
56
+ result = None
57
+ for i, (op, right) in enumerate(zip(node.ops, node.comparators)):
58
+ right_val = self.visit(right)
59
+
60
+ if isinstance(op, ast.Eq):
61
+ condition = left == right_val
62
+ elif isinstance(op, ast.NotEq):
63
+ condition = left != right_val
64
+ elif isinstance(op, ast.Lt):
65
+ condition = left < right_val
66
+ elif isinstance(op, ast.LtE):
67
+ condition = left <= right_val
68
+ elif isinstance(op, ast.Gt):
69
+ condition = left > right_val
70
+ elif isinstance(op, ast.GtE):
71
+ condition = left >= right_val
72
+
73
+ if result is None:
74
+ result = condition
75
+ else:
76
+ result = z3.And(result, condition)
77
+
78
+ return result
79
+
80
+ def visit_BoolOp(self, node):
81
+ values = [self.visit(value) for value in node.values]
82
+
83
+ if isinstance(node.op, ast.And):
84
+ return z3.And(*values)
85
+ elif isinstance(node.op, ast.Or):
86
+ return z3.Or(*values)
87
+ else:
88
+ raise NotImplementedError(f"Operation {node.op} not implemented")
89
+
90
+ def convert(self, ast_node):
91
+ return self.visit(ast_node)
92
+
93
+ def ast_to_z3_constraint(branch_condition, param_types):
94
+ converter = ASTToZ3(param_types)
95
+ z3_expr = converter.convert(branch_condition.condition_ast)
96
+ branch_condition.z3_expr = z3_expr
97
+ return z3_expr, converter.z3_vars
98
+
99
+
@@ -0,0 +1,72 @@
1
+ import ast
2
+
3
+ class BranchCondition:
4
+ def __init__(self, condition_ast, line_number, variables):
5
+ self._condition_ast = condition_ast
6
+ self._line_number = line_number
7
+ self._variables = variables
8
+ self._z3_expr = None
9
+
10
+ @property
11
+ def condition_ast(self):
12
+ """Get the AST node representing the condition"""
13
+ return self._condition_ast
14
+
15
+ @condition_ast.setter
16
+ def condition_ast(self, value):
17
+ """Set the AST node representing the condition"""
18
+ self._condition_ast = value
19
+
20
+ @property
21
+ def line_number(self):
22
+ """Get the line number where this condition appears"""
23
+ return self._line_number
24
+
25
+ @line_number.setter
26
+ def line_number(self, value):
27
+ """Set the line number where this condition appears"""
28
+ self._line_number = value
29
+
30
+ @property
31
+ def variables(self):
32
+ """Get the variables used in this condition"""
33
+ return self._variables
34
+
35
+ @variables.setter
36
+ def variables(self, value):
37
+ """Set the variables used in this condition"""
38
+ self._variables = value
39
+
40
+ @property
41
+ def z3_expr(self):
42
+ """Get the Z3 expression for this condition"""
43
+ return self._z3_expr
44
+
45
+ @z3_expr.setter
46
+ def z3_expr(self, value):
47
+ """Set the Z3 expression for this condition"""
48
+ self._z3_expr = value
49
+
50
+ def __str__(self):
51
+ """Return a string representation of this branch condition"""
52
+ condition_text = ast.unparse(self.condition_ast) if self.condition_ast else "None"
53
+ vars_text = ", ".join(sorted(self.variables)) if self.variables else "None"
54
+ z3_text = str(self.z3_expr) if self.z3_expr else "None"
55
+
56
+ return (f"BranchCondition(line={self.line_number}, "
57
+ f"condition='{condition_text}', "
58
+ f"variables=[{vars_text}], "
59
+ f"z3_expr={z3_text})")
60
+
61
+ def __repr__(self):
62
+ """Return a string representation for debugging"""
63
+ return self.__str__()
64
+
65
+ def to_dict(self):
66
+ """Convert this branch condition to a dictionary"""
67
+ return {
68
+ 'line_number': self.line_number,
69
+ 'condition': ast.unparse(self.condition_ast) if self.condition_ast else None,
70
+ 'variables': sorted(list(self.variables)) if self.variables else [],
71
+ 'z3_expr': str(self.z3_expr) if self.z3_expr else None
72
+ }
@@ -0,0 +1,36 @@
1
+ import ast
2
+ from _ast import FunctionDef
3
+ from typing import List, Tuple
4
+ from testgen.util.z3_utils.branch_condition import BranchCondition
5
+ from testgen.util.z3_utils.variable_finder import VariableFinder
6
+
7
+ class ConstraintExtractor(ast.NodeVisitor):
8
+ def __init__(self):
9
+ self.branch_conditions = []
10
+ self.current_function = None
11
+ self.param_types = {}
12
+
13
+ def visit_FunctionDef(self, node: FunctionDef):
14
+ prev_function = self.current_function
15
+ self.current_function = node.name
16
+
17
+ for arg in node.args.args:
18
+ if arg.arg != 'self' and arg.annotation:
19
+ self.param_types[arg.arg] = ast.unparse(arg.annotation)
20
+
21
+ self.generic_visit(node)
22
+ self.current_function = prev_function
23
+
24
+ def visit_If(self, node):
25
+ variable_finder = VariableFinder()
26
+ variable_finder.visit(node.test)
27
+ variables = variable_finder.variables
28
+
29
+ self.branch_conditions.append(BranchCondition(node.test, node.test.lineno, variables))
30
+
31
+ self.generic_visit(node)
32
+
33
+ def extract_branch_conditions(func_node: ast.FunctionDef) -> Tuple[List[BranchCondition], dict]:
34
+ extractor = ConstraintExtractor()
35
+ extractor.visit(func_node)
36
+ return extractor.branch_conditions, extractor.param_types
@@ -0,0 +1,10 @@
1
+ import ast
2
+ from typing import List
3
+
4
+ class VariableFinder(ast.NodeVisitor):
5
+ def __init__(self):
6
+ self.variables = set()
7
+
8
+ def visit_Name(self, node):
9
+ if isinstance(node.ctx, ast.Load):
10
+ self.variables.add(node.id)
@@ -0,0 +1,94 @@
1
+ import ast
2
+ from typing import List
3
+
4
+ import z3
5
+
6
+ import testgen.util.file_utils
7
+ from testgen.models.test_case import TestCase
8
+ from testgen.util.z3_utils import ast_to_z3
9
+ from testgen.util.z3_utils.constraint_extractor import extract_branch_conditions
10
+
11
+
12
+ def solve_branch_condition(file_name: str, func_node: ast.FunctionDef, uncovered_lines: List[int]) -> List[TestCase]:
13
+ branch_conditions, param_types = extract_branch_conditions(func_node)
14
+ uncovered_conditions = [bc for bc in branch_conditions if bc.line_number in uncovered_lines]
15
+ test_cases = []
16
+
17
+ for branch_condition in uncovered_conditions:
18
+ z3_expr, z3_vars = ast_to_z3.ast_to_z3_constraint(branch_condition, param_types)
19
+ solver = z3.Solver()
20
+ solver.add(z3_expr)
21
+
22
+ if solver.check() == z3.sat:
23
+ model = solver.model()
24
+
25
+ # Create default values for all parameters
26
+ param_values = {}
27
+ for param_name in param_types:
28
+ # Set default values based on type
29
+ if param_types[param_name] == "int":
30
+ param_values[param_name] = 0
31
+ elif param_types[param_name] == "float":
32
+ param_values[param_name] = 0.0
33
+ elif param_types[param_name] == "bool":
34
+ param_values[param_name] = False
35
+ elif param_types[param_name] == "str":
36
+ param_values[param_name] = ""
37
+ else:
38
+ param_values[param_name] = None
39
+
40
+ # Update with model values where available
41
+ for var_name, z3_var in z3_vars.items():
42
+ if var_name in param_types and z3_var in model:
43
+ try:
44
+ if param_types[var_name] == "int":
45
+ param_values[var_name] = model[z3_var].as_long()
46
+ elif param_types[var_name] == "float":
47
+ param_values[var_name] = float(model[z3_var].as_decimal())
48
+ elif param_types[var_name] == "bool":
49
+ param_values[var_name] = z3.is_true(model[z3_var])
50
+ elif param_types[var_name] == "str":
51
+ param_values[var_name] = str(model[z3_var])
52
+ else:
53
+ param_values[var_name] = model[z3_var].as_long()
54
+ except Exception as e:
55
+ print(f"Error converting Z3 model value for {var_name}: {e}")
56
+
57
+ # Ensure all parameters are included in correct order
58
+ ordered_params = []
59
+ for arg in func_node.args.args:
60
+ arg_name = arg.arg
61
+ if arg_name == 'self': # Skip self parameter for class methods
62
+ continue
63
+ if arg_name in param_values:
64
+ ordered_params.append(param_values[arg_name])
65
+ else:
66
+ print(f"Warning: Missing value for parameter {arg_name}")
67
+ # Provide default values based on annotation if available
68
+ if hasattr(arg, 'annotation') and arg.annotation:
69
+ if isinstance(arg.annotation, ast.Name):
70
+ if arg.annotation.id == 'int':
71
+ ordered_params.append(0)
72
+ elif arg.annotation.id == 'float':
73
+ ordered_params.append(0.0)
74
+ elif arg.annotation.id == 'bool':
75
+ ordered_params.append(False)
76
+ elif arg.annotation.id == 'str':
77
+ ordered_params.append('')
78
+ else:
79
+ ordered_params.append(None)
80
+ else:
81
+ ordered_params.append(None)
82
+ else:
83
+ ordered_params.append(None)
84
+
85
+ func_name = func_node.name
86
+ try:
87
+ module = testgen.util.file_utils.load_module(file_name)
88
+ func = getattr(module, func_name)
89
+ result = func(*ordered_params)
90
+ test_cases.append(TestCase(func_name, tuple(ordered_params), result))
91
+ except Exception as e:
92
+ print(f"Error executing function with Z3 solution for {func_name}: {e}")
93
+
94
+ return test_cases
@@ -0,0 +1,24 @@
1
+ Metadata-Version: 2.3
2
+ Name: testgenie-py
3
+ Version: 0.1.0
4
+ Summary:
5
+ Author: cjseitz
6
+ Author-email: charlesjseitz@gmail.com
7
+ Requires-Python: >=3.10,<4.0
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: Programming Language :: Python :: 3.10
10
+ Classifier: Programming Language :: Python :: 3.11
11
+ Classifier: Programming Language :: Python :: 3.12
12
+ Classifier: Programming Language :: Python :: 3.13
13
+ Requires-Dist: ConfigArgParse (==1.7)
14
+ Requires-Dist: astor (==0.8.1)
15
+ Requires-Dist: atheris (==2.3.0)
16
+ Requires-Dist: coverage (==7.6.4)
17
+ Requires-Dist: klara (==0.6.3)
18
+ Requires-Dist: pytest (>=8.3.5,<9.0.0)
19
+ Requires-Dist: staticfg (>=0.9.5,<0.10.0)
20
+ Requires-Dist: typed-ast (==1.5.5)
21
+ Requires-Dist: z3-solver (==4.13.3.0)
22
+ Description-Content-Type: text/markdown
23
+
24
+
@@ -0,0 +1,68 @@
1
+ testgen/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ testgen/analyzer/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
+ testgen/analyzer/ast_analyzer.py,sha256=JmqiosxgZJm2fhNDr5VUBpKKHmf8S2HP9Jm0Xl7NnnI,6783
4
+ testgen/analyzer/contracts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
+ testgen/analyzer/contracts/contract.py,sha256=6rNYJOy_2GrOhGtaXTDIOX6pTEOqo856FxG0yTc8amI,369
6
+ testgen/analyzer/contracts/no_exception_contract.py,sha256=rTWTuu5XKmvzBPD6yNAqiNehk9lbWn_Z8zFj-_djZ_w,512
7
+ testgen/analyzer/contracts/nonnull_contract.py,sha256=uurnrVptImYTVpSnu8ckdlU6c94AbiOWFoH1YnAQU0w,508
8
+ testgen/analyzer/fuzz_analyzer.py,sha256=ktkDdh3mgHjcC4ZitGo9fa9RjnGqkdehaYJeSKssWss,4299
9
+ testgen/analyzer/random_feedback_analyzer.py,sha256=S_8iRNmgNa2wIlhLZV798H5QWY9zwKpSs2MFE61uV60,13114
10
+ testgen/analyzer/reinforcement_analyzer.py,sha256=U6W7g-xDFS_P0aqxjPRnaXjGp2gOC9TMdfWaetFV7eE,3568
11
+ testgen/analyzer/test_case_analyzer.py,sha256=foHRbz9K6WAn711sXbp-smJHDjI8GTG8F2TpovLZVEo,1530
12
+ testgen/analyzer/test_case_analyzer_context.py,sha256=7umDPHBjoTaCRvZOdNynpnWsr14Gy0E2hpMBPK8mz3Q,2128
13
+ testgen/controller/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
+ testgen/controller/cli_controller.py,sha256=dKtqQMGw1IYRQox5gmQr53KAxEtrhesUdvI0KJkMjBo,8242
15
+ testgen/controller/docker_controller.py,sha256=fBRJFdY5NU6ipRY7Gihs-IA-EcpSa79Xu6GVh6_eaxk,6601
16
+ testgen/docker/Dockerfile,sha256=_xr3CWP9hhBIZbf4qRzWewBUAIkXoZGAh36g3yXpAbc,513
17
+ testgen/docker/poetry.lock,sha256=Xg2WyFgruylJ51Pvfi03Hc-VDeKj3f5DhM56XIXRBpI,30057
18
+ testgen/docker/pyproject.toml,sha256=QToniOghAyI6Hp5V-OWknO3Mo7cpa_HCV5lqynYYuPA,438
19
+ testgen/generator/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
20
+ testgen/generator/code_generator.py,sha256=V5Donxz3r3ZW56xyyldJwOuDBaX6e8NOyPc8UzllQs8,2467
21
+ testgen/generator/doctest_generator.py,sha256=Dkaf2l72ENk1mqNP3WkOnIY-iqrTHh-443AWtxzRWGY,8806
22
+ testgen/generator/generator.py,sha256=9M9zg8DO0uU5W5s9hsz2oPCL7bz7sAD087M5TYottSs,2007
23
+ testgen/generator/pytest_generator.py,sha256=ZjQKPHlizFK2yx9WabAxkW9sM-xa64d08IIQibnvwuk,3369
24
+ testgen/generator/test_generator.py,sha256=D2Y3DaWH4fdIc5_9Xrznrkm0urFfhpYxuhL81M7RRaw,710
25
+ testgen/generator/unit_test_generator.py,sha256=yXg7_A0nOR0jhOfz7yzL6C_6pwoNCwf19Bpr_RW_41I,3596
26
+ testgen/inspector/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
27
+ testgen/inspector/inspector.py,sha256=llDy03j8cz6Bk6HwSm20B8XvR5QaSxGXyNYyQxom25E,1816
28
+ testgen/main.py,sha256=zpLLi8HtPB6p3uMTKPrsRQDREP4i-ZqrOBwroW0XekM,385
29
+ testgen/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
30
+ testgen/models/analysis_context.py,sha256=-mhw_hn26MgF6aJnmj6Hub5jfCi8gmvcf4QNM4l7G2s,1442
31
+ testgen/models/function_metadata.py,sha256=t2lNSycFamuec7q3fiabq6aVO5XN0bylEU7mdup7Ezc,1587
32
+ testgen/models/generator_context.py,sha256=V-T9i-3Ar-gdBzQqidyqBb05PTmOu2LtdQdAIX3aaGk,1693
33
+ testgen/models/test_case.py,sha256=jwodn-6fKHCh4SO2qycbrFyggCb9UlwTZ8k3RdTObDQ,216
34
+ testgen/presentation/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
35
+ testgen/presentation/cli_view.py,sha256=2fZrsvZ-Wi4j37UvogsK9_yQV5o3A20jowIr6iFRu-s,296
36
+ testgen/q_table/global_q_table.json,sha256=T1EOATQ6L9FJL8bI3HxavYBdH8l95qGC5AdiUFz2ohM,6528
37
+ testgen/reinforcement/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
38
+ testgen/reinforcement/abstract_state.py,sha256=M9Kp8fyJzsTzpyL3ca4HjjYpGXy9DRMw-IG7OgFVisY,154
39
+ testgen/reinforcement/agent.py,sha256=wvgbi-OVoVJMwhasGgsP2y1TKLiC5qjjTwZBNqKNRns,6098
40
+ testgen/reinforcement/environment.py,sha256=z9ENIkbiB0N9Dbhm8yruQeSV1h4sK0QDkDRF_IO1VtI,8601
41
+ testgen/reinforcement/statement_coverage_state.py,sha256=hyoxkpOi_vdtjuAZ3PDz_fECurqWeNjeIhtng5TARCk,1523
42
+ testgen/service/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
43
+ testgen/service/analysis_service.py,sha256=SvQEhwbE_lWTRrWdT70C4kbh-H2xxf0mP8zlqSX_xqI,10670
44
+ testgen/service/cfg_service.py,sha256=7QWNM7WgX6iEwAV1qJuacKEAYihHyDqsOEMlu5Z3aA0,2207
45
+ testgen/service/generator_service.py,sha256=iKDPyCDlektRDLD6pLrR0CWiAF81xezkFHGyT31mre8,6920
46
+ testgen/service/service.py,sha256=WcCf8SOYAoElwFoYFpsWfZk8V675AY0pot5-QQp7AP4,15407
47
+ testgen/sqlite/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
48
+ testgen/sqlite/db.py,sha256=RUt88ndT4CQRo9aZzLGXPHRK1iw0LyDEGnoWlOLzKGM,2390
49
+ testgen/sqlite/db_service.py,sha256=i87YkhMP0VNyug5p1tWUvnzHB8isFcSIRe9vJJTmFLA,8954
50
+ testgen/tree/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
51
+ testgen/tree/node.py,sha256=ONJtbACShN4yNj1X-UslFRgLyBP6mrbg7qZr3c6dWyA,165
52
+ testgen/tree/tree_utils.py,sha256=gT7jucky6_GWVOlDI6jpv6RMeWCkntGOHIYLvHxD85k,2122
53
+ testgen/util/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
54
+ testgen/util/coverage_utils.py,sha256=lmta8F-ASsZpaAOs_YucSTHNHHEn4M0rUR7eeboZtZc,6044
55
+ testgen/util/coverage_visualizer.py,sha256=rYmwV4uTo02YAVPy3KKlLyKofr3IuhytFBNanu0z6Ok,5668
56
+ testgen/util/file_utils.py,sha256=P6zzABvuTlO2EAJdgFKwNxKNF_HHD0vcSkROeHrYTbg,3699
57
+ testgen/util/randomizer.py,sha256=hAW9szYhPWyQEkn7NTFuJRRIoYcVmvnzMf3dDwWdMKM,4479
58
+ testgen/util/utils.py,sha256=_TPXveAcI_TR9XLU8qaDx63CrZJDvpzSWl_gfYchJz0,5665
59
+ testgen/util/z3_utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
60
+ testgen/util/z3_utils/ast_to_z3.py,sha256=V87cvlH2OlO7_owuVTqygymMmK_FyesBovi6qe-BUcg,3180
61
+ testgen/util/z3_utils/branch_condition.py,sha256=N9FNR-iJmxIC62NpDQNVZ1OP14rXXqYzdA_NODPDUm4,2453
62
+ testgen/util/z3_utils/constraint_extractor.py,sha256=RXJLpmk6dAvHZ27839VXKXNtdy9St1F-17-pSEFu4bM,1285
63
+ testgen/util/z3_utils/variable_finder.py,sha256=dUh3F9_L_BDMz1ybiGss09LLcM_egbitgj0FT5Nh9u4,245
64
+ testgen/util/z3_utils/z3_test_case.py,sha256=cAafR5x7YMsWnqVFYU21h2jHO-SiaTDPdKe44cGQ5_M,4409
65
+ testgenie_py-0.1.0.dist-info/METADATA,sha256=Cs5-bhHuOerWHIaHz4xK84JHOQoALkFzU8xGUes08RE,764
66
+ testgenie_py-0.1.0.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
67
+ testgenie_py-0.1.0.dist-info/entry_points.txt,sha256=K52WcOoqyoG657-9IdKsDCBS_nJyuV4BhVtGzoomkL4,39
68
+ testgenie_py-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: poetry-core 2.1.2
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,3 @@
1
+ [console_scripts]
2
+ testgenie=main:main
3
+