diff options
| author | Ophestra <cat@gensokyo.uk> | 2026-10-13 18:55:52 +0900 |
|---|---|---|
| committer | Ophestra <cat@gensokyo.uk> | 2026-10-13 18:55:52 +0900 |
| commit | 0abf367b1334b76f5e8f989cf0c07b5d00b25868 (patch) | |
| tree | 9d78aae80b86770762e5d86358fd1d89c18c3f35 /internal/acl/acl_test.go | |
| parent | 11e395a1a7453b93c695e849bd93d8c2c0af6aef (diff) | |
internal/acl: skip superfluous acl_set_file
This slightly reduces startup latency.
Signed-off-by: Ophestra <cat@gensokyo.uk>
Diffstat (limited to 'internal/acl/acl_test.go')
| -rw-r--r-- | internal/acl/acl_test.go | 136 |
1 files changed, 89 insertions, 47 deletions
diff --git a/internal/acl/acl_test.go b/internal/acl/acl_test.go index 60c4b702..6e84e832 100644 --- a/internal/acl/acl_test.go +++ b/internal/acl/acl_test.go @@ -22,7 +22,7 @@ const testFileName = "acl.test" var ( uid = os.Geteuid() - cred = int32(os.Geteuid()) + cred = int32(uid) ) func TestUpdate(t *testing.T) { @@ -31,7 +31,7 @@ func TestUpdate(t *testing.T) { if err := os.WriteFile(name, nil, 0); err != nil { t.Fatal(err) } - if err := acl.Update(name, os.Geteuid()); errors.Is(err, syscall.ENOTSUP) { + if err := acl.Update(name, uid, 0); errors.Is(err, syscall.ENOTSUP) { t.Skip(err) } } @@ -60,7 +60,7 @@ func TestUpdate(t *testing.T) { }) t.Run("default clear mask", func(t *testing.T) { - if err := acl.Update(testFilePath, uid); err != nil { + if err := acl.Update(testFilePath, uid, 0); err != nil { t.Fatalf("Update: error = %v", err) } if cur = getfacl(t, testFilePath); len(cur) != 4 { @@ -69,7 +69,7 @@ func TestUpdate(t *testing.T) { }) t.Run("default clear consistency", func(t *testing.T) { - if err := acl.Update(testFilePath, uid); err != nil { + if err := acl.Update(testFilePath, uid, 0); err != nil { t.Fatalf("Update: error = %v", err) } if val := getfacl(t, testFilePath); !reflect.DeepEqual(val, cur) { @@ -77,34 +77,78 @@ func TestUpdate(t *testing.T) { } }) - testUpdate(t, testFilePath, "r--", cur, fAclPermRead, acl.Read) - testUpdate(t, testFilePath, "-w-", cur, fAclPermWrite, acl.Write) - testUpdate(t, testFilePath, "--x", cur, fAclPermExecute, acl.Execute) - testUpdate(t, testFilePath, "-wx", cur, fAclPermWrite|fAclPermExecute, acl.Write, acl.Execute) - testUpdate(t, testFilePath, "r-x", cur, fAclPermRead|fAclPermExecute, acl.Read, acl.Execute) - testUpdate(t, testFilePath, "rw-", cur, fAclPermRead|fAclPermWrite, acl.Read, acl.Write) - testUpdate(t, testFilePath, "rwx", cur, fAclPermRead|fAclPermWrite|fAclPermExecute, acl.Read, acl.Write, acl.Execute) + testUpdate(t, testFilePath, "r--", "", cur, acl.Read, true) + testUpdate(t, testFilePath, "-w-", "", cur, acl.Write, true) + testUpdate(t, testFilePath, "--x", "", cur, acl.Execute, true) + + testUpdate( + t, testFilePath, "-wx", "", cur, + acl.Write|acl.Execute, + true, + ) + testUpdate( + t, testFilePath, "r-x", "", cur, + acl.Read|acl.Execute, + true, + ) + testUpdate( + t, testFilePath, "rw-", "", cur, + acl.Read|acl.Write, + true, + ) + testUpdate( + t, testFilePath, "rwx", "", cur, + acl.Read|acl.Write|acl.Execute, + true, + ) + + for i := range 16 { + testUpdate( + t, testFilePath, "r-x", " "+strconv.Itoa(i), cur, + acl.Read|acl.Execute, + false, + ) + } + + testUpdate( + t, testFilePath, "rwx", " cleanup", cur, + acl.Read|acl.Write|acl.Execute, + true, + ) } -func testUpdate(t *testing.T, testFilePath, name string, cur []*getFAclResp, val fAclPerm, perms ...acl.Perm) { - t.Run(name, func(t *testing.T) { - t.Cleanup(func() { - if err := acl.Update(testFilePath, uid); err != nil { - t.Fatalf("Update: error = %v", err) - } - if v := getfacl(t, testFilePath); !reflect.DeepEqual(v, cur) { - t.Fatalf("Update: %v, want %v", v, cur) - } - }) +func testUpdate( + t *testing.T, + testFilePath, name, suffix string, + cur []*getFACLResp, + perms acl.Perm, + cleanup bool, +) { + t.Run(name+suffix, func(t *testing.T) { + if cleanup { + t.Cleanup(func() { + if err := acl.Update(testFilePath, uid, 0); err != nil { + t.Fatalf("Update: error = %v", err) + } + if v := getfacl(t, testFilePath); !reflect.DeepEqual(v, cur) { + t.Fatalf("Update: %v, want %v", v, cur) + } + }) + } - if err := acl.Update(testFilePath, uid, perms...); err != nil { + if err := acl.Update(testFilePath, uid, perms); err != nil { t.Fatalf("Update: error = %v", err) } r := respByCred(getfacl(t, testFilePath), fAclTypeUser, cred) if r == nil { t.Fatalf("Update did not add an ACL entry") } - if !r.equals(fAclTypeUser, cred, val) { + + if !r.equals(&getFACLResp{ + typ: fAclTypeUser, + cred: cred, + val: perms, + }) { t.Fatalf("Update(%s) = %s", name, r) } }) @@ -113,31 +157,24 @@ func testUpdate(t *testing.T, testFilePath, name string, cur []*getFAclResp, val type ( getFAclInvocation struct { cmd *exec.Cmd - val []*getFAclResp + val []*getFACLResp pe []error } - getFAclResp struct { + getFACLResp struct { typ fAclType cred int32 - val fAclPerm + val acl.Perm raw []byte } - fAclPerm uintptr fAclType uint8 ) const fAclBufSize = 16 const ( - fAclPermRead fAclPerm = 1 << iota - fAclPermWrite - fAclPermExecute -) - -const ( fAclTypeUser fAclType = iota fAclTypeGroup fAclTypeMask @@ -149,7 +186,13 @@ func (c *getFAclInvocation) run(name string) error { panic("attempted to run twice") } - c.cmd = exec.Command("getfacl", "--omit-header", "--absolute-names", "--numeric", name) + c.cmd = exec.Command( + "getfacl", + "--omit-header", + "--absolute-names", + "--numeric", + name, + ) c.cmd.Stderr = os.Stderr scanErr := make(chan error, 1) @@ -166,18 +209,17 @@ func (c *getFAclInvocation) run(name string) error { return errors.Join(<-scanErr, c.cmd.Wait()) } -func (c *getFAclInvocation) parse(pipe io.Reader, scanErr chan error) { - c.val = make([]*getFAclResp, 0, 4+fAclBufSize) +func (c *getFAclInvocation) parse(r io.Reader, scanErr chan error) { + c.val = make([]*getFACLResp, 0, 4+fAclBufSize) - s := bufio.NewScanner(pipe) + s := bufio.NewScanner(r) for s.Scan() { fields := bytes.SplitN(s.Bytes(), []byte{':'}, 3) if len(fields) != 3 { continue } - resp := getFAclResp{} - + var resp getFACLResp switch string(fields[0]) { case "user": resp.typ = fAclTypeUser @@ -213,7 +255,7 @@ func (c *getFAclInvocation) parse(pipe io.Reader, scanErr chan error) { } else { switch fields[2][0] { case 'r': - resp.val |= fAclPermRead + resp.val |= acl.Read case '-': default: c.pe = append(c.pe, fmt.Errorf("invalid perm %v", fields[2][0])) @@ -221,7 +263,7 @@ func (c *getFAclInvocation) parse(pipe io.Reader, scanErr chan error) { } switch fields[2][1] { case 'w': - resp.val |= fAclPermWrite + resp.val |= acl.Write case '-': default: c.pe = append(c.pe, fmt.Errorf("invalid perm %v", fields[2][1])) @@ -229,7 +271,7 @@ func (c *getFAclInvocation) parse(pipe io.Reader, scanErr chan error) { } switch fields[2][2] { case 'x': - resp.val |= fAclPermExecute + resp.val |= acl.Execute case '-': default: c.pe = append(c.pe, fmt.Errorf("invalid perm %v", fields[2][2])) @@ -244,7 +286,7 @@ func (c *getFAclInvocation) parse(pipe io.Reader, scanErr chan error) { scanErr <- s.Err() } -func (r *getFAclResp) String() string { +func (r *getFACLResp) String() string { if r.raw != nil && len(r.raw) > 0 { return string(r.raw) } @@ -252,11 +294,11 @@ func (r *getFAclResp) String() string { return "(user-initialised resp value)" } -func (r *getFAclResp) equals(typ fAclType, cred int32, val fAclPerm) bool { - return r.typ == typ && r.cred == cred && r.val == val +func (r *getFACLResp) equals(v *getFACLResp) bool { + return r.typ == v.typ && r.cred == v.cred && r.val == v.val } -func getfacl(t *testing.T, name string) []*getFAclResp { +func getfacl(t *testing.T, name string) []*getFACLResp { c := new(getFAclInvocation) if err := c.run(name); err != nil { t.Fatalf("getfacl: error = %v", err) @@ -267,7 +309,7 @@ func getfacl(t *testing.T, name string) []*getFAclResp { return c.val } -func respByCred(v []*getFAclResp, typ fAclType, cred int32) *getFAclResp { +func respByCred(v []*getFACLResp, typ fAclType, cred int32) *getFACLResp { j := -1 for i, r := range v { if r.typ == typ && r.cred == cred { |
