zrepl/zfs/versions_destroy_test.go

297 lines
7.3 KiB
Go
Raw Normal View History

package zfs
import (
"bytes"
"context"
"fmt"
"os"
"os/exec"
zfs: fix batch destroy panic if all snaps are undestroyable See https://github.com/zrepl/zrepl/pull/259#issuecomment-585334023 panic: runtime error: index out of range [0] with length 0 goroutine 14 [running]: github.com/zrepl/zrepl/zfs.tryBatch(0xd6aa20, 0xc0000b8018, 0xc00025e0c0, 0x0, 0x6, 0xd61d80, 0x1280df8, 0xd58920, 0xc000132000) zrepl/zfs/versions_destroy.go:129 +0x302 github.com/zrepl/zrepl/zfs.doDestroyBatchedRec(0xd6aa20, 0xc0000b8018, 0xc000578a80, 0x6, 0x6, 0xd61d80, 0x1280df8) zrepl/zfs/versions_destroy.go:184 +0x4a5 github.com/zrepl/zrepl/zfs.doDestroyBatched(0xd6aa20, 0xc0000b8018, 0xc000222780, 0x6, 0x8, 0xd61d80, 0x1280df8) zrepl/zfs/versions_destroy.go:95 +0xc7 github.com/zrepl/zrepl/zfs.doDestroy(0xd6aa20, 0xc0000b8018, 0xc0005788d0, 0x6, 0x6, 0xd61d80, 0x1280df8) zrepl/zfs/versions_destroy.go:82 +0x362 github.com/zrepl/zrepl/zfs.ZFSDestroyFilesystemVersions(...) zrepl/zfs/versions_destroy.go:41 github.com/zrepl/zrepl/endpoint.doDestroySnapshots(0xd6aaa0, 0xc0004412c0, 0xc00057ca00, 0xc0005785a0, 0x6, 0x6, 0xb68940, 0xc5df01, 0xc000150a80) zrepl/endpoint/endpoint.go:785 +0x388 github.com/zrepl/zrepl/endpoint.(*Receiver).DestroySnapshots(0xc000127500, 0xd6aaa0, 0xc0004412c0, 0xc0002ca280, 0xc000150880, 0xd73ca0, 0xc00057c960) zrepl/endpoint/endpoint.go:751 +0xdb github.com/zrepl/zrepl/daemon/pruner.doOneAttemptExec(0xc000429980, 0xc000429958, 0xc0001cb180) zrepl/daemon/pruner/pruner.go:531 +0x51f github.com/zrepl/zrepl/daemon/pruner.doOneAttempt(0xc000429980, 0xc000429958) zrepl/daemon/pruner/pruner.go:486 +0x1064 github.com/zrepl/zrepl/daemon/pruner.(*Pruner).prune(0xc00011e280, 0xd6aaa0, 0xc0004412c0, 0x7f4906fff7e8, 0xc000127500, 0x7f4906fff738, 0xc0001324e0, 0xc000064420, 0x1, 0x1, ...) zrepl/daemon/pruner/pruner.go:214 +0x53 github.com/zrepl/zrepl/daemon/pruner.(*Pruner).Prune(...) zrepl/daemon/pruner/pruner.go:200 github.com/zrepl/zrepl/daemon/job.(*ActiveSide).do(0xc000268000, 0xd6a9e0, 0xc0002223c0) zrepl/daemon/job/active.go:482 +0x906 github.com/zrepl/zrepl/daemon/job.(*ActiveSide).Run(0xc000268000, 0xd6aaa0, 0xc000127080) zrepl/daemon/job/active.go:404 +0x289 github.com/zrepl/zrepl/daemon.(*jobs).start.func1(0xc000032200, 0xd73ca0, 0xc00000f2e0, 0xd6efa0, 0xc000268000, 0xd6aaa0, 0xc000126c90) zrepl/daemon/daemon.go:220 +0x121 created by github.com/zrepl/zrepl/daemon.(*jobs).start zrepl/daemon/daemon.go:216 +0x52e
2020-02-14 21:34:22 +01:00
"regexp"
"strings"
"syscall"
"testing"
"github.com/stretchr/testify/assert"
"github.com/zrepl/zrepl/util/chainlock"
)
type mockBatchDestroy struct {
mtx chainlock.L
calls []string
commaUnsupported bool
zfs: fix batch destroy panic if all snaps are undestroyable See https://github.com/zrepl/zrepl/pull/259#issuecomment-585334023 panic: runtime error: index out of range [0] with length 0 goroutine 14 [running]: github.com/zrepl/zrepl/zfs.tryBatch(0xd6aa20, 0xc0000b8018, 0xc00025e0c0, 0x0, 0x6, 0xd61d80, 0x1280df8, 0xd58920, 0xc000132000) zrepl/zfs/versions_destroy.go:129 +0x302 github.com/zrepl/zrepl/zfs.doDestroyBatchedRec(0xd6aa20, 0xc0000b8018, 0xc000578a80, 0x6, 0x6, 0xd61d80, 0x1280df8) zrepl/zfs/versions_destroy.go:184 +0x4a5 github.com/zrepl/zrepl/zfs.doDestroyBatched(0xd6aa20, 0xc0000b8018, 0xc000222780, 0x6, 0x8, 0xd61d80, 0x1280df8) zrepl/zfs/versions_destroy.go:95 +0xc7 github.com/zrepl/zrepl/zfs.doDestroy(0xd6aa20, 0xc0000b8018, 0xc0005788d0, 0x6, 0x6, 0xd61d80, 0x1280df8) zrepl/zfs/versions_destroy.go:82 +0x362 github.com/zrepl/zrepl/zfs.ZFSDestroyFilesystemVersions(...) zrepl/zfs/versions_destroy.go:41 github.com/zrepl/zrepl/endpoint.doDestroySnapshots(0xd6aaa0, 0xc0004412c0, 0xc00057ca00, 0xc0005785a0, 0x6, 0x6, 0xb68940, 0xc5df01, 0xc000150a80) zrepl/endpoint/endpoint.go:785 +0x388 github.com/zrepl/zrepl/endpoint.(*Receiver).DestroySnapshots(0xc000127500, 0xd6aaa0, 0xc0004412c0, 0xc0002ca280, 0xc000150880, 0xd73ca0, 0xc00057c960) zrepl/endpoint/endpoint.go:751 +0xdb github.com/zrepl/zrepl/daemon/pruner.doOneAttemptExec(0xc000429980, 0xc000429958, 0xc0001cb180) zrepl/daemon/pruner/pruner.go:531 +0x51f github.com/zrepl/zrepl/daemon/pruner.doOneAttempt(0xc000429980, 0xc000429958) zrepl/daemon/pruner/pruner.go:486 +0x1064 github.com/zrepl/zrepl/daemon/pruner.(*Pruner).prune(0xc00011e280, 0xd6aaa0, 0xc0004412c0, 0x7f4906fff7e8, 0xc000127500, 0x7f4906fff738, 0xc0001324e0, 0xc000064420, 0x1, 0x1, ...) zrepl/daemon/pruner/pruner.go:214 +0x53 github.com/zrepl/zrepl/daemon/pruner.(*Pruner).Prune(...) zrepl/daemon/pruner/pruner.go:200 github.com/zrepl/zrepl/daemon/job.(*ActiveSide).do(0xc000268000, 0xd6a9e0, 0xc0002223c0) zrepl/daemon/job/active.go:482 +0x906 github.com/zrepl/zrepl/daemon/job.(*ActiveSide).Run(0xc000268000, 0xd6aaa0, 0xc000127080) zrepl/daemon/job/active.go:404 +0x289 github.com/zrepl/zrepl/daemon.(*jobs).start.func1(0xc000032200, 0xd73ca0, 0xc00000f2e0, 0xd6efa0, 0xc000268000, 0xd6aaa0, 0xc000126c90) zrepl/daemon/daemon.go:220 +0x121 created by github.com/zrepl/zrepl/daemon.(*jobs).start zrepl/daemon/daemon.go:216 +0x52e
2020-02-14 21:34:22 +01:00
undestroyable *regexp.Regexp
randomerror string
e2biglen int
}
func (m *mockBatchDestroy) DestroySnapshotsCommaSyntaxSupported() (bool, error) {
return !m.commaUnsupported, nil
}
func (m *mockBatchDestroy) Destroy(args []string) error {
defer m.mtx.Lock().Unlock()
if len(args) != 1 {
panic("unexpected use of Destroy")
}
a := args[0]
if m.e2biglen > 0 && len(a) > m.e2biglen {
return &os.PathError{Err: syscall.E2BIG} // TestExcessiveArgumentsResultInE2BIG checks that this errors is produced
}
m.calls = append(m.calls, a)
zfs: fix batch destroy panic if all snaps are undestroyable See https://github.com/zrepl/zrepl/pull/259#issuecomment-585334023 panic: runtime error: index out of range [0] with length 0 goroutine 14 [running]: github.com/zrepl/zrepl/zfs.tryBatch(0xd6aa20, 0xc0000b8018, 0xc00025e0c0, 0x0, 0x6, 0xd61d80, 0x1280df8, 0xd58920, 0xc000132000) zrepl/zfs/versions_destroy.go:129 +0x302 github.com/zrepl/zrepl/zfs.doDestroyBatchedRec(0xd6aa20, 0xc0000b8018, 0xc000578a80, 0x6, 0x6, 0xd61d80, 0x1280df8) zrepl/zfs/versions_destroy.go:184 +0x4a5 github.com/zrepl/zrepl/zfs.doDestroyBatched(0xd6aa20, 0xc0000b8018, 0xc000222780, 0x6, 0x8, 0xd61d80, 0x1280df8) zrepl/zfs/versions_destroy.go:95 +0xc7 github.com/zrepl/zrepl/zfs.doDestroy(0xd6aa20, 0xc0000b8018, 0xc0005788d0, 0x6, 0x6, 0xd61d80, 0x1280df8) zrepl/zfs/versions_destroy.go:82 +0x362 github.com/zrepl/zrepl/zfs.ZFSDestroyFilesystemVersions(...) zrepl/zfs/versions_destroy.go:41 github.com/zrepl/zrepl/endpoint.doDestroySnapshots(0xd6aaa0, 0xc0004412c0, 0xc00057ca00, 0xc0005785a0, 0x6, 0x6, 0xb68940, 0xc5df01, 0xc000150a80) zrepl/endpoint/endpoint.go:785 +0x388 github.com/zrepl/zrepl/endpoint.(*Receiver).DestroySnapshots(0xc000127500, 0xd6aaa0, 0xc0004412c0, 0xc0002ca280, 0xc000150880, 0xd73ca0, 0xc00057c960) zrepl/endpoint/endpoint.go:751 +0xdb github.com/zrepl/zrepl/daemon/pruner.doOneAttemptExec(0xc000429980, 0xc000429958, 0xc0001cb180) zrepl/daemon/pruner/pruner.go:531 +0x51f github.com/zrepl/zrepl/daemon/pruner.doOneAttempt(0xc000429980, 0xc000429958) zrepl/daemon/pruner/pruner.go:486 +0x1064 github.com/zrepl/zrepl/daemon/pruner.(*Pruner).prune(0xc00011e280, 0xd6aaa0, 0xc0004412c0, 0x7f4906fff7e8, 0xc000127500, 0x7f4906fff738, 0xc0001324e0, 0xc000064420, 0x1, 0x1, ...) zrepl/daemon/pruner/pruner.go:214 +0x53 github.com/zrepl/zrepl/daemon/pruner.(*Pruner).Prune(...) zrepl/daemon/pruner/pruner.go:200 github.com/zrepl/zrepl/daemon/job.(*ActiveSide).do(0xc000268000, 0xd6a9e0, 0xc0002223c0) zrepl/daemon/job/active.go:482 +0x906 github.com/zrepl/zrepl/daemon/job.(*ActiveSide).Run(0xc000268000, 0xd6aaa0, 0xc000127080) zrepl/daemon/job/active.go:404 +0x289 github.com/zrepl/zrepl/daemon.(*jobs).start.func1(0xc000032200, 0xd73ca0, 0xc00000f2e0, 0xd6efa0, 0xc000268000, 0xd6aaa0, 0xc000126c90) zrepl/daemon/daemon.go:220 +0x121 created by github.com/zrepl/zrepl/daemon.(*jobs).start zrepl/daemon/daemon.go:216 +0x52e
2020-02-14 21:34:22 +01:00
var snapnames []string
if m.commaUnsupported {
zfs: fix batch destroy panic if all snaps are undestroyable See https://github.com/zrepl/zrepl/pull/259#issuecomment-585334023 panic: runtime error: index out of range [0] with length 0 goroutine 14 [running]: github.com/zrepl/zrepl/zfs.tryBatch(0xd6aa20, 0xc0000b8018, 0xc00025e0c0, 0x0, 0x6, 0xd61d80, 0x1280df8, 0xd58920, 0xc000132000) zrepl/zfs/versions_destroy.go:129 +0x302 github.com/zrepl/zrepl/zfs.doDestroyBatchedRec(0xd6aa20, 0xc0000b8018, 0xc000578a80, 0x6, 0x6, 0xd61d80, 0x1280df8) zrepl/zfs/versions_destroy.go:184 +0x4a5 github.com/zrepl/zrepl/zfs.doDestroyBatched(0xd6aa20, 0xc0000b8018, 0xc000222780, 0x6, 0x8, 0xd61d80, 0x1280df8) zrepl/zfs/versions_destroy.go:95 +0xc7 github.com/zrepl/zrepl/zfs.doDestroy(0xd6aa20, 0xc0000b8018, 0xc0005788d0, 0x6, 0x6, 0xd61d80, 0x1280df8) zrepl/zfs/versions_destroy.go:82 +0x362 github.com/zrepl/zrepl/zfs.ZFSDestroyFilesystemVersions(...) zrepl/zfs/versions_destroy.go:41 github.com/zrepl/zrepl/endpoint.doDestroySnapshots(0xd6aaa0, 0xc0004412c0, 0xc00057ca00, 0xc0005785a0, 0x6, 0x6, 0xb68940, 0xc5df01, 0xc000150a80) zrepl/endpoint/endpoint.go:785 +0x388 github.com/zrepl/zrepl/endpoint.(*Receiver).DestroySnapshots(0xc000127500, 0xd6aaa0, 0xc0004412c0, 0xc0002ca280, 0xc000150880, 0xd73ca0, 0xc00057c960) zrepl/endpoint/endpoint.go:751 +0xdb github.com/zrepl/zrepl/daemon/pruner.doOneAttemptExec(0xc000429980, 0xc000429958, 0xc0001cb180) zrepl/daemon/pruner/pruner.go:531 +0x51f github.com/zrepl/zrepl/daemon/pruner.doOneAttempt(0xc000429980, 0xc000429958) zrepl/daemon/pruner/pruner.go:486 +0x1064 github.com/zrepl/zrepl/daemon/pruner.(*Pruner).prune(0xc00011e280, 0xd6aaa0, 0xc0004412c0, 0x7f4906fff7e8, 0xc000127500, 0x7f4906fff738, 0xc0001324e0, 0xc000064420, 0x1, 0x1, ...) zrepl/daemon/pruner/pruner.go:214 +0x53 github.com/zrepl/zrepl/daemon/pruner.(*Pruner).Prune(...) zrepl/daemon/pruner/pruner.go:200 github.com/zrepl/zrepl/daemon/job.(*ActiveSide).do(0xc000268000, 0xd6a9e0, 0xc0002223c0) zrepl/daemon/job/active.go:482 +0x906 github.com/zrepl/zrepl/daemon/job.(*ActiveSide).Run(0xc000268000, 0xd6aaa0, 0xc000127080) zrepl/daemon/job/active.go:404 +0x289 github.com/zrepl/zrepl/daemon.(*jobs).start.func1(0xc000032200, 0xd73ca0, 0xc00000f2e0, 0xd6efa0, 0xc000268000, 0xd6aaa0, 0xc000126c90) zrepl/daemon/daemon.go:220 +0x121 created by github.com/zrepl/zrepl/daemon.(*jobs).start zrepl/daemon/daemon.go:216 +0x52e
2020-02-14 21:34:22 +01:00
snapnames = append(snapnames, a)
if strings.Contains(a, ",") {
return fmt.Errorf("unsupported syntax mock error")
}
zfs: fix batch destroy panic if all snaps are undestroyable See https://github.com/zrepl/zrepl/pull/259#issuecomment-585334023 panic: runtime error: index out of range [0] with length 0 goroutine 14 [running]: github.com/zrepl/zrepl/zfs.tryBatch(0xd6aa20, 0xc0000b8018, 0xc00025e0c0, 0x0, 0x6, 0xd61d80, 0x1280df8, 0xd58920, 0xc000132000) zrepl/zfs/versions_destroy.go:129 +0x302 github.com/zrepl/zrepl/zfs.doDestroyBatchedRec(0xd6aa20, 0xc0000b8018, 0xc000578a80, 0x6, 0x6, 0xd61d80, 0x1280df8) zrepl/zfs/versions_destroy.go:184 +0x4a5 github.com/zrepl/zrepl/zfs.doDestroyBatched(0xd6aa20, 0xc0000b8018, 0xc000222780, 0x6, 0x8, 0xd61d80, 0x1280df8) zrepl/zfs/versions_destroy.go:95 +0xc7 github.com/zrepl/zrepl/zfs.doDestroy(0xd6aa20, 0xc0000b8018, 0xc0005788d0, 0x6, 0x6, 0xd61d80, 0x1280df8) zrepl/zfs/versions_destroy.go:82 +0x362 github.com/zrepl/zrepl/zfs.ZFSDestroyFilesystemVersions(...) zrepl/zfs/versions_destroy.go:41 github.com/zrepl/zrepl/endpoint.doDestroySnapshots(0xd6aaa0, 0xc0004412c0, 0xc00057ca00, 0xc0005785a0, 0x6, 0x6, 0xb68940, 0xc5df01, 0xc000150a80) zrepl/endpoint/endpoint.go:785 +0x388 github.com/zrepl/zrepl/endpoint.(*Receiver).DestroySnapshots(0xc000127500, 0xd6aaa0, 0xc0004412c0, 0xc0002ca280, 0xc000150880, 0xd73ca0, 0xc00057c960) zrepl/endpoint/endpoint.go:751 +0xdb github.com/zrepl/zrepl/daemon/pruner.doOneAttemptExec(0xc000429980, 0xc000429958, 0xc0001cb180) zrepl/daemon/pruner/pruner.go:531 +0x51f github.com/zrepl/zrepl/daemon/pruner.doOneAttempt(0xc000429980, 0xc000429958) zrepl/daemon/pruner/pruner.go:486 +0x1064 github.com/zrepl/zrepl/daemon/pruner.(*Pruner).prune(0xc00011e280, 0xd6aaa0, 0xc0004412c0, 0x7f4906fff7e8, 0xc000127500, 0x7f4906fff738, 0xc0001324e0, 0xc000064420, 0x1, 0x1, ...) zrepl/daemon/pruner/pruner.go:214 +0x53 github.com/zrepl/zrepl/daemon/pruner.(*Pruner).Prune(...) zrepl/daemon/pruner/pruner.go:200 github.com/zrepl/zrepl/daemon/job.(*ActiveSide).do(0xc000268000, 0xd6a9e0, 0xc0002223c0) zrepl/daemon/job/active.go:482 +0x906 github.com/zrepl/zrepl/daemon/job.(*ActiveSide).Run(0xc000268000, 0xd6aaa0, 0xc000127080) zrepl/daemon/job/active.go:404 +0x289 github.com/zrepl/zrepl/daemon.(*jobs).start.func1(0xc000032200, 0xd73ca0, 0xc00000f2e0, 0xd6efa0, 0xc000268000, 0xd6aaa0, 0xc000126c90) zrepl/daemon/daemon.go:220 +0x121 created by github.com/zrepl/zrepl/daemon.(*jobs).start zrepl/daemon/daemon.go:216 +0x52e
2020-02-14 21:34:22 +01:00
} else {
snapnames = append(snapnames, strings.Split(a, ",")...)
}
fs, vt, firstsnapname, err := DecomposeVersionString(snapnames[0])
if err != nil {
panic(err)
}
if vt != Snapshot {
panic(vt)
}
zfs: fix batch destroy panic if all snaps are undestroyable See https://github.com/zrepl/zrepl/pull/259#issuecomment-585334023 panic: runtime error: index out of range [0] with length 0 goroutine 14 [running]: github.com/zrepl/zrepl/zfs.tryBatch(0xd6aa20, 0xc0000b8018, 0xc00025e0c0, 0x0, 0x6, 0xd61d80, 0x1280df8, 0xd58920, 0xc000132000) zrepl/zfs/versions_destroy.go:129 +0x302 github.com/zrepl/zrepl/zfs.doDestroyBatchedRec(0xd6aa20, 0xc0000b8018, 0xc000578a80, 0x6, 0x6, 0xd61d80, 0x1280df8) zrepl/zfs/versions_destroy.go:184 +0x4a5 github.com/zrepl/zrepl/zfs.doDestroyBatched(0xd6aa20, 0xc0000b8018, 0xc000222780, 0x6, 0x8, 0xd61d80, 0x1280df8) zrepl/zfs/versions_destroy.go:95 +0xc7 github.com/zrepl/zrepl/zfs.doDestroy(0xd6aa20, 0xc0000b8018, 0xc0005788d0, 0x6, 0x6, 0xd61d80, 0x1280df8) zrepl/zfs/versions_destroy.go:82 +0x362 github.com/zrepl/zrepl/zfs.ZFSDestroyFilesystemVersions(...) zrepl/zfs/versions_destroy.go:41 github.com/zrepl/zrepl/endpoint.doDestroySnapshots(0xd6aaa0, 0xc0004412c0, 0xc00057ca00, 0xc0005785a0, 0x6, 0x6, 0xb68940, 0xc5df01, 0xc000150a80) zrepl/endpoint/endpoint.go:785 +0x388 github.com/zrepl/zrepl/endpoint.(*Receiver).DestroySnapshots(0xc000127500, 0xd6aaa0, 0xc0004412c0, 0xc0002ca280, 0xc000150880, 0xd73ca0, 0xc00057c960) zrepl/endpoint/endpoint.go:751 +0xdb github.com/zrepl/zrepl/daemon/pruner.doOneAttemptExec(0xc000429980, 0xc000429958, 0xc0001cb180) zrepl/daemon/pruner/pruner.go:531 +0x51f github.com/zrepl/zrepl/daemon/pruner.doOneAttempt(0xc000429980, 0xc000429958) zrepl/daemon/pruner/pruner.go:486 +0x1064 github.com/zrepl/zrepl/daemon/pruner.(*Pruner).prune(0xc00011e280, 0xd6aaa0, 0xc0004412c0, 0x7f4906fff7e8, 0xc000127500, 0x7f4906fff738, 0xc0001324e0, 0xc000064420, 0x1, 0x1, ...) zrepl/daemon/pruner/pruner.go:214 +0x53 github.com/zrepl/zrepl/daemon/pruner.(*Pruner).Prune(...) zrepl/daemon/pruner/pruner.go:200 github.com/zrepl/zrepl/daemon/job.(*ActiveSide).do(0xc000268000, 0xd6a9e0, 0xc0002223c0) zrepl/daemon/job/active.go:482 +0x906 github.com/zrepl/zrepl/daemon/job.(*ActiveSide).Run(0xc000268000, 0xd6aaa0, 0xc000127080) zrepl/daemon/job/active.go:404 +0x289 github.com/zrepl/zrepl/daemon.(*jobs).start.func1(0xc000032200, 0xd73ca0, 0xc00000f2e0, 0xd6efa0, 0xc000268000, 0xd6aaa0, 0xc000126c90) zrepl/daemon/daemon.go:220 +0x121 created by github.com/zrepl/zrepl/daemon.(*jobs).start zrepl/daemon/daemon.go:216 +0x52e
2020-02-14 21:34:22 +01:00
snapnames[0] = firstsnapname
zfs: fix batch destroy panic if all snaps are undestroyable See https://github.com/zrepl/zrepl/pull/259#issuecomment-585334023 panic: runtime error: index out of range [0] with length 0 goroutine 14 [running]: github.com/zrepl/zrepl/zfs.tryBatch(0xd6aa20, 0xc0000b8018, 0xc00025e0c0, 0x0, 0x6, 0xd61d80, 0x1280df8, 0xd58920, 0xc000132000) zrepl/zfs/versions_destroy.go:129 +0x302 github.com/zrepl/zrepl/zfs.doDestroyBatchedRec(0xd6aa20, 0xc0000b8018, 0xc000578a80, 0x6, 0x6, 0xd61d80, 0x1280df8) zrepl/zfs/versions_destroy.go:184 +0x4a5 github.com/zrepl/zrepl/zfs.doDestroyBatched(0xd6aa20, 0xc0000b8018, 0xc000222780, 0x6, 0x8, 0xd61d80, 0x1280df8) zrepl/zfs/versions_destroy.go:95 +0xc7 github.com/zrepl/zrepl/zfs.doDestroy(0xd6aa20, 0xc0000b8018, 0xc0005788d0, 0x6, 0x6, 0xd61d80, 0x1280df8) zrepl/zfs/versions_destroy.go:82 +0x362 github.com/zrepl/zrepl/zfs.ZFSDestroyFilesystemVersions(...) zrepl/zfs/versions_destroy.go:41 github.com/zrepl/zrepl/endpoint.doDestroySnapshots(0xd6aaa0, 0xc0004412c0, 0xc00057ca00, 0xc0005785a0, 0x6, 0x6, 0xb68940, 0xc5df01, 0xc000150a80) zrepl/endpoint/endpoint.go:785 +0x388 github.com/zrepl/zrepl/endpoint.(*Receiver).DestroySnapshots(0xc000127500, 0xd6aaa0, 0xc0004412c0, 0xc0002ca280, 0xc000150880, 0xd73ca0, 0xc00057c960) zrepl/endpoint/endpoint.go:751 +0xdb github.com/zrepl/zrepl/daemon/pruner.doOneAttemptExec(0xc000429980, 0xc000429958, 0xc0001cb180) zrepl/daemon/pruner/pruner.go:531 +0x51f github.com/zrepl/zrepl/daemon/pruner.doOneAttempt(0xc000429980, 0xc000429958) zrepl/daemon/pruner/pruner.go:486 +0x1064 github.com/zrepl/zrepl/daemon/pruner.(*Pruner).prune(0xc00011e280, 0xd6aaa0, 0xc0004412c0, 0x7f4906fff7e8, 0xc000127500, 0x7f4906fff738, 0xc0001324e0, 0xc000064420, 0x1, 0x1, ...) zrepl/daemon/pruner/pruner.go:214 +0x53 github.com/zrepl/zrepl/daemon/pruner.(*Pruner).Prune(...) zrepl/daemon/pruner/pruner.go:200 github.com/zrepl/zrepl/daemon/job.(*ActiveSide).do(0xc000268000, 0xd6a9e0, 0xc0002223c0) zrepl/daemon/job/active.go:482 +0x906 github.com/zrepl/zrepl/daemon/job.(*ActiveSide).Run(0xc000268000, 0xd6aaa0, 0xc000127080) zrepl/daemon/job/active.go:404 +0x289 github.com/zrepl/zrepl/daemon.(*jobs).start.func1(0xc000032200, 0xd73ca0, 0xc00000f2e0, 0xd6efa0, 0xc000268000, 0xd6aaa0, 0xc000126c90) zrepl/daemon/daemon.go:220 +0x121 created by github.com/zrepl/zrepl/daemon.(*jobs).start zrepl/daemon/daemon.go:216 +0x52e
2020-02-14 21:34:22 +01:00
var undestroyable []string
if m.undestroyable != nil {
for _, snap := range snapnames {
if m.undestroyable.MatchString(snap) {
undestroyable = append(undestroyable, snap)
}
}
}
if len(undestroyable) > 0 {
return &DestroySnapshotsError{
zfs: fix batch destroy panic if all snaps are undestroyable See https://github.com/zrepl/zrepl/pull/259#issuecomment-585334023 panic: runtime error: index out of range [0] with length 0 goroutine 14 [running]: github.com/zrepl/zrepl/zfs.tryBatch(0xd6aa20, 0xc0000b8018, 0xc00025e0c0, 0x0, 0x6, 0xd61d80, 0x1280df8, 0xd58920, 0xc000132000) zrepl/zfs/versions_destroy.go:129 +0x302 github.com/zrepl/zrepl/zfs.doDestroyBatchedRec(0xd6aa20, 0xc0000b8018, 0xc000578a80, 0x6, 0x6, 0xd61d80, 0x1280df8) zrepl/zfs/versions_destroy.go:184 +0x4a5 github.com/zrepl/zrepl/zfs.doDestroyBatched(0xd6aa20, 0xc0000b8018, 0xc000222780, 0x6, 0x8, 0xd61d80, 0x1280df8) zrepl/zfs/versions_destroy.go:95 +0xc7 github.com/zrepl/zrepl/zfs.doDestroy(0xd6aa20, 0xc0000b8018, 0xc0005788d0, 0x6, 0x6, 0xd61d80, 0x1280df8) zrepl/zfs/versions_destroy.go:82 +0x362 github.com/zrepl/zrepl/zfs.ZFSDestroyFilesystemVersions(...) zrepl/zfs/versions_destroy.go:41 github.com/zrepl/zrepl/endpoint.doDestroySnapshots(0xd6aaa0, 0xc0004412c0, 0xc00057ca00, 0xc0005785a0, 0x6, 0x6, 0xb68940, 0xc5df01, 0xc000150a80) zrepl/endpoint/endpoint.go:785 +0x388 github.com/zrepl/zrepl/endpoint.(*Receiver).DestroySnapshots(0xc000127500, 0xd6aaa0, 0xc0004412c0, 0xc0002ca280, 0xc000150880, 0xd73ca0, 0xc00057c960) zrepl/endpoint/endpoint.go:751 +0xdb github.com/zrepl/zrepl/daemon/pruner.doOneAttemptExec(0xc000429980, 0xc000429958, 0xc0001cb180) zrepl/daemon/pruner/pruner.go:531 +0x51f github.com/zrepl/zrepl/daemon/pruner.doOneAttempt(0xc000429980, 0xc000429958) zrepl/daemon/pruner/pruner.go:486 +0x1064 github.com/zrepl/zrepl/daemon/pruner.(*Pruner).prune(0xc00011e280, 0xd6aaa0, 0xc0004412c0, 0x7f4906fff7e8, 0xc000127500, 0x7f4906fff738, 0xc0001324e0, 0xc000064420, 0x1, 0x1, ...) zrepl/daemon/pruner/pruner.go:214 +0x53 github.com/zrepl/zrepl/daemon/pruner.(*Pruner).Prune(...) zrepl/daemon/pruner/pruner.go:200 github.com/zrepl/zrepl/daemon/job.(*ActiveSide).do(0xc000268000, 0xd6a9e0, 0xc0002223c0) zrepl/daemon/job/active.go:482 +0x906 github.com/zrepl/zrepl/daemon/job.(*ActiveSide).Run(0xc000268000, 0xd6aaa0, 0xc000127080) zrepl/daemon/job/active.go:404 +0x289 github.com/zrepl/zrepl/daemon.(*jobs).start.func1(0xc000032200, 0xd73ca0, 0xc00000f2e0, 0xd6efa0, 0xc000268000, 0xd6aaa0, 0xc000126c90) zrepl/daemon/daemon.go:220 +0x121 created by github.com/zrepl/zrepl/daemon.(*jobs).start zrepl/daemon/daemon.go:216 +0x52e
2020-02-14 21:34:22 +01:00
Filesystem: fs,
Undestroyable: undestroyable,
Reason: []string{"undestroyable mock with regexp " + m.undestroyable.String()},
}
}
if m.randomerror != "" && strings.Contains(a, m.randomerror) {
return fmt.Errorf("randomerror")
}
return nil
}
func TestBatchDestroySnaps(t *testing.T) {
errs := make([]error, 10)
nilErrs := func() {
for i := range errs {
errs[i] = nil
}
}
opsTemplate := []*DestroySnapOp{
&DestroySnapOp{"zroot/z", "foo", &errs[0]},
&DestroySnapOp{"zroot/a", "foo", &errs[1]},
&DestroySnapOp{"zroot/a", "bar", &errs[2]},
&DestroySnapOp{"zroot/b", "bar", &errs[3]},
&DestroySnapOp{"zroot/b", "zab", &errs[4]},
&DestroySnapOp{"zroot/b", "undestroyable", &errs[5]},
&DestroySnapOp{"zroot/c", "baz", &errs[6]},
&DestroySnapOp{"zroot/c", "randomerror", &errs[7]},
&DestroySnapOp{"zroot/c", "bar", &errs[8]},
&DestroySnapOp{"zroot/d", "blup", &errs[9]},
}
t.Run("single_undestroyable_dataset", func(t *testing.T) {
nilErrs()
mock := &mockBatchDestroy{
commaUnsupported: false,
zfs: fix batch destroy panic if all snaps are undestroyable See https://github.com/zrepl/zrepl/pull/259#issuecomment-585334023 panic: runtime error: index out of range [0] with length 0 goroutine 14 [running]: github.com/zrepl/zrepl/zfs.tryBatch(0xd6aa20, 0xc0000b8018, 0xc00025e0c0, 0x0, 0x6, 0xd61d80, 0x1280df8, 0xd58920, 0xc000132000) zrepl/zfs/versions_destroy.go:129 +0x302 github.com/zrepl/zrepl/zfs.doDestroyBatchedRec(0xd6aa20, 0xc0000b8018, 0xc000578a80, 0x6, 0x6, 0xd61d80, 0x1280df8) zrepl/zfs/versions_destroy.go:184 +0x4a5 github.com/zrepl/zrepl/zfs.doDestroyBatched(0xd6aa20, 0xc0000b8018, 0xc000222780, 0x6, 0x8, 0xd61d80, 0x1280df8) zrepl/zfs/versions_destroy.go:95 +0xc7 github.com/zrepl/zrepl/zfs.doDestroy(0xd6aa20, 0xc0000b8018, 0xc0005788d0, 0x6, 0x6, 0xd61d80, 0x1280df8) zrepl/zfs/versions_destroy.go:82 +0x362 github.com/zrepl/zrepl/zfs.ZFSDestroyFilesystemVersions(...) zrepl/zfs/versions_destroy.go:41 github.com/zrepl/zrepl/endpoint.doDestroySnapshots(0xd6aaa0, 0xc0004412c0, 0xc00057ca00, 0xc0005785a0, 0x6, 0x6, 0xb68940, 0xc5df01, 0xc000150a80) zrepl/endpoint/endpoint.go:785 +0x388 github.com/zrepl/zrepl/endpoint.(*Receiver).DestroySnapshots(0xc000127500, 0xd6aaa0, 0xc0004412c0, 0xc0002ca280, 0xc000150880, 0xd73ca0, 0xc00057c960) zrepl/endpoint/endpoint.go:751 +0xdb github.com/zrepl/zrepl/daemon/pruner.doOneAttemptExec(0xc000429980, 0xc000429958, 0xc0001cb180) zrepl/daemon/pruner/pruner.go:531 +0x51f github.com/zrepl/zrepl/daemon/pruner.doOneAttempt(0xc000429980, 0xc000429958) zrepl/daemon/pruner/pruner.go:486 +0x1064 github.com/zrepl/zrepl/daemon/pruner.(*Pruner).prune(0xc00011e280, 0xd6aaa0, 0xc0004412c0, 0x7f4906fff7e8, 0xc000127500, 0x7f4906fff738, 0xc0001324e0, 0xc000064420, 0x1, 0x1, ...) zrepl/daemon/pruner/pruner.go:214 +0x53 github.com/zrepl/zrepl/daemon/pruner.(*Pruner).Prune(...) zrepl/daemon/pruner/pruner.go:200 github.com/zrepl/zrepl/daemon/job.(*ActiveSide).do(0xc000268000, 0xd6a9e0, 0xc0002223c0) zrepl/daemon/job/active.go:482 +0x906 github.com/zrepl/zrepl/daemon/job.(*ActiveSide).Run(0xc000268000, 0xd6aaa0, 0xc000127080) zrepl/daemon/job/active.go:404 +0x289 github.com/zrepl/zrepl/daemon.(*jobs).start.func1(0xc000032200, 0xd73ca0, 0xc00000f2e0, 0xd6efa0, 0xc000268000, 0xd6aaa0, 0xc000126c90) zrepl/daemon/daemon.go:220 +0x121 created by github.com/zrepl/zrepl/daemon.(*jobs).start zrepl/daemon/daemon.go:216 +0x52e
2020-02-14 21:34:22 +01:00
undestroyable: regexp.MustCompile(`undestroyable`),
randomerror: "randomerror",
}
doDestroy(context.TODO(), opsTemplate, mock)
assert.NoError(t, errs[0])
assert.NoError(t, errs[1])
assert.NoError(t, errs[2])
assert.NoError(t, errs[3])
assert.NoError(t, errs[4])
assert.Error(t, errs[5], "undestroyable")
assert.NoError(t, errs[6])
assert.Error(t, errs[7], "randomerror")
assert.NoError(t, errs[8])
assert.NoError(t, errs[9])
defer mock.mtx.Lock().Unlock()
assert.Equal(
t,
[]string{
"zroot/a@bar,foo", // reordered snaps in lexicographical order
"zroot/b@bar,undestroyable,zab",
"zroot/b@bar,zab", // eliminate undestroyables, try others again
"zroot/b@undestroyable",
"zroot/c@bar,baz,randomerror",
"zroot/c@bar", // fallback to single-snapshot on non DestroyError
"zroot/c@baz",
"zroot/c@randomerror",
"zroot/d@blup",
"zroot/z@foo", // ordered at last position
},
mock.calls,
)
})
zfs: fix batch destroy panic if all snaps are undestroyable See https://github.com/zrepl/zrepl/pull/259#issuecomment-585334023 panic: runtime error: index out of range [0] with length 0 goroutine 14 [running]: github.com/zrepl/zrepl/zfs.tryBatch(0xd6aa20, 0xc0000b8018, 0xc00025e0c0, 0x0, 0x6, 0xd61d80, 0x1280df8, 0xd58920, 0xc000132000) zrepl/zfs/versions_destroy.go:129 +0x302 github.com/zrepl/zrepl/zfs.doDestroyBatchedRec(0xd6aa20, 0xc0000b8018, 0xc000578a80, 0x6, 0x6, 0xd61d80, 0x1280df8) zrepl/zfs/versions_destroy.go:184 +0x4a5 github.com/zrepl/zrepl/zfs.doDestroyBatched(0xd6aa20, 0xc0000b8018, 0xc000222780, 0x6, 0x8, 0xd61d80, 0x1280df8) zrepl/zfs/versions_destroy.go:95 +0xc7 github.com/zrepl/zrepl/zfs.doDestroy(0xd6aa20, 0xc0000b8018, 0xc0005788d0, 0x6, 0x6, 0xd61d80, 0x1280df8) zrepl/zfs/versions_destroy.go:82 +0x362 github.com/zrepl/zrepl/zfs.ZFSDestroyFilesystemVersions(...) zrepl/zfs/versions_destroy.go:41 github.com/zrepl/zrepl/endpoint.doDestroySnapshots(0xd6aaa0, 0xc0004412c0, 0xc00057ca00, 0xc0005785a0, 0x6, 0x6, 0xb68940, 0xc5df01, 0xc000150a80) zrepl/endpoint/endpoint.go:785 +0x388 github.com/zrepl/zrepl/endpoint.(*Receiver).DestroySnapshots(0xc000127500, 0xd6aaa0, 0xc0004412c0, 0xc0002ca280, 0xc000150880, 0xd73ca0, 0xc00057c960) zrepl/endpoint/endpoint.go:751 +0xdb github.com/zrepl/zrepl/daemon/pruner.doOneAttemptExec(0xc000429980, 0xc000429958, 0xc0001cb180) zrepl/daemon/pruner/pruner.go:531 +0x51f github.com/zrepl/zrepl/daemon/pruner.doOneAttempt(0xc000429980, 0xc000429958) zrepl/daemon/pruner/pruner.go:486 +0x1064 github.com/zrepl/zrepl/daemon/pruner.(*Pruner).prune(0xc00011e280, 0xd6aaa0, 0xc0004412c0, 0x7f4906fff7e8, 0xc000127500, 0x7f4906fff738, 0xc0001324e0, 0xc000064420, 0x1, 0x1, ...) zrepl/daemon/pruner/pruner.go:214 +0x53 github.com/zrepl/zrepl/daemon/pruner.(*Pruner).Prune(...) zrepl/daemon/pruner/pruner.go:200 github.com/zrepl/zrepl/daemon/job.(*ActiveSide).do(0xc000268000, 0xd6a9e0, 0xc0002223c0) zrepl/daemon/job/active.go:482 +0x906 github.com/zrepl/zrepl/daemon/job.(*ActiveSide).Run(0xc000268000, 0xd6aaa0, 0xc000127080) zrepl/daemon/job/active.go:404 +0x289 github.com/zrepl/zrepl/daemon.(*jobs).start.func1(0xc000032200, 0xd73ca0, 0xc00000f2e0, 0xd6efa0, 0xc000268000, 0xd6aaa0, 0xc000126c90) zrepl/daemon/daemon.go:220 +0x121 created by github.com/zrepl/zrepl/daemon.(*jobs).start zrepl/daemon/daemon.go:216 +0x52e
2020-02-14 21:34:22 +01:00
t.Run("all_undestroyable", func(t *testing.T) {
opsTemplate := []*DestroySnapOp{
&DestroySnapOp{"zroot/a", "foo", new(error)},
&DestroySnapOp{"zroot/a", "bar", new(error)},
}
mock := &mockBatchDestroy{
commaUnsupported: false,
undestroyable: regexp.MustCompile(`.*`),
}
doDestroy(context.TODO(), opsTemplate, mock)
defer mock.mtx.Lock().Unlock()
assert.Equal(
t,
[]string{
"zroot/a@bar,foo", // reordered snaps in lexicographical order
"zroot/a@bar",
"zroot/a@foo",
},
mock.calls,
)
})
t.Run("comma_syntax_unsupported", func(t *testing.T) {
nilErrs()
mock := &mockBatchDestroy{
commaUnsupported: true,
zfs: fix batch destroy panic if all snaps are undestroyable See https://github.com/zrepl/zrepl/pull/259#issuecomment-585334023 panic: runtime error: index out of range [0] with length 0 goroutine 14 [running]: github.com/zrepl/zrepl/zfs.tryBatch(0xd6aa20, 0xc0000b8018, 0xc00025e0c0, 0x0, 0x6, 0xd61d80, 0x1280df8, 0xd58920, 0xc000132000) zrepl/zfs/versions_destroy.go:129 +0x302 github.com/zrepl/zrepl/zfs.doDestroyBatchedRec(0xd6aa20, 0xc0000b8018, 0xc000578a80, 0x6, 0x6, 0xd61d80, 0x1280df8) zrepl/zfs/versions_destroy.go:184 +0x4a5 github.com/zrepl/zrepl/zfs.doDestroyBatched(0xd6aa20, 0xc0000b8018, 0xc000222780, 0x6, 0x8, 0xd61d80, 0x1280df8) zrepl/zfs/versions_destroy.go:95 +0xc7 github.com/zrepl/zrepl/zfs.doDestroy(0xd6aa20, 0xc0000b8018, 0xc0005788d0, 0x6, 0x6, 0xd61d80, 0x1280df8) zrepl/zfs/versions_destroy.go:82 +0x362 github.com/zrepl/zrepl/zfs.ZFSDestroyFilesystemVersions(...) zrepl/zfs/versions_destroy.go:41 github.com/zrepl/zrepl/endpoint.doDestroySnapshots(0xd6aaa0, 0xc0004412c0, 0xc00057ca00, 0xc0005785a0, 0x6, 0x6, 0xb68940, 0xc5df01, 0xc000150a80) zrepl/endpoint/endpoint.go:785 +0x388 github.com/zrepl/zrepl/endpoint.(*Receiver).DestroySnapshots(0xc000127500, 0xd6aaa0, 0xc0004412c0, 0xc0002ca280, 0xc000150880, 0xd73ca0, 0xc00057c960) zrepl/endpoint/endpoint.go:751 +0xdb github.com/zrepl/zrepl/daemon/pruner.doOneAttemptExec(0xc000429980, 0xc000429958, 0xc0001cb180) zrepl/daemon/pruner/pruner.go:531 +0x51f github.com/zrepl/zrepl/daemon/pruner.doOneAttempt(0xc000429980, 0xc000429958) zrepl/daemon/pruner/pruner.go:486 +0x1064 github.com/zrepl/zrepl/daemon/pruner.(*Pruner).prune(0xc00011e280, 0xd6aaa0, 0xc0004412c0, 0x7f4906fff7e8, 0xc000127500, 0x7f4906fff738, 0xc0001324e0, 0xc000064420, 0x1, 0x1, ...) zrepl/daemon/pruner/pruner.go:214 +0x53 github.com/zrepl/zrepl/daemon/pruner.(*Pruner).Prune(...) zrepl/daemon/pruner/pruner.go:200 github.com/zrepl/zrepl/daemon/job.(*ActiveSide).do(0xc000268000, 0xd6a9e0, 0xc0002223c0) zrepl/daemon/job/active.go:482 +0x906 github.com/zrepl/zrepl/daemon/job.(*ActiveSide).Run(0xc000268000, 0xd6aaa0, 0xc000127080) zrepl/daemon/job/active.go:404 +0x289 github.com/zrepl/zrepl/daemon.(*jobs).start.func1(0xc000032200, 0xd73ca0, 0xc00000f2e0, 0xd6efa0, 0xc000268000, 0xd6aaa0, 0xc000126c90) zrepl/daemon/daemon.go:220 +0x121 created by github.com/zrepl/zrepl/daemon.(*jobs).start zrepl/daemon/daemon.go:216 +0x52e
2020-02-14 21:34:22 +01:00
undestroyable: regexp.MustCompile(`undestroyable`),
randomerror: "randomerror",
}
doDestroy(context.TODO(), opsTemplate, mock)
assert.NoError(t, errs[0])
assert.NoError(t, errs[1])
assert.NoError(t, errs[2])
assert.NoError(t, errs[3])
assert.NoError(t, errs[4])
assert.Error(t, errs[5], "undestroyable")
assert.NoError(t, errs[6])
assert.Error(t, errs[7], "randomerror")
assert.NoError(t, errs[8])
assert.NoError(t, errs[9])
defer mock.mtx.Lock().Unlock()
assert.Equal(
t,
[]string{
// expect exactly argument order
"zroot/z@foo",
"zroot/a@foo",
"zroot/a@bar",
"zroot/b@bar",
"zroot/b@zab",
"zroot/b@undestroyable",
"zroot/c@baz",
"zroot/c@randomerror",
"zroot/c@bar",
"zroot/d@blup",
},
mock.calls,
)
})
t.Run("empty_ops", func(t *testing.T) {
mock := &mockBatchDestroy{}
doDestroy(context.TODO(), nil, mock)
defer mock.mtx.Lock().Unlock()
assert.Empty(t, mock.calls)
})
t.Run("ops_without_snapnames", func(t *testing.T) {
mock := &mockBatchDestroy{}
var err error
ops := []*DestroySnapOp{&DestroySnapOp{"somefs", "", &err}}
doDestroy(context.TODO(), ops, mock)
assert.Error(t, err)
defer mock.mtx.Lock().Unlock()
assert.Empty(t, mock.calls)
})
t.Run("ops_without_fsnames", func(t *testing.T) {
mock := &mockBatchDestroy{}
var err error
ops := []*DestroySnapOp{&DestroySnapOp{"", "fsname", &err}}
doDestroy(context.TODO(), ops, mock)
assert.Error(t, err)
defer mock.mtx.Lock().Unlock()
assert.Empty(t, mock.calls)
})
t.Run("splits_up_batches_at_e2big", func(t *testing.T) {
mock := &mockBatchDestroy{
e2biglen: 10,
}
var dummy error
reqs := []*DestroySnapOp{
// should fit (1111@a,b,c)
&DestroySnapOp{"1111", "a", &dummy},
&DestroySnapOp{"1111", "b", &dummy},
&DestroySnapOp{"1111", "c", &dummy},
// should split
&DestroySnapOp{"2222", "01", &dummy},
&DestroySnapOp{"2222", "02", &dummy},
&DestroySnapOp{"2222", "03", &dummy},
&DestroySnapOp{"2222", "04", &dummy},
&DestroySnapOp{"2222", "05", &dummy},
&DestroySnapOp{"2222", "06", &dummy},
&DestroySnapOp{"2222", "07", &dummy},
&DestroySnapOp{"2222", "08", &dummy},
&DestroySnapOp{"2222", "09", &dummy},
&DestroySnapOp{"2222", "10", &dummy},
}
doDestroy(context.TODO(), reqs, mock)
defer mock.mtx.Lock().Unlock()
assert.Equal(
t,
[]string{
"1111@a,b,c",
"2222@01,02",
"2222@03",
"2222@04,05",
"2222@06,07",
"2222@08",
"2222@09,10",
},
mock.calls,
)
})
}
func TestExcessiveArgumentsResultInE2BIG(t *testing.T) {
// FIXME dynamic value
const maxArgumentLength = 1 << 20 // higher than any OS we know, should always fail
t.Logf("maxArgumentLength=%v", maxArgumentLength)
maxArg := bytes.Repeat([]byte("a"), maxArgumentLength)
cmd := exec.Command("/bin/sh", "-c", "echo -n $1; echo -n $2", "cmdname", string(maxArg), string(maxArg))
output, err := cmd.CombinedOutput()
if pe, ok := err.(*os.PathError); ok && pe.Err == syscall.E2BIG {
t.Logf("ok, system returns E2BIG")
} else {
t.Errorf("system did not return E2BIG, but err=%T: %v ", err, err)
t.Logf("output:\n%s", output)
}
}