}
func XsaMain(args []string) int {
- if len(args) < 3 {
+ if len(args) < 3 && args[1] != "systemtest" {
fmt.Printf("Not enough arguments\n")
return 1
}
tgt := args[1]
args = args[2:]
- cmd := args[0]
- args = args[1:]
+ var cmd string
+ if len(args) > 0 {
+ cmd = args[0]
+ args = args[1:]
+ }
if xsanum, err = strconv.Atoi(tgt); err == nil {
switch cmd {
fmt.Printf("Unknown command: %s\n", cmd)
return 1
}
+ } else if tgt == "systemtest" {
+ return MainSystemTest()
}
if loadConfig {
}
func MainHarness(args ...string) int {
+ Q.real = false
x := append([]string{"xsatool"}, args...)
return XsaMain(x)
}
+++ /dev/null
-package main
-
-import (
- "fmt"
- "os"
- "path/filepath"
- "testing"
-)
-
-// Should we always do a new full clone (slow) or use a previous clone
-// if it exists (and leave clones for future callers)?
-var FullClone = false
-
-// Set up the repo in a known state.
-func InitRepo(t *testing.T) bool {
- callRepoInit := true
-
- if FullClone {
- // Make temporary directory and cd to it
- // rm -rf tmp
- if err := os.RemoveAll("tmp"); err != nil {
- t.Errorf("Removing temporary path: %v", err)
- return false
- }
- } else {
- // Check to see if the directory exists
- _, err := os.Stat("tmp")
- if err == nil {
- callRepoInit = false
- } else {
- if !os.IsNotExist(err) {
- t.Errorf("Stat'ing temporary directory: %v\n", err)
- return false
- }
- }
- }
-
- if callRepoInit {
- // mkdir tmp
- if err := os.Mkdir("tmp", 0777); err != nil {
- t.Errorf("Making temporary path: %v\n", err)
- return false
- }
- }
-
- if err := os.Chdir("tmp"); err != nil {
- t.Errorf("cd tmp: %v\n", err)
- return false
- }
-
- if callRepoInit {
- // Initialize a current version of the repo
- if ret := MainHarness("repo", "init"); ret != 0 {
- t.Errorf("repo init failed: %d\n", ret)
- return false
- }
- } else {
- // Read existing version of repos
- if ret := MainHarness("repo", "info"); ret != 0 {
- t.Errorf("repo info failed: %d\n", ret)
- return false
- }
- }
-
- // Reset to a known state:
- // (Want to be able to apply XSA-206 (backports) , XSA-211 (qemu), XSA-212-15 (xen)
- // ~ March 27th
- // Xen master : ac9ff74
- // qemu-upstream : acde9f3
- // qemu-trad : 8b4834e
- // xsa : bff3883
- master := map[Tree]string{
- "xen": "ac9ff74",
- "qemuu": "acde9f3",
- "qemut": "8b4834e",
- "xsa": "bff3883",
- }
-
- updateMaster := func(t Tree) (err error) {
- var r *Repo
- if t == TreeXSA {
- r = &G.repos.xsa
- } else {
- xr, prs := G.repos.XenRepos[t]
- if !prs {
- err = fmt.Errorf("Not present: %s\n", t)
- return
- }
- r = &xr.Repo
- }
-
- _, err = r.ResetBranch("master", master[t])
- return
- }
-
- if err := ForEachTree(updateMaster); err != nil {
- t.Errorf("Tree update failed: %v\n", err)
- return false
- }
-
- // Delete:
- // All xenversions > 4.8
- // 4.8.0, 4.7.2
- // (4.6 and previous will have no new versions)
- vlimit := map[XenVersion]XenVersionFull{
- "4.8": "4.8.0",
- "4.7": "4.7.2",
- }
- r := G.repos.XenRepos[TreeXen]
- versions, err := r.GetVersions()
- if err != nil {
- t.Errorf("Error getting Xen releases: %v\n", err)
- return false
- }
-
- // FIXME: Grab 4.8.1 ref so we can re-tag it and test repo update
- for _, fv := range versions {
- l, prs := vlimit[fv.XenVersion()]
- if fv.XenVersion().IsGreaterEqualThan(XenVersion("4.9")) ||
- (prs && fv.Point() > l.Point()) {
- tag := "RELEASE-" + string(fv)
- t.Logf("Deleting tag %s\n", tag)
- if err := r.DeleteTag(tag); err != nil {
- t.Errorf("Deleting tag %s: %v\n", tag, err)
- return false
- }
- }
- }
-
- // Delete files potentially left over from previous runs
- if !FullClone {
- // rm xsa.git/*.meta
- files, err := filepath.Glob("xsa.git/*.meta")
- if err != nil {
- t.Errorf("Finding meta files to remove: %v", err)
- return false
- }
-
- for _, file := range files {
- t.Logf("Removing meta file %s\n", file)
- err = os.Remove(file)
- if err != nil {
- t.Errorf("Removing meta file %s: %v", file, err)
- return false
- }
- }
- }
-
- // Test to make sure things are in the expected state
-
- return true
-}
-
-func GlobalInit(t *testing.T) (pass bool) {
- //args := []string{"xsatool", "global", "update"}
- pass = true
-
- QuerySetResponses([]string{"4.4"})
- if MainHarness("global", "update") != 0 {
- return false
- }
-
- // Check to see that we have the expected
- versions := map[XenVersion]*struct {
- fv XenVersionFull
- seen bool
- }{
- "master": {fv: "master"},
- "4.8": {fv: "4.8.0"},
- "4.7": {fv: "4.7.2"},
- "4.6": {fv: "4.6.5"},
- "4.5": {fv: "4.5.5"},
- "4.4": {fv: "4.4.4"},
- }
-
- for v := range G.config.Security.Versions {
- _, prs := versions[v]
- if !prs {
- t.Errorf("Unexpected version: %v\n", v)
- pass = false
- } else {
- versions[v].seen = true
- if versions[v].fv != G.config.Security.Versions[v].Latest {
- t.Errorf("Expected fullversion %v, got %v\n",
- versions[v].fv,
- G.config.Security.Versions[v].Latest)
- pass = false
- }
- }
- }
-
- for v := range versions {
- if !versions[v].seen {
- t.Errorf("Didn't find expected xenversion %v\n", v)
- pass = false
- }
- }
- return pass
-}
-
-func Story206Init(t *testing.T) (pass bool) {
- t.Logf(" xsatool 206 init xen")
- if MainHarness("206", "init", "xen") != 0 {
- t.Errorf("xsatool 206 init failed\n")
- return false
- }
-
- // Things to check
- // - Recipes for appropriate
- var xsa XSAMeta
- if err := xsa.Load(206); err != nil {
- t.Errorf("Re-loading xsa: %v\n", err)
- return false
- }
-
- pass = true
-
- if xsa.XSA != 206 {
- t.Errorf("Unexpected XSA number: %d\n", xsa.XSA)
- pass = false
- }
-
- if len(xsa.Trees) != 1 || xsa.Trees[0] != TreeXen {
- t.Errorf("Unexpected xsa.Trees state: %v\n", xsa.Trees)
- pass = false
- }
-
- versions := map[XenVersion]*struct {
- fv XenVersionFull
- seen bool
- }{
- "master": {fv: "master"},
- "4.8": {fv: "4.8.0"},
- "4.7": {fv: "4.7.2"},
- "4.6": {fv: "4.6.5"},
- "4.5": {fv: "4.5.5"},
- "4.4": {fv: "4.4.4"},
- }
-
- for v := range xsa.Recipes {
- r := xsa.Recipes[v]
- _, prs := versions[v]
- if !prs {
- t.Errorf("Unexpected version: %v\n", v)
- pass = false
- } else {
- versions[v].seen = true
- if versions[v].fv != r.XenVersionFull {
- t.Errorf("Expected fullversion %v, got %v\n",
- versions[v].fv,
- r.XenVersionFull)
- pass = false
- }
- ForEachCodeTree(func(tree Tree) error {
- tr, prs := r.Recipes[tree]
- if tree == TreeXen {
- if !prs {
- t.Errorf("Missing expected recipe for Xen\n")
- pass = false
- } else if len(tr.Prereqs) != 0 || len(tr.Patches) != 0 {
- t.Errorf("Unexpected recipe for tree Xen\n")
- pass = false
- }
- } else {
- if prs {
- t.Errorf("Unexpected tree: %v\n", tree)
- pass = false
- }
- }
- return nil
- })
- }
- }
-
- for v := range versions {
- if !versions[v].seen {
- t.Errorf("Didn't find expected xenversion %v\n", v)
- pass = false
- }
- }
-
- sm := &G.config.Security
- for _, vm := range sm.Versions {
- ForEachCodeTree(func(tree Tree) error {
- xsas, prs := vm.XSAs[tree]
- if !prs {
- t.Errorf("No XSA list for tree %v\n", tree)
- pass = false
- } else {
- expected := 0
- if tree == TreeXen {
- expected = 1
- }
- if len(xsas) != expected {
- t.Errorf("Expected %d xsas, got %d!\n", expected, len(xsas))
- pass = false
- }
- }
- return nil
- })
- }
-
- // - Branches exist
-
- return
-}
-
-func Story206Implement(t *testing.T) (pass bool) {
- // [should already be on correct branch]
-
- // git am $PATH/xsa206-master/*.patch
-
- out, err := G.repos.XenRepos[TreeXen].Am("../testdata/xsa206-unstable/*.patch")
- if err != nil {
- t.Errorf("Error importing example patches: %v %s\n", err, string(out))
- return
- }
-
- return true
-}
-
-func Story206SyncOne(t *testing.T) (pass bool) {
- t.Logf(" xsatool 206 sync-patches")
- if MainHarness("206", "sync-patches") != 0 {
- t.Errorf("xsatool 206 sync-patches failed\n")
- return false
- }
-
- var xsa XSAMeta
-
- err := xsa.Load(206)
- if err != nil {
- t.Errorf("Error loading updated recipe: %v\n", err)
- return false
- }
-
- pass = true
-
- for v := range xsa.Recipes {
- r := xsa.GetRecipe(v)
- for tree := range r.Recipes {
- tr := r.Recipes[tree]
- expected := 0
- if v == XenVersion("master") && tree == TreeXen {
- expected = 1
- }
- if len(tr.Patches) != expected {
- t.Errorf("Version %v tree %v: Wanted %d, got %d\n",
- v, tree, expected, len(tr.Patches))
- pass = false
- }
- }
- }
-
- return pass
-}
-
-func Story206(t *testing.T) bool {
- t.Logf("Starting XSA-206 'story'")
- // xsatool 206 init xen
- if !Story206Init(t) {
- return false
- }
-
- // Fake-up xsa/206/master
- if !Story206Implement(t) {
- return false
- }
-
- // 206 sync-patches
- if !Story206SyncOne(t) {
- return false
- }
-
- // 206 Backport (should fail at 4.8. 4.7, and 4.6; NOT 4.5)
-
- // 206 sync-patches
-
- // 206 test
-
- return true
-}
-
-func TestSystem(t *testing.T) {
- if testing.Short() {
- t.Skipf("Not running full system tests")
- }
-
- // Store the toplevel directory
- topdir, err := os.Getwd()
- if err != nil {
- t.Errorf("Getwd failed?\n")
- return
- }
-
- // Init and/or cd into the testing directory
- if !InitRepo(t) {
- t.Errorf("Could not initialize repo")
- goto out
- }
-
- // Initialize global state
- // xsatool global update
- if !GlobalInit(t) {
- goto out
- }
-
- //// xsa 206 "story"
- if !Story206(t) {
- goto out
- }
-
- //// xsa 211 "story"
-
- //// Drop 4.4 support, update to 4.8.1
-
- //// xsa 212-215 "story"
-
-out:
- os.Chdir(topdir)
-
- if FullClone {
- // rm -rf tmp
- if err := os.RemoveAll("tmp"); err != nil {
- t.Errorf("Removing temporary path: %v", err)
- return
- }
- }
-
-}
--- /dev/null
+package main
+
+import (
+ "fmt"
+ "os"
+ "path/filepath"
+)
+
+type SystemTest struct {
+ failed bool
+}
+
+func (st *SystemTest) Errorf(s string, args ...interface{}) {
+ st.failed = true
+ fmt.Printf(s, args...)
+}
+
+// Should we always do a new full clone (slow) or use a previous clone
+// if it exists (and leave clones for future callers)?
+var FullClone = false
+
+// Set up the repo in a known state.
+func InitRepo(st *SystemTest) bool {
+ callRepoInit := true
+
+ if FullClone {
+ // Make temporary directory and cd to it
+ // rm -rf tmp
+ if err := os.RemoveAll("tmp"); err != nil {
+ st.Errorf("Removing temporary path: %v", err)
+ return false
+ }
+ } else {
+ // Check to see if the directory exists
+ _, err := os.Stat("tmp")
+ if err == nil {
+ callRepoInit = false
+ } else {
+ if !os.IsNotExist(err) {
+ st.Errorf("Stat'ing temporary directory: %v\n", err)
+ return false
+ }
+ }
+ }
+
+ if callRepoInit {
+ // mkdir tmp
+ if err := os.Mkdir("tmp", 0777); err != nil {
+ st.Errorf("Making temporary path: %v\n", err)
+ return false
+ }
+ }
+
+ if err := os.Chdir("tmp"); err != nil {
+ st.Errorf("cd tmp: %v\n", err)
+ return false
+ }
+
+ if callRepoInit {
+ // Initialize a current version of the repo
+ if ret := MainHarness("repo", "init"); ret != 0 {
+ st.Errorf("repo init failed: %d\n", ret)
+ return false
+ }
+ } else {
+ // Read existing version of repos
+ if ret := MainHarness("repo", "info"); ret != 0 {
+ st.Errorf("repo info failed: %d\n", ret)
+ return false
+ }
+ }
+
+ // Reset to a known state:
+ // (Want to be able to apply XSA-206 (backports) , XSA-211 (qemu), XSA-212-15 (xen)
+ // ~ March 27th
+ // Xen master : ac9ff74
+ // qemu-upstream : acde9f3
+ // qemu-trad : 8b4834e
+ // xsa : bff3883
+ master := map[Tree]string{
+ "xen": "ac9ff74",
+ "qemuu": "acde9f3",
+ "qemut": "8b4834e",
+ "xsa": "bff3883",
+ }
+
+ updateMaster := func(t Tree) (err error) {
+ var r *Repo
+ if t == TreeXSA {
+ r = &G.repos.xsa
+ } else {
+ xr, prs := G.repos.XenRepos[t]
+ if !prs {
+ err = fmt.Errorf("Not present: %s\n", t)
+ return
+ }
+ r = &xr.Repo
+ }
+
+ _, err = r.ResetBranch("master", master[t])
+ return
+ }
+
+ if err := ForEachTree(updateMaster); err != nil {
+ st.Errorf("Tree update failed: %v\n", err)
+ return false
+ }
+
+ // Delete:
+ // All xenversions > 4.8
+ // 4.8.0, 4.7.2
+ // (4.6 and previous will have no new versions)
+ vlimit := map[XenVersion]XenVersionFull{
+ "4.8": "4.8.0",
+ "4.7": "4.7.2",
+ }
+ r := G.repos.XenRepos[TreeXen]
+ versions, err := r.GetVersions()
+ if err != nil {
+ st.Errorf("Error getting Xen releases: %v\n", err)
+ return false
+ }
+
+ // FIXME: Grab 4.8.1 ref so we can re-tag it and test repo update
+ for _, fv := range versions {
+ l, prs := vlimit[fv.XenVersion()]
+ if fv.XenVersion().IsGreaterEqualThan(XenVersion("4.9")) ||
+ (prs && fv.Point() > l.Point()) {
+ tag := "RELEASE-" + string(fv)
+ fmt.Printf("Deleting tag %s\n", tag)
+ if err := r.DeleteTag(tag); err != nil {
+ st.Errorf("Deleting tag %s: %v\n", tag, err)
+ return false
+ }
+ }
+ }
+
+ // Delete files potentially left over from previous runs
+ if !FullClone {
+ // rm xsa.git/*.meta
+ files, err := filepath.Glob("xsa.git/*.meta")
+ if err != nil {
+ st.Errorf("Finding meta files to remove: %v", err)
+ return false
+ }
+
+ for _, file := range files {
+ fmt.Printf("Removing meta file %s\n", file)
+ err = os.Remove(file)
+ if err != nil {
+ st.Errorf("Removing meta file %s: %v", file, err)
+ return false
+ }
+ }
+ }
+
+ // Test to make sure things are in the expected state
+
+ return true
+}
+
+func GlobalInit(st *SystemTest) (pass bool) {
+ //args := []string{"xsatool", "global", "update"}
+ pass = true
+
+ QuerySetResponses([]string{"4.4"})
+ if MainHarness("global", "update") != 0 {
+ return false
+ }
+
+ // Check to see that we have the expected
+ versions := map[XenVersion]*struct {
+ fv XenVersionFull
+ seen bool
+ }{
+ "master": {fv: "master"},
+ "4.8": {fv: "4.8.0"},
+ "4.7": {fv: "4.7.2"},
+ "4.6": {fv: "4.6.5"},
+ "4.5": {fv: "4.5.5"},
+ "4.4": {fv: "4.4.4"},
+ }
+
+ for v := range G.config.Security.Versions {
+ _, prs := versions[v]
+ if !prs {
+ st.Errorf("Unexpected version: %v\n", v)
+ pass = false
+ } else {
+ versions[v].seen = true
+ if versions[v].fv != G.config.Security.Versions[v].Latest {
+ st.Errorf("Expected fullversion %v, got %v\n",
+ versions[v].fv,
+ G.config.Security.Versions[v].Latest)
+ pass = false
+ }
+ }
+ }
+
+ for v := range versions {
+ if !versions[v].seen {
+ st.Errorf("Didn't find expected xenversion %v\n", v)
+ pass = false
+ }
+ }
+ return pass
+}
+
+func Story206Init(st *SystemTest) (pass bool) {
+ fmt.Printf(" xsatool 206 init xen")
+ if MainHarness("206", "init", "xen") != 0 {
+ st.Errorf("xsatool 206 init failed\n")
+ return false
+ }
+
+ // Things to check
+ // - Recipes for appropriate
+ var xsa XSAMeta
+ if err := xsa.Load(206); err != nil {
+ st.Errorf("Re-loading xsa: %v\n", err)
+ return false
+ }
+
+ pass = true
+
+ if xsa.XSA != 206 {
+ st.Errorf("Unexpected XSA number: %d\n", xsa.XSA)
+ pass = false
+ }
+
+ if len(xsa.Trees) != 1 || xsa.Trees[0] != TreeXen {
+ st.Errorf("Unexpected xsa.Trees state: %v\n", xsa.Trees)
+ pass = false
+ }
+
+ versions := map[XenVersion]*struct {
+ fv XenVersionFull
+ seen bool
+ }{
+ "master": {fv: "master"},
+ "4.8": {fv: "4.8.0"},
+ "4.7": {fv: "4.7.2"},
+ "4.6": {fv: "4.6.5"},
+ "4.5": {fv: "4.5.5"},
+ "4.4": {fv: "4.4.4"},
+ }
+
+ for v := range xsa.Recipes {
+ r := xsa.Recipes[v]
+ _, prs := versions[v]
+ if !prs {
+ st.Errorf("Unexpected version: %v\n", v)
+ pass = false
+ } else {
+ versions[v].seen = true
+ if versions[v].fv != r.XenVersionFull {
+ st.Errorf("Expected fullversion %v, got %v\n",
+ versions[v].fv,
+ r.XenVersionFull)
+ pass = false
+ }
+ ForEachCodeTree(func(tree Tree) error {
+ tr, prs := r.Recipes[tree]
+ if tree == TreeXen {
+ if !prs {
+ st.Errorf("Missing expected recipe for Xen\n")
+ pass = false
+ } else if len(tr.Prereqs) != 0 || len(tr.Patches) != 0 {
+ st.Errorf("Unexpected recipe for tree Xen\n")
+ pass = false
+ }
+ } else {
+ if prs {
+ st.Errorf("Unexpected tree: %v\n", tree)
+ pass = false
+ }
+ }
+ return nil
+ })
+ }
+ }
+
+ for v := range versions {
+ if !versions[v].seen {
+ st.Errorf("Didn't find expected xenversion %v\n", v)
+ pass = false
+ }
+ }
+
+ sm := &G.config.Security
+ for _, vm := range sm.Versions {
+ ForEachCodeTree(func(tree Tree) error {
+ xsas, prs := vm.XSAs[tree]
+ if !prs {
+ st.Errorf("No XSA list for tree %v\n", tree)
+ pass = false
+ } else {
+ expected := 0
+ if tree == TreeXen {
+ expected = 1
+ }
+ if len(xsas) != expected {
+ st.Errorf("Expected %d xsas, got %d!\n", expected, len(xsas))
+ pass = false
+ }
+ }
+ return nil
+ })
+ }
+
+ // - Branches exist
+
+ return
+}
+
+func Story206Implement(st *SystemTest) (pass bool) {
+ // [should already be on correct branch]
+
+ // git am $PATH/xsa206-master/*.patch
+
+ out, err := G.repos.XenRepos[TreeXen].Am("../testdata/xsa206-unstable/*.patch")
+ if err != nil {
+ st.Errorf("Error importing example patches: %v %s\n", err, string(out))
+ return
+ }
+
+ return true
+}
+
+func Story206SyncOne(st *SystemTest) (pass bool) {
+ fmt.Printf(" xsatool 206 sync-patches")
+ if MainHarness("206", "sync-patches") != 0 {
+ st.Errorf("xsatool 206 sync-patches failed\n")
+ return false
+ }
+
+ var xsa XSAMeta
+
+ err := xsa.Load(206)
+ if err != nil {
+ st.Errorf("Error loading updated recipe: %v\n", err)
+ return false
+ }
+
+ pass = true
+
+ for v := range xsa.Recipes {
+ r := xsa.GetRecipe(v)
+ for tree := range r.Recipes {
+ tr := r.Recipes[tree]
+ expected := 0
+ if v == XenVersion("master") && tree == TreeXen {
+ expected = 1
+ }
+ if len(tr.Patches) != expected {
+ st.Errorf("Version %v tree %v: Wanted %d, got %d\n",
+ v, tree, expected, len(tr.Patches))
+ pass = false
+ }
+ }
+ }
+
+ return pass
+}
+
+func Story206(st *SystemTest) bool {
+ fmt.Printf("Starting XSA-206 'story'")
+ // xsatool 206 init xen
+ if !Story206Init(st) {
+ return false
+ }
+
+ // Fake-up xsa/206/master
+ if !Story206Implement(st) {
+ return false
+ }
+
+ // 206 sync-patches
+ if !Story206SyncOne(st) {
+ return false
+ }
+
+ // 206 Backport (should fail at 4.8. 4.7, and 4.6; NOT 4.5)
+
+ // 206 sync-patches
+
+ // 206 test
+
+ return true
+}
+
+func MainSystemTest() (ret int) {
+ var st SystemTest
+
+ // Fail unless we make it through the gauntlet
+ ret = 1
+
+ // Store the toplevel directory
+ topdir, err := os.Getwd()
+ if err != nil {
+ st.Errorf("Getwd failed?\n")
+ return
+ }
+
+ // Init and/or cd into the testing directory
+ if !InitRepo(&st) {
+ st.Errorf("Could not initialize repo")
+ goto out
+ }
+
+ // Initialize global state
+ // xsatool global update
+ if !GlobalInit(&st) {
+ goto out
+ }
+
+ //// xsa 206 "story"
+ if !Story206(&st) {
+ goto out
+ }
+
+ //// xsa 211 "story"
+
+ //// Drop 4.4 support, update to 4.8.1
+
+ //// xsa 212-215 "story"
+
+ ret = 0
+out:
+ os.Chdir(topdir)
+
+ if FullClone {
+ // rm -rf tmp
+ if err := os.RemoveAll("tmp"); err != nil {
+ st.Errorf("Removing temporary path: %v", err)
+ ret = 1
+ return
+ }
+ }
+
+ if st.failed {
+ fmt.Print("System test: FAILED\n")
+ } else {
+ fmt.Print("System test: PASSED\n")
+ }
+
+ return
+}