summaryrefslogtreecommitdiffstats
path: root/util/system/direct_io_ut.cpp
diff options
context:
space:
mode:
authorDevtools Arcadia <[email protected]>2022-02-07 18:08:42 +0300
committerDevtools Arcadia <[email protected]>2022-02-07 18:08:42 +0300
commit1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch)
treee26c9fed0de5d9873cce7e00bc214573dc2195b7 /util/system/direct_io_ut.cpp
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'util/system/direct_io_ut.cpp')
-rw-r--r--util/system/direct_io_ut.cpp115
1 files changed, 115 insertions, 0 deletions
diff --git a/util/system/direct_io_ut.cpp b/util/system/direct_io_ut.cpp
new file mode 100644
index 00000000000..839c3de7ca4
--- /dev/null
+++ b/util/system/direct_io_ut.cpp
@@ -0,0 +1,115 @@
+#include <library/cpp/testing/unittest/registar.h>
+
+#include <util/generic/yexception.h>
+#include <util/system/fs.h>
+#include <util/system/tempfile.h>
+#include <util/random/random.h>
+
+#include "direct_io.h"
+
+static const char* FileName_("./test.file");
+
+Y_UNIT_TEST_SUITE(TDirectIoTestSuite) {
+ Y_UNIT_TEST(TestDirectFile) {
+ TDirectIOBufferedFile file(FileName_, RdWr | Direct | Seq | CreateAlways, 1 << 15);
+ TVector<ui64> data((1 << 15) + 1);
+ TVector<ui64> readResult(data.size());
+ for (auto& i : data) {
+ i = RandomNumber<ui64>();
+ }
+ for (size_t writePos = 0; writePos < data.size();) {
+ size_t writeCount = Min<size_t>(1 + RandomNumber<size_t>(1 << 10), data.ysize() - writePos);
+ file.Write(&data[writePos], sizeof(ui64) * writeCount);
+ writePos += writeCount;
+ size_t readPos = RandomNumber(writePos);
+ size_t readCount = RandomNumber(writePos - readPos);
+ UNIT_ASSERT_VALUES_EQUAL(
+ file.Pread(&readResult[0], readCount * sizeof(ui64), readPos * sizeof(ui64)),
+ readCount * sizeof(ui64));
+ for (size_t i = 0; i < readCount; ++i) {
+ UNIT_ASSERT_VALUES_EQUAL(readResult[i], data[i + readPos]);
+ }
+ }
+ file.Finish();
+ TDirectIOBufferedFile fileNew(FileName_, RdOnly | Direct | Seq | OpenAlways, 1 << 15);
+ for (int i = 0; i < 1000; ++i) {
+ size_t readPos = RandomNumber(data.size());
+ size_t readCount = RandomNumber(data.size() - readPos);
+ UNIT_ASSERT_VALUES_EQUAL(
+ fileNew.Pread(&readResult[0], readCount * sizeof(ui64), readPos * sizeof(ui64)),
+ readCount * sizeof(ui64));
+ for (size_t j = 0; j < readCount; ++j) {
+ UNIT_ASSERT_VALUES_EQUAL(readResult[j], data[j + readPos]);
+ }
+ }
+ size_t readCount = data.size();
+ UNIT_ASSERT_VALUES_EQUAL(
+ fileNew.Pread(&readResult[0], readCount * sizeof(ui64), 0),
+ readCount * sizeof(ui64));
+ for (size_t i = 0; i < readCount; ++i) {
+ UNIT_ASSERT_VALUES_EQUAL(readResult[i], data[i]);
+ }
+ NFs::Remove(FileName_);
+ }
+
+ void TestHugeFile(size_t size) {
+ TTempFile tmpFile("test.file");
+
+ {
+ TDirectIOBufferedFile directIOFile(tmpFile.Name(), WrOnly | CreateAlways | Direct);
+ TVector<ui8> data(size, 'x');
+ directIOFile.Write(&data[0], data.size());
+ }
+
+ {
+ TDirectIOBufferedFile directIOFile(tmpFile.Name(), RdOnly | Direct);
+ TVector<ui8> data(size + 1, 'y');
+
+ const size_t readResult = directIOFile.Read(&data[0], data.size());
+
+ UNIT_ASSERT_VALUES_EQUAL(readResult, size);
+
+ UNIT_ASSERT_VALUES_EQUAL(data[0], 'x');
+ UNIT_ASSERT_VALUES_EQUAL(data[size / 2], 'x');
+ UNIT_ASSERT_VALUES_EQUAL(data[size - 1], 'x');
+ UNIT_ASSERT_VALUES_EQUAL(data[size], 'y');
+ }
+ }
+
+ Y_UNIT_TEST(TestHugeFile1) {
+ if constexpr (sizeof(size_t) > 4) {
+ TestHugeFile(5 * 1024 * 1024 * 1024ULL);
+ }
+ }
+ Y_UNIT_TEST(TestHugeFile2) {
+ if constexpr (sizeof(size_t) > 4) {
+ TestHugeFile(5 * 1024 * 1024 * 1024ULL + 1111);
+ }
+ }
+}
+
+Y_UNIT_TEST_SUITE(TDirectIoErrorHandling) {
+ Y_UNIT_TEST(Constructor) {
+ // A non-existent file should not be opened for reading
+ UNIT_ASSERT_EXCEPTION(TDirectIOBufferedFile(FileName_, RdOnly, 1 << 15), TFileError);
+ }
+
+ Y_UNIT_TEST(WritingReadOnlyFileBufferFlushed) {
+ // Note the absence of Direct
+ TDirectIOBufferedFile file(FileName_, RdOnly | OpenAlways, 1);
+ TString buffer = "Hello";
+ UNIT_ASSERT_EXCEPTION(file.Write(buffer.data(), buffer.size()), TFileError);
+ NFs::Remove(FileName_);
+ }
+
+ Y_UNIT_TEST(WritingReadOnlyFileAllInBuffer) {
+ TDirectIOBufferedFile file(FileName_, RdOnly | Direct | Seq | OpenAlways, 1 << 15);
+ TString buffer = "Hello";
+
+ // Doesn't throw because of buffering.
+ file.Write(buffer.data(), buffer.size());
+
+ UNIT_ASSERT_EXCEPTION(file.Finish(), TFileError);
+ NFs::Remove(FileName_);
+ }
+}