From 05829401f2c8b355d192f64e1e55463953072ab3 Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Wed, 10 Jun 2015 06:07:42 -0400
Subject: [PATCH 12/16] input.c: add selftests

Jeff conditionally approved an earlier version of this (as
unittests/test-locations.c):
https://gcc.gnu.org/ml/gcc-patches/2015-10/msg03307.html
> OK if/when prereqs are approved. Minor twiddling if we end up
> moving it elsewhere or standardizing/reducing header files is
> pre-approved.

gcc/ChangeLog:
	* input.c: Include "selftest.h".
	(assert_loceq): New function.
	(test_accessing_ordinary_linemaps): New function.
	(test_unknown_location): New function.
	(test_builtins): New function.
	(test_reading_source_line): New function.
	(selftest::input_c_tests): New function.
---
 gcc/input.c | 112 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 112 insertions(+)

diff --git a/gcc/input.c b/gcc/input.c
index 61b1e44..b15b595 100644
--- a/gcc/input.c
+++ b/gcc/input.c
@@ -22,6 +22,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "coretypes.h"
 #include "intl.h"
 #include "diagnostic-core.h"
+#include "selftest.h"
 
 /* This is a cache used by get_next_line to store the content of a
    file to be searched for file lines.  */
@@ -1136,3 +1137,114 @@ dump_location_info (FILE *stream)
   dump_labelled_location_range (stream, "AD-HOC LOCATIONS",
 				MAX_SOURCE_LOCATION + 1, UINT_MAX);
 }
+
+#if CHECKING_P
+
+/* Selftests of location handling.  */
+
+/* Verify the result of LOCATION_FILE/LOCATION_LINE/LOCATION_COLUMN
+   on LOC.  */
+
+static void
+assert_loceq (const char *exp_filename,
+	      int exp_linenum,
+	      int exp_colnum,
+	      location_t loc)
+{
+  ASSERT_STREQ (exp_filename, LOCATION_FILE (loc));
+  ASSERT_EQ (exp_linenum, LOCATION_LINE (loc));
+  ASSERT_EQ (exp_colnum, LOCATION_COLUMN (loc));
+}
+
+/* Verify basic operation of ordinary linemaps.  */
+
+static void
+test_accessing_ordinary_linemaps ()
+{
+  /* Build a simple linemap describing some locations. */
+  linemap_add (line_table, LC_ENTER, false, "foo.c", 0);
+
+  linemap_line_start (line_table, 1, 100);
+  location_t loc_a = linemap_position_for_column (line_table, 1);
+  location_t loc_b = linemap_position_for_column (line_table, 23);
+
+  linemap_line_start (line_table, 2, 100);
+  location_t loc_c = linemap_position_for_column (line_table, 1);
+  location_t loc_d = linemap_position_for_column (line_table, 17);
+
+  /* Example of a very long line.  */
+  linemap_line_start (line_table, 3, 2000);
+  location_t loc_e = linemap_position_for_column (line_table, 700);
+
+  linemap_add (line_table, LC_LEAVE, false, NULL, 0);
+
+  /* Multiple files.  */
+  linemap_add (line_table, LC_ENTER, false, "bar.c", 0);
+  linemap_line_start (line_table, 1, 200);
+  location_t loc_f = linemap_position_for_column (line_table, 150);
+  linemap_add (line_table, LC_LEAVE, false, NULL, 0);
+
+  /* Verify that we can recover the location info.  */
+  assert_loceq ("foo.c", 1, 1, loc_a);
+  assert_loceq ("foo.c", 1, 23, loc_b);
+  assert_loceq ("foo.c", 2, 1, loc_c);
+  assert_loceq ("foo.c", 2, 17, loc_d);
+  assert_loceq ("foo.c", 3, 700, loc_e);
+  assert_loceq ("bar.c", 1, 150, loc_f);
+
+  ASSERT_FALSE (is_location_from_builtin_token (loc_a));
+}
+
+static void
+test_unknown_location ()
+{
+  ASSERT_EQ (NULL, LOCATION_FILE (UNKNOWN_LOCATION));
+  ASSERT_EQ (0, LOCATION_LINE (UNKNOWN_LOCATION));
+  ASSERT_EQ (0, LOCATION_COLUMN (UNKNOWN_LOCATION));
+}
+
+static void
+test_builtins ()
+{
+  assert_loceq ("<built-in>", 0, 0, BUILTINS_LOCATION);
+  ASSERT_PRED1 (is_location_from_builtin_token, BUILTINS_LOCATION);
+}
+
+/* Verify reading of input files (e.g. for caret-based diagnostics.  */
+
+static void
+test_reading_source_line ()
+{
+  /* We will read *this* source file, using __FILE__.
+     Here is some specific text to read and test for:
+     The quick brown fox jumps over the lazy dog.  */
+  const int linenum_after_test_message = __LINE__;
+  const int linenum = linenum_after_test_message - 1;
+
+  int line_size;
+  const char *source_line = location_get_source_line (__FILE__, linenum, &line_size);
+  ASSERT_TRUE (source_line != NULL);
+  ASSERT_EQ (53, line_size);
+  if (!strncmp ("     The quick brown fox jumps over the lazy dog.  */",
+	       source_line, line_size))
+    ::selftest::pass (__FILE__, __LINE__,
+		      "source_line matched expected value");
+  else
+    ::selftest::fail (__FILE__, __LINE__,
+		      "source_line did not match expected value");
+}
+
+namespace selftest {
+
+void
+input_c_tests ()
+{
+  test_accessing_ordinary_linemaps ();
+  test_unknown_location ();
+  test_builtins ();
+  test_reading_source_line ();
+}
+
+} // namespace selftest
+
+#endif /* CHECKING_P */
-- 
1.8.5.3

