diff --git a/cloud/filestore/apps/client/lib/ls.cpp b/cloud/filestore/apps/client/lib/ls.cpp index f64124d8f7..e1a91937b8 100644 --- a/cloud/filestore/apps/client/lib/ls.cpp +++ b/cloud/filestore/apps/client/lib/ls.cpp @@ -18,7 +18,6 @@ namespace { //////////////////////////////////////////////////////////////////////////////// const TString NameColumnName = "Name"; -constexpr int NameColumnIndex = NProto::TNodeAttr::kModeFieldNumber - 1; using TNodeId = ui64; @@ -61,6 +60,7 @@ TString FileStateModeToString(ui32 mode) mode & S_IROTH ? 'r' : '-', mode & S_IWOTH ? 'w' : '-', mode & S_IXOTH ? 'x' : '-', + '\0', }; return permissions; } @@ -99,6 +99,20 @@ TString NodeTypeToString(NProto::ENodeType nodeType) } } +const TVector NodeInfoColumns = { + "Id", + "Type", + "Name", + "Mode", + "Uid", + "Gid", + "ATime", + "MTime", + "CTime", + "Size", + "Links", +}; + TVector ToStringVector(const TNodeInfo& nodeInfo) { const auto& node = nodeInfo.Node; @@ -119,12 +133,7 @@ TVector ToStringVector(const TNodeInfo& nodeInfo) NTextTable::TTextTable ToTextTable(const TVector& nodes) { - auto columns = NTextTable::ToColumns(); - columns.emplace( - columns.begin() + NameColumnIndex, - NameColumnName, - NameColumnName.size() - ); + auto columns = NTextTable::ToColumns(NodeInfoColumns); NTextTable::TTextTable table{std::move(columns)}; diff --git a/cloud/filestore/apps/client/lib/text_table.cpp b/cloud/filestore/apps/client/lib/text_table.cpp index f8702cb5a5..f775d5396e 100644 --- a/cloud/filestore/apps/client/lib/text_table.cpp +++ b/cloud/filestore/apps/client/lib/text_table.cpp @@ -105,29 +105,14 @@ const TTextTable::TColumns& TTextTable::GetColumns() const return Columns; } -TTextTable::TRow ToRow(const ::google::protobuf::Message& message) +TTextTable::TColumns ToColumns(const TVector& columnNames) { - auto descriptor = message.GetDescriptor(); - Y_ENSURE( - descriptor != nullptr, - "Failed to acquire proto node descriptor" - ); - - constexpr i32 expectedNonRepeatedFieldIndex = -1; - - TTextTable::TRow row; - row.reserve(descriptor->field_count()); - for (int i = 0; i < descriptor->field_count(); ++i) { - TString value; - google::protobuf::TextFormat::PrintFieldValueToString( - message, - descriptor->field(i), - expectedNonRepeatedFieldIndex, - &value - ); - row.push_back(std::move(value)); + TTextTable::TColumns columns; + columns.reserve(columnNames.size()); + for (auto field: columnNames) { + columns.emplace_back(field, field.size()); } - return row; + return columns; } } // namespace NCloud::NFileStore::NClient::NTextTable diff --git a/cloud/filestore/apps/client/lib/text_table.h b/cloud/filestore/apps/client/lib/text_table.h index 4415a6aa55..c51392b7ab 100644 --- a/cloud/filestore/apps/client/lib/text_table.h +++ b/cloud/filestore/apps/client/lib/text_table.h @@ -37,27 +37,6 @@ struct TTextTable final const TColumns& GetColumns() const; }; -template requires std::is_base_of_v<::google::protobuf::Message, TProtobufMessage> -TTextTable::TColumns ToColumns() -{ - auto firstNodeDescriptor = TProtobufMessage::GetDescriptor(); - Y_ENSURE( - firstNodeDescriptor != nullptr, - "Failed to acquire proto node descriptor" - ); - - const int fieldsCount = firstNodeDescriptor->field_count(); - - TTextTable::TColumns columns; - columns.reserve(fieldsCount); - for (int i = 0; i < fieldsCount; ++i) { - auto field = firstNodeDescriptor->field(i); - - columns.emplace_back(field->name(), field->name().size()); - } - return columns; -} - -[[maybe_unused]] TTextTable::TRow ToRow(const ::google::protobuf::Message& message); +TTextTable::TColumns ToColumns(const TVector& columnNames); } // namespace NCloud::NFileStore::NClient::NTextTable diff --git a/cloud/filestore/tests/client/canondata/result.json b/cloud/filestore/tests/client/canondata/result.json index a4bc6f8e57..a90d991861 100644 --- a/cloud/filestore/tests/client/canondata/result.json +++ b/cloud/filestore/tests/client/canondata/result.json @@ -14,6 +14,9 @@ "test.test_list_filestores": { "uri": "file://test.test_list_filestores/results.txt" }, + "test.test_ls": { + "uri": "file://test.test_ls/results.txt" + }, "test.test_multitablet_findgarbage": { "uri": "file://test.test_multitablet_findgarbage/results.txt" }, diff --git a/cloud/filestore/tests/client/canondata/test.test_ls/results.txt b/cloud/filestore/tests/client/canondata/test.test_ls/results.txt new file mode 100644 index 0000000000..ce5cda3ab9 --- /dev/null +++ b/cloud/filestore/tests/client/canondata/test.test_ls/results.txt @@ -0,0 +1,10 @@ +Id Type Name Mode Uid Gid ATime MTime CTime Size Links + +Id Type Name Mode Uid Gid ATime MTime CTime Size Links +2 d aaa rwxrwxrwx 0 0 1970-01-01T00:00:00Z 1970-01-01T00:00:00Z 1970-01-01T00:00:00Z 0 1 +Id Type Name Mode Uid Gid ATime MTime CTime Size Links + +Id Type Name Mode Uid Gid ATime MTime CTime Size Links +2 d aaa rwxrwxrwx 0 0 1970-01-01T00:00:00Z 1970-01-01T00:00:00Z 1970-01-01T00:00:00Z 0 1 +3 d bbb rwxrwxrwx 0 0 1970-01-01T00:00:00Z 1970-01-01T00:00:00Z 1970-01-01T00:00:00Z 0 1 +4 f first -wx-wxr-x 10 20 1970-01-01T00:00:00Z 1970-01-01T00:00:00Z 1970-01-01T00:00:00Z 123 1 diff --git a/cloud/filestore/tests/client/canondata/test.test_write_ls_rm_ls/results.txt b/cloud/filestore/tests/client/canondata/test.test_write_ls_rm_ls/results.txt index 69247d72b5..8b3893592c 100644 --- a/cloud/filestore/tests/client/canondata/test.test_write_ls_rm_ls/results.txt +++ b/cloud/filestore/tests/client/canondata/test.test_write_ls_rm_ls/results.txt @@ -1,4 +1,4 @@ -Id Type Name Mode Uid Gid ATime MTime CTime Size Links FollowerFileSystemId FollowerNodeName +Id Type Name Mode Uid Gid ATime MTime CTime Size Links [ { diff --git a/cloud/filestore/tests/client/test.py b/cloud/filestore/tests/client/test.py index 682f47ca6b..954d9e94a0 100644 --- a/cloud/filestore/tests/client/test.py +++ b/cloud/filestore/tests/client/test.py @@ -1,5 +1,6 @@ import json import os +import re import yatest.common as common @@ -157,6 +158,36 @@ def test_stat(): return ret +def test_ls(): + client, results_path = __init_test() + client.create("fs0", "test_cloud", "test_folder", BLOCK_SIZE, BLOCKS_COUNT) + + out = client.ls("fs0", "/") + client.mkdir("fs0", "/aaa") + out += client.ls("fs0", "/") + out += client.ls("fs0", "/aaa") + client.mkdir("fs0", "/bbb") + client.touch("fs0", "/first") + node_id = json.loads(client.stat("fs0", "/first"))["Id"] + client.set_node_attr( + "fs0", node_id, "--uid", 10, "--gid", 20, "--size", 123, "--mode", 221 + ) + out += client.ls("fs0", "/") + # replace timestamps with a constant value + out = re.sub( + rb"(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z)", + b"1970-01-01T00:00:00Z", + out, + ) + client.destroy("fs0") + + with open(results_path, "wb") as results_file: + results_file.write(out) + + ret = common.canonical_file(results_path, local=True) + return ret + + def test_write_ls_rm_ls(): client, results_path = __init_test()