Skip to content

Commit

Permalink
Support nested DSLs by eval.caller() (#3523)
Browse files Browse the repository at this point in the history
* Run as subtests

* Change test structure

* Add test cases for eval.TooManyArgError()

* Support nested DSLs by eval.caller()
  • Loading branch information
tchssk committed May 28, 2024
1 parent 7e7f491 commit b055a8f
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 27 deletions.
14 changes: 10 additions & 4 deletions eval/eval.go
Original file line number Diff line number Diff line change
Expand Up @@ -240,20 +240,26 @@ func finalizeSet(set ExpressionSet) {

// caller returns the name of calling function.
func caller() string {
for skip := 2; skip <= 4; skip++ {
var latest string
for skip := 2; skip <= 5; skip++ {
pc, _, _, ok := runtime.Caller(skip)
if !ok {
break
}
name := runtime.FuncForPC(pc).Name()
elems := strings.Split(name, ".")
caller := elems[len(elems)-1]
if !strings.HasPrefix(name, "goa.design/goa/v3/dsl.") {
break
}
caller := strings.Split(strings.TrimPrefix(name, "goa.design/goa/v3/dsl."), ".")[0]
for _, first := range caller {
if unicode.IsUpper(first) {
return caller
latest = caller
}
break
}
}
if latest != "" {
return latest
}
return "<unknown>"
}
62 changes: 39 additions & 23 deletions eval/eval_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,29 +10,45 @@ import (
)

func TestTooManyArgError(t *testing.T) {
cases := map[string]struct {
DSL func()
Error string
}{
"ArrayOf": {func() { ArrayOf(String, func() {}, func() {}) }, "too many arguments given to ArrayOf"},
"Attribute": {func() { Type("name", func() { Attribute("name", 1, 2, 3, 4) }) }, "too many arguments given to Attribute"},
"Example": {func() { Example(1, 2, 3) }, "too many arguments given to Example"},
"Files": {func() { Files("path", "filename", func() {}, func() {}) }, "too many arguments given to Files"},
"MapOf": {func() { MapOf(String, String, func() {}, func() {}) }, "too many arguments given to MapOf"},
"MapParams": {func() { MapParams(1, 2) }, "too many arguments given to MapParams"},
"Payload": {func() { Payload(String, 1, 2, 3) }, "too many arguments given to Payload"},
"Response": {func() { API("name", func() { HTTP(func() { Response(StatusOK, "name", 1, 2) }) }) }, "too many arguments given to Response"},
"Result": {func() { Result(String, 1, 2, 3) }, "too many arguments given to Result"},
"ResultType": {func() { ResultType("identifier", "name", func() {}, func() {}) }, "too many arguments given to ResultType"},
"Scope": {func() { BasicAuthSecurity("name", func() { Scope("name", "1", "2") }) }, "too many arguments given to Scope"},
"Server": {func() { Server("name", func() {}, func() {}) }, "too many arguments given to Server"},
"StreamingPayload": {func() { StreamingPayload(String, 1, 2, 3) }, "too many arguments given to StreamingPayload"},
"StreamingResult": {func() { StreamingResult(String, 1, 2, 3) }, "too many arguments given to StreamingResult"},
"Type": {func() { Type("name", 1, 2, 3) }, "too many arguments given to Type"},
dsls := map[string]func(){
"APIKey": func() { Type("name", func() { APIKey("scheme", "name", 1, 2, 3) }) },
"APIKeyField": func() { Type("name", func() { APIKeyField("tag", "scheme", "name", 1, 2, 3) }) },
"AccessToken": func() { Type("name", func() { AccessToken("name", 1, 2, 3) }) },
"AccessTokenField": func() { Type("name", func() { AccessTokenField("tag", "name", 1, 2, 3) }) },
"ArrayOf": func() { ArrayOf(String, func() {}, func() {}) },
"Attribute": func() { Type("name", func() { Attribute("name", 1, 2, 3, 4) }) },
"Cookie": func() { API("name", func() { HTTP(func() { Cookie("name", 1, 2, 3, 4) }) }) },
"Error": func() { API("name", func() { Error("name", 1, 2, 3, 4) }) },
"ErrorName": func() { Type("name", func() { ErrorName("name", 1, 2, 3) }) },
"Example": func() { Example(1, 2, 3) },
"Field": func() { Type("name", func() { Field("tag", "name", 1, 2, 3, 4) }) },
"Files": func() { Files("path", "filename", func() {}, func() {}) },
"Header": func() { API("name", func() { HTTP(func() { Header("name", 1, 2, 3, 4) }) }) },
"MapOf": func() { MapOf(String, String, func() {}, func() {}) },
"MapParams": func() { MapParams(1, 2) },
"Param": func() { API("name", func() { HTTP(func() { Param("name", 1, 2, 3, 4) }) }) },
"Password": func() { Type("name", func() { Password("name", 1, 2, 3) }) },
"PasswordField": func() { Type("name", func() { PasswordField("tag", "name", 1, 2, 3) }) },
"Payload": func() { Payload(String, 1, 2, 3) },
"Response": func() { API("name", func() { HTTP(func() { Response(StatusOK, "name", 1, 2) }) }) },
"Result": func() { Result(String, 1, 2, 3) },
"ResultType": func() { ResultType("identifier", "name", func() {}, func() {}) },
"Scope": func() { BasicAuthSecurity("name", func() { Scope("name", "1", "2") }) },
"Server": func() { Server("name", func() {}, func() {}) },
"StreamingPayload": func() { StreamingPayload(String, 1, 2, 3) },
"StreamingResult": func() { StreamingResult(String, 1, 2, 3) },
"Token": func() { Type("name", func() { Token("name", 1, 2, 3) }) },
"TokenField": func() { Type("name", func() { TokenField("tag", "name", 1, 2, 3) }) },
"Type": func() { Type("name", 1, 2, 3) },
"Username": func() { Type("name", func() { Username("name", 1, 2, 3) }) },
"UsernameField": func() { Type("name", func() { UsernameField("tag", "name", 1, 2, 3) }) },
"Variable": func() { API("a", func() { Server("s", func() { Host("h", func() { Variable("v", 1, 2, 3, 4) }) }) }) },
}
for _, tc := range cases {
err := expr.RunInvalidDSL(t, tc.DSL)
assert.Len(t, strings.Split(err.Error(), "\n"), 1)
assert.Contains(t, err.Error(), tc.Error)
for name, dsl := range dsls {
t.Run(name, func(t *testing.T) {
err := expr.RunInvalidDSL(t, dsl)
assert.Len(t, strings.Split(err.Error(), "\n"), 1)
assert.Contains(t, err.Error(), "too many arguments given to "+name)
})
}
}

0 comments on commit b055a8f

Please sign in to comment.