geoip2_c 0.3.2 → 0.3.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (132) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/ubuntu.yml +33 -0
  3. data/.github/workflows/windows.yml +52 -0
  4. data/README.md +22 -10
  5. data/docker-compose.yml +22 -1
  6. data/dockerfiles/{Dockerfile-ruby2.3 → Dockerfile-ruby2.5} +1 -1
  7. data/dockerfiles/{Dockerfile-ruby2.1 → Dockerfile-ruby2.6} +1 -1
  8. data/dockerfiles/{Dockerfile-ruby2.2 → Dockerfile-ruby2.7} +1 -1
  9. data/ext/geoip2/extconf.rb +11 -4
  10. data/ext/geoip2/geoip2.c +63 -18
  11. data/ext/geoip2/libmaxminddb/.gitignore +3 -0
  12. data/ext/geoip2/libmaxminddb/.travis.yml +24 -2
  13. data/ext/geoip2/libmaxminddb/Changes.md +39 -0
  14. data/ext/geoip2/libmaxminddb/README.dev.md +41 -30
  15. data/ext/geoip2/libmaxminddb/README.md +3 -3
  16. data/ext/geoip2/libmaxminddb/bin/Makefile.am +5 -0
  17. data/ext/geoip2/libmaxminddb/bin/mmdblookup.c +333 -15
  18. data/ext/geoip2/libmaxminddb/configure.ac +5 -5
  19. data/ext/geoip2/libmaxminddb/dev-bin/ppa-release.sh +8 -5
  20. data/ext/geoip2/libmaxminddb/dev-bin/release.sh +7 -0
  21. data/ext/geoip2/libmaxminddb/dev-bin/valgrind-all.pl +10 -3
  22. data/ext/geoip2/libmaxminddb/include/maxminddb.h +11 -2
  23. data/ext/geoip2/libmaxminddb/projects/VS12/libmaxminddb.vcxproj +3 -1
  24. data/ext/geoip2/libmaxminddb/projects/VS12/libmaxminddb.vcxproj.filters +7 -1
  25. data/ext/geoip2/libmaxminddb/src/Makefile.am +18 -2
  26. data/ext/geoip2/libmaxminddb/src/data-pool.c +180 -0
  27. data/ext/geoip2/libmaxminddb/src/data-pool.h +52 -0
  28. data/ext/geoip2/libmaxminddb/src/maxminddb.c +58 -48
  29. data/ext/geoip2/libmaxminddb/t/Makefile.am +6 -2
  30. data/ext/geoip2/libmaxminddb/t/bad_databases_t.c +1 -0
  31. data/ext/geoip2/libmaxminddb/t/basic_lookup_t.c +35 -0
  32. data/ext/geoip2/libmaxminddb/t/data-pool-t.c +374 -0
  33. data/ext/geoip2/libmaxminddb/t/external_symbols_t.pl +106 -0
  34. data/ext/geoip2/libmaxminddb/t/libtap/.gitignore +13 -0
  35. data/ext/geoip2/libmaxminddb/t/libtap/.travis.yml +13 -0
  36. data/ext/geoip2/libmaxminddb/t/libtap/COPYING +165 -0
  37. data/ext/geoip2/libmaxminddb/t/libtap/INSTALL +41 -0
  38. data/ext/geoip2/libmaxminddb/t/libtap/Makefile +72 -0
  39. data/ext/geoip2/libmaxminddb/t/libtap/Makefile.win +37 -0
  40. data/ext/geoip2/libmaxminddb/t/libtap/README.md +268 -0
  41. data/ext/geoip2/libmaxminddb/t/libtap/t/cmp_mem.c +20 -0
  42. data/ext/geoip2/libmaxminddb/t/libtap/t/cmp_mem.expected +28 -0
  43. data/ext/geoip2/libmaxminddb/t/libtap/t/cmpok.c +16 -0
  44. data/ext/geoip2/libmaxminddb/t/libtap/t/cmpok.expected +37 -0
  45. data/ext/geoip2/libmaxminddb/t/libtap/t/diag.c +10 -0
  46. data/ext/geoip2/libmaxminddb/t/libtap/t/diag.expected +2 -0
  47. data/ext/geoip2/libmaxminddb/t/libtap/t/diesok.c +14 -0
  48. data/ext/geoip2/libmaxminddb/t/libtap/t/diesok.expected +6 -0
  49. data/ext/geoip2/libmaxminddb/t/libtap/t/is.c +24 -0
  50. data/ext/geoip2/libmaxminddb/t/libtap/t/is.expected +58 -0
  51. data/ext/geoip2/libmaxminddb/t/libtap/t/like.c +10 -0
  52. data/ext/geoip2/libmaxminddb/t/libtap/t/like.expected +4 -0
  53. data/ext/geoip2/libmaxminddb/t/libtap/t/simple.c +31 -0
  54. data/ext/geoip2/libmaxminddb/t/libtap/t/simple.expected +32 -0
  55. data/ext/geoip2/libmaxminddb/t/libtap/t/skip.c +23 -0
  56. data/ext/geoip2/libmaxminddb/t/libtap/t/skip.expected +9 -0
  57. data/ext/geoip2/libmaxminddb/t/libtap/t/synopsis.c +13 -0
  58. data/ext/geoip2/libmaxminddb/t/libtap/t/synopsis.expected +9 -0
  59. data/ext/geoip2/libmaxminddb/t/libtap/t/test.c +28 -0
  60. data/ext/geoip2/libmaxminddb/t/libtap/t/todo.c +17 -0
  61. data/ext/geoip2/libmaxminddb/t/libtap/t/todo.expected +11 -0
  62. data/ext/geoip2/libmaxminddb/t/libtap/tap.c +354 -0
  63. data/ext/geoip2/libmaxminddb/t/libtap/tap.h +115 -0
  64. data/ext/geoip2/libmaxminddb/t/maxmind-db/.gitattributes +1 -0
  65. data/ext/geoip2/libmaxminddb/t/maxmind-db/.gitconfig +2 -0
  66. data/ext/geoip2/libmaxminddb/t/maxmind-db/.gitignore +2 -0
  67. data/ext/geoip2/libmaxminddb/t/maxmind-db/.perltidyallrc +11 -0
  68. data/ext/geoip2/libmaxminddb/t/maxmind-db/.tidyallrc +7 -0
  69. data/ext/geoip2/libmaxminddb/t/maxmind-db/LICENSE +4 -0
  70. data/ext/geoip2/libmaxminddb/t/maxmind-db/MaxMind-DB-spec.md +558 -0
  71. data/ext/geoip2/libmaxminddb/t/maxmind-db/README.md +4 -0
  72. data/ext/geoip2/libmaxminddb/t/maxmind-db/bad-data/README.md +7 -0
  73. data/ext/geoip2/libmaxminddb/t/maxmind-db/bad-data/libmaxminddb/libmaxminddb-offset-integer-overflow.mmdb +0 -0
  74. data/ext/geoip2/libmaxminddb/t/maxmind-db/bad-data/maxminddb-golang/cyclic-data-structure.mmdb +0 -0
  75. data/ext/geoip2/libmaxminddb/t/maxmind-db/bad-data/maxminddb-golang/invalid-bytes-length.mmdb +1 -0
  76. data/ext/geoip2/libmaxminddb/t/maxmind-db/bad-data/maxminddb-golang/invalid-data-record-offset.mmdb +0 -0
  77. data/ext/geoip2/libmaxminddb/t/maxmind-db/bad-data/maxminddb-golang/invalid-map-key-length.mmdb +0 -0
  78. data/ext/geoip2/libmaxminddb/t/maxmind-db/bad-data/maxminddb-golang/invalid-string-length.mmdb +1 -0
  79. data/ext/geoip2/libmaxminddb/t/maxmind-db/bad-data/maxminddb-golang/metadata-is-an-uint128.mmdb +1 -0
  80. data/ext/geoip2/libmaxminddb/t/maxmind-db/bad-data/maxminddb-golang/unexpected-bytes.mmdb +0 -0
  81. data/ext/geoip2/libmaxminddb/t/maxmind-db/perltidyrc +12 -0
  82. data/ext/geoip2/libmaxminddb/t/maxmind-db/source-data/GeoIP2-Anonymous-IP-Test.json +32 -0
  83. data/ext/geoip2/libmaxminddb/t/maxmind-db/source-data/GeoIP2-City-Test.json +12616 -0
  84. data/ext/geoip2/libmaxminddb/t/maxmind-db/source-data/GeoIP2-Connection-Type-Test.json +102 -0
  85. data/ext/geoip2/libmaxminddb/t/maxmind-db/source-data/GeoIP2-Country-Test.json +10975 -0
  86. data/ext/geoip2/libmaxminddb/t/maxmind-db/source-data/GeoIP2-DensityIncome-Test.json +14 -0
  87. data/ext/geoip2/libmaxminddb/t/maxmind-db/source-data/GeoIP2-Domain-Test.json +452 -0
  88. data/ext/geoip2/libmaxminddb/t/maxmind-db/source-data/GeoIP2-Enterprise-Test.json +666 -0
  89. data/ext/geoip2/libmaxminddb/t/maxmind-db/source-data/GeoIP2-ISP-Test.json +12585 -0
  90. data/ext/geoip2/libmaxminddb/t/maxmind-db/source-data/GeoIP2-Precision-Enterprise-Test.json +1035 -0
  91. data/ext/geoip2/libmaxminddb/t/maxmind-db/source-data/GeoLite2-ASN-Test.json +37 -0
  92. data/ext/geoip2/libmaxminddb/t/maxmind-db/source-data/README +13 -0
  93. data/ext/geoip2/libmaxminddb/t/maxmind-db/test-data/GeoIP2-Anonymous-IP-Test.mmdb +0 -0
  94. data/ext/geoip2/libmaxminddb/t/maxmind-db/test-data/GeoIP2-City-Test-Broken-Double-Format.mmdb +0 -0
  95. data/ext/geoip2/libmaxminddb/t/maxmind-db/test-data/GeoIP2-City-Test-Invalid-Node-Count.mmdb +0 -0
  96. data/ext/geoip2/libmaxminddb/t/maxmind-db/test-data/GeoIP2-City-Test.mmdb +0 -0
  97. data/ext/geoip2/libmaxminddb/t/maxmind-db/test-data/GeoIP2-Connection-Type-Test.mmdb +0 -0
  98. data/ext/geoip2/libmaxminddb/t/maxmind-db/test-data/GeoIP2-Country-Test.mmdb +0 -0
  99. data/ext/geoip2/libmaxminddb/t/maxmind-db/test-data/GeoIP2-DensityIncome-Test.mmdb +0 -0
  100. data/ext/geoip2/libmaxminddb/t/maxmind-db/test-data/GeoIP2-Domain-Test.mmdb +0 -0
  101. data/ext/geoip2/libmaxminddb/t/maxmind-db/test-data/GeoIP2-Enterprise-Test.mmdb +0 -0
  102. data/ext/geoip2/libmaxminddb/t/maxmind-db/test-data/GeoIP2-ISP-Test.mmdb +0 -0
  103. data/ext/geoip2/libmaxminddb/t/maxmind-db/test-data/GeoIP2-Precision-Enterprise-Test.mmdb +0 -0
  104. data/ext/geoip2/libmaxminddb/t/maxmind-db/test-data/GeoLite2-ASN-Test.mmdb +0 -0
  105. data/ext/geoip2/libmaxminddb/t/maxmind-db/test-data/MaxMind-DB-no-ipv4-search-tree.mmdb +0 -0
  106. data/ext/geoip2/libmaxminddb/t/maxmind-db/test-data/MaxMind-DB-string-value-entries.mmdb +0 -0
  107. data/ext/geoip2/libmaxminddb/t/maxmind-db/test-data/MaxMind-DB-test-broken-pointers-24.mmdb +0 -0
  108. data/ext/geoip2/libmaxminddb/t/maxmind-db/test-data/MaxMind-DB-test-broken-search-tree-24.mmdb +0 -0
  109. data/ext/geoip2/libmaxminddb/t/maxmind-db/test-data/MaxMind-DB-test-decoder.mmdb +0 -0
  110. data/ext/geoip2/libmaxminddb/t/maxmind-db/test-data/MaxMind-DB-test-ipv4-24.mmdb +0 -0
  111. data/ext/geoip2/libmaxminddb/t/maxmind-db/test-data/MaxMind-DB-test-ipv4-28.mmdb +0 -0
  112. data/ext/geoip2/libmaxminddb/t/maxmind-db/test-data/MaxMind-DB-test-ipv4-32.mmdb +0 -0
  113. data/ext/geoip2/libmaxminddb/t/maxmind-db/test-data/MaxMind-DB-test-ipv6-24.mmdb +0 -0
  114. data/ext/geoip2/libmaxminddb/t/maxmind-db/test-data/MaxMind-DB-test-ipv6-28.mmdb +0 -0
  115. data/ext/geoip2/libmaxminddb/t/maxmind-db/test-data/MaxMind-DB-test-ipv6-32.mmdb +0 -0
  116. data/ext/geoip2/libmaxminddb/t/maxmind-db/test-data/MaxMind-DB-test-metadata-pointers.mmdb +0 -0
  117. data/ext/geoip2/libmaxminddb/t/maxmind-db/test-data/MaxMind-DB-test-mixed-24.mmdb +0 -0
  118. data/ext/geoip2/libmaxminddb/t/maxmind-db/test-data/MaxMind-DB-test-mixed-28.mmdb +0 -0
  119. data/ext/geoip2/libmaxminddb/t/maxmind-db/test-data/MaxMind-DB-test-mixed-32.mmdb +0 -0
  120. data/ext/geoip2/libmaxminddb/t/maxmind-db/test-data/MaxMind-DB-test-nested.mmdb +0 -0
  121. data/ext/geoip2/libmaxminddb/t/maxmind-db/test-data/README.md +26 -0
  122. data/ext/geoip2/libmaxminddb/t/maxmind-db/test-data/maps-with-pointers.raw +0 -0
  123. data/ext/geoip2/libmaxminddb/t/maxmind-db/test-data/write-test-data.pl +614 -0
  124. data/ext/geoip2/libmaxminddb/t/maxmind-db/tidyall.ini +5 -0
  125. data/geoip2_c.gemspec +2 -3
  126. data/lib/geoip2/database.rb +4 -0
  127. data/lib/geoip2/version.rb +1 -1
  128. metadata +114 -22
  129. data/.travis.yml +0 -31
  130. data/Appraisals +0 -7
  131. data/gemfiles/ruby_2.1.gemfile +0 -7
  132. data/gemfiles/ruby_2.2.gemfile +0 -7
@@ -0,0 +1,374 @@
1
+ #include <assert.h>
2
+ #include <data-pool.h>
3
+ #include <inttypes.h>
4
+ #include "libtap/tap.h"
5
+ #include <math.h>
6
+ #include "maxminddb_test_helper.h"
7
+
8
+ static void test_data_pool_new(void);
9
+ static void test_data_pool_destroy(void);
10
+ static void test_data_pool_alloc(void);
11
+ static void test_data_pool_to_list(void);
12
+ static bool create_and_check_list(size_t const,
13
+ size_t const);
14
+ static void check_block_count(MMDB_entry_data_list_s const *const,
15
+ size_t const);
16
+
17
+ int main(void)
18
+ {
19
+ plan(NO_PLAN);
20
+ test_data_pool_new();
21
+ test_data_pool_destroy();
22
+ test_data_pool_alloc();
23
+ test_data_pool_to_list();
24
+ done_testing();
25
+ }
26
+
27
+ static void test_data_pool_new(void)
28
+ {
29
+ {
30
+ MMDB_data_pool_s *const pool = data_pool_new(0);
31
+ ok(!pool, "size 0 is not valid");
32
+ }
33
+
34
+ {
35
+ MMDB_data_pool_s *const pool = data_pool_new(SIZE_MAX - 10);
36
+ ok(!pool, "very large size is not valid");
37
+ }
38
+
39
+ {
40
+ MMDB_data_pool_s *const pool = data_pool_new(512);
41
+ ok(pool != NULL, "size 512 is valid");
42
+ cmp_ok(pool->size, "==", 512, "size is 512");
43
+ cmp_ok(pool->used, "==", 0, "used size is 0");
44
+ data_pool_destroy(pool);
45
+ }
46
+ }
47
+
48
+ static void test_data_pool_destroy(void)
49
+ {
50
+ {
51
+ data_pool_destroy(NULL);
52
+ }
53
+
54
+ {
55
+ MMDB_data_pool_s *const pool = data_pool_new(512);
56
+ ok(pool != NULL, "created pool");
57
+ data_pool_destroy(pool);
58
+ }
59
+ }
60
+
61
+ static void test_data_pool_alloc(void)
62
+ {
63
+ {
64
+ MMDB_data_pool_s *const pool = data_pool_new(1);
65
+ ok(pool != NULL, "created pool");
66
+ cmp_ok(pool->used, "==", 0, "used size starts at 0");
67
+
68
+ MMDB_entry_data_list_s *const entry1 = data_pool_alloc(pool);
69
+ ok(entry1 != NULL, "allocated first entry");
70
+ // Arbitrary so that we can recognize it.
71
+ entry1->entry_data.offset = (uint32_t)123;
72
+
73
+ cmp_ok(pool->size, "==", 1, "size is still 1");
74
+ cmp_ok(pool->used, "==", 1, "used size is 1 after taking one");
75
+
76
+ MMDB_entry_data_list_s *const entry2 = data_pool_alloc(pool);
77
+ ok(entry2 != NULL, "got another entry");
78
+ ok(entry1 != entry2, "second entry is different from first entry");
79
+
80
+ cmp_ok(pool->size, "==", 2, "size is 2 (new block)");
81
+ cmp_ok(pool->used, "==", 1, "used size is 1 in current block");
82
+
83
+ ok(entry1->entry_data.offset == 123,
84
+ "accessing the original entry's memory is ok");
85
+
86
+ data_pool_destroy(pool);
87
+ }
88
+
89
+ {
90
+ size_t const initial_size = 10;
91
+ MMDB_data_pool_s *const pool = data_pool_new(initial_size);
92
+ ok(pool != NULL, "created pool");
93
+
94
+ MMDB_entry_data_list_s *entry1 = NULL;
95
+ for (size_t i = 0; i < initial_size; i++) {
96
+ MMDB_entry_data_list_s *const entry = data_pool_alloc(pool);
97
+ ok(entry != NULL, "got an entry");
98
+ // Give each a unique number so we can check it.
99
+ entry->entry_data.offset = (uint32_t)i;
100
+ if (i == 0) {
101
+ entry1 = entry;
102
+ }
103
+ }
104
+
105
+ cmp_ok(pool->size, "==", initial_size, "size is the initial size");
106
+ cmp_ok(pool->used, "==", initial_size, "used size is as expected");
107
+
108
+ MMDB_entry_data_list_s *const entry = data_pool_alloc(pool);
109
+ ok(entry != NULL, "got an entry");
110
+ entry->entry_data.offset = (uint32_t)initial_size;
111
+
112
+ cmp_ok(pool->size, "==", initial_size * 2,
113
+ "size is the initial size*2");
114
+ cmp_ok(pool->used, "==", 1, "used size is as expected");
115
+
116
+ MMDB_entry_data_list_s *const list = data_pool_to_list(pool);
117
+
118
+ MMDB_entry_data_list_s *element = list;
119
+ for (size_t i = 0; i < initial_size + 1; i++) {
120
+ ok(
121
+ element->entry_data.offset == (uint32_t)i,
122
+ "found offset %" PRIu32 ", should have %zu",
123
+ element->entry_data.offset,
124
+ i
125
+ );
126
+ element = element->next;
127
+ }
128
+
129
+ ok(entry1->entry_data.offset == (uint32_t)0,
130
+ "accessing entry1's original memory is ok after growing the pool");
131
+
132
+ data_pool_destroy(pool);
133
+ }
134
+ }
135
+
136
+ static void test_data_pool_to_list(void)
137
+ {
138
+ {
139
+ size_t const initial_size = 16;
140
+ MMDB_data_pool_s *const pool = data_pool_new(initial_size);
141
+ ok(pool != NULL, "created pool");
142
+
143
+ MMDB_entry_data_list_s *const entry1 = data_pool_alloc(pool);
144
+ ok(entry1 != NULL, "got an entry");
145
+
146
+ MMDB_entry_data_list_s *const list_one_element
147
+ = data_pool_to_list(pool);
148
+ ok(list_one_element != NULL, "got a list");
149
+ ok(list_one_element == entry1,
150
+ "list's first element is the first we retrieved");
151
+ ok(list_one_element->next == NULL, "list is one element in size");
152
+
153
+ MMDB_entry_data_list_s *const entry2 = data_pool_alloc(pool);
154
+ ok(entry2 != NULL, "got another entry");
155
+
156
+ MMDB_entry_data_list_s *const list_two_elements
157
+ = data_pool_to_list(pool);
158
+ ok(list_two_elements != NULL, "got a list");
159
+ ok(list_two_elements == entry1,
160
+ "list's first element is the first we retrieved");
161
+ ok(list_two_elements->next != NULL, "list has a second element");
162
+
163
+ MMDB_entry_data_list_s *const second_element = list_two_elements->next;
164
+ ok(second_element == entry2,
165
+ "second item in list is second we retrieved");
166
+ ok(second_element->next == NULL, "list ends with the second element");
167
+
168
+ data_pool_destroy(pool);
169
+ }
170
+
171
+ {
172
+ size_t const initial_size = 1;
173
+ MMDB_data_pool_s *const pool = data_pool_new(initial_size);
174
+ ok(pool != NULL, "created pool");
175
+
176
+ MMDB_entry_data_list_s *const entry1 = data_pool_alloc(pool);
177
+ ok(entry1 != NULL, "got an entry");
178
+
179
+ MMDB_entry_data_list_s *const list_one_element
180
+ = data_pool_to_list(pool);
181
+ ok(list_one_element != NULL, "got a list");
182
+ ok(list_one_element == entry1,
183
+ "list's first element is the first we retrieved");
184
+ ok(list_one_element->next == NULL, "list ends with this element");
185
+
186
+ data_pool_destroy(pool);
187
+ }
188
+
189
+ {
190
+ size_t const initial_size = 2;
191
+ MMDB_data_pool_s *const pool = data_pool_new(initial_size);
192
+ ok(pool != NULL, "created pool");
193
+
194
+ MMDB_entry_data_list_s *const entry1 = data_pool_alloc(pool);
195
+ ok(entry1 != NULL, "got an entry");
196
+
197
+ MMDB_entry_data_list_s *const entry2 = data_pool_alloc(pool);
198
+ ok(entry2 != NULL, "got an entry");
199
+ ok(entry1 != entry2, "second entry is different from the first");
200
+
201
+ MMDB_entry_data_list_s *const list_element1 = data_pool_to_list(pool);
202
+ ok(list_element1 != NULL, "got a list");
203
+ ok(list_element1 == entry1,
204
+ "list's first element is the first we retrieved");
205
+
206
+ MMDB_entry_data_list_s *const list_element2 = list_element1->next;
207
+ ok(list_element2 == entry2,
208
+ "second element is the second we retrieved");
209
+ ok(list_element2->next == NULL, "list ends with this element");
210
+
211
+ data_pool_destroy(pool);
212
+ }
213
+
214
+ {
215
+ diag("starting test: fill one block save for one spot");
216
+ ok(
217
+ create_and_check_list(3, 2),
218
+ "fill one block save for one spot"
219
+ );
220
+ }
221
+
222
+ {
223
+ diag("starting test: fill one block");
224
+ ok(
225
+ create_and_check_list(3, 3),
226
+ "fill one block"
227
+ );
228
+ }
229
+
230
+ {
231
+ diag("starting test: fill one block and use one spot in the next block");
232
+ ok(
233
+ create_and_check_list(3, 3 + 1),
234
+ "fill one block and use one spot in the next block"
235
+ );
236
+ }
237
+
238
+ {
239
+ diag("starting test: fill two blocks save for one spot");
240
+ ok(
241
+ create_and_check_list(3, 3 + 3 * 2 - 1),
242
+ "fill two blocks save for one spot"
243
+ );
244
+ }
245
+
246
+ {
247
+ diag("starting test: fill two blocks");
248
+ ok(
249
+ create_and_check_list(3, 3 + 3 * 2),
250
+ "fill two blocks"
251
+ );
252
+ }
253
+
254
+ {
255
+ diag("starting test: fill two blocks and use one spot in the next");
256
+ ok(
257
+ create_and_check_list(3, 3 + 3 * 2 + 1),
258
+ "fill two blocks and use one spot in the next"
259
+ );
260
+ }
261
+
262
+ {
263
+ diag("starting test: fill three blocks save for one spot");
264
+ ok(
265
+ create_and_check_list(3, 3 + 3 * 2 + 3 * 2 * 2 - 1),
266
+ "fill three blocks save for one spot"
267
+ );
268
+ }
269
+
270
+ {
271
+ diag("starting test: fill three blocks");
272
+ ok(
273
+ create_and_check_list(3, 3 + 3 * 2 + 3 * 2 * 2),
274
+ "fill three blocks"
275
+ );
276
+ }
277
+
278
+ // It would be nice to have a larger number of these, but it's expensive to
279
+ // run many. We currently hardcode what this will be anyway, so varying
280
+ // this is not very interesting.
281
+ size_t const initial_sizes[] = { 1, 2, 32, 64, 128, 256 };
282
+
283
+ size_t const max_element_count = 4096;
284
+
285
+ for (size_t i = 0; i < sizeof(initial_sizes) / sizeof(initial_sizes[0]);
286
+ i++) {
287
+ size_t const initial_size = initial_sizes[i];
288
+
289
+ for (size_t element_count = 0; element_count < max_element_count;
290
+ element_count++) {
291
+ assert(create_and_check_list(initial_size, element_count));
292
+ }
293
+ }
294
+ }
295
+
296
+ // Use assert() rather than libtap as libtap is significantly slower and we run
297
+ // this frequently.
298
+ static bool create_and_check_list(size_t const initial_size,
299
+ size_t const element_count)
300
+ {
301
+ MMDB_data_pool_s *const pool = data_pool_new(initial_size);
302
+ assert(pool != NULL);
303
+
304
+ assert(pool->used == 0);
305
+
306
+ // Hold on to the pointers as we initially see them so that we can check
307
+ // they are still valid after building the list.
308
+ MMDB_entry_data_list_s **const entry_array
309
+ = calloc(element_count, sizeof(MMDB_entry_data_list_s *));
310
+ assert(entry_array != NULL);
311
+
312
+ for (size_t i = 0; i < element_count; i++) {
313
+ MMDB_entry_data_list_s *const entry = data_pool_alloc(pool);
314
+ assert(entry != NULL);
315
+
316
+ entry->entry_data.offset = (uint32_t)i;
317
+
318
+ entry_array[i] = entry;
319
+ }
320
+
321
+ MMDB_entry_data_list_s *const list = data_pool_to_list(pool);
322
+
323
+ if (element_count == 0) {
324
+ assert(list == NULL);
325
+ data_pool_destroy(pool);
326
+ free(entry_array);
327
+ return true;
328
+ }
329
+
330
+ assert(list != NULL);
331
+
332
+ MMDB_entry_data_list_s *element = list;
333
+ for (size_t i = 0; i < element_count; i++) {
334
+ assert(element->entry_data.offset == (uint32_t)i);
335
+
336
+ assert(element == entry_array[i]);
337
+
338
+ element = element->next;
339
+ }
340
+ assert(element == NULL);
341
+
342
+ check_block_count(list, initial_size);
343
+
344
+ data_pool_destroy(pool);
345
+ free(entry_array);
346
+ return true;
347
+ }
348
+
349
+ // Use assert() rather than libtap as libtap is significantly slower and we run
350
+ // this frequently.
351
+ static void check_block_count(MMDB_entry_data_list_s const *const list,
352
+ size_t const initial_size)
353
+ {
354
+ size_t got_block_count = 0;
355
+ size_t got_element_count = 0;
356
+
357
+ MMDB_entry_data_list_s const *element = list;
358
+ while (element) {
359
+ got_element_count++;
360
+
361
+ if (element->pool) {
362
+ got_block_count++;
363
+ }
364
+
365
+ element = element->next;
366
+ }
367
+
368
+ // Because <number of elements> = <initial size> * 2^(number of blocks)
369
+ double const a = ceil((double)got_element_count / (double)initial_size);
370
+ double const b = log2(a);
371
+ size_t const expected_block_count = ((size_t)b) + 1;
372
+
373
+ assert(got_block_count == expected_block_count);
374
+ }
@@ -0,0 +1,106 @@
1
+ #!/usr/bin/env perl
2
+
3
+ use strict;
4
+ use warnings;
5
+
6
+ use FindBin qw( $Bin );
7
+
8
+ _skip_tests_if_required_modules_are_not_present();
9
+ _skip_tests_if_nm_is_not_present();
10
+ _test_libs_external_symbols();
11
+
12
+ done_testing();
13
+
14
+ sub _skip_tests_if_required_modules_are_not_present {
15
+ eval <<'EOF';
16
+ use Test::More 0.88;
17
+ use IPC::Run3 qw( run3 );
18
+ EOF
19
+
20
+ if ($@) {
21
+ print
22
+ "1..0 # skip all tests skipped - these tests need the Test::More 0.88, IPC::Run3 modules:\n";
23
+ print "$@";
24
+ exit 0;
25
+ }
26
+ }
27
+
28
+ sub _skip_tests_if_nm_is_not_present {
29
+ run3(
30
+ [ 'nm', '-V' ],
31
+ \undef,
32
+ \undef,
33
+ \undef,
34
+ );
35
+
36
+ my $exit_status = $? >> 8;
37
+ if ($exit_status) {
38
+ print
39
+ "1..0 # skipp all tests skipped - this test requires the command line utility `nm`.\n";
40
+ exit 0;
41
+ }
42
+ }
43
+
44
+ sub _test_libs_external_symbols {
45
+ my @libs = _libs_to_test();
46
+
47
+ if (@libs) {
48
+ for my $lib (@libs) {
49
+ _test_lib_external_symbols($lib);
50
+ }
51
+ }
52
+ else {
53
+ fail('No libs were found to test');
54
+ }
55
+ }
56
+
57
+ sub _libs_to_test {
58
+ my $lib_dir = "$Bin/../src/.libs";
59
+ opendir my $dh, $lib_dir
60
+ or die "Failed to open the lib dir at $lib_dir for reading: $!\n";
61
+ my @libs = map { $lib_dir . q{/} . $_ }
62
+ grep { $_ =~ m/\.so$/ } readdir $dh;
63
+ closedir $dh;
64
+
65
+ return @libs;
66
+ }
67
+
68
+ sub _test_lib_external_symbols {
69
+ my $lib = shift;
70
+
71
+ my $stdout;
72
+ my $stderr;
73
+ run3(
74
+ [ 'nm', '-g', '--defined-only', $lib ],
75
+ \undef,
76
+ \$stdout,
77
+ \$stderr,
78
+ );
79
+
80
+ my $exit_status = $? >> 8;
81
+ ok( !$exit_status, 'nm returned a non-error status' )
82
+ or diag($stderr);
83
+
84
+ my @external_symbols = _extract_external_symbols($stdout);
85
+ is_deeply(
86
+ [ grep { $_ !~ m/^MMDB_/ } @external_symbols ],
87
+ [],
88
+ "$lib exports only MMDB_ symbols"
89
+ );
90
+ }
91
+
92
+ sub _extract_external_symbols {
93
+ my $nm_output = shift;
94
+
95
+ my @lines = split /\r\n|\r|\n/, $nm_output;
96
+
97
+ my @external_symbols;
98
+ for my $line (@lines) {
99
+ my @fields = split /\s+/, $line;
100
+ die "Unexpected nm output for line $line\n"
101
+ if @fields != 3;
102
+ push @external_symbols, $fields[2];
103
+ }
104
+
105
+ return @external_symbols;
106
+ }
@@ -0,0 +1,13 @@
1
+ /t/*
2
+ !/t/*.*
3
+ /t/*.exe
4
+ /t/*.got
5
+ *.a
6
+ *.lo
7
+ *.o
8
+ *.so
9
+ *.pc
10
+ usr/
11
+ *.sw?
12
+ /.deps
13
+ /.dirstamp
@@ -0,0 +1,13 @@
1
+ language: c
2
+
3
+ compiler:
4
+ - gcc
5
+ - clang
6
+
7
+ before_install: sudo apt-get install -y libtest-differences-perl
8
+
9
+ install: make CC=$CC install
10
+
11
+ script: make CC=$CC test
12
+
13
+ after_script: make uninstall
@@ -0,0 +1,165 @@
1
+ GNU LESSER GENERAL PUBLIC LICENSE
2
+ Version 3, 29 June 2007
3
+
4
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
5
+ Everyone is permitted to copy and distribute verbatim copies
6
+ of this license document, but changing it is not allowed.
7
+
8
+
9
+ This version of the GNU Lesser General Public License incorporates
10
+ the terms and conditions of version 3 of the GNU General Public
11
+ License, supplemented by the additional permissions listed below.
12
+
13
+ 0. Additional Definitions.
14
+
15
+ As used herein, "this License" refers to version 3 of the GNU Lesser
16
+ General Public License, and the "GNU GPL" refers to version 3 of the GNU
17
+ General Public License.
18
+
19
+ "The Library" refers to a covered work governed by this License,
20
+ other than an Application or a Combined Work as defined below.
21
+
22
+ An "Application" is any work that makes use of an interface provided
23
+ by the Library, but which is not otherwise based on the Library.
24
+ Defining a subclass of a class defined by the Library is deemed a mode
25
+ of using an interface provided by the Library.
26
+
27
+ A "Combined Work" is a work produced by combining or linking an
28
+ Application with the Library. The particular version of the Library
29
+ with which the Combined Work was made is also called the "Linked
30
+ Version".
31
+
32
+ The "Minimal Corresponding Source" for a Combined Work means the
33
+ Corresponding Source for the Combined Work, excluding any source code
34
+ for portions of the Combined Work that, considered in isolation, are
35
+ based on the Application, and not on the Linked Version.
36
+
37
+ The "Corresponding Application Code" for a Combined Work means the
38
+ object code and/or source code for the Application, including any data
39
+ and utility programs needed for reproducing the Combined Work from the
40
+ Application, but excluding the System Libraries of the Combined Work.
41
+
42
+ 1. Exception to Section 3 of the GNU GPL.
43
+
44
+ You may convey a covered work under sections 3 and 4 of this License
45
+ without being bound by section 3 of the GNU GPL.
46
+
47
+ 2. Conveying Modified Versions.
48
+
49
+ If you modify a copy of the Library, and, in your modifications, a
50
+ facility refers to a function or data to be supplied by an Application
51
+ that uses the facility (other than as an argument passed when the
52
+ facility is invoked), then you may convey a copy of the modified
53
+ version:
54
+
55
+ a) under this License, provided that you make a good faith effort to
56
+ ensure that, in the event an Application does not supply the
57
+ function or data, the facility still operates, and performs
58
+ whatever part of its purpose remains meaningful, or
59
+
60
+ b) under the GNU GPL, with none of the additional permissions of
61
+ this License applicable to that copy.
62
+
63
+ 3. Object Code Incorporating Material from Library Header Files.
64
+
65
+ The object code form of an Application may incorporate material from
66
+ a header file that is part of the Library. You may convey such object
67
+ code under terms of your choice, provided that, if the incorporated
68
+ material is not limited to numerical parameters, data structure
69
+ layouts and accessors, or small macros, inline functions and templates
70
+ (ten or fewer lines in length), you do both of the following:
71
+
72
+ a) Give prominent notice with each copy of the object code that the
73
+ Library is used in it and that the Library and its use are
74
+ covered by this License.
75
+
76
+ b) Accompany the object code with a copy of the GNU GPL and this license
77
+ document.
78
+
79
+ 4. Combined Works.
80
+
81
+ You may convey a Combined Work under terms of your choice that,
82
+ taken together, effectively do not restrict modification of the
83
+ portions of the Library contained in the Combined Work and reverse
84
+ engineering for debugging such modifications, if you also do each of
85
+ the following:
86
+
87
+ a) Give prominent notice with each copy of the Combined Work that
88
+ the Library is used in it and that the Library and its use are
89
+ covered by this License.
90
+
91
+ b) Accompany the Combined Work with a copy of the GNU GPL and this license
92
+ document.
93
+
94
+ c) For a Combined Work that displays copyright notices during
95
+ execution, include the copyright notice for the Library among
96
+ these notices, as well as a reference directing the user to the
97
+ copies of the GNU GPL and this license document.
98
+
99
+ d) Do one of the following:
100
+
101
+ 0) Convey the Minimal Corresponding Source under the terms of this
102
+ License, and the Corresponding Application Code in a form
103
+ suitable for, and under terms that permit, the user to
104
+ recombine or relink the Application with a modified version of
105
+ the Linked Version to produce a modified Combined Work, in the
106
+ manner specified by section 6 of the GNU GPL for conveying
107
+ Corresponding Source.
108
+
109
+ 1) Use a suitable shared library mechanism for linking with the
110
+ Library. A suitable mechanism is one that (a) uses at run time
111
+ a copy of the Library already present on the user's computer
112
+ system, and (b) will operate properly with a modified version
113
+ of the Library that is interface-compatible with the Linked
114
+ Version.
115
+
116
+ e) Provide Installation Information, but only if you would otherwise
117
+ be required to provide such information under section 6 of the
118
+ GNU GPL, and only to the extent that such information is
119
+ necessary to install and execute a modified version of the
120
+ Combined Work produced by recombining or relinking the
121
+ Application with a modified version of the Linked Version. (If
122
+ you use option 4d0, the Installation Information must accompany
123
+ the Minimal Corresponding Source and Corresponding Application
124
+ Code. If you use option 4d1, you must provide the Installation
125
+ Information in the manner specified by section 6 of the GNU GPL
126
+ for conveying Corresponding Source.)
127
+
128
+ 5. Combined Libraries.
129
+
130
+ You may place library facilities that are a work based on the
131
+ Library side by side in a single library together with other library
132
+ facilities that are not Applications and are not covered by this
133
+ License, and convey such a combined library under terms of your
134
+ choice, if you do both of the following:
135
+
136
+ a) Accompany the combined library with a copy of the same work based
137
+ on the Library, uncombined with any other library facilities,
138
+ conveyed under the terms of this License.
139
+
140
+ b) Give prominent notice with the combined library that part of it
141
+ is a work based on the Library, and explaining where to find the
142
+ accompanying uncombined form of the same work.
143
+
144
+ 6. Revised Versions of the GNU Lesser General Public License.
145
+
146
+ The Free Software Foundation may publish revised and/or new versions
147
+ of the GNU Lesser General Public License from time to time. Such new
148
+ versions will be similar in spirit to the present version, but may
149
+ differ in detail to address new problems or concerns.
150
+
151
+ Each version is given a distinguishing version number. If the
152
+ Library as you received it specifies that a certain numbered version
153
+ of the GNU Lesser General Public License "or any later version"
154
+ applies to it, you have the option of following the terms and
155
+ conditions either of that published version or of any later version
156
+ published by the Free Software Foundation. If the Library as you
157
+ received it does not specify a version number of the GNU Lesser
158
+ General Public License, you may choose any version of the GNU Lesser
159
+ General Public License ever published by the Free Software Foundation.
160
+
161
+ If the Library as you received it specifies that a proxy can decide
162
+ whether future versions of the GNU Lesser General Public License shall
163
+ apply, that proxy's public statement of acceptance of any version is
164
+ permanent authorization for you to choose that version for the
165
+ Library.