text: /*
   * Copyright (c) 2002-2013 Balabit
   *
   * This library is free software; you can redistribute it and/or
   * modify it under the terms of the GNU Lesser General Public
   * License as published by the Free Software Foundation; either
   * version 2.1 of the License, or (at your option) any later version.
   *
   * This library is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   * Lesser General Public License for more details.
   *
   * You should have received a copy of the GNU Lesser General Public
   * License along with this library; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   *
   * As an additional exemption you are allowed to compile & link against the
   * OpenSSL libraries as published by the OpenSSL project. See the file
   * COPYING for details.
   *
   */
  #include "hostname.h"
  #include "testutils.h"
  #include "apphook.h"
  
  #include <string.h>
  #include <unistd.h>
  
  /*
   * NOTE: on WRAP_GETHOSTNAME below
   *
   * If WRAP_GETHOSTNAME is 1, this test will mock the gethostname() call in
   * order to run on all systems.  When gethostname() is mocked, it will
   * always return an FQDN as a hostname.  This in turn means, that the use of
   * DNS in detecting the FQDN is completely avoided.
   *
   * This means, that if WRAP_GETHOSTNAME is set to 1, it will run on all
   * systems, but some of the production code will not be tested.  If it is
   * set to 0, it'll only run on a host whose name is "bzorp.balabit", which
   * happens to be my notebook.
   *
   * I was thinking of mocking the DNS calls too, but that gets more and more
   * difficult, so I was left with this macro that I can change whenever I'm
   * working on the DNS related parts of the hostname.c file.
   */
  
  #define WRAP_GETHOSTNAME 1
  
  #ifdef WRAP_GETHOSTNAME
  static int (*__wrap_gethostname)(char *buf, size_t buflen);
  
  #define gethostname __wrap_gethostname
  #include "hostname.c"
  #undef gethostname
  
  static int
  __fqdn_gethostname(char *buf, size_t buflen)
  {
    strncpy(buf, "bzorp.balabit", buflen);
    return 0;
  }
  
  #else
  #include "hostname.c"
  #endif
  
  static void
  assert_hostname_fqdn(const gchar *expected)
  {
    const gchar *host;
  
    host = get_local_hostname_fqdn();
    assert_string(host, expected, "hostname values mismatch");
  }
  
  static void
  assert_hostname_short(const gchar *expected)
  {
    const gchar *host;
  
    host = get_local_hostname_short();
    assert_string(host, expected, "hostname values mismatch");
  }
  
  static void
  assert_fqdn_conversion(gchar *hostname, const gchar *expected)
  {
    gchar buf[256];
  
    g_strlcpy(buf, hostname, sizeof(buf));
    convert_hostname_to_fqdn(buf, sizeof(buf));
    assert_string(buf, expected, "hostname values mismatch");
  }
  
  static void
  assert_short_conversion(gchar *hostname, const gchar *expected)
  {
    gchar buf[256];
  
    g_strlcpy(buf, hostname, sizeof(buf));
    convert_hostname_to_short_hostname(buf, sizeof(buf));
    assert_string(buf, expected, "hostname values mismatch");
  }
  
  #define HOSTNAME_TESTCASE_WITH_DOMAIN(domain_override, x, ...) do { hostname_testcase_begin(domain_override, #x, #__VA_ARGS__); x(__VA_ARGS__); hostname_testcase_end(); } while(0)
  #define HOSTNAME_TESTCASE(x, ...) HOSTNAME_TESTCASE_WITH_DOMAIN(NULL, x, __VA_ARGS__)
  
  
  #ifdef WRAP_GETHOSTNAME
  #define wrap_gethostname() (__wrap_gethostname = __fqdn_gethostname)
  #else
  #define wrap_gethostname()
  #endif
  
  #define hostname_testcase_begin(domain_override, func, args)    \
    do                                                            \
      {                                                           \
        testcase_begin("%s(%s)", func, args);                     \
        wrap_gethostname();					\
        hostname_reinit(domain_override);				\
      }                                                           \
    while (0)
  
  #define hostname_testcase_end()                                 \
    do                                                            \
      {                                                           \
        testcase_end();                                           \
      }                                                           \
    while (0)
  
  
  static void
  test_without_domain_override_the_domain_in_the_hostname_is_used(void)
  {
    assert_fqdn_conversion("foo.bar", "foo.bar");
  }
  
  static void
  test_without_domain_override_the_local_domain_is_used_when_converting_a_short_hostname_to_fqdn(void)
  {
    assert_fqdn_conversion("foo", "foo.balabit");
  }
  
  static void
  test_without_domain_override_short_conversion_removes_any_domain_name(void)
  {
    assert_short_conversion("foo", "foo");
    assert_short_conversion("foo.bar", "foo");
    assert_short_conversion("foo.bardomain", "foo");
  }
  
  static void
  test_domain_override_short_conversion_removes_any_domain_name(void)
  {
    assert_short_conversion("foo", "foo");
    assert_short_conversion("foo.bar", "foo");
    assert_short_conversion("foo.bardomain", "foo");
  }
  
  static void
  test_system_host_and_domain_name_are_detected_properly(void)
  {
    assert_hostname_fqdn("bzorp.balabit");
    assert_hostname_short("bzorp");
    assert_fqdn_conversion("bzorp", "bzorp.balabit");
    assert_fqdn_conversion("bzorp.balabit", "bzorp.balabit");
  }
  
  static void
  test_domain_override_replaces_domain_detected_on_the_system(void)
  {
    assert_hostname_fqdn("bzorp.bardomain");
    assert_hostname_short("bzorp");
    assert_fqdn_conversion("bzorp", "bzorp.bardomain");
    assert_fqdn_conversion("bzorp.balabit", "bzorp.bardomain");
    assert_fqdn_conversion("foo", "foo.bardomain");
    assert_fqdn_conversion("foo.bar", "foo.bardomain");
  }
  
  /* this is hostname-unix specific and will probably be made conditional once the win32 bits are in */
  
  /* NOTE: we are testing a private function */
  static const gchar *
  _invoke_extract_fqdn_from_hostent(gchar *primary_host, gchar **aliases)
  {
    struct hostent hostent;
  
    memset(&hostent, 0, sizeof(hostent));
    hostent.h_name = primary_host;
    hostent.h_aliases = aliases;
    return _extract_fqdn_from_hostent(&hostent);
  }
  
  static void
  assert_extract_fqdn_from_hostent(gchar *primary_host, gchar **aliases, const gchar *expected)
  {
    assert_string(_invoke_extract_fqdn_from_hostent(primary_host, aliases), expected, "_extract_fqdn didn't return the requested hostname");
  }
  
  static void
  assert_extract_fqdn_from_hostent_fails(gchar *primary_host, gchar **aliases)
  {
    assert_null(_invoke_extract_fqdn_from_hostent(primary_host, aliases), "_extract_fqdn returned non-NULL when we expected failure");
  }
  
  static void
  test_extract_fqdn_from_hostent_uses_primary_name_if_it_is_an_fqdn(void)
  {
    gchar *aliases[] = { "bzorp", "bzorp.lan", NULL };
  
    assert_extract_fqdn_from_hostent("bzorp.balabit", aliases, "bzorp.balabit");
  }
  
  static void
  test_extract_fqdn_from_hostent_finds_the_first_fqdn_in_aliases_if_primary_is_short(void)
  {
    gchar *aliases[] = { "bzorp", "bzorp.lan", NULL };
  
    assert_extract_fqdn_from_hostent("bzorp", aliases, "bzorp.lan");
  }
  
  static void
  test_extract_fqdn_from_hostent_returns_NULL_when_no_fqdn_is_found(void)
  {
    gchar *aliases[] = { "bzorp", "foobar", NULL };
  
    assert_extract_fqdn_from_hostent_fails("bzorp", aliases);
  }
  
  int
  main(int argc G_GNUC_UNUSED, char *argv[] G_GNUC_UNUSED)
  {
    HOSTNAME_TESTCASE(test_without_domain_override_the_domain_in_the_hostname_is_used);
    HOSTNAME_TESTCASE(test_without_domain_override_the_local_domain_is_used_when_converting_a_short_hostname_to_fqdn);
    HOSTNAME_TESTCASE(test_without_domain_override_short_conversion_removes_any_domain_name);
    HOSTNAME_TESTCASE_WITH_DOMAIN("bardomain", test_domain_override_short_conversion_removes_any_domain_name);
    HOSTNAME_TESTCASE(test_system_host_and_domain_name_are_detected_properly);
    HOSTNAME_TESTCASE_WITH_DOMAIN("bardomain", test_domain_override_replaces_domain_detected_on_the_system);
    HOSTNAME_TESTCASE(test_extract_fqdn_from_hostent_uses_primary_name_if_it_is_an_fqdn);
    HOSTNAME_TESTCASE(test_extract_fqdn_from_hostent_finds_the_first_fqdn_in_aliases_if_primary_is_short);
    HOSTNAME_TESTCASE(test_extract_fqdn_from_hostent_returns_NULL_when_no_fqdn_is_found);
    return 0;
  }
  