msgx_darwin_test.go 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. //go:build !ios
  2. package msgx
  3. import (
  4. "bytes"
  5. "syscall"
  6. "testing"
  7. "github.com/stretchr/testify/assert"
  8. "github.com/stretchr/testify/require"
  9. "golang.org/x/sys/unix"
  10. )
  11. // TestAvailable pins that dlsym finds both calls in this macOS's libSystem, so the batched paths are live.
  12. func TestAvailable(t *testing.T) {
  13. assert.True(t, Available())
  14. }
  15. // TestSendRecvRoundTrip pins the libSystem calling path end to end: a batch goes out through sendmsg_x in one
  16. // call and comes back through recvmsg_x in one call, each message whole, in order, with Datalen set.
  17. func TestSendRecvRoundTrip(t *testing.T) {
  18. fds, err := unix.Socketpair(unix.AF_UNIX, unix.SOCK_DGRAM, 0)
  19. require.NoError(t, err)
  20. t.Cleanup(func() {
  21. _ = unix.Close(fds[0])
  22. _ = unix.Close(fds[1])
  23. })
  24. // A dropped datagram fails the receive instead of hanging it.
  25. require.NoError(t, unix.SetsockoptTimeval(fds[1], unix.SOL_SOCKET, unix.SO_RCVTIMEO, &unix.Timeval{Sec: 2}))
  26. const n = 5
  27. var want [n][]byte
  28. var iovs [n]unix.Iovec
  29. hdrs := make([]Hdr, n)
  30. for i := range n {
  31. want[i] = bytes.Repeat([]byte{byte(i + 1)}, 10+i)
  32. iovs[i] = unix.Iovec{Base: &want[i][0]}
  33. iovs[i].SetLen(len(want[i]))
  34. hdrs[i] = Hdr{Iov: &iovs[i], Iovlen: 1}
  35. }
  36. sent, errno := Send(uintptr(fds[0]), hdrs, 0)
  37. require.Zero(t, errno)
  38. require.Equal(t, n, sent)
  39. var bufs [n + 1][64]byte
  40. var riovs [n + 1]unix.Iovec
  41. rhdrs := make([]Hdr, n+1)
  42. for i := range rhdrs {
  43. riovs[i] = unix.Iovec{Base: &bufs[i][0]}
  44. riovs[i].SetLen(len(bufs[i]))
  45. rhdrs[i] = Hdr{Iov: &riovs[i], Iovlen: 1}
  46. }
  47. got, errno := Recv(uintptr(fds[1]), rhdrs, 0)
  48. require.Zero(t, errno)
  49. require.Equal(t, n, got)
  50. for i := range n {
  51. l := int(rhdrs[i].Datalen)
  52. assert.Equal(t, want[i], bufs[i][:l], "message %d", i)
  53. }
  54. }
  55. // TestEmptyBatch pins that an empty batch is refused before it reaches the kernel.
  56. func TestEmptyBatch(t *testing.T) {
  57. _, errno := Send(0, nil, 0)
  58. assert.Equal(t, syscall.EINVAL, errno)
  59. _, errno = Recv(0, nil, 0)
  60. assert.Equal(t, syscall.EINVAL, errno)
  61. }