github.com/MikeZappa87/cni@v0.8.1/pkg/version/testhelpers/testhelpers.go (about) 1 // Copyright 2016 CNI authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // Package testhelpers supports testing of CNI components of different versions 16 // 17 // For example, to build a plugin against an old version of the CNI library, 18 // we can pass the plugin's source and the old git commit reference to BuildAt. 19 // We could then test how the built binary responds when called by the latest 20 // version of this library. 21 package testhelpers 22 23 import ( 24 "fmt" 25 "io/ioutil" 26 "math/rand" 27 "os" 28 "os/exec" 29 "path/filepath" 30 "strings" 31 "time" 32 ) 33 34 const packageBaseName = "github.com/containernetworking/cni" 35 36 func run(cmd *exec.Cmd) error { 37 out, err := cmd.CombinedOutput() 38 if err != nil { 39 command := strings.Join(cmd.Args, " ") 40 return fmt.Errorf("running %q: %s", command, out) 41 } 42 return nil 43 } 44 45 func goBuildEnviron(gopath string) []string { 46 environ := os.Environ() 47 for i, kvp := range environ { 48 if strings.HasPrefix(kvp, "GOPATH=") { 49 environ[i] = "GOPATH=" + gopath 50 return environ 51 } 52 } 53 environ = append(environ, "GOPATH="+gopath) 54 return environ 55 } 56 57 func buildGoProgram(gopath, packageName, outputFilePath string) error { 58 cmd := exec.Command("go", "build", "-o", outputFilePath, packageName) 59 cmd.Env = goBuildEnviron(gopath) 60 return run(cmd) 61 } 62 63 func createSingleFilePackage(gopath, packageName string, fileContents []byte) error { 64 dirName := filepath.Join(gopath, "src", packageName) 65 err := os.MkdirAll(dirName, 0700) 66 if err != nil { 67 return err 68 } 69 70 return ioutil.WriteFile(filepath.Join(dirName, "main.go"), fileContents, 0600) 71 } 72 73 func removePackage(gopath, packageName string) error { 74 dirName := filepath.Join(gopath, "src", packageName) 75 return os.RemoveAll(dirName) 76 } 77 78 func isRepoRoot(path string) bool { 79 _, err := ioutil.ReadDir(filepath.Join(path, ".git")) 80 return (err == nil) && (filepath.Base(path) == "cni") 81 } 82 83 func LocateCurrentGitRepo() (string, error) { 84 dir, err := os.Getwd() 85 if err != nil { 86 return "", err 87 } 88 89 for i := 0; i < 5; i++ { 90 if isRepoRoot(dir) { 91 return dir, nil 92 } 93 94 dir, err = filepath.Abs(filepath.Dir(dir)) 95 if err != nil { 96 return "", fmt.Errorf("abs(dir(%q)): %s", dir, err) 97 } 98 } 99 100 return "", fmt.Errorf("unable to find cni repo root, landed at %q", dir) 101 } 102 103 func gitCloneThisRepo(cloneDestination string) error { 104 err := os.MkdirAll(cloneDestination, 0700) 105 if err != nil { 106 return err 107 } 108 109 currentGitRepo, err := LocateCurrentGitRepo() 110 if err != nil { 111 return err 112 } 113 114 return run(exec.Command("git", "clone", currentGitRepo, cloneDestination)) 115 } 116 117 func gitCheckout(localRepo string, gitRef string) error { 118 return run(exec.Command("git", "-C", localRepo, "checkout", gitRef)) 119 } 120 121 // BuildAt builds the go programSource using the version of the CNI library 122 // at gitRef, and saves the resulting binary file at outputFilePath 123 func BuildAt(programSource []byte, gitRef string, outputFilePath string) error { 124 tempGoPath, err := ioutil.TempDir("", "cni-git-") 125 if err != nil { 126 return err 127 } 128 defer os.RemoveAll(tempGoPath) 129 130 cloneDestination := filepath.Join(tempGoPath, "src", packageBaseName) 131 err = gitCloneThisRepo(cloneDestination) 132 if err != nil { 133 return err 134 } 135 136 err = gitCheckout(cloneDestination, gitRef) 137 if err != nil { 138 return err 139 } 140 141 rand.Seed(time.Now().UnixNano()) 142 testPackageName := fmt.Sprintf("test-package-%x", rand.Int31()) 143 144 err = createSingleFilePackage(tempGoPath, testPackageName, programSource) 145 if err != nil { 146 return err 147 } 148 defer removePackage(tempGoPath, testPackageName) 149 150 err = buildGoProgram(tempGoPath, testPackageName, outputFilePath) 151 if err != nil { 152 return err 153 } 154 155 return nil 156 }