trackler 2.2.1.19 → 2.2.1.20

Sign up to get free protection for your applications and to get access to all the features.
Files changed (96) hide show
  1. checksums.yaml +4 -4
  2. data/lib/trackler/version.rb +1 -1
  3. data/tracks/bash/config.json +11 -0
  4. data/tracks/bash/docs/ABOUT.md +5 -0
  5. data/tracks/bash/exercises/word-count/README.md +24 -0
  6. data/tracks/bash/exercises/word-count/example.awk +12 -0
  7. data/tracks/bash/exercises/word-count/example.sh +21 -0
  8. data/tracks/bash/exercises/word-count/word_count_test.sh +84 -0
  9. data/tracks/coffeescript/config/maintainers.json +5 -11
  10. data/tracks/csharp/.travis.yml +3 -0
  11. data/tracks/delphi/config/maintainers.json +1 -1
  12. data/tracks/ecmascript/config.json +108 -108
  13. data/tracks/elixir/exercises/phone-number/phone_number_test.exs +21 -1
  14. data/tracks/factor/docs/SNIPPET.txt +5 -0
  15. data/tracks/idris/docs/TESTS.md +7 -0
  16. data/tracks/java/config.json +47 -47
  17. data/tracks/javascript/config.json +103 -103
  18. data/tracks/julia/config.json +121 -121
  19. data/tracks/julia/docs/RESOURCES.md +1 -1
  20. data/tracks/julia/docs/SNIPPET.txt +8 -0
  21. data/tracks/objective-c/config.json +2 -3
  22. data/tracks/objective-c/exercises/rna-transcription/RNATranscriptionExample.m +11 -32
  23. data/tracks/ocaml/.travis-ci.sh +1 -1
  24. data/tracks/ocaml/.travis.yml +1 -1
  25. data/tracks/ocaml/README.md +1 -1
  26. data/tracks/ocaml/exercises/change/test.ml +24 -21
  27. data/tracks/ocaml/tools/test-generator/src/codegen.ml +3 -7
  28. data/tracks/ocaml/tools/test-generator/src/controller.ml +4 -5
  29. data/tracks/ocaml/tools/test-generator/src/languages.ml +4 -3
  30. data/tracks/ocaml/tools/test-generator/src/model.ml +1 -2
  31. data/tracks/ocaml/tools/test-generator/src/ocaml_special_cases.ml +19 -18
  32. data/tracks/ocaml/tools/test-generator/src/parser.ml +12 -17
  33. data/tracks/ocaml/tools/test-generator/src/purescript_special_cases.ml +11 -3
  34. data/tracks/ocaml/tools/test-generator/test/codegen_test.ml +2 -3
  35. data/tracks/ocaml/tools/test-generator/test/ocaml_special_cases_test.ml +12 -4
  36. data/tracks/ocaml/tools/test-generator/test/parser_test.ml +10 -10
  37. data/tracks/purescript/exercises/bob/test/Main.purs +5 -5
  38. data/tracks/ruby/bin/generate +1 -1
  39. data/tracks/ruby/docs/24pullrequests.md +1 -1
  40. data/tracks/ruby/exercises/all-your-base/all_your_base_test.rb +24 -24
  41. data/tracks/ruby/exercises/alphametics/.meta/generator/test_template.erb +1 -1
  42. data/tracks/ruby/exercises/bowling/.meta/generator/test_template.erb +1 -1
  43. data/tracks/ruby/exercises/bowling/bowling_test.rb +10 -10
  44. data/tracks/ruby/exercises/change/.meta/.version +1 -1
  45. data/tracks/ruby/exercises/change/.meta/solutions/change.rb +1 -1
  46. data/tracks/ruby/exercises/change/change_test.rb +7 -2
  47. data/tracks/ruby/exercises/collatz-conjecture/.meta/generator/collatz_conjecture_case.rb +1 -1
  48. data/tracks/ruby/exercises/connect/.meta/generator/test_template.erb +1 -1
  49. data/tracks/ruby/exercises/dominoes/.meta/generator/test_template.erb +1 -1
  50. data/tracks/ruby/exercises/hamming/.meta/generator/hamming_case.rb +5 -1
  51. data/tracks/ruby/exercises/hamming/hamming_test.rb +7 -7
  52. data/tracks/ruby/exercises/leap/.meta/generator/test_template.erb +1 -1
  53. data/tracks/ruby/exercises/pangram/.meta/.version +1 -1
  54. data/tracks/ruby/exercises/pangram/.meta/solutions/pangram.rb +1 -1
  55. data/tracks/ruby/exercises/pangram/pangram_test.rb +3 -3
  56. data/tracks/ruby/exercises/rna-transcription/rna_transcription_test.rb +4 -4
  57. data/tracks/ruby/exercises/roman-numerals/.meta/solutions/roman_numerals.rb +1 -1
  58. data/tracks/ruby/exercises/space-age/.meta/generator/test_template.erb +1 -1
  59. data/tracks/ruby/lib/generator/test_template.erb +1 -1
  60. data/tracks/ruby/lib/generator/underscore.rb +1 -1
  61. data/tracks/ruby/lib/helper.rb +4 -4
  62. data/tracks/ruby/test/fixtures/{xruby → ruby}/exercises/alpha-beta/.meta/generator/test_template.erb +1 -1
  63. data/tracks/ruby/test/fixtures/{xruby → ruby}/exercises/alpha/.meta/.version +0 -0
  64. data/tracks/ruby/test/fixtures/{xruby → ruby}/exercises/alpha/.meta/generator/alpha_case.rb +0 -0
  65. data/tracks/ruby/test/fixtures/{xruby → ruby}/exercises/alpha/.meta/generator/test_template.erb +1 -1
  66. data/tracks/ruby/test/fixtures/{xruby → ruby}/exercises/alpha/.meta/solutions/alpha.rb +0 -0
  67. data/tracks/ruby/test/fixtures/{xruby → ruby}/exercises/beta/.meta/.version +0 -0
  68. data/tracks/ruby/test/fixtures/{xruby → ruby}/exercises/beta/.meta/generator/beta_case.rb +0 -0
  69. data/tracks/ruby/test/fixtures/{xruby → ruby}/lib/generator/test_template.erb +1 -1
  70. data/tracks/ruby/test/generator/files/track_files_test.rb +4 -4
  71. data/tracks/ruby/test/generator/implementation_test.rb +1 -1
  72. data/tracks/ruby/test/generator/template_values_test.rb +1 -1
  73. data/tracks/scala/exercises/rail-fence-cipher/src/main/scala/{RailFenceCipher.scala → .keep} +0 -0
  74. data/tracks/scala/exercises/rail-fence-cipher/src/test/scala/RailFenceCipherTest.scala +16 -23
  75. data/tracks/scala/exercises/say/src/test/scala/SayTest.scala +20 -33
  76. data/tracks/scala/testgen/src/main/scala/RailFenceCipherTestGenerator.scala +9 -53
  77. data/tracks/scala/testgen/src/main/scala/SayTestGenerator.scala +50 -0
  78. data/tracks/sml/bin/generate +1 -1
  79. data/tracks/sml/config.json +30 -0
  80. data/tracks/sml/exercises/all-your-base/README.md +61 -0
  81. data/tracks/sml/exercises/all-your-base/all-your-base.sml +2 -0
  82. data/tracks/sml/exercises/all-your-base/example.sml +36 -0
  83. data/tracks/sml/exercises/all-your-base/test.sml +75 -0
  84. data/tracks/sml/exercises/all-your-base/testlib.sml +159 -0
  85. data/tracks/sml/exercises/difference-of-squares/example.sml +3 -6
  86. data/tracks/sml/exercises/list-ops/README.md +40 -0
  87. data/tracks/sml/exercises/list-ops/example.sml +34 -0
  88. data/tracks/sml/exercises/list-ops/list-ops.sml +23 -0
  89. data/tracks/sml/exercises/list-ops/test.sml +85 -0
  90. data/tracks/sml/exercises/list-ops/testlib.sml +159 -0
  91. data/tracks/sml/exercises/prime-factors/README.md +66 -0
  92. data/tracks/sml/exercises/prime-factors/example.sml +15 -0
  93. data/tracks/sml/exercises/prime-factors/prime-factors.sml +2 -0
  94. data/tracks/sml/exercises/prime-factors/test.sml +35 -0
  95. data/tracks/sml/exercises/prime-factors/testlib.sml +159 -0
  96. metadata +34 -11
@@ -8,39 +8,18 @@
8
8
  @"C" : @"G",
9
9
  @"T" : @"A",
10
10
  @"A" : @"U" };
11
-
12
- NSArray *dnaKeys = [dnaToRNADict allKeys];
13
- NSString *dnaKeyString = [dnaKeys componentsJoinedByString:@""];
14
- NSCharacterSet *invertedSet = [[NSCharacterSet characterSetWithCharactersInString:dnaKeyString] invertedSet];
15
- NSRange invertedSetRange = [dnaStrand rangeOfCharacterFromSet:invertedSet];
16
- if (invertedSetRange.location != NSNotFound) {
17
- return nil;
11
+
12
+ NSMutableString *rnaStrand = [NSMutableString stringWithString:dnaStrand];
13
+
14
+ for (NSUInteger i = 0; i < [dnaStrand length]; i++) {
15
+ NSRange charRange = [dnaStrand rangeOfComposedCharacterSequenceAtIndex:i];
16
+ NSString *dnaNucleotide = [dnaStrand substringWithRange:charRange];
17
+ NSString *rnaNucleotide = dnaToRNADict[dnaNucleotide];
18
+ if (!rnaNucleotide) return nil;
19
+ [rnaStrand replaceCharactersInRange:charRange withString:rnaNucleotide];
18
20
  }
19
-
20
- NSMutableString *rna = [NSMutableString stringWithString:dnaStrand];
21
- NSMutableDictionary *dnaToRnaRanges = [NSMutableDictionary dictionary];
22
-
23
- [[dnaToRNADict allKeys] enumerateObjectsUsingBlock:^(NSString *dnaKey, NSUInteger idx, BOOL * _Nonnull stop) {
24
- NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:dnaKey options:0 error:NULL];
25
- NSMutableArray *ranges = [NSMutableArray array];
26
-
27
- [regex enumerateMatchesInString:dnaStrand options:0 range:NSMakeRange(0, [dnaStrand length]) usingBlock:^(NSTextCheckingResult * _Nullable match, NSMatchingFlags flags, BOOL * _Nonnull stop) {
28
- NSRange range = [match rangeAtIndex:0];
29
- [ranges addObject:[NSValue valueWithRange:range]];
30
- }];
31
-
32
- dnaToRnaRanges[dnaKey] = [ranges copy];
33
- }];
34
-
35
- [dnaToRNADict enumerateKeysAndObjectsUsingBlock:^(NSString *dnaKey, NSString *rnaValue, BOOL * _Nonnull stop) {
36
- NSArray *dnaRanges = dnaToRnaRanges[dnaKey];
37
-
38
- [dnaRanges enumerateObjectsUsingBlock:^(NSValue *dnaRangeValue, NSUInteger idx, BOOL * _Nonnull stop) {
39
- [rna replaceOccurrencesOfString:dnaKey withString:rnaValue options:NSLiteralSearch range:[dnaRangeValue rangeValue]];
40
- }];
41
- }];
42
-
43
- return [rna copy];
21
+
22
+ return [rnaStrand copy];
44
23
  }
45
24
 
46
25
  @end
@@ -2,7 +2,7 @@
2
2
  OPAM_DEPENDS="ocamlfind core ounit react"
3
3
 
4
4
  case "$OCAML_VERSION,$OPAM_VERSION" in
5
- 4.04.1,1.2.2) ppa=avsm/ocaml42+opam12 ;;
5
+ 4.05.0,1.2.2) ppa=avsm/ocaml42+opam12 ;;
6
6
  *) echo Unknown $OCAML_VERSION,$OPAM_VERSION; exit 1 ;;
7
7
  esac
8
8
 
@@ -6,4 +6,4 @@ script:
6
6
  - bin/configlet lint .
7
7
 
8
8
  env:
9
- - OCAML_VERSION=4.04.1 OPAM_VERSION=1.2.2
9
+ - OCAML_VERSION=4.05.0 OPAM_VERSION=1.2.2
@@ -11,7 +11,7 @@ notes contain a few details specific to Ocaml.
11
11
 
12
12
  ## Prerequisites
13
13
 
14
- The OCaml track assumes installation of OCaml version 4.04.1, and installation of Core, OUnit, and React (for the Hangman exercise).
14
+ The OCaml track assumes installation of OCaml version 4.05.0, and installation of Core, OUnit, and React (for the Hangman exercise).
15
15
  Assuming you have opam, these can be installed with
16
16
  ```bash
17
17
  opam install core ounit react
@@ -1,4 +1,4 @@
1
- (* Test/exercise version: "1.0.0" *)
1
+ (* Test/exercise version: "1.1.0" *)
2
2
 
3
3
  open Core
4
4
  open OUnit2
@@ -9,35 +9,38 @@ let ae exp got _test_ctxt = assert_equal ~printer exp got
9
9
 
10
10
  let tests = [
11
11
  "single coin change" >::
12
- ae (Some [25])
13
- (make_change ~target:25 ~coins:[1; 5; 10; 25; 100]);
12
+ ae (Some [25])
13
+ (make_change ~target:25 ~coins:[1; 5; 10; 25; 100]);
14
14
  "multiple coin change" >::
15
- ae (Some [5; 10])
16
- (make_change ~target:15 ~coins:[1; 5; 10; 25; 100]);
15
+ ae (Some [5; 10])
16
+ (make_change ~target:15 ~coins:[1; 5; 10; 25; 100]);
17
17
  "change with Lilliputian Coins" >::
18
- ae (Some [4; 4; 15])
19
- (make_change ~target:23 ~coins:[1; 4; 15; 20; 50]);
18
+ ae (Some [4; 4; 15])
19
+ (make_change ~target:23 ~coins:[1; 4; 15; 20; 50]);
20
20
  "change with Lower Elbonia Coins" >::
21
- ae (Some [21; 21; 21])
22
- (make_change ~target:63 ~coins:[1; 5; 10; 21; 25]);
21
+ ae (Some [21; 21; 21])
22
+ (make_change ~target:63 ~coins:[1; 5; 10; 21; 25]);
23
23
  "large target values" >::
24
- ae (Some [2; 2; 5; 20; 20; 50; 100; 100; 100; 100; 100; 100; 100; 100; 100])
25
- (make_change ~target:999 ~coins:[1; 2; 5; 10; 20; 50; 100]);
24
+ ae (Some [2; 2; 5; 20; 20; 50; 100; 100; 100; 100; 100; 100; 100; 100; 100])
25
+ (make_change ~target:999 ~coins:[1; 2; 5; 10; 20; 50; 100]);
26
26
  "possible change without unit coins available" >::
27
- ae (Some [2; 2; 2; 5; 10])
28
- (make_change ~target:21 ~coins:[2; 5; 10; 20; 50]);
27
+ ae (Some [2; 2; 2; 5; 10])
28
+ (make_change ~target:21 ~coins:[2; 5; 10; 20; 50]);
29
+ "another possible change without unit coins available" >::
30
+ ae (Some [4; 4; 4; 5; 5; 5])
31
+ (make_change ~target:27 ~coins:[4; 5]);
29
32
  "no coins make 0 change" >::
30
- ae (Some [])
31
- (make_change ~target:0 ~coins:[1; 5; 10; 21; 25]);
33
+ ae (Some [])
34
+ (make_change ~target:0 ~coins:[1; 5; 10; 21; 25]);
32
35
  "error testing for change smaller than the smallest of coins" >::
33
- ae None
34
- (make_change ~target:3 ~coins:[5; 10]);
36
+ ae None
37
+ (make_change ~target:3 ~coins:[5; 10]);
35
38
  "error if no combination can add up to target" >::
36
- ae None
37
- (make_change ~target:94 ~coins:[5; 10]);
39
+ ae None
40
+ (make_change ~target:94 ~coins:[5; 10]);
38
41
  "cannot find negative change values" >::
39
- ae None
40
- (make_change ~target:(-5) ~coins:[1; 2; 5]);
42
+ ae None
43
+ (make_change ~target:(-5) ~coins:[1; 2; 5]);
41
44
  ]
42
45
 
43
46
  let () =
@@ -3,8 +3,6 @@ open Core
3
3
  open Model
4
4
  open Yojson.Basic
5
5
 
6
- type edit_expected_function = value: json -> string
7
-
8
6
  type edit_parameters_function = (string * json) list -> (string * string) list
9
7
 
10
8
  type subst = Subst of string [@@deriving eq, show]
@@ -18,13 +16,11 @@ let replace_key (key: string) (value: string) (target: string): string =
18
16
  let replace = String.substr_replace_all ~with_:value in
19
17
  replace ~pattern:("$" ^ key) target |> replace ~pattern:("$(" ^ key ^ ")")
20
18
 
21
- let rec replace_keys (f: edit_expected_function) (ed: edit_parameters_function) (s: string) (suite_name: string) (c: case): subst =
19
+ let rec replace_keys (ed: edit_parameters_function) (s: string) (suite_name: string) (c: case): subst =
22
20
  let s = replace_key "description" c.description s in
23
- let expected = f ~value:c.expected in
24
- let s = replace_key "expected" expected s in
25
21
  let s = replace_key "suite-name" suite_name s in
26
22
  let parameter_strings = ed @@ List.map ~f:(fun (k,p) -> (k,p)) c.parameters in
27
23
  List.fold parameter_strings ~init:(Subst s) ~f:(fun (Subst s) (k,v) -> Subst (replace_key k v s))
28
24
 
29
- let fill_in_template (f: edit_expected_function) (ed: edit_parameters_function) (test_template: string) (suite_name: string) (cases: case list) =
30
- List.map cases ~f:(replace_keys f ed test_template suite_name)
25
+ let fill_in_template (ed: edit_parameters_function) (test_template: string) (suite_name: string) (cases: case list) =
26
+ List.map cases ~f:(replace_keys ed test_template suite_name)
@@ -39,13 +39,12 @@ let prepend_version (version_printer: string -> string) (v: string option) (str:
39
39
  let generate_code ~(lc: language_config) ~(slug: string) ~(template_file: content) ~(canonical_data_file: content): (content, string) Result.t =
40
40
  let open Result.Monad_infix in
41
41
  Result.of_option ~error:("cannot recognize file for " ^ slug ^ " as a template") @@ find_template template_file lc.test_start_marker lc.test_end_marker >>= fun template ->
42
- let edit_expected = lc.edit_expected ~stringify:json_to_string ~slug in
43
- let edit_parameters = edit_parameters ~slug in
44
- let fill_in_template = fill_in_template edit_expected edit_parameters in
42
+ let edit_parameters = lc.edit_parameters ~slug in
43
+ let fill_in_template = fill_in_template edit_parameters in
45
44
  let file_text = template.file_text in
46
45
  let file_lines = String.split_lines file_text |> List.to_array in
47
46
  let prepend_version = prepend_version lc.version_printer in
48
- parse_json_text canonical_data_file "expected" "cases"
47
+ parse_json_text canonical_data_file "cases"
49
48
  |> Result.map_error ~f:show_error >>| simplify_single_test_suite >>= fun cd -> (match cd.tests with
50
49
  | Single cases ->
51
50
  let template = to_single template.template in
@@ -89,7 +88,7 @@ let check_canonical_data canonical_data_folder =
89
88
  let canonical_data_files = List.sort canonical_data_files ~cmp:(fun (s1, _) (s2, _) -> String.compare s1 s2) in
90
89
  let total_count = List.length canonical_data_files in
91
90
  List.iter canonical_data_files ~f:(fun (slug, text) ->
92
- match parse_json_text text "expected" "cases" with
91
+ match parse_json_text text "cases" with
93
92
  | Error e -> print_endline @@ slug ^ ": " ^ (show_error e)
94
93
  | _ -> ok_count := !ok_count + 1
95
94
  );
@@ -1,6 +1,7 @@
1
1
  open Core
2
2
  open Yojson.Basic
3
3
  include Ocaml_special_cases
4
+ include Purescript_special_cases
4
5
 
5
6
  type language_config = {
6
7
  template_file_name: string;
@@ -8,7 +9,7 @@ type language_config = {
8
9
  test_start_marker: string;
9
10
  test_end_marker: string;
10
11
  version_printer: string -> string;
11
- edit_expected: stringify: (json -> string) -> slug: string -> value: json -> string;
12
+ edit_parameters: slug: string -> (string * json) list -> (string * string) list;
12
13
  }
13
14
 
14
15
  let default_language_config = function
@@ -18,7 +19,7 @@ let default_language_config = function
18
19
  test_start_marker = "(* TEST";
19
20
  test_end_marker = "END TEST";
20
21
  version_printer = (fun v -> "(* Test/exercise version: \"" ^ v ^ "\" *)\n\n");
21
- edit_expected = ocaml_edit_expected;
22
+ edit_parameters = ocaml_edit_parameters
22
23
  }
23
24
  | "purescript" -> {
24
25
  template_file_name = "Main.purs";
@@ -26,7 +27,7 @@ let default_language_config = function
26
27
  test_start_marker = "--TEST";
27
28
  test_end_marker = "--END TEST";
28
29
  version_printer = (fun v -> "-- Test/exercise version: \"" ^ v ^ "\"\n\n");
29
- edit_expected = Purescript_special_cases.edit_expected;
30
+ edit_parameters = purescript_edit_parameters
30
31
  }
31
32
  | x -> failwith @@ "unknown language " ^ x
32
33
 
@@ -5,8 +5,7 @@ open Yojson.Basic
5
5
 
6
6
  type case = {
7
7
  description: string;
8
- parameters: (string * json) list;
9
- expected: json;
8
+ parameters: (string * json) list
10
9
  }
11
10
 
12
11
  type test = {name: string; cases: case list}
@@ -62,21 +62,10 @@ let edit_bowling_expected (value: json) = match value with
62
62
  if k = "error" then "(Error " ^ json_to_string v ^ ")" else failwith ("Can only handle error value but got " ^ k)
63
63
  | _ -> failwith "Bad json value in bowling"
64
64
 
65
- let ocaml_edit_expected ~(stringify: json -> string) ~(slug: string) ~(value: json) = match slug with
66
- | "hamming" -> optional_int ~none:(-1) value
67
- | "all-your-base" -> optional_int_list value
68
- | "say" -> optional_int_or_string ~none:(-1) value
69
- | "phone-number" -> option_of_null value
70
- | "connect" -> edit_connect_expected value
71
- | "change" -> edit_change_expected value
72
- | "bowling" -> edit_bowling_expected value
73
- | "binary-search" -> optional_int ~none:(-1) value
74
- | "forth" -> option_of_null value
75
- | _ -> stringify value
76
-
77
65
  let edit_say (ps: (string * json) list) =
78
66
  let edit = function
79
67
  | ("input", v) -> ("input", let v = json_to_string v in if Int.of_string v >= 0 then "(" ^ v ^ "L)" else v ^ "L")
68
+ | ("expected", v) -> ("expected", optional_int_or_string ~none:(-1) v)
80
69
  | (k, ps) -> (k, json_to_string ps) in
81
70
  List.map ps ~f:edit
82
71
 
@@ -84,6 +73,7 @@ let edit_all_your_base (ps: (string * json) list): (string * string) list =
84
73
  let edit = function
85
74
  | ("output_base", v) -> let v = json_to_string v in ("output_base", if Int.of_string v >= 0 then v else "(" ^ v ^ ")")
86
75
  | ("input_base", v) -> let v = json_to_string v in ("input_base", if Int.of_string v >= 0 then v else "(" ^ v ^ ")")
76
+ | ("expected", v) -> ("expected", optional_int_list v)
87
77
  | (k, v) -> (k, json_to_string v) in
88
78
  List.map ps ~f:edit
89
79
 
@@ -96,7 +86,6 @@ let edit_dominoes (ps: (string * json) list): (string * string) list =
96
86
  | (k, v) -> (k, json_to_string v) in
97
87
  List.map ps ~f:edit
98
88
 
99
-
100
89
  let edit_space_age (ps: (string * json) list): (string * string) list =
101
90
  let edit = function
102
91
  | ("planet", v) -> ("planet", json_to_string v |> strip_quotes)
@@ -107,6 +96,7 @@ let edit_bowling (ps: (string * json) list): (string * string) list =
107
96
  let edit = function
108
97
  | ("property", v) -> ("property", json_to_string v |> strip_quotes)
109
98
  | ("roll", `Int n) -> ("roll", let s = Int.to_string n in if n < 0 then ("(" ^ s ^ ")") else s)
99
+ | ("expected", v) -> ("expected", edit_bowling_expected v)
110
100
  | (k, v) -> (k, json_to_string v) in
111
101
  List.map ps ~f:edit
112
102
 
@@ -117,15 +107,26 @@ let edit_binary_search (ps: (string * json) list): (string * string) list =
117
107
  "[|" ^ String.concat ~sep:"; " xs ^ "|]" in
118
108
  let edit = function
119
109
  | ("array", v) -> ("array", as_array_string v)
110
+ | ("expected", v) -> ("expected", optional_int ~none:(-1) v)
120
111
  | (k, v) -> (k, json_to_string v) in
121
112
  List.map ps ~f:edit
122
113
 
123
- let edit_parameters ~(slug: string) (parameters: (string * json) list) = match (slug, parameters) with
124
- | ("hello-world", ps) -> default_value ~key:"name" ~value:"None" (optional_strings ~f:(fun _x -> true) parameters)
125
- | ("say", ps) -> edit_say ps
114
+ let rec edit_expected ~(f: json -> string) (parameters: (string * json) list) = match parameters with
115
+ | [] -> []
116
+ | ("expected", v) :: rest -> ("expected", f v) :: edit_expected f rest
117
+ | (k, v) :: rest -> (k, json_to_string v) :: edit_expected f rest
118
+
119
+ let ocaml_edit_parameters ~(slug: string) (parameters: (string * json) list) = match (slug, parameters) with
126
120
  | ("all-your-base", ps) -> edit_all_your_base ps
121
+ | ("binary-search", ps) -> edit_binary_search ps
122
+ | ("bowling", ps) -> edit_bowling ps
123
+ | ("change", ps) -> edit_expected ~f:edit_change_expected ps
124
+ | ("connect", ps) -> edit_expected ~f:edit_connect_expected ps
127
125
  | ("dominoes", ps) -> edit_dominoes ps
126
+ | ("forth", ps) -> edit_expected ~f:option_of_null ps
127
+ | ("hamming", ps) -> edit_expected ~f:(optional_int ~none:(-1)) ps
128
+ | ("hello-world", ps) -> default_value ~key:"name" ~value:"None" (optional_strings ~f:(fun _ -> true) parameters)
129
+ | ("phone-number", ps) -> edit_expected ~f:option_of_null ps
130
+ | ("say", ps) -> edit_say ps
128
131
  | ("space-age", ps) -> edit_space_age ps
129
- | ("bowling", ps) -> edit_bowling ps
130
- | ("binary-search", ps) -> edit_binary_search ps
131
132
  | (_, ps) -> map_elements json_to_string ps
@@ -6,20 +6,18 @@ open Model
6
6
 
7
7
  type error =
8
8
  TestMustHaveKeyCalledCases of string | ExpectingListOfCases | ExpectingMapForCase |
9
- NoDescription | BadDescription | NoExpected of string | BadExpected | UnrecognizedJson [@@deriving eq, show]
9
+ NoDescription | BadDescription | UnrecognizedJson [@@deriving eq, show]
10
10
 
11
- let parse_case_assoc (parameters: (string * json) list) (expected_key: string): (case, error) Result.t =
11
+ let parse_case_assoc (parameters: (string * json) list): (case, error) Result.t =
12
12
  let find name e = List.Assoc.find parameters ~equal:String.equal name |> Result.of_option ~error:e in
13
13
  let test_parameters = List.Assoc.remove parameters ~equal:String.equal "description" in
14
- let test_parameters = List.Assoc.remove test_parameters ~equal:String.equal expected_key in
15
14
  let open Result.Monad_infix in
16
15
  find "description" NoDescription >>=
17
16
  to_string_note BadDescription >>= fun description ->
18
- find expected_key (NoExpected description) >>= fun expected ->
19
- Ok {description = description; parameters = test_parameters; expected = expected}
17
+ Ok {description = description; parameters = test_parameters}
20
18
 
21
- let parse_case (expected_key: string) (s: json): (case, error) Result.t = match s with
22
- | `Assoc assoc -> parse_case_assoc assoc expected_key
19
+ let parse_case (s: json): (case, error) Result.t = match s with
20
+ | `Assoc assoc -> parse_case_assoc assoc
23
21
  | _ -> Error ExpectingMapForCase
24
22
 
25
23
  let parse_cases (text: string) (cases_key: string): (json, error) Result.t =
@@ -27,11 +25,11 @@ let parse_cases (text: string) (cases_key: string): (json, error) Result.t =
27
25
  | `Null -> Error (TestMustHaveKeyCalledCases cases_key)
28
26
  | json -> Ok json
29
27
 
30
- let parse_single (text: string) (expected_key: string) (cases_key: string): (tests, error) Result.t =
28
+ let parse_single (text: string) (cases_key: string): (tests, error) Result.t =
31
29
  let open Result.Monad_infix in
32
30
  parse_cases text cases_key >>=
33
31
  to_list_note ExpectingListOfCases >>=
34
- (sequence >> (List.map ~f:(parse_case expected_key))) >>= fun ts ->
32
+ (sequence >> (List.map ~f:parse_case)) >>= fun ts ->
35
33
  Result.return (Single ts)
36
34
 
37
35
  let rec to_cases case: (case list, error) Result.t =
@@ -43,8 +41,7 @@ let rec to_cases case: (case list, error) Result.t =
43
41
  List.map cases ~f:(to_assoc_note UnrecognizedJson) |> sequence >>= fun x ->
44
42
  List.map x ~f:to_cases |> sequence |> Result.map ~f:List.concat
45
43
  | None ->
46
- find_note case "expected" (NoExpected "expected") >>= fun expected ->
47
- Result.return [{description = desc; parameters = case; expected = expected}]
44
+ Result.return [{description = desc; parameters = case}]
48
45
 
49
46
  let convert_cases_description_to_name desc =
50
47
  String.lowercase desc |> String.substr_replace_all ~pattern:" " ~with_:"_"
@@ -63,19 +60,19 @@ let suite_cases (json: json) (cases_key: string): (test list, error) Result.t =
63
60
  (member cases_key json |> to_list_note ExpectingListOfCases) >>= fun assoc_cases ->
64
61
  List.map ~f:suite_case assoc_cases |> sequence
65
62
 
66
- let parse_cases_from_suite name suite expected_key cases_key =
63
+ let parse_cases_from_suite name suite cases_key =
67
64
  let open Result.Monad_infix in
68
65
  member_note (TestMustHaveKeyCalledCases name) cases_key suite >>=
69
66
  to_list_note ExpectingListOfCases >>= fun tests ->
70
- List.map tests ~f:(parse_case expected_key) |> sequence
67
+ List.map tests ~f:parse_case |> sequence
71
68
 
72
- let parse_json_text (text: string) (expected_key: string) (cases_key: string): (canonical_data, error) Result.t =
69
+ let parse_json_text (text: string) (cases_key: string): (canonical_data, error) Result.t =
73
70
  let open Result.Monad_infix in
74
71
  let json = from_string text in
75
72
  let version = member "version" json |> to_string_option in
76
73
  match suite_cases json cases_key with
77
74
  | Ok suite_cases -> Ok {version; tests=(Suite suite_cases)}
78
- | Error _ -> parse_single text expected_key cases_key >>= fun tests -> Ok {version; tests}
75
+ | Error _ -> parse_single text cases_key >>= fun tests -> Ok {version; tests}
79
76
 
80
77
  let show_error = function
81
78
  | TestMustHaveKeyCalledCases name -> "Test named '" ^ name ^ "' is expected to have an object with a key: 'cases'"
@@ -83,6 +80,4 @@ let show_error = function
83
80
  | ExpectingListOfCases -> "Expected a top level map with key cases, and a list of cases as its value."
84
81
  | NoDescription -> "Case is missing a description."
85
82
  | BadDescription -> "Description is not a string."
86
- | NoExpected s -> "Case '" ^ s ^ "' is missing an expected key."
87
- | BadExpected -> "Do not understand type of Expected key."
88
83
  | UnrecognizedJson -> "Cannot understand this json."
@@ -3,11 +3,19 @@ open Core
3
3
  open Model
4
4
  open Yojson.Basic
5
5
 
6
+ let map_elements (to_str: json -> string) (parameters: (string * json) list): (string * string) list =
7
+ List.map parameters ~f:(fun (k,j) -> (k,to_str j))
8
+
6
9
  let optional_int ~(none: int) = function
7
10
  | `Int n when n = none -> "Nothing"
8
11
  | `Int n -> "(Just " ^ Int.to_string n ^ ")"
9
12
  | x -> json_to_string x
10
13
 
11
- let edit_expected ~(stringify: json -> string) ~(slug: string) ~(value: json) = match slug with
12
- | "hamming" -> optional_int ~none:(-1) value
13
- | _ -> stringify value
14
+ let rec edit_expected ~(f: json -> string) (parameters: (string * json) list) = match parameters with
15
+ | [] -> []
16
+ | ("expected", v) :: rest -> ("expected", f v) :: edit_expected f rest
17
+ | (k, v) :: rest -> (k, json_to_string v) :: edit_expected f rest
18
+
19
+ let purescript_edit_parameters ~(slug: string) (parameters: (string * json) list) = match (slug, parameters) with
20
+ | ("hamming", ps) -> edit_expected ~f:(optional_int ~none:(-1)) ps
21
+ | (_, ps) -> map_elements json_to_string ps
@@ -6,12 +6,11 @@ open Yojson.Basic
6
6
 
7
7
  let leap_template = "\"$description\" >:: ae $expected (leap_year $input);"
8
8
 
9
- let edit_expected ~value = json_to_string value
10
9
  let edit_parameters (j: (string * json) list): (string * string) list =
11
10
  List.map ~f:(fun (k,v) -> (k,to_string v)) j
12
11
  let assert_fill_in_template exp cases = assert_equal exp
13
12
  ~printer:(fun xs -> "[" ^ (String.concat ~sep:";" xs) ^ "]")
14
- (fill_in_template edit_expected edit_parameters leap_template "suite-name" cases |> List.map ~f:subst_to_string)
13
+ (fill_in_template edit_parameters leap_template "suite-name" cases |> List.map ~f:subst_to_string)
15
14
  let ae exp cases _test_ctxt = assert_fill_in_template exp cases
16
15
 
17
16
  let codegen_tests = [
@@ -19,7 +18,7 @@ let codegen_tests = [
19
18
  ae [] [];
20
19
 
21
20
  "generates one function based on leap year for one case" >::(fun ctxt ->
22
- let c = {description = "leap_year"; parameters = [("input", `Int 1996)]; expected = `Bool true} in
21
+ let c = {description = "leap_year"; parameters = [("input", `Int 1996); ("expected", `Bool true)];} in
23
22
  assert_fill_in_template ["\"leap_year\" >:: ae true (leap_year 1996);"] [c]
24
23
  );
25
24
  ]