diff options
| -rw-r--r-- | netfs/fuse/fuseFiles.cpp | 25 | ||||
| -rw-r--r-- | netfs/fuse/fuseFiles.h | 14 | ||||
| -rw-r--r-- | netfs/unittests/testEdgeCases.cpp | 68 | 
3 files changed, 107 insertions, 0 deletions
diff --git a/netfs/fuse/fuseFiles.cpp b/netfs/fuse/fuseFiles.cpp index 3ecb37f..a44f56e 100644 --- a/netfs/fuse/fuseFiles.cpp +++ b/netfs/fuse/fuseFiles.cpp @@ -210,6 +210,31 @@ namespace NetFS {  		}  	} +	FuseApp::OpenFile::BlockSizes +	FuseApp::OpenFile::blockSizes(size_t total, size_t max) noexcept +	{ +		if (max >= total) { // Simple case, all in remainder block +			return {total, 0, 0}; +		} +		else if (total % max == 0) { // Simplish case, multiples of max +			return {0, max, total / max}; +		} +		else { +			const auto blocks = (total / max); +			const auto blockSize = (total / (blocks + 1)) + 1; +			const auto batchTotal = blockSize * blocks; +			const auto remainder = total - batchTotal; + +			return {remainder, blockSize, blocks}; +		} +	} + +	size_t +	FuseApp::OpenFile::BlockSizes::total() const noexcept +	{ +		return size1 + (sizeN * N); +	} +  	ssize_t  	FuseApp::copy_file_range(const char *, struct fuse_file_info * fi_in, off_t offset_in, const char *,  			struct fuse_file_info * fi_out, off_t offset_out, size_t size, int flags) diff --git a/netfs/fuse/fuseFiles.h b/netfs/fuse/fuseFiles.h index 37e3dec..087e1ee 100644 --- a/netfs/fuse/fuseFiles.h +++ b/netfs/fuse/fuseFiles.h @@ -11,6 +11,20 @@ namespace NetFS {  		void flush();  		void wait() const; +		struct BlockSizes { +			size_t size1, sizeN, N; +			auto operator<=>(const BlockSizes &) const = default; +			[[nodiscard]] size_t total() const noexcept; +		}; + +		[[nodiscard]] static BlockSizes blockSizes(size_t total, size_t max) noexcept; + +		[[nodiscard]] auto +		blockSizes(size_t total) const noexcept +		{ +			return blockSizes(total, bodyMaxSize); +		} +  		FilePrxPtr remote;  		const std::string path;  		const int flags; diff --git a/netfs/unittests/testEdgeCases.cpp b/netfs/unittests/testEdgeCases.cpp index 5249aed..f47ecd4 100644 --- a/netfs/unittests/testEdgeCases.cpp +++ b/netfs/unittests/testEdgeCases.cpp @@ -1,6 +1,9 @@  #define BOOST_TEST_MODULE TestNetFSEdgeCases + +#include "fuseFiles.h"  #include "mockDaemon.h"  #include "mockFuse.h" +#include <boost/test/data/test_case.hpp>  #include <boost/test/unit_test.hpp>  #include <definedDirs.h>  #include <random> @@ -121,6 +124,71 @@ BOOST_AUTO_TEST_CASE(manyThreads)  	BOOST_CHECK_EQUAL(failure, 0);  } +namespace std { +	ostream & +	operator<<(ostream & s, const FuseMock::OpenFile::BlockSizes & b) +	{ +		return s << '(' << b.size1 << '+' << b.sizeN << '*' << b.N << ')'; +	} +} + +BOOST_AUTO_TEST_CASE(blockSizes) +{ +	using BS = NetFS::FuseApp::OpenFile::BlockSizes; +	BOOST_CHECK_EQUAL(NetFS::FuseApp::OpenFile::blockSizes(1, 1), (BS {1, 0, 0})); +	BOOST_CHECK_EQUAL(NetFS::FuseApp::OpenFile::blockSizes(1, 5), (BS {1, 0, 0})); +	BOOST_CHECK_EQUAL(NetFS::FuseApp::OpenFile::blockSizes(5, 5), (BS {5, 0, 0})); +	BOOST_CHECK_EQUAL(NetFS::FuseApp::OpenFile::blockSizes(0, 1), (BS {0, 0, 0})); +	BOOST_CHECK_EQUAL(NetFS::FuseApp::OpenFile::blockSizes(5, 2), (BS {1, 2, 2})); +	BOOST_CHECK_EQUAL(NetFS::FuseApp::OpenFile::blockSizes(5, 3), (BS {2, 3, 1})); +	BOOST_CHECK_EQUAL(NetFS::FuseApp::OpenFile::blockSizes(29, 10), (BS {9, 10, 2})); +	BOOST_CHECK_EQUAL(NetFS::FuseApp::OpenFile::blockSizes(30, 10), (BS {0, 10, 3})); +	BOOST_CHECK_EQUAL(NetFS::FuseApp::OpenFile::blockSizes(31, 10), (BS {7, 8, 3})); +	BOOST_CHECK_EQUAL(NetFS::FuseApp::OpenFile::blockSizes(32, 10), (BS {5, 9, 3})); +	BOOST_CHECK_EQUAL(NetFS::FuseApp::OpenFile::blockSizes(33, 10), (BS {6, 9, 3})); +	BOOST_CHECK_EQUAL(NetFS::FuseApp::OpenFile::blockSizes(34, 10), (BS {7, 9, 3})); +	BOOST_CHECK_EQUAL(NetFS::FuseApp::OpenFile::blockSizes(35, 10), (BS {8, 9, 3})); +	BOOST_CHECK_EQUAL(NetFS::FuseApp::OpenFile::blockSizes(36, 10), (BS {6, 10, 3})); +	BOOST_CHECK_EQUAL(NetFS::FuseApp::OpenFile::blockSizes(37, 10), (BS {7, 10, 3})); +	BOOST_CHECK_EQUAL(NetFS::FuseApp::OpenFile::blockSizes(38, 10), (BS {8, 10, 3})); +	BOOST_CHECK_EQUAL(NetFS::FuseApp::OpenFile::blockSizes(39, 10), (BS {9, 10, 3})); +	BOOST_CHECK_EQUAL(NetFS::FuseApp::OpenFile::blockSizes(40, 10), (BS {0, 10, 4})); +	BOOST_CHECK_EQUAL(NetFS::FuseApp::OpenFile::blockSizes(41, 10), (BS {5, 9, 4})); +	BOOST_CHECK_EQUAL(NetFS::FuseApp::OpenFile::blockSizes(1234, 100), (BS {94, 95, 12})); +	BOOST_CHECK_EQUAL(NetFS::FuseApp::OpenFile::blockSizes(1235, 100), (BS {83, 96, 12})); +	BOOST_CHECK_EQUAL(NetFS::FuseApp::OpenFile::blockSizes(1236, 100), (BS {84, 96, 12})); +	BOOST_CHECK_EQUAL(NetFS::FuseApp::OpenFile::blockSizes(1237, 100), (BS {85, 96, 12})); +	BOOST_CHECK_EQUAL(NetFS::FuseApp::OpenFile::blockSizes(1238, 100), (BS {86, 96, 12})); +	BOOST_CHECK_EQUAL(NetFS::FuseApp::OpenFile::blockSizes(1239, 100), (BS {87, 96, 12})); +	BOOST_CHECK_EQUAL(NetFS::FuseApp::OpenFile::blockSizes(1240, 100), (BS {88, 96, 12})); +	BOOST_CHECK_EQUAL(NetFS::FuseApp::OpenFile::blockSizes(1241, 100), (BS {89, 96, 12})); +} + +BOOST_DATA_TEST_CASE(blockSizes_range, +		boost::unit_test::data::xrange<size_t>(1, 200) +				* boost::unit_test::data::make<size_t>({1, 5, 10, 16, 32, 256, 1024}), +		total, max) +{ +	const auto bs = NetFS::FuseApp::OpenFile::blockSizes(total, max); +	BOOST_CHECK_LE(bs.size1, max); +	BOOST_CHECK_LE(bs.sizeN, max); +	BOOST_CHECK_EQUAL(bs.total(), total); +	BOOST_CHECK_NE(bs.size1, bs.sizeN); +} + +BOOST_DATA_TEST_CASE(blockSizes_scatter, +		(boost::unit_test::data::xrange<size_t>(1, 200, 17LU) + boost::unit_test::data::xrange<size_t>(1200, 1300, 3LU)) +				* (boost::unit_test::data::xrange<size_t>(1, 100) +						+ boost::unit_test::data::xrange<size_t>(256, 4096, 256LU)), +		total, max) +{ +	const auto bs = NetFS::FuseApp::OpenFile::blockSizes(total, max); +	BOOST_CHECK_LE(bs.size1, max); +	BOOST_CHECK_LE(bs.sizeN, max); +	BOOST_CHECK_EQUAL(bs.total(), total); +	BOOST_CHECK_NE(bs.size1, bs.sizeN); +} +  BOOST_AUTO_TEST_CASE(bigWritesAsync)  {  	MockDaemonHost daemon(testEndpoint, {"--NetFSD.ConfigPath=" + (rootDir / "defaultDaemon.xml").string()});  | 
