package uevent_test

import (
	"syscall"
	"testing"

	"hakurei.app/internal/uevent"
)

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

	testCases := []struct {
		name     string
		v        uevent.Message
		want     string
		wantErr  error
		wantErrE error

		s string
	}{
		{"sample virtio-sound-pci add", uevent.Message{
			Action:  uevent.KOBJ_ADD,
			DevPath: "/devices/pci0000:00/0000:00:04.0/virtio1",
			Env: []string{
				"ACTION=add",
				"DEVPATH=/devices/pci0000:00/0000:00:04.0/virtio1",
				"SUBSYSTEM=virtio",
				"MODALIAS=virtio:d00000019v00001AF4",
				"SEQNUM=779",
			},
		}, "add@/devices/pci0000:00/0000:00:04.0/virtio1\x00" +
			"ACTION=add\x00" +
			"DEVPATH=/devices/pci0000:00/0000:00:04.0/virtio1\x00" +
			"SUBSYSTEM=virtio\x00" +
			"MODALIAS=virtio:d00000019v00001AF4\x00" +
			"SEQNUM=779\x00",
			nil, nil, `add event on /devices/pci0000:00/0000:00:04.0/virtio1:
ACTION=add
DEVPATH=/devices/pci0000:00/0000:00:04.0/virtio1
SUBSYSTEM=virtio
MODALIAS=virtio:d00000019v00001AF4
SEQNUM=779`},

		{"sample virtio-sound-pci bind", uevent.Message{
			Action:  uevent.KOBJ_BIND,
			DevPath: "/devices/pci0000:00/0000:00:04.0",
			Env: []string{
				"ACTION=bind",
				"DEVPATH=/devices/pci0000:00/0000:00:04.0",
				"SUBSYSTEM=pci",
				"DRIVER=virtio-pci",
				"PCI_CLASS=40100",
				"PCI_ID=1AF4:1059",
				"PCI_SUBSYS_ID=1AF4:1100",
				"PCI_SLOT_NAME=0000:00:04.0",
				"MODALIAS=pci:v00001AF4d00001059sv00001AF4sd00001100bc04sc01i00",
				"SEQNUM=780",
			},
		}, "bind@/devices/pci0000:00/0000:00:04.0\x00" +
			"ACTION=bind\x00" +
			"DEVPATH=/devices/pci0000:00/0000:00:04.0\x00" +
			"SUBSYSTEM=pci\x00" +
			"DRIVER=virtio-pci\x00" +
			"PCI_CLASS=40100\x00" +
			"PCI_ID=1AF4:1059\x00" +
			"PCI_SUBSYS_ID=1AF4:1100\x00" +
			"PCI_SLOT_NAME=0000:00:04.0\x00" +
			"MODALIAS=pci:v00001AF4d00001059sv00001AF4sd00001100bc04sc01i00\x00" +
			"SEQNUM=780\x00", nil, nil, `bind event on /devices/pci0000:00/0000:00:04.0:
ACTION=bind
DEVPATH=/devices/pci0000:00/0000:00:04.0
SUBSYSTEM=pci
DRIVER=virtio-pci
PCI_CLASS=40100
PCI_ID=1AF4:1059
PCI_SUBSYS_ID=1AF4:1100
PCI_SLOT_NAME=0000:00:04.0
MODALIAS=pci:v00001AF4d00001059sv00001AF4sd00001100bc04sc01i00
SEQNUM=780`},

		{"zero devpath env", uevent.Message{
			Action: uevent.KOBJ_MOVE,
		}, "move@\x00", nil, nil, "move event:"},

		{"d final NUL e bad action", uevent.Message{
			Action: 0xbad,
		}, "move@\x00truncated", &uevent.MessageError{
			Data:    "move@\x00truncated",
			Section: "truncated",
			Kind:    uevent.MErrorKindFinalNUL,
		}, syscall.EINVAL, "unsupported kobject_action 2989 event:"},

		{"bad action", uevent.Message{
			Action: 0xbad,
		}, "nonexistent@\x00", uevent.UnsupportedActionError(
			"nonexistent",
		), syscall.EINVAL, "unsupported kobject_action 2989 event:"},

		{"d header sep e bad action", uevent.Message{
			Action: 0xbad,
		}, "move\x00", &uevent.MessageError{
			Data:    "move\x00",
			Section: "move",
			Kind:    uevent.MErrorKindHeaderSep,
		}, syscall.EINVAL, "unsupported kobject_action 2989 event:"},

		{"d missing header e bad action", uevent.Message{
			Action: 0xbad,
		}, "move", uevent.MissingHeaderError(
			"move",
		), syscall.EINVAL, "unsupported kobject_action 2989 event:"},
	}
	for _, tc := range testCases {
		t.Run(tc.name, func(t *testing.T) {
			t.Parallel()

			adeB(t, "", tc.v, tc.want, tc.wantErr, tc.wantErrE)
			t.Run("string", func(t *testing.T) {
				if got := tc.v.String(); got != tc.s {
					t.Errorf("String: %q, want %q", got, tc.s)
				}
			})
		})
	}
}
