Skip to content

Instantly share code, notes, and snippets.

@Samyak2
Last active December 9, 2021 07:56
Show Gist options
  • Save Samyak2/20eaef27510506fc74408f59cdcb3a2c to your computer and use it in GitHub Desktop.
Save Samyak2/20eaef27510506fc74408f59cdcb3a2c to your computer and use it in GitHub Desktop.
Random test case generator and tester for intal in C
# this is a testing file for intal (integer of arbitrary length) in C, to be used with the python file
# Steps to use
# 1. Compile with the main file (which is here - https://gist.github.com/Samyak2/d0c2552b11581f59091f9f377bbc65f0)
# 1.1 Make sure the executable is named `intal` (using `-o intal` during compiling)
# 2. Make sure python version is >=3.6 and scipy is installed
# 3. Run this script
# excuse the bad code, it was only intended to work
# Here is another version to test the time complexity - https://gist.github.com/Samyak2/a2975ec738e76dd7ead1147db3c0ef93
# Author: Samyak S Sarnayak
import sys
import subprocess
import random
import operator
import math
import scipy.special
def fibonacci(n):
a = 0
b = 1
if n == 0:
return a
if n == 1:
return b
for _ in range(2, n+1):
c = a + b
a = b
b = c
return b
def coin_row_problem(arr, s):
n = len(arr)
if n == 0:
return 0
prev = 0
cur = arr[0]
for i in range(1, n):
next_ = max(prev+arr[i], cur)
prev = cur
cur = next_
return cur
max_ = 10**1000
def test_intal_outs_binary(operation, name, cases=100, max1=max_//2, max2=max_//2):
passed = 0
skipped = 0
total_time = 0.0
max_time = 0.0
for _ in range(cases):
a = random.randrange(0, max1)
b = random.randrange(0, max2)
try:
expected_res = operation(a, b)
if expected_res > max_:
# print(f"Skipped a test case due to result being huge. {a} {name} {b} = {expected_res}")
skipped += 1
continue
p = subprocess.run(["./intal", name], check=True,
input=f"{a}\n{b}\n",
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
encoding="ascii")
# res = int(p.stdout.strip())
res, time = p.stdout.strip().split()
res = res.strip() # int(res)
expected_res = str(expected_res)
time = float(time)
if time > max_time:
max_time = time
total_time += time
if res == expected_res:
passed += 1
else:
print(f"Test failed: {a} {name} {b} = {expected_res} != {res}", file=sys.stderr)
except subprocess.CalledProcessError as e:
print(f"Test failed: for a = {a}, b = {b}. Error: {e}", file=sys.stderr)
except OverflowError as e:
print(f"Test failed due to overflow {a} {name} {b}", file=sys.stderr)
except ValueError as e:
print(f"Test failed due to invalid output: {a} {name} {b} = {expected_res}. Error: {e}", file=sys.stderr)
avg_time = (total_time*1000)/passed if passed > 0 else "N/A"
print(f"{passed} tests passed, {skipped} tests skipped out of {cases} for {name}. Average time taken: {avg_time}ms. Maximum time: {max_time*1000}ms")
def test_intal_outs_unary(operation, name, cases=100, max1=100):
passed = 0
skipped = 0
total_time = 0.0
max_time = 0.0
for _ in range(cases):
a = random.randrange(0, max1)
try:
expected_res = operation(a)
if expected_res > max_:
# print(f"Skipped a test case due to result being huge. {name} {a} = {expected_res}")
skipped += 1
continue
p = subprocess.run(["./intal", name], check=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
input=f"{a}\n",
encoding="ascii")
# res = int(p.stdout.strip())
res, time = p.stdout.strip().split()
res = res.strip() # int(res)
expected_res = str(expected_res)
time = float(time)
if time > max_time:
max_time = time
total_time += time
if res == expected_res:
passed += 1
else:
print(f"Test failed: {name} {a} = {expected_res} != {res}", file=sys.stderr)
except subprocess.CalledProcessError as e:
print(f"Test failed: for a = {a}. Error: {e}", file=sys.stderr)
except OverflowError as e:
print(f"Test failed due to overflow {name} {a}", file=sys.stderr)
except ValueError as e:
print(f"Test failed due to invalid output: {name} {a} = {expected_res}. Error: {e}", file=sys.stderr)
avg_time = (total_time*1000)/passed if passed > 0 else "N/A"
print(f"{passed} tests passed, {skipped} tests skipped out of {cases} for {name}. Average time taken: {avg_time}ms. Maximum time: {max_time*1000}ms")
def test_intal_outs_array(operation, name, extra_inp=False, extra_inp_from_arr=False, cases=100, arraylength=50, max1=max_, sort=False,
check_sort=False):
passed = 0
skipped = 0
total_time = 0.0
max_time = 0.0
for __ in range(cases):
arr = [random.randrange(0, max1) for _ in range(arraylength)]
if sort:
arr.sort()
if extra_inp:
if extra_inp_from_arr:
s = random.choice(arr)
else:
s = random.randrange(0, max1)
else:
s = None
try:
expected_res = operation(arr, s)
if not check_sort:
if expected_res > max_:
skipped += 1
continue
p = subprocess.run(["./intal", "array", name], check=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
input="{}\n{}\n".format(arraylength, '\n'.join(map(str, arr if s is None else arr+[s]))),
encoding="ascii")
# res = int(p.stdout.strip())
if not check_sort:
res, time = p.stdout.strip().split()
res = res.strip() # int(res)
expected_res = str(expected_res)
else:
res = p.stdout.strip().split()
time = res[-1]
res = res[:-1]
res = [str(res_).strip() for res_ in res]
expected_res = [str(res_) for res_ in expected_res]
time = float(time)
if time > max_time:
max_time = time
total_time += time
if res == expected_res:
passed += 1
else:
print(f"Test failed: {name} {[len(str(a)) for a in arr]} = {expected_res} != {res}", file=sys.stderr)
except subprocess.CalledProcessError as e:
print(f"Test failed: for a = {[len(str(a)) for a in arr]}. Error: {e}", file=sys.stderr)
except OverflowError as e:
print(f"Test failed due to overflow {name} {[len(str(a)) for a in arr]}", file=sys.stderr)
except ValueError as e:
print(f"Test failed due to invalid output: {name} {[len(str(a)) for a in arr]} = {expected_res}. Error: {e}", file=sys.stderr)
avg_time = (total_time*1000)/passed if passed > 0 else "N/A"
print(f"{passed} tests passed, {skipped} tests skipped out of {cases} for {name}. Average time taken: {avg_time}ms. Maximum time: {max_time*1000}ms")
# this feature was implemented by Rehan in his fork. Source: https://gist.github.com/rehanvipin/2bcbe40fb9e25b44c3439f9855df98fb
all_tests = ["add", "diff", "multiply", "mod", "bincoeff", "gcd", "pow", "fibo", "fact", "min", "max", "search", "binsearch", "sort", "coinrow"]
print("Which functions do you want to test?")
for index, _test in enumerate(all_tests):
print(index, _test)
print("Enter your choices, index numbers, separated by a comma, enter 12345 to test them all")
choices = list(map(int, input().split(",")))
use_all = False
if 12345 in choices:
use_all = True
if 0 in choices or use_all:
test_intal_outs_binary(operator.add, "add")
if 1 in choices or use_all:
test_intal_outs_binary(lambda a, b: operator.abs(operator.sub(a, b)), "diff")
if 2 in choices or use_all:
test_intal_outs_binary(operator.mul, "multiply", max1=10**100, max2=10**10)
if 3 in choices or use_all:
test_intal_outs_binary(operator.mod, "mod")
if 4 in choices or use_all:
test_intal_outs_binary(lambda n, k: scipy.special.comb(n, k, exact=True), "bincoeff",
max1=1000,
max2=1000)
if 5 in choices or use_all:
test_intal_outs_binary(math.gcd, "gcd")
if 6 in choices or use_all:
test_intal_outs_binary(operator.pow, "pow", max1=10**3, max2=10**2)
if 7 in choices or use_all:
test_intal_outs_unary(fibonacci, "fibo")
if 8 in choices or use_all:
test_intal_outs_unary(math.factorial, "fact")
if 9 in choices or use_all:
test_intal_outs_array(lambda arr, s: min(enumerate(arr), key=lambda p: p[1])[0], "min")
if 10 in choices or use_all:
test_intal_outs_array(lambda arr, s: max(enumerate(arr), key=lambda p: p[1])[0], "max")
if 11 in choices or use_all:
test_intal_outs_array(lambda arr, s: arr.index(s) if s in arr else -1, "search", extra_inp=True)
test_intal_outs_array(lambda arr, s: arr.index(s) if s in arr else -1, "search", extra_inp=True, extra_inp_from_arr=True)
if 12 in choices or use_all:
test_intal_outs_array(lambda arr, s: arr.index(s) if s in arr else -1, "binsearch", extra_inp=True, sort=True)
test_intal_outs_array(lambda arr, s: arr.index(s) if s in arr else -1, "binsearch", extra_inp=True, extra_inp_from_arr=True, sort=True)
if 13 in choices or use_all:
test_intal_outs_array(lambda arr, s: sorted(arr), "sort", check_sort=True)
test_intal_outs_array(lambda arr, s: sorted(arr), "sort", check_sort=True, sort=True)
if 14 in choices or use_all:
test_intal_outs_array(coin_row_problem, "coinrow", max1=10*100)
test_intal_outs_array(coin_row_problem, "coinrow", max1=10*100, sort=True)
@KulkarniKaustubh
Copy link

KulkarniKaustubh commented May 19, 2020

I am getting a Permission Error. Any idea on how to solve this?

Traceback (most recent call last):
  File "tests.py", line 195, in <module>
    test_intal_outs_binary(operator.add, "add")
  File "tests.py", line 73, in test_intal_outs_binary
    p = subprocess.run(["./intal", name], check=True,
  File "/usr/lib/python3.8/subprocess.py", line 489, in run
    with Popen(*popenargs, **kwargs) as process:
  File "/usr/lib/python3.8/subprocess.py", line 854, in __init__
    self._execute_child(args, executable, preexec_fn, close_fds,
  File "/usr/lib/python3.8/subprocess.py", line 1702, in _execute_child
    raise child_exception_type(errno_num, err_msg, err_filename)
PermissionError: [Errno 13] Permission denied: './intal'

@Samyak2
Copy link
Author

Samyak2 commented May 19, 2020

I am getting a Permission Error. Any idea on how to solve this?

Traceback (most recent call last):
  File "tests.py", line 195, in <module>
    test_intal_outs_binary(operator.add, "add")
  File "tests.py", line 73, in test_intal_outs_binary
    p = subprocess.run(["./intal", name], check=True,
  File "/usr/lib/python3.8/subprocess.py", line 489, in run
    with Popen(*popenargs, **kwargs) as process:
  File "/usr/lib/python3.8/subprocess.py", line 854, in __init__
    self._execute_child(args, executable, preexec_fn, close_fds,
  File "/usr/lib/python3.8/subprocess.py", line 1702, in _execute_child
    raise child_exception_type(errno_num, err_msg, err_filename)
PermissionError: [Errno 13] Permission denied: './intal'

I'm not sure. Are you on Windows? If so, you could try naming the output file intal.exe and replace all ./intal in the code with intal.exe or .\intal.exe.

@KulkarniKaustubh
Copy link

I am getting a Permission Error. Any idea on how to solve this?

Traceback (most recent call last):
  File "tests.py", line 195, in <module>
    test_intal_outs_binary(operator.add, "add")
  File "tests.py", line 73, in test_intal_outs_binary
    p = subprocess.run(["./intal", name], check=True,
  File "/usr/lib/python3.8/subprocess.py", line 489, in run
    with Popen(*popenargs, **kwargs) as process:
  File "/usr/lib/python3.8/subprocess.py", line 854, in __init__
    self._execute_child(args, executable, preexec_fn, close_fds,
  File "/usr/lib/python3.8/subprocess.py", line 1702, in _execute_child
    raise child_exception_type(errno_num, err_msg, err_filename)
PermissionError: [Errno 13] Permission denied: './intal'

I'm not sure. Are you on Windows? If so, you could try naming the output file intal.exe and replace all ./intal in the code with intal.exe or .\intal.exe.

Nope. I'm using Ubuntu.

@Samyak2
Copy link
Author

Samyak2 commented May 19, 2020

Try chmod u+x intal, this will make sure that the executable you generated using the main.c file can be executed.

@coconutlad
Copy link

Hello,
Awesome work! Thank you very much!
I've added this feature for testing functions individually, would you please look at it and merge if possible?
I just forked and added some if conditions : https://gist.github.com/rehanvipin/2bcbe40fb9e25b44c3439f9855df98fb
, couldn't find anything here for making pull requests though.

@Samyak2
Copy link
Author

Samyak2 commented May 20, 2020

Hello,
Awesome work! Thank you very much!
I've added this feature for testing functions individually, would you please look at it and merge if possible?
I just forked and added some if conditions : https://gist.github.com/rehanvipin/2bcbe40fb9e25b44c3439f9855df98fb
, couldn't find anything here for making pull requests though.

Thanks! I'll merge it.

@KulkarniKaustubh
Copy link

Try chmod u+x intal, this will make sure that the executable you generated using the main.c file can be executed.

The error was because I had not downloaded main.c. The tests worked fine after that 👍.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment