LCOV - code coverage report
Current view: top level - tests/functional - test_tl_skip_message_functional.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 100.0 % 77 77
Test Date: 2026-04-20 19:54:22 Functions: 100.0 % 4 4

            Line data    Source code
       1              : /**
       2              :  * @file test_tl_skip_message_functional.c
       3              :  * @brief End-to-end iteration of a heavily-decorated Message object.
       4              :  *
       5              :  * The unit tests exercise each skipper in isolation. This functional
       6              :  * test builds one Message carrying every supported trailer flag at
       7              :  * once (media + reply_markup + entities + views + forwards + replies +
       8              :  * restriction_reason + reactions + ttl_period + factcheck), feeds it
       9              :  * to tl_skip_message, and asserts the reader lands exactly on the
      10              :  * bytes that follow. The goal is to catch dispatch-order bugs and
      11              :  * cross-skipper interactions that the per-unit tests cannot see.
      12              :  */
      13              : 
      14              : #include "test_helpers.h"
      15              : #include "tl_serial.h"
      16              : #include "tl_registry.h"
      17              : #include "tl_skip.h"
      18              : 
      19              : #include <stdint.h>
      20              : #include <string.h>
      21              : 
      22              : /* CRCs not re-exposed from tl_skip.c. */
      23              : #define CRC_messageMediaEmpty_t       0x3ded6320u
      24              : #define CRC_replyInlineMarkup_t       0x48a30254u
      25              : #define CRC_keyboardButtonRow_t       0x77608b83u
      26              : #define CRC_keyboardButtonCallback_t  0x35bbdb6bu
      27              : #define CRC_messageEntityBold_t       0xbd610bc9u
      28              : #define CRC_messageReplies_t          0x83d60fc2u
      29              : #define CRC_restrictionReason_t       0xd072acb4u
      30              : #define CRC_messageReactions_t        0x4f2b9479u
      31              : #define CRC_reactionCount_t           0xa3d1cb80u
      32              : #define CRC_reactionEmoji_t           0x1b2286b8u
      33              : #define CRC_factCheck_t               0xb89bfccfu
      34              : #define CRC_textWithEntities_t        0x751f3146u
      35              : 
      36              : /* Message flag constants. */
      37              : #define FLAG_REPLY_MARKUP   (1u <<  6)
      38              : #define FLAG_ENTITIES       (1u <<  7)
      39              : #define FLAG_FROM_ID        (1u <<  8)
      40              : #define FLAG_MEDIA          (1u <<  9)
      41              : #define FLAG_VIEWS_FWDS     (1u << 10)
      42              : #define FLAG_EDIT_DATE      (1u << 15)
      43              : #define FLAG_POST_AUTHOR    (1u << 16)
      44              : #define FLAG_GROUPED_ID     (1u << 17)
      45              : #define FLAG_REACTIONS      (1u << 20)
      46              : #define FLAG_RESTRICTION    (1u << 22)
      47              : #define FLAG_REPLIES        (1u << 23)
      48              : #define FLAG_TTL_PERIOD     (1u << 25)
      49              : #define FLAG2_FACTCHECK     (1u <<  3)
      50              : 
      51            6 : static void write_message_kitchen_sink(TlWriter *w) {
      52            6 :     uint32_t flags = FLAG_FROM_ID | FLAG_MEDIA | FLAG_REPLY_MARKUP
      53              :                    | FLAG_ENTITIES | FLAG_VIEWS_FWDS | FLAG_EDIT_DATE
      54              :                    | FLAG_POST_AUTHOR | FLAG_GROUPED_ID | FLAG_REACTIONS
      55              :                    | FLAG_RESTRICTION | FLAG_REPLIES | FLAG_TTL_PERIOD;
      56            6 :     uint32_t flags2 = FLAG2_FACTCHECK;
      57              : 
      58            6 :     tl_write_uint32(w, TL_message);
      59            6 :     tl_write_uint32(w, flags);
      60            6 :     tl_write_uint32(w, flags2);
      61            6 :     tl_write_int32 (w, 1001);                 /* message id */
      62              : 
      63              :     /* from_id:Peer + peer_id:Peer */
      64            6 :     tl_write_uint32(w, TL_peerUser); tl_write_int64(w, 42LL);
      65            6 :     tl_write_uint32(w, TL_peerChannel); tl_write_int64(w, 5001LL);
      66              : 
      67            6 :     tl_write_int32 (w, 1700000000);           /* date */
      68            6 :     tl_write_string(w, "Kitchen-sink post");  /* message */
      69              : 
      70              :     /* media: messageMediaEmpty */
      71            6 :     tl_write_uint32(w, CRC_messageMediaEmpty_t);
      72              : 
      73              :     /* reply_markup: replyInlineMarkup + one row with a callback button. */
      74            6 :     tl_write_uint32(w, CRC_replyInlineMarkup_t);
      75            6 :     tl_write_uint32(w, TL_vector); tl_write_uint32(w, 1);
      76            6 :     tl_write_uint32(w, CRC_keyboardButtonRow_t);
      77            6 :     tl_write_uint32(w, TL_vector); tl_write_uint32(w, 1);
      78            6 :     tl_write_uint32(w, CRC_keyboardButtonCallback_t);
      79            6 :     tl_write_uint32(w, 0);                    /* inner flags */
      80            6 :     tl_write_string(w, "Click me");
      81            6 :     tl_write_string(w, "payload");
      82              : 
      83              :     /* entities: one bold */
      84            6 :     tl_write_uint32(w, TL_vector); tl_write_uint32(w, 1);
      85            6 :     tl_write_uint32(w, CRC_messageEntityBold_t);
      86            6 :     tl_write_int32 (w, 0); tl_write_int32(w, 7);
      87              : 
      88              :     /* views + forwards */
      89            6 :     tl_write_int32 (w, 12345);
      90            6 :     tl_write_int32 (w, 67);
      91              : 
      92              :     /* replies: messageReplies flags=0, two int32 */
      93            6 :     tl_write_uint32(w, CRC_messageReplies_t);
      94            6 :     tl_write_uint32(w, 0);
      95            6 :     tl_write_int32 (w, 9);
      96            6 :     tl_write_int32 (w, 200);
      97              : 
      98              :     /* edit_date */
      99            6 :     tl_write_int32 (w, 1700001111);
     100              : 
     101              :     /* post_author */
     102            6 :     tl_write_string(w, "Anonymous");
     103              : 
     104              :     /* grouped_id */
     105            6 :     tl_write_int64 (w, 0xDEADBEEFLL);
     106              : 
     107              :     /* reactions: one emoji reaction with 3 voters */
     108            6 :     tl_write_uint32(w, CRC_messageReactions_t);
     109            6 :     tl_write_uint32(w, 0);
     110            6 :     tl_write_uint32(w, TL_vector); tl_write_uint32(w, 1);
     111            6 :     tl_write_uint32(w, CRC_reactionCount_t);
     112            6 :     tl_write_uint32(w, 0);                    /* no chosen_order */
     113            6 :     tl_write_uint32(w, CRC_reactionEmoji_t);
     114            6 :     tl_write_string(w, "\xf0\x9f\x94\xa5"); /* 🔥 */
     115            6 :     tl_write_int32 (w, 3);
     116              : 
     117              :     /* restriction_reason: Vector<RestrictionReason>, one entry */
     118            6 :     tl_write_uint32(w, TL_vector); tl_write_uint32(w, 1);
     119            6 :     tl_write_uint32(w, CRC_restrictionReason_t);
     120            6 :     tl_write_string(w, "android");
     121            6 :     tl_write_string(w, "sensitive");
     122            6 :     tl_write_string(w, "Age-restricted");
     123              : 
     124              :     /* ttl_period */
     125            6 :     tl_write_int32 (w, 3600);
     126              : 
     127              :     /* factcheck: flags.1 with country + TextWithEntities, hash */
     128            6 :     tl_write_uint32(w, CRC_factCheck_t);
     129            6 :     tl_write_uint32(w, (1u << 1));
     130            6 :     tl_write_string(w, "HU");
     131            6 :     tl_write_uint32(w, CRC_textWithEntities_t);
     132            6 :     tl_write_string(w, "verified claim");
     133            6 :     tl_write_uint32(w, TL_vector); tl_write_uint32(w, 0);
     134            6 :     tl_write_int64 (w, 0xABCDEF0012345678LL);
     135            6 : }
     136              : 
     137            2 : static void test_kitchen_sink_message_iterates_fully(void) {
     138            2 :     TlWriter w; tl_writer_init(&w);
     139            2 :     write_message_kitchen_sink(&w);
     140            2 :     tl_write_int32(&w, 0x0BAD1DEA);           /* sentinel trailer */
     141              : 
     142            2 :     TlReader r = tl_reader_init(w.data, w.len);
     143            2 :     ASSERT(tl_skip_message(&r) == 0,
     144              :            "multi-flag Message skipped cleanly");
     145            2 :     ASSERT(tl_read_int32(&r) == 0x0BAD1DEA,
     146              :            "cursor landed exactly on sentinel after Message");
     147            2 :     ASSERT(r.pos == r.len, "reader fully consumed");
     148            2 :     tl_writer_free(&w);
     149              : }
     150              : 
     151              : /* Two Messages in sequence: prove that hitting any trailer does not
     152              :  * desynchronise the reader for the next one. */
     153            2 : static void test_two_messages_in_a_row(void) {
     154            2 :     TlWriter w; tl_writer_init(&w);
     155            2 :     write_message_kitchen_sink(&w);
     156            2 :     write_message_kitchen_sink(&w);
     157            2 :     tl_write_int32(&w, 0xCAFEBABE);
     158              : 
     159            2 :     TlReader r = tl_reader_init(w.data, w.len);
     160            2 :     ASSERT(tl_skip_message(&r) == 0, "first Message skipped");
     161            2 :     ASSERT(tl_skip_message(&r) == 0, "second Message skipped");
     162            2 :     ASSERT(tl_read_int32(&r) == (int32_t)0xCAFEBABE, "trailer reached");
     163            2 :     tl_writer_free(&w);
     164              : }
     165              : 
     166            2 : void run_tl_skip_message_functional_tests(void) {
     167            2 :     RUN_TEST(test_kitchen_sink_message_iterates_fully);
     168            2 :     RUN_TEST(test_two_messages_in_a_row);
     169            2 : }
        

Generated by: LCOV version 2.0-1