-
-
Notifications
You must be signed in to change notification settings - Fork 655
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
grains: add generator #959
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
package main | ||
|
||
import ( | ||
"encoding/json" | ||
"log" | ||
"strings" | ||
"text/template" | ||
|
||
"../../../gen" | ||
) | ||
|
||
func main() { | ||
t, err := template.New("").Parse(tmpl) | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
var j js | ||
if err := gen.Gen("grains", &j, t); err != nil { | ||
log.Fatal(err) | ||
} | ||
} | ||
|
||
// The JSON structure we expect to be able to unmarshal into | ||
type js struct { | ||
Groups []testGroup `json:"Cases"` | ||
} | ||
|
||
type testGroup struct { | ||
Description string | ||
Cases []json.RawMessage `property:"RAW"` | ||
SquareCases []SquareCase `property:"square"` | ||
// Note: canonical-data.json has a element of "cases" | ||
// which includes a test for property 'total', but it is ignored here, | ||
// since "expected" is a single known value. | ||
} | ||
|
||
type SquareCase struct { | ||
Description string | ||
Input int | ||
Expected interface{} | ||
} | ||
|
||
func (c SquareCase) Valid() bool { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Perhaps There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree, HasAnswer is more descriptive. |
||
valid, _ := determineExpected(c.Expected) | ||
return valid | ||
} | ||
|
||
func (c SquareCase) Answer() uint64 { | ||
_, answer := determineExpected(c.Expected) | ||
return answer | ||
} | ||
|
||
func (c SquareCase) EditedDescription() string { | ||
// Go doesn't raise exceptions, so replace the wording in .Description. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do you think this is worth bringing up in problem-specifications? Exception seems to be the narrower term here, while Error is the more general. If anything exception based languages should be rewriting these descriptions if necessary. I've always considered Exceptions to be a sub-term for Errors in generic conversation, but not the other way around. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes. I was actually surprised to see the exception wording in the canonical data file. I thought it was very tilted toward languages that use exceptions. Error is a better term to use there. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agreed here. |
||
return strings.Replace(c.Description, "raises an exception", "returns an error", 1) | ||
} | ||
|
||
// determineExpected examines an .Expected interface{} object and determines | ||
// whether a test case is valid(bool) and has an answer or expects an error. | ||
// returning valid and answer. | ||
func determineExpected(expected interface{}) (bool, uint64) { | ||
ans, ok := expected.(float64) | ||
if ok { | ||
if ans == float64(-1) { | ||
return false, 0 | ||
} | ||
return ok, uint64(ans) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For my own curiousity, why not return There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, agree. |
||
} | ||
return false, 0 | ||
} | ||
|
||
func (groups testGroup) GroupShortName() string { | ||
return strings.ToLower(strings.Fields(groups.Description)[0]) | ||
} | ||
|
||
var tmpl = `package grains | ||
|
||
{{.Header}} | ||
|
||
{{range .J.Groups}} | ||
{{- if .SquareCases }} | ||
// {{ .Description }} | ||
var squareTests = []struct { | ||
description string | ||
input int | ||
expectedVal uint64 | ||
expectError bool | ||
}{ | ||
{{- range .SquareCases}} | ||
{ | ||
description: "{{.EditedDescription}}", | ||
input: {{.Input}}, | ||
{{- if .Valid}} | ||
expectedVal: {{.Answer}}, | ||
{{- else}} | ||
expectError: true, | ||
{{- end}} | ||
}, | ||
{{- end }} | ||
} | ||
{{- end }} | ||
{{end}} | ||
` |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
package grains | ||
|
||
// Source: exercism/problem-specifications | ||
// Commit: d4554e6 grains: fix a typo in comments of canonical data | ||
// Problem Specifications Version: 1.0.0 | ||
|
||
// returns the number of grains on the square | ||
var squareTests = []struct { | ||
description string | ||
input int | ||
expectedVal uint64 | ||
expectError bool | ||
}{ | ||
{ | ||
description: "1", | ||
input: 1, | ||
expectedVal: 1, | ||
}, | ||
{ | ||
description: "2", | ||
input: 2, | ||
expectedVal: 2, | ||
}, | ||
{ | ||
description: "3", | ||
input: 3, | ||
expectedVal: 4, | ||
}, | ||
{ | ||
description: "4", | ||
input: 4, | ||
expectedVal: 8, | ||
}, | ||
{ | ||
description: "16", | ||
input: 16, | ||
expectedVal: 32768, | ||
}, | ||
{ | ||
description: "32", | ||
input: 32, | ||
expectedVal: 2147483648, | ||
}, | ||
{ | ||
description: "64", | ||
input: 64, | ||
expectedVal: 9223372036854775808, | ||
}, | ||
{ | ||
description: "square 0 returns an error", | ||
input: 0, | ||
expectError: true, | ||
}, | ||
{ | ||
description: "negative square returns an error", | ||
input: -1, | ||
expectError: true, | ||
}, | ||
{ | ||
description: "square greater than 64 returns an error", | ||
input: 65, | ||
expectError: true, | ||
}, | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Have you or @ferhatelmas encountered an other canonical-data files with a cases.cases structure like this one? It seems odd. Wonder if there may be a better way to represent the data in that file we could suggest upstream.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The are several which have nested cases.cases but only one property value; these are not a problem. Others also have differing property values, which make it a little harder to handle. Two exercises, custom-set and variable-length-quantity have generators that use a PropertyMatch technique. Four others use the RAW special handling with classifyByProperty (allergies, run-length-encoding, clock, and grains). A different structuring in canonical data could help to generate separate test case arrays for different property values. A change would require a retrofit for current generators however.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When I first saw, I was shocked but then checked json schema in problem-specification and it was valid. Thus, even if it's harder to handle, thought that was the decision and tried to live with.