public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
From: Ilya Leoshkevich <iii@linux.ibm.com>
To: Tom Tromey <tromey@adacore.com>,
	Andrew Burgess <aburgess@redhat.com>,
	Pedro Alves <pedro@palves.net>
Cc: Andreas Arnez <arnez@linux.ibm.com>,
	gdb-patches@sourceware.org, Ilya Leoshkevich <iii@linux.ibm.com>
Subject: [PATCH 3/5] gdbsupport: Add interval_tree unit tests
Date: Thu,  2 Jun 2022 15:35:44 +0200	[thread overview]
Message-ID: <20220602133546.2948282-4-iii@linux.ibm.com> (raw)
In-Reply-To: <20220602133546.2948282-1-iii@linux.ibm.com>

Test small corner cases as well as a large tree.
---
 gdb/Makefile.in                         |   1 +
 gdb/unittests/interval_tree-selftests.c | 263 ++++++++++++++++++++++++
 2 files changed, 264 insertions(+)
 create mode 100644 gdb/unittests/interval_tree-selftests.c

diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index d80087749de..8d848add1e3 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -456,6 +456,7 @@ SELFTESTS_SRCS = \
 	unittests/function-view-selftests.c \
 	unittests/gdb_tilde_expand-selftests.c \
 	unittests/gmp-utils-selftests.c \
+	unittests/interval_tree-selftests.c \
 	unittests/intrusive_list-selftests.c \
 	unittests/lookup_name_info-selftests.c \
 	unittests/memory-map-selftests.c \
diff --git a/gdb/unittests/interval_tree-selftests.c b/gdb/unittests/interval_tree-selftests.c
new file mode 100644
index 00000000000..98a3f4c15bd
--- /dev/null
+++ b/gdb/unittests/interval_tree-selftests.c
@@ -0,0 +1,263 @@
+/* Tests interval tree for GDB, the GNU debugger.
+   Copyright (C) 2022 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/selftest.h"
+#include <iostream>
+#include <set>
+#include <sstream>
+
+#include "gdbsupport/interval_tree.h"
+
+/* A test type for storing in an interval tree.  Interval tree must be able to
+   handle types without a default constructor, nonmoveable types, and
+   noncopyable types.  */
+
+struct test_interval
+{
+  test_interval (int low, int high) : low (low), high (high) {}
+
+  test_interval () = delete;
+  test_interval (const test_interval &) = delete;
+  test_interval &operator= (const test_interval &) = delete;
+  test_interval (test_interval &&) = delete;
+  test_interval &operator= (test_interval &&) = delete;
+
+  typedef int endpoint_type;
+  const int low;
+  const int high;
+};
+
+/* An expected ordering within an interval tree.  */
+
+struct cmp_test_interval
+{
+  bool
+  operator() (const test_interval &lhs, const test_interval &rhs) const
+  {
+    if (lhs.low != rhs.low)
+      return lhs.low < rhs.low;
+    return lhs.high < rhs.high;
+  }
+};
+
+/* Insert an interval into a tree and verify its integrity.  */
+
+static interval_tree<test_interval>::iterator
+check_emplace (interval_tree<test_interval> &t, int low, int high)
+{
+  auto it = t.emplace (low, high);
+  std::ostringstream () << t;
+  return it;
+}
+
+/* Check that iterator range has specific content.  */
+
+template <typename Iterator, typename EndIterator>
+static void
+check_iterator (Iterator it, EndIterator end)
+{
+  gdb_assert (it == end);
+}
+
+template <typename Iterator, typename EndIterator, typename... Args>
+static void
+check_iterator (Iterator it, EndIterator end, int low, int high,
+		Args &&...args)
+{
+  gdb_assert (it != end);
+  gdb_assert (it->low == low && it->high == high);
+  ++it;
+  check_iterator (it, end, std::forward<Args> (args)...);
+}
+
+/* Remove an interval from a tree and verify its integrity.  */
+
+static void
+check_erase (interval_tree<test_interval> &t,
+	     interval_tree<test_interval>::iterator it)
+{
+  t.erase (it);
+  std::ostringstream () << t;
+}
+
+/* Small tests for various corner cases.  */
+
+static void
+test_interval_tree_1 ()
+{
+  interval_tree<test_interval> t;
+  check_iterator (t.find (0, 1), t.end ());
+  auto it0 = check_emplace (t, 0, 1);
+  check_iterator (t.find (0, 1), t.end (), 0, 1);
+  check_erase (t, it0);
+  check_iterator (t.find (0, 1), t.end ());
+}
+
+static void
+test_interval_tree_2 ()
+{
+  interval_tree<test_interval> t;
+  check_emplace (t, -16119041, -1);
+  check_emplace (t, -1, 184549375);
+  check_emplace (t, 0, 0);
+  check_iterator (t.find (0, 0), t.end (), -1, 184549375, 0, 0);
+}
+
+static void
+test_interval_tree_3 ()
+{
+  interval_tree<test_interval> t;
+  check_emplace (t, 0, 65536);
+  check_emplace (t, -1978987776, 10);
+  check_iterator (t.find (0, 239), t.end (), -1978987776, 10, 0, 65536);
+}
+
+static void
+test_interval_tree_4 ()
+{
+  interval_tree<test_interval> t;
+  check_emplace (t, 0, 59);
+  check_emplace (t, 0, 0);
+  check_iterator (t.find (0, 0), t.end (), 0, 0, 0, 59);
+}
+
+static void
+test_interval_tree_5 ()
+{
+  interval_tree<test_interval> t;
+  check_emplace (t, -16777216, -16711936);
+  check_emplace (t, 0, 0);
+}
+
+static void
+test_interval_tree_6 ()
+{
+  interval_tree<test_interval> t;
+  check_emplace (t, -167772160, -33554186);
+  check_emplace (t, -16908034, -16712192);
+  check_emplace (t, -1, -1);
+  check_emplace (t, 0, 0);
+}
+
+static void
+test_interval_tree_7 ()
+{
+  interval_tree<test_interval> t;
+  check_emplace (t, 621897471, 983770623);
+  check_emplace (t, 0, 0);
+  check_emplace (t, 0, 0);
+  check_emplace (t, 0, 8061696);
+  check_iterator (t.find (0, 0), t.end (), 0, 0, 0, 0, 0, 8061696);
+}
+
+static void
+test_interval_tree_8 ()
+{
+  interval_tree<test_interval> t;
+  auto it0 = check_emplace (t, 1795875964, 1796149007);
+  check_emplace (t, 3855, 252371968);
+  check_erase (t, it0);
+}
+
+static void
+test_interval_tree_9 ()
+{
+  interval_tree<test_interval> t;
+  check_emplace (t, 0, 0);
+  auto it1 = check_emplace (t, -603979523, 853292838);
+  check_erase (t, it1);
+}
+
+static void
+test_interval_tree_10 ()
+{
+  interval_tree<test_interval> t;
+  auto it0 = check_emplace (t, 0, 6);
+  check_emplace (t, -65527, 65280);
+  check_emplace (t, 5636352, 26411009);
+  check_erase (t, it0);
+}
+
+static void
+test_interval_tree_11 ()
+{
+  interval_tree<test_interval> t;
+  auto it0 = check_emplace (t, 62652437, 454794924);
+  check_emplace (t, -188, 1145351340);
+  check_emplace (t, 352332868, 1140916191);
+  check_erase (t, it0);
+}
+
+static void
+test_interval_tree_12 ()
+{
+  interval_tree<test_interval> t;
+  auto it0 = check_emplace (t, -366592, 1389189);
+  auto it1 = check_emplace (t, 16128, 29702);
+  check_emplace (t, 2713716, 1946157056);
+  check_emplace (t, 393215, 1962868736);
+  check_erase (t, it0);
+  check_emplace (t, 2560, 4128768);
+  check_emplace (t, 0, 4128768);
+  check_emplace (t, 0, 125042688);
+  check_erase (t, it1);
+}
+
+/* Performance test: add and lookup 1M intervals.  */
+
+static void
+test_interval_tree_perf ()
+{
+  interval_tree<test_interval> t;
+  const int count = 1000000;
+  for (int i = 0; i < count; i++)
+    t.emplace (i * 5, i * 5 + 5);
+  std::ostringstream () << t;
+  for (int i = 1; i < count; i++)
+    check_iterator (t.find (i * 5 - 2, i * 5 + 2), t.end (), i * 5 - 5, i * 5,
+		    i * 5, i * 5 + 5);
+}
+
+/* Test registration.  */
+
+static void
+test_interval_tree ()
+{
+  test_interval_tree_1 ();
+  test_interval_tree_2 ();
+  test_interval_tree_3 ();
+  test_interval_tree_4 ();
+  test_interval_tree_5 ();
+  test_interval_tree_6 ();
+  test_interval_tree_7 ();
+  test_interval_tree_8 ();
+  test_interval_tree_9 ();
+  test_interval_tree_10 ();
+  test_interval_tree_11 ();
+  test_interval_tree_12 ();
+  test_interval_tree_perf ();
+}
+
+void _initialize_interval_tree_selftests ();
+void
+_initialize_interval_tree_selftests ()
+{
+  selftests::register_test ("interval_tree", test_interval_tree);
+}
-- 
2.35.3


  parent reply	other threads:[~2022-06-02 13:36 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-06-02 13:35 [PATCH 0/5] gdb: Store section map in an interval tree Ilya Leoshkevich
2022-06-02 13:35 ` [PATCH 1/5] gdbsupport: Introduce obstack_newvec Ilya Leoshkevich
2022-06-02 14:31   ` Tom Tromey
2022-06-02 14:33     ` Ilya Leoshkevich
2022-06-02 13:35 ` [PATCH 2/5] gdbsupport: Introduce interval_tree Ilya Leoshkevich
2022-06-02 14:12   ` Pedro Alves
2022-06-02 14:17     ` Ilya Leoshkevich
2022-06-02 14:12   ` Pedro Alves
2022-06-02 14:37     ` Pedro Alves
2022-06-02 15:09       ` Ilya Leoshkevich
2022-06-02 18:04       ` Tom Tromey
2022-06-02 13:35 ` Ilya Leoshkevich [this message]
2022-06-02 13:35 ` [PATCH 4/5] gdbsupport: Add interval_tree fuzzing harness Ilya Leoshkevich
2022-06-02 13:35 ` [PATCH 5/5] gdb: Optimize section map Ilya Leoshkevich

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220602133546.2948282-4-iii@linux.ibm.com \
    --to=iii@linux.ibm.com \
    --cc=aburgess@redhat.com \
    --cc=arnez@linux.ibm.com \
    --cc=gdb-patches@sourceware.org \
    --cc=pedro@palves.net \
    --cc=tromey@adacore.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).