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