Skip to content

Commit f81412d

Browse files
committed
refactor folder structure and update prompt
1 parent b0ab5fa commit f81412d

35 files changed

+136
-253
lines changed

MANIFEST.in

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
include src/mutahunter/core/pilot/aider/queries/*.scm
1+
include src/mutahunter/core/queries/*.scm

README.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ Mutahunter uses LLM models to inject context-aware faults into your codebase. Th
3030

3131
## Features
3232

33-
- **Extreme Mutation Testing:** Leverages language agnostic [TreeSitter](https://tree-sitter.github.io/) parser to apply extreme mutations to the codebase without using LLMs. [Research](https://arxiv.org/abs/2103.08480) shows that this approach is effective at detecting pseudo-tested methods with significantly lower computational cost. Currently supports Python, Java, JavaScript, and Go. Check the [scheme files](/src/mutahunter/core/pilot/aider/queries/) to see the supported operators. We welcome contributions to add more operators and languages.
33+
- **Extreme Mutation Testing:** Leverages language agnostic [TreeSitter](https://tree-sitter.github.io/) parser to apply extreme mutations to the codebase without using LLMs. [Research](https://arxiv.org/abs/2103.08480) shows that this approach is effective at detecting pseudo-tested methods with significantly lower computational cost. Currently supports Python, Java, JavaScript, and Go. Check the [scheme files](/src/mutahunter/core/queries/) to see the supported operators. We welcome contributions to add more operators and languages.
3434
- **LLM Context-aware Mutations:** Utilizes LLM models to generate context-aware mutants. [Research](https://arxiv.org/abs/2406.09843) indicates that LLM-generated mutants have higher fault detection potential, fewer equivalent mutants, and higher coupling and semantic similarity to real faults. It uses a map of your entire git repository to generate contextually relevant mutants using [aider's repomap](https://aider.chat/docs/repomap.html). Supports self-hosted LLMs, Anthropic, OpenAI, and any LLM models via [LiteLLM](https://github.com/BerriAI/litellm).
3535
- **Change-Based Testing:** Runs mutation tests on modified files and lines based on the latest commit or pull request changes, ensuring that only relevant parts of the code are tested.
3636
- **Language Agnostic:** Compatible with languages that provide coverage reports in Cobertura XML, Jacoco XML, and lcov formats. Extensible to additional languages and testing frameworks.
@@ -172,7 +172,6 @@ jobs:
172172
173173
Help us improve Mutahunter and get rewarded! We have a cash bounty program to incentivize contributions to the project. Check out the [bounty board](https://docs.google.com/spreadsheets/d/1cT2_O55m5txrUgZV81g1gtqE_ZDu9LlzgbpNa_HIisc/edit?gid=0#gid=0) to see the available bounties and claim one today!
174174
175-
176175
## Acknowledgements
177176
178177
Mutahunter makes use of the following open-source libraries:

pyproject.toml

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,10 @@ dependencies = [
2525
'scipy',
2626
'setuptools',
2727
'jinja2',
28-
'litellm'
28+
'litellm',
2929
]
3030

31-
authors = [
32-
{ name = "Steven Jung", email = "[email protected]" },
33-
]
31+
authors = [{ name = "Steven Jung", email = "[email protected]" }]
3432

3533
[project.optional-dependencies]
3634
dev = ['isort', 'black']
@@ -40,4 +38,4 @@ testing = ['pytest']
4038
mutahunter = "mutahunter.main:run"
4139

4240
[tool.setuptools.package-data]
43-
mutahunter = ['src/mutahunter/core/pilot/aider/queries/*.scm']
41+
mutahunter = ['src/mutahunter/core/queries/*.scm']

src/mutahunter/core/analyzer.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,7 @@ def _load_query_scm(self, lang: str) -> str:
334334
"""
335335
try:
336336
scm_fname = resources.files(__package__).joinpath(
337-
"pilot", "aider", "queries", f"tree-sitter-{lang}-tags.scm"
337+
"queries", f"tree-sitter-{lang}-tags.scm"
338338
)
339339
except KeyError:
340340
return ""

src/mutahunter/core/mutator.py

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
from jinja2 import Template
77

88
from mutahunter.core.logger import logger
9-
from mutahunter.core.pilot.aider.repomap import RepoMap
10-
from mutahunter.core.pilot.prompts.factory import PromptFactory
9+
from mutahunter.core.repomap import RepoMap
10+
from mutahunter.core.prompts.factory import PromptFactory
1111

1212

1313
class MutationStrategy:
@@ -42,15 +42,12 @@ def generate_mutations(
4242
):
4343
start_byte = function_block.start_byte
4444
end_byte = function_block.end_byte
45-
function_name = function_block.child_by_field_name("name").text.decode(
46-
"utf8"
47-
)
45+
4846
mutant_generator = MutantGenerator(
4947
config=hunter.config,
5048
executed_lines=executed_lines,
5149
cov_files=list(hunter.analyzer.file_lines_executed.keys()),
5250
source_file_path=file_path,
53-
function_name=function_name,
5451
start_byte=start_byte,
5552
end_byte=end_byte,
5653
router=hunter.router,
@@ -96,7 +93,6 @@ def __init__(
9693
executed_lines,
9794
cov_files,
9895
source_file_path, # file_path for the source code
99-
function_name,
10096
start_byte,
10197
end_byte,
10298
router,
@@ -105,7 +101,6 @@ def __init__(
105101
self.executed_lines = executed_lines
106102
self.cov_files = cov_files
107103
self.source_file_path = source_file_path
108-
self.function_name = function_name
109104
self.start_byte = start_byte
110105
self.end_byte = end_byte
111106
self.router = router
@@ -121,22 +116,36 @@ def get_function_block_source_code(self):
121116
return src_code[self.start_byte : self.end_byte].decode("utf-8")
122117

123118
def generate_mutant(self, repo_map_result):
124-
system_template = Template(self.prompt.system_prompt).render()
119+
# add line number for each line of code
120+
function_block_with_line_num = "\n".join(
121+
[
122+
f"{i + 1} {line}"
123+
for i, line in enumerate(self.function_block_source_code.splitlines())
124+
]
125+
)
126+
system_template = Template(self.prompt.system_prompt).render(
127+
language=self.language
128+
)
125129
user_template = Template(self.prompt.user_prompt).render(
126130
language=self.language,
127-
covered_lines=self.executed_lines,
128131
ast=repo_map_result,
129-
function_name=self.function_name,
132+
covered_lines=self.executed_lines,
130133
example_output=self.prompt.example_output,
131-
function_block=self.function_block_source_code,
134+
function_block=function_block_with_line_num,
135+
maximum_num_of_mutants_per_function_block=3,
132136
)
133137
prompt = {
134138
"system": system_template,
135139
"user": user_template,
136140
}
141+
print("system_template:", system_template)
142+
print("user_template:", user_template)
143+
144+
exit()
137145
model_response, _, _ = self.router.generate_response(
138146
prompt=prompt, streaming=True
139147
)
148+
# print("model_response", model_response)
140149
return model_response
141150

142151
def generate(self):
@@ -150,6 +159,7 @@ def generate(self):
150159
ai_reply = self.generate_mutant(repo_map_result)
151160
mutation_info = self.extract_json_from_reply(ai_reply)
152161
changes = mutation_info["changes"]
162+
print("changes:", len(changes))
153163
original_lines = self.function_block_source_code.splitlines(keepends=True)
154164
for change in changes:
155165
original_line = change["original_line"]

src/mutahunter/core/pilot/aider/queries/__init__.py

Whitespace-only changes.

src/mutahunter/core/pilot/prompts/__init__.py

Whitespace-only changes.

src/mutahunter/core/pilot/prompts/system.py

Lines changed: 0 additions & 18 deletions
This file was deleted.

src/mutahunter/core/pilot/prompts/user.py

Lines changed: 0 additions & 29 deletions
This file was deleted.

0 commit comments

Comments
 (0)