/* Self tests for scoped_mmap for GDB, the GNU debugger.

   Copyright (C) 2018-2021 Free Software Foundation, Inc.

   This file is part of GDB.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 3 of the License, or
   (at your option) any later version.

   This program 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 General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */

#include "defs.h"

#include "gdbsupport/filestuff.h"
#include "gdbsupport/scoped_mmap.h"
#include "config.h"

#if defined(HAVE_SYS_MMAN_H)

#include "gdbsupport/selftest.h"
#include "gdbsupport/gdb_unlinker.h"

#include <unistd.h>

namespace selftests {
namespace scoped_mmap {

/* Test that the file is unmapped.  */
static void
test_destroy ()
{
  void *mem;

  errno = 0;
  {
    ::scoped_mmap smmap (nullptr, sysconf (_SC_PAGESIZE), PROT_WRITE,
			 MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);

    mem = smmap.get ();
    SELF_CHECK (mem != nullptr);
  }

  SELF_CHECK (msync (mem, sysconf (_SC_PAGESIZE), 0) == -1 && errno == ENOMEM);
}

/* Test that the memory can be released.  */
static void
test_release ()
{
  void *mem;

  errno = 0;
  {
    ::scoped_mmap smmap (nullptr, sysconf (_SC_PAGESIZE), PROT_WRITE,
			 MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);

    mem = smmap.release ();
    SELF_CHECK (mem != nullptr);
  }

  SELF_CHECK (msync (mem, sysconf (_SC_PAGESIZE), 0) == 0 || errno != ENOMEM);

  munmap (mem, sysconf (_SC_PAGESIZE));
}

/* Run selftests.  */
static void
run_tests ()
{
  test_destroy ();
  test_release ();
}

} /* namespace scoped_mmap */

namespace mmap_file
{

/* Test the standard usage of mmap_file.  */
static void
test_normal ()
{
  char filename[] = "scoped_mmapped_file-selftest-XXXXXX";
  int fd = gdb_mkostemp_cloexec (filename);
  SELF_CHECK (fd >= 0);

  SELF_CHECK (write (fd, "Hello!", 7) == 7);
  close (fd);

  gdb::unlinker unlink_test_file (filename);

  {
    ::scoped_mmap m = ::mmap_file (filename);

    SELF_CHECK (m.get () != MAP_FAILED);
    SELF_CHECK (m.size () == 7);
    SELF_CHECK (0 == strcmp ((char *) m.get (), "Hello!"));
  }
}

/* Calling mmap_file with a non-existent file should throw an exception.  */
static void
test_invalid_filename ()
{
  bool threw = false;

  try {
      ::scoped_mmap m = ::mmap_file ("/this/file/should/not/exist");
  } catch (gdb_exception &e) {
      threw = true;
  }

  SELF_CHECK (threw);
}


/* Run selftests.  */
static void
run_tests ()
{
  test_normal ();
  test_invalid_filename ();
}

} /* namespace mmap_file */
} /* namespace selftests */

#endif /* !defined(HAVE_SYS_MMAN_H) */

void _initialize_scoped_mmap_selftests ();
void
_initialize_scoped_mmap_selftests ()
{
#if defined(HAVE_SYS_MMAN_H)
  selftests::register_test ("scoped_mmap",
			    selftests::scoped_mmap::run_tests);
  selftests::register_test ("mmap_file",
			    selftests::mmap_file::run_tests);
#endif
}
