| /*************************************************************************** | 
 |  *                                  _   _ ____  _ | 
 |  *  Project                     ___| | | |  _ \| | | 
 |  *                             / __| | | | |_) | | | 
 |  *                            | (__| |_| |  _ <| |___ | 
 |  *                             \___|\___/|_| \_\_____| | 
 |  * | 
 |  * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al. | 
 |  * | 
 |  * This software is licensed as described in the file COPYING, which | 
 |  * you should have received as part of this distribution. The terms | 
 |  * are also available at https://curl.se/docs/copyright.html. | 
 |  * | 
 |  * You may opt to use, copy, modify, merge, publish, distribute and/or sell | 
 |  * copies of the Software, and permit persons to whom the Software is | 
 |  * furnished to do so, under the terms of the COPYING file. | 
 |  * | 
 |  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | 
 |  * KIND, either express or implied. | 
 |  * | 
 |  * SPDX-License-Identifier: curl | 
 |  * | 
 |  ***************************************************************************/ | 
 | #include "curlcheck.h" | 
 |  | 
 | #include "splay.h" | 
 | #include "warnless.h" | 
 |  | 
 |  | 
 | static CURLcode unit_setup(void) | 
 | { | 
 |   return CURLE_OK; | 
 | } | 
 |  | 
 | static void unit_stop(void) | 
 | { | 
 |  | 
 | } | 
 |  | 
 | static void splayprint(struct Curl_tree *t, int d, char output) | 
 | { | 
 |   struct Curl_tree *node; | 
 |   int i; | 
 |   int count; | 
 |   if(!t) | 
 |     return; | 
 |  | 
 |   splayprint(t->larger, d + 1, output); | 
 |   for(i = 0; i<d; i++) | 
 |     if(output) | 
 |       printf("  "); | 
 |  | 
 |   if(output) { | 
 |     printf("%ld.%ld[%d]", (long)t->key.tv_sec, | 
 |            (long)t->key.tv_usec, i); | 
 |   } | 
 |  | 
 |   for(count = 0, node = t->samen; node != t; node = node->samen, count++) | 
 |     ; | 
 |  | 
 |   if(output) { | 
 |     if(count) | 
 |       printf(" [%d more]\n", count); | 
 |     else | 
 |       printf("\n"); | 
 |   } | 
 |  | 
 |   splayprint(t->smaller, d + 1, output); | 
 | } | 
 |  | 
 | UNITTEST_START | 
 |  | 
 | /* number of nodes to add to the splay tree */ | 
 | #define NUM_NODES 50 | 
 |  | 
 |   struct Curl_tree *root, *removed; | 
 |   struct Curl_tree nodes[NUM_NODES*3]; | 
 |   size_t storage[NUM_NODES*3]; | 
 |   int rc; | 
 |   int i, j; | 
 |   struct curltime tv_now = {0, 0}; | 
 |   root = NULL;              /* the empty tree */ | 
 |  | 
 |   /* add nodes */ | 
 |   for(i = 0; i < NUM_NODES; i++) { | 
 |     struct curltime key; | 
 |  | 
 |     key.tv_sec = 0; | 
 |     key.tv_usec = (541*i)%1023; | 
 |     storage[i] = key.tv_usec; | 
 |     nodes[i].payload = &storage[i]; | 
 |     root = Curl_splayinsert(key, root, &nodes[i]); | 
 |   } | 
 |  | 
 |   puts("Result:"); | 
 |   splayprint(root, 0, 1); | 
 |  | 
 |   for(i = 0; i < NUM_NODES; i++) { | 
 |     int rem = (i + 7)%NUM_NODES; | 
 |     printf("Tree look:\n"); | 
 |     splayprint(root, 0, 1); | 
 |     printf("remove pointer %d, payload %zu\n", rem, | 
 |            *(size_t *)nodes[rem].payload); | 
 |     rc = Curl_splayremove(root, &nodes[rem], &root); | 
 |     if(rc) { | 
 |       /* failed! */ | 
 |       printf("remove %d failed!\n", rem); | 
 |       fail("remove"); | 
 |     } | 
 |   } | 
 |  | 
 |   fail_unless(root == NULL, "tree not empty after removing all nodes"); | 
 |  | 
 |   /* rebuild tree */ | 
 |   for(i = 0; i < NUM_NODES; i++) { | 
 |     struct curltime key; | 
 |  | 
 |     key.tv_sec = 0; | 
 |     key.tv_usec = (541*i)%1023; | 
 |  | 
 |     /* add some nodes with the same key */ | 
 |     for(j = 0; j <= i % 3; j++) { | 
 |       storage[i * 3 + j] = key.tv_usec*10 + j; | 
 |       nodes[i * 3 + j].payload = &storage[i * 3 + j]; | 
 |       root = Curl_splayinsert(key, root, &nodes[i * 3 + j]); | 
 |     } | 
 |   } | 
 |  | 
 |   removed = NULL; | 
 |   for(i = 0; i <= 1100; i += 100) { | 
 |     printf("Removing nodes not larger than %d\n", i); | 
 |     tv_now.tv_usec = i; | 
 |     root = Curl_splaygetbest(tv_now, root, &removed); | 
 |     while(removed) { | 
 |       printf("removed payload %zu[%zu]\n", | 
 |              (*(size_t *)removed->payload) / 10, | 
 |              (*(size_t *)removed->payload) % 10); | 
 |       root = Curl_splaygetbest(tv_now, root, &removed); | 
 |     } | 
 |   } | 
 |  | 
 |   fail_unless(root == NULL, "tree not empty when it should be"); | 
 |  | 
 | UNITTEST_STOP |