Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bash env packing #343

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions check50/_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,10 +161,16 @@ def __init__(self, command, env={}):
full_env = os.environ.copy()
full_env.update(env)

# load in env into bash manually via export commands
bash_command = ""
for key in full_env:
bash_command += "export {}={} && ".format(shlex.quote(key), shlex.quote(full_env[key]))
bash_command += command

# Workaround for OSX pexpect bug http://pexpect.readthedocs.io/en/stable/commonissues.html#truncated-output-just-before-child-exits
# Workaround from https://github.com/pexpect/pexpect/issues/373
command = "bash -c {}".format(shlex.quote(command))
self.process = pexpect.spawn(command, encoding="utf-8", echo=False, env=full_env)
command = "bash -c {}".format(shlex.quote(bash_command))
self.process = pexpect.spawn(command, encoding="utf-8", echo=False)

def stdin(self, line, str_line=None, prompt=True, timeout=3):
"""
Expand Down
2 changes: 1 addition & 1 deletion check50/_simple.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ def _compile_check(name, check):
if check_name[0].isdigit():
check_name = f"_{check_name}"

if not re.match("\w+", check_name):
if not re.match(r"\w+", check_name):
raise CompileError(
_("{} is not a valid name for a check; check names should consist only of alphanumeric characters, underscores, and spaces").format(name))

Expand Down
3 changes: 2 additions & 1 deletion check50/c.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@ def compile(*files, exe_name=None, cc=CC, max_log_lines=50, **cflags):

out_flag = f" -o {exe_name} " if exe_name is not None else " "

process = run(f"{cc} {files}{out_flag}{flags}")
proc_str = f"{cc} {files}{out_flag}{flags}"
process = run(proc_str)

# Strip out ANSI codes
stdout = re.sub(r"\x1B\[[0-?]*[ -/]*[@-~]", "", process.stdout())
Expand Down
8 changes: 4 additions & 4 deletions check50/regex.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,16 @@ def decimal(number):

In case of a positive number::

(?<![\d\-])number(?!(\.?\d))
(?<![\\d\\-])number(?!(\\.?\\d))

In case of a negative number::

number(?!(\.?\d))
number(?!(\\.?\\d))

:code:`(?<![\d\-])` = negative lookbehind, \
:code:`(?<![\\d\\-])` = negative lookbehind, \
asserts that there are no digits and no - in front of the number.

:code:`(?!(\.?\d))` = negative lookahead, \
:code:`(?!(\\.?\\d))` = negative lookahead, \
asserts that there are no digits and no additional . followed by digits after the number.

:param number: the number to match in the regex
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,6 @@
"console_scripts": ["check50=check50.__main__:main"]
},
url="https://github.com/cs50/check50",
version="3.3.11",
version="3.3.12",
include_package_data=True
)
51 changes: 29 additions & 22 deletions tests/c_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,49 +15,63 @@
CHECKS_DIRECTORY = pathlib.Path(__file__).absolute().parent / "checks"

class Base(unittest.TestCase):
starting_dir = os.getcwd()

def setUp(self):
if not CLANG_INSTALLED:
raise unittest.SkipTest("clang not installed")
if not VALGRIND_INSTALLED:
raise unittest.SkipTest("valgrind not installed")

# ensures each test starts from same cwd;
# 'chdir' would otherwise persist between tests
os.chdir(self.starting_dir)

# write c test files to temp directory
test_files = {}
os.chdir("test_files")
for file in os.listdir():
with open(file) as f:
test_files[file] = f.read()

self.working_directory = tempfile.TemporaryDirectory()
os.chdir(self.working_directory.name)

for file in test_files:
with open(file, "w") as f:
f.write(test_files[file])

def tearDown(self):
self.working_directory.cleanup()

class TestCompile(Base):
def test_compile_incorrect(self):
open("blank.c", "w").close()

with self.assertRaises(check50.Failure):
check50.c.compile("blank.c")

def test_compile_hello_world(self):
with open("hello.c", "w") as f:
src = '#include <stdio.h>\n'\
'int main() {\n'\
' printf("hello, world!\\n");\n'\
'}'
f.write(src)

check50.c.compile("hello.c")

self.assertTrue(os.path.isfile("hello"))

class TestRun(Base):
def test_stdout_hello_world(self):
check50.c.compile("hello.c")
check50.run("./hello").stdout("hello, world!", regex=False)

def test_stdin_cash(self):
check50.c.compile("cash.c", lcs50=True)
check50.run("./cash").stdin("42", prompt=True).stdout("5").exit()

class TestValgrind(Base):
def setUp(self):
super().setUp()

# valgrind installation check moved to here from Base()
if not VALGRIND_INSTALLED:
raise unittest.SkipTest("valgrind not installed")
if not (sys.platform == "linux" or sys.platform == "linux2"):
raise unittest.SkipTest("skipping valgrind checks under anything other than Linux due to false positives")

def test_no_leak(self):
check50.internal.check_running = True
with open("foo.c", "w") as f:
src = 'int main() {}'
f.write(src)

check50.c.compile("foo.c")
with check50.internal.register:
Expand All @@ -66,13 +80,6 @@ def test_no_leak(self):

def test_leak(self):
check50.internal.check_running = True
with open("leak.c", "w") as f:
src = '#include <stdlib.h>\n'\
'void leak() {malloc(sizeof(int));}\n'\
'int main() {\n'\
' leak();\n'\
'}'
f.write(src)

check50.c.compile("leak.c")
with self.assertRaises(check50.Failure):
Expand Down
Empty file added tests/test_files/blank.c
Empty file.
21 changes: 21 additions & 0 deletions tests/test_files/cash.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#include <cs50.h>
#include <stdio.h>

int main(void) {
int cents;
do {
cents = get_int("Cents? ");
}
while (cents < 0);

const int n_denominations = 4;
int denominations[n_denominations] = {1, 5, 10, 25};

int coins = 0;
for (int i = n_denominations - 1; i >= 0; i--) {
coins += cents / denominations[i];
cents %= denominations[i];
}

printf("%i\n", coins);
}
1 change: 1 addition & 0 deletions tests/test_files/foo.c
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
int main() {}
5 changes: 5 additions & 0 deletions tests/test_files/hello.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#include <stdio.h>

int main() {
printf("hello, world!\n");
}
9 changes: 9 additions & 0 deletions tests/test_files/leak.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#include <stdlib.h>

void leak() {
malloc(sizeof(int));
}

int main() {
leak();
}