]> xenbits.xensource.com Git - people/gdunlap/xsatool/commitdiff
Refactor main to be more test-friendly
authorGeorge Dunlap <george.dunlap@citrix.com>
Wed, 10 May 2017 13:27:05 +0000 (14:27 +0100)
committerGeorge Dunlap <george.dunlap@citrix.com>
Wed, 10 May 2017 15:54:39 +0000 (16:54 +0100)
Have a special function, XsaMain(), which does the work and is passed
parameters and a return value.  Have a wrapper which interacts with
the operating system under normal conditions.  This allows the testing
infrastructure to simulate being called as closely as possible.

Get rid of global references to 'xsa' entirely; instead pass
references to a local copy on the stack.

Collect all remaining global state into a struct called 'G', and reset
its state every time XsaMain() is called.

Signed-off-by: George Dunlap <george.dunlap@citrix.com>
global.go
main.go
meta.go
recipe.go
repo.go
test.go
xsa.go

index e42542e29eb9047d510c1c4b1a9e79cb1e054de1..74533cc7bc6173d7b36a5d839e213e4b8de52be2 100644 (file)
--- a/global.go
+++ b/global.go
@@ -7,7 +7,7 @@ import (
        "strings"
 )
 
-func MainGlobalUpdate(xsanum int, args []string) int {
+func MainGlobalUpdate(unused *XSAMeta, args []string) int {
        err := OpenRepos()
        if err != nil {
                fmt.Printf("Error opening repos: %v\n", err)
@@ -47,7 +47,7 @@ func MainGlobalUpdate(xsanum int, args []string) int {
        }
 
        fmt.Printf("Getting Xen releases from treee...\n")
-       versions, err := repos.XenRepos[TreeXen].GetVersions()
+       versions, err := G.repos.XenRepos[TreeXen].GetVersions()
        if err != nil {
                fmt.Printf("Error getting Xen releases: %v\n", err)
                return 1
@@ -83,6 +83,6 @@ func MainGlobalUpdate(xsanum int, args []string) int {
        return 0
 }
 
-func MainGlobalInfo(xsanum int, args []string) int {
+func MainGlobalInfo(unused *XSAMeta, args []string) int {
        return 0
 }
diff --git a/main.go b/main.go
index 3674b6466657febc0217d3b6c0f72dd8c1c175e0..63019f3d609138f31038a7dcad07b122698deb4e 100644 (file)
--- a/main.go
+++ b/main.go
@@ -6,14 +6,9 @@ import (
        "strconv"
 )
 
-var repos struct {
-       XenRepos map[Tree]*XenRepo
-       xsa      Repo
-}
-
 func OpenRepos() (err error) {
        open := func(t Tree) (err error) {
-               repos.XenRepos[t], err = XenRepoOpen(config.Tool.GetPath(t), t)
+               G.repos.XenRepos[t], err = XenRepoOpen(G.config.Tool.GetPath(t), t)
                return
        }
 
@@ -24,7 +19,7 @@ func OpenRepos() (err error) {
 
 func ForEachXenRepo(f func(*XenRepo, Tree) error) error {
        f2 := func(tree Tree) (err error) {
-               xr := repos.XenRepos[tree]
+               xr := G.repos.XenRepos[tree]
 
                return f(xr, tree)
        }
@@ -32,7 +27,7 @@ func ForEachXenRepo(f func(*XenRepo, Tree) error) error {
        return ForEachCodeTree(f2)
 }
 
-func VersionsFromArgs(args []string) (vers []XenVersion) {
+func VersionsFromArgs(xsa *XSAMeta, args []string) (vers []XenVersion) {
        if len(args) == 1 && args[0] == "all" {
                vers = append(vers, xsa.SupportedVersions...)
        } else {
@@ -44,29 +39,40 @@ func VersionsFromArgs(args []string) (vers []XenVersion) {
        return
 }
 
-type MainFunc func(int, []string) int
+type MainFunc func(*XSAMeta, []string) int
 
-var config struct {
-       Tool     ToolConfig
-       Security SecurityMeta
+// GLOBAL
+var G struct {
+       config struct {
+               Tool     ToolConfig
+               Security SecurityMeta
+       }
+       repos struct {
+               XenRepos map[Tree]*XenRepo
+               xsa      Repo
+       }
 }
 
-var xsa XSAMeta
+// Reset global state each run for testing sake
+func globalReset() {
+       G.config.Tool = ToolConfig{}
+       G.config.Security = SecurityMeta{}
+       G.repos.xsa = Repo{}
+       G.repos.XenRepos = make(map[Tree]*XenRepo)
+}
 
-func main() {
+func XsaMain(args []string) int {
+       var xsa XSAMeta
        var main MainFunc
-       loadConfig := false
-       loadXSA := false
-       var xsanum int
-       var err error
 
-       repos.XenRepos = make(map[Tree]*XenRepo)
+       globalReset()
 
-       args := os.Args
+       loadConfig := false
+       loadXSA := false
 
        if len(args) < 3 {
                fmt.Printf("Not enough arguments\n")
-               os.Exit(1)
+               return 1
        }
 
        tgt := args[1]
@@ -74,11 +80,14 @@ func main() {
        cmd := args[0]
        args = args[1:]
 
+       var err error
+       var xsanum int
        if xsanum, err = strconv.Atoi(tgt); err == nil {
                switch cmd {
                case "new":
-                       main = func(xsanum int, args []string) int {
-                               if xsanum == 0 {
+                       xsa.XSA = xsanum
+                       main = func(xsa *XSAMeta, args []string) int {
+                               if xsa.XSA == 0 {
                                        fmt.Printf("Error: Need an XSA\n")
                                        return 1
                                }
@@ -113,18 +122,21 @@ func main() {
                        loadXSA = true
                default:
                        fmt.Printf("Unknown command: %s\n", cmd)
-                       os.Exit(1)
+                       return 1
                }
        } else if tgt == "repo" {
                switch cmd {
                case "init":
                        main = MainRepoInit
+               case "x":
+                       main = MainRepoX
+                       loadConfig = true
                case "info":
                        loadConfig = true
                        main = MainRepoInfo
                default:
                        fmt.Printf("Unknown command: %s\n", cmd)
-                       os.Exit(1)
+                       return 1
                }
        } else if tgt == "global" {
                switch cmd {
@@ -135,15 +147,15 @@ func main() {
                        main = MainGlobalInfo
                default:
                        fmt.Printf("Unknown command: %s\n", cmd)
-                       os.Exit(1)
+                       return 1
                }
        }
 
        if loadConfig {
-               err := config.Tool.Load()
+               err := G.config.Tool.Load()
                if err != nil {
                        fmt.Printf("Error finding config: %v\n", err)
-                       os.Exit(1)
+                       return 1
                }
        }
 
@@ -152,9 +164,13 @@ func main() {
                if err != nil {
                        fmt.Printf("Loading xsa-%d metadata: %v\n",
                                xsanum, err)
-                       os.Exit(1)
+                       return 1
                }
        }
 
-       os.Exit(main(xsanum, args))
+       return main(&xsa, args)
+}
+
+func main() {
+       os.Exit(XsaMain(os.Args))
 }
diff --git a/meta.go b/meta.go
index 0a86e501c2ff8e3b4d12e2ca19dc202a48423117..8ea8d06e499f10aabd0e44d348fb9b605d5f67bd 100644 (file)
--- a/meta.go
+++ b/meta.go
@@ -152,11 +152,11 @@ type SecurityMeta struct {
 const GlobalMetaFilename = "global.meta"
 
 func (sm *SecurityMeta) Load() (err error) {
-       if config.Tool.GetPath(TreeXSA) == "" {
+       if G.config.Tool.GetPath(TreeXSA) == "" {
                return fmt.Errorf("Tool config not loaded")
        }
 
-       filename := config.Tool.GetPath(TreeXSA) + "/" + GlobalMetaFilename
+       filename := G.config.Tool.GetPath(TreeXSA) + "/" + GlobalMetaFilename
 
        b, err := ioutil.ReadFile(filename)
        if err != nil {
@@ -173,7 +173,7 @@ func (sm *SecurityMeta) Load() (err error) {
 }
 
 func (sm *SecurityMeta) Save() (err error) {
-       if config.Tool.GetPath(TreeXSA) == "" {
+       if G.config.Tool.GetPath(TreeXSA) == "" {
                return fmt.Errorf("Tool config not loaded")
        }
 
@@ -182,7 +182,7 @@ func (sm *SecurityMeta) Save() (err error) {
                return fmt.Errorf("Marshalling config: %v", err)
        }
 
-       filename := config.Tool.GetPath(TreeXSA) + "/" + GlobalMetaFilename
+       filename := G.config.Tool.GetPath(TreeXSA) + "/" + GlobalMetaFilename
        err = ioutil.WriteFile(filename, b, 0666)
        if err != nil {
                return fmt.Errorf("Writing config: %v", err)
@@ -220,11 +220,11 @@ func (m *XSAMeta) NewRecipe(fv XenVersionFull) *Recipe {
 }
 
 func getXSAPath(xsanum int) string {
-       return fmt.Sprintf("%s/xsa%d.meta", config.Tool.GetPath(TreeXSA), xsanum)
+       return fmt.Sprintf("%s/xsa%d.meta", G.config.Tool.GetPath(TreeXSA), xsanum)
 }
 
 func (xm *XSAMeta) Load(xsanum int) (err error) {
-       if config.Tool.GetPath(TreeXSA) == "" {
+       if G.config.Tool.GetPath(TreeXSA) == "" {
                return fmt.Errorf("Tool config not loaded")
        }
 
@@ -259,7 +259,7 @@ func (xm *XSAMeta) Load(xsanum int) (err error) {
 }
 
 func (xm *XSAMeta) Save() (err error) {
-       if config.Tool.GetPath(TreeXSA) == "" {
+       if G.config.Tool.GetPath(TreeXSA) == "" {
                return fmt.Errorf("Tool config not loaded")
        }
 
index bc53bc5648d7102209639ebe7b45d9faac412977..e6f60b852ad9430323d6095575452db39f09a9aa 100644 (file)
--- a/recipe.go
+++ b/recipe.go
@@ -148,7 +148,7 @@ func (r *Recipe) MakePatches(prefix string, sync bool) (err error) {
                //
                // 'unstable' if VVV is 'master'
 
-               xsabase := fmt.Sprintf("xsa%d", xsa.XSA)
+               xsabase := fmt.Sprintf("xsa%d", r.xsa)
 
                if tree != TreeXen {
                        xsabase += "-" + tree.String()
@@ -160,7 +160,7 @@ func (r *Recipe) MakePatches(prefix string, sync bool) (err error) {
                        xsabase += "-" + r.XenVersionFull.XenVersion().String()
                }
 
-               xsatgt := config.Tool.GetPath(TreeXSA) + "/" + xsabase
+               xsatgt := G.config.Tool.GetPath(TreeXSA) + "/" + xsabase
 
                // rm -rf ../xsa.git/xsa206-unstable
                // Do a full remove of $base and $base.patch just to be sure
@@ -301,7 +301,7 @@ func (r *Recipe) apply(xr *XenRepo, tr *TreeRecipe, prefix string) (err error) {
 
        for _, glob := range tr.Patches {
                // git am
-               _, err = xr.AmClean(config.Tool.GetPath(TreeXSA) + "/" + glob)
+               _, err = xr.AmClean(G.config.Tool.GetPath(TreeXSA) + "/" + glob)
                if err != nil {
                        return fmt.Errorf("Appling am %s: %v\n", glob, err)
                }
@@ -344,13 +344,13 @@ func (r *Recipe) CreateBranch(prefix string, tree Tree) (err error) {
        if err != nil {
                return err
        }
-       return r.apply(repos.XenRepos[tree], tr, prefix)
+       return r.apply(G.repos.XenRepos[tree], tr, prefix)
 }
 
 func (r *Recipe) Build(prefix string) (err error) {
        branch, _ := r.branchName(prefix)
 
-       xenrepo := repos.XenRepos[TreeXen]
+       xenrepo := G.repos.XenRepos[TreeXen]
 
        /* Always check out a temporary branch for xen */
        tmpBranch := "tmp"
@@ -377,8 +377,8 @@ func (r *Recipe) Build(prefix string) (err error) {
        config += "OVMF_UPSTREAM_URL ?= file://" + mirrorpath + "ovmf.git\n"
        config += "SEABIOS_UPSTREAM_URL ?= file://" + mirrorpath + "seabios.git\n"
        config += "MINIOS_UPSTREAM_URL ?= file://" + mirrorpath + "mini-os.git\n"
-       config += "QEMU_UPSTREAM_URL ?= file://" + repos.XenRepos[TreeQemuU].GetPath() + "\n"
-       config += "QEMU_TRADITIONAL_URL ?= file://" + repos.XenRepos[TreeQemuT].GetPath() + "\n"
+       config += "QEMU_UPSTREAM_URL ?= file://" + G.repos.XenRepos[TreeQemuU].GetPath() + "\n"
+       config += "QEMU_TRADITIONAL_URL ?= file://" + G.repos.XenRepos[TreeQemuT].GetPath() + "\n"
 
        if tr, prs := r.Recipes[TreeQemuU]; prs && tr.HasPatches() {
                config += "QEMU_UPSTREAM_REVISION = origin/" + branch + "\n"
diff --git a/repo.go b/repo.go
index 7b7d1787f9a025461b740b4289d81f1a8483602d..dd20ef273429ac0a94b35c2b28c0bd325f2140c3 100644 (file)
--- a/repo.go
+++ b/repo.go
@@ -12,7 +12,7 @@ import (
 // Then attempt to clone the repositories and set them up so that push
 // is disabled by default.  Don't overwrite existing repositories
 // unless -f is specified.
-func MainRepoInit(xsanum int, args []string) (ret int) {
+func MainRepoInit(unused *XSAMeta, args []string) (ret int) {
        force := false
 
        for len(args) > 0 {
@@ -28,9 +28,9 @@ func MainRepoInit(xsanum int, args []string) (ret int) {
        }
 
        fmt.Printf("Trying local config...\n")
-       if err := config.Tool.Load(); err != nil {
+       if err := G.config.Tool.Load(); err != nil {
                if os.IsNotExist(err) {
-                       config.Tool.Init()
+                       G.config.Tool.Init()
                } else {
                        fmt.Printf("Error opening config file: %v\n", err)
                        return 1
@@ -44,11 +44,11 @@ func MainRepoInit(xsanum int, args []string) (ret int) {
                TreeXSA:   "xsa.git",
        }
        setDefaultPath := func(tree Tree) (err error) {
-               _, prs := config.Tool.Paths[tree]
+               _, prs := G.config.Tool.Paths[tree]
                if prs {
-                       fmt.Printf("Already set to %s\n", config.Tool.Paths[tree])
+                       fmt.Printf("Already set to %s\n", G.config.Tool.Paths[tree])
                } else {
-                       config.Tool.Paths[tree] = defaultPath[tree]
+                       G.config.Tool.Paths[tree] = defaultPath[tree]
                        fmt.Printf("Setting default: %s\n", defaultPath[tree])
                }
                return
@@ -96,7 +96,7 @@ func MainRepoInit(xsanum int, args []string) (ret int) {
                        err = xr.DisablePush()
                }
 
-               repos.XenRepos[t] = xr
+               G.repos.XenRepos[t] = xr
 
                return
        }
@@ -111,13 +111,13 @@ func MainRepoInit(xsanum int, args []string) (ret int) {
        }
 
        clone := func(tree Tree) (err error) {
-               target := config.Tool.Paths[tree]
+               target := G.config.Tool.Paths[tree]
                origin := defaultUrl[tree]
 
                if tree == TreeXSA {
-                       repos.xsa, err = cloneNormal(target, origin)
+                       G.repos.xsa, err = cloneNormal(target, origin)
                } else {
-                       repos.XenRepos[tree], err = cloneXen(target, origin, tree)
+                       G.repos.XenRepos[tree], err = cloneXen(target, origin, tree)
                }
                return
        }
@@ -128,13 +128,13 @@ func MainRepoInit(xsanum int, args []string) (ret int) {
                return 1
        }
 
-       err = config.Tool.Save()
+       err = G.config.Tool.Save()
        if err != nil {
                fmt.Printf("Trying to save config: %v\n", err)
                return 1
        }
 
-       err = config.Tool.Save()
+       err = G.config.Tool.Save()
        if err != nil {
                fmt.Printf("Trying to save config: %v\n", err)
                return 1
@@ -143,12 +143,31 @@ func MainRepoInit(xsanum int, args []string) (ret int) {
        return 0
 }
 
-func MainRepoInfo(xsanum int, args []string) (ret int) {
+func MainRepoInfo(unused *XSAMeta, args []string) (ret int) {
        fmt.Printf("[Tool]\n")
-       fmt.Printf("rootDir: %s\n", config.Tool.rootDir)
-       fmt.Printf("XSA repo: %s\n", config.Tool.GetPath(TreeXSA))
-       fmt.Printf("Xen repo: %s\n", config.Tool.GetPath(TreeXen))
-       fmt.Printf("Qemu Upstream repo: %s\n", config.Tool.GetPath(TreeQemuU))
-       fmt.Printf("Qemu Traditional repo: %s\n", config.Tool.GetPath(TreeQemuT))
+       fmt.Printf("rootDir: %s\n", G.config.Tool.rootDir)
+       fmt.Printf("XSA repo: %s\n", G.config.Tool.GetPath(TreeXSA))
+       fmt.Printf("Xen repo: %s\n", G.config.Tool.GetPath(TreeXen))
+       fmt.Printf("Qemu Upstream repo: %s\n", G.config.Tool.GetPath(TreeQemuU))
+       fmt.Printf("Qemu Traditional repo: %s\n", G.config.Tool.GetPath(TreeQemuT))
+       return 0
+}
+
+func MainRepoX(unused *XSAMeta, args []string) (ret int) {
+       err := OpenRepos()
+       if err != nil {
+               fmt.Printf("Error opening repos: %v\n", err)
+               return 1
+       }
+
+       versions, err := G.repos.XenRepos[TreeXen].GetVersions()
+
+       if err != nil {
+               fmt.Printf("Error getting versions: %v\n", err)
+               return 1
+       }
+
+       fmt.Printf("Versions in repo: %v\n", versions)
+
        return 0
 }
diff --git a/test.go b/test.go
index f0c070ea2d4d69e0f90cf5a23c20c7d5f1d177a1..e59412af630c594d7a37f832167f449c3872b716 100644 (file)
--- a/test.go
+++ b/test.go
@@ -40,7 +40,7 @@ func backport(xsa *XSAMeta) (ret int) {
 
 func test(xsa *XSAMeta, args []string, apply bool, build bool) (ret int) {
 
-       vers := VersionsFromArgs(args)
+       vers := VersionsFromArgs(xsa, args)
 
        for _, v := range vers {
                prefix := "test"
@@ -86,7 +86,7 @@ func test(xsa *XSAMeta, args []string, apply bool, build bool) (ret int) {
        return 0
 }
 
-func MainTestApply(xsanum int, args []string) (ret int) {
+func MainTestApply(xsa *XSAMeta, args []string) (ret int) {
 
        err := OpenRepos()
        if err != nil {
@@ -94,10 +94,10 @@ func MainTestApply(xsanum int, args []string) (ret int) {
                return 1
        }
 
-       return test(&xsa, args, true, false)
+       return test(xsa, args, true, false)
 }
 
-func MainTestBuild(xsanum int, args []string) (ret int) {
+func MainTestBuild(xsa *XSAMeta, args []string) (ret int) {
 
        err := OpenRepos()
        if err != nil {
@@ -105,10 +105,10 @@ func MainTestBuild(xsanum int, args []string) (ret int) {
                return 1
        }
 
-       return test(&xsa, args, false, true)
+       return test(xsa, args, false, true)
 }
 
-func MainTest(xsanum int, args []string) (ret int) {
+func MainTest(xsa *XSAMeta, args []string) (ret int) {
 
        err := OpenRepos()
        if err != nil {
@@ -116,5 +116,5 @@ func MainTest(xsanum int, args []string) (ret int) {
                return 1
        }
 
-       return test(&xsa, args, true, true)
+       return test(xsa, args, true, true)
 }
diff --git a/xsa.go b/xsa.go
index 03dc3773b5b07bf4ba0c95ebbaafa8d67a6748ad..ce33f96e348923805f57afb1ee395b13ee4b3e51 100644 (file)
--- a/xsa.go
+++ b/xsa.go
@@ -4,14 +4,14 @@ import (
        "fmt"
 )
 
-func sync(args []string, sync bool) (ret int) {
+func sync(xsa *XSAMeta, args []string, sync bool) (ret int) {
        err := OpenRepos()
        if err != nil {
                fmt.Printf("Error initializing repos: %v\n", err)
                return 1
        }
 
-       vers := VersionsFromArgs(args)
+       vers := VersionsFromArgs(xsa, args)
 
        if !sync && len(vers) > 1 {
                fmt.Printf("Error: Doesn't make sense to make more than one version\n")
@@ -41,16 +41,16 @@ func sync(args []string, sync bool) (ret int) {
        return 0
 }
 
-func MainSyncPatches(xsanum int, args []string) (ret int) {
-       return sync(args, true)
+func MainSyncPatches(xsa *XSAMeta, args []string) (ret int) {
+       return sync(xsa, args, true)
 }
 
-func MainMakePatches(xsanum int, args []string) (ret int) {
-       return sync(args, false)
+func MainMakePatches(xsa *XSAMeta, args []string) (ret int) {
+       return sync(xsa, args, false)
 }
 
-func MainSyncBranch(xsanum int, args []string) (ret int) {
-       vers := VersionsFromArgs(args)
+func MainSyncBranch(xsa *XSAMeta, args []string) (ret int) {
+       vers := VersionsFromArgs(xsa, args)
 
        for _, v := range vers {
                prefix := "xsa"
@@ -72,7 +72,7 @@ func MainSyncBranch(xsanum int, args []string) (ret int) {
 }
 
 // xsatool NNN new-recipe $FULLVERSION {xen,qemuu,qemut} [prerequisites]
-func MainNewRecipe(xsanum int, args []string) (ret int) {
+func MainNewRecipe(xsa *XSAMeta, args []string) (ret int) {
        if len(args) < 2 {
                fmt.Printf("Not enough argruments\n")
                return 1
@@ -111,7 +111,7 @@ func MainNewRecipe(xsanum int, args []string) (ret int) {
        } else {
                r = xsa.NewRecipe(fv)
                fmt.Printf("Made new metadata: %v\n", *r)
-               if r.xsa != xsanum {
+               if r.xsa != xsa.XSA {
                        fmt.Printf("xsanum didn't get set!\n")
                        return 1
                }