diff options
author | Devtools Arcadia <arcadia-devtools@yandex-team.ru> | 2022-02-07 18:08:42 +0300 |
---|---|---|
committer | Devtools Arcadia <arcadia-devtools@mous.vla.yp-c.yandex.net> | 2022-02-07 18:08:42 +0300 |
commit | 1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch) | |
tree | e26c9fed0de5d9873cce7e00bc214573dc2195b7 /util/system/file_ut.cpp | |
download | ydb-1110808a9d39d4b808aef724c861a2e1a38d2a69.tar.gz |
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'util/system/file_ut.cpp')
-rw-r--r-- | util/system/file_ut.cpp | 416 |
1 files changed, 416 insertions, 0 deletions
diff --git a/util/system/file_ut.cpp b/util/system/file_ut.cpp new file mode 100644 index 0000000000..941e6a50f3 --- /dev/null +++ b/util/system/file_ut.cpp @@ -0,0 +1,416 @@ +#include "file.h" +#include "fs.h" +#include "tempfile.h" + +#include <library/cpp/testing/unittest/registar.h> + +#include <util/stream/file.h> +#include <util/generic/yexception.h> + +class TFileTest: public TTestBase { + UNIT_TEST_SUITE(TFileTest); + UNIT_TEST(TestOpen); + UNIT_TEST(TestOpenSync); + UNIT_TEST(TestRW); + UNIT_TEST(TestReWrite); + UNIT_TEST(TestAppend); + UNIT_TEST(TestLinkTo); + UNIT_TEST(TestResize); + UNIT_TEST(TestLocale); + UNIT_TEST(TestFlush); + UNIT_TEST(TestFlushSpecialFile); + UNIT_TEST(TestRawRead); + UNIT_TEST(TestRead); + UNIT_TEST(TestRawPread); + UNIT_TEST(TestPread); + UNIT_TEST(TestCache); + UNIT_TEST_SUITE_END(); + +public: + void TestOpen(); + void TestOpenSync(); + void TestRW(); + void TestLocale(); + void TestFlush(); + void TestFlushSpecialFile(); + void TestRawRead(); + void TestRead(); + void TestRawPread(); + void TestPread(); + void TestCache(); + + inline void TestLinkTo() { + TTempFile tmp1("tmp1"); + TTempFile tmp2("tmp2"); + + { + TFile f1(tmp1.Name(), OpenAlways | WrOnly); + TFile f2(tmp2.Name(), OpenAlways | WrOnly); + + f1.LinkTo(f2); + + f1.Write("12345", 5); + f2.Write("67890", 5); + } + + UNIT_ASSERT_EQUAL(TUnbufferedFileInput(tmp2.Name()).ReadAll(), "1234567890"); + } + + inline void TestAppend() { + TTempFile tmp("tmp"); + + { + TFile f(tmp.Name(), OpenAlways | WrOnly); + + f.Write("12345678", 8); + } + + { + TFile f(tmp.Name(), OpenAlways | WrOnly | ForAppend); + + f.Write("67", 2); + f.Write("89", 2); + } + + UNIT_ASSERT_EQUAL(TUnbufferedFileInput(tmp.Name()).ReadAll(), "123456786789"); + } + + inline void TestReWrite() { + TTempFile tmp("tmp"); + + { + TFile f(tmp.Name(), OpenAlways | WrOnly); + + f.Write("12345678", 8); + } + + { + TFile f(tmp.Name(), OpenAlways | WrOnly); + + f.Write("6789", 4); + } + + UNIT_ASSERT_EQUAL(TUnbufferedFileInput(tmp.Name()).ReadAll(), "67895678"); + } + + inline void TestResize() { + TTempFile tmp("tmp"); + + { + TFile file(tmp.Name(), OpenAlways | WrOnly); + + file.Write("1234567", 7); + file.Seek(3, sSet); + + file.Resize(5); + UNIT_ASSERT_EQUAL(file.GetLength(), 5); + UNIT_ASSERT_EQUAL(file.GetPosition(), 3); + + file.Resize(12); + UNIT_ASSERT_EQUAL(file.GetLength(), 12); + UNIT_ASSERT_EQUAL(file.GetPosition(), 3); + } + + const TString data = TUnbufferedFileInput(tmp.Name()).ReadAll(); + UNIT_ASSERT_EQUAL(data.length(), 12); + UNIT_ASSERT(data.StartsWith("12345")); + } +}; + +UNIT_TEST_SUITE_REGISTRATION(TFileTest); + +void TFileTest::TestOpen() { + TString res; + TFile f1; + + try { + TFile f2("f1.txt", OpenExisting); + } catch (const yexception& e) { + res = e.what(); + } + UNIT_ASSERT(!res.empty()); + res.remove(); + + try { + TFile f2("f1.txt", OpenAlways); + f1 = f2; + } catch (const yexception& e) { + res = e.what(); + } + UNIT_ASSERT(res.empty()); + UNIT_ASSERT(f1.IsOpen()); + UNIT_ASSERT_VALUES_EQUAL(f1.GetName(), "f1.txt"); + UNIT_ASSERT_VALUES_EQUAL(f1.GetLength(), 0); + + try { + TFile f2("f1.txt", CreateNew); + } catch (const yexception& e) { + res = e.what(); + } + UNIT_ASSERT(!res.empty()); + res.remove(); + + f1.Close(); + UNIT_ASSERT(unlink("f1.txt") == 0); +} + +void TFileTest::TestOpenSync() { + TFile f1("f1.txt", CreateNew | Sync); + UNIT_ASSERT(f1.IsOpen()); + f1.Close(); + UNIT_ASSERT(!f1.IsOpen()); + UNIT_ASSERT(unlink("f1.txt") == 0); +} + +void TFileTest::TestRW() { + TFile f1("f1.txt", CreateNew); + UNIT_ASSERT(f1.IsOpen()); + UNIT_ASSERT_VALUES_EQUAL(f1.GetName(), "f1.txt"); + UNIT_ASSERT_VALUES_EQUAL(f1.GetLength(), 0); + ui32 d[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + f1.Write(&d, sizeof(ui32) * 10); + UNIT_ASSERT_VALUES_EQUAL(f1.GetLength(), 40); + UNIT_ASSERT_VALUES_EQUAL(f1.GetPosition(), 40); + UNIT_ASSERT_VALUES_EQUAL(f1.Seek(12, sSet), 12); + f1.Flush(); + ui32 v; + f1.Load(&v, sizeof(v)); + UNIT_ASSERT_VALUES_EQUAL(v, 3u); + UNIT_ASSERT_VALUES_EQUAL(f1.GetPosition(), 16); + + TFile f2 = f1; + UNIT_ASSERT(f2.IsOpen()); + UNIT_ASSERT_VALUES_EQUAL(f2.GetName(), "f1.txt"); + UNIT_ASSERT_VALUES_EQUAL(f2.GetPosition(), 16); + UNIT_ASSERT_VALUES_EQUAL(f2.GetLength(), 40); + f2.Write(&v, sizeof(v)); + + UNIT_ASSERT_VALUES_EQUAL(f1.GetPosition(), 20); + UNIT_ASSERT_VALUES_EQUAL(f1.Seek(-4, sCur), 16); + v = 0; + f1.Load(&v, sizeof(v)); + UNIT_ASSERT_VALUES_EQUAL(v, 3u); + f1.Close(); + UNIT_ASSERT(!f1.IsOpen()); + UNIT_ASSERT(!f2.IsOpen()); + UNIT_ASSERT(unlink("f1.txt") == 0); +} + +#ifdef _unix_ + #include <locale.h> +#endif + +void TFileTest::TestLocale() { +#ifdef _unix_ + const char* loc = setlocale(LC_CTYPE, nullptr); + setlocale(LC_CTYPE, "ru_RU.UTF-8"); +#endif + TFile f("Имя.txt", CreateNew); + UNIT_ASSERT(f.IsOpen()); + UNIT_ASSERT_VALUES_EQUAL(f.GetName(), "Имя.txt"); + UNIT_ASSERT_VALUES_EQUAL(f.GetLength(), 0); + f.Close(); + UNIT_ASSERT(NFs::Remove("Имя.txt")); +#ifdef _unix_ + setlocale(LC_CTYPE, loc); +#endif +} + +void TFileTest::TestFlush() { + TTempFile tmp("tmp"); + + { + TFile f(tmp.Name(), OpenAlways | WrOnly); + f.Flush(); + f.FlushData(); + f.Close(); + + UNIT_ASSERT_EXCEPTION(f.Flush(), TFileError); + UNIT_ASSERT_EXCEPTION(f.FlushData(), TFileError); + } +} + +void TFileTest::TestFlushSpecialFile() { +#ifdef _unix_ + TFile devNull("/dev/null", WrOnly); + devNull.FlushData(); + devNull.Flush(); + devNull.Close(); +#endif +} + +void TFileTest::TestRawRead() { + TTempFile tmp("tmp"); + + { + TFile file(tmp.Name(), OpenAlways | WrOnly); + file.Write("1234567", 7); + file.Flush(); + file.Close(); + } + + { + TFile file(tmp.Name(), OpenExisting | RdOnly); + char buf[7]; + i32 reallyRead = file.RawRead(buf, 7); + Y_ENSURE(0 <= reallyRead && reallyRead <= 7); + Y_ENSURE(TStringBuf(buf, reallyRead) == TStringBuf("1234567").Head(reallyRead)); + } +} + +void TFileTest::TestRead() { + TTempFile tmp("tmp"); + + { + TFile file(tmp.Name(), OpenAlways | WrOnly); + file.Write("1234567", 7); + file.Flush(); + file.Close(); + } + + { + TFile file(tmp.Name(), OpenExisting | RdOnly); + char buf[7]; + Y_ENSURE(file.Read(buf, 7) == 7); + Y_ENSURE(TStringBuf(buf, 7) == "1234567"); + + memset(buf, 0, sizeof(buf)); + file.Seek(0, sSet); + Y_ENSURE(file.Read(buf, 123) == 7); + Y_ENSURE(TStringBuf(buf, 7) == "1234567"); + } +} + +void TFileTest::TestRawPread() { + TTempFile tmp("tmp"); + + { + TFile file(tmp.Name(), OpenAlways | WrOnly); + file.Write("1234567", 7); + file.Flush(); + file.Close(); + } + + { + TFile file(tmp.Name(), OpenExisting | RdOnly); + char buf[7]; + i32 reallyRead = file.RawPread(buf, 3, 1); + Y_ENSURE(0 <= reallyRead && reallyRead <= 3); + Y_ENSURE(TStringBuf(buf, reallyRead) == TStringBuf("234").Head(reallyRead)); + + memset(buf, 0, sizeof(buf)); + reallyRead = file.RawPread(buf, 2, 5); + Y_ENSURE(0 <= reallyRead && reallyRead <= 2); + Y_ENSURE(TStringBuf(buf, reallyRead) == TStringBuf("67").Head(reallyRead)); + } +} + +void TFileTest::TestPread() { + TTempFile tmp("tmp"); + + { + TFile file(tmp.Name(), OpenAlways | WrOnly); + file.Write("1234567", 7); + file.Flush(); + file.Close(); + } + + { + TFile file(tmp.Name(), OpenExisting | RdOnly); + char buf[7]; + Y_ENSURE(file.Pread(buf, 3, 1) == 3); + Y_ENSURE(TStringBuf(buf, 3) == "234"); + + memset(buf, 0, sizeof(buf)); + Y_ENSURE(file.Pread(buf, 2, 5) == 2); + Y_ENSURE(TStringBuf(buf, 2) == "67"); + } +} + +#ifdef _linux_ + #include <sys/statfs.h> +#endif + +#ifndef TMPFS_MAGIC + #define TMPFS_MAGIC 0x01021994 +#endif + +void TFileTest::TestCache(){ +#ifdef _linux_ + {// create file in /tmp, current dir could be tmpfs which does not support fadvise + TFile file(MakeTempName("/tmp"), OpenAlways | Transient | RdWr | NoReadAhead); + +struct statfs fs; +if (!fstatfs(file.GetHandle(), &fs) && fs.f_type == TMPFS_MAGIC) { + return; +} + +UNIT_ASSERT_VALUES_EQUAL(file.CountCache(), 0); +UNIT_ASSERT_VALUES_EQUAL(file.CountCache(0, 0), 0); + +file.Resize(7); +file.PrefetchCache(); +UNIT_ASSERT_VALUES_EQUAL(file.CountCache(), 7); +UNIT_ASSERT_VALUES_EQUAL(file.CountCache(3, 2), 2); + +file.FlushCache(); +UNIT_ASSERT_VALUES_EQUAL(file.CountCache(), 7); + +file.EvictCache(); +UNIT_ASSERT_VALUES_EQUAL(file.CountCache(), 0); + +file.PrefetchCache(); +UNIT_ASSERT_VALUES_EQUAL(file.CountCache(), 7); + +file.Resize(12345); +UNIT_ASSERT_VALUES_EQUAL(file.CountCache(), 4096); +UNIT_ASSERT_VALUES_EQUAL(file.CountCache(4096, 0), 0); + +file.PrefetchCache(); +UNIT_ASSERT_VALUES_EQUAL(file.CountCache(), 12345); + +file.FlushCache(); +file.EvictCache(); +UNIT_ASSERT_LE(file.CountCache(), 0); + +file.Resize(33333333); +file.PrefetchCache(11111111, 11111111); +UNIT_ASSERT_GE(file.CountCache(), 11111111); + +UNIT_ASSERT_LE(file.CountCache(0, 11111111), 1111111); +UNIT_ASSERT_VALUES_EQUAL(file.CountCache(11111111, 11111111), 11111111); +UNIT_ASSERT_LE(file.CountCache(22222222, 11111111), 1111111); + +file.FlushCache(11111111, 11111111); +UNIT_ASSERT_GE(file.CountCache(), 11111111); + +// first and last incomplete pages could stay in cache +file.EvictCache(11111111, 11111111); +UNIT_ASSERT_LT(file.CountCache(11111111, 11111111), 4096 * 2); + +file.EvictCache(); +UNIT_ASSERT_VALUES_EQUAL(file.CountCache(), 0); +} +#else + {TFile file(MakeTempName(), OpenAlways | Transient | RdWr); + +file.Resize(12345); + +UNIT_ASSERT_VALUES_EQUAL(file.CountCache(), -1); +file.PrefetchCache(); +file.FlushCache(); +file.EvictCache(); +UNIT_ASSERT_VALUES_EQUAL(file.CountCache(0, 12345), -1); +} +#endif +} + +Y_UNIT_TEST_SUITE(TTestDecodeOpenMode) { + Y_UNIT_TEST(It) { + UNIT_ASSERT_VALUES_EQUAL("0", DecodeOpenMode(0)); + UNIT_ASSERT_VALUES_EQUAL("RdOnly", DecodeOpenMode(RdOnly)); + UNIT_ASSERT_VALUES_EQUAL("RdWr", DecodeOpenMode(RdWr)); + UNIT_ASSERT_VALUES_EQUAL("WrOnly|ForAppend", DecodeOpenMode(WrOnly | ForAppend)); + UNIT_ASSERT_VALUES_EQUAL("RdWr|CreateAlways|CreateNew|ForAppend|Transient|CloseOnExec|Temp|Sync|Direct|DirectAligned|Seq|NoReuse|NoReadAhead|AX|AR|AW|AWOther|0xF8888000", DecodeOpenMode(0xFFFFFFFF)); + } +} |