return an error instead of recording a test failure

Signed-off-by: carlory <baofa.fan@daocloud.io>
This commit is contained in:
carlory 2025-01-21 22:33:56 +08:00
parent aecf3238bf
commit c68fc01b77
6 changed files with 74 additions and 40 deletions

View File

@ -20,6 +20,7 @@ import (
"bytes"
"context"
"errors"
"fmt"
"io"
"net/url"
"strings"
@ -144,40 +145,40 @@ func ExecShellInPodWithFullOutput(ctx context.Context, f *framework.Framework, p
}
// VerifyExecInPodSucceed verifies shell cmd in target pod succeed
func VerifyExecInPodSucceed(ctx context.Context, f *framework.Framework, pod *v1.Pod, shExec string) {
func VerifyExecInPodSucceed(ctx context.Context, f *framework.Framework, pod *v1.Pod, shExec string) error {
stdout, stderr, err := ExecShellInPodWithFullOutput(ctx, f, pod.Name, shExec)
if err != nil {
var exitError clientexec.CodeExitError
if errors.As(err, &exitError) {
exitCode := exitError.ExitStatus()
framework.ExpectNoError(err,
"%q should succeed, but failed with exit code %d and error message %q\nstdout: %s\nstderr: %s",
return fmt.Errorf("%q should succeed, but failed with exit code %d and error message %w\nstdout: %s\nstderr: %s",
shExec, exitCode, exitError, stdout, stderr)
} else {
framework.ExpectNoError(err,
"%q should succeed, but failed with error message %q\nstdout: %s\nstderr: %s",
return fmt.Errorf("%q should succeed, but failed with error message %w\nstdout: %s\nstderr: %s",
shExec, err, stdout, stderr)
}
}
return nil
}
// VerifyExecInPodFail verifies shell cmd in target pod fail with certain exit code
func VerifyExecInPodFail(ctx context.Context, f *framework.Framework, pod *v1.Pod, shExec string, exitCode int) {
func VerifyExecInPodFail(ctx context.Context, f *framework.Framework, pod *v1.Pod, shExec string, exitCode int) error {
stdout, stderr, err := ExecShellInPodWithFullOutput(ctx, f, pod.Name, shExec)
if err != nil {
var exitError clientexec.CodeExitError
if errors.As(err, &exitError) {
actualExitCode := exitError.ExitStatus()
gomega.Expect(actualExitCode).To(gomega.Equal(exitCode),
"%q should fail with exit code %d, but failed with exit code %d and error message %q\nstdout: %s\nstderr: %s",
if actualExitCode == exitCode {
return nil
}
return fmt.Errorf("%q should fail with exit code %d, but failed with exit code %d and error message %w\nstdout: %s\nstderr: %s",
shExec, exitCode, actualExitCode, exitError, stdout, stderr)
} else {
framework.ExpectNoError(err,
"%q should fail with exit code %d, but failed with error message %q\nstdout: %s\nstderr: %s",
return fmt.Errorf("%q should fail with exit code %d, but failed with error message %w\nstdout: %s\nstderr: %s",
shExec, exitCode, err, stdout, stderr)
}
}
gomega.Expect(err).To(gomega.HaveOccurred(), "%q should fail with exit code %d, but exit without error", shExec, exitCode)
return fmt.Errorf("%q should fail with exit code %d, but exit without error", shExec, exitCode)
}
func execute(ctx context.Context, method string, url *url.URL, config *restclient.Config, stdin io.Reader, stdout, stderr io.Writer, tty bool) error {

View File

@ -510,7 +510,8 @@ func testVolumeContent(ctx context.Context, f *framework.Framework, pod *v1.Pod,
framework.ExpectNoError(err, "failed: finding the contents of the block device %s.", deviceName)
// Check that it's a real block device
CheckVolumeModeOfPath(ctx, f, pod, test.Mode, deviceName)
err = CheckVolumeModeOfPath(ctx, f, pod, test.Mode, deviceName)
framework.ExpectNoError(err, "failed: getting the right privileges in the block device %v", deviceName)
} else {
// Filesystem: check content
fileName := fmt.Sprintf("/opt/%d/%s", i, test.File)
@ -520,7 +521,8 @@ func testVolumeContent(ctx context.Context, f *framework.Framework, pod *v1.Pod,
// Check that a directory has been mounted
dirName := filepath.Dir(fileName)
CheckVolumeModeOfPath(ctx, f, pod, test.Mode, dirName)
err = CheckVolumeModeOfPath(ctx, f, pod, test.Mode, dirName)
framework.ExpectNoError(err, "failed: getting the right privileges in the directory %v", dirName)
if !framework.NodeOSDistroIs("windows") {
// Filesystem: check fsgroup
@ -663,18 +665,27 @@ func generateWriteFileCmd(content, fullPath string) []string {
}
// CheckVolumeModeOfPath check mode of volume
func CheckVolumeModeOfPath(ctx context.Context, f *framework.Framework, pod *v1.Pod, volMode v1.PersistentVolumeMode, path string) {
func CheckVolumeModeOfPath(ctx context.Context, f *framework.Framework, pod *v1.Pod, volMode v1.PersistentVolumeMode, path string) error {
if volMode == v1.PersistentVolumeBlock {
// Check if block exists
e2epod.VerifyExecInPodSucceed(ctx, f, pod, fmt.Sprintf("test -b %s", path))
if err := e2epod.VerifyExecInPodSucceed(ctx, f, pod, fmt.Sprintf("test -b %s", path)); err != nil {
return err
}
// Double check that it's not directory
e2epod.VerifyExecInPodFail(ctx, f, pod, fmt.Sprintf("test -d %s", path), 1)
if err := e2epod.VerifyExecInPodFail(ctx, f, pod, fmt.Sprintf("test -d %s", path), 1); err != nil {
return err
}
} else {
// Check if directory exists
e2epod.VerifyExecInPodSucceed(ctx, f, pod, fmt.Sprintf("test -d %s", path))
if err := e2epod.VerifyExecInPodSucceed(ctx, f, pod, fmt.Sprintf("test -d %s", path)); err != nil {
return err
}
// Double check that it's not block
e2epod.VerifyExecInPodFail(ctx, f, pod, fmt.Sprintf("test -b %s", path), 1)
if err := e2epod.VerifyExecInPodFail(ctx, f, pod, fmt.Sprintf("test -b %s", path), 1); err != nil {
return err
}
}
return nil
}

View File

@ -194,7 +194,8 @@ func (p *ephemeralTestSuite) DefineTests(driver storageframework.TestDriver, pat
// attempt to create a dummy file and expect for it not to be created
command = "ls /mnt/test* && (touch /mnt/test-0/hello-world || true) && [ ! -f /mnt/test-0/hello-world ]"
}
e2epod.VerifyExecInPodSucceed(ctx, f, pod, command)
err := e2epod.VerifyExecInPodSucceed(ctx, f, pod, command)
framework.ExpectNoError(err, "while checking read-only mount")
return nil
}
l.testCase.TestEphemeral(ctx)
@ -214,7 +215,8 @@ func (p *ephemeralTestSuite) DefineTests(driver storageframework.TestDriver, pat
if pattern.VolMode == v1.PersistentVolumeBlock {
command = "if ! [ -b /mnt/test-0 ]; then echo /mnt/test-0 is not a block device; exit 1; fi"
}
e2epod.VerifyExecInPodSucceed(ctx, f, pod, command)
err := e2epod.VerifyExecInPodSucceed(ctx, f, pod, command)
framework.ExpectNoError(err, "while checking read/write mount")
return nil
}
l.testCase.TestEphemeral(ctx)
@ -308,8 +310,10 @@ func (p *ephemeralTestSuite) DefineTests(driver storageframework.TestDriver, pat
// visible in the other.
if pattern.VolMode != v1.PersistentVolumeBlock && !readOnly && !shared {
ginkgo.By("writing data in one pod and checking the second does not see it (it should get its own volume)")
e2epod.VerifyExecInPodSucceed(ctx, f, pod, "touch /mnt/test-0/hello-world")
e2epod.VerifyExecInPodSucceed(ctx, f, pod2, "[ ! -f /mnt/test-0/hello-world ]")
err := e2epod.VerifyExecInPodSucceed(ctx, f, pod, "touch /mnt/test-0/hello-world")
framework.ExpectNoError(err, "while writing data in first pod")
err = e2epod.VerifyExecInPodSucceed(ctx, f, pod2, "[ ! -f /mnt/test-0/hello-world ]")
framework.ExpectNoError(err, "while checking data in second pod")
}
// TestEphemeral expects the pod to be fully deleted

View File

@ -499,7 +499,8 @@ func testAccessMultipleVolumes(ctx context.Context, f *framework.Framework, cs c
index := i + 1
path := fmt.Sprintf("/mnt/volume%d", index)
ginkgo.By(fmt.Sprintf("Checking if the volume%d exists as expected volume mode (%s)", index, *pvc.Spec.VolumeMode))
e2evolume.CheckVolumeModeOfPath(ctx, f, pod, *pvc.Spec.VolumeMode, path)
err = e2evolume.CheckVolumeModeOfPath(ctx, f, pod, *pvc.Spec.VolumeMode, path)
framework.ExpectNoError(err)
if readSeedBase > 0 {
ginkgo.By(fmt.Sprintf("Checking if read from the volume%d works properly", index))
@ -607,7 +608,8 @@ func TestConcurrentAccessToSingleVolume(ctx context.Context, f *framework.Framew
for i, pod := range pods {
index := i + 1
ginkgo.By(fmt.Sprintf("Checking if the volume in pod%d exists as expected volume mode (%s)", index, *pvc.Spec.VolumeMode))
e2evolume.CheckVolumeModeOfPath(ctx, f, pod, *pvc.Spec.VolumeMode, path)
err := e2evolume.CheckVolumeModeOfPath(ctx, f, pod, *pvc.Spec.VolumeMode, path)
framework.ExpectNoError(err)
if readOnly {
ginkgo.By("Skipping volume content checks, volume is read-only")
@ -643,7 +645,8 @@ func TestConcurrentAccessToSingleVolume(ctx context.Context, f *framework.Framew
index := i + 1
// index of pod and index of pvc match, because pods are created above way
ginkgo.By(fmt.Sprintf("Rechecking if the volume in pod%d exists as expected volume mode (%s)", index, *pvc.Spec.VolumeMode))
e2evolume.CheckVolumeModeOfPath(ctx, f, pod, *pvc.Spec.VolumeMode, "/mnt/volume1")
err := e2evolume.CheckVolumeModeOfPath(ctx, f, pod, *pvc.Spec.VolumeMode, "/mnt/volume1")
framework.ExpectNoError(err)
if readOnly {
ginkgo.By("Skipping volume content checks, volume is read-only")

View File

@ -449,25 +449,34 @@ func isSudoPresent(ctx context.Context, nodeIP string, provider string) bool {
func CheckReadWriteToPath(ctx context.Context, f *framework.Framework, pod *v1.Pod, volMode v1.PersistentVolumeMode, path string) {
if volMode == v1.PersistentVolumeBlock {
// random -> file1
e2epod.VerifyExecInPodSucceed(ctx, f, pod, "dd if=/dev/urandom of=/tmp/file1 bs=64 count=1")
err := e2epod.VerifyExecInPodSucceed(ctx, f, pod, "dd if=/dev/urandom of=/tmp/file1 bs=64 count=1")
framework.ExpectNoError(err, "Failed to write to file1")
// file1 -> dev (write to dev)
e2epod.VerifyExecInPodSucceed(ctx, f, pod, fmt.Sprintf("dd if=/tmp/file1 of=%s bs=64 count=1", path))
err = e2epod.VerifyExecInPodSucceed(ctx, f, pod, fmt.Sprintf("dd if=/tmp/file1 of=%s bs=64 count=1", path))
framework.ExpectNoError(err, "Failed to write to block volume")
// dev -> file2 (read from dev)
e2epod.VerifyExecInPodSucceed(ctx, f, pod, fmt.Sprintf("dd if=%s of=/tmp/file2 bs=64 count=1", path))
err = e2epod.VerifyExecInPodSucceed(ctx, f, pod, fmt.Sprintf("dd if=%s of=/tmp/file2 bs=64 count=1", path))
framework.ExpectNoError(err, "Failed to read from block volume")
// file1 == file2 (check contents)
e2epod.VerifyExecInPodSucceed(ctx, f, pod, "diff /tmp/file1 /tmp/file2")
err = e2epod.VerifyExecInPodSucceed(ctx, f, pod, "diff /tmp/file1 /tmp/file2")
framework.ExpectNoError(err, "Failed to compare file1 and file2")
// Clean up temp files
e2epod.VerifyExecInPodSucceed(ctx, f, pod, "rm -f /tmp/file1 /tmp/file2")
err = e2epod.VerifyExecInPodSucceed(ctx, f, pod, "rm -f /tmp/file1 /tmp/file2")
framework.ExpectNoError(err, "Failed to clean up temp files")
// Check that writing file to block volume fails
e2epod.VerifyExecInPodFail(ctx, f, pod, fmt.Sprintf("echo 'Hello world.' > %s/file1.txt", path), 1)
err = e2epod.VerifyExecInPodFail(ctx, f, pod, fmt.Sprintf("echo 'Hello world.' > %s/file1.txt", path), 1)
framework.ExpectNoError(err, "Expected write to block volume to fail")
} else {
// text -> file1 (write to file)
e2epod.VerifyExecInPodSucceed(ctx, f, pod, fmt.Sprintf("echo 'Hello world.' > %s/file1.txt", path))
err := e2epod.VerifyExecInPodSucceed(ctx, f, pod, fmt.Sprintf("echo 'Hello world.' > %s/file1.txt", path))
framework.ExpectNoError(err, "Failed to write to file1")
// grep file1 (read from file and check contents)
e2epod.VerifyExecInPodSucceed(ctx, f, pod, readFile("Hello word.", path))
err = e2epod.VerifyExecInPodSucceed(ctx, f, pod, readFile("Hello word.", path))
framework.ExpectNoError(err, "Failed to read from file1")
// Check that writing to directory as block volume fails
e2epod.VerifyExecInPodFail(ctx, f, pod, fmt.Sprintf("dd if=/dev/urandom of=%s bs=64 count=1", path), 1)
err = e2epod.VerifyExecInPodFail(ctx, f, pod, fmt.Sprintf("dd if=/dev/urandom of=%s bs=64 count=1", path), 1)
framework.ExpectNoError(err, "Expected write to directory to fail")
}
}
@ -513,8 +522,10 @@ func CheckReadFromPath(ctx context.Context, f *framework.Framework, pod *v1.Pod,
sum := sha256.Sum256(genBinDataFromSeed(len, seed))
e2epod.VerifyExecInPodSucceed(ctx, f, pod, fmt.Sprintf("dd if=%s %s bs=%d count=1 | sha256sum", pathForVolMode, iflag, len))
e2epod.VerifyExecInPodSucceed(ctx, f, pod, fmt.Sprintf("dd if=%s %s bs=%d count=1 | sha256sum | grep -Fq %x", pathForVolMode, iflag, len, sum))
err := e2epod.VerifyExecInPodSucceed(ctx, f, pod, fmt.Sprintf("dd if=%s %s bs=%d count=1 | sha256sum", pathForVolMode, iflag, len))
framework.ExpectNoError(err, "Failed to read from %s", pathForVolMode)
err = e2epod.VerifyExecInPodSucceed(ctx, f, pod, fmt.Sprintf("dd if=%s %s bs=%d count=1 | sha256sum | grep -Fq %x", pathForVolMode, iflag, len, sum))
framework.ExpectNoError(err, "Failed to read from %s", pathForVolMode)
}
// CheckWriteToPath that file can be properly written.
@ -538,8 +549,10 @@ func CheckWriteToPath(ctx context.Context, f *framework.Framework, pod *v1.Pod,
encoded := base64.StdEncoding.EncodeToString(genBinDataFromSeed(len, seed))
e2epod.VerifyExecInPodSucceed(ctx, f, pod, fmt.Sprintf("echo %s | base64 -d | sha256sum", encoded))
e2epod.VerifyExecInPodSucceed(ctx, f, pod, fmt.Sprintf("echo %s | base64 -d | dd of=%s %s bs=%d count=1", encoded, pathForVolMode, oflag, len))
err := e2epod.VerifyExecInPodSucceed(ctx, f, pod, fmt.Sprintf("echo %s | base64 -d | sha256sum", encoded))
framework.ExpectNoError(err, "Failed to generate sha256sum of encoded data")
err = e2epod.VerifyExecInPodSucceed(ctx, f, pod, fmt.Sprintf("echo %s | base64 -d | dd of=%s %s bs=%d count=1", encoded, pathForVolMode, oflag, len))
framework.ExpectNoError(err, "Failed to write to %s", pathForVolMode)
}
// GetSectorSize returns the sector size of the device.

View File

@ -105,7 +105,8 @@ func (t *VolumeModeDowngradeTest) Setup(ctx context.Context, f *framework.Framew
framework.ExpectNoError(err)
ginkgo.By("Checking if PV exists as expected volume mode")
e2evolume.CheckVolumeModeOfPath(ctx, f, t.pod, block, devicePath)
err = e2evolume.CheckVolumeModeOfPath(ctx, f, t.pod, block, devicePath)
framework.ExpectNoError(err)
ginkgo.By("Checking if read/write to PV works properly")
storageutils.CheckReadWriteToPath(ctx, f, t.pod, block, devicePath)
@ -118,7 +119,8 @@ func (t *VolumeModeDowngradeTest) Test(ctx context.Context, f *framework.Framewo
<-done
ginkgo.By("Verifying that nothing exists at the device path in the pod")
e2epod.VerifyExecInPodFail(ctx, f, t.pod, fmt.Sprintf("test -e %s", devicePath), 1)
err := e2epod.VerifyExecInPodFail(ctx, f, t.pod, fmt.Sprintf("test -e %s", devicePath), 1)
framework.ExpectNoError(err)
}
// Teardown cleans up any remaining resources.