testmark-go

testexec: the "then-*" feature.

commit aa3d1eab87c123e67afc9731e895c384aa12b486 · parent a217051880 · browse this tree
Eric Myhre, 2021-10-21 18:04:55 UTC

Not yet tested.
diff --git a/testexec/testexec.go b/testexec/testexec.go
index f59ddb2..4e13da0 100644
--- a/testexec/testexec.go
+++ b/testexec/testexec.go
@@ -141,20 +141,20 @@ func (tcfg *Tester) init() {
 // the test will still be failed, even though in patch regen mode most assertions are usually skipped.
 func (tcfg Tester) TestSequence(t *testing.T, data testmark.DirEnt) {
 	t.Helper()
-	tcfg.test(t, data, true, false)
+	tcfg.test(t, data, true, false, "")
 }
 
 func (tcfg Tester) TestScript(t *testing.T, data testmark.DirEnt) {
 	t.Helper()
-	tcfg.test(t, data, false, true)
+	tcfg.test(t, data, false, true, "")
 }
 
 func (tcfg Tester) Test(t *testing.T, data testmark.DirEnt) {
 	t.Helper()
-	tcfg.test(t, data, true, true)
+	tcfg.test(t, data, true, true, "")
 }
 
-func (tcfg Tester) test(t *testing.T, data testmark.DirEnt, allowExec, allowScript bool) {
+func (tcfg Tester) test(t *testing.T, data testmark.DirEnt, allowExec, allowScript bool, parentTmpdir string) {
 	t.Helper()
 	tcfg.init()
 
@@ -179,9 +179,11 @@ func (tcfg Tester) test(t *testing.T, data testmark.DirEnt, allowExec, allowScri
 	}
 
 	// Create a tempdir, and fill it with any files.
-	if fsEnt, exists := data.Children["fs"]; exists {
+	var dir string
+	if fsEnt, exists := data.Children["fs"]; exists || parentTmpdir != "" {
 		// Create and get into a tempdir.
-		dir, err := ioutil.TempDir("", "testmarkexec")
+		var err error
+		dir, err = ioutil.TempDir("", "testmarkexec")
 		if err != nil {
 			t.Errorf("test aborted: could not create tempdir: %s", err)
 		}
@@ -195,7 +197,14 @@ func (tcfg Tester) test(t *testing.T, data testmark.DirEnt, allowExec, allowScri
 			t.Errorf("test aborted: could not chdir to tempdir: %s", err)
 		}
 
-		// Create files.
+		// If there was a parent tempdir: copy those files first.
+		if parentTmpdir != "" {
+			if err := copyFiles(parentTmpdir, dir); err != nil {
+				t.Errorf("test aborted: could not populate files to tempdir: %s", err)
+			}
+		}
+
+		// Create any new files.
 		if err := createFiles(fsEnt, "."); err != nil {
 			t.Errorf("test aborted: could not populate files to tempdir: %s", err)
 		}
@@ -273,7 +282,20 @@ func (tcfg Tester) test(t *testing.T, data testmark.DirEnt, allowExec, allowScri
 		}
 	})
 
-	// TODO: look for "then-*" dirs.
+	// Look for "then-*" dirs.
+	//  If we're already failed -- make the run block, but skip it.
+	//  If we're going to procede: make a new tempdir, copy the contents, and then procede by recursing.
+	for _, child := range data.ChildrenList {
+		if len(child.Name) > 5 && strings.HasPrefix(child.Name, "then-") {
+			alreadyFailed := t.Failed()
+			t.Run(child.Name, func(t *testing.T) {
+				if alreadyFailed {
+					t.Skipf("parent commands failed, so while more commands are specified, testing them is not meaningful")
+				}
+				tcfg.test(t, child, allowExec, allowScript, dir)
+			})
+		}
+	}
 
 }
 
@@ -326,3 +348,39 @@ func createFiles(dir *testmark.DirEnt, prefix string) error {
 	}
 	return nil
 }
+
+// copyFiles does what it says on the tin, recursively,
+// and handles dirs, files, and symlinks, with basic posix perms (the 0777 bits).
+// It doesn't pay attention to dev nodes, uid/gid, etc etc.
+func copyFiles(source, destination string) error {
+	var err error = filepath.Walk(source, func(path string, fileInfo os.FileInfo, err error) error {
+		var relPath string = strings.Replace(path, source, "", 1)
+		if relPath == "" {
+			return nil
+		}
+		switch fileInfo.Mode() & os.ModeType {
+		case os.ModeDir:
+			return os.Mkdir(filepath.Join(destination, relPath), fileInfo.Mode())
+		case os.ModeSymlink:
+			link, err := os.Readlink(path)
+			if err != nil {
+				return err
+			}
+			return os.Symlink(link, filepath.Join(destination, relPath))
+		default:
+			fnew, err := os.OpenFile(filepath.Join(destination, relPath), os.O_CREATE|os.O_WRONLY|os.O_TRUNC, fileInfo.Mode())
+			if err != nil {
+				return err
+			}
+			defer fnew.Close()
+			fold, err := os.OpenFile(path, os.O_RDONLY, 0)
+			if err != nil {
+				return err
+			}
+			defer fold.Close()
+			_, err = io.Copy(fnew, fold)
+			return err
+		}
+	})
+	return err
+}