119 lines
2.5 KiB
Go
119 lines
2.5 KiB
Go
package i3
|
|
|
|
import (
|
|
"context"
|
|
"math/rand"
|
|
"os"
|
|
"os/exec"
|
|
"reflect"
|
|
"testing"
|
|
|
|
"github.com/BurntSushi/xgb/xproto"
|
|
"github.com/BurntSushi/xgbutil"
|
|
)
|
|
|
|
// TestSyncSubprocess runs in a process which has been started with
|
|
// DISPLAY= pointing to an Xvfb instance with i3 -c testdata/i3.config running.
|
|
func TestSyncSubprocess(t *testing.T) {
|
|
if os.Getenv("GO_WANT_XVFB") != "1" {
|
|
t.Skip("parent process")
|
|
}
|
|
|
|
xu, err := xgbutil.NewConn()
|
|
if err != nil {
|
|
t.Fatalf("NewConn: %v", err)
|
|
}
|
|
defer xu.Conn().Close()
|
|
|
|
// Create an X11 window
|
|
X := xu.Conn()
|
|
wid, err := xproto.NewWindowId(X)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
screen := xproto.Setup(X).DefaultScreen(X)
|
|
cookie := xproto.CreateWindowChecked(
|
|
X,
|
|
screen.RootDepth,
|
|
wid,
|
|
screen.Root,
|
|
0, // x
|
|
0, // y
|
|
1, // width
|
|
1, // height
|
|
0, // border width
|
|
xproto.WindowClassInputOutput,
|
|
screen.RootVisual,
|
|
xproto.CwBackPixel|xproto.CwEventMask,
|
|
[]uint32{ // values must be in the order defined by the protocol
|
|
0xffffffff,
|
|
xproto.EventMaskStructureNotify |
|
|
xproto.EventMaskKeyPress |
|
|
xproto.EventMaskKeyRelease})
|
|
if err := cookie.Check(); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
// Synchronize i3 with that X11 window
|
|
rnd := rand.Uint32()
|
|
resp, err := Sync(SyncRequest{
|
|
Rnd: rnd,
|
|
Window: uint32(wid),
|
|
})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if got, want := resp.Success, true; got != want {
|
|
t.Fatalf("SyncResult.Success: got %v, want %v", got, want)
|
|
}
|
|
|
|
for {
|
|
ev, xerr := X.WaitForEvent()
|
|
if xerr != nil {
|
|
t.Fatalf("WaitEvent: got X11 error %v", xerr)
|
|
}
|
|
cm, ok := ev.(xproto.ClientMessageEvent)
|
|
if !ok {
|
|
t.Logf("ignoring non-ClientMessage %v", ev)
|
|
continue
|
|
}
|
|
if got, want := cm.Window, wid; got != want {
|
|
t.Errorf("sync ClientMessage.Window: got %v, want %v", got, want)
|
|
}
|
|
if got, want := cm.Data.Data32[:2], []uint32{uint32(wid), rnd}; !reflect.DeepEqual(got, want) {
|
|
t.Errorf("sync ClientMessage.Data: got %x, want %x", got, want)
|
|
}
|
|
break
|
|
}
|
|
}
|
|
|
|
func TestSync(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
ctx, canc := context.WithCancel(context.Background())
|
|
defer canc()
|
|
|
|
_, DISPLAY, err := launchXvfb(ctx)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
cleanup, err := launchI3(ctx, DISPLAY, "")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer cleanup()
|
|
|
|
cmd := exec.Command(os.Args[0], "-test.run=TestSyncSubprocess", "-test.v")
|
|
cmd.Env = []string{
|
|
"GO_WANT_XVFB=1",
|
|
"DISPLAY=" + DISPLAY,
|
|
"PATH=" + os.Getenv("PATH"),
|
|
}
|
|
cmd.Stdout = os.Stdout
|
|
cmd.Stderr = os.Stderr
|
|
if err := cmd.Run(); err != nil {
|
|
t.Fatal(err.Error())
|
|
}
|
|
}
|