gen_test.go 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388
  1. package gogen
  2. import (
  3. goformat "go/format"
  4. "io/ioutil"
  5. "os"
  6. "path/filepath"
  7. "strings"
  8. "testing"
  9. "github.com/stretchr/testify/assert"
  10. "github.com/tal-tech/go-zero/tools/goctl/api/parser"
  11. )
  12. const testApiTemplate = `
  13. info(
  14. title: doc title
  15. desc: >
  16. doc description first part,
  17. doc description second part<
  18. version: 1.0
  19. )
  20. type Request struct {
  21. Name string ` + "`" + `path:"name,options=you|me"` + "`" + `
  22. }
  23. type Response struct {
  24. Message string ` + "`" + `json:"message"` + "`" + `
  25. }
  26. service A-api {
  27. @server(
  28. handler: GreetHandler
  29. )
  30. get /greet/from/:name(Request) returns (Response)
  31. @server(
  32. handler: NoResponseHandler
  33. )
  34. get /greet/get(Request) returns
  35. }
  36. `
  37. const testMultiServiceTemplate = `
  38. info(
  39. title: doc title
  40. desc: >
  41. doc description first part,
  42. doc description second part<
  43. version: 1.0
  44. )
  45. type Request struct {
  46. Name string ` + "`" + `path:"name,options=you|me"` + "`" + `
  47. }
  48. type Response struct {
  49. Message string ` + "`" + `json:"message"` + "`" + `
  50. }
  51. service A-api {
  52. @server(
  53. handler: GreetHandler
  54. )
  55. get /greet/from/:name(Request) returns (Response)
  56. }
  57. service A-api {
  58. @server(
  59. handler: NoResponseHandler
  60. )
  61. get /greet/get(Request) returns
  62. }
  63. `
  64. const apiNoInfo = `
  65. type Request struct {
  66. Name string ` + "`" + `path:"name,options=you|me"` + "`" + `
  67. }
  68. type Response struct {
  69. Message string ` + "`" + `json:"message"` + "`" + `
  70. }
  71. service A-api {
  72. @server(
  73. handler: GreetHandler
  74. )
  75. get /greet/from/:name(Request) returns (Response)
  76. }
  77. `
  78. const invalidApiFile = `
  79. type Request struct {
  80. Name string ` + "`" + `path:"name,options=you|me"` + "`" + `
  81. }
  82. type Response struct {
  83. Message string ` + "`" + `json:"message"` + "`" + `
  84. }
  85. service A-api
  86. @server(
  87. handler: GreetHandler
  88. )
  89. get /greet/from/:name(Request) returns (Response)
  90. }
  91. `
  92. const anonymousAnnotation = `
  93. type Request struct {
  94. Name string ` + "`" + `path:"name,options=you|me"` + "`" + `
  95. }
  96. type Response struct {
  97. Message string ` + "`" + `json:"message"` + "`" + `
  98. }
  99. service A-api {
  100. @handler GreetHandler
  101. get /greet/from/:name(Request) returns (Response)
  102. }
  103. `
  104. const apiHasMiddleware = `
  105. type Request struct {
  106. Name string ` + "`" + `path:"name,options=you|me"` + "`" + `
  107. }
  108. type Response struct {
  109. Message string ` + "`" + `json:"message"` + "`" + `
  110. }
  111. @server(
  112. middleware: TokenValidate
  113. )
  114. service A-api {
  115. @handler GreetHandler
  116. get /greet/from/:name(Request) returns (Response)
  117. }
  118. `
  119. const apiJwt = `
  120. type Request struct {
  121. Name string ` + "`" + `path:"name,options=you|me"` + "`" + `
  122. }
  123. type Response struct {
  124. Message string ` + "`" + `json:"message"` + "`" + `
  125. }
  126. @server(
  127. jwt: Auth
  128. )
  129. service A-api {
  130. @handler GreetHandler
  131. get /greet/from/:name(Request) returns (Response)
  132. }
  133. `
  134. const apiJwtWithMiddleware = `
  135. type Request struct {
  136. Name string ` + "`" + `path:"name,options=you|me"` + "`" + `
  137. }
  138. type Response struct {
  139. Message string ` + "`" + `json:"message"` + "`" + `
  140. }
  141. @server(
  142. jwt: Auth
  143. middleware: TokenValidate
  144. )
  145. service A-api {
  146. @handler GreetHandler
  147. get /greet/from/:name(Request) returns (Response)
  148. }
  149. `
  150. const apiHasNoRequest = `
  151. service A-api {
  152. @handler GreetHandler
  153. post /greet/ping ()
  154. }
  155. `
  156. const apiRouteTest = `
  157. type Request struct {
  158. Name string ` + "`" + `path:"name,options=you|me"` + "`" + `
  159. }
  160. type Response struct {
  161. Message string ` + "`" + `json:"message"` + "`" + `
  162. }
  163. service A-api {
  164. @handler NormalHandler
  165. get /greet/from/:name(Request) returns (Response)
  166. @handler NoResponseHandler
  167. get /greet/from/:sex(Request)
  168. @handler NoRequestHandler
  169. get /greet/from/request returns (Response)
  170. @handler NoRequestNoResponseHandler
  171. get /greet/from
  172. }
  173. `
  174. func TestParser(t *testing.T) {
  175. filename := "greet.api"
  176. err := ioutil.WriteFile(filename, []byte(testApiTemplate), os.ModePerm)
  177. assert.Nil(t, err)
  178. defer os.Remove(filename)
  179. parser, err := parser.NewParser(filename)
  180. assert.Nil(t, err)
  181. api, err := parser.Parse()
  182. assert.Nil(t, err)
  183. assert.Equal(t, len(api.Types), 2)
  184. assert.Equal(t, len(api.Service.Routes), 2)
  185. assert.Equal(t, api.Service.Routes[0].Path, "/greet/from/:name")
  186. assert.Equal(t, api.Service.Routes[1].Path, "/greet/get")
  187. assert.Equal(t, api.Service.Routes[1].RequestType.Name, "Request")
  188. assert.Equal(t, api.Service.Routes[1].ResponseType.Name, "")
  189. validate(t, filename)
  190. }
  191. func TestMultiService(t *testing.T) {
  192. filename := "greet.api"
  193. err := ioutil.WriteFile(filename, []byte(testMultiServiceTemplate), os.ModePerm)
  194. assert.Nil(t, err)
  195. defer os.Remove(filename)
  196. parser, err := parser.NewParser(filename)
  197. assert.Nil(t, err)
  198. api, err := parser.Parse()
  199. assert.Nil(t, err)
  200. assert.Equal(t, len(api.Service.Routes), 2)
  201. assert.Equal(t, len(api.Service.Groups), 2)
  202. validate(t, filename)
  203. }
  204. func TestApiNoInfo(t *testing.T) {
  205. filename := "greet.api"
  206. err := ioutil.WriteFile(filename, []byte(apiNoInfo), os.ModePerm)
  207. assert.Nil(t, err)
  208. defer os.Remove(filename)
  209. parser, err := parser.NewParser(filename)
  210. assert.Nil(t, err)
  211. _, err = parser.Parse()
  212. assert.Nil(t, err)
  213. validate(t, filename)
  214. }
  215. func TestInvalidApiFile(t *testing.T) {
  216. filename := "greet.api"
  217. err := ioutil.WriteFile(filename, []byte(invalidApiFile), os.ModePerm)
  218. assert.Nil(t, err)
  219. defer os.Remove(filename)
  220. parser, err := parser.NewParser(filename)
  221. assert.Nil(t, err)
  222. _, err = parser.Parse()
  223. assert.NotNil(t, err)
  224. }
  225. func TestAnonymousAnnotation(t *testing.T) {
  226. filename := "greet.api"
  227. err := ioutil.WriteFile(filename, []byte(anonymousAnnotation), os.ModePerm)
  228. assert.Nil(t, err)
  229. defer os.Remove(filename)
  230. parser, err := parser.NewParser(filename)
  231. assert.Nil(t, err)
  232. api, err := parser.Parse()
  233. assert.Nil(t, err)
  234. assert.Equal(t, len(api.Service.Routes), 1)
  235. assert.Equal(t, api.Service.Routes[0].Annotations[0].Value, "GreetHandler")
  236. validate(t, filename)
  237. }
  238. func TestApiHasMiddleware(t *testing.T) {
  239. filename := "greet.api"
  240. err := ioutil.WriteFile(filename, []byte(apiHasMiddleware), os.ModePerm)
  241. assert.Nil(t, err)
  242. defer os.Remove(filename)
  243. parser, err := parser.NewParser(filename)
  244. assert.Nil(t, err)
  245. _, err = parser.Parse()
  246. assert.Nil(t, err)
  247. validate(t, filename)
  248. }
  249. func TestApiHasJwt(t *testing.T) {
  250. filename := "jwt.api"
  251. err := ioutil.WriteFile(filename, []byte(apiJwt), os.ModePerm)
  252. assert.Nil(t, err)
  253. defer os.Remove(filename)
  254. parser, err := parser.NewParser(filename)
  255. assert.Nil(t, err)
  256. _, err = parser.Parse()
  257. assert.Nil(t, err)
  258. validate(t, filename)
  259. }
  260. func TestApiHasJwtAndMiddleware(t *testing.T) {
  261. filename := "jwt.api"
  262. err := ioutil.WriteFile(filename, []byte(apiJwtWithMiddleware), os.ModePerm)
  263. assert.Nil(t, err)
  264. defer os.Remove(filename)
  265. parser, err := parser.NewParser(filename)
  266. assert.Nil(t, err)
  267. _, err = parser.Parse()
  268. assert.Nil(t, err)
  269. validate(t, filename)
  270. }
  271. func TestApiHasNoRequestBody(t *testing.T) {
  272. filename := "greet.api"
  273. err := ioutil.WriteFile(filename, []byte(apiHasNoRequest), os.ModePerm)
  274. assert.Nil(t, err)
  275. defer os.Remove(filename)
  276. parser, err := parser.NewParser(filename)
  277. assert.Nil(t, err)
  278. _, err = parser.Parse()
  279. assert.Nil(t, err)
  280. validate(t, filename)
  281. }
  282. func TestApiRoutes(t *testing.T) {
  283. filename := "greet.api"
  284. err := ioutil.WriteFile(filename, []byte(apiRouteTest), os.ModePerm)
  285. assert.Nil(t, err)
  286. defer os.Remove(filename)
  287. parser, err := parser.NewParser(filename)
  288. assert.Nil(t, err)
  289. _, err = parser.Parse()
  290. assert.Nil(t, err)
  291. validate(t, filename)
  292. }
  293. func validate(t *testing.T, api string) {
  294. dir := "_go"
  295. err := DoGenProject(api, dir, true)
  296. defer os.RemoveAll(dir)
  297. assert.Nil(t, err)
  298. filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
  299. if strings.HasSuffix(path, ".go") {
  300. code, err := ioutil.ReadFile(path)
  301. assert.Nil(t, err)
  302. assert.Nil(t, validateCode(string(code)))
  303. }
  304. return nil
  305. })
  306. }
  307. func validateCode(code string) error {
  308. _, err := goformat.Source([]byte(code))
  309. return err
  310. }