package landlock_test

import (
	"testing"
	"unsafe"

	"hakurei.app/internal/landlock"
)

func TestLandlockString(t *testing.T) {
	t.Parallel()

	testCases := []struct {
		name        string
		rulesetAttr *landlock.RulesetAttr
		want        string
	}{
		{"nil", nil, "NULL"},
		{"zero", new(landlock.RulesetAttr), "0"},
		{"some", &landlock.RulesetAttr{Scoped: landlock.LANDLOCK_SCOPE_SIGNAL}, "scoped: signal"},
		{"set", &landlock.RulesetAttr{
			HandledAccessFS:  landlock.LANDLOCK_ACCESS_FS_MAKE_SYM | landlock.LANDLOCK_ACCESS_FS_IOCTL_DEV | landlock.LANDLOCK_ACCESS_FS_WRITE_FILE,
			HandledAccessNet: landlock.LANDLOCK_ACCESS_NET_BIND_TCP,
			Scoped:           landlock.LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET | landlock.LANDLOCK_SCOPE_SIGNAL,
		}, "fs: write_file make_sym fs_ioctl_dev, net: bind_tcp, scoped: abstract_unix_socket signal"},
		{"all", &landlock.RulesetAttr{
			HandledAccessFS: landlock.LANDLOCK_ACCESS_FS_EXECUTE |
				landlock.LANDLOCK_ACCESS_FS_WRITE_FILE |
				landlock.LANDLOCK_ACCESS_FS_READ_FILE |
				landlock.LANDLOCK_ACCESS_FS_READ_DIR |
				landlock.LANDLOCK_ACCESS_FS_REMOVE_DIR |
				landlock.LANDLOCK_ACCESS_FS_REMOVE_FILE |
				landlock.LANDLOCK_ACCESS_FS_MAKE_CHAR |
				landlock.LANDLOCK_ACCESS_FS_MAKE_DIR |
				landlock.LANDLOCK_ACCESS_FS_MAKE_REG |
				landlock.LANDLOCK_ACCESS_FS_MAKE_SOCK |
				landlock.LANDLOCK_ACCESS_FS_MAKE_FIFO |
				landlock.LANDLOCK_ACCESS_FS_MAKE_BLOCK |
				landlock.LANDLOCK_ACCESS_FS_MAKE_SYM |
				landlock.LANDLOCK_ACCESS_FS_REFER |
				landlock.LANDLOCK_ACCESS_FS_TRUNCATE |
				landlock.LANDLOCK_ACCESS_FS_IOCTL_DEV,
			HandledAccessNet: landlock.LANDLOCK_ACCESS_NET_BIND_TCP |
				landlock.LANDLOCK_ACCESS_NET_CONNECT_TCP,
			Scoped: landlock.LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET |
				landlock.LANDLOCK_SCOPE_SIGNAL,
		}, "fs: execute write_file read_file read_dir remove_dir remove_file make_char make_dir make_reg make_sock make_fifo make_block make_sym fs_refer fs_truncate fs_ioctl_dev, net: bind_tcp connect_tcp, scoped: abstract_unix_socket signal"},
	}
	for _, tc := range testCases {
		t.Run(tc.name, func(t *testing.T) {
			t.Parallel()
			if got := tc.rulesetAttr.String(); got != tc.want {
				t.Errorf("String: %s, want %s", got, tc.want)
			}
		})
	}
}

func TestLandlockAttrSize(t *testing.T) {
	t.Parallel()
	want := 24
	if got := unsafe.Sizeof(landlock.RulesetAttr{}); got != uintptr(want) {
		t.Errorf("Sizeof: %d, want %d", got, want)
	}
}
