Adjust sourcize.c to use _snprintf if using MSVC.
[SquirrelJME.git] / nanocoat / tests / testAllocRandom.c
blobdc86a0a97e32b31ef20a127c9f0d3524df468c39
1 /* -*- Mode: C; indent-tabs-mode: t; tab-width: 4 -*-
2 // ---------------------------------------------------------------------------
3 // SquirrelJME
4 // Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
5 // ---------------------------------------------------------------------------
6 // SquirrelJME is under the Mozilla Public License Version 2.0.
7 // See license.mkd for licensing and copyright information.
8 // -------------------------------------------------------------------------*/
10 #include <string.h>
12 #include "proto.h"
13 #include "sjme/alloc.h"
14 #include "sjme/util.h"
15 #include "test.h"
16 #include "unit.h"
18 /** The number of random allocations to make. */
19 #define NUM_RANDOM 512
21 /** Basic allocation link. */
22 typedef struct testLink testLink;
24 struct testLink
26 /** The previous link. */
27 testLink* prev;
29 /** The next link. */
30 testLink* next;
33 /**
34 * Tests random allocations and frees.
36 * @since 2023/11/29
38 SJME_TEST_DECLARE(testAllocRandom)
40 sjme_pointer chunk;
41 sjme_jint chunkLen, i, linkLen, desire;
42 sjme_alloc_pool* pool;
43 sjme_random random;
44 testLink* link;
45 testLink* lastLink;
46 testLink* oldPrev;
47 testLink* oldNext;
49 /* Allocate data on the stack so it gets cleared. */
50 chunkLen = 32768;
51 chunk = sjme_alloca(chunkLen);
52 if (chunk == NULL)
53 return sjme_unit_skip(test, "Could not alloca(%d).",
54 (int)chunkLen);
56 /* Initialize the pool. */
57 pool = NULL;
58 if (sjme_error_is(sjme_alloc_poolInitStatic(&pool, chunk,
59 chunkLen)) || pool == NULL)
60 return sjme_unit_fail(test, "Could not initialize static pool?");
62 /* Initialize the PRNG. */
63 memset(&random, 0, sizeof(random));
64 if (!sjme_randomInit(&random, 12345, 67890))
65 return sjme_unit_fail(test, "Could not initialize PRNG?");
67 /* Perform many small allocations. */
68 lastLink = NULL;
69 for (i = 0; i < NUM_RANDOM; i++)
71 /* Determine size to allocate. */
72 linkLen = 0;
73 if (!sjme_randomNextIntMax(&random, &linkLen, 32))
74 return sjme_unit_fail(test, "Could not random size %d %d.",
75 (int)i, (int)linkLen);
76 linkLen += sizeof(linkLen);
78 /* Allocate link. */
79 link = NULL;
80 if (sjme_error_is(sjme_alloc(pool, linkLen, (void**)&link)))
81 return sjme_unit_fail(test, "Could not allocate link %d %d.",
82 (int)i, (int)linkLen);
84 /* Link in. */
85 if (lastLink == NULL)
86 lastLink = link;
87 else
89 /* Connect the two. */
90 link->prev = lastLink;
91 lastLink->next = link;
93 /* Replace the old link. */
94 lastLink = link;
98 /* Reallocate all links randomly. */
99 for (i = 1; i < NUM_RANDOM; i++)
101 /* Which link do we want to clear? */
102 desire = -1;
103 if (!sjme_randomNextIntMax(&random, &desire,
104 NUM_RANDOM))
105 return sjme_unit_fail(test, "Could not desire %d.",
106 (int)i);
108 /* Always bump up by one to skip the last link. */
109 desire++;
111 /* Find the target link to free. */
112 link = NULL;
115 /* Always pivot onto the last link. */
116 if (link == NULL)
117 link = lastLink->prev;
119 /* Link left. */
120 link = link->prev;
122 /* Reduce count one. */
123 desire--;
124 } while (desire > 0);
126 /* Always pivot onto the last link, again... */
127 if (link == NULL)
128 link = lastLink->prev;
130 /* Unlink. */
131 oldPrev = link->prev;
132 oldNext = link->next;
134 /* Determine size to allocate. */
135 linkLen = 0;
136 if (!sjme_randomNextIntMax(&random, &linkLen, 32))
137 return sjme_unit_fail(test, "Could not random size %d %d.",
138 (int)i, (int)linkLen);
139 linkLen += sizeof(linkLen);
141 /* Free it. */
142 if (sjme_error_is(sjme_alloc_realloc((sjme_pointer*)&link,
143 linkLen)))
144 return sjme_unit_fail(test, "Could not realloc link %d at %p.",
145 (int)i, link);
147 /* Re-link in. */
148 if (oldPrev != NULL)
149 oldPrev->next = link;
150 if (oldNext != NULL)
151 oldNext->prev = link;
154 /* Finished. */
155 return SJME_TEST_RESULT_PASS;