gopkg.in/alecthomas/gometalinter.v3@v3.0.0/_linters/src/github.com/securego/gosec/testutils/pkg.go (about) 1 package testutils 2 3 import ( 4 "fmt" 5 "go/build" 6 "go/parser" 7 "io/ioutil" 8 "log" 9 "os" 10 "path" 11 "strings" 12 13 "github.com/securego/gosec" 14 "golang.org/x/tools/go/loader" 15 ) 16 17 type buildObj struct { 18 pkg *build.Package 19 config loader.Config 20 program *loader.Program 21 } 22 23 // TestPackage is a mock package for testing purposes 24 type TestPackage struct { 25 Path string 26 Files map[string]string 27 ondisk bool 28 build *buildObj 29 } 30 31 // NewTestPackage will create a new and empty package. Must call Close() to cleanup 32 // auxilary files 33 func NewTestPackage() *TestPackage { 34 // Files must exist in $GOPATH 35 sourceDir := path.Join(os.Getenv("GOPATH"), "src") 36 workingDir, err := ioutil.TempDir(sourceDir, "gosecs_test") 37 if err != nil { 38 return nil 39 } 40 41 return &TestPackage{ 42 Path: workingDir, 43 Files: make(map[string]string), 44 ondisk: false, 45 build: nil, 46 } 47 } 48 49 // AddFile inserts the filename and contents into the package contents 50 func (p *TestPackage) AddFile(filename, content string) { 51 p.Files[path.Join(p.Path, filename)] = content 52 } 53 54 func (p *TestPackage) write() error { 55 if p.ondisk { 56 return nil 57 } 58 for filename, content := range p.Files { 59 if e := ioutil.WriteFile(filename, []byte(content), 0644); e != nil { 60 return e 61 } 62 } 63 p.ondisk = true 64 return nil 65 } 66 67 // Build ensures all files are persisted to disk and built 68 func (p *TestPackage) Build() error { 69 if p.build != nil { 70 return nil 71 } 72 if err := p.write(); err != nil { 73 return err 74 } 75 basePackage, err := build.Default.ImportDir(p.Path, build.ImportComment) 76 if err != nil { 77 return err 78 } 79 80 var packageFiles []string 81 packageConfig := loader.Config{Build: &build.Default, ParserMode: parser.ParseComments} 82 for _, filename := range basePackage.GoFiles { 83 packageFiles = append(packageFiles, path.Join(p.Path, filename)) 84 } 85 86 packageConfig.CreateFromFilenames(basePackage.Name, packageFiles...) 87 program, err := packageConfig.Load() 88 if err != nil { 89 return err 90 } 91 p.build = &buildObj{ 92 pkg: basePackage, 93 config: packageConfig, 94 program: program, 95 } 96 return nil 97 } 98 99 // CreateContext builds a context out of supplied package context 100 func (p *TestPackage) CreateContext(filename string) *gosec.Context { 101 if err := p.Build(); err != nil { 102 log.Fatal(err) 103 return nil 104 } 105 106 for _, pkg := range p.build.program.Created { 107 for _, file := range pkg.Files { 108 pkgFile := p.build.program.Fset.File(file.Pos()).Name() 109 strip := fmt.Sprintf("%s%c", p.Path, os.PathSeparator) 110 pkgFile = strings.TrimPrefix(pkgFile, strip) 111 if pkgFile == filename { 112 ctx := &gosec.Context{ 113 FileSet: p.build.program.Fset, 114 Root: file, 115 Config: gosec.NewConfig(), 116 Info: &pkg.Info, 117 Pkg: pkg.Pkg, 118 Imports: gosec.NewImportTracker(), 119 } 120 ctx.Imports.TrackPackages(ctx.Pkg.Imports()...) 121 return ctx 122 } 123 } 124 } 125 return nil 126 } 127 128 // Close will delete the package and all files in that directory 129 func (p *TestPackage) Close() { 130 if p.ondisk { 131 err := os.RemoveAll(p.Path) 132 if err != nil { 133 log.Fatal(err) 134 } 135 } 136 }