55
66#include "aws/s3/private/s3_checksums.h"
77#include "aws/s3/private/s3_client_impl.h"
8+ #include <aws/checksums/crc.h>
89#include "aws/s3/private/s3_default_buffer_pool.h"
910#include "aws/s3/private/s3_meta_request_impl.h"
1011#include "aws/s3/private/s3_util.h"
2829#include <aws/testing/stream_tester.h>
2930#include <inttypes.h>
3031
32+ /* Forward declaration for checksum validation callback used in O_DIRECT tests */
33+ void s_s3_test_validate_checksum (
34+ struct aws_s3_meta_request * meta_request ,
35+ const struct aws_s3_meta_request_result * result ,
36+ void * user_data );
37+
3138AWS_TEST_CASE (test_s3_client_create_destroy , s_test_s3_client_create_destroy )
3239static int s_test_s3_client_create_destroy (struct aws_allocator * allocator , void * ctx ) {
3340 (void )ctx ;
@@ -1688,21 +1695,122 @@ static int s_test_s3_get_object_file_path_direct_io(struct aws_allocator *alloca
16881695}
16891696
16901697AWS_TEST_CASE (
1691- test_s3_get_object_file_path_direct_io_to_position ,
1692- s_test_s3_get_object_file_path_direct_io_to_position )
1693- static int s_test_s3_get_object_file_path_direct_io_to_position (struct aws_allocator * allocator , void * ctx ) {
1698+ test_s3_get_object_file_path_direct_io_content_verify ,
1699+ s_test_s3_get_object_file_path_direct_io_content_verify )
1700+ static int s_test_s3_get_object_file_path_direct_io_content_verify (struct aws_allocator * allocator , void * ctx ) {
16941701 (void )ctx ;
16951702
16961703 struct aws_s3_tester tester ;
1697- AWS_ZERO_STRUCT (tester );
16981704 ASSERT_SUCCESS (aws_s3_tester_init (allocator , & tester ));
16991705
17001706 struct aws_s3_tester_client_options client_options = {
17011707 .part_size = MB_TO_BYTES (5 ),
17021708 };
17031709
1710+ struct aws_s3_client * client = NULL ;
1711+ ASSERT_SUCCESS (aws_s3_tester_client_new (& tester , & client_options , & client ));
1712+
1713+ /* Upload with CRC32 checksum */
1714+ struct aws_byte_buf path_buf ;
1715+ AWS_ZERO_STRUCT (path_buf );
1716+ ASSERT_SUCCESS (aws_s3_tester_upload_file_path_init (
1717+ allocator , & path_buf , aws_byte_cursor_from_c_str ("/prefix/round_trip/direct_io_verify.txt" )));
1718+ struct aws_byte_cursor object_path = aws_byte_cursor_from_buf (& path_buf );
1719+
1720+ struct aws_s3_tester_meta_request_options put_options = {
1721+ .allocator = allocator ,
1722+ .meta_request_type = AWS_S3_META_REQUEST_TYPE_PUT_OBJECT ,
1723+ .client = client ,
1724+ .checksum_algorithm = AWS_SCA_CRC32 ,
1725+ .put_options =
1726+ {
1727+ .object_size_mb = 1 ,
1728+ .object_path_override = object_path ,
1729+ },
1730+ };
1731+ ASSERT_SUCCESS (aws_s3_tester_send_meta_request_with_options (& tester , & put_options , NULL ));
1732+
1733+ /* Download with O_DIRECT to a known file path */
1734+ const char * local_file_path = "/tmp/aws_s3_direct_io_crc32_verify" ;
1735+ struct aws_string * host_name =
1736+ aws_s3_tester_build_endpoint_string (allocator , & g_test_bucket_name , & g_test_s3_region );
1737+ struct aws_byte_cursor host_cursor = aws_byte_cursor_from_string (host_name );
1738+ struct aws_http_message * message = aws_s3_test_get_object_request_new (allocator , host_cursor , object_path );
1739+
1740+ struct aws_s3_checksum_config checksum_config = {
1741+ .validate_response_checksum = true,
1742+ };
1743+ struct aws_s3_file_io_options fio_opts = {
1744+ .direct_io = true,
1745+ };
1746+ struct aws_s3_meta_request_options meta_request_options = {
1747+ .type = AWS_S3_META_REQUEST_TYPE_GET_OBJECT ,
1748+ .message = message ,
1749+ .recv_filepath = aws_byte_cursor_from_c_str (local_file_path ),
1750+ .checksum_config = & checksum_config ,
1751+ .fio_opts = & fio_opts ,
1752+ };
1753+
17041754 struct aws_s3_meta_request_test_results meta_request_test_results ;
17051755 aws_s3_meta_request_test_results_init (& meta_request_test_results , allocator );
1756+ ASSERT_SUCCESS (aws_s3_tester_bind_meta_request (& tester , & meta_request_options , & meta_request_test_results ));
1757+
1758+ struct aws_s3_meta_request * meta_request = aws_s3_client_make_meta_request (client , & meta_request_options );
1759+ ASSERT_NOT_NULL (meta_request );
1760+
1761+ aws_s3_tester_wait_for_meta_request_finish (& tester );
1762+ ASSERT_INT_EQUALS (AWS_ERROR_SUCCESS , meta_request_test_results .finished_error_code );
1763+ /* S3 response checksum was validated */
1764+ ASSERT_TRUE (meta_request_test_results .did_validate );
1765+ ASSERT_INT_EQUALS (AWS_SCA_CRC32 , meta_request_test_results .validation_algorithm );
1766+
1767+ aws_s3_meta_request_release (meta_request );
1768+ aws_s3_tester_wait_for_meta_request_shutdown (& tester );
1769+
1770+ /* Read file back from disk and compute CRC32.
1771+ * The tester uploads content using AWS_AUTOGEN_LOREM_IPSUM pattern. */
1772+ size_t expected_size = MB_TO_BYTES (1 );
1773+ struct aws_byte_buf expected_buf ;
1774+ s_byte_buf_init_autogenned (& expected_buf , allocator , expected_size , AWS_AUTOGEN_LOREM_IPSUM );
1775+ uint32_t expected_crc = aws_checksums_crc32 (expected_buf .buffer , (int )expected_buf .len , 0 );
1776+
1777+ FILE * verify_file = aws_fopen (local_file_path , "rb" );
1778+ ASSERT_NOT_NULL (verify_file );
1779+ struct aws_byte_buf file_buf ;
1780+ aws_byte_buf_init (& file_buf , allocator , expected_size );
1781+ file_buf .len = fread (file_buf .buffer , 1 , expected_size , verify_file );
1782+ fclose (verify_file );
1783+
1784+ ASSERT_UINT_EQUALS (expected_size , file_buf .len );
1785+ uint32_t actual_crc = aws_checksums_crc32 (file_buf .buffer , (int )file_buf .len , 0 );
1786+ ASSERT_UINT_EQUALS (expected_crc , actual_crc );
1787+
1788+ /* Cleanup */
1789+ remove (local_file_path );
1790+ aws_byte_buf_clean_up (& file_buf );
1791+ aws_byte_buf_clean_up (& expected_buf );
1792+ aws_s3_meta_request_test_results_clean_up (& meta_request_test_results );
1793+ aws_http_message_release (message );
1794+ aws_string_destroy (host_name );
1795+ aws_byte_buf_clean_up (& path_buf );
1796+ aws_s3_client_release (client );
1797+ aws_s3_tester_clean_up (& tester );
1798+ return 0 ;
1799+ }
1800+
1801+ AWS_TEST_CASE (
1802+ test_s3_get_object_file_path_direct_io_unsupported_append ,
1803+ s_test_s3_get_object_file_path_direct_io_unsupported_append )
1804+ static int s_test_s3_get_object_file_path_direct_io_unsupported_append (struct aws_allocator * allocator , void * ctx ) {
1805+ (void )ctx ;
1806+
1807+ struct aws_s3_tester tester ;
1808+ ASSERT_SUCCESS (aws_s3_tester_init (allocator , & tester ));
1809+
1810+ struct aws_s3_tester_client_options client_options = {
1811+ .part_size = MB_TO_BYTES (5 ),
1812+ };
1813+
17061814 struct aws_s3_client * client = NULL ;
17071815 ASSERT_SUCCESS (aws_s3_tester_client_new (& tester , & client_options , & client ));
17081816
@@ -1711,29 +1819,69 @@ static int s_test_s3_get_object_file_path_direct_io_to_position(struct aws_alloc
17111819 };
17121820
17131821 struct aws_byte_cursor object_path = aws_byte_cursor_from_c_str ("/pre-existing-1MB" );
1714- uint64_t pre_exist_file_length = 10 ;
17151822 struct aws_s3_tester_meta_request_options get_options = {
17161823 .allocator = allocator ,
17171824 .meta_request_type = AWS_S3_META_REQUEST_TYPE_GET_OBJECT ,
1718- .validate_type = AWS_S3_TESTER_VALIDATE_TYPE_EXPECT_SUCCESS ,
1825+ .validate_type = AWS_S3_TESTER_VALIDATE_TYPE_EXPECT_FAILURE ,
1826+ .client = client ,
1827+ .fio_opts = & fio_opts ,
1828+ .get_options =
1829+ {
1830+ .object_path = object_path ,
1831+ .file_on_disk = true,
1832+ .recv_file_option = AWS_S3_RECV_FILE_CREATE_OR_APPEND ,
1833+ },
1834+ };
1835+
1836+ ASSERT_SUCCESS (aws_s3_tester_send_meta_request_with_options (& tester , & get_options , NULL ));
1837+
1838+ aws_s3_client_release (client );
1839+ aws_s3_tester_clean_up (& tester );
1840+ return 0 ;
1841+ }
1842+
1843+ AWS_TEST_CASE (
1844+ test_s3_get_object_file_path_direct_io_unsupported_write_to_position ,
1845+ s_test_s3_get_object_file_path_direct_io_unsupported_write_to_position )
1846+ static int s_test_s3_get_object_file_path_direct_io_unsupported_write_to_position (
1847+ struct aws_allocator * allocator ,
1848+ void * ctx ) {
1849+ (void )ctx ;
1850+
1851+ struct aws_s3_tester tester ;
1852+ ASSERT_SUCCESS (aws_s3_tester_init (allocator , & tester ));
1853+
1854+ struct aws_s3_tester_client_options client_options = {
1855+ .part_size = MB_TO_BYTES (5 ),
1856+ };
1857+
1858+ struct aws_s3_client * client = NULL ;
1859+ ASSERT_SUCCESS (aws_s3_tester_client_new (& tester , & client_options , & client ));
1860+
1861+ struct aws_s3_file_io_options fio_opts = {
1862+ .direct_io = true,
1863+ };
1864+
1865+ struct aws_byte_cursor object_path = aws_byte_cursor_from_c_str ("/pre-existing-1MB" );
1866+ struct aws_s3_tester_meta_request_options get_options = {
1867+ .allocator = allocator ,
1868+ .meta_request_type = AWS_S3_META_REQUEST_TYPE_GET_OBJECT ,
1869+ .validate_type = AWS_S3_TESTER_VALIDATE_TYPE_EXPECT_FAILURE ,
17191870 .client = client ,
17201871 .fio_opts = & fio_opts ,
17211872 .get_options =
17221873 {
17231874 .object_path = object_path ,
17241875 .file_on_disk = true,
17251876 .recv_file_option = AWS_S3_RECV_FILE_WRITE_TO_POSITION ,
1726- .recv_file_position = 20 ,
1727- .pre_exist_file_length = pre_exist_file_length ,
1877+ .recv_file_position = 4096 ,
1878+ .pre_exist_file_length = 10 ,
17281879 },
17291880 };
17301881
1731- ASSERT_SUCCESS (aws_s3_tester_send_meta_request_with_options (& tester , & get_options , & meta_request_test_results ));
1732- ASSERT_UINT_EQUALS (
1733- get_options .get_options .recv_file_position + MB_TO_BYTES (1 ), meta_request_test_results .received_file_size );
1882+ ASSERT_SUCCESS (aws_s3_tester_send_meta_request_with_options (& tester , & get_options , NULL ));
17341883
1735- aws_s3_meta_request_test_results_clean_up (& meta_request_test_results );
1736- client = aws_s3_client_release (client );
1884+ aws_s3_client_release (client );
17371885 aws_s3_tester_clean_up (& tester );
17381886 return 0 ;
17391887}
0 commit comments