Line data Source code
1 : /**
2 : * @file
3 : *
4 : * @brief
5 : *
6 : * @copyright BSD License (see doc/LICENSE.md or https://www.libelektra.org)
7 : */
8 :
9 : #include <opmphmpredictor.c>
10 : #include <tests_internal.h>
11 :
12 2 : void test_internal_basic (void)
13 : {
14 2 : OpmphmPredictor * op = opmphmPredictorNew ();
15 2 : exit_if_fail (op, "opmphmPredictorNew");
16 2 : succeed_if (!op->history, "history init");
17 2 : succeed_if (!op->lookupCount, "lookupCount init");
18 2 : succeed_if (!op->ksSize, "lookupCount init");
19 2 : succeed_if (op->size, "size init");
20 256 : for (size_t i = 0; i < op->size; ++i)
21 : {
22 256 : succeed_if (!op->patternTable[i], "patternTable init");
23 : }
24 2 : opmphmPredictorDel (op);
25 2 : }
26 :
27 2 : void test_internal_nochange (void)
28 : {
29 2 : OpmphmPredictor * op = opmphmPredictorNew ();
30 2 : exit_if_fail (op, "opmphmPredictorNew");
31 2 : const size_t n = 1000;
32 2 : succeed_if (!opmphmPredictor (op, n), "first prediction");
33 2 : succeed_if (op->lookupCount == 1, "lookupCount");
34 36000 : for (size_t i = 1; i < opmphmPredictorWorthOpmphm (n) * 3; ++i)
35 : {
36 : // no opmphm
37 35998 : succeed_if (!opmphmPredictorIncCountBinarySearch (op, n), "binary search usage");
38 35998 : succeed_if (op->lookupCount == i + 1, "lookupCount");
39 : }
40 : // switch to opmphm
41 2 : succeed_if (opmphmPredictorIncCountBinarySearch (op, n), "hash usage");
42 2 : succeed_if (op->lookupCount == opmphmPredictorWorthOpmphm (n) * 3 + 1, "lookupCount");
43 2 : opmphmPredictorDel (op);
44 2 : }
45 :
46 : /**
47 : * @brief Switches the internal states of the OpmphmPredictor and checks switch.
48 : *
49 : * @param oldState old State
50 : * @param newState new State
51 : * @param op the OpmphmPredictor
52 : * @param n number of elements
53 : */
54 18 : static void test_internal_change_whitebox_set_to_state (uint8_t oldState, uint8_t newState, OpmphmPredictor * op, size_t n)
55 : {
56 : size_t setLookupCount;
57 18 : if (oldState == 0 && newState == 0)
58 : {
59 : // not worth hashing
60 4 : setLookupCount = opmphmPredictorWorthOpmphm (n);
61 : }
62 14 : else if (oldState == 3 && newState == 3)
63 : {
64 : // worth hashing
65 2 : setLookupCount = opmphmPredictorWorthOpmphm (n) + 1;
66 : }
67 12 : else if (oldState + 1 == newState)
68 : {
69 : // worth hashing
70 6 : setLookupCount = opmphmPredictorWorthOpmphm (n) + 1;
71 : }
72 6 : else if (oldState == newState + 1)
73 : {
74 : // not worth hashing
75 6 : setLookupCount = opmphmPredictorWorthOpmphm (n);
76 : }
77 : else
78 : {
79 0 : exit_if_fail (0, "wrong usage");
80 : }
81 : /*
82 : * Set every entry in pattern table to state
83 : */
84 9234 : for (uint16_t testHistory = 0; testHistory <= opmphmPredictorHistoryMask; ++testHistory)
85 : {
86 9216 : op->history = testHistory;
87 : // set not worth to hash
88 9216 : op->lookupCount = setLookupCount;
89 : // between state 1 and 2 is the prediction reulst transition, and patterns interfere, thus no check
90 9216 : if (!((oldState == 1 && newState == 2) || (oldState == 2 && newState == 1)))
91 : {
92 7168 : if (newState < 2)
93 : {
94 4096 : succeed_if (!opmphmPredictor (op, n), "binary search usage");
95 : }
96 : else
97 : {
98 3072 : succeed_if (opmphmPredictor (op, n), "hash usage");
99 : }
100 : }
101 : else
102 : {
103 : // no ckeck
104 2048 : opmphmPredictor (op, n);
105 : }
106 9216 : succeed_if (op->lookupCount == 1, "lookupCount");
107 : }
108 : // test pattern
109 2304 : for (size_t i = 0; i < op->size; ++i)
110 : {
111 2304 : if (newState == 0)
112 : {
113 768 : succeed_if (op->patternTable[i] == 0x0, "patternTable state 0"); // 0x0 is 00000000 all 4 states per byte to 0
114 : }
115 1536 : else if (newState == 1)
116 : {
117 512 : succeed_if (op->patternTable[i] == 0x55, "patternTable state 1"); // 0x55 is 01010101 all 4 states per byte to 1
118 : }
119 1024 : else if (newState == 2)
120 : {
121 512 : succeed_if (op->patternTable[i] == 0xAA, "patternTable state 2"); // 0xAA is 10101010 all 4 states per byte to 2
122 : }
123 512 : else if (newState == 3)
124 : {
125 512 : succeed_if (op->patternTable[i] == 0xFF, "patternTable state 3"); // 0xFF is 11111111 all 4 states per byte to 3
126 : }
127 : }
128 18 : }
129 :
130 :
131 2 : void test_internal_change_whitebox (void)
132 : {
133 2 : OpmphmPredictor * op = opmphmPredictorNew ();
134 2 : exit_if_fail (op, "opmphmPredictorNew");
135 2 : const size_t n = 1000;
136 : // inform predictor about size
137 2 : op->ksSize = n;
138 : // start state is 0
139 2 : test_internal_change_whitebox_set_to_state (0, 0, op, n);
140 2 : test_internal_change_whitebox_set_to_state (0, 1, op, n);
141 2 : test_internal_change_whitebox_set_to_state (1, 2, op, n);
142 2 : test_internal_change_whitebox_set_to_state (2, 3, op, n);
143 2 : test_internal_change_whitebox_set_to_state (3, 3, op, n);
144 2 : test_internal_change_whitebox_set_to_state (3, 2, op, n);
145 2 : test_internal_change_whitebox_set_to_state (2, 1, op, n);
146 2 : test_internal_change_whitebox_set_to_state (1, 0, op, n);
147 2 : test_internal_change_whitebox_set_to_state (0, 0, op, n);
148 :
149 2 : opmphmPredictorDel (op);
150 2 : }
151 :
152 :
153 2 : void test_ks_flag (void)
154 : {
155 2 : KeySet * ks = ksNew (10, KS_END);
156 2 : succeed_if (ks->flags & KS_FLAG_NAME_CHANGE, "flag not set at fresh ks");
157 :
158 2 : KeySet * copy = ksDup (ks);
159 2 : exit_if_fail (copy, "copy");
160 2 : succeed_if (copy->flags & KS_FLAG_NAME_CHANGE, "flag not set at copy ks");
161 2 : ksDel (copy);
162 :
163 2 : copy = ksDeepDup (ks);
164 2 : exit_if_fail (copy, "copy");
165 2 : succeed_if (copy->flags & KS_FLAG_NAME_CHANGE, "flag not set at copy ks");
166 2 : ksDel (copy);
167 :
168 2 : copy = ksNew (0, KS_END);
169 2 : succeed_if (ksCopy (copy, ks) == 1, "copy");
170 2 : succeed_if (copy->flags & KS_FLAG_NAME_CHANGE, "flag not set at copy ks");
171 2 : ksDel (copy);
172 :
173 2 : ksDel (ks);
174 2 : }
175 :
176 :
177 2 : void test_ks (void)
178 : {
179 : Key * found;
180 :
181 : // create keyset just under opmphmPredictorActionLimit
182 2 : KeySet * ks = ksNew (opmphmPredictorActionLimit, KS_END);
183 : char name[11]; // "/test" + "10000" + "\0"
184 1200 : for (size_t i = 0; i < opmphmPredictorActionLimit; ++i)
185 : {
186 1198 : snprintf (name, 11, "/test%zu", i);
187 1198 : succeed_if (ksAppendKey (ks, keyNew (name, KEY_END)) > 0, "ksAppendKey failed");
188 : }
189 :
190 : // predictor under limit
191 2 : found = ksLookupByName (ks, "/test0", KDB_O_NONE);
192 2 : succeed_if (found, "key found");
193 2 : exit_if_fail (!ks->opmphmPredictor, "predictor here");
194 :
195 : // append to be over opmphmPredictorActionLimit
196 2 : snprintf (name, 11, "/test%zu", opmphmPredictorActionLimit);
197 2 : succeed_if (ksAppendKey (ks, keyNew (name, KEY_END)) > 0, "ksAppendKey failed");
198 :
199 : // predictor over limit
200 2 : found = ksLookupByName (ks, "/test0", KDB_O_NOCASCADING);
201 2 : succeed_if (found, "key found");
202 2 : exit_if_fail (ks->opmphmPredictor, "predictor not here");
203 :
204 : // overrule with binary search
205 2 : found = ksLookupByName (ks, "/test0", KDB_O_BINSEARCH | KDB_O_NOCASCADING);
206 2 : succeed_if (found, "key found");
207 :
208 2 : succeed_if (ks->opmphmPredictor->lookupCount == 1, "predictor touched");
209 2 : succeed_if (ks->opmphmPredictor->history == 0, "predictor touched");
210 :
211 : // overrule with OPMPHM
212 2 : found = ksLookupByName (ks, "/test0", KDB_O_OPMPHM);
213 2 : succeed_if (found, "key found");
214 :
215 2 : succeed_if (ks->opmphmPredictor->lookupCount == 1, "predictor touched");
216 2 : succeed_if (ks->opmphmPredictor->history == 0, "predictor touched");
217 :
218 : // use predictor again
219 2 : found = ksLookupByName (ks, "/test0", KDB_O_NONE | KDB_O_NOCASCADING);
220 2 : succeed_if (found, "key found");
221 2 : succeed_if (ks->opmphmPredictor->lookupCount == 2, "predictor not touched");
222 :
223 : // copy
224 2 : KeySet * copy = ksDup (ks);
225 2 : exit_if_fail (copy, "copy");
226 2 : succeed_if (copy->opmphmPredictor->lookupCount == ks->opmphmPredictor->lookupCount, "copy predictor lookupCount");
227 2 : succeed_if (copy->opmphmPredictor->history == ks->opmphmPredictor->history, "copy predictor history");
228 2 : succeed_if (copy->opmphmPredictor->ksSize == ks->opmphmPredictor->ksSize, "copy predictor ksSize");
229 2 : ksDel (copy);
230 :
231 2 : copy = ksDeepDup (ks);
232 2 : exit_if_fail (copy, "copy");
233 2 : succeed_if (copy->opmphmPredictor->lookupCount == ks->opmphmPredictor->lookupCount, "copy predictor lookupCount");
234 2 : succeed_if (copy->opmphmPredictor->history == ks->opmphmPredictor->history, "copy predictor history");
235 2 : succeed_if (copy->opmphmPredictor->ksSize == ks->opmphmPredictor->ksSize, "copy predictor ksSize");
236 2 : ksDel (copy);
237 :
238 2 : copy = ksNew (0, KS_END);
239 2 : succeed_if (ksCopy (copy, ks) == 1, "copy");
240 2 : succeed_if (copy->opmphmPredictor->lookupCount == ks->opmphmPredictor->lookupCount, "copy predictor lookupCount");
241 2 : succeed_if (copy->opmphmPredictor->history == ks->opmphmPredictor->history, "copy predictor history");
242 2 : succeed_if (copy->opmphmPredictor->ksSize == ks->opmphmPredictor->ksSize, "copy predictor ksSize");
243 2 : ksDel (copy);
244 :
245 2 : ksDel (ks);
246 2 : }
247 :
248 :
249 2 : int main (int argc, char ** argv)
250 : {
251 2 : printf ("OPMPHM PREDICTOR TESTS\n");
252 2 : printf ("==================\n\n");
253 :
254 2 : init (argc, argv);
255 :
256 2 : test_internal_basic ();
257 2 : test_internal_nochange ();
258 2 : test_internal_change_whitebox ();
259 2 : test_ks_flag ();
260 2 : test_ks ();
261 :
262 2 : print_result ("test_opmphm_predictor");
263 :
264 2 : return nbError;
265 : }
|