github.com/machinebox/remoto@v0.1.2-0.20191024144331-eff21a7d321f/generator/parser_test.go (about) 1 package generator 2 3 import ( 4 "bytes" 5 "io/ioutil" 6 "os" 7 "strings" 8 "testing" 9 10 "github.com/matryer/is" 11 ) 12 13 func TestParser(t *testing.T) { 14 is := is.New(t) 15 16 def, err := ParseDir("testdata/rpc/example") 17 is.NoErr(err) 18 19 is.Equal(len(def.Services), 2) 20 is.Equal(def.PackageName, "greeter") 21 is.Equal(def.PackageComment, "Package greeter is a sweet API that greets people.") 22 is.Equal(def.Services[0].Name, "GreetFormatter") 23 is.Equal(def.Services[0].Comment, "GreetFormatter provides formattable greeting services.") 24 25 greetFormatRequest := def.Structure("GreetFormatRequest") 26 is.True(greetFormatRequest != nil) 27 is.Equal(greetFormatRequest.Name, "GreetFormatRequest") 28 is.Equal(greetFormatRequest.Fields[1].Name, "Names") 29 is.Equal(greetFormatRequest.Fields[1].Comment, "Names is one or more names of people to greet.") 30 is.Equal(greetFormatRequest.Fields[1].Type.Name, "string") 31 is.Equal(greetFormatRequest.Fields[1].Type.IsMultiple, true) 32 33 is.Equal(def.Services[1].Name, "Greeter") 34 is.Equal(def.Services[1].Comment, "Greeter provides greeting services.") 35 36 is.Equal(def.Services[1].Methods[0].Name, "Greet") 37 is.Equal(def.Services[1].Methods[0].Comment, "Greet generates a greeting.") 38 39 greetRequest := def.Structure("GreetRequest") 40 is.Equal(greetRequest.Name, "GreetRequest") 41 is.Equal(greetRequest.Comment, "GreetRequest is the request for Greeter.GreetRequest.") 42 is.Equal(greetRequest.Fields[0].Name, "Name") 43 is.Equal(greetRequest.Fields[0].Comment, "Name is the name of the person to greet.") 44 45 is.Equal(def.Services[1].Structures[1].Name, "GreetResponse") 46 is.Equal(def.Services[1].Structures[1].Comment, "GreetResponse is the response for Greeter.GreetRequest.") 47 48 greetingFormat := def.Structure("GreetingFormat") 49 is.Equal(greetingFormat.Comment, "GreetingFormat describes the format of a greeting.") 50 is.Equal(greetingFormat.Fields[0].Name, "Format") 51 is.Equal(greetingFormat.Fields[0].Comment, "Format is a Go-style format string describing the greeting.\n%s will be replaced with the name of the person.") 52 is.Equal(greetingFormat.Fields[0].Type.Name, "string") 53 is.Equal(greetingFormat.Fields[1].Name, "AllCaps") 54 is.Equal(greetingFormat.Fields[1].Comment, "AllCaps is whether to convert the greeting to all caps.") 55 is.Equal(greetingFormat.Fields[1].Type.Name, "bool") 56 57 out := def.String() 58 is.Equal(out, `// Package greeter is a sweet API that greets people. 59 package greeter 60 61 // GreetFormatter provides formattable greeting services. 62 type GreetFormatter interface { 63 // Greet generates a greeting. 64 Greet(GreetFormatRequest) GreetResponse 65 } 66 67 // GreetingFormat describes the format of a greeting. 68 type GreetingFormat struct { 69 // Format is a Go-style format string describing the greeting. 70 // %s will be replaced with the name of the person. 71 Format string 72 // AllCaps is whether to convert the greeting to all caps. 73 AllCaps bool 74 } 75 76 // GreetFormatRequest is the request for Greeter.GreetRequest. 77 type GreetFormatRequest struct { 78 // Format is the GreetingFormat describing the format 79 // of the greetings. 80 Format GreetingFormat 81 // Names is one or more names of people to greet. 82 Names []string 83 } 84 85 // GreetResponse is the response for Greeter.GreetRequest. 86 type GreetResponse struct { 87 // Greeting is the personalized greeting. 88 Greeting string 89 // Error is an error message if one occurred. 90 Error string 91 } 92 93 // Greeter provides greeting services. 94 type Greeter interface { 95 // Greet generates a greeting. 96 Greet(GreetRequest) GreetResponse 97 } 98 99 // GreetRequest is the request for Greeter.GreetRequest. 100 type GreetRequest struct { 101 // Name is the name of the person to greet. 102 Name string 103 } 104 105 // GreetResponse is the response for Greeter.GreetRequest. 106 type GreetResponse struct { 107 // Greeting is the personalized greeting. 108 Greeting string 109 // Error is an error message if one occurred. 110 Error string 111 } 112 113 `) 114 } 115 116 func TestParseReader(t *testing.T) { 117 is := is.New(t) 118 119 src := strings.NewReader(exampleRemotoDefinition) 120 def, err := Parse(src) 121 is.NoErr(err) 122 123 is.Equal(len(def.Services), 2) 124 is.Equal(def.PackageName, "greeter") 125 is.Equal(def.PackageComment, "Package greeter is a sweet API that greets people.") 126 is.Equal(def.Services[0].Name, "GreetFormatter") 127 is.Equal(def.Services[0].Comment, "GreetFormatter provides formattable greeting services.") 128 129 greetFormatRequest := def.Structure("GreetFormatRequest") 130 is.Equal(greetFormatRequest.Name, "GreetFormatRequest") 131 is.Equal(greetFormatRequest.Fields[1].Name, "Names") 132 is.Equal(greetFormatRequest.Fields[1].Comment, "Names is one or more names of people to greet.") 133 is.Equal(greetFormatRequest.Fields[1].Type.Name, "string") 134 is.Equal(greetFormatRequest.Fields[1].Type.IsMultiple, true) 135 136 is.Equal(def.Services[1].Name, "Greeter") 137 is.Equal(def.Services[1].Comment, "Greeter provides greeting services.") 138 139 is.Equal(def.Services[1].Methods[0].Name, "Greet") 140 is.Equal(def.Services[1].Methods[0].Comment, "Greet generates a greeting.") 141 142 greetRequest := def.Structure("GreetRequest") 143 is.Equal(greetRequest.Name, "GreetRequest") 144 is.Equal(greetRequest.Comment, "GreetRequest is the request for Greeter.GreetRequest.") 145 is.Equal(greetRequest.Fields[0].Name, "Name") 146 is.Equal(greetRequest.Fields[0].Comment, "Name is the name of the person to greet.") 147 148 is.Equal(def.Services[1].Structures[1].Name, "GreetResponse") 149 is.Equal(def.Services[1].Structures[1].Comment, "GreetResponse is the response for Greeter.GreetRequest.") 150 151 greetingFormat := def.Structure("GreetingFormat") 152 is.Equal(greetingFormat.Comment, "GreetingFormat describes the format of a greeting.") 153 is.Equal(greetingFormat.Fields[0].Name, "Format") 154 is.Equal(greetingFormat.Fields[0].Comment, "Format is a Go-style format string describing the greeting.\n%s will be replaced with the name of the person.") 155 is.Equal(greetingFormat.Fields[0].Type.Name, "string") 156 is.Equal(greetingFormat.Fields[1].Name, "AllCaps") 157 is.Equal(greetingFormat.Fields[1].Comment, "AllCaps is whether to convert the greeting to all caps.") 158 is.Equal(greetingFormat.Fields[1].Type.Name, "bool") 159 160 out := def.String() 161 is.Equal(out, `// Package greeter is a sweet API that greets people. 162 package greeter 163 164 // GreetFormatter provides formattable greeting services. 165 type GreetFormatter interface { 166 // Greet generates a greeting. 167 Greet(GreetFormatRequest) GreetResponse 168 } 169 170 // GreetingFormat describes the format of a greeting. 171 type GreetingFormat struct { 172 // Format is a Go-style format string describing the greeting. 173 // %s will be replaced with the name of the person. 174 Format string 175 // AllCaps is whether to convert the greeting to all caps. 176 AllCaps bool 177 } 178 179 // GreetFormatRequest is the request for Greeter.GreetRequest. 180 type GreetFormatRequest struct { 181 // Format is the GreetingFormat describing the format 182 // of the greetings. 183 Format GreetingFormat 184 // Names is one or more names of people to greet. 185 Names []string 186 } 187 188 // GreetResponse is the response for Greeter.GreetRequest. 189 type GreetResponse struct { 190 // Greeting is the personalized greeting. 191 Greeting string 192 // Error is an error message if one occurred. 193 Error string 194 } 195 196 // Greeter provides greeting services. 197 type Greeter interface { 198 // Greet generates a greeting. 199 Greet(GreetRequest) GreetResponse 200 } 201 202 // GreetRequest is the request for Greeter.GreetRequest. 203 type GreetRequest struct { 204 // Name is the name of the person to greet. 205 Name string 206 } 207 208 // GreetResponse is the response for Greeter.GreetRequest. 209 type GreetResponse struct { 210 // Greeting is the personalized greeting. 211 Greeting string 212 // Error is an error message if one occurred. 213 Error string 214 } 215 216 `) 217 } 218 219 func TestErrors(t *testing.T) { 220 is := is.New(t) 221 tests := map[string]string{ 222 "testdata/rpc/errors/too-many-args": "greeter.remoto.go:4:2: service methods must have signature (*Request) *Response", 223 "testdata/rpc/errors/no-variadic": "greeter.remoto.go:6:2: service methods must have signature (*Request) *Response", 224 "testdata/rpc/errors/bad-first-arg": "greeter.remoto.go:4:2: service methods must have signature (*Request) *Response", 225 "testdata/rpc/errors/too-few-return-args": "greeter.remoto.go:4:2: service methods must have signature (*Request) *Response", 226 "testdata/rpc/errors/bad-return-args": "greeter.remoto.go:4:22: response object must be a named struct", 227 "testdata/rpc/errors/pointer-request": "greeter.remoto.go:4:8: request object must be a named struct (not a pointer - remove the *)", 228 "testdata/rpc/errors/pointer-response": "greeter.remoto.go:4:22: response object must be a named struct (not a pointer - remove the *)", 229 "testdata/rpc/errors/bad-type": "greeter.remoto.go:8:2: type int32 not supported: use int", 230 "testdata/rpc/errors/unexported-fields": "greeter.remoto.go:11:2: field name: must be exported", 231 "testdata/rpc/errors/unexported-methods": "greeter.remoto.go:6:2: method greet: must be exported", 232 "testdata/rpc/errors/same-request-response-types": "greeter.remoto.go:7:2: service methods must use different types for request and response objects", 233 "testdata/rpc/errors/other-imports": "import not allowed: context", 234 } 235 pwd, err := os.Getwd() 236 is.NoErr(err) 237 for path, expectedErr := range tests { 238 t.Run(path, func(t *testing.T) { 239 is := is.New(t) 240 err := os.Chdir(path) 241 is.NoErr(err) 242 defer func() { 243 err = os.Chdir(pwd) 244 is.NoErr(err) 245 }() 246 _, err = ParseDir(".") 247 is.True(err != nil) // must be an error 248 is.Equal(err.Error(), expectedErr) 249 }) 250 } 251 } 252 253 func TestParserImports(t *testing.T) { 254 is := is.New(t) 255 256 b, err := ioutil.ReadFile("testdata/rpc/import/greeter.remoto.go") 257 is.NoErr(err) 258 259 def, err := Parse(bytes.NewReader(b)) 260 is.NoErr(err) 261 262 is.Equal(len(def.Services), 1) 263 is.Equal(def.PackageName, "greeter") 264 out := def.String() 265 is.True(strings.Contains(out, `Photo remototypes.File`)) 266 } 267 268 // exampleRemotoDefinition is a copy of testdata/rpc/example/greeter.remoto.go 269 // used for testing the io.Reader version of the parser. 270 var exampleRemotoDefinition = `// Package greeter is a sweet API that greets people. 271 package greeter 272 273 // Greeter provides greeting services. 274 type Greeter interface { 275 // Greet generates a greeting. 276 Greet(GreetRequest) GreetResponse 277 } 278 279 // GreetFormatter provides formattable greeting services. 280 type GreetFormatter interface { 281 // Greet generates a greeting. 282 Greet(GreetFormatRequest) GreetResponse 283 } 284 285 // GreetRequest is the request for Greeter.GreetRequest. 286 type GreetRequest struct { 287 // Name is the name of the person to greet. 288 Name string 289 } 290 291 // GreetResponse is the response for Greeter.GreetRequest. 292 type GreetResponse struct { 293 // Greeting is the personalized greeting. 294 Greeting string 295 } 296 297 // GreetFormatRequest is the request for Greeter.GreetRequest. 298 type GreetFormatRequest struct { 299 // Format is the GreetingFormat describing the format 300 // of the greetings. 301 Format GreetingFormat 302 // Names is one or more names of people to greet. 303 Names []string 304 } 305 306 // GreetingFormat describes the format of a greeting. 307 type GreetingFormat struct { 308 // Format is a Go-style format string describing the greeting. 309 // %s will be replaced with the name of the person. 310 Format string 311 // AllCaps is whether to convert the greeting to all caps. 312 AllCaps bool 313 } 314 `