Skip to content

Commit

Permalink
Add a yarpgen wrapper
Browse files Browse the repository at this point in the history
  • Loading branch information
thetheodor committed Apr 25, 2024
1 parent 0280b33 commit c080bc4
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 3 deletions.
4 changes: 2 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
repos:
- repo: https://github.com/psf/black
rev: 24.2.0
rev: 24.4.1
hooks:
- id: black
- repo: https://github.com/PyCQA/isort
Expand All @@ -13,7 +13,7 @@ repos:
hooks:
- id: flake8
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.8.0
rev: v1.10.0
hooks:
- id: mypy
additional_dependencies: [pytest >= 7.0.0]
Expand Down
80 changes: 80 additions & 0 deletions diopter/generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

from diopter.compiler import Language, SourceProgram
from diopter.sanitizer import Sanitizer
from diopter.utils import TempDirEnv


def dummy_func(generator: Generator) -> SourceProgram:
Expand Down Expand Up @@ -187,3 +188,82 @@ def filter_program(self, program: SourceProgram) -> bool:
):
return False
return bool(self.sanitizer.sanitize(program))


class YarpGen(Generator):
def __init__(
self,
sanitizer: Sanitizer,
yarpgen: str | None = None,
language: Language = Language.C,
additional_flags: tuple[str, ...] = (),
minimum_length: int = 10000,
maximum_length: int = 50000,
):
"""
Args:
sanitizer (Sanitizer):
used to sanitize and discard generated code
yarpgen (str | None):
Path to yarpgen executable, if empty "csmith" will be used
language (Language):
The language of the generated code (--std flag).
additional_flags (tuple[str, ...]):
Additional flags to pass to yarpgen.
minimum_length (int):
The minimum length of a generated test case in characters.
maximum_length (int):
The maximum length of a generated test case in characters.
"""
super().__init__(sanitizer)
self.minimum_length = minimum_length
self.maximum_length = maximum_length
self.yarpgen = yarpgen if yarpgen else "yarpgen"
self.language = language
self.additional_flags = additional_flags

if not which(self.yarpgen):
raise ValueError(f"Invalid yarpgen executable: {self.yarpgen}")

def generate_program_impl(self) -> SourceProgram:
"""Generate random code with yarpgen.
Returns:
SourceProgram: yarpgen generated program.
"""

lang_flag = {
Language.C: "--std=c",
Language.CPP: "--std=c++",
}[self.language]
with TempDirEnv() as temp_dir:
cmd = [self.yarpgen, lang_flag, "-o", str(temp_dir.resolve())] + list(
self.additional_flags
)
result = subprocess.run(
cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT
)
assert result.returncode == 0, result.stdout.decode("utf-8")
driver_str = (temp_dir / ("driver" + self.language.to_suffix())).read_text()
func_str = (
(temp_dir / ("func" + self.language.to_suffix()))
.read_text()
.replace('#include "init.h"', "")
)

return SourceProgram(
code=driver_str + "\n" + func_str,
language=self.language,
defined_macros=(),
include_paths=(),
system_include_paths=(),
flags=(),
)

def filter_program(self, program: SourceProgram) -> bool:
if (
len(program.code) < self.minimum_length
or len(program.code) > self.maximum_length
):
return False
return bool(self.sanitizer.sanitize(program))
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[metadata]
name = diopter
version = 0.0.27
version = 0.0.28
author = Theodoros Theodoridis, Yann Girsberger
author_email = [email protected]
description = A library for building differential tests
Expand Down

0 comments on commit c080bc4

Please sign in to comment.