github.com/furusax0621/goa-v1@v1.4.3/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 an invalid GOPATH environment variable", func() { 93 var gopath string 94 const invalidPath = "DOES NOT EXIST" 95 96 BeforeEach(func() { 97 gopath = os.Getenv("GOPATH") 98 os.Setenv("GOPATH", invalidPath) 99 }) 100 101 AfterEach(func() { 102 os.Setenv("GOPATH", gopath) 103 }) 104 105 It("fails with a useful error message", func() { 106 Ω(compileError).Should(MatchError(HavePrefix(`invalid design package import path: cannot find package "design" in any of:`))) 107 Ω(compileError).Should(MatchError(HaveSuffix(filepath.Join(invalidPath, "src", "design") + " (from $GOPATH)"))) 108 }) 109 110 }) 111 112 Context("with an invalid design package path", func() { 113 BeforeEach(func() { 114 designPkgPath = invalidPkgPath 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(invalidPkgPath))) 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 pathEnv = os.Getenv("PATH") 129 os.Setenv("PATH", invalidPath) 130 }) 131 132 AfterEach(func() { 133 os.Setenv("PATH", pathEnv) 134 }) 135 136 It("fails with a useful error message", func() { 137 Ω(compileError).Should(MatchError(`failed to find a go compiler, looked in "` + os.Getenv("PATH") + `"`)) 138 }) 139 }) 140 141 Context("with no output directory specified", func() { 142 BeforeEach(func() { 143 outputDir = "" 144 }) 145 146 It("fails with a useful error message", func() { 147 Ω(compileError).Should(MatchError("missing output directory flag")) 148 }) 149 }) 150 151 Context("with no design package path specified", func() { 152 BeforeEach(func() { 153 designPkgPath = "" 154 }) 155 156 It("fails with a useful error message", func() { 157 Ω(compileError).Should(MatchError("missing design package flag")) 158 }) 159 }) 160 161 Context("with gen package content", func() { 162 163 BeforeEach(func() { 164 outputDir = os.TempDir() 165 }) 166 167 Context("that is not valid Go code", func() { 168 BeforeEach(func() { 169 genPkgSource = invalidSource 170 }) 171 172 It("fails with a useful error message", func() { 173 Ω(compileError.Error()).Should(ContainSubstring("syntax error")) 174 }) 175 }) 176 177 Context("whose code blows up", func() { 178 BeforeEach(func() { 179 genPkgSource = panickySource 180 }) 181 182 It("fails with a useful error message", func() { 183 Ω(compileError.Error()).Should(ContainSubstring("panic: kaboom")) 184 }) 185 }) 186 187 Context("with valid code", func() { 188 BeforeEach(func() { 189 genPkgSource = validSource 190 }) 191 192 It("successfully runs", func() { 193 Ω(compileError).ShouldNot(HaveOccurred()) 194 }) 195 196 Context("with a comma separated list of path in GOPATH", func() { 197 var gopath string 198 BeforeEach(func() { 199 gopath = os.Getenv("GOPATH") 200 os.Setenv("GOPATH", fmt.Sprintf("%s%c%s", gopath, os.PathListSeparator, os.TempDir())) 201 }) 202 203 AfterEach(func() { 204 os.Setenv("GOPATH", gopath) 205 }) 206 207 It("successfull runs", func() { 208 Ω(compileError).ShouldNot(HaveOccurred()) 209 }) 210 }) 211 }) 212 213 Context("with code that returns generated file paths", func() { 214 var filePaths = []string{"foo", "bar"} 215 216 BeforeEach(func() { 217 var b bytes.Buffer 218 tmpl, err := template.New("source").Parse(validSourceTmpl) 219 Ω(err).ShouldNot(HaveOccurred()) 220 err = tmpl.Execute(&b, filePaths) 221 Ω(err).ShouldNot(HaveOccurred()) 222 genPkgSource = b.String() 223 }) 224 225 It("returns the paths", func() { 226 Ω(compileError).ShouldNot(HaveOccurred()) 227 Ω(compiledFiles).Should(Equal(filePaths)) 228 }) 229 }) 230 231 Context("with code that uses custom flags", func() { 232 BeforeEach(func() { 233 var b bytes.Buffer 234 tmpl, err := template.New("source").Parse(validSourceTmplWithCustomFlags) 235 Ω(err).ShouldNot(HaveOccurred()) 236 err = tmpl.Execute(&b, "--custom=arg") 237 Ω(err).ShouldNot(HaveOccurred()) 238 genPkgSource = b.String() 239 240 }) 241 242 It("returns no error", func() { 243 Ω(compileError).ShouldNot(HaveOccurred()) 244 }) 245 }) 246 }) 247 }) 248 249 const ( 250 invalidSource = `package gen 251 invalid go code 252 ` 253 254 panickySource = `package gen 255 func Generate() ([]string, error) { 256 return nil, nil 257 } 258 259 func init() { panic("kaboom") } 260 ` 261 262 validSource = `package gen 263 func Generate() ([]string, error) { 264 return nil, nil 265 } 266 ` 267 268 validSourceTmpl = `package gen 269 import "fmt" 270 func Generate() ([]string, error) { 271 {{range .}}fmt.Println("{{.}}") 272 {{end}} 273 return nil, nil 274 } 275 ` 276 277 validSourceTmplWithCustomFlags = `package gen 278 import "fmt" 279 import "os" 280 281 func Generate() ([]string, error) { 282 for _, arg := range os.Args { 283 if arg == "{{.}}" { 284 return nil, nil 285 } 286 } 287 return nil, fmt.Errorf("no flag {{.}} found") 288 } 289 ` 290 )