github.com/sentienttechnologies/studio-go-runner@v0.0.0-20201118202441-6d21f2ced8ee/internal/runner/go.go (about) 1 // Copyright 2018-2020 (c) Cognizant Digital Business, Evolutionary AI. All rights reserved. Issued under the Apache 2.0 License. 2 3 package runner 4 5 // This file contains function(s) useful for running the test suite. 6 7 import ( 8 "fmt" 9 "go/ast" 10 "go/parser" 11 "go/token" 12 "os" 13 "path/filepath" 14 "strings" 15 16 "github.com/go-stack/stack" 17 "github.com/jjeffery/kv" // MIT License 18 ) 19 20 // IsInTest will examine the OS arguments passed into the software 21 // being run to detect if the go test framework is present. If varies from 22 // the cudaInTest approach in that it will work if the tests were enabled 23 // in another module 24 // 25 func IsInTest() (isTest bool) { 26 if strings.HasSuffix(os.Args[0], ".test") { 27 return true 28 } 29 30 for _, arg := range os.Args { 31 if strings.HasPrefix(arg, "-test.v=") { 32 return true 33 } 34 } 35 return false 36 } 37 38 // GoGetConst will retrieve data structures from source code within the 39 // code directories that can contain useful information to utilities 40 // visiting the code for testing purposes. It is used mainly to 41 // retrieve command line parameters used during testing that packages contain 42 // so that when tests are run by external application neutral software the 43 // code under test can parameterize itself. 44 // 45 func GoGetConst(dir string, constName string) (v [][]string, err kv.Error) { 46 47 fset := token.NewFileSet() 48 parserMode := parser.ParseComments 49 50 errGo := filepath.Walk(dir, func(file string, fi os.FileInfo, err error) error { 51 if v != nil { 52 return nil 53 } 54 if fi.IsDir() { 55 // Dont recurse into directories with a main, needs AST treatment to discover main(s) 56 if fi.Name() == "cmd" || fi.Name() == "vendor" { 57 return filepath.SkipDir 58 } 59 return nil 60 } 61 if !strings.HasSuffix(fi.Name(), ".go") { 62 return nil 63 } 64 fileAst, errGo := parser.ParseFile(fset, file, nil, parserMode) 65 if errGo != nil { 66 return kv.Wrap(errGo).With("stack", stack.Trace().TrimRuntime()) 67 } 68 69 for _, d := range fileAst.Decls { 70 switch decl := d.(type) { 71 case *ast.FuncDecl: 72 continue 73 case *ast.GenDecl: 74 for _, spec := range decl.Specs { 75 switch spec := spec.(type) { 76 case *ast.ImportSpec: 77 continue 78 case *ast.TypeSpec: 79 continue 80 case *ast.ValueSpec: 81 for _, id := range spec.Names { 82 if id.Name == constName { 83 opts := []string{} 84 for _, value := range spec.Values { 85 for _, lts := range value.(*ast.CompositeLit).Elts { 86 if strs, ok := lts.(*ast.CompositeLit); ok { 87 for _, lt := range strs.Elts { 88 if entry, ok := lt.(*ast.BasicLit); ok { 89 opts = append(opts, entry.Value) 90 } 91 } 92 } 93 } 94 } 95 v = append(v, opts) 96 } 97 } 98 default: 99 fmt.Printf("Unknown token type: %s\n", decl.Tok) 100 } 101 } 102 default: 103 fmt.Print("Unknown declaration @\n", decl.Pos()) 104 } 105 } 106 return nil 107 }) 108 if errGo != nil { 109 return nil, kv.Wrap(errGo).With("stack", stack.Trace().TrimRuntime()) 110 } 111 return v, nil 112 }