Skip to content

Commit

Permalink
Add random testcase generator for large but realistic setups
Browse files Browse the repository at this point in the history
  • Loading branch information
florianschanda committed Oct 24, 2023
1 parent 549c209 commit 405db53
Showing 1 changed file with 150 additions and 0 deletions.
150 changes: 150 additions & 0 deletions util/large-test-generator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
#!/usr/bin/env python3

import os
import argparse
import random
from pprint import pprint

STRING_CONTENT_SINGLE = "".join(chr(c)
for c in range(0x200)
if (chr(c).isprintable() and
chr(c) != "\n"))
STRING_CONTENT_TRIPLE = "".join(chr(c)
for c in range(0x200)
if chr(c).isprintable())

def generate_string(options):
if random.randint(0, 1):
delim = '"'
content = STRING_CONTENT_SINGLE
escape = '"'
banned = "\\"
else:
delim = "'''"
content = STRING_CONTENT_TRIPLE
escape = None
banned = "'"

string = "".join(random.choice(content)
for _ in range(random.randint(25, 200)))

if banned is not None:
string = string.replace(banned, "")

if escape is not None:
string = string.replace(escape, "\\" + escape)

return delim + string + delim


def generate_tests(options):
random.seed(42)


packages = ["generic"]
for i in range(options.packages - 1):
packages.append("package_%u" % (i + 1))

with open("generic.rsl", "w") as fd:
fd.write("package generic\n\n")
fd.write("type Requirement {\n")
fd.write(" description optional String\n")
fd.write(" links optional Requirement [1 .. *]\n")
fd.write("}\n")

tree = {pkg: set() for pkg in packages}
for pkg_id, pkg in enumerate(packages[1:], 1):
tree[pkg].add("generic")
tree[pkg] |= set(random.choices(
packages[1:pkg_id] + packages[pkg_id + 1:],
k = random.randint(0, options.max_imports_per_package)))

# packages -> files -> items
items = {}
pkg_items = {"generic" : []}
for pkg_name in packages[1:]:
items[pkg_name] = {}
pkg_items[pkg_name] = []
num_files = random.randint(1, options.max_files_per_package)
num_items = random.randint(options.max_items_per_package // 3,
options.max_items_per_package)
offset = 1
for file_id in range(1, num_files + 1):
file_name = "%s_%u.trlc" % (pkg_name,
file_id)
if file_id == num_files:
item_count = num_items
else:
item_count = random.randint(0, num_items * 2 // 3)
num_items -= item_count

items[pkg_name][file_name] = ["Item_%u" % (offset + item_id)
for item_id in range(item_count)]
pkg_items[pkg_name] += items[pkg_name][file_name]
offset += item_count

total_pkg = 1
total_items = 0
for pkg_name in packages[1:]:
total_pkg += 1
with open(pkg_name + ".rsl", "w") as fd:
fd.write("package %s\n\n" % pkg_name)
for file_name in items[pkg_name]:
with open(file_name, "w") as fd:
fd.write("package %s\n" % pkg_name)
for import_name in tree[pkg_name]:
fd.write("import %s\n" % import_name)
fd.write("\n")

for item_name in items[pkg_name][file_name]:
total_items += 1
links = random.choices(
pkg_items[pkg_name] +
["%s.%s" % (p_name, i_name)
for p_name in tree[pkg_name]
for i_name in pkg_items[p_name]],
k = random.randint(0, options.max_links_per_item))
fd.write("generic.Requirement %s {\n" % item_name)
fd.write(" description = %s\n" % generate_string(options))
if links:
fd.write(" links = [%s]\n" % ", ".join(links))
fd.write("}\n\n")

print("Wrote %u items over %u packages." % (total_items,
total_pkg))

def main():
ap = argparse.ArgumentParser()
ap.add_argument("target",
help="generate test in this directory")
ap.add_argument("--packages",
type=int,
default=100)
ap.add_argument("--max-files-per-package",
type=int,
default=10)
ap.add_argument("--max-items-per-package",
type=int,
default=1500)
ap.add_argument("--max-imports-per-package",
type=int,
default=2)
ap.add_argument("--max-links-per-item",
type=int,
default=5)

options = ap.parse_args()

if os.path.isdir(options.target):
pass
elif not os.path.exists(options.target):
os.mkdir(options.target)
else:
ap.error("%s exists and is not a directory" % options.target)

os.chdir(options.target)
generate_tests(options)


if __name__ == "__main__":
main()

0 comments on commit 405db53

Please sign in to comment.