Age Owner TLA Line data Source code
1 : /*--------------------------------------------------------------------------
2 : *
3 : * test_lfind.c
4 : * Test correctness of optimized linear search functions.
5 : *
6 : * Copyright (c) 2022-2023, PostgreSQL Global Development Group
7 : *
8 : * IDENTIFICATION
9 : * src/test/modules/test_lfind/test_lfind.c
10 : *
11 : * -------------------------------------------------------------------------
12 : */
13 :
14 : #include "postgres.h"
15 :
16 : #include "fmgr.h"
17 : #include "port/pg_lfind.h"
18 :
19 : /*
20 : * Convenience macros for testing both vector and scalar operations. The 2x
21 : * factor is to make sure iteration works
22 : */
23 : #define LEN_NO_TAIL(vectortype) (2 * sizeof(vectortype))
24 : #define LEN_WITH_TAIL(vectortype) (LEN_NO_TAIL(vectortype) + 3)
25 :
249 john.naylor 26 GNC 1 : PG_MODULE_MAGIC;
27 :
28 : /* workhorse for test_lfind8 */
29 : static void
232 30 8 : test_lfind8_internal(uint8 key)
31 : {
32 : uint8 charbuf[LEN_WITH_TAIL(Vector8)];
33 8 : const int len_no_tail = LEN_NO_TAIL(Vector8);
34 8 : const int len_with_tail = LEN_WITH_TAIL(Vector8);
35 :
36 8 : memset(charbuf, 0xFF, len_with_tail);
37 : /* search tail to test one-byte-at-a-time path */
38 8 : charbuf[len_with_tail - 1] = key;
39 8 : if (key > 0x00 && pg_lfind8(key - 1, charbuf, len_with_tail))
232 john.naylor 40 UNC 0 : elog(ERROR, "pg_lfind8() found nonexistent element '0x%x'", key - 1);
232 john.naylor 41 GNC 8 : if (key < 0xFF && !pg_lfind8(key, charbuf, len_with_tail))
232 john.naylor 42 UNC 0 : elog(ERROR, "pg_lfind8() did not find existing element '0x%x'", key);
232 john.naylor 43 GNC 8 : if (key < 0xFE && pg_lfind8(key + 1, charbuf, len_with_tail))
232 john.naylor 44 UNC 0 : elog(ERROR, "pg_lfind8() found nonexistent element '0x%x'", key + 1);
45 :
232 john.naylor 46 GNC 8 : memset(charbuf, 0xFF, len_with_tail);
47 : /* search with vector operations */
48 8 : charbuf[len_no_tail - 1] = key;
49 8 : if (key > 0x00 && pg_lfind8(key - 1, charbuf, len_no_tail))
232 john.naylor 50 UNC 0 : elog(ERROR, "pg_lfind8() found nonexistent element '0x%x'", key - 1);
232 john.naylor 51 GNC 8 : if (key < 0xFF && !pg_lfind8(key, charbuf, len_no_tail))
232 john.naylor 52 UNC 0 : elog(ERROR, "pg_lfind8() did not find existing element '0x%x'", key);
232 john.naylor 53 GNC 8 : if (key < 0xFE && pg_lfind8(key + 1, charbuf, len_no_tail))
232 john.naylor 54 UNC 0 : elog(ERROR, "pg_lfind8() found nonexistent element '0x%x'", key + 1);
232 john.naylor 55 GNC 8 : }
56 :
57 2 : PG_FUNCTION_INFO_V1(test_lfind8);
58 : Datum
59 1 : test_lfind8(PG_FUNCTION_ARGS)
60 : {
61 1 : test_lfind8_internal(0);
62 1 : test_lfind8_internal(1);
63 1 : test_lfind8_internal(0x7F);
64 1 : test_lfind8_internal(0x80);
65 1 : test_lfind8_internal(0x81);
66 1 : test_lfind8_internal(0xFD);
67 1 : test_lfind8_internal(0xFE);
68 1 : test_lfind8_internal(0xFF);
69 :
70 1 : PG_RETURN_VOID();
71 : }
72 :
73 : /* workhorse for test_lfind8_le */
74 : static void
75 8 : test_lfind8_le_internal(uint8 key)
76 : {
77 : uint8 charbuf[LEN_WITH_TAIL(Vector8)];
78 8 : const int len_no_tail = LEN_NO_TAIL(Vector8);
79 8 : const int len_with_tail = LEN_WITH_TAIL(Vector8);
80 :
81 8 : memset(charbuf, 0xFF, len_with_tail);
82 : /* search tail to test one-byte-at-a-time path */
83 8 : charbuf[len_with_tail - 1] = key;
84 8 : if (key > 0x00 && pg_lfind8_le(key - 1, charbuf, len_with_tail))
232 john.naylor 85 UNC 0 : elog(ERROR, "pg_lfind8_le() found nonexistent element <= '0x%x'", key - 1);
232 john.naylor 86 GNC 8 : if (key < 0xFF && !pg_lfind8_le(key, charbuf, len_with_tail))
232 john.naylor 87 UNC 0 : elog(ERROR, "pg_lfind8_le() did not find existing element <= '0x%x'", key);
232 john.naylor 88 GNC 8 : if (key < 0xFE && !pg_lfind8_le(key + 1, charbuf, len_with_tail))
232 john.naylor 89 UNC 0 : elog(ERROR, "pg_lfind8_le() did not find existing element <= '0x%x'", key + 1);
90 :
232 john.naylor 91 GNC 8 : memset(charbuf, 0xFF, len_with_tail);
92 : /* search with vector operations */
93 8 : charbuf[len_no_tail - 1] = key;
94 8 : if (key > 0x00 && pg_lfind8_le(key - 1, charbuf, len_no_tail))
232 john.naylor 95 UNC 0 : elog(ERROR, "pg_lfind8_le() found nonexistent element <= '0x%x'", key - 1);
232 john.naylor 96 GNC 8 : if (key < 0xFF && !pg_lfind8_le(key, charbuf, len_no_tail))
232 john.naylor 97 UNC 0 : elog(ERROR, "pg_lfind8_le() did not find existing element <= '0x%x'", key);
232 john.naylor 98 GNC 8 : if (key < 0xFE && !pg_lfind8_le(key + 1, charbuf, len_no_tail))
232 john.naylor 99 UNC 0 : elog(ERROR, "pg_lfind8_le() did not find existing element <= '0x%x'", key + 1);
232 john.naylor 100 GNC 8 : }
101 :
102 2 : PG_FUNCTION_INFO_V1(test_lfind8_le);
103 : Datum
104 1 : test_lfind8_le(PG_FUNCTION_ARGS)
105 : {
106 1 : test_lfind8_le_internal(0);
107 1 : test_lfind8_le_internal(1);
108 1 : test_lfind8_le_internal(0x7F);
109 1 : test_lfind8_le_internal(0x80);
110 1 : test_lfind8_le_internal(0x81);
111 1 : test_lfind8_le_internal(0xFD);
112 1 : test_lfind8_le_internal(0xFE);
113 1 : test_lfind8_le_internal(0xFF);
114 :
115 1 : PG_RETURN_VOID();
116 : }
117 :
118 2 : PG_FUNCTION_INFO_V1(test_lfind32);
119 : Datum
120 1 : test_lfind32(PG_FUNCTION_ARGS)
121 : {
122 : #define TEST_ARRAY_SIZE 135
249 123 1 : uint32 test_array[TEST_ARRAY_SIZE] = {0};
124 :
125 1 : test_array[8] = 1;
126 1 : test_array[64] = 2;
127 1 : test_array[TEST_ARRAY_SIZE - 1] = 3;
128 :
129 1 : if (pg_lfind32(1, test_array, 4))
249 john.naylor 130 UNC 0 : elog(ERROR, "pg_lfind32() found nonexistent element");
249 john.naylor 131 GNC 1 : if (!pg_lfind32(1, test_array, TEST_ARRAY_SIZE))
249 john.naylor 132 UNC 0 : elog(ERROR, "pg_lfind32() did not find existing element");
133 :
249 john.naylor 134 GNC 1 : if (pg_lfind32(2, test_array, 32))
249 john.naylor 135 UNC 0 : elog(ERROR, "pg_lfind32() found nonexistent element");
249 john.naylor 136 GNC 1 : if (!pg_lfind32(2, test_array, TEST_ARRAY_SIZE))
249 john.naylor 137 UNC 0 : elog(ERROR, "pg_lfind32() did not find existing element");
138 :
249 john.naylor 139 GNC 1 : if (pg_lfind32(3, test_array, 96))
249 john.naylor 140 UNC 0 : elog(ERROR, "pg_lfind32() found nonexistent element");
249 john.naylor 141 GNC 1 : if (!pg_lfind32(3, test_array, TEST_ARRAY_SIZE))
249 john.naylor 142 UNC 0 : elog(ERROR, "pg_lfind32() did not find existing element");
143 :
249 john.naylor 144 GNC 1 : if (pg_lfind32(4, test_array, TEST_ARRAY_SIZE))
249 john.naylor 145 UNC 0 : elog(ERROR, "pg_lfind32() found nonexistent element");
146 :
249 john.naylor 147 GNC 1 : PG_RETURN_VOID();
148 : }
|