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  }