Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 2297938

Browse files
committed
fix cmocka tests for postgresql-13
1 parent 2744cb9 commit 2297938

File tree

3 files changed

+314
-4
lines changed

3 files changed

+314
-4
lines changed

Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,8 @@ REGRESS = pathman_array_qual \
6666

6767
EXTRA_REGRESS_OPTS=--temp-config=$(top_srcdir)/$(subdir)/conf.add
6868

69-
EXTRA_CLEAN = pg_pathman--$(EXTVERSION).sql ./isolation_output
69+
CMOCKA_EXTRA_CLEAN = missing_basic.o missing_list.o missing_stringinfo.o missing_bitmapset.o rangeset_tests.o rangeset_tests
70+
EXTRA_CLEAN = ./isolation_output $(patsubst %,tests/cmocka/%, $(CMOCKA_EXTRA_CLEAN))
7071

7172
ifdef USE_PGXS
7273
PG_CONFIG=pg_config

tests/cmocka/missing_basic.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@ repalloc(void *pointer, Size size)
1616
return realloc(pointer, size);
1717
}
1818

19+
void
20+
pfree(void *pointer)
21+
{
22+
free(pointer);
23+
}
1924

2025
void
2126
ExceptionalCondition(const char *conditionName,

tests/cmocka/missing_list.c

Lines changed: 307 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
/*-------------------------------------------------------------------------
22
*
33
* list.c
4-
* implementation for PostgreSQL generic linked list package
4+
* implementation for PostgreSQL generic list package
55
*
66
*
7-
* Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
7+
* Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
1010
*
@@ -13,10 +13,11 @@
1313
*
1414
*-------------------------------------------------------------------------
1515
*/
16-
#define _GNU_SOURCE
1716
#include "postgres.h"
17+
1818
#include "nodes/pg_list.h"
1919

20+
#if PG_VERSION_NUM < 130000
2021

2122
#define IsPointerList(l) ((l) == NIL || IsA((l), List))
2223
#define IsIntegerList(l) ((l) == NIL || IsA((l), IntList))
@@ -141,3 +142,306 @@ lcons(void *datum, List *list)
141142
return list;
142143

143144
}
145+
146+
#else /* PG_VERSION_NUM >= 130000 */
147+
148+
/*-------------------------------------------------------------------------
149+
*
150+
* This was taken from src/backend/nodes/list.c PostgreSQL-13 source code.
151+
* We only need lappend() and lcons() and their dependencies.
152+
* There is one change: we use palloc() instead MemoryContextAlloc() in
153+
* enlarge_list() (see #defines).
154+
*
155+
*-------------------------------------------------------------------------
156+
*/
157+
#include "port/pg_bitutils.h"
158+
#include "utils/memdebug.h"
159+
#include "utils/memutils.h"
160+
161+
#define MemoryContextAlloc(c, s) palloc(s)
162+
#define GetMemoryChunkContext(l) 0
163+
164+
/*
165+
* The previous List implementation, since it used a separate palloc chunk
166+
* for each cons cell, had the property that adding or deleting list cells
167+
* did not move the storage of other existing cells in the list. Quite a
168+
* bit of existing code depended on that, by retaining ListCell pointers
169+
* across such operations on a list. There is no such guarantee in this
170+
* implementation, so instead we have debugging support that is meant to
171+
* help flush out now-broken assumptions. Defining DEBUG_LIST_MEMORY_USAGE
172+
* while building this file causes the List operations to forcibly move
173+
* all cells in a list whenever a cell is added or deleted. In combination
174+
* with MEMORY_CONTEXT_CHECKING and/or Valgrind, this can usually expose
175+
* broken code. It's a bit expensive though, as there's many more palloc
176+
* cycles and a lot more data-copying than in a default build.
177+
*
178+
* By default, we enable this when building for Valgrind.
179+
*/
180+
#ifdef USE_VALGRIND
181+
#define DEBUG_LIST_MEMORY_USAGE
182+
#endif
183+
184+
/* Overhead for the fixed part of a List header, measured in ListCells */
185+
#define LIST_HEADER_OVERHEAD \
186+
((int) ((offsetof(List, initial_elements) - 1) / sizeof(ListCell) + 1))
187+
188+
/*
189+
* Macros to simplify writing assertions about the type of a list; a
190+
* NIL list is considered to be an empty list of any type.
191+
*/
192+
#define IsPointerList(l) ((l) == NIL || IsA((l), List))
193+
#define IsIntegerList(l) ((l) == NIL || IsA((l), IntList))
194+
#define IsOidList(l) ((l) == NIL || IsA((l), OidList))
195+
196+
#ifdef USE_ASSERT_CHECKING
197+
/*
198+
* Check that the specified List is valid (so far as we can tell).
199+
*/
200+
static void
201+
check_list_invariants(const List *list)
202+
{
203+
if (list == NIL)
204+
return;
205+
206+
Assert(list->length > 0);
207+
Assert(list->length <= list->max_length);
208+
Assert(list->elements != NULL);
209+
210+
Assert(list->type == T_List ||
211+
list->type == T_IntList ||
212+
list->type == T_OidList);
213+
}
214+
#else
215+
#define check_list_invariants(l) ((void) 0)
216+
#endif /* USE_ASSERT_CHECKING */
217+
218+
/*
219+
* Return a freshly allocated List with room for at least min_size cells.
220+
*
221+
* Since empty non-NIL lists are invalid, new_list() sets the initial length
222+
* to min_size, effectively marking that number of cells as valid; the caller
223+
* is responsible for filling in their data.
224+
*/
225+
static List *
226+
new_list(NodeTag type, int min_size)
227+
{
228+
List *newlist;
229+
int max_size;
230+
231+
Assert(min_size > 0);
232+
233+
/*
234+
* We allocate all the requested cells, and possibly some more, as part of
235+
* the same palloc request as the List header. This is a big win for the
236+
* typical case of short fixed-length lists. It can lose if we allocate a
237+
* moderately long list and then it gets extended; we'll be wasting more
238+
* initial_elements[] space than if we'd made the header small. However,
239+
* rounding up the request as we do in the normal code path provides some
240+
* defense against small extensions.
241+
*/
242+
243+
#ifndef DEBUG_LIST_MEMORY_USAGE
244+
245+
/*
246+
* Normally, we set up a list with some extra cells, to allow it to grow
247+
* without a repalloc. Prefer cell counts chosen to make the total
248+
* allocation a power-of-2, since palloc would round it up to that anyway.
249+
* (That stops being true for very large allocations, but very long lists
250+
* are infrequent, so it doesn't seem worth special logic for such cases.)
251+
*
252+
* The minimum allocation is 8 ListCell units, providing either 4 or 5
253+
* available ListCells depending on the machine's word width. Counting
254+
* palloc's overhead, this uses the same amount of space as a one-cell
255+
* list did in the old implementation, and less space for any longer list.
256+
*
257+
* We needn't worry about integer overflow; no caller passes min_size
258+
* that's more than twice the size of an existing list, so the size limits
259+
* within palloc will ensure that we don't overflow here.
260+
*/
261+
max_size = pg_nextpower2_32(Max(8, min_size + LIST_HEADER_OVERHEAD));
262+
max_size -= LIST_HEADER_OVERHEAD;
263+
#else
264+
265+
/*
266+
* For debugging, don't allow any extra space. This forces any cell
267+
* addition to go through enlarge_list() and thus move the existing data.
268+
*/
269+
max_size = min_size;
270+
#endif
271+
272+
newlist = (List *) palloc(offsetof(List, initial_elements) +
273+
max_size * sizeof(ListCell));
274+
newlist->type = type;
275+
newlist->length = min_size;
276+
newlist->max_length = max_size;
277+
newlist->elements = newlist->initial_elements;
278+
279+
return newlist;
280+
}
281+
282+
/*
283+
* Enlarge an existing non-NIL List to have room for at least min_size cells.
284+
*
285+
* This does *not* update list->length, as some callers would find that
286+
* inconvenient. (list->length had better be the correct number of existing
287+
* valid cells, though.)
288+
*/
289+
static void
290+
enlarge_list(List *list, int min_size)
291+
{
292+
int new_max_len;
293+
294+
Assert(min_size > list->max_length); /* else we shouldn't be here */
295+
296+
#ifndef DEBUG_LIST_MEMORY_USAGE
297+
298+
/*
299+
* As above, we prefer power-of-two total allocations; but here we need
300+
* not account for list header overhead.
301+
*/
302+
303+
/* clamp the minimum value to 16, a semi-arbitrary small power of 2 */
304+
new_max_len = pg_nextpower2_32(Max(16, min_size));
305+
306+
#else
307+
/* As above, don't allocate anything extra */
308+
new_max_len = min_size;
309+
#endif
310+
311+
if (list->elements == list->initial_elements)
312+
{
313+
/*
314+
* Replace original in-line allocation with a separate palloc block.
315+
* Ensure it is in the same memory context as the List header. (The
316+
* previous List implementation did not offer any guarantees about
317+
* keeping all list cells in the same context, but it seems reasonable
318+
* to create such a guarantee now.)
319+
*/
320+
list->elements = (ListCell *)
321+
MemoryContextAlloc(GetMemoryChunkContext(list),
322+
new_max_len * sizeof(ListCell));
323+
memcpy(list->elements, list->initial_elements,
324+
list->length * sizeof(ListCell));
325+
326+
/*
327+
* We must not move the list header, so it's unsafe to try to reclaim
328+
* the initial_elements[] space via repalloc. In debugging builds,
329+
* however, we can clear that space and/or mark it inaccessible.
330+
* (wipe_mem includes VALGRIND_MAKE_MEM_NOACCESS.)
331+
*/
332+
#ifdef CLOBBER_FREED_MEMORY
333+
wipe_mem(list->initial_elements,
334+
list->max_length * sizeof(ListCell));
335+
#else
336+
VALGRIND_MAKE_MEM_NOACCESS(list->initial_elements,
337+
list->max_length * sizeof(ListCell));
338+
#endif
339+
}
340+
else
341+
{
342+
#ifndef DEBUG_LIST_MEMORY_USAGE
343+
/* Normally, let repalloc deal with enlargement */
344+
list->elements = (ListCell *) repalloc(list->elements,
345+
new_max_len * sizeof(ListCell));
346+
#else
347+
/*
348+
* repalloc() might enlarge the space in-place, which we don't want
349+
* for debugging purposes, so forcibly move the data somewhere else.
350+
*/
351+
ListCell *newelements;
352+
353+
newelements = (ListCell *)
354+
MemoryContextAlloc(GetMemoryChunkContext(list),
355+
new_max_len * sizeof(ListCell));
356+
memcpy(newelements, list->elements,
357+
list->length * sizeof(ListCell));
358+
pfree(list->elements);
359+
list->elements = newelements;
360+
#endif
361+
}
362+
363+
list->max_length = new_max_len;
364+
}
365+
366+
/*
367+
* Make room for a new head cell in the given (non-NIL) list.
368+
*
369+
* The data in the new head cell is undefined; the caller should be
370+
* sure to fill it in
371+
*/
372+
static void
373+
new_head_cell(List *list)
374+
{
375+
/* Enlarge array if necessary */
376+
if (list->length >= list->max_length)
377+
enlarge_list(list, list->length + 1);
378+
/* Now shove the existing data over */
379+
memmove(&list->elements[1], &list->elements[0],
380+
list->length * sizeof(ListCell));
381+
list->length++;
382+
}
383+
384+
/*
385+
* Make room for a new tail cell in the given (non-NIL) list.
386+
*
387+
* The data in the new tail cell is undefined; the caller should be
388+
* sure to fill it in
389+
*/
390+
static void
391+
new_tail_cell(List *list)
392+
{
393+
/* Enlarge array if necessary */
394+
if (list->length >= list->max_length)
395+
enlarge_list(list, list->length + 1);
396+
list->length++;
397+
}
398+
399+
/*
400+
* Append a pointer to the list. A pointer to the modified list is
401+
* returned. Note that this function may or may not destructively
402+
* modify the list; callers should always use this function's return
403+
* value, rather than continuing to use the pointer passed as the
404+
* first argument.
405+
*/
406+
List *
407+
lappend(List *list, void *datum)
408+
{
409+
Assert(IsPointerList(list));
410+
411+
if (list == NIL)
412+
list = new_list(T_List, 1);
413+
else
414+
new_tail_cell(list);
415+
416+
lfirst(list_tail(list)) = datum;
417+
check_list_invariants(list);
418+
return list;
419+
}
420+
421+
/*
422+
* Prepend a new element to the list. A pointer to the modified list
423+
* is returned. Note that this function may or may not destructively
424+
* modify the list; callers should always use this function's return
425+
* value, rather than continuing to use the pointer passed as the
426+
* second argument.
427+
*
428+
* Caution: before Postgres 8.0, the original List was unmodified and
429+
* could be considered to retain its separate identity. This is no longer
430+
* the case.
431+
*/
432+
List *
433+
lcons(void *datum, List *list)
434+
{
435+
Assert(IsPointerList(list));
436+
437+
if (list == NIL)
438+
list = new_list(T_List, 1);
439+
else
440+
new_head_cell(list);
441+
442+
lfirst(list_head(list)) = datum;
443+
check_list_invariants(list);
444+
return list;
445+
}
446+
447+
#endif /* PG_VERSION_NUM */

0 commit comments

Comments
 (0)