/work/auto_tests/scenarios/scenario_file_seek_test.c
Line | Count | Source (jump to first uncovered line) |
1 | | #include "framework/framework.h" |
2 | | #include <stdio.h> |
3 | | #include <stdlib.h> |
4 | | #include <string.h> |
5 | | |
6 | 1 | #define FILE_SIZE (1024 * 1024) |
7 | 385 | #define SEEK_POS (512 * 1024) |
8 | | |
9 | | typedef struct { |
10 | | bool seek_happened; |
11 | | bool finished; |
12 | | } SenderState; |
13 | | |
14 | | static void on_file_chunk_request(const Tox_Event_File_Chunk_Request *event, void *user_data) |
15 | 384 | { |
16 | 384 | ToxNode *self = (ToxNode *)user_data; |
17 | 384 | SenderState *state = (SenderState *)tox_node_get_script_ctx(self); |
18 | | |
19 | 384 | uint32_t friend_number = tox_event_file_chunk_request_get_friend_number(event); |
20 | 384 | uint32_t file_number = tox_event_file_chunk_request_get_file_number(event); |
21 | 384 | uint64_t position = tox_event_file_chunk_request_get_position(event); |
22 | 384 | size_t length = tox_event_file_chunk_request_get_length(event); |
23 | | |
24 | 384 | if (length == 0) { |
25 | 1 | state->finished = true; |
26 | 1 | return; |
27 | 1 | } |
28 | | |
29 | 383 | if (position >= SEEK_POS) { |
30 | 383 | state->seek_happened = true; |
31 | 383 | } |
32 | | |
33 | 383 | uint8_t data[TOX_MAX_CUSTOM_PACKET_SIZE]; |
34 | 383 | memset(data, (uint8_t)(position % 256), length); |
35 | 383 | tox_file_send_chunk(tox_node_get_tox(self), friend_number, file_number, position, data, length, nullptr); |
36 | 383 | } |
37 | | |
38 | | static void sender_script(ToxNode *self, void *ctx) |
39 | 1 | { |
40 | 1 | SenderState *state = (SenderState *)ctx; |
41 | 1 | tox_events_callback_file_chunk_request(tox_node_get_dispatch(self), on_file_chunk_request); |
42 | | |
43 | 1 | tox_node_wait_for_self_connected(self); |
44 | 1 | tox_node_wait_for_friend_connected(self, 0); |
45 | | |
46 | 1 | Tox *tox = tox_node_get_tox(self); |
47 | 1 | tox_file_send(tox, 0, TOX_FILE_KIND_DATA, FILE_SIZE, nullptr, (const uint8_t *)"seek_test.bin", 13, nullptr); |
48 | | |
49 | 1 | WAIT_UNTIL(state->finished); |
50 | 1 | tox_node_log(self, "Sender finished. Seek happened: %s", state->seek_happened ? "YES" : "NO"); |
51 | 1 | ck_assert(state->seek_happened); |
52 | 1 | } |
53 | | |
54 | | typedef struct { |
55 | | uint32_t file_number; |
56 | | bool file_recv_called; |
57 | | bool finished; |
58 | | } ReceiverState; |
59 | | |
60 | | static void on_file_recv(const Tox_Event_File_Recv *event, void *user_data) |
61 | 2 | { |
62 | 2 | ToxNode *self = (ToxNode *)user_data; |
63 | 2 | ReceiverState *state = (ReceiverState *)tox_node_get_script_ctx(self); |
64 | 2 | state->file_number = tox_event_file_recv_get_file_number(event); |
65 | 2 | state->file_recv_called = true; |
66 | 2 | tox_node_log(self, "Received file request, file_number = %u", state->file_number); |
67 | 2 | } |
68 | | |
69 | | static void on_file_recv_chunk(const Tox_Event_File_Recv_Chunk *event, void *user_data) |
70 | 384 | { |
71 | 384 | ToxNode *self = (ToxNode *)user_data; |
72 | 384 | ReceiverState *state = (ReceiverState *)tox_node_get_script_ctx(self); |
73 | 384 | size_t length = tox_event_file_recv_chunk_get_data_length(event); |
74 | 384 | if (length == 0) { |
75 | 1 | state->finished = true; |
76 | 1 | } |
77 | 384 | } |
78 | | |
79 | | static void receiver_script(ToxNode *self, void *ctx) |
80 | 1 | { |
81 | 1 | ReceiverState *state = (ReceiverState *)ctx; |
82 | 1 | tox_events_callback_file_recv(tox_node_get_dispatch(self), on_file_recv); |
83 | 1 | tox_events_callback_file_recv_chunk(tox_node_get_dispatch(self), on_file_recv_chunk); |
84 | | |
85 | 1 | tox_node_wait_for_self_connected(self); |
86 | 1 | tox_node_wait_for_friend_connected(self, 0); |
87 | | |
88 | 1 | WAIT_UNTIL(state->file_recv_called); |
89 | | |
90 | 1 | tox_node_log(self, "Seeking to %d before resuming...", SEEK_POS); |
91 | 1 | Tox_Err_File_Seek seek_err; |
92 | 1 | bool seek_res = tox_file_seek(tox_node_get_tox(self), 0, state->file_number, SEEK_POS, &seek_err); |
93 | 1 | if (!seek_res) { |
94 | 0 | tox_node_log(self, "tox_file_seek failed: %s", tox_err_file_seek_to_string(seek_err)); |
95 | 0 | } |
96 | 1 | ck_assert(seek_res); |
97 | | |
98 | 1 | tox_node_log(self, "Resuming file %u...", state->file_number); |
99 | 1 | Tox_Err_File_Control ctrl_err; |
100 | 1 | bool resume_res = tox_file_control(tox_node_get_tox(self), 0, state->file_number, TOX_FILE_CONTROL_RESUME, &ctrl_err); |
101 | 1 | ck_assert(resume_res); |
102 | | |
103 | 1 | WAIT_UNTIL(state->finished); |
104 | 1 | tox_node_log(self, "Receiver finished!"); |
105 | 1 | } |
106 | | |
107 | | int main(int argc, char *argv[]) |
108 | 31 | { |
109 | 31 | ToxScenario *s = tox_scenario_new(argc, argv, 60000); |
110 | | |
111 | 31 | SenderState sender_state = {false, false}; |
112 | 31 | ReceiverState receiver_state = {0, false, false}; |
113 | | |
114 | 31 | tox_scenario_add_node(s, "Sender", sender_script, &sender_state, sizeof(SenderState)); |
115 | 31 | tox_scenario_add_node(s, "Receiver", receiver_script, &receiver_state, sizeof(ReceiverState)); |
116 | | |
117 | 31 | ToxNode *sender = tox_scenario_get_node(s, 0); |
118 | 31 | ToxNode *receiver = tox_scenario_get_node(s, 1); |
119 | | |
120 | 31 | tox_node_bootstrap(sender, receiver); |
121 | 31 | tox_node_friend_add(sender, receiver); |
122 | 31 | tox_node_friend_add(receiver, sender); |
123 | | |
124 | 31 | ToxScenarioStatus res = tox_scenario_run(s); |
125 | 31 | if (res != TOX_SCENARIO_DONE) { |
126 | 0 | fprintf(stderr, "Scenario failed with status %u\n", res); |
127 | 0 | return 1; |
128 | 0 | } |
129 | | |
130 | 31 | tox_scenario_free(s); |
131 | 31 | return 0; |
132 | 31 | } |
133 | | |
134 | | #undef FILE_SIZE |