@@ -1301,7 +1301,7 @@ test_oversize (void)
1301
1301
ASSERT_ERROR_CONTAINS (error ,
1302
1302
MONGOC_ERROR_GRIDFS ,
1303
1303
MONGOC_ERROR_GRIDFS_CORRUPT ,
1304
- "corrupt chunk number 0: bad size" );
1304
+ "corrupt chunk number 0: greater than chunk size" );
1305
1305
1306
1306
mongoc_gridfs_file_destroy (file );
1307
1307
ASSERT_OR_PRINT (mongoc_gridfs_drop (gridfs , & error ), error );
@@ -1584,6 +1584,156 @@ test_write_failure (void)
1584
1584
mock_server_destroy (server );
1585
1585
}
1586
1586
1587
+ static void
1588
+ test_reading_multiple_chunks (void )
1589
+ {
1590
+ mongoc_client_t * client = test_framework_new_default_client ();
1591
+ bson_error_t error ;
1592
+
1593
+ // Test reading a file spanning two chunks.
1594
+ {
1595
+ mongoc_gridfs_t * gridfs = mongoc_client_get_gridfs (
1596
+ client , "test_reading_multiple_chunks" , NULL , & error );
1597
+
1598
+ ASSERT_OR_PRINT (gridfs , error );
1599
+ // Drop prior test data.
1600
+ ASSERT_OR_PRINT (mongoc_gridfs_drop (gridfs , & error ), error );
1601
+
1602
+ // Write a file spanning two chunks.
1603
+ {
1604
+ mongoc_gridfs_file_opt_t opts = {.chunk_size = 4 ,
1605
+ .filename = "test_file" };
1606
+ mongoc_iovec_t iov = {.iov_base = (void * ) "foobar" , .iov_len = 7 };
1607
+ mongoc_gridfs_file_t * file = mongoc_gridfs_create_file (gridfs , & opts );
1608
+ // First chunk is 4 bytes: "foob", second chunk is 3 bytes: "ar\0"
1609
+ ASSERT_CMPSSIZE_T (
1610
+ mongoc_gridfs_file_writev (file , & iov , 1 , 0 ), = = , 7 );
1611
+ BSON_ASSERT (mongoc_gridfs_file_save (file ));
1612
+ mongoc_gridfs_file_destroy (file );
1613
+ }
1614
+
1615
+ // Read the entire file.
1616
+ {
1617
+ bson_string_t * str = bson_string_new ("" );
1618
+ uint8_t buf [7 ] = {0 };
1619
+ mongoc_iovec_t iov = {.iov_base = (void * ) buf ,
1620
+ .iov_len = sizeof (buf )};
1621
+ mongoc_gridfs_file_t * file =
1622
+ mongoc_gridfs_find_one_by_filename (gridfs , "test_file" , & error );
1623
+ ASSERT_OR_PRINT (file , error );
1624
+
1625
+ // First read gets first chunk.
1626
+ {
1627
+ ssize_t got = mongoc_gridfs_file_readv (file ,
1628
+ & iov ,
1629
+ 1 /* iovcnt */ ,
1630
+ 1 /* min_bytes */ ,
1631
+ 0 /* timeout_msec */ );
1632
+ ASSERT_CMPSSIZE_T (got , >=, 0 );
1633
+ ASSERT (bson_in_range_int_signed (got ));
1634
+ bson_string_append_printf (str , "%.*s" , (int ) got , (char * ) buf );
1635
+ ASSERT_CMPSSIZE_T (got , = = , 4 );
1636
+ }
1637
+
1638
+ // Second read gets second chunk.
1639
+ {
1640
+ ssize_t got = mongoc_gridfs_file_readv (file ,
1641
+ & iov ,
1642
+ 1 /* iovcnt */ ,
1643
+ 1 /* min_bytes */ ,
1644
+ 0 /* timeout_msec */ );
1645
+ ASSERT_CMPSSIZE_T (got , >=, 0 );
1646
+ ASSERT (bson_in_range_int_signed (got ));
1647
+ bson_string_append_printf (str , "%.*s" , (int ) got , (char * ) buf );
1648
+ ASSERT_CMPSSIZE_T (got , = = , 3 );
1649
+ }
1650
+
1651
+ ASSERT_CMPSTR (str -> str , "foobar" );
1652
+ bson_string_free (str , true);
1653
+ mongoc_gridfs_file_destroy (file );
1654
+ }
1655
+
1656
+ mongoc_gridfs_destroy (gridfs );
1657
+ }
1658
+
1659
+ // Test an error occurs if reading an incomplete chunk. This is a regression
1660
+ // test for CDRIVER-5506.
1661
+ {
1662
+ mongoc_gridfs_t * gridfs = mongoc_client_get_gridfs (
1663
+ client , "test_reading_multiple_chunks" , NULL , & error );
1664
+
1665
+ ASSERT_OR_PRINT (gridfs , error );
1666
+ // Drop prior test data.
1667
+ ASSERT_OR_PRINT (mongoc_gridfs_drop (gridfs , & error ), error );
1668
+
1669
+ // Write a file spanning two chunks.
1670
+ {
1671
+ mongoc_gridfs_file_opt_t opts = {.chunk_size = 4 ,
1672
+ .filename = "test_file" };
1673
+ mongoc_iovec_t iov = {.iov_base = (void * ) "foobar" , .iov_len = 7 };
1674
+ mongoc_gridfs_file_t * file = mongoc_gridfs_create_file (gridfs , & opts );
1675
+ // First chunk is 4 bytes: "foob", second chunk is 3 bytes: "ar\0"
1676
+ ASSERT_CMPSSIZE_T (
1677
+ mongoc_gridfs_file_writev (file , & iov , 1 , 0 ), = = , 7 );
1678
+ BSON_ASSERT (mongoc_gridfs_file_save (file ));
1679
+ mongoc_gridfs_file_destroy (file );
1680
+ }
1681
+
1682
+ // Manually remove data from the first chunk.
1683
+ {
1684
+ mongoc_collection_t * coll = mongoc_client_get_collection (
1685
+ client , "test_reading_multiple_chunks" , "fs.chunks" );
1686
+ bson_t reply ;
1687
+ // Change the data of the first chunk from "foob" to "foo".
1688
+ bool ok = mongoc_collection_update_one (
1689
+ coll ,
1690
+ tmp_bson (BSON_STR ({"n" : 0 })),
1691
+ tmp_bson (BSON_STR ({
1692
+ "$set" :
1693
+ {"data" : {"$binary" : {"base64" : "Zm9v ", " subType " : " 0 "}}}
1694
+ })),
1695
+ NULL /* opts */ ,
1696
+ & reply ,
1697
+ & error );
1698
+ ASSERT_OR_PRINT (ok , error );
1699
+ ASSERT_MATCH (& reply , BSON_STR ({"modifiedCount" : 1 }));
1700
+ mongoc_collection_destroy (coll );
1701
+ }
1702
+
1703
+ // Attempt to read the entire file.
1704
+ {
1705
+ uint8_t buf [7 ] = {0 };
1706
+ mongoc_iovec_t iov = {.iov_base = (void * ) buf ,
1707
+ .iov_len = sizeof (buf )};
1708
+ mongoc_gridfs_file_t * file =
1709
+ mongoc_gridfs_find_one_by_filename (gridfs , "test_file" , & error );
1710
+ ASSERT_OR_PRINT (file , error );
1711
+
1712
+ // First read gets an error.
1713
+ {
1714
+ ssize_t got = mongoc_gridfs_file_readv (file ,
1715
+ & iov ,
1716
+ 1 /* iovcnt */ ,
1717
+ 1 /* min_bytes */ ,
1718
+ 0 /* timeout_msec */ );
1719
+ ASSERT_CMPSSIZE_T (got , = = , -1 );
1720
+ ASSERT (mongoc_gridfs_file_error (file , & error ));
1721
+ ASSERT_ERROR_CONTAINS (
1722
+ error ,
1723
+ MONGOC_ERROR_GRIDFS ,
1724
+ MONGOC_ERROR_GRIDFS_CORRUPT ,
1725
+ "corrupt chunk number 0: not equal to chunk size: 4" );
1726
+ }
1727
+
1728
+ mongoc_gridfs_file_destroy (file );
1729
+ }
1730
+
1731
+ mongoc_gridfs_destroy (gridfs );
1732
+ }
1733
+
1734
+ mongoc_client_destroy (client );
1735
+ }
1736
+
1587
1737
1588
1738
void
1589
1739
test_gridfs_install (TestSuite * suite )
@@ -1628,4 +1778,7 @@ test_gridfs_install (TestSuite *suite)
1628
1778
suite , "/gridfs_old/inherit_client_config" , test_inherit_client_config );
1629
1779
TestSuite_AddMockServerTest (
1630
1780
suite , "/gridfs_old/write_failure" , test_write_failure );
1781
+ TestSuite_AddLive (suite ,
1782
+ "/gridfs_old/reading_multiple_chunks" ,
1783
+ test_reading_multiple_chunks );
1631
1784
}
0 commit comments