|
| 1 | +import glob # For getting all the solution files |
| 2 | +import os # For checking if path exists |
| 3 | +import shutil # For deleting the data directory |
| 4 | +import subprocess # For executing the files |
| 5 | +import sys # For command line arguments |
| 6 | +import distutils # For copying the data directory |
| 7 | +from distutils import dir_util # https://stackoverflow.com/a/33417555/6525260 |
| 8 | + |
| 9 | +class colors: |
| 10 | + OKBLUE = '\033[36;1m' |
| 11 | + OKGREEN = '\033[32;1m' |
| 12 | + WARNING = '\033[33;1m' |
| 13 | + FAIL = '\033[31;1m' |
| 14 | + ENDC = '\033[0m' |
| 15 | + BOLD = '\033[1m' |
| 16 | + UNDERLINE = '\033[4m' |
| 17 | + |
| 18 | +def test_all_solutions(directory_name, compiler_name, expected_solutions): |
| 19 | + files = glob.glob(directory_name + "/Problem***.cpp") |
| 20 | + |
| 21 | + if not files: |
| 22 | + print(colors.FAIL + "Error: No files were found!" + colors.ENDC) |
| 23 | + return 1 |
| 24 | + |
| 25 | + files.sort() |
| 26 | + |
| 27 | + print("\nThe following files were found: ") |
| 28 | + |
| 29 | + for file in files: |
| 30 | + print(file) |
| 31 | + |
| 32 | + print("\n") |
| 33 | + |
| 34 | + try: |
| 35 | + dir_util.copy_tree(directory_name + "/data/", "./data/") # Copy the data folder that some solutions need |
| 36 | + except dir_util.DistutilsFileError: |
| 37 | + print(colors.WARNING + "The data folder was unable to be copied from " + directory_name + " to ./data!") |
| 38 | + print("Some solutions may not be able to compile!\n" + colors.ENDC) |
| 39 | + |
| 40 | + passed_tests = 0 |
| 41 | + |
| 42 | + for file in files: |
| 43 | + compile_command = compiler_name + " " + file + " -std=c++14 -O2" |
| 44 | + current_key = file[-7: -4] |
| 45 | + |
| 46 | + print(colors.BOLD + "===============" + colors.ENDC) |
| 47 | + print(colors.OKBLUE + "TEST" + colors.ENDC + ": Problem " + str(current_key) + "\n") |
| 48 | + print("Trying to compile " + file + " with " + compile_command) |
| 49 | + |
| 50 | + if (subprocess.call(compile_command.split(), stdout = subprocess.DEVNULL, stderr = subprocess.STDOUT) != 0): # Compile the current file |
| 51 | + print("Result: " + colors.FAIL + "FAILURE" + colors.ENDC + ": File was unable to be compiled!") |
| 52 | + else: |
| 53 | + try: |
| 54 | + print("File was successfully able to be compiled. Running executable with ./a.out\n") |
| 55 | + current_output = int(subprocess.check_output(['./a.out']).decode('utf-8')) # Execute the file and capture output |
| 56 | + |
| 57 | + print("Current output: " + str(current_output)) |
| 58 | + |
| 59 | + if current_key in expected_solutions: |
| 60 | + expected_solution = expected_solutions[current_key] # Extract problem number for indexing solution |
| 61 | + |
| 62 | + print("Expected output: " + str(expected_solution)) |
| 63 | + |
| 64 | + if current_output == expected_solution: |
| 65 | + print("\nResult: " + colors.OKGREEN + "SUCCESS" + colors.ENDC) |
| 66 | + passed_tests += 1 |
| 67 | + else: |
| 68 | + print("\nResult: " + colors.FAIL + "FAILURE" + colors.ENDC + ": Current output " + str(current_output) + " does not match expected output " + str(expected_solution) + "!") |
| 69 | + else: |
| 70 | + print("Result: " + colors.FAIL + "FAILURE" + colors.ENDC + ": Expected solution to problem " + str(current_key) + " was not found!") |
| 71 | + except ValueError: |
| 72 | + print("Result: " + colors.FAIL + "FAILURE" + colors.ENDC + ": Output is of non-integer type!") |
| 73 | + |
| 74 | + print(colors.BOLD + "===============" + colors.ENDC) |
| 75 | + |
| 76 | + if os.path.isfile('./a.out'): # Remove the new executable file |
| 77 | + os.remove('a.out') |
| 78 | + |
| 79 | + if os.path.isdir("./data"): # Remove the data directory |
| 80 | + shutil.rmtree("./data") |
| 81 | + |
| 82 | + print("\n") |
| 83 | + |
| 84 | + num_tests = len(expected_solutions) |
| 85 | + |
| 86 | + print(colors.BOLD + str(passed_tests) + " out of " + str(num_tests) + " tests were successful." + colors.ENDC) |
| 87 | + |
| 88 | + if passed_tests == num_tests: |
| 89 | + print("Result: " + colors.OKGREEN + "SUCCESS" + colors.ENDC) |
| 90 | + return 0 |
| 91 | + else: |
| 92 | + print("Result: " + colors.FAIL + "FAILURE" + colors.ENDC) |
| 93 | + return 1 |
| 94 | + |
| 95 | + |
| 96 | + |
| 97 | +if __name__ == '__main__': |
| 98 | + |
| 99 | + expected_solutions = { } |
| 100 | + try: |
| 101 | + with open("expected_solutions.txt", "r") as expected_solutions_file: |
| 102 | + for line in expected_solutions_file: |
| 103 | + line = line[:-1] # Remove trailing newlines |
| 104 | + key_value_pair = line.split(" ") |
| 105 | + if len(key_value_pair) == 2 and key_value_pair[1].isdigit(): # Extract all expected solutions; ignore bad entries |
| 106 | + print("Got here") |
| 107 | + expected_solutions[key_value_pair[0]] = int(key_value_pair[1]) |
| 108 | + except IOError: |
| 109 | + print("Unable to open file './expected_solutions.txt'! Please check that the file is located in the current working directory!") |
| 110 | + |
| 111 | + if len(sys.argv) != 3: |
| 112 | + print("Error: Missing operands!") |
| 113 | + print("Usage: " + sys.argv[0] + " path/to/problems compiler-name") |
| 114 | + sys.exit(1) |
| 115 | + elif not os.path.exists(sys.argv[1]): |
| 116 | + print("Error: Path " + sys.argv[1] + " does not exist!") |
| 117 | + else: |
| 118 | + sys.exit(test_all_solutions(sys.argv[1], sys.argv[2], expected_solutions)) |
0 commit comments