All checks were successful
Test / Create distribution (push) Successful in 27s
Test / Sandbox (push) Successful in 1m50s
Test / Fortify (push) Successful in 2m49s
Test / Sandbox (race detector) (push) Successful in 3m4s
Test / Fpkg (push) Successful in 3m35s
Test / Fortify (race detector) (push) Successful in 4m13s
Test / Flake checks (push) Successful in 1m3s
The dbus proxy wrapper haven't been updated much ever since the helper interface was introduced. Signed-off-by: Ophestra <cat@gensokyo.uk>
214 lines
5.5 KiB
Go
214 lines
5.5 KiB
Go
package dbus_test
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
"os/exec"
|
|
"strings"
|
|
"syscall"
|
|
"testing"
|
|
"time"
|
|
|
|
"git.gensokyo.uk/security/fortify/dbus"
|
|
"git.gensokyo.uk/security/fortify/helper"
|
|
"git.gensokyo.uk/security/fortify/internal"
|
|
"git.gensokyo.uk/security/fortify/internal/fmsg"
|
|
"git.gensokyo.uk/security/fortify/sandbox"
|
|
)
|
|
|
|
func TestFinalise(t *testing.T) {
|
|
if _, err := dbus.Finalise(dbus.ProxyPair{}, dbus.ProxyPair{}, nil, nil); !errors.Is(err, syscall.EBADE) {
|
|
t.Errorf("Finalise: error = %v, want %v",
|
|
err, syscall.EBADE)
|
|
}
|
|
|
|
for id, tc := range testCasePairs() {
|
|
t.Run("create final for "+id, func(t *testing.T) {
|
|
var wt io.WriterTo
|
|
if v, err := dbus.Finalise(tc[0].bus, tc[1].bus, tc[0].c, tc[1].c); (errors.Is(err, syscall.EINVAL)) != tc[0].wantErr {
|
|
t.Errorf("Finalise: error = %v, wantErr %v",
|
|
err, tc[0].wantErr)
|
|
return
|
|
} else {
|
|
wt = v
|
|
}
|
|
|
|
// rest of the tests happen for sealed instances
|
|
if tc[0].wantErr {
|
|
return
|
|
}
|
|
|
|
// build null-terminated string from wanted args
|
|
want := new(strings.Builder)
|
|
args := append(tc[0].want, tc[1].want...)
|
|
for _, arg := range args {
|
|
want.WriteString(arg)
|
|
want.WriteByte(0)
|
|
}
|
|
|
|
got := new(strings.Builder)
|
|
if _, err := wt.WriteTo(got); err != nil {
|
|
t.Errorf("WriteTo: error = %v", err)
|
|
}
|
|
|
|
if want.String() != got.String() {
|
|
t.Errorf("Seal: %q, want %q",
|
|
got.String(), want.String())
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestProxyStartWaitCloseString(t *testing.T) {
|
|
oldWaitDelay := helper.WaitDelay
|
|
helper.WaitDelay = 16 * time.Second
|
|
t.Cleanup(func() { helper.WaitDelay = oldWaitDelay })
|
|
|
|
t.Run("sandbox", func(t *testing.T) {
|
|
proxyName := dbus.ProxyName
|
|
dbus.ProxyName = os.Args[0]
|
|
t.Cleanup(func() { dbus.ProxyName = proxyName })
|
|
testProxyFinaliseStartWaitCloseString(t, true)
|
|
})
|
|
t.Run("direct", func(t *testing.T) { testProxyFinaliseStartWaitCloseString(t, false) })
|
|
}
|
|
|
|
func testProxyFinaliseStartWaitCloseString(t *testing.T, useSandbox bool) {
|
|
var p *dbus.Proxy
|
|
|
|
t.Run("string for nil proxy", func(t *testing.T) {
|
|
want := "(invalid dbus proxy)"
|
|
if got := p.String(); got != want {
|
|
t.Errorf("String: %q, want %q",
|
|
got, want)
|
|
}
|
|
})
|
|
|
|
t.Run("invalid start", func(t *testing.T) {
|
|
if !useSandbox {
|
|
p = dbus.NewDirect(context.TODO(), nil, nil)
|
|
} else {
|
|
p = dbus.New(context.TODO(), nil, nil)
|
|
}
|
|
|
|
if err := p.Start(); !errors.Is(err, syscall.ENOTRECOVERABLE) {
|
|
t.Errorf("Start: error = %q, wantErr %q",
|
|
err, syscall.ENOTRECOVERABLE)
|
|
return
|
|
}
|
|
})
|
|
|
|
for id, tc := range testCasePairs() {
|
|
// this test does not test errors
|
|
if tc[0].wantErr {
|
|
continue
|
|
}
|
|
|
|
t.Run("proxy for "+id, func(t *testing.T) {
|
|
var final *dbus.Final
|
|
t.Run("finalise", func(t *testing.T) {
|
|
if v, err := dbus.Finalise(tc[0].bus, tc[1].bus, tc[0].c, tc[1].c); err != nil {
|
|
t.Errorf("Finalise: error = %v, wantErr %v",
|
|
err, tc[0].wantErr)
|
|
return
|
|
} else {
|
|
final = v
|
|
}
|
|
})
|
|
|
|
ctx, cancel := context.WithTimeout(context.TODO(), 5*time.Second)
|
|
defer cancel()
|
|
if !useSandbox {
|
|
p = dbus.NewDirect(ctx, final, nil)
|
|
} else {
|
|
p = dbus.New(ctx, final, nil)
|
|
}
|
|
|
|
p.CommandContext = func(ctx context.Context) (cmd *exec.Cmd) {
|
|
return exec.CommandContext(ctx, os.Args[0], "-test.v",
|
|
"-test.run=TestHelperInit", "--", "init")
|
|
}
|
|
p.CmdF = func(v any) {
|
|
if useSandbox {
|
|
container := v.(*sandbox.Container)
|
|
if container.Args[0] != dbus.ProxyName {
|
|
panic(fmt.Sprintf("unexpected argv0 %q", os.Args[0]))
|
|
}
|
|
container.Args = append([]string{os.Args[0], "-test.run=TestHelperStub", "--"}, container.Args[1:]...)
|
|
} else {
|
|
cmd := v.(*exec.Cmd)
|
|
if cmd.Args[0] != dbus.ProxyName {
|
|
panic(fmt.Sprintf("unexpected argv0 %q", os.Args[0]))
|
|
}
|
|
cmd.Err = nil
|
|
cmd.Path = os.Args[0]
|
|
cmd.Args = append([]string{os.Args[0], "-test.run=TestHelperStub", "--"}, cmd.Args[1:]...)
|
|
}
|
|
}
|
|
p.FilterF = func(v []byte) []byte { return bytes.SplitN(v, []byte("TestHelperInit\n"), 2)[1] }
|
|
output := new(strings.Builder)
|
|
|
|
t.Run("invalid wait", func(t *testing.T) {
|
|
wantErr := "dbus: not started"
|
|
if err := p.Wait(); err == nil || err.Error() != wantErr {
|
|
t.Errorf("Wait: error = %v, wantErr %v",
|
|
err, wantErr)
|
|
}
|
|
})
|
|
|
|
t.Run("string", func(t *testing.T) {
|
|
want := "(unused dbus proxy)"
|
|
if got := p.String(); got != want {
|
|
t.Errorf("String: %q, want %q",
|
|
got, want)
|
|
return
|
|
}
|
|
})
|
|
|
|
t.Run("start", func(t *testing.T) {
|
|
if err := p.Start(); err != nil {
|
|
t.Fatalf("Start: error = %v",
|
|
err)
|
|
}
|
|
|
|
t.Run("string", func(t *testing.T) {
|
|
wantSubstr := fmt.Sprintf("%s -test.run=TestHelperStub -- --args=3 --fd=4", os.Args[0])
|
|
if useSandbox {
|
|
wantSubstr = fmt.Sprintf(`argv: ["%s" "-test.run=TestHelperStub" "--" "--args=3" "--fd=4"], flags: 0x0, seccomp: 0x3e`, os.Args[0])
|
|
}
|
|
if got := p.String(); !strings.Contains(got, wantSubstr) {
|
|
t.Errorf("String: %q, want %q",
|
|
got, wantSubstr)
|
|
return
|
|
}
|
|
})
|
|
|
|
t.Run("wait", func(t *testing.T) {
|
|
done := make(chan struct{})
|
|
go func() {
|
|
if err := p.Wait(); err != nil {
|
|
t.Errorf("Wait: error = %v\noutput: %s",
|
|
err, output.String())
|
|
}
|
|
close(done)
|
|
}()
|
|
p.Close()
|
|
<-done
|
|
})
|
|
})
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestHelperInit(t *testing.T) {
|
|
if len(os.Args) != 5 || os.Args[4] != "init" {
|
|
return
|
|
}
|
|
sandbox.SetOutput(fmsg.Output{})
|
|
sandbox.Init(fmsg.Prepare, internal.InstallFmsg)
|
|
}
|