EncodingScheme_test.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. /* vim: set expandtab ts=4 sw=4: */
  2. /*
  3. * You may redistribute this program and/or modify it under the terms of
  4. * the GNU General Public License as published by the Free Software Foundation,
  5. * either version 3 of the License, or (at your option) any later version.
  6. *
  7. * This program is distributed in the hope that it will be useful,
  8. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. * GNU General Public License for more details.
  11. *
  12. * You should have received a copy of the GNU General Public License
  13. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  14. */
  15. #include "benc/String.h"
  16. #include "crypto/random/Random.h"
  17. #include "switch/EncodingScheme.h"
  18. #include "memory/Allocator.h"
  19. #include "memory/MallocAllocator.h"
  20. #include "util/Bits.h"
  21. #define Order_TYPE struct EncodingScheme_Form
  22. #define Order_NAME OfEncodingForms
  23. #define Order_COMPARE compareEncodingForms
  24. #include "util/Order.h"
  25. static inline int compareEncodingForms(const struct EncodingScheme_Form* a,
  26. const struct EncodingScheme_Form* b)
  27. {
  28. int diff = a->bitCount;
  29. diff -= b->bitCount;
  30. return diff == 0 ? 0 : diff > 0 ? 1 : -1;
  31. }
  32. static void randomForm(struct EncodingScheme_Form* form, struct Random* rand)
  33. {
  34. for (;;) {
  35. Random_bytes(rand, (uint8_t*)form, sizeof(struct EncodingScheme_Form));
  36. //Bits_memset(form, 0xff, sizeof(struct EncodingScheme_Form));
  37. form->bitCount &= ((1<<5)-1);
  38. if (!form->bitCount) {
  39. form->bitCount++;
  40. }
  41. form->prefixLen &= ((1<<5)-1);
  42. if (!form->prefixLen) {
  43. form->prefixLen++;
  44. }
  45. if (EncodingScheme_formSize(form) > 59) { continue; }
  46. if (form->prefixLen > 3 && (form->prefix & 0xf) == 1) { continue; }
  47. break;
  48. }
  49. form->prefix &= ((((uint64_t)1)<<form->prefixLen)-1);
  50. }
  51. static struct EncodingScheme* randomScheme(struct Random* rand, struct Allocator* alloc)
  52. {
  53. struct EncodingScheme* out =
  54. Allocator_malloc(alloc, sizeof(struct EncodingScheme));
  55. do {
  56. out->count = Random_uint32(rand) % 32;
  57. } while (out->count < 2);
  58. out->forms = Allocator_malloc(alloc, sizeof(struct EncodingScheme_Form) * out->count);
  59. for (int i = 0; i < (int)out->count; i++) {
  60. randomForm(&out->forms[i], rand);
  61. for (int j = 0; j < i; j++) {
  62. if (out->forms[i].bitCount == out->forms[j].bitCount) {
  63. i--;
  64. break;
  65. }
  66. int minPfx = (out->forms[i].prefixLen < out->forms[j].prefixLen)
  67. ? out->forms[i].prefixLen : out->forms[j].prefixLen;
  68. if (((out->forms[j].prefix ^ out->forms[i].prefix) & ((1<<minPfx)-1)) == 0) {
  69. // collision, destroy both entries and try again.
  70. if (j != i-1) {
  71. Bits_memcpyConst(&out->forms[j],
  72. &out->forms[i-1],
  73. sizeof(struct EncodingScheme_Form));
  74. }
  75. i -= 2;
  76. break;
  77. }
  78. }
  79. }
  80. Order_OfEncodingForms_qsort(out->forms, out->count);
  81. return out;
  82. }
  83. static void assertEqual(struct EncodingScheme* a,
  84. struct EncodingScheme* b)
  85. {
  86. Assert_always(b);
  87. Assert_always(a->count == b->count);
  88. Assert_always(
  89. !Bits_memcmp(a->forms, b->forms, sizeof(struct EncodingScheme_Form) * a->count));
  90. }
  91. static void randomTest(struct Allocator* parent, struct Random* rand)
  92. {
  93. struct Allocator* alloc = Allocator_child(parent);
  94. struct EncodingScheme* control = randomScheme(rand, alloc);
  95. String* data = EncodingScheme_serialize(control, alloc);
  96. struct EncodingScheme* test = EncodingScheme_deserialize(data, alloc);
  97. assertEqual(control, test);
  98. Allocator_free(alloc);
  99. }
  100. // Just make sure random crap doesn't crash it.
  101. static void fuzzTest(struct Allocator* parent, struct Random* rand)
  102. {
  103. struct Allocator* alloc = Allocator_child(parent);
  104. String* data = String_newBinary(NULL, Random_uint32(rand) % 1024, alloc);
  105. Random_bytes(rand, (uint8_t*)data->bytes, data->len);
  106. EncodingScheme_deserialize(data, alloc);
  107. Allocator_free(alloc);
  108. }
  109. /** Greatest possible number using x bits, all are set. */
  110. #define Bits_maxBits64(x) ((((uint64_t)1)<<(x))-1)
  111. static void encoding(struct Allocator* parent)
  112. {
  113. struct EncodingScheme_Form forms[3] = {
  114. {
  115. .prefixLen = 15,
  116. .bitCount = 2,
  117. .prefix = ((1<<15)-1) ^ (1<<1),
  118. }, {
  119. .prefixLen = 20,
  120. .bitCount = 4,
  121. .prefix = ((1<<20)-1) ^ (1<<2),
  122. }, {
  123. .prefixLen = 18,
  124. .bitCount = 8,
  125. .prefix = ((1<<18)-1) ^ (1<<3),
  126. }
  127. };
  128. // should encode as prefixLen, bitCount, prefix
  129. // 111111111111101 00010 01111 15/2/~0 -> 01001111 11110100 11111111 remainder 1
  130. // 11111111111111111011 00100 10100 20/4/~0 -> 00101001 11011001 11111111 remainder 7f
  131. // 111111111111110111 01000 10010 18/8/~0 -> 01111111 10001001 11101110 11111111 remainder 7
  132. // 00000111 <-- appliation of remainder
  133. //
  134. // In bytes:
  135. // 01001111 11110100 11111111 00101001 11011001 11111111
  136. // 01111111 10001001 11101110 11111111 00000111
  137. //
  138. // or \x4f\xf4\xff\x29\xd9\xff\x7f\x89\xee\xff\x07
  139. struct EncodingScheme list = {
  140. .count = 3,
  141. .forms = forms
  142. };
  143. struct Allocator* alloc = Allocator_child(parent);
  144. String* data = EncodingScheme_serialize(&list, alloc);
  145. Assert_always(data->len == 11);
  146. Assert_always(!Bits_memcmp(data->bytes, "\x4f\xf4\xff\x29\xd9\xff\x7f\x89\xee\xff\x07", 11));
  147. Allocator_free(alloc);
  148. }
  149. #define convertLabel_SELF_ROUTE 1
  150. #define convertLabel_TOO_BIG 2
  151. static int convertLabel(struct EncodingScheme_Form* iform,
  152. struct EncodingScheme_Form* oform,
  153. uint64_t label)
  154. {
  155. struct {
  156. struct EncodingScheme scheme;
  157. struct EncodingScheme_Form forms[2];
  158. } s;
  159. s.scheme.count = 2;
  160. s.scheme.forms = s.forms;
  161. Bits_memcpyConst(&s.forms[0], iform, sizeof(struct EncodingScheme_Form));
  162. Bits_memcpyConst(&s.forms[1], oform, sizeof(struct EncodingScheme_Form));
  163. int iformNum = 0;
  164. int oformNum = 1;
  165. struct EncodingScheme* scheme = &s.scheme;
  166. Assert_always(EncodingScheme_getFormNum(scheme, label) == iformNum);
  167. uint64_t label2 = EncodingScheme_convertLabel(scheme, label, oformNum);
  168. if ((label & Bits_maxBits64(s.forms[0].prefixLen + s.forms[0].bitCount)) == 1) {
  169. Assert_always(label2 == EncodingScheme_convertLabel_INVALID);
  170. return convertLabel_SELF_ROUTE;
  171. }
  172. if (Bits_log2x64(label) + EncodingScheme_formSize(oform) -
  173. EncodingScheme_formSize(iform) > 59)
  174. {
  175. Assert_always(label2 == EncodingScheme_convertLabel_INVALID);
  176. return convertLabel_TOO_BIG;
  177. }
  178. uint64_t additional = label >> s.forms[0].prefixLen;
  179. uint64_t director = additional & Bits_maxBits64(s.forms[0].bitCount);
  180. additional = additional >> s.forms[0].bitCount;
  181. // Conversions are necessary for two reasons.
  182. // #1 ensure 0001 always references interface 1, the self interface.
  183. // #2 reuse interface the binary encoding for interface 1 in other EncodingForms
  184. // because interface 1 cannot be expressed as anything other than 0001
  185. if ((s.forms[0].prefix & Bits_maxBits64(s.forms[0].prefixLen)) == 1) {
  186. // Swap 0 and 1 because zero is represented as 1 and 1 is handled specially
  187. if (director == 1) { director--; }
  188. } else if (director) {
  189. // Reuse the number 1 for 2 and 2 for 3 etc. to gain an extra slot in all other encodings.
  190. director++;
  191. }
  192. if ((s.forms[1].prefix & Bits_maxBits64(s.forms[1].prefixLen)) == 1) {
  193. // Swap 1 and 0 back if necessary.
  194. if (director == 0) { director++; }
  195. } else if (director) {
  196. // Or move the numbers down by one.
  197. director--;
  198. }
  199. uint64_t converted = (additional << s.forms[1].bitCount) | director;
  200. converted = (converted << s.forms[1].prefixLen) | s.forms[1].prefix;
  201. if ((converted & Bits_maxBits64(s.forms[1].prefixLen + s.forms[1].bitCount)) == 1) {
  202. // looks like a self-route
  203. Assert_always(label2 == EncodingScheme_convertLabel_INVALID);
  204. return convertLabel_SELF_ROUTE;
  205. }
  206. Assert_always(label2 == converted);
  207. uint64_t label3 = EncodingScheme_convertLabel(scheme, label2, iformNum);
  208. Assert_always(label3 == label);
  209. return 0;
  210. }
  211. static void convertLabelRand(struct Random* rand, struct EncodingScheme* scheme)
  212. {
  213. for (int i = 0; i < 100; i++) {
  214. int oformNum;
  215. do {
  216. oformNum = Random_uint8(rand) % scheme->count;
  217. } while (!oformNum);
  218. int iformNum = Random_uint8(rand) % oformNum;
  219. uint64_t label = Random_uint64(rand);
  220. label &= (UINT64_MAX >> (Random_uint8(rand) % 63));
  221. for (;;) {
  222. // make sure the label has the right prefix
  223. label <<= scheme->forms[iformNum].prefixLen;
  224. label |= scheme->forms[iformNum].prefix;
  225. Assert_always(EncodingScheme_getFormNum(scheme, label) == iformNum);
  226. if (Bits_log2x64(label) > 59) {
  227. // fall through
  228. } else {
  229. int ret = convertLabel(&scheme->forms[iformNum], &scheme->forms[oformNum], label);
  230. if (ret == convertLabel_SELF_ROUTE) {
  231. i--;
  232. break;
  233. } else if (ret == convertLabel_TOO_BIG) {
  234. // fall through
  235. } else if (!ret) {
  236. // success
  237. break;
  238. } else {
  239. Assert_always(0);
  240. }
  241. }
  242. label >>= scheme->forms[iformNum].prefixLen + 1;
  243. }
  244. }
  245. }
  246. int main()
  247. {
  248. struct Allocator* alloc = MallocAllocator_new(20000000);
  249. struct Random* rand = Random_new(alloc, NULL, NULL);
  250. encoding(alloc);
  251. for (int i = 0; i < 1000; i++) {
  252. randomTest(alloc, rand);
  253. }
  254. for (int i = 0; i < 1000; i++) {
  255. fuzzTest(alloc, rand);
  256. }
  257. // for testing individual conversions in isolation.
  258. /*convertLabel(
  259. &(struct EncodingScheme_Form){.bitCount = 15, .prefixLen = 20, .prefix = 792003},
  260. &(struct EncodingScheme_Form){.bitCount = 31, .prefixLen = 30, .prefix = 385462496},
  261. 11331704259
  262. );*/
  263. for (int i = 0; i < 10; i++) {
  264. struct Allocator* tempAlloc = Allocator_child(alloc);
  265. struct EncodingScheme* scheme = randomScheme(rand, tempAlloc);
  266. convertLabelRand(rand, scheme);
  267. Allocator_free(tempAlloc);
  268. }
  269. return 0;
  270. }