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  )