Add [initial] functional tests for sendfile(2) as lib/libc/sys/sendfile
These testcases exercise a number of functional requirements for sendfile(2).
The testcases use IPv4 and IPv6 domain sockets with TCP, and were confirmed
functional on UFS and ZFS. UDP address family sockets cannot be used per the
sendfile(2) contract, thus using UDP sockets is outside the scope of
testing the syscall in positive cases. As seen in
:s_negative_udp_socket_test, UDP is used to test the sendfile(2) contract
to ensure that EINVAL is returned by sendfile(2).
The testcases added explicitly avoid testing out SF_SYNC due to the
complexity of verifying that support. However, this is a good next logical
item to verify.
The hdtr_positive* testcases work to a certain degree (the header
testcases pass), but the trailer testcases do not work (it is an expected
failure). In particular, the value received by the mock server doesn't match
the expected value, and instead looks something like the following (using
python array notation):
This makes me think there's a buffer overrun issue or problem with the
offset somewhere in the sendfile(2) system call, but I need to do some
other testing first to verify that the code is indeed sane, and my
assumptions/code isn't buggy.
The sbytes_negative testcases that check sbytes being set to an
invalid value resulting in EFAULT fails today as the other change
(which checks copyout(9)) has not been committed . Thus, it
should remain an expected failure (see bug 232210 for more details
on this item).
Next steps for testing sendfile(2):
- Fix the header/trailer testcases so that they pass.
- Setup if_tap interface and test with it, instead of using "localhost", per @asomers's suggestion.
- Handle short recv(2)'s in server_cat(..).
- Add SF_SYNC support.
- Add some more negative tests outside the scope of the functional contract.
Unbreak the gcc build with sendfile_test after r343362
gcc 8.x is more pedantic than clang 7.x with format strings and the tests
passed void* variables while supplying %s (which is technically
Make the affected void* variables use char* storage instead to address
this issue, as the compiler will upcast the values to char*.
MFC with: r343362
Unbreak the build on architectures where size_t isn't synonymous with uintmax_t
I should have used %zu instead of %ju with size_t types.
MFC with: r343362, r343365
Pointyhat to: ngie
Fix up r343367
I should have only changed the format qualifier with the size_t value,
length, not the other [off_t] value, dest_file_size.
MFC with: r343362, r343365, r343367
Fix reporting errors with gai_strerror(..)
The return value (err) should be checked; not the errno value.
MFC with: r343362, r343365, r343367-r343368
Avoid the DNS lookup for "localhost"
ci.FreeBSD.org does not have access to a DNS resolver/network (unlike my test
VM), so in order for the test to pass on the host, it needs to avoid the DNS
lookup by using the numeric host address representation.
MFC with: r343362, r343365, r343367-r343368, r343461
Make server_cat(..) handle short receives
In short, the prior code was far too simplistic when it came to calling recv(2)
and failed intermittently (or in the case of Jenkins, deterministically).
Handle short recv(2)s by checking the return code and incrementing the window
into the buffer by the number of received bytes. If the number of received
bytes <= 0, then bail out of the loop, and test the total number of received
bytes vs the expected number of bytes sent for equality, and base whether or
not the test passes/fails on that fact.
Remove the expected failure, now that the hdtr testcases deterministically pass
on my host after this change .
PR: 234809 , 235200
Approved by: emaste (mentor, implicit: MFC to ^/stable/11 in r344977)
Differential Revision: https://reviews.freebsd.org/D19523