Training courses

Kernel and Embedded Linux

Bootlin training courses

Embedded Linux, kernel,
Yocto Project, Buildroot, real-time,
graphics, boot time, debugging...

Bootlin logo

Elixir Cross Referencer

/* Unit tests for unique-ptr.h.
   Copyright (C) 2017-2020 Free Software Foundation, Inc.

This file is part of GCC.

GCC 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, or (at your option) any later
version.

GCC 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 GCC; see the file COPYING3.  If not see
<http://www.gnu.org/licenses/>.  */

#include "config.h"
#define INCLUDE_UNIQUE_PTR
#include "system.h"
#include "coretypes.h"
#include "selftest.h"

#if CHECKING_P

namespace selftest {

namespace {

/* A class for counting ctor and dtor invocations.  */

class stats
{
public:
  stats () : ctor_count (0), dtor_count (0) {}

  int ctor_count;
  int dtor_count;
};

/* A class that uses "stats" to track its ctor and dtor invocations.  */

class foo
{
public:
  foo (stats &s) : m_s (s) { ++m_s.ctor_count; }
  ~foo () { ++m_s.dtor_count; }

  int example_method () const { return 42; }

private:
  foo (const foo&);
  foo & operator= (const foo &);

private:
  stats &m_s;
};

/* A struct for testing unique_ptr<T[]>.  */

class has_default_ctor
{
public:
  has_default_ctor () : m_field (42) {}
  int m_field;
};

/* A dummy struct for testing unique_xmalloc_ptr.  */

struct dummy
{
  int field;
};

} // anonymous namespace

/* Verify that the default ctor inits ptrs to NULL.  */

static void
test_null_ptr ()
{
  gnu::unique_ptr<void *> p;
  ASSERT_EQ (NULL, p);

  gnu::unique_xmalloc_ptr<void *> q;
  ASSERT_EQ (NULL, q);
}

/* Verify that deletion happens when a unique_ptr goes out of scope.  */

static void
test_implicit_deletion ()
{
  stats s;
  ASSERT_EQ (0, s.ctor_count);
  ASSERT_EQ (0, s.dtor_count);

  {
    gnu::unique_ptr<foo> f (new foo (s));
    ASSERT_NE (NULL, f);
    ASSERT_EQ (1, s.ctor_count);
    ASSERT_EQ (0, s.dtor_count);
  }

  /* Verify that the foo was implicitly deleted.  */
  ASSERT_EQ (1, s.ctor_count);
  ASSERT_EQ (1, s.dtor_count);
}

/* Verify that we can assign to a NULL unique_ptr.  */

static void
test_overwrite_of_null ()
{
  stats s;
  ASSERT_EQ (0, s.ctor_count);
  ASSERT_EQ (0, s.dtor_count);

  {
    gnu::unique_ptr<foo> f;
    ASSERT_EQ (NULL, f);
    ASSERT_EQ (0, s.ctor_count);
    ASSERT_EQ (0, s.dtor_count);

    /* Overwrite with a non-NULL value.  */
    f = gnu::unique_ptr<foo> (new foo (s));
    ASSERT_EQ (1, s.ctor_count);
    ASSERT_EQ (0, s.dtor_count);
  }

  /* Verify that the foo is implicitly deleted.  */
  ASSERT_EQ (1, s.ctor_count);
  ASSERT_EQ (1, s.dtor_count);
}

/* Verify that we can assign to a non-NULL unique_ptr.  */

static void
test_overwrite_of_non_null ()
{
  stats s;
  ASSERT_EQ (0, s.ctor_count);
  ASSERT_EQ (0, s.dtor_count);

  {
    gnu::unique_ptr<foo> f (new foo (s));
    ASSERT_NE (NULL, f);
    ASSERT_EQ (1, s.ctor_count);
    ASSERT_EQ (0, s.dtor_count);

    /* Overwrite with a different value.  */
    f = gnu::unique_ptr<foo> (new foo (s));
    ASSERT_EQ (2, s.ctor_count);
    ASSERT_EQ (1, s.dtor_count);
  }

  /* Verify that the 2nd foo was implicitly deleted.  */
  ASSERT_EQ (2, s.ctor_count);
  ASSERT_EQ (2, s.dtor_count);
}

/* Verify that unique_ptr's overloaded ops work.  */

static void
test_overloaded_ops ()
{
  stats s;
  gnu::unique_ptr<foo> f (new foo (s));
  ASSERT_EQ (42, f->example_method ());
  ASSERT_EQ (42, (*f).example_method ());
  ASSERT_EQ (f, f);
  ASSERT_NE (NULL, f.get ());

  gnu::unique_ptr<foo> g (new foo (s));
  ASSERT_NE (f, g);
}

/* Verify that the gnu::unique_ptr specialization for T[] works.  */

static void
test_array_new ()
{
  const int num = 10;
  gnu::unique_ptr<has_default_ctor[]> p (new has_default_ctor[num]);
  ASSERT_NE (NULL, p.get ());
  /* Verify that operator[] works, and that the default ctor was called
     on each element.  */
  for (int i = 0; i < num; i++)
    ASSERT_EQ (42, p[i].m_field);
}

/* Verify that gnu::unique_xmalloc_ptr works.  */

static void
test_xmalloc ()
{
  gnu::unique_xmalloc_ptr<dummy> p (XNEW (dummy));
  ASSERT_NE (NULL, p.get ());
}

/* Verify the gnu::unique_xmalloc_ptr specialization for T[].  */

static void
test_xmalloc_array ()
{
  const int num = 10;
  gnu::unique_xmalloc_ptr<dummy[]> p (XNEWVEC (dummy, num));
  ASSERT_NE (NULL, p.get ());

  /* Verify that operator[] works.  */
  for (int i = 0; i < num; i++)
    p[i].field = 42;
  for (int i = 0; i < num; i++)
    ASSERT_EQ (42, p[i].field);
}

/* Run all of the selftests within this file.  */

void
unique_ptr_tests_cc_tests ()
{
  test_null_ptr ();
  test_implicit_deletion ();
  test_overwrite_of_null ();
  test_overwrite_of_non_null ();
  test_overloaded_ops ();
  test_array_new ();
  test_xmalloc ();
  test_xmalloc_array ();
}

} // namespace selftest

#endif /* #if CHECKING_P */