github.com/blp1526/goa@v1.4.0/goagen/meta/generator_test.go (about) 1 package meta_test 2 3 import ( 4 "bytes" 5 "fmt" 6 "html/template" 7 "os" 8 "path/filepath" 9 10 "github.com/goadesign/goa/goagen/codegen" 11 "github.com/goadesign/goa/goagen/meta" 12 . "github.com/onsi/ginkgo" 13 . "github.com/onsi/gomega" 14 ) 15 16 var _ = Describe("Run", func() { 17 18 const invalidPkgPath = "foobar" 19 20 var ( 21 compiledFiles []string 22 compileError error 23 outputWorkspace *codegen.Workspace 24 designWorkspace *codegen.Workspace 25 genWorkspace *codegen.Workspace 26 27 outputDir string 28 designPkgPath string 29 genPkgSource string 30 customFlags []string 31 32 m *meta.Generator 33 ) 34 35 BeforeEach(func() { 36 designPkgPath = "design" 37 genPkgSource = "package gen\nfunc Generate() ([]string, error) { return nil, nil }" 38 39 var err error 40 41 outputWorkspace, err = codegen.NewWorkspace("output") 42 p, err := outputWorkspace.NewPackage("testOutput") 43 Ω(err).ShouldNot(HaveOccurred()) 44 outputDir = p.Abs() 45 46 designWorkspace, err = codegen.NewWorkspace("test") 47 Ω(err).ShouldNot(HaveOccurred()) 48 49 genWorkspace, err = codegen.NewWorkspace("gen") 50 Ω(err).ShouldNot(HaveOccurred()) 51 52 compiledFiles = nil 53 compileError = nil 54 customFlags = []string{"--custom=arg"} 55 }) 56 57 JustBeforeEach(func() { 58 if designPkgPath != "" && designPkgPath != invalidPkgPath { 59 designPackage, err := designWorkspace.NewPackage(designPkgPath) 60 Ω(err).ShouldNot(HaveOccurred()) 61 file, err := designPackage.CreateSourceFile("design.go") 62 Ω(err).ShouldNot(HaveOccurred()) 63 _, err = file.Write([]byte("package design")) 64 Ω(err).ShouldNot(HaveOccurred()) 65 file.Close() 66 } 67 68 genPackage, err := genWorkspace.NewPackage("gen") 69 Ω(err).ShouldNot(HaveOccurred()) 70 file, err := genPackage.CreateSourceFile("gen.go") 71 Ω(err).ShouldNot(HaveOccurred()) 72 _, err = file.Write([]byte(genPkgSource)) 73 Ω(err).ShouldNot(HaveOccurred()) 74 file.Close() 75 76 m = &meta.Generator{ 77 Genfunc: "gen.Generate", 78 Imports: []*codegen.ImportSpec{codegen.SimpleImport("gen")}, 79 OutDir: outputDir, 80 CustomFlags: customFlags, 81 DesignPkgPath: designPkgPath, 82 } 83 compiledFiles, compileError = m.Generate() 84 }) 85 86 AfterEach(func() { 87 designWorkspace.Delete() 88 outputWorkspace.Delete() 89 genWorkspace.Delete() 90 }) 91 92 Context("with no GOPATH environment variable", func() { 93 var gopath string 94 95 BeforeEach(func() { 96 gopath = os.Getenv("GOPATH") 97 os.Setenv("GOPATH", "") 98 }) 99 100 AfterEach(func() { 101 os.Setenv("GOPATH", gopath) 102 }) 103 104 It("fails with a useful error message", func() { 105 Ω(compileError).Should(MatchError("GOPATH not set")) 106 }) 107 }) 108 109 Context("with an invalid GOPATH environment variable", func() { 110 var gopath string 111 const invalidPath = "DOES NOT EXIST" 112 113 BeforeEach(func() { 114 gopath = os.Getenv("GOPATH") 115 os.Setenv("GOPATH", invalidPath) 116 }) 117 118 AfterEach(func() { 119 os.Setenv("GOPATH", gopath) 120 }) 121 122 It("fails with a useful error message", func() { 123 Ω(compileError).Should(MatchError(HavePrefix(`invalid design package import path: cannot find package "design" in any of:`))) 124 Ω(compileError).Should(MatchError(HaveSuffix(filepath.Join(invalidPath, "src", "design") + " (from $GOPATH)"))) 125 }) 126 127 }) 128 129 Context("with an invalid design package path", func() { 130 BeforeEach(func() { 131 designPkgPath = invalidPkgPath 132 }) 133 134 It("fails with a useful error message", func() { 135 Ω(compileError).Should(MatchError(HavePrefix("invalid design package import path: cannot find package"))) 136 Ω(compileError).Should(MatchError(ContainSubstring(invalidPkgPath))) 137 }) 138 }) 139 140 Context("with no go compiler in PATH", func() { 141 var pathEnv string 142 const invalidPath = "/foobar" 143 144 BeforeEach(func() { 145 pathEnv = os.Getenv("PATH") 146 os.Setenv("PATH", invalidPath) 147 }) 148 149 AfterEach(func() { 150 os.Setenv("PATH", pathEnv) 151 }) 152 153 It("fails with a useful error message", func() { 154 Ω(compileError).Should(MatchError(`failed to find a go compiler, looked in "` + os.Getenv("PATH") + `"`)) 155 }) 156 }) 157 158 Context("with no output directory specified", func() { 159 BeforeEach(func() { 160 outputDir = "" 161 }) 162 163 It("fails with a useful error message", func() { 164 Ω(compileError).Should(MatchError("missing output directory flag")) 165 }) 166 }) 167 168 Context("with no design package path specified", func() { 169 BeforeEach(func() { 170 designPkgPath = "" 171 }) 172 173 It("fails with a useful error message", func() { 174 Ω(compileError).Should(MatchError("missing design package flag")) 175 }) 176 }) 177 178 Context("with gen package content", func() { 179 180 BeforeEach(func() { 181 outputDir = os.TempDir() 182 }) 183 184 Context("that is not valid Go code", func() { 185 BeforeEach(func() { 186 genPkgSource = invalidSource 187 }) 188 189 It("fails with a useful error message", func() { 190 Ω(compileError.Error()).Should(ContainSubstring("syntax error")) 191 }) 192 }) 193 194 Context("whose code blows up", func() { 195 BeforeEach(func() { 196 genPkgSource = panickySource 197 }) 198 199 It("fails with a useful error message", func() { 200 Ω(compileError.Error()).Should(ContainSubstring("panic: kaboom")) 201 }) 202 }) 203 204 Context("with valid code", func() { 205 BeforeEach(func() { 206 genPkgSource = validSource 207 }) 208 209 It("successfully runs", func() { 210 Ω(compileError).ShouldNot(HaveOccurred()) 211 }) 212 213 Context("with a comma separated list of path in GOPATH", func() { 214 var gopath string 215 BeforeEach(func() { 216 gopath = os.Getenv("GOPATH") 217 os.Setenv("GOPATH", fmt.Sprintf("%s%c%s", gopath, os.PathListSeparator, os.TempDir())) 218 }) 219 220 AfterEach(func() { 221 os.Setenv("GOPATH", gopath) 222 }) 223 224 It("successfull runs", func() { 225 Ω(compileError).ShouldNot(HaveOccurred()) 226 }) 227 }) 228 }) 229 230 Context("with code that returns generated file paths", func() { 231 var filePaths = []string{"foo", "bar"} 232 233 BeforeEach(func() { 234 var b bytes.Buffer 235 tmpl, err := template.New("source").Parse(validSourceTmpl) 236 Ω(err).ShouldNot(HaveOccurred()) 237 err = tmpl.Execute(&b, filePaths) 238 Ω(err).ShouldNot(HaveOccurred()) 239 genPkgSource = b.String() 240 }) 241 242 It("returns the paths", func() { 243 Ω(compileError).ShouldNot(HaveOccurred()) 244 Ω(compiledFiles).Should(Equal(filePaths)) 245 }) 246 }) 247 248 Context("with code that uses custom flags", func() { 249 BeforeEach(func() { 250 var b bytes.Buffer 251 tmpl, err := template.New("source").Parse(validSourceTmplWithCustomFlags) 252 Ω(err).ShouldNot(HaveOccurred()) 253 err = tmpl.Execute(&b, "--custom=arg") 254 Ω(err).ShouldNot(HaveOccurred()) 255 genPkgSource = b.String() 256 257 }) 258 259 It("returns no error", func() { 260 Ω(compileError).ShouldNot(HaveOccurred()) 261 }) 262 }) 263 }) 264 }) 265 266 const ( 267 invalidSource = `package gen 268 invalid go code 269 ` 270 271 panickySource = `package gen 272 func Generate() ([]string, error) { 273 return nil, nil 274 } 275 276 func init() { panic("kaboom") } 277 ` 278 279 validSource = `package gen 280 func Generate() ([]string, error) { 281 return nil, nil 282 } 283 ` 284 285 validSourceTmpl = `package gen 286 import "fmt" 287 func Generate() ([]string, error) { 288 {{range .}}fmt.Println("{{.}}") 289 {{end}} 290 return nil, nil 291 } 292 ` 293 294 validSourceTmplWithCustomFlags = `package gen 295 import "fmt" 296 import "os" 297 298 func Generate() ([]string, error) { 299 for _, arg := range os.Args { 300 if arg == "{{.}}" { 301 return nil, nil 302 } 303 } 304 return nil, fmt.Errorf("no flag {{.}} found") 305 } 306 ` 307 )