On Tue, Jun 06, 2023 at 06:09:09PM +0200, Laszlo Ersek wrote:
only superficial comments:
On 6/6/23 13:22, Richard W.M. Jones wrote:
[...]
> diff --git a/tests/test-curl-head-forbidden.c
b/tests/test-curl-head-forbidden.c
> new file mode 100644
> index 000000000..16b1f0533
> --- /dev/null
> +++ b/tests/test-curl-head-forbidden.c
> @@ -0,0 +1,134 @@
> +/* nbdkit
> + * Copyright Red Hat
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions are
> + * met:
> + *
> + * * Redistributions of source code must retain the above copyright
> + * notice, this list of conditions and the following disclaimer.
> + *
> + * * Redistributions in binary form must reproduce the above copyright
> + * notice, this list of conditions and the following disclaimer in the
> + * documentation and/or other materials provided with the distribution.
> + *
> + * * Neither the name of Red Hat nor the names of its contributors may be
> + * used to endorse or promote products derived from this software without
> + * specific prior written permission.
> + *
> + * THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS''
AND
> + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
> + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
> + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR
> + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
> + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
> + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
> + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
> + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
> + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
> + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
> + * SUCH DAMAGE.
> + */
> +
> +/* Test curl plugin against a simulated webserver which responds with
> + * 403 Forbidden to HEAD requests, but allows the GET method.
> + */
> +
> +#include <config.h>
> +
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <stdbool.h>
> +#include <stdint.h>
> +#include <inttypes.h>
> +#include <string.h>
> +#include <unistd.h>
> +#include <errno.h>
> +#include <sys/stat.h>
> +
> +#include <libnbd.h>
> +
> +#include "cleanup.h"
> +#include "web-server.h"
> +
> +#include "test.h"
> +
> +static char buf[1024];
> +
> +int
> +main (int argc, char *argv[])
> +{
> + struct stat statbuf;
> + const char *sockpath;
> + struct nbd_handle *nbd;
> + CLEANUP_FREE char *usp_param = NULL;
> + int64_t size;
> +
> +#ifndef HAVE_CURLOPT_UNIX_SOCKET_PATH
> + fprintf (stderr, "%s: curl does not support
CURLOPT_UNIX_SOCKET_PATH\n",
> + program_name);
> + exit (77);
> +#endif
> +
> + if (stat ("disk", &statbuf) == -1) {
> + if (errno == ENOENT) {
> + fprintf (stderr, "%s: test skipped because \"disk\" is
missing\n",
> + program_name);
> + exit (77);
> + }
> + perror ("disk");
> + exit (EXIT_FAILURE);
> + }
> +
> + sockpath = web_server ("disk", NULL, true);
> + if (sockpath == NULL) {
> + fprintf (stderr, "%s: could not start web server thread\n",
program_name);
> + exit (EXIT_FAILURE);
> + }
> +
> + nbd = nbd_create ();
> + if (nbd == NULL) {
> + fprintf (stderr, "%s\n", nbd_get_error ());
> + exit (EXIT_FAILURE);
> + }
> +
> + /* Start nbdkit. */
> + if (asprintf (&usp_param, "unix-socket-path=%s", sockpath) == -1)
{
> + perror ("asprintf");
> + exit (EXIT_FAILURE);
> + }
> + if (nbd_connect_command (nbd,
> + (char *[]) {
> + "nbdkit", "-s",
"--exit-with-parent", "-v",
> + "curl",
> + "-D", "curl.verbose=1",
> + "http://localhost/disk",
> + usp_param, /* unix-socket-path=... */
> + NULL }) == -1) {
> + fprintf (stderr, "%s\n", nbd_get_error ());
> + exit (EXIT_FAILURE);
> + }
> +
> + /* Check the size is expected. */
> + size = nbd_get_size (nbd);
> + if (size == -1) {
> + fprintf (stderr, "%s\n", nbd_get_error ());
> + exit (EXIT_FAILURE);
> + }
> + if (size != statbuf.st_size) {
> + fprintf (stderr, "%s: incorrect export size, "
> + "expected: %" PRIu64 " actual: %" PRIi64
"\n",
> + program_name,
> + (uint64_t) statbuf.st_size, size);
> + exit (EXIT_FAILURE);
> + }
> +
> + /* Make a request. */
> + if (nbd_pread (nbd, buf, sizeof buf, 0, 0) == -1) {
> + fprintf (stderr, "%s\n", nbd_get_error ());
> + exit (EXIT_FAILURE);
> + }
> +
> + nbd_close (nbd);
> + exit (EXIT_SUCCESS);
> +}
I take it this is a small customization (more precisely, lightly
modified copy) of another (existent) test. The --find-copies-harder git
formatting option is good for presenting new code in such terms, i.e. as
a copy of another file + diffs on top. I figure the only relevant
difference would be the last, "true", argument, for web_server().
It's indeed a copy of test-curl-header-script.c. --find-copies-harder
thinks it's:
--- a/tests/test-curl-cookie-script.c
+++ b/tests/test-curl-head-forbidden.c
which makes sense as test-curl-header-script.c and
test-curl-cookie-script.c were from a common source originally.
> @@ -108,6 +112,7 @@ web_server (const char *filename,
check_request_t _check_request)
> ignore_sigpipe ();
>
> check_request = _check_request;
> + head_fails_with_403 = _head_fails_with_403;
>
> /* Open the file. */
> fd = open (filename, O_RDONLY|O_CLOEXEC);
> @@ -250,6 +255,11 @@ handle_requests (int s)
> }
> memcpy (path, &request[5], n);
> path[n] = '\0';
> + if (head_fails_with_403) {
> + send_403_forbidden (s);
> + eof = true;
> + break;
> + }
I'm not a fan of the pre-existent pattern where we both set "eof = true"
and break out of the loop. It would have to be cleaned up first, in a
different patch, but I'm not sure if we care enough.
It's a test :-) However what do you suggest? Both statements are
necessary because we have to break out of the inner for(;;) loop, run
a tiny bit of common cleanup code (just a fprintf), and then break
from the while(!eof) loop.
> +static void
> +xwrite_allow_epipe (int s, const char *buf, size_t len)
> +{
> + ssize_t r;
> +
> + while (len > 0) {
> + r = write (s, buf, len);
> + if (r == -1) {
> + if (errno != EPIPE) {
> + perror ("write");
> + exit (EXIT_FAILURE);
> + }
> + else
> + return;
> + }
exit() doesn't return, so I suggest removing the "else" (i.e., unnesting
the "return").
OK.
> + buf += r;
> + len -= r;
> + }
> +}
> +
> static void
> xpread (char *buf, size_t count, off_t offset)
> {
> diff --git a/tests/web-server.h b/tests/web-server.h
> index 36f0ea1e1..0961f4c5d 100644
> --- a/tests/web-server.h
> +++ b/tests/web-server.h
> @@ -43,6 +43,8 @@
> #ifndef NBDKIT_WEB_SERVER_H
> #define NBDKIT_WEB_SERVER_H
>
> +#include <stdbool.h>
> +
> /* Starts a web server in a background thread. The web server will
> * serve 'filename' (only) - the URL in requests is ignored.
> *
> @@ -57,10 +59,15 @@
> * The optional check_request function is called when the request is
> * received (note: not in the main thread) and can be used to perform
> * checks for example that particular headers were sent.
> + *
> + * If head_fails_with_403 == true then we simulate a server that
> + * responds to GET but fails HEAD with 403 errors, see:
> + *
https://github.com/kubevirt/containerized-data-importer/issues/2737#issue...
> */
> typedef void (*check_request_t) (const char *request);
> extern const char *web_server (const char *filename,
> - check_request_t check_request)
> + check_request_t check_request,
> + bool head_fails_with_403)
> __attribute__ ((__nonnull__ (1)));
>
> #endif /* NBDKIT_WEB_SERVER_H */
I'd prefer the introduction of this new parameter to be a separate
patch. That would isolate much the boilerplate from the relevant feature
addition.
OK.
> diff --git a/.gitignore b/.gitignore
> index e62c23d8b..49af3998f 100644
> --- a/.gitignore
> +++ b/.gitignore
> @@ -122,6 +122,7 @@ plugins/*/*.3
> /tests/test-curl
> /tests/test-curl-cookie-script
> /tests/test-curl-header-script
> +/tests/test-curl-head-forbidden
> /tests/test-data
> /tests/test-delay
> /tests/test-exit-with-parent
Reviewed-by: Laszlo Ersek <lersek(a)redhat.com>
Thanks,
Rich.
--
Richard Jones, Virtualization Group, Red Hat
http://people.redhat.com/~rjones
Read my programming and virtualization blog:
http://rwmj.wordpress.com
libguestfs lets you edit virtual machines. Supports shell scripting,
bindings from many languages.
http://libguestfs.org