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