Last active
December 12, 2015 05:58
-
-
Save kvalle/4725568 to your computer and use it in GitHub Desktop.
Tests for coursera-pl hw3
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
fun assert_equals (expected, actual, formatter) = | |
if expected = actual | |
then " -- PASS" | |
else "Expected: '" ^ formatter (expected) ^ "' but got '" ^ formatter (actual) ^ "' -- FAIL" | |
fun assert_bool_equals(expected, actual) = | |
if expected = actual then " -- PASS" | |
else "Expected: " ^ Bool.toString (expected) ^ ", but was: " ^ Bool.toString (actual) ^ " -- FAIL" | |
fun assert_true (actual) = assert_bool_equals(true, actual) | |
fun assert_false (actual) = assert_bool_equals(false, actual) | |
fun assert_raise (f, e) = | |
( | |
f(); | |
"Expected: " ^ exnName (e) ^ " to be thrown, but it wasn't -- FAIL" | |
) | |
handle e' => | |
if exnName e = exnName e' then " -- PASS" | |
else "Expected: " ^ exnName (e) ^ " to be thrown " ^ | |
"but " ^ exnName (e') ^ " was thrown -- FAIL" | |
fun assert_equal_fn_outputs(f1, f2, args_list, input_formatter, output_formatter) = | |
let | |
fun inner(args_list, errors) = | |
case (args_list, errors) of | |
([],[]) => " -- PASS" | |
| ([], errors) => "Outputs did not match. " ^ (String.concatWith " AND " errors) ^ " -- FAIL" | |
| (args::rest, errors) => | |
let | |
val out1 = f1(args) | |
val out2 = f2(args) | |
in | |
if out1 = out2 then inner(rest, errors) | |
else | |
let val message = "'" ^ input_formatter(args) ^ "' ==> '" ^ | |
output_formatter(out1) ^ "' <> '" ^ output_formatter(out2) ^ "'" | |
in | |
inner(rest, message::errors) | |
end | |
end | |
in | |
inner(args_list, []) | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
val string_formatter = fn s => s | |
val int_formatter = Int.toString | |
fun string_list_option_formatter some_list = | |
case some_list of | |
NONE => "NONE" | |
| SOME [] => "" | |
| SOME (x::[]) => x | |
| SOME (x::rest) => x ^ ", " ^ string_list_option_formatter(SOME rest) | |
fun int_list_option_formatter some_list = | |
case some_list of | |
NONE => "NONE" | |
| SOME [] => "" | |
| SOME (x::[]) => Int.toString(x) | |
| SOME (x::rest) => Int.toString(x) ^ ", " ^ int_list_option_formatter(SOME rest) | |
fun string_list_formatter list = | |
case list of | |
[] => "EMPTY" | |
| x::[] => x | |
| x::rest => x ^ ", " ^ string_list_formatter (rest) | |
(* hw3 specific below *) | |
fun valu_formatter v = | |
case v of | |
Const n => "Const " ^ Int.toString(n) | |
| Unit => "Unit" | |
| Tuple valuList => "Tuple(" ^ (String.concatWith ", " (List.map valu_formatter valuList)) ^ ")" | |
| Constructor (str, v) => "Constructor(" ^ str ^ ", " ^ valu_formatter(v) ^ ")" | |
fun binding_formatter (s,v) = s ^ " = " ^ valu_formatter(v) | |
fun binding_list_option_formatter some_list = | |
case some_list of | |
NONE => "NONE" | |
| SOME list => "SOME [" | |
^ (String.concatWith ", " (List.map binding_formatter list)) | |
^ "]" | |
fun type_formatter t = | |
case t of | |
Anything => "Anything" | |
| UnitT => "UnitT" | |
| IntT => "IntT" | |
| TupleT ts => "TupleT(" ^(String.concatWith ", " (List.map type_formatter ts)) ^ ")" | |
| Datatype s => "Datatype(" ^ s ^ ")" | |
fun type_list_option_formatter list_option = | |
case list_option of | |
NONE => "NONE" | |
| SOME list => "SOME [" | |
^ (String.concatWith ", " (List.map type_formatter list)) | |
^ "]" | |
fun type_option_formatter option = | |
case option of | |
NONE => "NONE" | |
| SOME t => "SOME " ^ type_formatter(t) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use "hw3.sml"; | |
use "asserts.sml"; | |
use "formatters.sml"; | |
Control.Print.printDepth := 1024; | |
(* problem 1 *) | |
val removes_all_words_not_starting_with_capital = | |
assert_equals(["Foo", "BAZ"], | |
only_capitals(["Foo", "bar", "BAZ", "uNF UNF"]), | |
string_list_formatter) | |
val empty_list_returns_empty_list = | |
assert_equals([], only_capitals([]), string_list_formatter) | |
(* problem 2 *) | |
val longest_string1_of_empty_list_is_empty_string = | |
assert_equals("", longest_string1([]), string_formatter) | |
val longest_string1_returns_the_longest_string = | |
assert_equals("12345678", | |
longest_string1(["123", "12345", "12345678", "12"]), | |
string_formatter) | |
val longest_string1_returns_first_in_case_of_tie = | |
assert_equals("foo", | |
longest_string1(["a","b","foo","c","bar","d"]), | |
string_formatter) | |
(* problem 3 *) | |
val longest_string2_returns_last_in_case_of_tie = | |
assert_equals("bar", | |
longest_string2(["a","b","foo","c","bar","d"]), | |
string_formatter) | |
(* problem 4 *) | |
val longest_string3_is_same_as_longest_string1 = | |
let val inputs = [[""], | |
["123", "12345", "12345678", "12"], | |
["a","b","foo","c","bar","d"]] | |
val out_formatter = string_formatter | |
val in_formatter = string_list_formatter | |
in | |
assert_equal_fn_outputs(longest_string3, longest_string1, | |
inputs, | |
in_formatter, out_formatter) | |
end | |
val longest_string4_is_same_as_longest_string2 = | |
let val inputs = [[""], | |
["123", "12345", "12345678", "12"], | |
["a","b","foo","c","bar","d"]] | |
val out_formatter = string_formatter | |
val in_formatter = string_list_formatter | |
in | |
assert_equal_fn_outputs(longest_string4, longest_string2, | |
inputs, | |
in_formatter, out_formatter) | |
end | |
(* problem 5 *) | |
val non_capitalized_are_ignored = | |
assert_equals("Aaa", longest_capitalized(["aaaaaaa", "Aaa"]), string_formatter) | |
val first_longest_is_returned = | |
assert_equals("Aaa", longest_capitalized(["aa", "Aaa", "Bbb"]), string_formatter) | |
val empty_list_returns_empty_string = | |
assert_equals("", longest_capitalized([]), string_formatter) | |
(* problem 6 *) | |
val reverse_of_empty_string_is_unchanged = | |
assert_equals("", rev_string(""), string_formatter) | |
val test_reverse_of_non_empty_string = | |
assert_equals("zab rab oof", rev_string("foo bar baz"), string_formatter) | |
(* problem 7 *) | |
val test_empty_args_raises_exception = | |
assert_raise( | |
(fn () => | |
first_answer (fn x => SOME 1) []), | |
NoAnswer | |
) | |
val exception_is_raised_if_no_args_produce_result = | |
assert_raise( | |
(fn () => | |
first_answer (fn x => NONE) [1,2,3,4]), | |
NoAnswer | |
) | |
val test_that_first_result_is_returned = | |
let val even = (fn x => if (x mod 2) = 0 then SOME x else NONE) | |
in | |
assert_equals(2, | |
(first_answer | |
even | |
[1,2,3,4]), | |
int_formatter) | |
end | |
(* problem 8 *) | |
val even_or_none = (fn x => if (x mod 2) = 0 then SOME [x] else NONE) | |
val test_that_all_answers_returns_SOME_for_empty_list = | |
assert_equals(SOME [], | |
all_answers even_or_none [], | |
int_list_option_formatter) | |
val test_return_when_all_have_answers = | |
assert_equals(SOME [2,4], | |
all_answers even_or_none [2,4], | |
int_list_option_formatter) | |
val test_return_when_some_answer_is_NONE = | |
assert_equals(NONE, | |
all_answers even_or_none [2,3,4], | |
int_list_option_formatter) | |
val test_return_concatinated_answers = | |
assert_equals(SOME [1,2,1,2,1,2], | |
all_answers (fn x => SOME [1,2]) [2,3,4], | |
int_list_option_formatter) | |
(* problem 9a *) | |
val test_count_wildcards_on_single_wildcard = | |
assert_equals(1, count_wildcards(Wildcard), int_formatter) | |
val test_count_wildcards_on_variable = | |
assert_equals(0, count_wildcards(Variable "foo"), int_formatter) | |
val test_count_wildcards_on_nested_pattern = | |
let val pattern = TupleP([Wildcard, | |
TupleP([Variable "foo", | |
Wildcard, | |
UnitP]), | |
ConstructorP("bar", Wildcard), | |
ConstructorP("baz", UnitP), | |
Wildcard]) | |
in | |
assert_equals(4, count_wildcards(pattern), int_formatter) | |
end | |
(* problem 9b *) | |
val test_count_wild_and_variable_lengths_on_pattern_with_neighter = | |
assert_equals(0, count_wild_and_variable_lengths(UnitP), int_formatter) | |
val test_count_wild_and_variable_lenghts_on_nested_pattern = | |
let val pattern = TupleP([Wildcard, | |
TupleP([Variable "foo", | |
Wildcard, | |
UnitP]), | |
Variable "bar"]) | |
in | |
assert_equals(8, count_wild_and_variable_lengths(pattern), int_formatter) | |
end | |
val test_that_count_wild_and_variable_lengths_ignores_constructors = | |
let val pattern = TupleP([Wildcard, | |
Variable "foo", | |
ConstructorP("bar", Wildcard)]) | |
in | |
assert_equals(5, count_wild_and_variable_lengths(pattern), int_formatter) | |
end | |
(* problem 9c *) | |
val test_count_some_var_in_pattern_without_vars = | |
assert_equals(0, count_some_var("foo", UnitP), int_formatter) | |
val test_count_some_var_in_pattern_with_only_other_vars = | |
assert_equals(0, | |
count_some_var("foo", TupleP([Variable "bar", | |
Variable "baz"])), | |
int_formatter) | |
val test_count_some_var_in_pattern_with_var_present = | |
assert_equals(2, | |
count_some_var("foo", TupleP([Variable "foo", | |
TupleP([Variable "bar", | |
Variable "foo"]), | |
Variable "baz"])), | |
int_formatter) | |
(* problem 10 *) | |
val test_check_pat_on_no_variables_is_true = | |
assert_true(check_pat(UnitP)) | |
val test_check_pat_on_pattern_with_no_duplicates = | |
assert_true(check_pat(TupleP([UnitP, | |
Variable "foo", | |
ConstructorP ("foo", UnitP), (* should be ignored *) | |
Variable "bar"]))) | |
val test_check_pat_on_pattern_with_duplicates = | |
assert_false(check_pat(TupleP([Variable "foo", | |
Variable "bar", | |
TupleP([UnitP, | |
Variable "foo"])]))) | |
(* problem 11 *) | |
val test_mismatch_between_pattern_and_value = | |
assert_equals(NONE, match(Const 42, UnitP), binding_list_option_formatter) | |
val test_matching_pattern_without_variables = | |
assert_equals(SOME [], match(Const 41, Wildcard), binding_list_option_formatter) | |
val test_matching_pattern_with_variable_bindings = | |
assert_equals(SOME [("foo", Tuple([Const 42, Unit])),("bar", Const 100)], | |
match(Tuple([Unit, | |
Tuple([Const 42, Unit]), | |
Const 100, | |
Constructor("x", Unit)]), | |
TupleP([UnitP, | |
Variable "foo", | |
Variable "bar", | |
ConstructorP("x", Wildcard)])), | |
binding_list_option_formatter) | |
(* problem 12 *) | |
val test_first_match_with_no_matches = | |
assert_equals(NONE, | |
first_match (Const 1) [ConstP 2, UnitP, ConstP 3], | |
binding_list_option_formatter) | |
val test_first_match_with_binding = | |
assert_equals(SOME [("foo", Const 1)], | |
first_match (Const 1) [ConstP 2, UnitP, Variable "foo", Variable "bar"], | |
binding_list_option_formatter) | |
val test_first_match_without_bindings = | |
assert_equals(SOME [], | |
first_match (Const 1) [Wildcard, Variable "foo"], | |
binding_list_option_formatter) | |
(* challenge problem *) | |
val test_both_wildcard_and_variable_can_be_anything = | |
assert_equals(SOME (TupleT [Anything, Anything]), | |
typecheck_patterns([], [TupleP [Variable("x"),Variable("y")], | |
TupleP [Wildcard,Wildcard]]), | |
type_option_formatter) | |
val test_tuple_more_specific_than_wildcard = | |
assert_equals(SOME (TupleT [Anything, TupleT [Anything,Anything]]), | |
typecheck_patterns([], [TupleP [Wildcard, Wildcard], | |
TupleP [Wildcard, TupleP [Wildcard, Wildcard]]]), | |
type_option_formatter) | |
val test_type_check_fail_returns_none = | |
assert_equals(NONE, | |
typecheck_patterns([], [UnitP, TupleP [Wildcard, UnitP]]), | |
type_option_formatter) | |
val test_type_check_fails_for_undefined_constructors = | |
assert_equals(NONE, | |
typecheck_patterns([], [ConstructorP("some_const", Variable "a_variable")]), | |
type_option_formatter) | |
val test_type_is_datatype_if_correct_type_is_given_in_constructor = | |
assert_equals(SOME (Datatype "my_type"), | |
typecheck_patterns([("my_cons", "my_type", IntT)], [ConstructorP("my_cons", ConstP 13)]), | |
type_option_formatter) | |
val test_type_check_fails_for_wrong_type_in_constuctor = | |
assert_equals(NONE, | |
typecheck_patterns([("my_cons", "my_type", IntT)], [ConstructorP("my_cons", UnitP)]), | |
type_option_formatter) | |
val test_type_of_two_constructors_of_same_datatype = | |
assert_equals(SOME (Datatype "my_type"), | |
typecheck_patterns([("int_cons", "my_type", IntT), ("unit_cons", "my_type", UnitT)], | |
[ConstructorP("int_cons", ConstP 42), ConstructorP("unit_cons", UnitP)]), | |
type_option_formatter) | |
val test_type_check_fails_for_two_constructors_of_different_types = | |
assert_equals(NONE, | |
typecheck_patterns([("int_cons", "my_type1", IntT), ("unit_cons", "my_type2", UnitT)], | |
[ConstructorP("int_cons", ConstP 42), ConstructorP("unit_cons", UnitP)]), | |
type_option_formatter) | |
val test_variable_is_anything_which_is_more_general_than_IntT = | |
assert_equals(NONE, | |
typecheck_patterns([("MyConstructor", "my_datatype", TupleT[Anything,IntT])], | |
[ConstructorP ("MyConstructor", TupleP[ConstP 4, Variable "x"])]), | |
type_option_formatter); | |
val test_type_check_works_for_nested_constructors = | |
assert_equals(SOME (Datatype "x_type"), | |
typecheck_patterns ([("x","x_type", Datatype("y_type")),("y","y_type",UnitT)], | |
[ConstructorP ("x", ConstructorP ("y", UnitP))]), | |
type_option_formatter) | |
val test_type_check_works_for_nested_recursive_constructors = | |
assert_equals(SOME (Datatype "type"), | |
typecheck_patterns ([("rec_c","type", Datatype("type")), ("nil_c","type",UnitT)], | |
[ConstructorP ("rec_c", ConstructorP ("nil_c", UnitP))]), | |
type_option_formatter) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment