1
0
mirror of https://github.com/libssh2/libssh2.git synced 2025-08-01 11:26:53 +03:00

Add test to read lots of data over a channel

Connects to the ssh server then downloads several MB of data.  This
tests the data transfer path as well as boundary cases in packet
handling as data is split into smaller SSH blocks.
This commit is contained in:
Dan Fandrich
2023-02-28 17:01:26 -08:00
parent 45d33da3c7
commit 5f88efdddc
3 changed files with 111 additions and 1 deletions

108
tests/test_read.c Normal file
View File

@ -0,0 +1,108 @@
/* libssh2 test receiving large amounts of data through a channel */
#include "session_fixture.h"
#include "runner.h"
#include <libssh2.h>
#include <stdio.h>
/* configured in Dockerfile */
static const char *USERNAME = "libssh2";
static const char *KEY_FILE_PRIVATE = "key_rsa";
static const char *KEY_FILE_PUBLIC = "key_rsa.pub";
/* Size and number of blocks to transfer
* This needs to be large to increase the chance of timing effects causing
* different code paths to be hit in the unframing code, but not so long that
* the integration tests take too long. 5 seconds of run time is probably a
* reasonable compromise. The block size is an odd number to increase the
* chance that various internal buffer and block boundaries are overlapped. */
#define XFER_BS 997
#define XFER_COUNT 140080
#define STRINGIFY(x) STRINGIFY2(x)
#define STRINGIFY2(x) #x
/* command to transfer the desired amount of data */
#define REMOTE_COMMAND "dd if=/dev/zero bs=" STRINGIFY(XFER_BS) \
" count=" STRINGIFY(XFER_COUNT) " status=none"
int test(LIBSSH2_SESSION *session)
{
int rc;
long xfer_bytes = 0;
LIBSSH2_CHANNEL *channel;
const char *userauth_list =
libssh2_userauth_list(session, USERNAME, strlen(USERNAME));
if(userauth_list == NULL) {
print_last_session_error("libssh2_userauth_list");
return 1;
}
if(strstr(userauth_list, "publickey") == NULL) {
fprintf(stderr, "'publickey' was expected in userauth list: %s\n",
userauth_list);
return 1;
}
rc = libssh2_userauth_publickey_fromfile_ex(
session, USERNAME, strlen(USERNAME),
srcdir_path(KEY_FILE_PUBLIC), srcdir_path(KEY_FILE_PRIVATE), NULL);
if(rc != 0) {
print_last_session_error("libssh2_userauth_publickey_fromfile_ex");
return 1;
}
/* Request a session channel on which to run a shell */
channel = libssh2_channel_open_session(session);
if(!channel) {
fprintf(stderr, "Unable to open a session\n");
goto shutdown;
}
/* Send the command to transfer data */
if(libssh2_channel_exec(channel, REMOTE_COMMAND)) {
fprintf(stderr, "Unable to request command on channel\n");
goto shutdown;
}
/* Read data */
while(!libssh2_channel_eof(channel)) {
char buf[1024];
ssize_t err = libssh2_channel_read(channel, buf, sizeof(buf));
if(err < 0)
fprintf(stderr, "Unable to read response: %zd\n", err);
else {
int i;
for(i = 0; i < err; ++i) {
if(buf[i]) {
fprintf(stderr, "Bad data received\n");
/* Test will fail below due to bad data length */
break;
}
}
xfer_bytes += i;
}
}
/* Shut down */
if(libssh2_channel_close(channel))
fprintf(stderr, "Unable to close channel\n");
if(channel) {
libssh2_channel_free(channel);
channel = NULL;
}
shutdown:
/* Test check */
if(xfer_bytes != XFER_COUNT * XFER_BS) {
fprintf(stderr, "Not enough bytes received: %ld not %ld\n",
xfer_bytes, (long)XFER_COUNT * XFER_BS);
return 1; /* error */
}
return 0;
}