crt: tests: update t_tsearch and mark it as XFAIL

Add logic to test how many nodes have been visited by a single call to `twalk`;
this allows to test that nodes were properly inserted and removed.

This change has uncovered a bug in `tdestroy` which causes this test to fail.

Add t_tsearch to testcases/Makefile.am, but mark it as XFAIL.

Signed-off-by: Kirill Makurin <maiddaisuki@outlook.com>
Signed-off-by: LIU Hao <lh_mouse@126.com>
diff --git a/mingw-w64-crt/testcases/Makefile.am b/mingw-w64-crt/testcases/Makefile.am
index 037f4c0..6bf961b 100644
--- a/mingw-w64-crt/testcases/Makefile.am
+++ b/mingw-w64-crt/testcases/Makefile.am
@@ -94,6 +94,7 @@
   t_tmpfile \
   t_towctrans \
   t_trycatch \
+  t_tsearch \
   t_utime \
   t_vsscanf \
   t_wcrtomb \
@@ -179,7 +180,8 @@
   t_excpt_int_divzero_thrd \
   t_excpt_int_overflow \
   t_excpt_int_overflow_thrd \
-  t_nullptrexception
+  t_nullptrexception \
+  t_tsearch
 
 # Include the complex math testcase fragment.
 include complex/Makefile.am
diff --git a/mingw-w64-crt/testcases/t_tsearch.c b/mingw-w64-crt/testcases/t_tsearch.c
index 14af6ff..2e97b67 100644
--- a/mingw-w64-crt/testcases/t_tsearch.c
+++ b/mingw-w64-crt/testcases/t_tsearch.c
@@ -1,7 +1,14 @@
+#define _GNU_SOURCE
 #include <search.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
 
+/**
+ * FIXME: calling `twalk` after `tdestroy` walks the tree as if tree was not
+ *  destroyed. That is, it dereferences freed nodes.
+ */
+
 static int node_cmp (const void *a, const void *b)
 {
  return strcmp((const char *) a, (const char *) b);
@@ -16,17 +23,25 @@
 static void
 noop_free (void *arg)
 {
+  return;
 }
 
+/* Number of nodes printed by `print_node` in a call to `twalk` */
+static int nodes_printed;
+
 void print_node (const void *ptr, VISIT order, int level)
 {
  const char *s = *(const char **) ptr;
- if (order == postorder || order == leaf)
+ if (order == postorder || order == leaf) {
+   nodes_printed += 1;
    printf("%s\n", s);
+ }
 }
 
 int main (int argc, char **argv)
 {
+ int exit_code = EXIT_SUCCESS;
+
  void *root = NULL;
  void *nodep;
 
@@ -34,7 +49,12 @@
  tsearch("bbb", &root, node_cmp);
  tsearch("ccc", &root, node_cmp);
  printf("---------- tree after insertion of 3 nodes:\n");
+ nodes_printed = 0;
  twalk(root, print_node);
+ if (nodes_printed != 3) {
+  printf ("ERROR: printed %d nodes when expected %d\n", nodes_printed, 3);
+  exit_code = EXIT_FAILURE;
+ }
 
  printf("----------\n");
 
@@ -44,7 +64,12 @@
    tdelete(key, &root, node_cmp);
  }
  printf("---------- tree after deletion of all nodes using tfind()+tdelete():\n");
+ nodes_printed = 0;
  twalk(root, print_node);
+ if (nodes_printed != 0) {
+  printf ("ERROR: printed %d nodes when expected %d\n", nodes_printed, 0);
+  exit_code = EXIT_FAILURE;
+ }
 
  printf("----------\n");
 
@@ -52,14 +77,24 @@
  tsearch("eee", &root, node_cmp);
  tsearch("fff", &root, node_cmp);
  printf("---------- tree after insertion of 3 new nodes:\n");
+ nodes_printed = 0;
  twalk(root, print_node);
+ if (nodes_printed != 3) {
+  printf ("ERROR: printed %d nodes when expected %d\n", nodes_printed, 3);
+  exit_code = EXIT_FAILURE;
+ }
 
  printf("----------\n");
 
  while (tdelete(NULL, &root, node_any) != NULL)
    ;
  printf("---------- tree after deletion of all nodes using tdelete() only:\n");
+ nodes_printed = 0;
  twalk(root, print_node);
+ if (nodes_printed != 0) {
+  printf ("ERROR: printed %d nodes when expected %d\n", nodes_printed, 0);
+  exit_code = EXIT_FAILURE;
+ }
 
  printf("----------\n");
 
@@ -67,17 +102,27 @@
  tsearch("hhh", &root, node_cmp);
  tsearch("iii", &root, node_cmp);
  printf("---------- tree after insertion of 3 new nodes:\n");
+ nodes_printed = 0;
  twalk(root, print_node);
+ if (nodes_printed != 3) {
+  printf ("ERROR: printed %d nodes when expected %d\n", nodes_printed, 3);
+  exit_code = EXIT_FAILURE;
+ }
 
  printf("----------\n");
 
  tdestroy(root, noop_free);
- printf("---------- tree after deletion of all nodes using tdeosty() only:\n");
+ printf("---------- tree after deletion of all nodes using tdestroy() only:\n");
+ nodes_printed = 0;
  twalk(root, print_node);
+ if (nodes_printed != 0) {
+  printf ("ERROR: printed %d nodes when expected %d\n", nodes_printed, 0);
+  exit_code = EXIT_FAILURE;
+ }
 
  printf("----------\n");
 
- printf("Passed\n");
+ printf("Done\n");
 
- return 0;
+ return exit_code;
 }