/* $Id: url.c,v 1.4 2002/06/23 20:28:31 richdawe Exp $ */

/*
 * url.c - Test program for libpakke's URL handling
 * Copyright (C) 2002 by Richard Dawe
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <assert.h>

#include <libpakke/util.h>

typedef struct {
  const char *url;

  const char *expected_scheme;
  const char *expected_user;
  const char *expected_password;
  const char *expected_host;
  const char *expected_port;
  const char *expected_path;
} testcase_t;

static const testcase_t testcases[] = {
  { "http://foo/bar/bar",
    "http", "", "", "foo", "", "/bar/bar" },

  { "ftp://user:password@foo/bar/bar",
    "ftp", "user", "password", "foo", "", "/bar/bar" },

  { "http://user@foo/bar/bar",
    "http", "user", "", "foo", "", "/bar/bar" },

  { "ftp://foo:777",
    "ftp", "", "", "foo", "777", "" },

  { "file:///usr/doc/foo",
    "file", "", "", "", "", "/usr/doc/foo" },

  /* Test edge case */
  { "http://:@foo:",
    "http", "", "", "foo", "", "" },

  { NULL }
};

/* -----------------
 * - comp2compname -
 * ----------------- */

const char *
comp2compname (const url_comp_t comp)
{
  switch(comp) {
  case URL_COMP_SCHEME:   return("scheme");
  case URL_COMP_USER:     return("username");
  case URL_COMP_PASSWORD: return("password");
  case URL_COMP_HOST:     return("hostname");
  case URL_COMP_PORT:     return("portnumber");
  case URL_COMP_PATH:     return("path");
  default: assert(0);
  }

  return(NULL);
}

/* ---------------
 * - parse_error -
 * --------------- */

static void
parse_error (const url_comp_t comp, const testcase_t *testcase)
{
  fprintf(stderr,
	  "Failed to parse %s component of URL '%s'\n",
	  comp2compname(comp), testcase->url);
}

/* ----------------
 * - expect_error -
 * ---------------- */

static void
expect_error (const url_comp_t comp,
	      const testcase_t *testcase,
	      const char *expected,
	      const char *got)
{
  fprintf(stderr,
	  "Failed to correctly parse %s component of URL '%s': "
	  "expected '%s'; got '%s'\n",
	  comp2compname(comp), testcase->url, expected, got);
}

/* --------
 * - main -
 * -------- */

int
main (int argc, char *argv[])
{
  char         scheme_buf[PATH_MAX];
  char         user_buf[PATH_MAX];
  char         password_buf[PATH_MAX];
  char         host_buf[PATH_MAX];
  char         port_buf[PATH_MAX];
  char         path_buf[PATH_MAX];
  const size_t bufsize = PATH_MAX;
  int          quiet = 0;
  int          ok = 1; /* Succeed by default */
  int          i;

  /* Paranoid */
  assert(sizeof(scheme_buf)   == bufsize);
  assert(sizeof(user_buf)     == bufsize);
  assert(sizeof(password_buf) == bufsize);
  assert(sizeof(host_buf)     == bufsize);
  assert(sizeof(port_buf)     == bufsize);
  assert(sizeof(path_buf)     == bufsize);

  /* Parse arguments. */
  for (i = 1; i < argc; i++) {
    /* Quiet operation, for automatic testing. */
    if (   (strcmp(argv[i], "--quiet") == 0)
	|| (strcmp(argv[i], "-q") == 0))
      quiet = 1;
  }

  for (i = 0; testcases[i].url != NULL; i++) {
    /* Set the buffers to catch mismatches. */
    memset(scheme_buf, 'X', bufsize);
    scheme_buf[bufsize - 1] = '\0';

    memset(user_buf, 'X', bufsize);
    user_buf[bufsize - 1] = '\0';

    memset(password_buf, 'X', bufsize);
    password_buf[bufsize - 1] = '\0';

    memset(host_buf, 'X', bufsize);
    host_buf[bufsize - 1] = '\0';

    memset(port_buf, 'X', bufsize);
    port_buf[bufsize - 1] = '\0';

    memset(path_buf, 'X', bufsize);
    path_buf[bufsize - 1] = '\0';

    /* - Parse the URL - */

    /* Scheme */
    if (!get_url_component(URL_COMP_SCHEME, testcases[i].url,
			   scheme_buf, bufsize)) {
      if (!quiet)
	parse_error(URL_COMP_SCHEME, &testcases[i]);
      ok = 0;
    }

    /* User */
    if (!get_url_component(URL_COMP_USER, testcases[i].url,
			   user_buf, bufsize)) {
      if (!quiet)
	parse_error(URL_COMP_USER, &testcases[i]);
      ok = 0;
    }

    /* Password */
    if (!get_url_component(URL_COMP_PASSWORD, testcases[i].url,
			   password_buf, bufsize)) {
      if (!quiet)
	parse_error(URL_COMP_PASSWORD, &testcases[i]);
      ok = 0;
    }

    /* Host */
    if (!get_url_component(URL_COMP_HOST, testcases[i].url,
			   host_buf, bufsize)) {
      if (!quiet)
	parse_error(URL_COMP_HOST, &testcases[i]);
      ok = 0;
    }

    /* Port */
    if (!get_url_component(URL_COMP_PORT, testcases[i].url,
			   port_buf, bufsize)) {
      if (!quiet)
	parse_error(URL_COMP_PORT, &testcases[i]);
      ok = 0;
    }

    /* Path */
    if (!get_url_component(URL_COMP_PATH, testcases[i].url,
			   path_buf, bufsize)) {
      if (!quiet)
	parse_error(URL_COMP_PATH, &testcases[i]);
      ok = 0;
    }

    /* - Check that we get what we expect - */

    /* Scheme */
    if (strcmp(scheme_buf, testcases[i].expected_scheme) != 0) {
      if (!quiet) {
	expect_error(URL_COMP_SCHEME, &testcases[i],
		     testcases[i].expected_scheme, scheme_buf);
      }
      ok = 0;
    }

    /* User */
    if (strcmp(user_buf, testcases[i].expected_user) != 0) {
      if (!quiet) {
	expect_error(URL_COMP_USER, &testcases[i],
		     testcases[i].expected_user, user_buf);
      }
      ok = 0;
    }

    /* Password */
    if (strcmp(password_buf, testcases[i].expected_password) != 0) {
      if (!quiet) {
	expect_error(URL_COMP_PASSWORD, &testcases[i],
		     testcases[i].expected_password, password_buf);
      }
      ok = 0;
    }

    /* Host */
    if (strcmp(host_buf, testcases[i].expected_host) != 0) {
      if (!quiet) {
	expect_error(URL_COMP_HOST, &testcases[i],
		     testcases[i].expected_host, host_buf);
      }
      ok = 0;
    }

    /* Port */
    if (strcmp(port_buf, testcases[i].expected_port) != 0) {
      if (!quiet) {
	expect_error(URL_COMP_PORT, &testcases[i],
		     testcases[i].expected_port, port_buf);
      }
      ok = 0;
    }

    /* Path */
    if (strcmp(path_buf, testcases[i].expected_path) != 0) {
      if (!quiet) {
	expect_error(URL_COMP_PATH, &testcases[i],
		     testcases[i].expected_path, path_buf);
      }
      ok = 0;
    }
  }

  if (!ok)
    return(EXIT_FAILURE);

  return(EXIT_SUCCESS);
}
