def validate(sources_buf): if "malloc(" in sources_buf or "free(" in sources_buf: raise check50.Failure("There should be no calls to malloc/free") if re.search("multiply_arrays.*[\n]{0,1}.*size[1|2].*[\n]{0,1}.*\)", sources_buf): raise check50.Failure( "multiply_array should not take size1 or size2 as parameters")
def helper_commands(): """Testing helper commands; HELP, LOOK, QUIT.""" # Test HELP try: check = check50.run(run_command).stdin("HELP") for help in help_statement: check.stdout(help) except check50.Failure as error: raise check50.Failure( f"HELP did not print the expected message.\n {error}") # Test LOOK command try: check50.run(run_command).stdin("LOOK").stdout(room_1_description) check50.run(run_command).stdin("look").stdout(room_1_description) except check50.Failure as error: raise check50.Failure( f"LOOK/look did not print the expected room description.\n {error}" ) # Test QUIT try: check50.run(run_command).stdin("QUIT").stdout( "Thanks for playing!").exit(0) except check50.Failure as error: raise check50.Failure( f"QUIT did not function as expected.\n {error}")
def check_bmps(expected_filename, actual_filename): # Open files. with open(expected_filename, "rb") as expected_file, \ open(actual_filename, "rb") as actual_file: # Read in the headers. expected_header = BitmapHeader.from_file(expected_file) actual_header = BitmapHeader.from_file(actual_file) expected_bytes = expected_file.read() actual_bytes = actual_file.read() check50.log(f"checking {actual_filename} header...") for (field, expected_field), (_, actual_field) in zip(expected_header, actual_header): if expected_field != actual_field: raise check50.Failure( f"expected {hex(expected_field)}, not {hex(actual_field)} in header field {field}" ) check50.log(f"checking {actual_filename} pixel data...") for i, (expected_byte, actual_byte) in enumerate( zip_longest(expected_bytes, actual_bytes), 1): if actual_byte is None: raise check50.Failure("image has fewer bytes than expected.") elif expected_byte is None: raise check50.Failure("image has more bytes than expected.") elif expected_byte != actual_byte: raise check50.Failure( f"expected {hex(expected_byte)}, not {hex(actual_byte)} in byte {i} of pixel data" )
def validate_form(self, route, fields, field_tag="input"): """Make sure HTML form at `route` has input fields given by `fields`""" if not isinstance(fields, list): fields = [fields] content = self.get(route).content() required = {field: False for field in fields} for tag in content.find_all(field_tag): try: name = tag.attrs["name"] if required[name]: raise Error("found more than one field called \"{}\"".format(name)) except KeyError: pass else: check50.log("found required \"{}\" field".format(name)) required[name] = True try: missing = next(name for name, found in required.items() if not found) except StopIteration: pass else: raise check50.Failure(f"expected to find {field_tag} field with name \"{missing}\", but none found") if content.find("button", type="submit") is None: raise check50.Failure("expected button to submit form, but none was found") return self
def card_initializer(): """class 'Card' can be initialized correctly.""" module = uva.check50.py.run("cardgame.py").module # check if __init__ exists and accepts the correct args class_method(module.Card, "__init__") required_args = ["self", "suit", "value"] method_arguments(module.Card, "__init__", required_args) # loop through all possible cards for suit in suits: for value in values: card = module.Card(suit=suit, value=value) # check if the object has the required attributes attributes = ["suit", "value"] attributes_present(card, attributes) # check if the initializer worked if card.suit != suit: raise check50.Failure( f"class 'Card' was initialized with unexpected suit '{card.suit}'. expected '{suit}'" ) elif card.value != value: raise check50.Failure( f"class 'Card' was initialized with unexpected value '{card.value}'. expected '{value}'" )
def has_variables(sources_buf): if "int_var" not in sources_buf: raise check50.Failure("Could not find mention of int_var in the " "source") if "double_var" not in sources_buf: raise check50.Failure("Could not find mention of double_var in the" "source")
def check_solved(sudoku, original): for x, y in itertools.product(range(9), range(9)): if int(original[x][y]) != 0 and sudoku[x][y] != original[x][y]: raise check50.Failure( f"The solved sudoku changed from the original sudoku at x={x}, y={y}" ) expected = set(range(1, 10)) for i in range(9): row = [int(v) for v in sudoku[i]] column = [int(sudoku[x][i]) for x in range(9)] grid = [ int(sudoku[x][y]) for x, y in itertools.product([j + (i % 3 * 3) for j in range(3)], [j + (i // 3 * 3) for j in range(3)]) ] if set(row) != expected: raise check50.Failure( f"This row {row} at x={i} does not contain the numbers 1 to 9") if set(column) != expected: raise check50.Failure( f"This column {column} at y={i} does not contain the numbers 1 to 9" ) if set(grid) != expected: raise check50.Failure( f"This grid {grid} at x={i % 3 * 3}..{i % 3 * 3 + 2}, and y={i // 3 * 3}..{i // 3 * 3 + 2} does not contain the numbers 1 to 9" )
def wrong_lexicon(): """creating a Lexicon with incorrect parameters yields an assertion error""" sys.path.append(os.getcwd()) import hangman Lexicon = hangman.Lexicon params = [-2, 29] messages = [ "negative word length", "word length that does not appear anywhere in the dictionary" ] for param, message in zip(params, messages): lex = None try: lex = Lexicon(param) except AssertionError as e: pass except Exception as e: raise check50.Failure("got error but not an assertion failure", help=f"got exception {e}") if lex is not None: raise check50.Failure("when creating a Lexicon object for a " + message)
def valid(): """project exists and is valid Scratch program""" # Make sure there is only one .sb2 file. filenames = [ filename for filename in os.listdir() if filename.endswith(".sb3") ] if len(filenames) > 1: raise check50.Failure( "more than one .sb3 file found. Make sure there's only one!") elif not filenames: raise check50.Failure("no .sb3 file found") filename = filenames[0] # Ensure that unzipped .sb2 file contains .json file. if check50.run(f"unzip {shlex.quote(filename)}").exit(): raise check50.Failure("invalid .sb3 file") check50.exists("project.json") with open("project.json") as f: project = json.load(f) return project["targets"]
def correct_days(out): """correct dates of bad days.""" days = {(24, 3, 2018), (23, 3, 2018), (21, 3, 2018), (19, 3, 2018), (18, 3, 2018), (17, 3, 2018), (13, 3, 2018), (6, 3, 2018), (3, 3, 2018), (18, 2, 2018), (17, 2, 2018), (16, 2, 2018), (15, 2, 2018), (12, 2, 2018), (10, 2, 2018), (4, 2, 2018), (28, 1, 2018), (11, 1, 2018), (7, 1, 2018), (5, 1, 2018), (30, 12, 2017), (12, 12, 2017), (11, 12, 2017), (3, 12, 2017), (26, 11, 2017), (25, 11, 2017), (20, 11, 2017), (19, 11, 2017), (3, 11, 2017), (31, 10, 2017), (30, 10, 2017)} days_copy = set(days) matches = re.findall("(\d+)[^\n^\d]*(\d+)[^\n^\d]*(\d+)", out) for match in matches: match = tuple([int(d) for d in match]) if match in days_copy: try: days.remove(match) except KeyError: pass else: raise check50.Failure(f"Did not expect {match} as a bad day!") if days: raise check50.Failure(f"Expected to find {days} as bad days.")
def helper_commands(): """Testing helper commands; HELP, LOOK, QUIT.""" try: check50.run(run_command).stdin("HELP").stdout( "You can move by typing directions such as EAST/WEST/IN/OUT\n" + "QUIT quits the game.\n" + "HELP prints instructions for the game.\n" + "INVENTORY lists the item in your inventory.\n" + "LOOK lists the complete description of the room and its contents.\n" + "TAKE <item> take item from the room.\n" + "DROP <item> drop item from your inventory.\n") except check50.Failure as error: raise check50.Failure( f"HELP did not print the expected message.\n {error}") try: check50.run(run_command).stdin("LOOK").stdout(room_1_description) check50.run(run_command).stdin("look").stdout(room_1_description) except check50.Failure as error: raise check50.Failure( f"LOOK/look did not print the expected room description.\n {error}" ) try: check50.run(run_command).stdin("QUIT").stdout( "Thanks for playing!").exit(0) except check50.Failure as error: raise check50.Failure( f"QUIT did not print the expected message.\n {error}")
def find_items(): """Finds items in rooms.""" # Check initial description try: check = check50.run(RUN_CROWTHER).stdin("in") check.stdout(room_3_description, regex=False) for item in room_3_items: check.stdout(item, regex=False) except check50.Failure as error: raise check50.Failure( f"Could not find items upon first entering room.\n" f" Remember to seperate multiple items by a " f"single newline.\n" f" {error}") # Check for look command try: check = check50.run(RUN_CROWTHER) moves = ["IN", "OUT", "IN", "LOOK"] for move in moves: check.stdout("> ") check.stdin(move, prompt=False) for item in room_3_items: check.stdout(item, regex=False) except check50.Failure as error: raise check50.Failure(f"Could not find items when using LOOK.\n" f" {error}")
def qualifies(): """qualifies for Big Board""" try: # inject canary canary = str(uuid.uuid4()) check50.run( "sed -i -e 's/CANARY/{}/' speller.c".format(canary)).exit(0) check50.run("make -B").exit(0) # Run on aca.txt check50.c.valgrind( "./speller dictionaries/large texts/aca.txt 0 > actual.out").exit( 0, timeout=20) actual = open("actual.out").read().splitlines() expected = open("sols/aca.txt").read().splitlines() # check for canary if canary != actual[-1]: raise check50.Failure( "Your Makefile doesn't seem to have compiled speller.c") del actual[-1] # Compare output line for line. if len(actual) != len(expected): raise check50.Failure("{} lines expected, not {}".format( len(expected), len(actual))) for actual_line, expected_line in zip(actual, expected): if actual_line != expected_line: raise check50.Failure("expected {}, not {}".format( expected_line, actual_line)) # Clear log to avoid clutter. finally: check50._log.clear()
def check_single_col(actual, expected, ordered=False): """ Checks for queries that return just a single column, ensures correct results. """ # Make sure query returned results if actual is None or actual == []: raise check50.Failure("Query did not return results") # Make sure there is only a single column row_counts = {len(list(row.values())) for row in actual} if row_counts != {1}: raise check50.Failure("Query should only return a single column") # Get data from column try: result = [str(list(row.values())[0]) for row in actual] result = result if ordered else set(result) except IndexError: return None # Check column data against expected values expected = [str(value) for value in expected] if not ordered: expected = set(expected) if result != expected: raise check50.Mismatch("\n".join(expected), "\n".join(list(result)))
def check_double_col(actual, expected, ordered=False): """ Checks for queries that return just a single column, ensures correct results. """ # Make sure query returned results if actual is None or actual == []: raise check50.Failure("Query did not return results") # Make sure there is only a single column row_counts = {len(list(row.values())) for row in actual} if row_counts != {2}: raise check50.Failure("Query should only return a single column") # Get data from column try: result = [] for row in actual: values = list(row.values()) result.append({str(values[0]), str(values[1])}) result = result if ordered else set(result) except IndexError: return None # Check column data against expected values if result != expected: raise check50.Mismatch( "\n".join([str(entry) for entry in list(expected)]), "\n".join([str(entry) for entry in list(result)]))
def deck_valid(deck, module): # check if 52 different and valid cards are present cards = set() # check amount of cards if len(deck._cards) != 52: raise check50.Failure( f"found invalid amount of cards {len(deck._cards)} in deck.") # check each card in the deck for card in deck._cards: # check if cards are actually instances of the Card class if not isinstance(card, module.Card): raise check50.Failure( f"items in deck are not instances of the 'Card' class, instead found '{type(card).__name__}'." ) # check for duplicate cards if card.suit + card.value in cards: raise check50.Failure( f"found the {card.value} of {card.suit} in deck at least twice." ) cards.add(card.suit + card.value) # check if the card is valid if not card.value in values_set or not card.suit in suits_set: raise check50.Failure( f"found invalid card {card.value} of {card.suit} in deck.")
def has_typedef_struct(sources_buf): if not re.search("typedef struct s_rectangle {$.*} rectangle;", sources_buf, re.DOTALL | re.MULTILINE) and \ "typedef struct s_rectangle rectangle;" not in sources_buf: raise check50.Failure("Found no typedef for rectangle") if "rectangle r" not in sources_buf: raise check50.Failure("Found no use of rectangle")
def deck_initializer(): """class 'Deck' exists, has basic attributes and can be initialized correctly.""" # check if the class exists module = uva.check50.py.run("cardgame.py").module class_exists(module, "Deck") # check if __init__ exists and accepts the correct args class_method(module.Deck, "__init__") required_args = ["self"] method_arguments(module.Deck, "__init__", required_args) # initialize a deck and check if it worked deck = module.Deck() # check if the object has the required attributes attributes = ["_suits", "_values"] attributes_present(deck, attributes) # check for correct initialization if not all_list_in_set(deck._suits, suits_set): raise check50.Failure( "expected 'deck._suits' to contain all possible suits after initialization." ) elif not all_list_in_set(deck._values, values_set): raise check50.Failure( "expected 'deck._values' to contain all possible values after initialization." )
def test0(): """Informacija faile U1.txt yra surašyta teisingai""" linesRez = len(open("U1rez.txt").readlines()) if not lines: raise check50.Failure("U1.txt yra tusčias") if linesRez < 4: raise check50.Failure("U1.txt yra užrašytas neteisingai.")
def helper_commands(): """Testing helper commands; HELP, LOOK, QUIT.""" # Test HELP try: check = check50.run(RUN_TINY).stdin("HELP") for help in help_statement: check.stdout(help) except check50.Failure as error: raise check50.Failure(f"HELP did not print the expected message.\n" f" {error}") # Test LOOK command try: check50.run(RUN_TINY).stdin("LOOK").stdout(room_1_description, regex=False) except check50.Failure as error: raise check50.Failure(f"LOOK did not print the expected room" f"description.\n {error}") try: check50.run(RUN_TINY).stdin("look").stdout(room_1_description, regex=False) except check50.Failure as error: raise check50.Failure(f"look (lowercase) did not print the expected room" f"description.\n {error}") # Test QUIT try: check50.run(RUN_TINY).stdin("QUIT").exit(0) except check50.Failure as error: raise check50.Failure(f"QUIT did not function as expected.\n" f" {error}")
def check_tracks(): """Check if the solution is valid.""" with open("output.csv") as csvfile, \ open(r"data/connections.csv") as connectionsfile: df = pd.read_csv(csvfile) connections = pd.read_csv(connectionsfile) # Check if the order of stations are valid. tracks = df["stations"][:-1].map(lambda x: x[1:-1].split(", ")).values valid_cons = connections.iloc[:, :-1].values.tolist() output_cons = [] errors = [] for i, track in enumerate(tracks): output_cons.append([]) for j, t in enumerate(track[:-1]): if [t, track[j + 1]] in valid_cons: output_cons[i].append([t, track[j + 1]]) elif [track[j + 1], t] in valid_cons: output_cons[i].append([track[j + 1], t]) else: errors.append([i, f"{t}, {track[j + 1]}"]) if errors: error = "Found the following illegal connections:\n" for row, stations in errors: error = "".join( [error, f"\t'{stations}' \ton row " f"{row + 2}.\n"]) raise check50.Failure(error) # Check if the time limit has not been exceeded. errors = [] for row, track in enumerate(output_cons): time = 0 for con in track: time += connections[(connections["station1"].isin([con[0]])) & (connections["station2"].isin([con[1]]))] \ ["distance"].values[0] if time > MAX_TIME: errors.append([row, time]) if errors: error = f"Found tracks that exceed the maximum time of " \ f"{MAX_TIME} minutes on:\n" for row, time in errors: error = "".join([ error, f"\tRow {row + 2} with a time of " f"{time} minutes\n" ]) raise check50.Failure(error)
def has_format_specifier(sources_buf): buf = sources_buf if "%d" not in buf and "%i" not in buf: raise check50.Failure("Could not find an integer format specifier " "(%d or %i)") if "%f" not in buf and "%F" not in buf and "%q" not in buf and \ "%G" not in buf and "%lf" not in buf: raise check50.Failure("Could not find a floating point format " "specifier (%f, %F, %q, %G, %lf)")
def validate(sources_buf): if not re.search("class\s+Vehicle", sources_buf): raise check50.Failure("Could not find class Vehicle") if not re.search("class\s+Car\s+:\s+public\s+Vehicle", sources_buf): raise check50.Failure("Could not find class Car or class Car does not "\ "inheritates from a parent") if not re.search("class\s+Motorbike\s+:\s+public\s+Vehicle", sources_buf): raise check50.Failure("Could not find class Motorbike or class "\ "Motorbike does not inheritates from a parent")
def has_right_size(sources_buf): string_re = "char\s+string\[([0-9]+)\];" res = re.search(string_re, sources_buf) if not res: raise check50.Failure("Cannot determine the string size") size = int(res.groups()[0]) if size < 9: raise check50.Failure("String size not large enough")
def correct_min_temp(stdout): """prints the minimum temperature measured""" match = re.search("minimale temperatuur[^\d-]*(-\d+[\.,]\d+)", stdout) if not match: raise check50.Failure("expected: De minimale temperatuur was -XX.XX graden op") answer = float(match.groups(0)[0].replace(",", ".")) if answer != -11.3: raise check50.Failure(f"expected -11.3 but found {answer}")
def test5(): """Teisingai paskaičiuoja gautą pelną""" check50.run("> U1rez.txt").exit(0) check50.run("./aliejus").exit(0) with open('U1rez.txt') as f1: linesRez = f1.read().split() if(len(linesRez) < 11): raise check50.Failure("File U1rez.txt nepakanka duomenų") else: if (str(gautasPelnas) != linesRez[10]): raise check50.Failure("Blogai suskaičiuoja gautą pelną")
def test2(): """Teisingai paskaičiuoja aliejaus likutį""" check50.run("> U1rez.txt").exit(0) check50.run("./aliejus").exit(0) with open('U1rez.txt') as f2: linesRez = f2.read().split() if(len(linesRez) < 4): raise check50.Failure("File U1rez.txt nepakanka duomenų") else: if (str(aliejuNeispilstytas) != linesRez[3]): raise check50.Failure("Blogai suskaičiuotas ispilstytas aliejus")
def correct_longest_freezing_period(stdout): """prints the length of the longest freezing period""" match = re.search("langste vriesperiode[^\d]*(\d+)", stdout) if not match: raise check50.Failure("expected: De langste vriesperiode is XX dagen") days = int(match.groups()[0]) if days != 21: raise check50.Failure(f"expected 21 days but found {days}")
def test5(): """Correctly calculates the given profit""" check50.run("> U1rez.txt").exit(0) check50.run("./aliejus").exit(0) with open('U1rez.txt') as f1: linesRez = f1.read().split() if(len(linesRez) < 11): raise check50.Failure("File U1rez.txt does not have enough data") else: if (str(gautasPelnas) != linesRez[10]): raise check50.Failure("The calculation is not correct")
def test2(): """Correctly calculates the amount of oil that wasn't used""" check50.run("> U1rez.txt").exit(0) check50.run("./aliejus").exit(0) with open('U1rez.txt') as f2: linesRez = f2.read().split() if(len(linesRez) < 4): raise check50.Failure("File U1rez.txt does not have enough data") else: if (str(aliejuNeispilstytas) != linesRez[3]): raise check50.Failure("The calculation is not correct")