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

            Line data    Source code
       1              : /**
       2              :  * @file test_phase2.c
       3              :  * @brief Unit tests for Phase 2 modules (socket mock, transport, session).
       4              :  */
       5              : 
       6              : #include "test_helpers.h"
       7              : #include "platform/socket.h"
       8              : #include "mock_socket.h"
       9              : #include "transport.h"
      10              : #include "mtproto_session.h"
      11              : #include "mock_crypto.h"
      12              : 
      13              : #include <stdlib.h>
      14              : #include <string.h>
      15              : 
      16              : /* ---- Socket mock tests ---- */
      17              : 
      18            1 : void test_mock_socket_create(void) {
      19            1 :     mock_socket_reset();
      20            1 :     int fd = sys_socket_create();
      21            1 :     ASSERT(fd == 42, "mock socket_create should return 42");
      22            1 :     ASSERT(mock_socket_was_created() == 1, "create count should be 1");
      23              : }
      24              : 
      25            1 : void test_mock_socket_connect(void) {
      26            1 :     mock_socket_reset();
      27            1 :     sys_socket_create();
      28            1 :     int rc = sys_socket_connect(42, "149.154.175.50", 443);
      29            1 :     ASSERT(rc == 0, "mock connect should succeed");
      30            1 :     ASSERT(mock_socket_was_connected() == 1, "connect count should be 1");
      31              : }
      32              : 
      33            1 : void test_mock_socket_send_recv(void) {
      34            1 :     mock_socket_reset();
      35            1 :     sys_socket_create();
      36            1 :     sys_socket_connect(42, "localhost", 443);
      37              : 
      38              :     /* Send data */
      39            1 :     const char *msg = "hello";
      40            1 :     ssize_t sent = sys_socket_send(42, msg, 5);
      41            1 :     ASSERT(sent == 5, "send should return 5");
      42              : 
      43              :     /* Verify sent data */
      44            1 :     size_t sent_len = 0;
      45            1 :     const uint8_t *sent_data = mock_socket_get_sent(&sent_len);
      46            1 :     ASSERT(sent_len == 5, "sent_len should be 5");
      47            1 :     ASSERT(memcmp(sent_data, "hello", 5) == 0, "sent data should match");
      48              : 
      49              :     /* Set response and recv */
      50            1 :     mock_socket_set_response((const uint8_t *)"world", 5);
      51              :     uint8_t buf[16];
      52            1 :     ssize_t recvd = sys_socket_recv(42, buf, 16);
      53            1 :     ASSERT(recvd == 5, "recv should return 5");
      54            1 :     ASSERT(memcmp(buf, "world", 5) == 0, "recv data should match");
      55              : }
      56              : 
      57            1 : void test_mock_socket_close(void) {
      58            1 :     mock_socket_reset();
      59            1 :     sys_socket_create();
      60            1 :     sys_socket_close(42);
      61            1 :     ASSERT(mock_socket_was_closed() == 1, "close count should be 1");
      62              : }
      63              : 
      64              : /* ---- Transport error-path tests ---- */
      65              : 
      66            1 : void test_transport_connect_socket_create_fails(void) {
      67            1 :     mock_socket_reset();
      68            1 :     mock_socket_fail_create();
      69              :     Transport t;
      70            1 :     transport_init(&t);
      71            1 :     int rc = transport_connect(&t, "host", 443);
      72            1 :     ASSERT(rc == -1, "connect should fail when socket create fails");
      73            1 :     ASSERT(t.fd == -1, "fd should stay -1");
      74            1 :     ASSERT(t.connected == 0, "should not be connected");
      75              : }
      76              : 
      77            1 : void test_transport_connect_socket_connect_fails(void) {
      78            1 :     mock_socket_reset();
      79            1 :     mock_socket_fail_connect();
      80              :     Transport t;
      81            1 :     transport_init(&t);
      82            1 :     int rc = transport_connect(&t, "host", 443);
      83            1 :     ASSERT(rc == -1, "connect should fail when connect() fails");
      84            1 :     ASSERT(t.fd == -1, "fd should be reset to -1 after failure");
      85            1 :     ASSERT(mock_socket_was_closed() == 1, "socket should be closed on failure");
      86              : }
      87              : 
      88            1 : void test_transport_connect_marker_send_fails(void) {
      89            1 :     mock_socket_reset();
      90            1 :     mock_socket_fail_send_at(1); /* abridged marker */
      91              :     Transport t;
      92            1 :     transport_init(&t);
      93            1 :     int rc = transport_connect(&t, "host", 443);
      94            1 :     ASSERT(rc == -1, "connect should fail when marker send fails");
      95            1 :     ASSERT(t.fd == -1, "fd should be reset");
      96            1 :     ASSERT(t.connected == 0, "should not be connected");
      97              : }
      98              : 
      99            1 : void test_transport_connect_null_args(void) {
     100              :     Transport t;
     101            1 :     transport_init(&t);
     102            1 :     ASSERT(transport_connect(NULL, "host", 443) == -1, "null transport");
     103            1 :     ASSERT(transport_connect(&t, NULL, 443) == -1, "null host");
     104              : }
     105              : 
     106            1 : void test_transport_send_bad_args(void) {
     107              :     Transport t;
     108            1 :     transport_init(&t);
     109            1 :     uint8_t data[4] = {0};
     110            1 :     ASSERT(transport_send(NULL, data, 4) == -1, "null transport");
     111            1 :     ASSERT(transport_send(&t, NULL, 4) == -1, "null data");
     112            1 :     ASSERT(transport_send(&t, data, 0) == -1, "zero len");
     113              :     /* fd < 0 path */
     114            1 :     ASSERT(transport_send(&t, data, 4) == -1, "fd < 0");
     115              : }
     116              : 
     117            1 : void test_transport_send_unaligned_len(void) {
     118              :     /* QA-14: MTProto Abridged requires 4-byte aligned payloads. Any len
     119              :      * that isn't a multiple of 4 must be rejected with -1 rather than
     120              :      * silently truncating via the length prefix division. */
     121            1 :     mock_socket_reset();
     122              :     Transport t;
     123            1 :     transport_init(&t);
     124            1 :     transport_connect(&t, "host", 443);
     125            1 :     uint8_t data[16] = {0};
     126            1 :     ASSERT(transport_send(&t, data, 5) == -1, "len=5 not 4-byte aligned");
     127            1 :     ASSERT(transport_send(&t, data, 7) == -1, "len=7 not 4-byte aligned");
     128            1 :     ASSERT(transport_send(&t, data, 13) == -1, "len=13 not 4-byte aligned");
     129            1 :     transport_close(&t);
     130              : }
     131              : 
     132            1 : void test_transport_send_prefix_fails(void) {
     133            1 :     mock_socket_reset();
     134              :     Transport t;
     135            1 :     transport_init(&t);
     136            1 :     transport_connect(&t, "host", 443);
     137              :     /* After connect: send_call_n==1 used for marker. Next send (prefix) fails. */
     138            1 :     mock_socket_fail_send_at(2);
     139            1 :     uint8_t data[8] = {1,2,3,4,5,6,7,8};
     140            1 :     int rc = transport_send(&t, data, 8);
     141            1 :     ASSERT(rc == -1, "send should fail on prefix send failure");
     142            1 :     transport_close(&t);
     143              : }
     144              : 
     145            1 : void test_transport_send_extended_prefix(void) {
     146            1 :     mock_socket_reset();
     147              :     Transport t;
     148            1 :     transport_init(&t);
     149            1 :     transport_connect(&t, "host", 443);
     150            1 :     mock_socket_clear_sent();
     151              : 
     152              :     /* Need wire_len >= 0x7F → len >= 0x7F*4 = 508 bytes */
     153              :     uint8_t big[512];
     154          513 :     for (int i = 0; i < 512; i++) big[i] = (uint8_t)i;
     155            1 :     int rc = transport_send(&t, big, 512);
     156            1 :     ASSERT(rc == 0, "extended prefix send should succeed");
     157              : 
     158            1 :     size_t sent_len = 0;
     159            1 :     const uint8_t *sent = mock_socket_get_sent(&sent_len);
     160              :     /* QA-15: extended prefix is 4 bytes (0x7F + LE24). */
     161            1 :     ASSERT(sent_len == 4 + 512, "should send 4-byte prefix + 512 payload");
     162            1 :     ASSERT(sent[0] == 0x7F, "extended prefix marker");
     163              :     /* wire_len = 512/4 = 128 = 0x80 */
     164            1 :     ASSERT(sent[1] == 0x80, "low byte of wire_len");
     165            1 :     ASSERT(sent[2] == 0x00, "middle byte of wire_len");
     166            1 :     ASSERT(sent[3] == 0x00, "high byte of wire_len");
     167            1 :     transport_close(&t);
     168              : }
     169              : 
     170              : /* QA-15: payload > 0xFFFF * 4 bytes must round-trip the 3rd length byte. */
     171            1 : void test_transport_send_extended_prefix_wide(void) {
     172            1 :     mock_socket_reset();
     173              :     Transport t;
     174            1 :     transport_init(&t);
     175            1 :     transport_connect(&t, "host", 443);
     176            1 :     mock_socket_clear_sent();
     177              : 
     178              :     /* wire_len = 0x010000 → payload = 0x040000 bytes = 262144 bytes. */
     179            1 :     const size_t payload_len = 0x040000;
     180            1 :     uint8_t *big = (uint8_t *)calloc(payload_len, 1);
     181            1 :     ASSERT(big != NULL, "allocation ok");
     182            1 :     int rc = transport_send(&t, big, payload_len);
     183            1 :     ASSERT(rc == 0, "wide extended prefix send ok");
     184              : 
     185            1 :     size_t sent_len = 0;
     186            1 :     const uint8_t *sent = mock_socket_get_sent(&sent_len);
     187            1 :     ASSERT(sent_len == 4 + payload_len, "4-byte prefix + payload");
     188            1 :     ASSERT(sent[0] == 0x7F, "marker");
     189            1 :     ASSERT(sent[1] == 0x00, "LE[0]");
     190            1 :     ASSERT(sent[2] == 0x00, "LE[1]");
     191            1 :     ASSERT(sent[3] == 0x01, "LE[2] carries the 17th bit");
     192              : 
     193            1 :     free(big);
     194            1 :     transport_close(&t);
     195              : }
     196              : 
     197            1 : void test_transport_send_extended_prefix_send_fails(void) {
     198            1 :     mock_socket_reset();
     199              :     Transport t;
     200            1 :     transport_init(&t);
     201            1 :     transport_connect(&t, "host", 443);
     202            1 :     mock_socket_fail_send_at(2); /* prefix send */
     203            1 :     uint8_t big[512] = {0};
     204            1 :     int rc = transport_send(&t, big, 512);
     205            1 :     ASSERT(rc == -1, "extended prefix failure must propagate");
     206            1 :     transport_close(&t);
     207              : }
     208              : 
     209            1 : void test_transport_send_payload_send_fails(void) {
     210            1 :     mock_socket_reset();
     211              :     Transport t;
     212            1 :     transport_init(&t);
     213            1 :     transport_connect(&t, "host", 443);
     214              :     /* send_call_n: 1 marker, 2 prefix, 3 payload */
     215            1 :     mock_socket_fail_send_at(3);
     216            1 :     uint8_t data[16] = {0};
     217            1 :     int rc = transport_send(&t, data, 16);
     218            1 :     ASSERT(rc == -1, "payload send failure must propagate");
     219            1 :     transport_close(&t);
     220              : }
     221              : 
     222            1 : void test_transport_recv_bad_args(void) {
     223              :     Transport t;
     224            1 :     transport_init(&t);
     225              :     uint8_t buf[32];
     226            1 :     size_t out_len = 0;
     227            1 :     ASSERT(transport_recv(NULL, buf, 32, &out_len) == -1, "null transport");
     228            1 :     ASSERT(transport_recv(&t, NULL, 32, &out_len) == -1, "null buf");
     229            1 :     ASSERT(transport_recv(&t, buf, 32, NULL)     == -1, "null out_len");
     230              :     /* fd < 0 */
     231            1 :     ASSERT(transport_recv(&t, buf, 32, &out_len) == -1, "fd < 0");
     232              : }
     233              : 
     234            1 : void test_transport_recv_prefix_fails(void) {
     235            1 :     mock_socket_reset();
     236              :     Transport t;
     237            1 :     transport_init(&t);
     238            1 :     transport_connect(&t, "host", 443);
     239              :     /* No response set → recv returns 0, not 1 */
     240              :     uint8_t buf[32];
     241            1 :     size_t out_len = 0;
     242            1 :     int rc = transport_recv(&t, buf, 32, &out_len);
     243            1 :     ASSERT(rc == -1, "recv should fail when prefix byte missing");
     244            1 :     transport_close(&t);
     245              : }
     246              : 
     247            1 : void test_transport_recv_extended_prefix(void) {
     248            1 :     mock_socket_reset();
     249              :     Transport t;
     250            1 :     transport_init(&t);
     251            1 :     transport_connect(&t, "host", 443);
     252              : 
     253              :     /* QA-15: extended prefix = marker(0x7F) + 3 LE bytes wire_len.
     254              :      * wire_len = 3 → payload 12 bytes. */
     255              :     uint8_t wire[4 + 12];
     256            1 :     wire[0] = 0x7F;
     257            1 :     wire[1] = 0x03;
     258            1 :     wire[2] = 0x00;
     259            1 :     wire[3] = 0x00;
     260           13 :     for (int i = 0; i < 12; i++) wire[4 + i] = (uint8_t)(i + 1);
     261            1 :     mock_socket_set_response(wire, sizeof(wire));
     262              : 
     263              :     uint8_t buf[64];
     264            1 :     size_t out_len = 0;
     265            1 :     int rc = transport_recv(&t, buf, sizeof(buf), &out_len);
     266            1 :     ASSERT(rc == 0, "extended prefix recv must succeed");
     267            1 :     ASSERT(out_len == 12, "payload length must be 12");
     268            1 :     ASSERT(buf[0] == 1 && buf[11] == 12, "payload content must match");
     269            1 :     transport_close(&t);
     270              : }
     271              : 
     272            1 : void test_transport_recv_extended_prefix_short(void) {
     273            1 :     mock_socket_reset();
     274              :     Transport t;
     275            1 :     transport_init(&t);
     276            1 :     transport_connect(&t, "host", 443);
     277              :     /* Only 3 bytes (0x7F + 2 bytes) — second recv returns <3 */
     278            1 :     uint8_t wire[3] = {0x7F, 0x01, 0x00};
     279            1 :     mock_socket_set_response(wire, sizeof(wire));
     280              : 
     281              :     uint8_t buf[32];
     282            1 :     size_t out_len = 0;
     283            1 :     int rc = transport_recv(&t, buf, sizeof(buf), &out_len);
     284            1 :     ASSERT(rc == -1, "must fail on truncated extended prefix");
     285            1 :     transport_close(&t);
     286              : }
     287              : 
     288              : /* QA-15: recv handles 3rd length byte (>16 MB payload encoded). */
     289            1 : void test_transport_recv_extended_prefix_wide(void) {
     290            1 :     mock_socket_reset();
     291              :     Transport t;
     292            1 :     transport_init(&t);
     293            1 :     transport_connect(&t, "host", 443);
     294              : 
     295              :     /* wire_len = 0x010001 → payload = 0x040004 bytes. Too big to allocate
     296              :      * in test but we can check the length is parsed correctly by making
     297              :      * it exceed the caller's max_len and expecting -1. */
     298            1 :     uint8_t wire[4] = {0x7F, 0x01, 0x00, 0x01};
     299            1 :     mock_socket_set_response(wire, sizeof(wire));
     300              : 
     301              :     uint8_t buf[128];
     302            1 :     size_t out_len = 0;
     303            1 :     int rc = transport_recv(&t, buf, sizeof(buf), &out_len);
     304              :     /* 0x040004 bytes > 128 buffer, expect "frame too large" error. */
     305            1 :     ASSERT(rc == -1, "wide frame rejected against small buffer");
     306            1 :     transport_close(&t);
     307              : }
     308              : 
     309            1 : void test_transport_recv_zero_payload(void) {
     310            1 :     mock_socket_reset();
     311              :     Transport t;
     312            1 :     transport_init(&t);
     313            1 :     transport_connect(&t, "host", 443);
     314              :     /* wire_len = 0 → payload 0 */
     315            1 :     uint8_t wire[1] = {0x00};
     316            1 :     mock_socket_set_response(wire, 1);
     317              : 
     318              :     uint8_t buf[32];
     319            1 :     size_t out_len = 99;
     320            1 :     int rc = transport_recv(&t, buf, sizeof(buf), &out_len);
     321            1 :     ASSERT(rc == 0, "zero-length frame should succeed");
     322            1 :     ASSERT(out_len == 0, "out_len should be 0");
     323            1 :     transport_close(&t);
     324              : }
     325              : 
     326            1 : void test_transport_recv_frame_too_large(void) {
     327            1 :     mock_socket_reset();
     328              :     Transport t;
     329            1 :     transport_init(&t);
     330            1 :     transport_connect(&t, "host", 443);
     331              :     /* wire_len = 5 → payload 20, but caller max 8 */
     332            1 :     uint8_t wire[1] = {0x05};
     333            1 :     mock_socket_set_response(wire, 1);
     334              : 
     335              :     uint8_t buf[8];
     336            1 :     size_t out_len = 0;
     337            1 :     int rc = transport_recv(&t, buf, sizeof(buf), &out_len);
     338            1 :     ASSERT(rc == -1, "must fail when frame exceeds max_len");
     339            1 :     transport_close(&t);
     340              : }
     341              : 
     342            1 : void test_transport_recv_payload_fails(void) {
     343            1 :     mock_socket_reset();
     344              :     Transport t;
     345            1 :     transport_init(&t);
     346            1 :     transport_connect(&t, "host", 443);
     347              :     /* wire_len = 1 → payload 4, but no payload bytes provided */
     348            1 :     uint8_t wire[1] = {0x01};
     349            1 :     mock_socket_set_response(wire, 1);
     350              :     uint8_t buf[16];
     351            1 :     size_t out_len = 0;
     352            1 :     int rc = transport_recv(&t, buf, sizeof(buf), &out_len);
     353            1 :     ASSERT(rc == -1, "must fail when payload recv returns 0");
     354            1 :     transport_close(&t);
     355              : }
     356              : 
     357              : /* ---- Session tests ---- */
     358              : 
     359            1 : void test_session_init(void) {
     360            1 :     mock_crypto_reset();
     361              :     MtProtoSession s;
     362            1 :     mtproto_session_init(&s);
     363            1 :     ASSERT(s.session_id != 0, "session_id should be non-zero");
     364            1 :     ASSERT(s.seq_no == 0, "seq_no should start at 0");
     365            1 :     ASSERT(s.has_auth_key == 0, "should not have auth_key");
     366              : }
     367              : 
     368            1 : void test_session_msg_id_monotonic(void) {
     369            1 :     mock_crypto_reset();
     370              :     MtProtoSession s;
     371            1 :     mtproto_session_init(&s);
     372              : 
     373            1 :     uint64_t id1 = mtproto_session_next_msg_id(&s);
     374            1 :     uint64_t id2 = mtproto_session_next_msg_id(&s);
     375            1 :     ASSERT(id2 > id1, "msg_id should be monotonically increasing");
     376            1 :     ASSERT(id1 % 2 == 0, "msg_id should be even (client→server)");
     377            1 :     ASSERT(id2 % 2 == 0, "msg_id should be even");
     378              : }
     379              : 
     380            1 : void test_session_seq_no(void) {
     381            1 :     mock_crypto_reset();
     382              :     MtProtoSession s;
     383            1 :     mtproto_session_init(&s);
     384              : 
     385              :     /* Non-content-related (e.g., ping): seq_no = seq*2 */
     386            1 :     uint32_t s1 = mtproto_session_next_seq_no(&s, 0);
     387            1 :     ASSERT(s1 == 0, "first non-content seq should be 0");
     388              : 
     389              :     /* Content-related (RPC call): seq_no = seq*2 + 1, seq++ */
     390            1 :     uint32_t s2 = mtproto_session_next_seq_no(&s, 1);
     391            1 :     ASSERT(s2 == 1, "first content seq should be 1");
     392              : 
     393              :     /* Another content-related: seq_no = seq*2 + 1 */
     394            1 :     uint32_t s3 = mtproto_session_next_seq_no(&s, 1);
     395            1 :     ASSERT(s3 == 3, "second content seq should be 3");
     396              : 
     397              :     /* Non-content: seq_no = seq*2 */
     398            1 :     uint32_t s4 = mtproto_session_next_seq_no(&s, 0);
     399            1 :     ASSERT(s4 == 4, "non-content after 2 content should be 4");
     400              : }
     401              : 
     402            1 : void test_session_auth_key(void) {
     403            1 :     mock_crypto_reset();
     404              :     MtProtoSession s;
     405            1 :     mtproto_session_init(&s);
     406              : 
     407              :     uint8_t key[256];
     408            1 :     memset(key, 0xAB, 256);
     409            1 :     mtproto_session_set_auth_key(&s, key);
     410              : 
     411            1 :     ASSERT(s.has_auth_key == 1, "should have auth_key");
     412            1 :     ASSERT(memcmp(s.auth_key, key, 256) == 0, "auth_key should match");
     413              : }
     414              : 
     415            1 : void test_session_salt(void) {
     416            1 :     mock_crypto_reset();
     417              :     MtProtoSession s;
     418            1 :     mtproto_session_init(&s);
     419              : 
     420            1 :     mtproto_session_set_salt(&s, 0xDEADBEEFCAFEBABEULL);
     421            1 :     ASSERT(s.server_salt == 0xDEADBEEFCAFEBABEULL, "salt should match");
     422              : }
     423              : 
     424            1 : void test_session_save_load(void) {
     425            1 :     mock_crypto_reset();
     426              :     MtProtoSession s;
     427            1 :     mtproto_session_init(&s);
     428              : 
     429              :     uint8_t key[256];
     430            1 :     memset(key, 0x42, 256);
     431            1 :     mtproto_session_set_auth_key(&s, key);
     432              : 
     433              :     char tmppath[64];
     434            1 :     snprintf(tmppath, sizeof(tmppath), "/tmp/tg-cli-test-auth-%d", getpid());
     435              : 
     436            1 :     int rc = mtproto_session_save_auth_key(&s, tmppath);
     437            1 :     ASSERT(rc == 0, "save should succeed");
     438              : 
     439              :     MtProtoSession s2;
     440            1 :     memset(&s2, 0, sizeof(s2));
     441            1 :     rc = mtproto_session_load_auth_key(&s2, tmppath);
     442            1 :     ASSERT(rc == 0, "load should succeed");
     443            1 :     ASSERT(s2.has_auth_key == 1, "loaded session should have auth_key");
     444            1 :     ASSERT(memcmp(s2.auth_key, key, 256) == 0, "loaded key should match");
     445              : 
     446            1 :     remove(tmppath);
     447              : }
     448              : 
     449            1 : void test_session_load_nonexistent(void) {
     450              :     MtProtoSession s;
     451            1 :     memset(&s, 0, sizeof(s));
     452            1 :     int rc = mtproto_session_load_auth_key(&s, "/tmp/tg-cli-nonexistent-file-12345");
     453            1 :     ASSERT(rc == -1, "load from nonexistent file should fail");
     454            1 :     ASSERT(s.has_auth_key == 0, "should not have auth_key after failed load");
     455              : }
     456              : 
     457            1 : void test_session_load_truncated(void) {
     458              :     /* Write only 100 bytes (less than 256) */
     459              :     char tmppath[64];
     460            1 :     snprintf(tmppath, sizeof(tmppath), "/tmp/tg-cli-test-trunc-%d", getpid());
     461            1 :     FILE *f = fopen(tmppath, "wb");
     462            1 :     ASSERT(f != NULL, "should create temp file");
     463              :     uint8_t short_data[100];
     464            1 :     memset(short_data, 0x42, 100);
     465            1 :     fwrite(short_data, 1, 100, f);
     466            1 :     fclose(f);
     467              : 
     468              :     MtProtoSession s;
     469            1 :     memset(&s, 0, sizeof(s));
     470            1 :     int rc = mtproto_session_load_auth_key(&s, tmppath);
     471            1 :     ASSERT(rc == -1, "load from truncated file should fail");
     472            1 :     ASSERT(s.has_auth_key == 0, "should not have auth_key after truncated load");
     473              : 
     474            1 :     remove(tmppath);
     475              : }
     476              : 
     477            1 : void test_session_save_invalid_path(void) {
     478              :     MtProtoSession s;
     479            1 :     memset(&s, 0, sizeof(s));
     480              :     uint8_t key[256];
     481            1 :     memset(key, 0x42, 256);
     482            1 :     mtproto_session_set_auth_key(&s, key);
     483              : 
     484            1 :     int rc = mtproto_session_save_auth_key(&s, "/nonexistent/dir/auth.key");
     485            1 :     ASSERT(rc == -1, "save to invalid path should fail");
     486              : }
     487              : 
     488            1 : void test_session_save_null_args(void) {
     489              :     MtProtoSession s;
     490            1 :     memset(&s, 0, sizeof(s));
     491              : 
     492            1 :     ASSERT(mtproto_session_save_auth_key(NULL, "/tmp/x") == -1, "NULL session");
     493            1 :     ASSERT(mtproto_session_save_auth_key(&s, NULL) == -1, "NULL path");
     494              :     /* No auth_key set */
     495            1 :     ASSERT(mtproto_session_save_auth_key(&s, "/tmp/x") == -1, "no auth_key");
     496              : 
     497            1 :     ASSERT(mtproto_session_load_auth_key(NULL, "/tmp/x") == -1, "load NULL session");
     498            1 :     ASSERT(mtproto_session_load_auth_key(&s, NULL) == -1, "load NULL path");
     499              : }
     500              : 
     501              : /* ---- Test suite entry point ---- */
     502              : 
     503            1 : void test_phase2(void) {
     504            1 :     RUN_TEST(test_mock_socket_create);
     505            1 :     RUN_TEST(test_mock_socket_connect);
     506            1 :     RUN_TEST(test_mock_socket_send_recv);
     507            1 :     RUN_TEST(test_mock_socket_close);
     508            1 :     RUN_TEST(test_transport_connect_socket_create_fails);
     509            1 :     RUN_TEST(test_transport_connect_socket_connect_fails);
     510            1 :     RUN_TEST(test_transport_connect_marker_send_fails);
     511            1 :     RUN_TEST(test_transport_connect_null_args);
     512            1 :     RUN_TEST(test_transport_send_bad_args);
     513            1 :     RUN_TEST(test_transport_send_unaligned_len);
     514            1 :     RUN_TEST(test_transport_send_prefix_fails);
     515            1 :     RUN_TEST(test_transport_send_extended_prefix);
     516            1 :     RUN_TEST(test_transport_send_extended_prefix_wide);
     517            1 :     RUN_TEST(test_transport_send_extended_prefix_send_fails);
     518            1 :     RUN_TEST(test_transport_send_payload_send_fails);
     519            1 :     RUN_TEST(test_transport_recv_bad_args);
     520            1 :     RUN_TEST(test_transport_recv_prefix_fails);
     521            1 :     RUN_TEST(test_transport_recv_extended_prefix);
     522            1 :     RUN_TEST(test_transport_recv_extended_prefix_wide);
     523            1 :     RUN_TEST(test_transport_recv_extended_prefix_short);
     524            1 :     RUN_TEST(test_transport_recv_zero_payload);
     525            1 :     RUN_TEST(test_transport_recv_frame_too_large);
     526            1 :     RUN_TEST(test_transport_recv_payload_fails);
     527            1 :     RUN_TEST(test_session_init);
     528            1 :     RUN_TEST(test_session_msg_id_monotonic);
     529            1 :     RUN_TEST(test_session_seq_no);
     530            1 :     RUN_TEST(test_session_auth_key);
     531            1 :     RUN_TEST(test_session_salt);
     532            1 :     RUN_TEST(test_session_save_load);
     533            1 :     RUN_TEST(test_session_load_nonexistent);
     534            1 :     RUN_TEST(test_session_load_truncated);
     535            1 :     RUN_TEST(test_session_save_invalid_path);
     536            1 :     RUN_TEST(test_session_save_null_args);
     537            1 : }
        

Generated by: LCOV version 2.0-1