Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create tests for functions that will check ftp:// prefix #945

Closed
Closed
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
4. [912] - Adding working compose instance for core metadata services.
5. [937] - Working metadata services running together as part of CI
6. [946] - Added docker compose for DataFed Repository and for Metadata Services
7. [945] - Added C functions for comparing POSIX path in Authz module

## PATCH Bug fixes/Technical Debt/Documentation

Expand Down
1 change: 1 addition & 0 deletions repository/gridftp/globus5/authz/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
add_subdirectory( source )
add_subdirectory( tests )
92 changes: 92 additions & 0 deletions repository/gridftp/globus5/authz/source/URL.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
#include <stdio.h>
#include <string.h>

#include "URL.h"

// Function to extract the relative path from an FTP URL
// Returns 1 on success, 0 on failure
int ftpExtractRelativePath(const char *url, char *relativePath,
size_t maxLength) {
size_t len_of_prefix = strlen("ftp://");
size_t len_of_url = strlen(url);

// Step 1. Check that the URL starts with "ftp://"
if (strncmp(url, "ftp://", len_of_prefix) != 0) {
fprintf(stderr,
"Error: URL must start with 'ftp:// but you have provided %s'\n",
url);
return 0;
}

if (len_of_url == len_of_prefix) {
// This means we have ftp:// but with no relative path and missing
// the final / separating the domain from the relative path.
fprintf(stderr,
"Error: Invalid URL format expected ftp://domain/ instead received "
"%s\n",
url);
return 0;
} else if (url[len_of_prefix] == '/') {
// If they are not equal the url must be greater because we already
// compared the prefix. Let's make sure we don't have
// ftp:/// where no domain is given this is invalid as well
//
// NOTE the third / will appear at index 6 not 7
fprintf(stderr,
"Error: Invalid URL format missing domain name expected "
"ftp://domain/ instead received %s\n",
url);
return 0;
}
// Find the position of the third slash ('/') after "ftp://"
const char *slashPtr = strchr(url + len_of_prefix, '/');
if (slashPtr == NULL) {
if (len_of_url == len_of_prefix) {
// This means we have ftp:// but with no relative path and missing
// the final / separating the domain from the relative path.
fprintf(stderr,
"Error: Invalid URL format expected ftp://domain/ instead "
"received %s\n",
url);
return 0;
} else {
// This means we have ftp://domain but with no relative path and missing
// the final / separating the domain from the relative path. We will
// report this as a success and return a slash
relativePath[0] = '/';
relativePath[1] = '\0';
return 1;
}
}

printf("slashPtr is %s\n", slashPtr);
// Calculate the length of the relative path
size_t pathLength = strlen(slashPtr);

// Check if the provided buffer is sufficient
if (pathLength >= maxLength) {
fprintf(
stderr,
"Error: Insufficient buffer size max size is %ld actual size is %ld\n",
maxLength, pathLength);
return 0;
}

// Copy the relative path to the output buffer
strcpy(relativePath, slashPtr);

return 1; // Success
}

int comparePrefix(const char *str1, const char *str2, size_t prefix_length) {
size_t len1 = strlen(str1);
size_t len2 = strlen(str2);

// Ensure the prefix length is not longer than the shortest string length
if (prefix_length > len1 || prefix_length > len2) {
return -1; // Prefix length is longer than one or both of the strings
}

// Compare the prefixes
return strncmp(str1, str2, prefix_length);
}
31 changes: 31 additions & 0 deletions repository/gridftp/globus5/authz/source/URL.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#include <stdio.h>
#include <string.h>

#ifdef __cplusplus
extern "C" {
#endif

/**
* Function to extract the relative path from an FTP URL
*
* Will take a uri of the form ftp://domain/path/to/file
*
* If the URI has the prefix
*
* ftp://domain Returns 1 for success
* else it will return 0 for failure
**/
int ftpExtractRelativePath(const char *url, char *relativePath,
size_t maxLength);

/**
* Will compare two strings and ensure that prefixes are equivalent
*
* On success will return the results of strncmp which will be 0 if they
* match.
**/
int comparePrefix(const char *str1, const char *str2, size_t prefix_length);

#ifdef __cplusplus
}
#endif
3 changes: 3 additions & 0 deletions repository/gridftp/globus5/authz/tests/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
if( ENABLE_UNIT_TESTS )
add_subdirectory(unit)
endif( ENABLE_UNIT_TESTS )
17 changes: 17 additions & 0 deletions repository/gridftp/globus5/authz/tests/unit/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Each test listed in Alphabetical order

include_directories(${PROJECT_SOURCE_DIR}/repository/gridftp/globus5/authz/source)
add_executable(unit_test_URL test_URL.cpp ../../source/URL.c )

target_compile_options(unit_test_URL PRIVATE -fPIC)

add_dependencies(unit_test_URL common)
if(BUILD_SHARED_LIBS)
target_link_libraries(unit_test_URL PRIVATE ${DATAFED_BOOST_LIBRARIES})
target_compile_definitions(unit_test_URL PRIVATE BOOST_TEST_DYN_LINK)
else()
target_link_libraries(unit_test_URL PRIVATE ${DATAFED_BOOST_LIBRARIES})
endif()
# Only want this if using shared boost libraries
add_test(unit_test_URL unit_test_URL)

122 changes: 122 additions & 0 deletions repository/gridftp/globus5/authz/tests/unit/test_URL.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
#include <stdio.h>
#include <string.h>

#define BOOST_TEST_MAIN

#define BOOST_TEST_MODULE buffer
#include <boost/filesystem.hpp>
#include <boost/test/unit_test.hpp>

#include "URL.h"

BOOST_AUTO_TEST_SUITE(BufferTest)

BOOST_AUTO_TEST_CASE(test_1_ftpExtractRelativePath) {
char relative_path[100]; // Adjust the buffer size as needed
const char *url1 = "ftp://domain/relative_path";

int rv = ftpExtractRelativePath(url1, relative_path, sizeof(relative_path));
// Should pass
BOOST_CHECK(strcmp(relative_path, "/relative_path") == 0);
BOOST_CHECK(rv == 1);
}

BOOST_AUTO_TEST_CASE(test_2_ftpExtractRelativePath) {
char relative_path[100]; // Adjust the buffer size as needed
const char *url = "ftp://domain";

int rv = ftpExtractRelativePath(url, relative_path, sizeof(relative_path));
// Should not throw an error
BOOST_CHECK(rv == 1);
BOOST_CHECK(strcmp(relative_path, "/") == 0);
}

BOOST_AUTO_TEST_CASE(test_3_ftpExtractRelativePath) {
char relative_path[100]; // Adjust the buffer size as needed
const char *url = "";

int rv = ftpExtractRelativePath(url, relative_path, sizeof(relative_path));
// Should throw an error
BOOST_CHECK(rv == 0);
}

BOOST_AUTO_TEST_CASE(test_4_ftpExtractRelativePath) {
char relative_path[100]; // Adjust the buffer size as needed
const char *url = "ftp:///";

int rv = ftpExtractRelativePath(url, relative_path, sizeof(relative_path));
// Should throw an error
BOOST_CHECK(rv == 0);
}

BOOST_AUTO_TEST_CASE(test_5_ftpExtractRelativePath) {
char relative_path[100]; // Adjust the buffer size as needed
const char *url = "ftp:/domain///path";

int rv = ftpExtractRelativePath(url, relative_path, sizeof(relative_path));
// Should throw an error because prefix is incorrect
BOOST_CHECK(rv == 0);
}

BOOST_AUTO_TEST_CASE(test_6_ftpExtractRelativePath) {
char relative_path[100]; // Adjust the buffer size as needed
const char *url = "ftp://domain///path";

int rv = ftpExtractRelativePath(url, relative_path, sizeof(relative_path));
// Should not throw an error
BOOST_CHECK(rv == 1);
printf("Relative path is %s\n", relative_path);
BOOST_CHECK(strcmp(relative_path, "///path") == 0);
}

BOOST_AUTO_TEST_CASE(test_1_comparePrefix) {
const char *allowed_prefix = "/mnt/storage/globus";
size_t prefix_len = strlen(allowed_prefix);
const char *relative_path = "";
int rv = comparePrefix(allowed_prefix, relative_path, prefix_len);

// Should fail
BOOST_CHECK(rv != 0);
}

BOOST_AUTO_TEST_CASE(test_2_comparePrefix) {
const char *allowed_prefix = "/mnt/storage/globus";
size_t prefix_len = strlen(allowed_prefix);
const char *relative_path = "/";
int rv = comparePrefix(allowed_prefix, relative_path, prefix_len);

// Should fail
BOOST_CHECK(rv != 0);
}

BOOST_AUTO_TEST_CASE(test_3_comparePrefix) {
const char *allowed_prefix = "/mnt/storage/globus";
size_t prefix_len = strlen(allowed_prefix);
const char *relative_path = "/mnt/storage/globus/";
int rv = comparePrefix(allowed_prefix, relative_path, prefix_len);

// Should pass
BOOST_CHECK(rv == 0);
}

BOOST_AUTO_TEST_CASE(test_4_comparePrefix) {
const char *allowed_prefix = "/mnt/storage/globus";
size_t prefix_len = strlen(allowed_prefix);
const char *relative_path = "/mnt/storage/globus";
int rv = comparePrefix(allowed_prefix, relative_path, prefix_len);

// Should pass
BOOST_CHECK(rv == 0);
}

BOOST_AUTO_TEST_CASE(test_5_comparePrefix) {
const char *allowed_prefix = "/mnt/storage/globus";
size_t prefix_len = strlen(allowed_prefix);
const char *relative_path = "/mnt/storage/globu";
int rv = comparePrefix(allowed_prefix, relative_path, prefix_len);

// Should fail
BOOST_CHECK(rv != 0);
}

BOOST_AUTO_TEST_SUITE_END()