mirror of
https://github.com/SCST-project/scst.git
synced 2026-10-22 14:12:33 +00:00
Add shared sg3_utils scenarios for scst_local and iSCSI exports: inquiry and VPD identity, capacity, LUN visibility, write protection and invalid LBA handling. Require the expected SCSI status and raw sense for rejected commands, then verify that valid reads still work. Use temporary fileio backends with 512-byte sectors. Keep fixture identifiers within vdisk's 20-character USN limit. Match each exported device to its fixture by identity and geometry before submitting commands. Carry binary responses over the existing supervised command transports and retain fixture ownership through successful cleanup. Add framework checks for response parsing, device selection and command interruption. Document tool prerequisites and the scsi label for both transports through the common Make targets.
55 lines
1.8 KiB
Go
55 lines
1.8 KiB
Go
// SPDX-License-Identifier: GPL-2.0-only
|
|
package dataio
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"os/exec"
|
|
"testing"
|
|
"time"
|
|
|
|
"scst-component-tests/internal/admin"
|
|
)
|
|
|
|
func TestBinaryCommandPreservesOutputAndExit(t *testing.T) {
|
|
if _, err := exec.LookPath("python3"); err != nil {
|
|
t.Skip("python3 not available")
|
|
}
|
|
run := func(ctx context.Context, _ time.Duration, argv ...string) (admin.Result, error) {
|
|
out, err := exec.CommandContext(ctx, argv[0], argv[1:]...).Output()
|
|
return admin.Result{Stdout: string(out)}, err
|
|
}
|
|
payload := []byte{0, 0xff, 0x80, '\n'}
|
|
r, err := command(context.Background(), run, time.Second, payload, "python3", "-c",
|
|
"import sys; sys.stdout.buffer.write(sys.stdin.buffer.read()); sys.stderr.write('sense'); sys.exit(7)")
|
|
if err != nil || r.ExitCode != 7 || r.Stderr != "sense" || !bytes.Equal(r.Data, payload) {
|
|
t.Fatalf("binary response: %+v %v", r, err)
|
|
}
|
|
for _, output := range []string{"null", "{}", `{"exit_code":0,"stderr":""}`} {
|
|
fake := func(context.Context, time.Duration, ...string) (admin.Result, error) {
|
|
return admin.Result{Stdout: output}, nil
|
|
}
|
|
if _, err := command(context.Background(), fake, time.Second, nil, "unused"); err == nil {
|
|
t.Fatal("accepted missing reply")
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestChildInterruptionBlocksFurtherCommands(t *testing.T) {
|
|
if _, err := exec.LookPath("python3"); err != nil {
|
|
t.Skip("python3 not available")
|
|
}
|
|
for name, script := range map[string]string{
|
|
"signal": "import os,signal; os.kill(os.getpid(), signal.SIGTERM)",
|
|
"timeout": "import time; time.sleep(5)",
|
|
} {
|
|
t.Run(name, func(t *testing.T) {
|
|
client := &admin.Client{}
|
|
_, err := command(context.Background(), client.RunProgram, 500*time.Millisecond, nil, "python3", "-c", script)
|
|
if err == nil || client.Blocked() == nil {
|
|
t.Fatalf("lost supervision failure: %v, latch %v", err, client.Blocked())
|
|
}
|
|
})
|
|
}
|
|
}
|