summaryrefslogtreecommitdiff
path: root/integrationtests/xattr_test.go
blob: 2ba30ac9c48921ec3e264e6faef44ff4627d16a9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
package integrationtests

import "testing"

// xattrTraceArgs restricts tracing to the getxattrat tracepoints so the test is
// not perturbed by unrelated xattr/open traffic.
var xattrTraceArgs = []string{"-trace-syscalls", "getxattrat,setxattr,openat"}

// xattrListTraceArgs restricts tracing to the listxattrat tracepoints so the
// test is not perturbed by unrelated xattr/open traffic.
var xattrListTraceArgs = []string{"-trace-syscalls", "listxattrat,setxattr,openat"}

// TestXattrGetxattrat verifies ior traces getxattrat(2) (Linux 6.13+)
// end-to-end. getxattrat takes a dirfd plus a real filesystem path at args[1]
// (NOT args[0]=dfd) and an xattr NAME at args[3]; only the path must be
// captured. The path is read on syscall entry, so enter_getxattrat must carry
// the file path "xattrfile.txt" and never the xattr name "user.ior".
func TestXattrGetxattrat(t *testing.T) {
	result, _ := runScenarioResultWithIorArgs(t, "xattr-getxattrat", []ExpectedEvent{
		{
			PathContains: "xattrfile.txt",
			Tracepoint:   "enter_getxattrat",
			Comm:         "ioworkload",
			MinCount:     1,
		},
	}, xattrTraceArgs)

	// The captured path must be the filesystem path, never the xattr name.
	for _, rec := range result.Records {
		if rec.TraceID.String() == "enter_getxattrat" && rec.Path == "user.ior" {
			t.Errorf("getxattrat captured xattr name %q as path instead of file path", rec.Path)
		}
	}

	// getxattrat returns the xattr value size in bytes; ior READ-classifies the
	// exit, so the recorded byte count must reflect the 16-byte value written by
	// the workload (consistent with getxattr/lgetxattr/fgetxattr).
	exp := ExpectedEvent{Tracepoint: "enter_getxattrat", Comm: "ioworkload"}
	assertEventBytesAtLeast(t, result, exp, uint64(len("getxattrat-value")))
	assertEventDurationPositive(t, result, exp)
}

// TestXattrListxattrat verifies ior traces listxattrat(2) (Linux 6.13+)
// end-to-end. listxattrat takes a dirfd plus a real filesystem path at args[1]
// (NOT args[0]=dfd); only the path must be captured. The path is read on
// syscall entry, so enter_listxattrat must carry the file path "xattrfile.txt".
func TestXattrListxattrat(t *testing.T) {
	result, _ := runScenarioResultWithIorArgs(t, "xattr-listxattrat", []ExpectedEvent{
		{
			PathContains: "xattrfile.txt",
			Tracepoint:   "enter_listxattrat",
			Comm:         "ioworkload",
			MinCount:     1,
		},
	}, xattrListTraceArgs)

	// listxattrat returns the size in bytes of the xattr name list; ior
	// READ-classifies the exit, so the recorded byte count must reflect at least
	// the NUL-terminated "user.ior" name set by the workload (consistent with
	// listxattr/llistxattr/flistxattr).
	exp := ExpectedEvent{Tracepoint: "enter_listxattrat", Comm: "ioworkload"}
	assertEventBytesAtLeast(t, result, exp, uint64(len("user.ior")+1))
	assertEventDurationPositive(t, result, exp)
}