Skip to content

Commit

Permalink
Merge pull request #4 from christian-byrne/large-assignment-01
Browse files Browse the repository at this point in the history
Refactor Tests, LA01
  • Loading branch information
christian-byrne authored Oct 1, 2024
2 parents 83c621f + 8fc2778 commit ab41718
Show file tree
Hide file tree
Showing 21 changed files with 557 additions and 301 deletions.
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ chmod +x ./install
## Run tests

```
chmod +x ./test
./test
```

Expand Down
74 changes: 63 additions & 11 deletions src/large_assignment_01/large_assignment_01.sml
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@


(*
* `triangle`
*
* Type: `int * int * int -> bool`
* Description: The triangle inequality theorem states that the sum of any
* two sides of a triangle must be greater than or equal to the
Expand All @@ -24,15 +22,13 @@ fun triangle(0, _, _) = false


(*
* `triangleR`
*
* Type: `real * real * real -> bool`
* Description: The triangle inequality theorem states that the sum
* of any two sides of a triangle must be greater than
* or equal to the third side. This function should
* return true if the three real numbers can make a
* triangle and false otherwise.
*)
* Type: `real * real * real -> bool`
* Description: The triangle inequality theorem states that the sum
* of any two sides of a triangle must be greater than
* or equal to the third side. This function should
* return true if the three real numbers can make a
* triangle and false otherwise.
*)
fun triangleR(a, b, c) =
let
val epsilon = 1.0E~10
Expand All @@ -42,3 +38,59 @@ fun triangleR(a, b, c) =
not(is_zero(a)) andalso not(is_zero(b)) andalso not(is_zero(c)) andalso
sum_geq_to(a, b, c) andalso sum_geq_to(a, c, b) andalso sum_geq_to(b, c, a)
end;


(*
* Type: `int * 'a list -> 'a list`
* Description: Given an integer n and a list l, cycle n elements
* from the list to the end of the list. You can assume
* the input for n will be non-negative.
* Example: cycle(4,[1,2,3,4,5,6,7]) → [5,6,7,1,2,3,4]
*)
fun cycle(0, li) = li
| cycle(_, []) = []
| cycle(n, x::li) = cycle(n - 1, li @ [x]);


(*
* Type: `'a list -> 'a list`
* Description: Mirror the list. You may not use any reverse function
* (even as a helper function).
* Example: mirror [1,2,3,4] → [1,2,3,4,4,3,2,1]
*)
fun mirror([]) = []
| mirror(x::li) = x::mirror(li) @ [x];


(*
* Type: `int list * int -> int list`
* Description: Take a list l and an integer n and return a list that
* contains all the elements in l that are greater than
* n. Keep the same relative order of items.
*)
fun gtList(_, []) = []
| gtList(n, x::li) = if x > n then x::gtList(n, li) else gtList(n, li);


(*
* Type: `''a list * ''a list -> bool`
* Description: Return true if the first list is a suffix of the
* second list and false otherwise. Do not reverse
* either of the lists.
*)
fun suffix([], _) = true
| suffix(_, []) = false
| suffix(li1, li2) =
let
fun listLength([]) = 0
| listLength(x::li) = 1 + listLength(li)
fun truncatePrefix(count, x::li) = if count = 0 then x::li else truncatePrefix(count - 1, li)
fun suffixEqual([], []) = true
| suffixEqual(x::a, y::b) = if x = y then suffixEqual(a, b) else false
val truncateCount = listLength(li2) - listLength(li1)
in
if truncateCount < 0 then false
else suffixEqual(li1, truncatePrefix(truncateCount, li2))
end;


2 changes: 1 addition & 1 deletion test-la-01.sh
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
#!/bin/bash
#
./test --ignore-glob "tests-ica05/*" --failed-first --log-cli-level WARNING
./test --rootdir tests/tests-large_assignment_01 --failed-first --log-cli-level WARNING $@
36 changes: 22 additions & 14 deletions test.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@
parser.add_argument(
"--nf", "--new-first", action="store_true", help="Run tests from new files first."
)
parser.add_argument(
"--nl", "--new-last", action="store_true", help="Run tests from new files last."
)
parser.add_argument(
"--sw-skip",
"--stepwise-skip",
Expand Down Expand Up @@ -198,12 +201,8 @@ def clear_cache():
logging.debug(f"Cache file on start: {cache_}")
logging.debug(f"all_seen_tests in cache: {cache_.get('all_seen_tests')}")
logging.debug(f"failed_tests in cache: {cache_.get('failed_tests')}")
all_seen_tests = set(
Path(test) for test in cache_.get("all_seen_tests", [])
)
last_failed_tests = set(
Path(test) for test in cache_.get("failed_tests", [])
)
all_seen_tests = set(Path(test) for test in cache_.get("all_seen_tests", []))
last_failed_tests = set(Path(test) for test in cache_.get("failed_tests", []))
except Exception as e:
logging.error(f"Error reading cache file: {e}")

Expand Down Expand Up @@ -241,7 +240,6 @@ def clear_cache():
break
if skip_test:
continue

# If --last-failed is set, only include the tests that are in the 'failed_tests' cache
if args.lf and test not in last_failed_tests:
continue
Expand All @@ -257,11 +255,15 @@ def clear_cache():
if args.nf and test not in all_seen_tests:
tests.appendleft(Path(test))
continue

tests.append(Path(test))

logging.info(f"Found {len(tests)} tests")

# If --new-last is set, sort by mtime
if args.nl:
tests = deque(sorted(tests, key=lambda x: x.stat().st_mtime))


def format_test_list(tests: Set[Path]) -> str:
return "\n\t".join([test.name for test in tests])
Expand All @@ -282,6 +284,7 @@ def format_test_list(tests: Set[Path]) -> str:
maxfail = 1 # Only skip the first failing test if --sw-skip is set
os.environ["SML_TEST_MAXFAIL"] = str(maxfail)


def check_for_runtime_error(output: str) -> bool:
if "uncaught exception" in output:
return True
Expand Down Expand Up @@ -344,12 +347,15 @@ def run_test(test_path: Path):
logging.critical("Error with test runner script")
print(f"Error: {error}")


logging.info("Running tests")
logging.debug(f"All Tests: {tests}")
for test in tests:
run_test(test)
if passed_tests:
logging.info(f"Passed all tests in files:\n\t[green]{format_test_list(passed_tests)}[/green]")
logging.info(
f"Passed all tests in files:\n\t[green]{format_test_list(passed_tests)}[/green]"
)
if compile_error_tests:
logging.critical(
f"Compilation error in test files:[bold red]\n\t{format_test_list(compile_error_tests)}[/bold red]"
Expand All @@ -359,7 +365,9 @@ def run_test(test_path: Path):
f"Runtimes errors in test files:\n\t[red]{format_test_list(runtime_error_tests)}[/red]"
)
if failed_tests:
logging.warning(f"Failed tests in files:\n\t[dim red]{format_test_list(failed_tests)}[/dim red]")
logging.warning(
f"Failed tests in files:\n\t[dim red]{format_test_list(failed_tests)}[/dim red]"
)
passed_all = len(passed_tests) == len(tests)
if passed_all:
logging.info("All tests passed!")
Expand All @@ -376,18 +384,18 @@ def run_test(test_path: Path):
clear_cache()
cache = {}


def write_(test_set: Set[Path], cache_key: str):
if len(test_set) == 0:
cache[cache_key] = []
return

cache[cache_key] = [str(test.resolve()) for test in test_set]


write_(runtime_error_tests, "runtime_error_tests")
write_(failed_tests, "failed_tests")
write_(passed_tests, "passed_tests")
write_(
runtime_error_tests.union(failed_tests).union(passed_tests), "all_seen_tests"
)
write_(runtime_error_tests.union(failed_tests).union(passed_tests), "all_seen_tests")
with open(args.cache_path, "w") as cache_file:
json.dump(cache, cache_file)
4 changes: 3 additions & 1 deletion tests/tests-ica05/test_addLists.sml
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,6 @@ val testCasesAddLists = [
(addLists, ([1, 2, 3], [4, 5, 6, 7]), [5, 7, 9]),
(addLists, ([1, 2, 3, 4, 5], [4, 5, 6, 0, 0]), [5, 7, 9, 4, 5])
];
runTestCasesIntListIntList(testCasesAddLists);

fun addListsParamsToString(li1, li2) = "addLists(" ^ valueToStringIntList(li1) ^ ", " ^ valueToStringIntList(li2) ^ ")";
runTests(testCasesAddLists, addListsParamsToString, valueToStringIntList);
16 changes: 9 additions & 7 deletions tests/tests-ica05/test_andList.sml
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@ use "src/ica05/ica5.sml";
use "tests/utils.sml";

val testCasesAndList = [
(andList, [true, true, true], true),
(andList, [true, false, true], false),
(andList, [false, false, false], false),
(andList, [], true), (* Empty list case *)
(andList, [true], true),
(andList, [false], false)
(andList, ([true, true, true]), true),
(andList, ([true, false, true]), false),
(andList, ([false, false, false]), false),
(andList, ([]), true), (* Empty list case *)
(andList, ([true]), true),
(andList, ([false]), false)
];
runTestCasesBoolListBool(testCasesAndList);

fun andListParamsToString(li) = "andList(" ^ valueToStringBoolList(li) ^ ")";
runTests(testCasesAndList, andListParamsToString, valueToStringBool);
32 changes: 17 additions & 15 deletions tests/tests-ica05/test_combineLists.sml
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,21 @@ fun mockDiv(x, y) = x div y;
fun doNothing(x, y) = x;

val testCasesCombineLists = [
(combineLists, [1, 2, 3], [4, 5, 6], mockAdd, [5, 7, 9]),
(combineLists, [1, 2], [4, 5, 6], mockAdd, [5, 7]),
(combineLists, [], [4, 5, 6], mockModulus, []),
(combineLists, [], [], mockModulus, []),
(combineLists, [1, 2, 3], [4, 5, 6], mockDiv, [0, 0, 0]),
(combineLists, [1, 2], [4, 5, 6], mockDiv, [0, 0]),
(combineLists, [8, 8, 3], [4], mockDiv, [2]),
(combineLists, [4], [4, 5, 6], mockDiv, [1]),
(combineLists, [], [], mockDiv, []),
(combineLists, [1, 2, 3], [4, 5, 6], doNothing, [1, 2, 3]),
(combineLists, [1, 2], [4, 5, 6], doNothing, [1, 2]),
(combineLists, [1, 2, 3], [], doNothing, []),
(combineLists, [], [4, 5, 6], doNothing, []),
(combineLists, [], [], doNothing, [])
(combineLists, ([1, 2, 3], [4, 5, 6], mockAdd), [5, 7, 9]),
(combineLists, ([1, 2], [4, 5, 6], mockAdd), [5, 7]),
(combineLists, ([], [4, 5, 6], mockModulus), []),
(combineLists, ([], [], mockModulus), []),
(combineLists, ([1, 2, 3], [4, 5, 6], mockDiv), [0, 0, 0]),
(combineLists, ([1, 2], [4, 5, 6], mockDiv), [0, 0]),
(combineLists, ([8, 8, 3], [4], mockDiv), [2]),
(combineLists, ([4], [4, 5, 6], mockDiv), [1]),
(combineLists, ([], [], mockDiv), []),
(combineLists, ([1, 2, 3], [4, 5, 6], doNothing), [1, 2, 3]),
(combineLists, ([1, 2], [4, 5, 6], doNothing), [1, 2]),
(combineLists, ([1, 2, 3], [], doNothing), []),
(combineLists, ([], [4, 5, 6], doNothing), []),
(combineLists, ([], [], doNothing), [])
];
runTestCasesIntListIntListOperatorToIntList(testCasesCombineLists);

fun combineListsParamsToString(li1, li2, _) = "combineLists(" ^ valueToStringIntList(li1) ^ ", " ^ valueToStringIntList(li2) ^ ")";
runTests(testCasesCombineLists, combineListsParamsToString, valueToStringIntList);
22 changes: 12 additions & 10 deletions tests/tests-ica05/test_countZeros.sml
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,16 @@ use "src/ica05/ica5.sml";
use "tests/utils.sml";

val testCasesCountZeros = [
(countZeros, [0, 1, 0, 1, 0], 3),
(countZeros, [1, 1, 1, 1, 1], 0),
(countZeros, [0, 0, 0, 0, 0], 5),
(countZeros, [], 0),
(countZeros, [0], 1),
(countZeros, [1], 0),
(countZeros, [0, 0, 0, 1, 0], 4),
(countZeros, [1, 0, 1, 0, 1], 2),
(countZeros, [0, 0, 1, 0, 0, 0], 5)
(countZeros, ([0, 1, 0, 1, 0]), 3),
(countZeros, ([1, 1, 1, 1, 1]), 0),
(countZeros, ([0, 0, 0, 0, 0]), 5),
(countZeros, ([]), 0),
(countZeros, ([0]), 1),
(countZeros, ([1]), 0),
(countZeros, ([0, 0, 0, 1, 0]), 4),
(countZeros, ([1, 0, 1, 0, 1]), 2),
(countZeros, ([0, 0, 1, 0, 0, 0]), 5)
];
runTestCasesIntListInt(testCasesCountZeros);

fun countZerosParamsToString(li) = "countZeros(" ^ valueToStringIntList(li) ^ ")";
runTests(testCasesCountZeros, countZerosParamsToString, Int.toString);
24 changes: 13 additions & 11 deletions tests/tests-ica05/test_factorial.sml
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,17 @@ use "src/ica05/ica5.sml";
use "tests/utils.sml";

val testCasesFactorial = [
(factorial, 0, 1), (* 0! = 1 *)
(factorial, 1, 1), (* 1! = 1 *)
(factorial, 2, 2), (* 2! = 2 *)
(factorial, 3, 6), (* 3! = 6 *)
(factorial, 4, 24), (* 4! = 24 *)
(factorial, 5, 120), (* 5! = 120 *)
(factorial, 6, 720), (* 6! = 720 *)
(factorial, 7, 5040), (* 7! = 5040 *)
(factorial, 8, 40320), (* 8! = 40320 *)
(factorial, 10, 3628800) (* 10! = 3628800 *)
(factorial, (0), 1), (* 0! = 1 *)
(factorial, (1), 1), (* 1! = 1 *)
(factorial, (2), 2), (* 2! = 2 *)
(factorial, (3), 6), (* 3! = 6 *)
(factorial, (4), 24), (* 4! = 24 *)
(factorial, (5), 120),(* 5! = 120 *)
(factorial, (6), 720),(* 6! = 720 *)
(factorial, (7), 5040),(* 7! = 5040 *)
(factorial, (8), 40320),(* 8! = 40320 *)
(factorial, (10), 3628800) (* 10! = 3628800 *)
];
runTestCasesIntInt(testCasesFactorial);

fun factorialParamsToString(n) = "factorial(" ^ Int.toString(n) ^ ")";
runTests(testCasesFactorial, factorialParamsToString, Int.toString);
26 changes: 14 additions & 12 deletions tests/tests-ica05/test_fib.sml
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,18 @@ use "tests/utils.sml";

val testCasesFib = [
(* a_n = {0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55} *)
(fib, 0, 0),
(fib, 1, 1),
(fib, 2, 1),
(fib, 3, 2),
(fib, 4, 3),
(fib, 5, 5),
(fib, 6, 8),
(fib, 7, 13),
(fib, 8, 21),
(fib, 9, 34),
(fib, 10, 55)
(fib, (0), 0),
(fib, (1), 1),
(fib, (2), 1),
(fib, (3), 2),
(fib, (4), 3),
(fib, (5), 5),
(fib, (6), 8),
(fib, (7), 13),
(fib, (8), 21),
(fib, (9), 34),
(fib, (10), 55)
];
runTestCasesIntInt(testCasesFib);

fun fibParamsToString(n) = "fib(" ^ Int.toString(n) ^ ")";
runTests(testCasesFib, fibParamsToString, Int.toString);
Loading

0 comments on commit ab41718

Please sign in to comment.