1 /*
2  * This file Copyright (C) 2010-2014 Mnemosyne LLC
3  *
4  * It may be used under the GNU GPL versions 2 or 3
5  * or any future license endorsed by Mnemosyne LLC.
6  *
7  */
8 
9 #include <string.h> /* strlen() */
10 #include "transmission.h"
11 #include "crypto-utils.h"
12 #include "bitfield.h"
13 #include "utils.h" /* tr_free */
14 
15 #include "libtransmission-test.h"
16 
test_bitfield_count_range(void)17 static int test_bitfield_count_range(void)
18 {
19     int begin;
20     int end;
21     int count1;
22     int count2;
23     int const bitCount = 100 + tr_rand_int_weak(1000);
24     tr_bitfield bf;
25 
26     /* generate a random bitfield */
27     tr_bitfieldConstruct(&bf, bitCount);
28 
29     for (int i = 0, n = tr_rand_int_weak(bitCount); i < n; ++i)
30     {
31         tr_bitfieldAdd(&bf, tr_rand_int_weak(bitCount));
32     }
33 
34     begin = tr_rand_int_weak(bitCount);
35 
36     do
37     {
38         end = tr_rand_int_weak(bitCount);
39     }
40     while (end == begin);
41 
42     /* ensure end <= begin */
43     if (end < begin)
44     {
45         int const tmp = begin;
46         begin = end;
47         end = tmp;
48     }
49 
50     /* test the bitfield */
51     count1 = 0;
52 
53     for (int i = begin; i < end; ++i)
54     {
55         if (tr_bitfieldHas(&bf, i))
56         {
57             ++count1;
58         }
59     }
60 
61     count2 = tr_bitfieldCountRange(&bf, begin, end);
62     check_int(count1, ==, count2);
63 
64     /* cleanup */
65     tr_bitfieldDestruct(&bf);
66     return 0;
67 }
68 
test_bitfields(void)69 static int test_bitfields(void)
70 {
71     unsigned int bitcount = 500;
72     tr_bitfield field;
73 
74     tr_bitfieldConstruct(&field, bitcount);
75 
76     /* test tr_bitfieldAdd */
77     for (unsigned int i = 0; i < bitcount; i++)
78     {
79         if (i % 7 == 0)
80         {
81             tr_bitfieldAdd(&field, i);
82         }
83     }
84 
85     for (unsigned int i = 0; i < bitcount; i++)
86     {
87         check_bool(tr_bitfieldHas(&field, i), ==, (i % 7 == 0));
88     }
89 
90     /* test tr_bitfieldAddRange */
91     tr_bitfieldAddRange(&field, 0, bitcount);
92 
93     for (unsigned int i = 0; i < bitcount; i++)
94     {
95         check(tr_bitfieldHas(&field, i));
96     }
97 
98     /* test tr_bitfieldRem */
99     for (unsigned int i = 0; i < bitcount; i++)
100     {
101         if (i % 7 != 0)
102         {
103             tr_bitfieldRem(&field, i);
104         }
105     }
106 
107     for (unsigned int i = 0; i < bitcount; i++)
108     {
109         check_bool(tr_bitfieldHas(&field, i), ==, (i % 7 == 0));
110     }
111 
112     /* test tr_bitfieldRemRange in the middle of a boundary */
113     tr_bitfieldAddRange(&field, 0, 64);
114     tr_bitfieldRemRange(&field, 4, 21);
115 
116     for (unsigned int i = 0; i < 64; i++)
117     {
118         check_bool(tr_bitfieldHas(&field, i), ==, (i < 4 || i >= 21));
119     }
120 
121     /* test tr_bitfieldRemRange on the boundaries */
122     tr_bitfieldAddRange(&field, 0, 64);
123     tr_bitfieldRemRange(&field, 8, 24);
124 
125     for (unsigned int i = 0; i < 64; i++)
126     {
127         check_bool(tr_bitfieldHas(&field, i), ==, (i < 8 || i >= 24));
128     }
129 
130     /* test tr_bitfieldRemRange when begin & end is on the same word */
131     tr_bitfieldAddRange(&field, 0, 64);
132     tr_bitfieldRemRange(&field, 4, 5);
133 
134     for (unsigned int i = 0; i < 64; i++)
135     {
136         check_bool(tr_bitfieldHas(&field, i), ==, (i < 4 || i >= 5));
137     }
138 
139     /* test tr_bitfieldAddRange */
140     tr_bitfieldRemRange(&field, 0, 64);
141     tr_bitfieldAddRange(&field, 4, 21);
142 
143     for (unsigned int i = 0; i < 64; i++)
144     {
145         check_bool(tr_bitfieldHas(&field, i), ==, (4 <= i && i < 21));
146     }
147 
148     /* test tr_bitfieldAddRange on the boundaries */
149     tr_bitfieldRemRange(&field, 0, 64);
150     tr_bitfieldAddRange(&field, 8, 24);
151 
152     for (unsigned int i = 0; i < 64; i++)
153     {
154         check_bool(tr_bitfieldHas(&field, i), ==, (8 <= i && i < 24));
155     }
156 
157     /* test tr_bitfieldAddRange when begin & end is on the same word */
158     tr_bitfieldRemRange(&field, 0, 64);
159     tr_bitfieldAddRange(&field, 4, 5);
160 
161     for (unsigned int i = 0; i < 64; i++)
162     {
163         check_bool(tr_bitfieldHas(&field, i), ==, (4 <= i && i < 5));
164     }
165 
166     tr_bitfieldDestruct(&field);
167     return 0;
168 }
169 
test_bitfield_has_all_none(void)170 static int test_bitfield_has_all_none(void)
171 {
172     tr_bitfield field;
173 
174     tr_bitfieldConstruct(&field, 3);
175 
176     check(!tr_bitfieldHasAll(&field));
177     check(tr_bitfieldHasNone(&field));
178 
179     tr_bitfieldAdd(&field, 0);
180     check(!tr_bitfieldHasAll(&field));
181     check(!tr_bitfieldHasNone(&field));
182 
183     tr_bitfieldRem(&field, 0);
184     tr_bitfieldAdd(&field, 1);
185     check(!tr_bitfieldHasAll(&field));
186     check(!tr_bitfieldHasNone(&field));
187 
188     tr_bitfieldRem(&field, 1);
189     tr_bitfieldAdd(&field, 2);
190     check(!tr_bitfieldHasAll(&field));
191     check(!tr_bitfieldHasNone(&field));
192 
193     tr_bitfieldAdd(&field, 0);
194     tr_bitfieldAdd(&field, 1);
195     check(tr_bitfieldHasAll(&field));
196     check(!tr_bitfieldHasNone(&field));
197 
198     tr_bitfieldSetHasNone(&field);
199     check(!tr_bitfieldHasAll(&field));
200     check(tr_bitfieldHasNone(&field));
201 
202     tr_bitfieldSetHasAll(&field);
203     check(tr_bitfieldHasAll(&field));
204     check(!tr_bitfieldHasNone(&field));
205 
206     tr_bitfieldDestruct(&field);
207     tr_bitfieldConstruct(&field, 0);
208 
209     check(!tr_bitfieldHasAll(&field));
210     check(!tr_bitfieldHasNone(&field));
211 
212     tr_bitfieldSetHasNone(&field);
213     check(!tr_bitfieldHasAll(&field));
214     check(tr_bitfieldHasNone(&field));
215 
216     tr_bitfieldSetHasAll(&field);
217     check(tr_bitfieldHasAll(&field));
218     check(!tr_bitfieldHasNone(&field));
219 
220     tr_bitfieldDestruct(&field);
221     return 0;
222 }
223 
main(void)224 int main(void)
225 {
226     testFunc const tests[] =
227     {
228         test_bitfields,
229         test_bitfield_has_all_none
230     };
231 
232     int ret = runTests(tests, NUM_TESTS(tests));
233 
234     /* bitfield count range */
235     for (int l = 0; l < 10000; ++l)
236     {
237         if (test_bitfield_count_range() != 0)
238         {
239             ++ret;
240         }
241     }
242 
243     return ret;
244 }
245