LinkState_test.c 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  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 <https://www.gnu.org/licenses/>.
  14. */
  15. #include "crypto/random/Random.h"
  16. #include "exception/Err.h"
  17. #include "memory/Allocator.h"
  18. #include "subnode/LinkState.h"
  19. #include "util/Assert.h"
  20. #include "wire/Message.h"
  21. #define CYCLES 10
  22. static uint64_t randVarInt(struct Random* rand)
  23. {
  24. uint64_t val = Random_uint64(rand);
  25. if ((val & 0xff) < 192) {
  26. return (val >> 8) & 0xff;
  27. }
  28. if ((val & 0xff) < 224) {
  29. return (val >> 8) & 0xffff;
  30. }
  31. if ((val & 0xff) < 240) {
  32. return (val >> 8) & 0xffffffff;
  33. }
  34. return Random_uint64(rand);
  35. }
  36. static void randomLs(struct Random* rand, struct LinkState* ls, bool total)
  37. {
  38. if (total) {
  39. ls->samples = Random_uint32(rand);
  40. ls->nodeId = Random_uint16(rand);
  41. }
  42. for (int i = 0; i < LinkState_SLOTS; i++) {
  43. ls->lagSlots[i] = Random_uint16(rand); //randVarInt(rand);
  44. ls->dropSlots[i] = Random_uint16(rand); // randVarInt(rand);
  45. ls->kbRecvSlots[i] = Random_uint32(rand); //randVarInt(rand);
  46. }
  47. }
  48. static void randomLsUpdate(struct Random* rand, struct LinkState* ls)
  49. {
  50. uint8_t toUpdate = Random_uint8(rand) % 20;
  51. if (!toUpdate) { return; }
  52. //printf(">>%d\n", toUpdate);
  53. int samplesNext = ls->samples;
  54. if (toUpdate >= LinkState_SLOTS) {
  55. samplesNext += LinkState_SLOTS;
  56. randomLs(rand, ls, false);
  57. } else {
  58. samplesNext += toUpdate;
  59. int i = ls->samples % LinkState_SLOTS;
  60. do {
  61. ls->lagSlots[i] = randVarInt(rand);
  62. ls->dropSlots[i] = randVarInt(rand);
  63. ls->kbRecvSlots[i] = randVarInt(rand);
  64. i = (i + 1) % LinkState_SLOTS;
  65. } while (i != samplesNext % LinkState_SLOTS);
  66. }
  67. Assert_true(samplesNext - ls->samples <= LinkState_SLOTS);
  68. ls->samples = samplesNext;
  69. }
  70. static void applyStateUpdates(struct LinkState* local, Message_t* msg)
  71. {
  72. if (!Message_getLength(msg)) { return; }
  73. uint8_t length = Message_bytes(msg)[0];
  74. struct VarInt_Iter it;
  75. Assert_true(!LinkState_mkDecoder(msg, &it));
  76. uint32_t id = 0;
  77. Assert_true(!LinkState_getNodeId(&it, &id));
  78. Assert_true(id == local->nodeId);
  79. Err_assert(Message_eshift(msg, -length));
  80. applyStateUpdates(local, msg);
  81. Assert_true(!LinkState_decode(&it, local));
  82. }
  83. static void assertSame(struct LinkState* beforeState,
  84. struct LinkState* updated,
  85. Message_t* update)
  86. {
  87. struct LinkState local;
  88. Bits_memcpy(&local, beforeState, sizeof(struct LinkState));
  89. //printf("%02x %02x\n", local.nodeId, local.samples);
  90. applyStateUpdates(&local, update);
  91. #if 0
  92. printf("%02x %02x\n", updated->nodeId, updated->samples);
  93. printf("%02x %02x\n", local.nodeId, local.samples);
  94. for (int i = 0; i < LinkState_SLOTS; i++) {
  95. printf("%02x %02x %02x\n",
  96. updated->lagSlots[i], updated->dropSlots[i], updated->kbRecvSlots[i]);
  97. printf("%02x %02x %02x\n\n",
  98. local.lagSlots[i], local.dropSlots[i], local.kbRecvSlots[i]);
  99. }
  100. printf("\n");
  101. #endif
  102. Assert_true(!Bits_memcmp(&local, updated, sizeof(struct LinkState)));
  103. }
  104. static void testStatic(Allocator_t* alloc)
  105. {
  106. uint8_t* hex =
  107. "\x20\x03\x06\x00\x00\x00\x00\x00\x00"
  108. "\x04" "\x10"
  109. "\x13\x00\x01"
  110. "\x12\x00\x02"
  111. "\x13\x00\x02"
  112. "\x13\x00\x00"
  113. "\x14\x00\x03"
  114. "\x12\x00\x01"
  115. "\x13\x00\x01";
  116. struct LinkState ls = { .nodeId = 0 };
  117. struct VarInt_Iter it = { .start = 0 };
  118. Message_t* msg = Message_new(0, 512, alloc);
  119. Err_assert(Message_epush(msg, hex, 32));
  120. Assert_true(!LinkState_mkDecoder(msg, &it));
  121. Assert_true(!LinkState_decode(&it, &ls));
  122. // printf("%u %u\n", ls.nodeId, ls.samples);
  123. // for (int i = 0; i < LinkState_SLOTS; i++) {
  124. // printf("%u %u %u\n", ls.lagSlots[i], ls.dropSlots[i], ls.kbRecvSlots[i]);
  125. // }
  126. struct LinkState gold = {
  127. .nodeId = 4,
  128. .samples = 7,
  129. .lagSlots = { 19, 19, 20, 18, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 18 },
  130. .dropSlots = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
  131. .kbRecvSlots = { 2, 0, 3, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2 },
  132. };
  133. Assert_true(!Bits_memcmp(&ls, &gold, sizeof(struct LinkState)));
  134. }
  135. int main(int argc, char* argv[])
  136. {
  137. struct Allocator* mainAlloc = Allocator_new(1<<18);
  138. testStatic(mainAlloc);
  139. struct Random* rand = NULL;
  140. Err_assert(Random_new(&rand, mainAlloc, NULL));
  141. int cycles = CYCLES;
  142. Message_t* msg = Message_new(0, 2048, mainAlloc);
  143. for (int cycle = 0; cycle < cycles; cycle++) {
  144. uint16_t nodeId = Random_uint16(rand);
  145. struct LinkState ls0 = { .nodeId = nodeId };
  146. struct LinkState ls = { .nodeId = nodeId, .samples = LinkState_SLOTS };
  147. randomLs(rand, &ls, false);
  148. Assert_true(!Message_getLength(msg));
  149. Assert_true(!LinkState_encode(msg, &ls, 0));
  150. assertSame(&ls0, &ls, msg);
  151. for (int cc = 0; cc < 100; cc++) {
  152. Bits_memcpy(&ls0, &ls, sizeof(struct LinkState));
  153. randomLsUpdate(rand, &ls);
  154. Assert_true(!LinkState_encode(msg, &ls, ls0.samples));
  155. //printf("L>%d\n", Message_getLength(msg));
  156. //for (int i = 0; i < Message_getLength(msg); i++) { printf("%02x", msg->bytes[i]); }
  157. //printf("\n");
  158. assertSame(&ls0, &ls, msg);
  159. }
  160. //printf("Test %d\n", Message_getLength(msg));
  161. //for (int i = 0; i < Message_getLength(msg); i++) { printf("%02x", msg->bytes[i]); }
  162. //printf("\n");
  163. }
  164. Allocator_free(mainAlloc);
  165. return 0;
  166. }