xref: /aosp_15_r20/external/libcap/psx/psx_test.go (revision 2810ac1b38eead2603277920c78344c84ddf3aff)
1*2810ac1bSKiyoung Kimpackage psx
2*2810ac1bSKiyoung Kim
3*2810ac1bSKiyoung Kimimport (
4*2810ac1bSKiyoung Kim	"runtime"
5*2810ac1bSKiyoung Kim	"sync"
6*2810ac1bSKiyoung Kim	"syscall"
7*2810ac1bSKiyoung Kim	"testing"
8*2810ac1bSKiyoung Kim)
9*2810ac1bSKiyoung Kim
10*2810ac1bSKiyoung Kimfunc TestSyscall3(t *testing.T) {
11*2810ac1bSKiyoung Kim	want := syscall.Getpid()
12*2810ac1bSKiyoung Kim	if got, _, err := Syscall3(syscall.SYS_GETPID, 0, 0, 0); err != 0 {
13*2810ac1bSKiyoung Kim		t.Errorf("failed to get PID via libpsx: %v", err)
14*2810ac1bSKiyoung Kim	} else if int(got) != want {
15*2810ac1bSKiyoung Kim		t.Errorf("pid mismatch: got=%d want=%d", got, want)
16*2810ac1bSKiyoung Kim	}
17*2810ac1bSKiyoung Kim	if got, _, err := Syscall3(syscall.SYS_CAPGET, 0, 0, 0); err != 14 {
18*2810ac1bSKiyoung Kim		t.Errorf("malformed capget returned %d: %v (want 14: %v)", err, err, syscall.Errno(14))
19*2810ac1bSKiyoung Kim	} else if ^got != 0 {
20*2810ac1bSKiyoung Kim		t.Errorf("malformed capget did not return -1, got=%d", got)
21*2810ac1bSKiyoung Kim	}
22*2810ac1bSKiyoung Kim}
23*2810ac1bSKiyoung Kim
24*2810ac1bSKiyoung Kimfunc TestSyscall6(t *testing.T) {
25*2810ac1bSKiyoung Kim	want := syscall.Getpid()
26*2810ac1bSKiyoung Kim	if got, _, err := Syscall6(syscall.SYS_GETPID, 0, 0, 0, 0, 0, 0); err != 0 {
27*2810ac1bSKiyoung Kim		t.Errorf("failed to get PID via libpsx: %v", err)
28*2810ac1bSKiyoung Kim	} else if int(got) != want {
29*2810ac1bSKiyoung Kim		t.Errorf("pid mismatch: got=%d want=%d", got, want)
30*2810ac1bSKiyoung Kim	}
31*2810ac1bSKiyoung Kim	if got, _, err := Syscall6(syscall.SYS_CAPGET, 0, 0, 0, 0, 0, 0); err != 14 {
32*2810ac1bSKiyoung Kim		t.Errorf("malformed capget errno %d: %v (want 14: %v)", err, err, syscall.Errno(14))
33*2810ac1bSKiyoung Kim	} else if ^got != 0 {
34*2810ac1bSKiyoung Kim		t.Errorf("malformed capget did not return -1, got=%d", got)
35*2810ac1bSKiyoung Kim	}
36*2810ac1bSKiyoung Kim}
37*2810ac1bSKiyoung Kim
38*2810ac1bSKiyoung Kim// killAThread locks the goroutine to a thread and exits. This has the
39*2810ac1bSKiyoung Kim// effect of making the go runtime terminate the thread.
40*2810ac1bSKiyoung Kimfunc killAThread(c <-chan struct{}) {
41*2810ac1bSKiyoung Kim	runtime.LockOSThread()
42*2810ac1bSKiyoung Kim	<-c
43*2810ac1bSKiyoung Kim}
44*2810ac1bSKiyoung Kim
45*2810ac1bSKiyoung Kim// Test state is mirrored as expected.
46*2810ac1bSKiyoung Kimfunc TestShared(t *testing.T) {
47*2810ac1bSKiyoung Kim	const prGetKeepCaps = 7
48*2810ac1bSKiyoung Kim	const prSetKeepCaps = 8
49*2810ac1bSKiyoung Kim
50*2810ac1bSKiyoung Kim	var wg sync.WaitGroup
51*2810ac1bSKiyoung Kim
52*2810ac1bSKiyoung Kim	newTracker := func() chan<- uintptr {
53*2810ac1bSKiyoung Kim		ch := make(chan uintptr)
54*2810ac1bSKiyoung Kim		go func() {
55*2810ac1bSKiyoung Kim			runtime.LockOSThread()
56*2810ac1bSKiyoung Kim			defer wg.Done()
57*2810ac1bSKiyoung Kim			tid := syscall.Gettid()
58*2810ac1bSKiyoung Kim			for {
59*2810ac1bSKiyoung Kim				if _, ok := <-ch; !ok {
60*2810ac1bSKiyoung Kim					break
61*2810ac1bSKiyoung Kim				}
62*2810ac1bSKiyoung Kim				val, ok := <-ch
63*2810ac1bSKiyoung Kim				if !ok {
64*2810ac1bSKiyoung Kim					break
65*2810ac1bSKiyoung Kim				}
66*2810ac1bSKiyoung Kim				got, _, e := Syscall3(syscall.SYS_PRCTL, prGetKeepCaps, 0, 0)
67*2810ac1bSKiyoung Kim				if e != 0 {
68*2810ac1bSKiyoung Kim					t.Fatalf("[%d] psx:prctl(GET_KEEPCAPS) ?= %d failed: %v", tid, val, syscall.Errno(e))
69*2810ac1bSKiyoung Kim				}
70*2810ac1bSKiyoung Kim				if got != val {
71*2810ac1bSKiyoung Kim					t.Errorf("[%d] bad keepcaps value: got=%d, want=%d", tid, got, val)
72*2810ac1bSKiyoung Kim				}
73*2810ac1bSKiyoung Kim				if _, ok := <-ch; !ok {
74*2810ac1bSKiyoung Kim					break
75*2810ac1bSKiyoung Kim				}
76*2810ac1bSKiyoung Kim			}
77*2810ac1bSKiyoung Kim		}()
78*2810ac1bSKiyoung Kim		return ch
79*2810ac1bSKiyoung Kim	}
80*2810ac1bSKiyoung Kim
81*2810ac1bSKiyoung Kim	var tracked []chan<- uintptr
82*2810ac1bSKiyoung Kim	for i := 0; i <= 10; i++ {
83*2810ac1bSKiyoung Kim		val := uintptr(i & 1)
84*2810ac1bSKiyoung Kim		if _, _, e := Syscall3(syscall.SYS_PRCTL, prSetKeepCaps, val, 0); e != 0 {
85*2810ac1bSKiyoung Kim			t.Fatalf("[%d] psx:prctl(SET_KEEPCAPS, %d) failed: %v", i, i&1, syscall.Errno(e))
86*2810ac1bSKiyoung Kim		}
87*2810ac1bSKiyoung Kim		wg.Add(1)
88*2810ac1bSKiyoung Kim		tracked = append(tracked, newTracker())
89*2810ac1bSKiyoung Kim		for _, ch := range tracked {
90*2810ac1bSKiyoung Kim			ch <- 2   // start serialization.
91*2810ac1bSKiyoung Kim			ch <- val // definitely written after change.
92*2810ac1bSKiyoung Kim			ch <- 3   // end serialization.
93*2810ac1bSKiyoung Kim		}
94*2810ac1bSKiyoung Kim	}
95*2810ac1bSKiyoung Kim	for _, ch := range tracked {
96*2810ac1bSKiyoung Kim		close(ch)
97*2810ac1bSKiyoung Kim	}
98*2810ac1bSKiyoung Kim	wg.Wait()
99*2810ac1bSKiyoung Kim}
100*2810ac1bSKiyoung Kim
101*2810ac1bSKiyoung Kim// Test to confirm no regression against:
102*2810ac1bSKiyoung Kim//
103*2810ac1bSKiyoung Kim//	https://github.com/golang/go/issues/42494
104*2810ac1bSKiyoung Kimfunc TestThreadChurn(t *testing.T) {
105*2810ac1bSKiyoung Kim	const prSetKeepCaps = 8
106*2810ac1bSKiyoung Kim
107*2810ac1bSKiyoung Kim	for j := 0; j < 4; j++ {
108*2810ac1bSKiyoung Kim		kill := (j & 1) != 0
109*2810ac1bSKiyoung Kim		sysc := (j & 2) != 0
110*2810ac1bSKiyoung Kim		t.Logf("[%d] testing kill=%v, sysc=%v", j, kill, sysc)
111*2810ac1bSKiyoung Kim		for i := 50; i > 0; i-- {
112*2810ac1bSKiyoung Kim			if kill {
113*2810ac1bSKiyoung Kim				c := make(chan struct{})
114*2810ac1bSKiyoung Kim				go killAThread(c)
115*2810ac1bSKiyoung Kim				close(c)
116*2810ac1bSKiyoung Kim			}
117*2810ac1bSKiyoung Kim			if sysc {
118*2810ac1bSKiyoung Kim				if _, _, e := Syscall3(syscall.SYS_PRCTL, prSetKeepCaps, uintptr(i&1), 0); e != 0 {
119*2810ac1bSKiyoung Kim					t.Fatalf("[%d] psx:prctl(SET_KEEPCAPS, %d) failed: %v", i, i&1, syscall.Errno(e))
120*2810ac1bSKiyoung Kim				}
121*2810ac1bSKiyoung Kim			}
122*2810ac1bSKiyoung Kim		}
123*2810ac1bSKiyoung Kim		t.Logf("[%d] PASSED kill=%v, sysc=%v", j, kill, sysc)
124*2810ac1bSKiyoung Kim	}
125*2810ac1bSKiyoung Kim}
126