text: /*
   * This file is part of libmodulemd
   * Copyright (C) 2021 Red Hat, Inc.
   *
   * Fedora-License-Identifier: MIT
   * SPDX-2.0-License-Identifier: MIT
   * SPDX-3.0-License-Identifier: MIT
   *
   * This program is free software.
   * For more information on the license, see COPYING.
   * For more information on free software, see <https://www.gnu.org/philosophy/free-sw.en.html>.
   */
  
  #include "config.h"
  #include <glib.h>
  #include <glib/gprintf.h>
  #include <stdlib.h>
  #include <locale.h>
  
  gint test_number = 0;
  gint failed = 0;
  
  gchar **validator_argv = NULL;
  gchar *validator_stdout = NULL;
  gchar *validator_stderr = NULL;
  gint validator_exit_status = 0;
  gint expected_exit_code = 0;
  gchar *expected_stdout = NULL;
  gchar *expected_stderr = NULL;
  
  static void
  ok (gboolean value, const gchar *name)
  {
    test_number++;
    if (value)
      {
        g_fprintf (stdout, "ok %d - %s\n", test_number, name);
      }
    else
      {
        failed++;
        g_fprintf (stdout, "not ok %d - %s\n", test_number, name);
      }
  }
  
  static void
  skip_n (gint tests, const gchar *reason)
  {
    while (tests-- > 0)
      {
        test_number++;
        if (!reason)
          reason = "";
        g_fprintf (stdout, "ok %d # SKIP %s\n", test_number, reason);
      }
  }
  
  static void
  skip (const gchar *reason)
  {
    test_number++;
    if (!reason)
      reason = "";
    g_fprintf (stdout, "ok %d # SKIP %s\n", test_number, reason);
  }
  
  static gboolean
  test_execute (void)
  {
    gboolean executed;
    g_autoptr (GError) error = NULL;
    g_autofree gchar *command = g_strjoinv (" ", validator_argv);
    g_fprintf (stdout, "# Executing: %s\n", command);
    executed = g_spawn_sync (NULL,
                             validator_argv,
                             NULL,
                             G_SPAWN_SEARCH_PATH,
                             NULL,
                             NULL,
                             &validator_stdout,
                             &validator_stderr,
                             &validator_exit_status,
                             &error);
    ok (executed, "command executed");
    if (error)
      {
        g_fprintf (stdout, "# Exec failed with: %s\n", error->message);
      }
    return executed;
  }
  
  static void
  test_stdout (void)
  {
    if (expected_stdout)
      {
        const gchar *found =
          g_strstr_len (validator_stdout, -1, expected_stdout);
        ok (NULL != found, "standard output conforms");
        if (!found)
          g_fprintf (stdout,
                     "# expected: %s\n# got: %s\n",
                     expected_stdout,
                     validator_stdout);
      }
    else
      {
        skip ("no check for standard output specified");
      }
  }
  
  static void
  test_stderr (void)
  {
    if (expected_stderr)
      {
        const gchar *found =
          g_strstr_len (validator_stderr, -1, expected_stderr);
        ok (NULL != found, "error output conforms");
        if (!found)
          g_fprintf (stderr,
                     "# expected: %s\n# got: %s\n",
                     expected_stderr,
                     validator_stderr);
      }
    else
      {
        skip ("no check for error output specified");
      }
  }
  
  static void
  test_exit_code (void)
  {
    g_autoptr (GError) error = NULL;
    g_autofree gchar *message = NULL;
  #ifdef HAVE_G_SPAWN_CHECK_WAIT_STATUS
    g_spawn_check_wait_status (validator_exit_status, &error);
  #else
    g_spawn_check_exit_status (validator_exit_status, &error);
  #endif
    message = g_strdup_printf ("exit code was %d", expected_exit_code);
    if (0 == expected_exit_code)
      ok (!error, message);
    else
      ok (error && error->domain == G_SPAWN_EXIT_ERROR &&
            error->code == expected_exit_code,
          message);
  }
  
  
  int
  main (int argc, char *argv[])
  {
    GOptionEntry entries[] = {
      { "code",
        '\0',
        G_OPTION_FLAG_NONE,
        G_OPTION_ARG_INT,
        &expected_exit_code,
        "Expected exit code (default is 0)",
        NULL },
      { "stdout",
        '\0',
        G_OPTION_FLAG_NONE,
        G_OPTION_ARG_STRING,
        &expected_stdout,
        "Check standard output for a substring (default is no check)",
        NULL },
      { "stderr",
        '\0',
        G_OPTION_FLAG_NONE,
        G_OPTION_ARG_STRING,
        &expected_stderr,
        "Check error output for a substring (default is no check)",
        NULL },
      { 0 }
    };
    GOptionContext *context;
    g_autoptr (GError) error = NULL;
  
    setlocale (LC_ALL, "");
  
    /* "-- --help" is not handled as a non-option if g_test_init() is used.
     * Therefore this program does not Glib test frame work. */
    context = g_option_context_new (
      "MODULEMD_VALIDATOR_EXECUTABLE [MODULEMD_VALIDATOR_ARGUMENT...] - "
      "test modulemd-validator behavior");
    g_option_context_add_main_entries (context, entries, NULL);
    if (!g_option_context_parse (context, &argc, &argv, &error))
      {
        g_fprintf (stderr, "Could not parse arguments: %s\n", error->message);
        exit (EXIT_FAILURE);
      }
    g_option_context_free (context);
    validator_argv = argv + 1;
    if (!g_strcmp0 (validator_argv[0], "--"))
      {
        validator_argv++;
      }
    if (!validator_argv[0])
      {
        g_fprintf (stderr, "No positional arguments.\n");
        exit (EXIT_FAILURE);
      }
  
    g_fprintf (stdout, "1..4\n");
    if (test_execute ())
      {
        test_exit_code ();
        test_stdout ();
        test_stderr ();
      }
    else
      {
        skip_n (3, "program failed to execute");
      }
    g_free (expected_stdout);
    g_free (expected_stderr);
    g_free (validator_stdout);
    g_free (validator_stderr);
    exit (failed ? EXIT_FAILURE : EXIT_SUCCESS);
  }
  