msgx_darwin_test.go 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. package msgx
  2. import (
  3. "bytes"
  4. "syscall"
  5. "testing"
  6. "unsafe"
  7. "github.com/stretchr/testify/assert"
  8. "github.com/stretchr/testify/require"
  9. "golang.org/x/sys/unix"
  10. )
  11. // TestHdrLayout pins Hdr to struct msghdr_x's LP64 layout: 56 bytes, Datalen last at 48.
  12. func TestHdrLayout(t *testing.T) {
  13. var h Hdr
  14. assert.EqualValues(t, 56, unsafe.Sizeof(h))
  15. assert.EqualValues(t, 48, unsafe.Offsetof(h.Datalen))
  16. }
  17. // TestSendRecvRoundTrip sends a batch through sendmsg_x in one call and reads it back through recvmsg_x in one
  18. // call, each message whole, in order, with Datalen set.
  19. func TestSendRecvRoundTrip(t *testing.T) {
  20. fds, err := unix.Socketpair(unix.AF_UNIX, unix.SOCK_DGRAM, 0)
  21. require.NoError(t, err)
  22. t.Cleanup(func() {
  23. _ = unix.Close(fds[0])
  24. _ = unix.Close(fds[1])
  25. })
  26. // A dropped datagram fails the receive instead of hanging it.
  27. require.NoError(t, unix.SetsockoptTimeval(fds[1], unix.SOL_SOCKET, unix.SO_RCVTIMEO, &unix.Timeval{Sec: 2}))
  28. const n = 5
  29. var want [n][]byte
  30. var iovs [n]unix.Iovec
  31. hdrs := make([]Hdr, n)
  32. for i := range n {
  33. want[i] = bytes.Repeat([]byte{byte(i + 1)}, 10+i)
  34. iovs[i] = unix.Iovec{Base: &want[i][0]}
  35. iovs[i].SetLen(len(want[i]))
  36. hdrs[i] = Hdr{Iov: &iovs[i], Iovlen: 1}
  37. }
  38. sent, errno := Send(uintptr(fds[0]), hdrs)
  39. require.Zero(t, errno)
  40. require.Equal(t, n, sent)
  41. var bufs [n + 1][64]byte
  42. var riovs [n + 1]unix.Iovec
  43. rhdrs := make([]Hdr, n+1)
  44. for i := range rhdrs {
  45. riovs[i] = unix.Iovec{Base: &bufs[i][0]}
  46. riovs[i].SetLen(len(bufs[i]))
  47. rhdrs[i] = Hdr{Iov: &riovs[i], Iovlen: 1}
  48. }
  49. got, errno := Recv(uintptr(fds[1]), rhdrs)
  50. require.Zero(t, errno)
  51. require.Equal(t, n, got)
  52. for i := range n {
  53. l := int(rhdrs[i].Datalen)
  54. assert.Equal(t, want[i], bufs[i][:l], "message %d", i)
  55. }
  56. }
  57. // TestEmptyBatch pins that an empty batch is refused before it reaches the kernel.
  58. func TestEmptyBatch(t *testing.T) {
  59. _, errno := Send(0, nil)
  60. assert.Equal(t, syscall.EINVAL, errno)
  61. _, errno = Recv(0, nil)
  62. assert.Equal(t, syscall.EINVAL, errno)
  63. }
  64. func TestUnsupported(t *testing.T) {
  65. for _, e := range []syscall.Errno{syscall.ENOSYS, syscall.EPERM, syscall.EOPNOTSUPP} {
  66. assert.True(t, Unsupported(e), "%v", e)
  67. }
  68. for _, e := range []syscall.Errno{0, syscall.EAGAIN, syscall.ENOBUFS, syscall.EINVAL} {
  69. assert.False(t, Unsupported(e), "%v", e)
  70. }
  71. }