trackler 2.2.1.77 → 2.2.1.78
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/trackler/version.rb +1 -1
- data/problem-specifications/exercises/transpose/canonical-data.json +94 -116
- data/tracks/bash/config/maintainers.json +11 -1
- data/tracks/clojure/config.json +10 -2
- data/tracks/clojure/exercises/reverse-string/README.md +14 -0
- data/tracks/clojure/exercises/reverse-string/project.clj +4 -0
- data/tracks/clojure/exercises/reverse-string/src/example.clj +5 -0
- data/tracks/clojure/exercises/reverse-string/src/reverse_string.clj +5 -0
- data/tracks/clojure/exercises/reverse-string/test/reverse_string_test.clj +18 -0
- data/tracks/clojure/exercises/say/README.md +70 -0
- data/tracks/clojure/exercises/{two-fer → say}/project.clj +3 -3
- data/tracks/clojure/exercises/say/src/example.clj +9 -0
- data/tracks/clojure/exercises/say/src/say.clj +5 -0
- data/tracks/clojure/exercises/say/test/say_test.clj +48 -0
- data/tracks/coffeescript/docs/ABOUT.md +4 -9
- data/tracks/coffeescript/docs/INSTALLATION.md +2 -2
- data/tracks/erlang/exercises/pangram/rebar.config +1 -1
- data/tracks/erlang/exercises/pangram/src/example.erl +2 -3
- data/tracks/erlang/exercises/pangram/test/pangram_tests.erl +12 -13
- data/tracks/fsharp/exercises/grep/Example.fs +16 -20
- data/tracks/fsharp/exercises/grep/GrepTest.fs +154 -233
- data/tracks/fsharp/generators/Common.fs +7 -2
- data/tracks/fsharp/generators/Exercise.fs +51 -16
- data/tracks/fsharp/generators/Formatting.fs +13 -6
- data/tracks/fsharp/generators/Generators.fs +44 -14
- data/tracks/fsharp/generators/Rendering.fs +8 -1
- data/tracks/fsharp/generators/Templates/Generators/_GrepSetup.liquid +37 -0
- data/tracks/fsharp/generators/Templates/_TestClass.liquid +9 -3
- data/tracks/fsharp/generators/Templates/{_TestMethod.liquid → _TestFunction.liquid} +0 -0
- data/tracks/fsharp/generators/Templates/{_TestMethodBody.liquid → _TestFunctionBody.liquid} +0 -0
- data/tracks/fsharp/generators/Templates/_TestMember.liquid +3 -0
- data/tracks/fsharp/generators/Templates/_TestMemberBody.liquid +4 -0
- data/tracks/fsharp/generators/Templates/_TestModule.liquid +17 -0
- data/tracks/go/config.json +24 -0
- data/tracks/go/exercises/acronym/.meta/gen.go +5 -3
- data/tracks/go/exercises/acronym/acronym.go +0 -2
- data/tracks/go/exercises/acronym/cases_test.go +2 -2
- data/tracks/go/exercises/acronym/example.go +2 -3
- data/tracks/go/exercises/all-your-base/.meta/gen.go +9 -7
- data/tracks/go/exercises/all-your-base/cases_test.go +2 -2
- data/tracks/go/exercises/allergies/.meta/gen.go +10 -6
- data/tracks/go/exercises/allergies/cases_test.go +2 -2
- data/tracks/go/exercises/anagram/.meta/gen.go +7 -5
- data/tracks/go/exercises/anagram/cases_test.go +2 -2
- data/tracks/go/exercises/armstrong-numbers/.meta/gen.go +54 -0
- data/tracks/go/exercises/armstrong-numbers/armstrong_test.go +12 -0
- data/tracks/go/exercises/armstrong-numbers/cases_test.go +52 -0
- data/tracks/go/exercises/armstrong-numbers/example.go +24 -0
- data/tracks/go/exercises/binary-search/.meta/gen.go +7 -5
- data/tracks/go/exercises/binary-search/cases_test.go +2 -2
- data/tracks/go/exercises/book-store/.meta/gen.go +5 -3
- data/tracks/go/exercises/book-store/cases_test.go +2 -2
- data/tracks/go/exercises/connect/example.go +4 -5
- data/tracks/go/exercises/dominoes/.meta/gen.go +61 -0
- data/tracks/go/exercises/dominoes/.meta/hints.md +29 -0
- data/tracks/go/exercises/dominoes/README.md +67 -0
- data/tracks/go/exercises/dominoes/cases_test.go +72 -0
- data/tracks/go/exercises/dominoes/dominoes_test.go +106 -0
- data/tracks/go/exercises/dominoes/example.go +146 -0
- data/tracks/go/exercises/ledger/example.go +1 -1
- data/tracks/groovy/.gitignore +3 -0
- data/tracks/groovy/.travis.yml +10 -1
- data/tracks/groovy/bin/prepeare_exercise_builds.groovy +77 -0
- data/tracks/groovy/build.gradle +25 -0
- data/tracks/groovy/exercises/difference-of-squares/Example.groovy +3 -3
- data/tracks/groovy/exercises/gigasecond/GigasecondSpec.groovy +3 -3
- data/tracks/groovy/exercises/linked-list/{DoubleLinkedList.groovy → LinkedList.groovy} +0 -0
- data/tracks/groovy/exercises/linked-list/{DoubleLinkedListSpec.groovy → LinkedListSpec.groovy} +0 -0
- data/tracks/groovy/exercises/linked-list/README.md +1 -1
- data/tracks/groovy/gradle/wrapper/gradle-wrapper.jar +0 -0
- data/tracks/groovy/gradle/wrapper/gradle-wrapper.properties +6 -0
- data/tracks/groovy/gradlew +172 -0
- data/tracks/groovy/gradlew.bat +84 -0
- data/tracks/groovy/settings.gradle +9 -0
- data/tracks/ocaml/exercises/acronym/.merlin +1 -1
- data/tracks/ocaml/exercises/all-your-base/.merlin +1 -1
- data/tracks/ocaml/exercises/anagram/.merlin +1 -1
- data/tracks/ocaml/exercises/atbash-cipher/.merlin +1 -1
- data/tracks/ocaml/exercises/beer-song/.merlin +1 -1
- data/tracks/ocaml/exercises/binary-search/.merlin +1 -1
- data/tracks/ocaml/exercises/bob/.merlin +1 -1
- data/tracks/ocaml/exercises/bowling/.merlin +1 -1
- data/tracks/ocaml/exercises/change/.merlin +1 -1
- data/tracks/ocaml/exercises/difference-of-squares/.merlin +1 -1
- data/tracks/ocaml/exercises/etl/.merlin +1 -1
- data/tracks/ocaml/exercises/forth/.merlin +1 -1
- data/tracks/ocaml/exercises/grade-school/.merlin +1 -1
- data/tracks/ocaml/exercises/hamming/.merlin +1 -1
- data/tracks/ocaml/exercises/hangman/.merlin +1 -1
- data/tracks/ocaml/exercises/hello-world/.merlin +1 -1
- data/tracks/ocaml/exercises/hexadecimal/.merlin +1 -1
- data/tracks/ocaml/exercises/leap/.merlin +1 -1
- data/tracks/ocaml/exercises/list-ops/.merlin +1 -1
- data/tracks/ocaml/exercises/luhn/.merlin +1 -1
- data/tracks/ocaml/exercises/meetup/.merlin +1 -1
- data/tracks/ocaml/exercises/minesweeper/.merlin +1 -1
- data/tracks/ocaml/exercises/nucleotide-count/.merlin +1 -1
- data/tracks/ocaml/exercises/phone-number/.merlin +1 -1
- data/tracks/ocaml/exercises/prime-factors/.merlin +1 -1
- data/tracks/ocaml/exercises/raindrops/.merlin +1 -1
- data/tracks/ocaml/exercises/react/.merlin +1 -1
- data/tracks/ocaml/exercises/rectangles/.merlin +1 -1
- data/tracks/ocaml/exercises/rna-transcription/.merlin +1 -1
- data/tracks/ocaml/exercises/run-length-encoding/.merlin +1 -1
- data/tracks/ocaml/exercises/say/.merlin +1 -1
- data/tracks/ocaml/exercises/space-age/.merlin +1 -1
- data/tracks/ocaml/exercises/triangle/.merlin +1 -1
- data/tracks/ocaml/exercises/word-count/.merlin +1 -1
- data/tracks/ocaml/exercises/zipper/.merlin +1 -1
- data/tracks/typescript/config/maintainers.json +2 -2
- metadata +37 -12
- data/tracks/clojure/exercises/two-fer/README.md +0 -19
- data/tracks/clojure/exercises/two-fer/src/example.clj +0 -5
- data/tracks/clojure/exercises/two-fer/src/two_fer.clj +0 -5
- data/tracks/clojure/exercises/two-fer/test/two_fer_test.clj +0 -12
- data/tracks/erlang/exercises/pangram/include/exercism.hrl +0 -11
|
@@ -31,13 +31,18 @@ type TestMethodBodyAssert =
|
|
|
31
31
|
{ Sut: string
|
|
32
32
|
Expected: string }
|
|
33
33
|
|
|
34
|
-
type
|
|
34
|
+
type TestFile =
|
|
35
35
|
{ Version: string
|
|
36
36
|
ExerciseName: string
|
|
37
37
|
TestModuleName: string
|
|
38
38
|
TestedModuleName: string
|
|
39
39
|
Namespaces: string list
|
|
40
|
-
Methods: string list
|
|
40
|
+
Methods: string list
|
|
41
|
+
Setup: string }
|
|
42
|
+
|
|
43
|
+
type TestFileFormat =
|
|
44
|
+
| Module
|
|
45
|
+
| Class
|
|
41
46
|
|
|
42
47
|
module Logging =
|
|
43
48
|
let setupLogger() =
|
|
@@ -23,17 +23,24 @@ type GeneratorExercise() =
|
|
|
23
23
|
abstract member MapCanonicalDataCaseProperty : CanonicalDataCase * string * obj -> obj
|
|
24
24
|
|
|
25
25
|
// Convert canonical data to representation used when rendering
|
|
26
|
-
abstract member
|
|
26
|
+
abstract member ToTestFile : CanonicalData -> TestFile
|
|
27
27
|
abstract member ToTestMethod : int * CanonicalDataCase -> TestMethod
|
|
28
28
|
abstract member ToTestMethodBody : CanonicalDataCase -> TestMethodBody
|
|
29
29
|
abstract member ToTestMethodBodyAssert : CanonicalDataCase -> TestMethodBodyAssert
|
|
30
|
-
|
|
30
|
+
|
|
31
|
+
// Determine the templates to use when rendering
|
|
32
|
+
abstract member TestFileTemplate : string
|
|
33
|
+
abstract member TestMethodTemplate : int * CanonicalDataCase -> string
|
|
34
|
+
abstract member TestMethodBodyTemplate : CanonicalDataCase -> string
|
|
35
|
+
abstract member TestMethodBodyAssertTemplate : CanonicalDataCase -> string
|
|
36
|
+
abstract member TestFileFormat: TestFileFormat
|
|
31
37
|
|
|
32
38
|
// Rendering of canonical data
|
|
33
39
|
abstract member Render : CanonicalData -> string
|
|
34
|
-
abstract member RenderTestMethod : int
|
|
40
|
+
abstract member RenderTestMethod : int * CanonicalDataCase -> string
|
|
35
41
|
abstract member RenderTestMethodBody : CanonicalDataCase -> string
|
|
36
42
|
abstract member RenderTestMethodName : CanonicalDataCase -> string
|
|
43
|
+
abstract member RenderSetup : CanonicalData -> string
|
|
37
44
|
|
|
38
45
|
// Generic value/identifier rendering methods
|
|
39
46
|
abstract member RenderValue : CanonicalDataCase * string * obj -> string
|
|
@@ -66,10 +73,10 @@ type GeneratorExercise() =
|
|
|
66
73
|
member this.TestedModuleName = this.GetType().Name.Pascalize()
|
|
67
74
|
|
|
68
75
|
member this.WriteToFile contents =
|
|
69
|
-
let
|
|
76
|
+
let testFilePath = Path.Combine("..", "exercises", this.Name, sprintf "%s.fs" this.TestModuleName)
|
|
70
77
|
|
|
71
|
-
Directory.CreateDirectory(Path.GetDirectoryName(
|
|
72
|
-
File.WriteAllText(
|
|
78
|
+
Directory.CreateDirectory(Path.GetDirectoryName(testFilePath)) |> ignore
|
|
79
|
+
File.WriteAllText(testFilePath, contents)
|
|
73
80
|
|
|
74
81
|
member this.Regenerate(canonicalData) =
|
|
75
82
|
canonicalData
|
|
@@ -94,13 +101,16 @@ type GeneratorExercise() =
|
|
|
94
101
|
|
|
95
102
|
// Convert canonical data to representation used when rendering
|
|
96
103
|
|
|
97
|
-
default this.
|
|
104
|
+
default this.ToTestFile canonicalData =
|
|
105
|
+
let renderTestMethod i canonicalDataCase = this.RenderTestMethod(i, canonicalDataCase)
|
|
106
|
+
|
|
98
107
|
{ Version = canonicalData.Version
|
|
99
108
|
ExerciseName = this.Name
|
|
100
109
|
TestModuleName = this.TestModuleName
|
|
101
110
|
TestedModuleName = this.TestedModuleName
|
|
102
111
|
Namespaces = ["FsUnit.Xunit"; "Xunit"] @ this.AdditionalNamespaces
|
|
103
|
-
Methods = List.mapi
|
|
112
|
+
Methods = List.mapi renderTestMethod canonicalData.Cases
|
|
113
|
+
Setup = this.RenderSetup canonicalData }
|
|
104
114
|
|
|
105
115
|
default this.ToTestMethod (index, canonicalDataCase) =
|
|
106
116
|
{ Skip = index > 0
|
|
@@ -115,27 +125,50 @@ type GeneratorExercise() =
|
|
|
115
125
|
{ Sut = this.RenderSut canonicalDataCase
|
|
116
126
|
Expected = this.RenderValueOrIdentifier (canonicalDataCase, "expected", canonicalDataCase.Expected) }
|
|
117
127
|
|
|
118
|
-
|
|
128
|
+
// Determine the templates to use when rendering
|
|
129
|
+
|
|
130
|
+
default this.TestFileTemplate =
|
|
131
|
+
match this.TestFileFormat with
|
|
132
|
+
| Module -> "TestModule"
|
|
133
|
+
| Class -> "TestClass"
|
|
134
|
+
|
|
135
|
+
default this.TestMethodTemplate (_, _) =
|
|
136
|
+
match this.TestFileFormat with
|
|
137
|
+
| Module -> "TestFunction"
|
|
138
|
+
| Class -> "TestMember"
|
|
139
|
+
|
|
140
|
+
default this.TestMethodBodyTemplate _ =
|
|
141
|
+
match this.TestFileFormat with
|
|
142
|
+
| Module -> "TestFunctionBody"
|
|
143
|
+
| Class -> "TestMemberBody"
|
|
144
|
+
|
|
145
|
+
default this.TestMethodBodyAssertTemplate canonicalDataCase =
|
|
119
146
|
match canonicalDataCase.Expected with
|
|
120
147
|
| :? JArray as jArray when jArray.Count = 0 && not (List.contains "expected" (this.PropertiesWithIdentifier canonicalDataCase)) -> "AssertEmpty"
|
|
121
148
|
| _ -> "AssertEqual"
|
|
122
149
|
|
|
150
|
+
default __.TestFileFormat = TestFileFormat.Module
|
|
151
|
+
|
|
123
152
|
// Rendering of canonical data
|
|
124
153
|
|
|
125
154
|
default this.Render canonicalData =
|
|
126
155
|
canonicalData
|
|
127
|
-
|> this.
|
|
128
|
-
|> renderPartialTemplate
|
|
156
|
+
|> this.ToTestFile
|
|
157
|
+
|> renderPartialTemplate this.TestFileTemplate
|
|
158
|
+
|
|
159
|
+
default this.RenderTestMethod (index, canonicalDataCase) =
|
|
160
|
+
let template = this.TestMethodTemplate (index, canonicalDataCase)
|
|
129
161
|
|
|
130
|
-
default this.RenderTestMethod index canonicalDataCase =
|
|
131
162
|
(index, canonicalDataCase)
|
|
132
163
|
|> this.ToTestMethod
|
|
133
|
-
|> renderPartialTemplate
|
|
164
|
+
|> renderPartialTemplate template
|
|
134
165
|
|
|
135
166
|
default this.RenderTestMethodBody canonicalDataCase =
|
|
167
|
+
let template = this.TestMethodBodyTemplate canonicalDataCase
|
|
168
|
+
|
|
136
169
|
canonicalDataCase
|
|
137
170
|
|> this.ToTestMethodBody
|
|
138
|
-
|> renderPartialTemplate
|
|
171
|
+
|> renderPartialTemplate template
|
|
139
172
|
|
|
140
173
|
default this.RenderTestMethodName canonicalDataCase =
|
|
141
174
|
match this.UseFullMethodName canonicalDataCase with
|
|
@@ -144,7 +177,9 @@ type GeneratorExercise() =
|
|
|
144
177
|
| true ->
|
|
145
178
|
canonicalDataCase.DescriptionPath
|
|
146
179
|
|> String.concat " - "
|
|
147
|
-
|> String.upperCaseFirst
|
|
180
|
+
|> String.upperCaseFirst
|
|
181
|
+
|
|
182
|
+
default __.RenderSetup _ = ""
|
|
148
183
|
|
|
149
184
|
// Generic value/identifier rendering methods
|
|
150
185
|
|
|
@@ -195,7 +230,7 @@ type GeneratorExercise() =
|
|
|
195
230
|
|> List.choose renderArrangeProperty
|
|
196
231
|
|
|
197
232
|
default this.RenderAssert canonicalDataCase =
|
|
198
|
-
let template = this.
|
|
233
|
+
let template = this.TestMethodBodyAssertTemplate canonicalDataCase
|
|
199
234
|
|
|
200
235
|
canonicalDataCase
|
|
201
236
|
|> this.ToTestMethodBodyAssert
|
|
@@ -121,7 +121,7 @@ let rec formatValue (value: obj) =
|
|
|
121
121
|
| _ ->
|
|
122
122
|
string value
|
|
123
123
|
|
|
124
|
-
let formatCollection formatString collection =
|
|
124
|
+
let private formatCollection formatString collection =
|
|
125
125
|
collection
|
|
126
126
|
|> String.concat "; "
|
|
127
127
|
|> sprintf formatString
|
|
@@ -132,7 +132,7 @@ let formatArray sequence = formatCollection "[|%s|]" sequence
|
|
|
132
132
|
|
|
133
133
|
let formatSequence sequence = formatCollection "seq {%s}" sequence
|
|
134
134
|
|
|
135
|
-
let formatMultiLineCollection (openPrefix, closePostfix) collection =
|
|
135
|
+
let private formatMultiLineCollection (openPrefix, closePostfix) collection indentation =
|
|
136
136
|
match Seq.length collection with
|
|
137
137
|
| 0 ->
|
|
138
138
|
sprintf "%s%s" openPrefix closePostfix
|
|
@@ -153,15 +153,22 @@ let formatMultiLineCollection (openPrefix, closePostfix) collection =
|
|
|
153
153
|
collection
|
|
154
154
|
|> Seq.mapi formatLine
|
|
155
155
|
|> Seq.toList
|
|
156
|
-
|> List.map (indent
|
|
156
|
+
|> List.map (indent indentation)
|
|
157
157
|
|> String.concat "\n"
|
|
158
158
|
|> sprintf "\n%s"
|
|
159
159
|
|
|
160
|
-
let formatMultiLineList sequence = formatMultiLineCollection ("[", "]") sequence
|
|
161
160
|
|
|
162
|
-
let
|
|
161
|
+
let formatMultiLineListWithIndentation indentation sequence = formatMultiLineCollection ("[", "]") sequence indentation
|
|
163
162
|
|
|
164
|
-
let
|
|
163
|
+
let formatMultiLineArrayWithIndentation indentation sequence = formatMultiLineCollection ("[|", "|]") sequence indentation
|
|
164
|
+
|
|
165
|
+
let formatMultiLineSequenceWithIndentation indentation sequence = formatMultiLineCollection ("seq {", "}") sequence indentation
|
|
166
|
+
|
|
167
|
+
let formatMultiLineList sequence = formatMultiLineListWithIndentation 2 sequence
|
|
168
|
+
|
|
169
|
+
let formatMultiLineArray sequence = formatMultiLineArrayWithIndentation 2 sequence
|
|
170
|
+
|
|
171
|
+
let formatMultiLineSequence sequence = formatMultiLineSequenceWithIndentation 2 sequence
|
|
165
172
|
|
|
166
173
|
let formatMultiLineString strings =
|
|
167
174
|
let length = Seq.length strings
|
|
@@ -4,6 +4,7 @@ open System
|
|
|
4
4
|
open System.Globalization
|
|
5
5
|
open Newtonsoft.Json.Linq
|
|
6
6
|
open Formatting
|
|
7
|
+
open Rendering
|
|
7
8
|
open Exercise
|
|
8
9
|
|
|
9
10
|
type Acronym() =
|
|
@@ -61,7 +62,7 @@ type Allergies() =
|
|
|
61
62
|
type Alphametics() =
|
|
62
63
|
inherit GeneratorExercise()
|
|
63
64
|
|
|
64
|
-
member __.
|
|
65
|
+
member __.FormatMap<'TKey, 'TValue> (value: obj) =
|
|
65
66
|
if isNull value then
|
|
66
67
|
"None"
|
|
67
68
|
else
|
|
@@ -77,7 +78,7 @@ type Alphametics() =
|
|
|
77
78
|
else
|
|
78
79
|
sprintf "%s |> Map.ofList |> Some" formattedList
|
|
79
80
|
|
|
80
|
-
override this.RenderExpected (_, _, value) = this.
|
|
81
|
+
override this.RenderExpected (_, _, value) = this.FormatMap<char, int> value
|
|
81
82
|
|
|
82
83
|
override this.PropertiesWithIdentifier canonicalDataCase = this.Properties canonicalDataCase
|
|
83
84
|
|
|
@@ -164,7 +165,7 @@ type Clock() =
|
|
|
164
165
|
let minute = clock.["minute"].ToObject<string>()
|
|
165
166
|
sprintf "let %s = create %s %s" clockId hour minute
|
|
166
167
|
|
|
167
|
-
member private this.
|
|
168
|
+
member private this.RenderPropertyValue canonicalDataCase property =
|
|
168
169
|
this.RenderSutParameter (canonicalDataCase, property, Map.find property canonicalDataCase.Properties)
|
|
169
170
|
|
|
170
171
|
override __.PropertiesWithIdentifier _ = ["clock1"; "clock2"]
|
|
@@ -177,8 +178,8 @@ type Clock() =
|
|
|
177
178
|
override this.RenderArrange canonicalDataCase =
|
|
178
179
|
match canonicalDataCase.Property with
|
|
179
180
|
| "create" | "add" ->
|
|
180
|
-
let hour = this.
|
|
181
|
-
let minute = this.
|
|
181
|
+
let hour = this.RenderPropertyValue canonicalDataCase "hour"
|
|
182
|
+
let minute = this.RenderPropertyValue canonicalDataCase "minute"
|
|
182
183
|
[sprintf "let clock = create %s %s" hour minute]
|
|
183
184
|
| _ ->
|
|
184
185
|
base.RenderArrange canonicalDataCase
|
|
@@ -188,7 +189,7 @@ type Clock() =
|
|
|
188
189
|
| "create" ->
|
|
189
190
|
sprintf "display clock"
|
|
190
191
|
| "add" ->
|
|
191
|
-
this.
|
|
192
|
+
this.RenderPropertyValue canonicalDataCase "add"
|
|
192
193
|
|> sprintf "add %s clock |> display"
|
|
193
194
|
| "equal" ->
|
|
194
195
|
"clock1 = clock2"
|
|
@@ -250,7 +251,7 @@ type Dominoes() =
|
|
|
250
251
|
type Etl() =
|
|
251
252
|
inherit GeneratorExercise()
|
|
252
253
|
|
|
253
|
-
member __.
|
|
254
|
+
member __.FormatMap<'TKey, 'TValue> (value: obj) =
|
|
254
255
|
let input = value :?> JObject
|
|
255
256
|
let dict = input.ToObject<Collections.Generic.Dictionary<'TKey, 'TValue>>();
|
|
256
257
|
let formattedList =
|
|
@@ -263,9 +264,9 @@ type Etl() =
|
|
|
263
264
|
else
|
|
264
265
|
sprintf "%s |> Map.ofList" formattedList
|
|
265
266
|
|
|
266
|
-
override this.RenderInput (_, _, value) = this.
|
|
267
|
+
override this.RenderInput (_, _, value) = this.FormatMap<int, List<char>> value
|
|
267
268
|
|
|
268
|
-
override this.RenderExpected (_, _, value) = this.
|
|
269
|
+
override this.RenderExpected (_, _, value) = this.FormatMap<char, int> value
|
|
269
270
|
|
|
270
271
|
override this.PropertiesWithIdentifier canonicalDataCase = this.Properties canonicalDataCase
|
|
271
272
|
|
|
@@ -323,6 +324,35 @@ type Grains() =
|
|
|
323
324
|
| "-1" -> "Error \"Invalid input\""
|
|
324
325
|
| x -> sprintf "Ok %sUL" x
|
|
325
326
|
|
|
327
|
+
type Grep() =
|
|
328
|
+
inherit GeneratorExercise()
|
|
329
|
+
|
|
330
|
+
override this.PropertiesWithIdentifier canonicalDataCase = this.Properties canonicalDataCase
|
|
331
|
+
|
|
332
|
+
override __.RenderExpected (_, _, value) =
|
|
333
|
+
(value :?> JArray)
|
|
334
|
+
|> normalizeJArray
|
|
335
|
+
|> Seq.map formatValue
|
|
336
|
+
|> formatMultiLineListWithIndentation 3
|
|
337
|
+
|
|
338
|
+
override __.RenderSetup _ = renderPartialTemplate "Generators/GrepSetup" Map.empty<string, obj>
|
|
339
|
+
|
|
340
|
+
override __.RenderArrange canonicalDataCase =
|
|
341
|
+
base.RenderArrange canonicalDataCase @ [""; "createFiles() |> ignore"]
|
|
342
|
+
|
|
343
|
+
override __.IdentifierTypeAnnotation (canonicalDataCase, key, value) =
|
|
344
|
+
match key with
|
|
345
|
+
| "expected" ->
|
|
346
|
+
match value :?> JArray |> Seq.isEmpty with
|
|
347
|
+
| true -> Some "string list"
|
|
348
|
+
| false -> None
|
|
349
|
+
| _ ->
|
|
350
|
+
base.IdentifierTypeAnnotation(canonicalDataCase, key, value)
|
|
351
|
+
|
|
352
|
+
override __.AdditionalNamespaces = [typeof<System.IO.File>.Namespace]
|
|
353
|
+
|
|
354
|
+
override __.TestFileFormat = TestFileFormat.Class
|
|
355
|
+
|
|
326
356
|
type Hamming() =
|
|
327
357
|
inherit GeneratorExercise()
|
|
328
358
|
|
|
@@ -417,7 +447,7 @@ type Meetup() =
|
|
|
417
447
|
override __.PropertiesUsedAsSutParameter _ =
|
|
418
448
|
["year"; "month"; "dayofweek"; "week"]
|
|
419
449
|
|
|
420
|
-
override
|
|
450
|
+
override __.AdditionalNamespaces = [typeof<DateTime>.Namespace]
|
|
421
451
|
|
|
422
452
|
type Minesweeper() =
|
|
423
453
|
inherit GeneratorExercise()
|
|
@@ -447,7 +477,7 @@ type NthPrime() =
|
|
|
447
477
|
type NucleotideCount() =
|
|
448
478
|
inherit GeneratorExercise()
|
|
449
479
|
|
|
450
|
-
member __.
|
|
480
|
+
member __.FormatMap<'TKey, 'TValue> (value: obj) =
|
|
451
481
|
match Option.ofNonError value with
|
|
452
482
|
| None ->
|
|
453
483
|
"None"
|
|
@@ -464,7 +494,7 @@ type NucleotideCount() =
|
|
|
464
494
|
else
|
|
465
495
|
sprintf "%s |> Map.ofList |> Some" formattedList
|
|
466
496
|
|
|
467
|
-
override this.RenderExpected (_, _, value) = this.
|
|
497
|
+
override this.RenderExpected (_, _, value) = this.FormatMap<char, int> value
|
|
468
498
|
|
|
469
499
|
override this.PropertiesWithIdentifier canonicalDataCase = this.Properties canonicalDataCase
|
|
470
500
|
|
|
@@ -544,7 +574,7 @@ type PascalsTriangle() =
|
|
|
544
574
|
| false -> None
|
|
545
575
|
| _ -> base.IdentifierTypeAnnotation (canonicalDataCase, key, value)
|
|
546
576
|
|
|
547
|
-
override __.
|
|
577
|
+
override __.TestMethodBodyAssertTemplate _ = "AssertEqual"
|
|
548
578
|
|
|
549
579
|
type PerfectNumbers() =
|
|
550
580
|
inherit GeneratorExercise()
|
|
@@ -770,7 +800,7 @@ type RunLengthEncoding() =
|
|
|
770
800
|
| _ ->
|
|
771
801
|
base.RenderSut canonicalDataCase
|
|
772
802
|
|
|
773
|
-
override
|
|
803
|
+
override __.RenderTestMethodName canonicalDataCase =
|
|
774
804
|
match canonicalDataCase.Property with
|
|
775
805
|
| "consistency" ->
|
|
776
806
|
base.RenderTestMethodName canonicalDataCase
|
|
@@ -7,6 +7,7 @@ open FSharp.Reflection
|
|
|
7
7
|
open DotLiquid
|
|
8
8
|
open DotLiquid.FileSystems
|
|
9
9
|
open Formatting
|
|
10
|
+
open System.Collections
|
|
10
11
|
|
|
11
12
|
type OutputFilter() =
|
|
12
13
|
static member Format (input: string) = formatValue input
|
|
@@ -47,11 +48,17 @@ let rec private registerTypeTree templateDataType =
|
|
|
47
48
|
registrations.[templateDataType] <- true
|
|
48
49
|
for p in properties do registerTypeTree p.PropertyType
|
|
49
50
|
|
|
51
|
+
let private hashFromData (data: obj) =
|
|
52
|
+
match FSharpType.IsRecord (data.GetType()) with
|
|
53
|
+
| true -> Hash.FromAnonymousObject(data)
|
|
54
|
+
| false -> Hash.FromDictionary(data :?> IDictionary<string, obj>)
|
|
55
|
+
|
|
50
56
|
let renderInlineTemplate template data =
|
|
51
57
|
data.GetType() |> registerTypeTree
|
|
52
58
|
|
|
53
59
|
let parsedTemplate = Template.Parse template
|
|
54
|
-
|
|
60
|
+
let hash = hashFromData data
|
|
61
|
+
parsedTemplate.Render(hash)
|
|
55
62
|
|
|
56
63
|
let renderPartialTemplate templateName data =
|
|
57
64
|
let template = sprintf "{%% include \"%s\" %%}" templateName
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
let iliadFileName = "iliad.txt"
|
|
2
|
+
let iliadContents =
|
|
3
|
+
"""Achilles sing, O Goddess! Peleus' son;
|
|
4
|
+
His wrath pernicious, who ten thousand woes
|
|
5
|
+
Caused to Achaia's host, sent many a soul
|
|
6
|
+
Illustrious into Ades premature,
|
|
7
|
+
And Heroes gave (so stood the will of Jove)
|
|
8
|
+
To dogs and to all ravening fowls a prey,
|
|
9
|
+
When fierce dispute had separated once
|
|
10
|
+
The noble Chief Achilles from the son
|
|
11
|
+
Of Atreus, Agamemnon, King of men."""
|
|
12
|
+
|
|
13
|
+
let midsummerNightFileName = "midsummer-night.txt"
|
|
14
|
+
let midsummerNightContents =
|
|
15
|
+
"""I do entreat your grace to pardon me.
|
|
16
|
+
I know not by what power I am made bold,
|
|
17
|
+
Nor how it may concern my modesty,
|
|
18
|
+
In such a presence here to plead my thoughts;
|
|
19
|
+
But I beseech your grace that I may know
|
|
20
|
+
The worst that may befall me in this case,
|
|
21
|
+
If I refuse to wed Demetrius."""
|
|
22
|
+
|
|
23
|
+
let paradiseLostFileName = "paradise-lost.txt"
|
|
24
|
+
let paradiseLostContents =
|
|
25
|
+
"""Of Mans First Disobedience, and the Fruit
|
|
26
|
+
Of that Forbidden Tree, whose mortal tast
|
|
27
|
+
Brought Death into the World, and all our woe,
|
|
28
|
+
With loss of Eden, till one greater Man
|
|
29
|
+
Restore us, and regain the blissful Seat,
|
|
30
|
+
Sing Heav'nly Muse, that on the secret top
|
|
31
|
+
Of Oreb, or of Sinai, didst inspire
|
|
32
|
+
That Shepherd, who first taught the chosen Seed"""
|
|
33
|
+
|
|
34
|
+
let createFiles() =
|
|
35
|
+
File.WriteAllText(iliadFileName, iliadContents)
|
|
36
|
+
File.WriteAllText(midsummerNightFileName, midsummerNightContents)
|
|
37
|
+
File.WriteAllText(paradiseLostFileName, paradiseLostContents)
|
|
@@ -7,7 +7,13 @@ open {{ namespace }}
|
|
|
7
7
|
{%- endfor -%}
|
|
8
8
|
|
|
9
9
|
open {{ TestedModuleName }}
|
|
10
|
+
{%- if Setup != empty -%}
|
|
10
11
|
|
|
11
|
-
{
|
|
12
|
-
{
|
|
13
|
-
|
|
12
|
+
{{ Setup }}
|
|
13
|
+
{%- endif -%}
|
|
14
|
+
|
|
15
|
+
type {{ TestModuleName }}() =
|
|
16
|
+
|
|
17
|
+
{%- for method in Methods -%}
|
|
18
|
+
{{ method }}
|
|
19
|
+
{%- endfor -%}
|
|
File without changes
|
|
File without changes
|