Line data Source code
1 : /**
2 : * @file test_domain_contacts.c
3 : */
4 :
5 : #include "test_helpers.h"
6 : #include "domain/read/contacts.h"
7 : #include "tl_serial.h"
8 : #include "tl_registry.h"
9 : #include "mock_socket.h"
10 : #include "mock_crypto.h"
11 : #include "mtproto_session.h"
12 : #include "transport.h"
13 : #include "api_call.h"
14 :
15 : #include <stdlib.h>
16 : #include <string.h>
17 :
18 : #define CRC_contact 0x145ade0bu
19 :
20 2 : static void build_fake_encrypted_response(const uint8_t *payload, size_t plen,
21 : uint8_t *out, size_t *out_len) {
22 2 : TlWriter w; tl_writer_init(&w);
23 2 : uint8_t z24[24] = {0}; tl_write_raw(&w, z24, 24);
24 2 : uint8_t hdr[32] = {0};
25 2 : uint32_t pl32 = (uint32_t)plen;
26 2 : memcpy(hdr + 28, &pl32, 4);
27 2 : tl_write_raw(&w, hdr, 32);
28 2 : tl_write_raw(&w, payload, plen);
29 2 : size_t enc = w.len - 24;
30 2 : if (enc % 16 != 0) {
31 2 : uint8_t pad[16] = {0}; tl_write_raw(&w, pad, 16 - (enc % 16));
32 : }
33 2 : out[0] = (uint8_t)(w.len / 4);
34 2 : memcpy(out + 1, w.data, w.len);
35 2 : *out_len = 1 + w.len;
36 2 : tl_writer_free(&w);
37 2 : }
38 :
39 3 : static void fix_session(MtProtoSession *s) {
40 3 : mtproto_session_init(s);
41 3 : s->session_id = 0; /* match the zero session_id in fake encrypted frames */
42 3 : uint8_t k[256] = {0}; mtproto_session_set_auth_key(s, k);
43 3 : mtproto_session_set_salt(s, 0xCAFE11223344DEAD);
44 3 : }
45 3 : static void fix_transport(Transport *t) {
46 3 : transport_init(t); t->fd = 42; t->connected = 1; t->dc_id = 1;
47 3 : }
48 3 : static void fix_cfg(ApiConfig *cfg) {
49 3 : api_config_init(cfg); cfg->api_id = 12345; cfg->api_hash = "deadbeef";
50 3 : }
51 :
52 1 : static void test_contacts_simple(void) {
53 1 : mock_socket_reset(); mock_crypto_reset();
54 :
55 : /* contacts.contacts + 3 contacts + saved_count + empty users vector. */
56 1 : TlWriter w; tl_writer_init(&w);
57 1 : tl_write_uint32(&w, TL_contacts_contacts);
58 1 : tl_write_uint32(&w, TL_vector);
59 1 : tl_write_uint32(&w, 3);
60 1 : tl_write_uint32(&w, CRC_contact); tl_write_int64(&w, 100LL); tl_write_bool(&w, 1);
61 1 : tl_write_uint32(&w, CRC_contact); tl_write_int64(&w, 200LL); tl_write_bool(&w, 0);
62 1 : tl_write_uint32(&w, CRC_contact); tl_write_int64(&w, 300LL); tl_write_bool(&w, 1);
63 1 : tl_write_int32 (&w, 3); /* saved_count */
64 1 : tl_write_uint32(&w, TL_vector);
65 1 : tl_write_uint32(&w, 0);
66 :
67 1 : uint8_t payload[512]; memcpy(payload, w.data, w.len);
68 1 : size_t plen = w.len; tl_writer_free(&w);
69 :
70 1 : uint8_t resp[1024]; size_t rlen = 0;
71 1 : build_fake_encrypted_response(payload, plen, resp, &rlen);
72 1 : mock_socket_set_response(resp, rlen);
73 :
74 : MtProtoSession s; Transport t; ApiConfig cfg;
75 1 : fix_session(&s); fix_transport(&t); fix_cfg(&cfg);
76 :
77 1 : ContactEntry entries[10] = {0};
78 1 : int count = 0;
79 1 : int rc = domain_get_contacts(&cfg, &s, &t, entries, 10, &count);
80 1 : ASSERT(rc == 0, "contacts parsed");
81 1 : ASSERT(count == 3, "all 3 contacts");
82 1 : ASSERT(entries[0].user_id == 100 && entries[0].mutual == 1, "c0");
83 1 : ASSERT(entries[1].user_id == 200 && entries[1].mutual == 0, "c1");
84 1 : ASSERT(entries[2].user_id == 300 && entries[2].mutual == 1, "c2");
85 : }
86 :
87 1 : static void test_contacts_rpc_error(void) {
88 1 : mock_socket_reset(); mock_crypto_reset();
89 1 : TlWriter w; tl_writer_init(&w);
90 1 : tl_write_uint32(&w, TL_rpc_error);
91 1 : tl_write_int32(&w, 401);
92 1 : tl_write_string(&w, "AUTH_KEY_INVALID");
93 1 : uint8_t payload[64]; memcpy(payload, w.data, w.len);
94 1 : size_t plen = w.len; tl_writer_free(&w);
95 :
96 1 : uint8_t resp[256]; size_t rlen = 0;
97 1 : build_fake_encrypted_response(payload, plen, resp, &rlen);
98 1 : mock_socket_set_response(resp, rlen);
99 :
100 : MtProtoSession s; Transport t; ApiConfig cfg;
101 1 : fix_session(&s); fix_transport(&t); fix_cfg(&cfg);
102 :
103 1 : ContactEntry e[5] = {0}; int n = 0;
104 1 : int rc = domain_get_contacts(&cfg, &s, &t, e, 5, &n);
105 1 : ASSERT(rc != 0, "RPC error propagates");
106 : }
107 :
108 1 : static void test_contacts_null_args(void) {
109 1 : ContactEntry e[1]; int n = 0;
110 1 : ASSERT(domain_get_contacts(NULL, NULL, NULL, e, 5, &n) == -1, "nulls");
111 1 : ApiConfig cfg; fix_cfg(&cfg);
112 1 : MtProtoSession s; fix_session(&s);
113 1 : Transport t; fix_transport(&t);
114 1 : ASSERT(domain_get_contacts(&cfg, &s, &t, e, 0, &n) == -1, "zero max");
115 : }
116 :
117 1 : void run_domain_contacts_tests(void) {
118 1 : RUN_TEST(test_contacts_simple);
119 1 : RUN_TEST(test_contacts_rpc_error);
120 1 : RUN_TEST(test_contacts_null_args);
121 1 : }
|