c1e1db8f5e
CI / lint (pull_request) Failing after 2s
CI / build-and-test (pull_request) Has been skipped
CI / sanitizers (address) (pull_request) Has been skipped
CI / sanitizers (undefined) (pull_request) Has been skipped
CI / fuzz-build (pull_request) Has been skipped
CI / coverage (pull_request) Has been skipped
CI / valgrind (pull_request) Has been skipped
236 lines
6.1 KiB
C
236 lines
6.1 KiB
C
#include "test_file_sendfile.h"
|
|
#include "file.h"
|
|
#include "data.h"
|
|
#include "config.h"
|
|
#include "protocol.h"
|
|
#include "utils.h"
|
|
#include "test_utils.h"
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/wait.h>
|
|
#include <unistd.h>
|
|
|
|
static void test_sendfile_basic() {
|
|
const char* content = "Hello sendfile test content!";
|
|
size_t len = strlen(content);
|
|
EXPECT_TRUE(to_disk("test_sendfile_basic.txt", content, len));
|
|
|
|
File* file = file_create("test_sendfile_basic.txt");
|
|
EXPECT_NOT_NULL(file);
|
|
file->data->size = len;
|
|
file->data->data = malloc(len);
|
|
EXPECT_NOT_NULL(file->data->data);
|
|
memcpy(file->data->data, content, len);
|
|
|
|
int p[2];
|
|
EXPECT_EQ_INT(pipe(p), 0);
|
|
io_set_fds(p[0], p[1]);
|
|
io_set_bwlimit(0);
|
|
|
|
pid_t pid = fork();
|
|
if (pid == 0) {
|
|
close(p[1]);
|
|
// Receive path: read size then data
|
|
unsigned long long recv_size;
|
|
EXPECT_TRUE(receive_n_data(p[0], &recv_size, sizeof(recv_size)));
|
|
EXPECT_EQ_INT((int)recv_size, (int)len);
|
|
|
|
char* buf = malloc(recv_size + 1);
|
|
EXPECT_NOT_NULL(buf);
|
|
EXPECT_TRUE(receive_n_data(p[0], buf, recv_size));
|
|
buf[recv_size] = '\0';
|
|
EXPECT_EQ_INT(memcmp(buf, content, len), 0);
|
|
free(buf);
|
|
close(p[0]);
|
|
_exit(0);
|
|
} else {
|
|
close(p[0]);
|
|
bool sent = file_send_sendfile(file, p[1], false, 0, false);
|
|
close(p[1]);
|
|
|
|
int status;
|
|
waitpid(pid, &status, 0);
|
|
|
|
file_destroy(file);
|
|
unlink("test_sendfile_basic.txt");
|
|
|
|
EXPECT_TRUE(sent);
|
|
EXPECT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) == 0);
|
|
}
|
|
}
|
|
|
|
static void test_sendfile_with_path() {
|
|
const char* content = "Sendfile with path test";
|
|
size_t len = strlen(content);
|
|
EXPECT_TRUE(to_disk("test_sendfile_path.txt", content, len));
|
|
|
|
File* file = file_create("test_sendfile_path.txt");
|
|
EXPECT_NOT_NULL(file);
|
|
file->data->size = len;
|
|
file->data->data = malloc(len);
|
|
EXPECT_NOT_NULL(file->data->data);
|
|
memcpy(file->data->data, content, len);
|
|
|
|
int p[2];
|
|
EXPECT_EQ_INT(pipe(p), 0);
|
|
io_set_fds(p[0], p[1]);
|
|
io_set_bwlimit(0);
|
|
|
|
pid_t pid = fork();
|
|
if (pid == 0) {
|
|
close(p[1]);
|
|
char* recv_path = receive_str(p[0]);
|
|
EXPECT_NOT_NULL(recv_path);
|
|
EXPECT_EQ_STR(recv_path, "test_sendfile_path.txt");
|
|
free(recv_path);
|
|
|
|
unsigned long long recv_size;
|
|
EXPECT_TRUE(receive_n_data(p[0], &recv_size, sizeof(recv_size)));
|
|
|
|
char* buf = malloc(recv_size + 1);
|
|
EXPECT_NOT_NULL(buf);
|
|
EXPECT_TRUE(receive_n_data(p[0], buf, recv_size));
|
|
buf[recv_size] = '\0';
|
|
EXPECT_EQ_INT(memcmp(buf, content, len), 0);
|
|
free(buf);
|
|
close(p[0]);
|
|
_exit(0);
|
|
} else {
|
|
close(p[0]);
|
|
bool sent = file_send_sendfile(file, p[1], false, 0, true);
|
|
close(p[1]);
|
|
|
|
int status;
|
|
waitpid(pid, &status, 0);
|
|
|
|
file_destroy(file);
|
|
unlink("test_sendfile_path.txt");
|
|
|
|
EXPECT_TRUE(sent);
|
|
EXPECT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) == 0);
|
|
}
|
|
}
|
|
|
|
static void test_sendfile_empty_file() {
|
|
const char* content = "";
|
|
size_t len = 0;
|
|
EXPECT_TRUE(to_disk("test_sendfile_empty.txt", content, len));
|
|
|
|
File* file = file_create("test_sendfile_empty.txt");
|
|
EXPECT_NOT_NULL(file);
|
|
file->data->size = len;
|
|
file->data->data = NULL;
|
|
|
|
int p[2];
|
|
EXPECT_EQ_INT(pipe(p), 0);
|
|
io_set_fds(p[0], p[1]);
|
|
io_set_bwlimit(0);
|
|
|
|
pid_t pid = fork();
|
|
if (pid == 0) {
|
|
close(p[1]);
|
|
unsigned long long recv_size;
|
|
EXPECT_TRUE(receive_n_data(p[0], &recv_size, sizeof(recv_size)));
|
|
EXPECT_EQ_INT((int)recv_size, 0);
|
|
close(p[0]);
|
|
_exit(0);
|
|
} else {
|
|
close(p[0]);
|
|
bool sent = file_send_sendfile(file, p[1], false, 0, false);
|
|
close(p[1]);
|
|
|
|
int status;
|
|
waitpid(pid, &status, 0);
|
|
|
|
file_destroy(file);
|
|
unlink("test_sendfile_empty.txt");
|
|
|
|
EXPECT_TRUE(sent);
|
|
EXPECT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) == 0);
|
|
}
|
|
}
|
|
|
|
static void test_sendfile_with_compression_fallback() {
|
|
// When compression_level > 0, sendfile falls back to file_send_single_calls
|
|
const char* content = "Sendfile compression fallback test data here.";
|
|
size_t len = strlen(content);
|
|
EXPECT_TRUE(to_disk("test_sendfile_comp.txt", content, len));
|
|
|
|
File* file = file_create("test_sendfile_comp.txt");
|
|
EXPECT_NOT_NULL(file);
|
|
file->data->size = len;
|
|
file->data->data = malloc(len);
|
|
EXPECT_NOT_NULL(file->data->data);
|
|
memcpy(file->data->data, content, len);
|
|
|
|
Config* cfg = config_create(str_dup(PROTOCOL_VERSION), str_dup("/tmp"), str_dup("/tmp"), false,
|
|
false, false, false, false, 0, false, 0);
|
|
|
|
int p[2];
|
|
EXPECT_EQ_INT(pipe(p), 0);
|
|
io_set_fds(p[0], p[1]);
|
|
io_set_bwlimit(0);
|
|
|
|
pid_t pid = fork();
|
|
if (pid == 0) {
|
|
close(p[1]);
|
|
File* received = file_receive(cfg, p[0]);
|
|
close(p[0]);
|
|
bool ok = true;
|
|
if (!received) ok = false;
|
|
else {
|
|
if (!received->data || received->data->size != len) ok = false;
|
|
else if (memcmp(received->data->data, content, len) != 0) ok = false;
|
|
}
|
|
file_destroy(received);
|
|
config_delete(cfg);
|
|
_exit(ok ? 0 : 1);
|
|
} else {
|
|
close(p[0]);
|
|
// Send with compression_level=1, should fall back to file_send_single_calls
|
|
bool sent = file_send_sendfile(file, p[1], false, 1, true);
|
|
close(p[1]);
|
|
|
|
int status;
|
|
waitpid(pid, &status, 0);
|
|
|
|
file_destroy(file);
|
|
config_delete(cfg);
|
|
unlink("test_sendfile_comp.txt");
|
|
|
|
EXPECT_TRUE(sent);
|
|
EXPECT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) == 0);
|
|
}
|
|
}
|
|
|
|
static void test_sendfile_nonexistent_file() {
|
|
File* file = file_create("nonexistent_file_xyz_sendfile_test.txt");
|
|
EXPECT_NOT_NULL(file);
|
|
file->data->size = 100;
|
|
file->data->data = malloc(100);
|
|
EXPECT_NOT_NULL(file->data->data);
|
|
memset(file->data->data, 0, 100);
|
|
|
|
int p[2];
|
|
EXPECT_EQ_INT(pipe(p), 0);
|
|
io_set_fds(p[0], p[1]);
|
|
io_set_bwlimit(0);
|
|
close(p[0]);
|
|
|
|
bool sent = file_send_sendfile(file, p[1], false, 0, false);
|
|
close(p[1]);
|
|
|
|
file_destroy(file);
|
|
// File doesn't exist on disk, sendfile should fail
|
|
EXPECT_FALSE(sent);
|
|
}
|
|
|
|
void test_file_sendfile() {
|
|
test_sendfile_basic();
|
|
test_sendfile_with_path();
|
|
test_sendfile_empty_file();
|
|
test_sendfile_with_compression_fallback();
|
|
test_sendfile_nonexistent_file();
|
|
}
|