Skip to content

Commit e89fd96

Browse files
HDFS-16474. Make HDFS tail tool cross platform (#4157)
* The source files for hdfs_tail uses getopt for parsing the command line arguments. * getopt is available only on Linux and thus, isn't cross platform. * We need to replace getopt with boost::program_options to make these tools cross platform.
1 parent 5de78ce commit e89fd96

File tree

11 files changed

+517
-147
lines changed

11 files changed

+517
-147
lines changed

hadoop-hdfs-project/hadoop-hdfs-native-client/src/main/native/libhdfspp/tests/tools/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ add_executable(hdfs_tool_tests
4040
hdfs-ls-mock.cc
4141
hdfs-setrep-mock.cc
4242
hdfs-stat-mock.cc
43+
hdfs-tail-mock.cc
4344
main.cc)
4445
target_include_directories(hdfs_tool_tests PRIVATE
4546
../tools
@@ -64,6 +65,7 @@ target_include_directories(hdfs_tool_tests PRIVATE
6465
../../tools/hdfs-ls
6566
../../tools/hdfs-setrep
6667
../../tools/hdfs-stat
68+
../../tools/hdfs-tail
6769
../../tools/hdfs-cat)
6870
target_link_libraries(hdfs_tool_tests PRIVATE
6971
gmock_main
@@ -87,5 +89,6 @@ target_link_libraries(hdfs_tool_tests PRIVATE
8789
hdfs_ls_lib
8890
hdfs_setrep_lib
8991
hdfs_stat_lib
92+
hdfs_tail_lib
9093
hdfs_cat_lib)
9194
add_test(hdfs_tool_tests hdfs_tool_tests)
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/**
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
#include <functional>
20+
#include <memory>
21+
#include <string>
22+
#include <vector>
23+
24+
#include <gmock/gmock.h>
25+
#include <gtest/gtest.h>
26+
27+
#include "hdfs-tail-mock.h"
28+
#include "hdfs-tool-tests.h"
29+
30+
namespace hdfs::tools::test {
31+
TailMock::~TailMock() = default;
32+
33+
void TailMock::SetExpectations(
34+
std::function<std::unique_ptr<TailMock>()> test_case,
35+
const std::vector<std::string> &args) const {
36+
// Get the pointer to the function that defines the test case
37+
const auto test_case_func =
38+
test_case.target<std::unique_ptr<TailMock> (*)()>();
39+
ASSERT_NE(test_case_func, nullptr);
40+
41+
// Set the expected method calls and their corresponding arguments for each
42+
// test case
43+
if (*test_case_func == &CallHelp<TailMock>) {
44+
EXPECT_CALL(*this, HandleHelp()).Times(1).WillOnce(testing::Return(true));
45+
return;
46+
}
47+
48+
if (*test_case_func == &PassAPath<TailMock>) {
49+
const auto path = args[0];
50+
EXPECT_CALL(*this, HandlePath(path, false))
51+
.Times(1)
52+
.WillOnce(testing::Return(true));
53+
}
54+
55+
if (*test_case_func == &PassFOptAndAPath<TailMock>) {
56+
const auto f_opt = args[0];
57+
const auto path = args[1];
58+
ASSERT_EQ(f_opt, "-f");
59+
EXPECT_CALL(*this, HandlePath(path, true))
60+
.Times(1)
61+
.WillOnce(testing::Return(true));
62+
}
63+
}
64+
} // namespace hdfs::tools::test
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/**
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
#ifndef LIBHDFSPP_TOOLS_HDFS_TAIL_MOCK
20+
#define LIBHDFSPP_TOOLS_HDFS_TAIL_MOCK
21+
22+
#include <functional>
23+
#include <memory>
24+
#include <string>
25+
#include <vector>
26+
27+
#include <gmock/gmock.h>
28+
29+
#include "hdfs-tail.h"
30+
31+
namespace hdfs::tools::test {
32+
/**
33+
* {@class TailMock} is an {@class Tail} whereby it mocks the
34+
* HandleHelp and HandlePath methods for testing their functionality.
35+
*/
36+
class TailMock : public hdfs::tools::Tail {
37+
public:
38+
/**
39+
* {@inheritdoc}
40+
*/
41+
TailMock(const int argc, char **argv) : Tail(argc, argv) {}
42+
43+
// Abiding to the Rule of 5
44+
TailMock(const TailMock &) = delete;
45+
TailMock(TailMock &&) = delete;
46+
TailMock &operator=(const TailMock &) = delete;
47+
TailMock &operator=(TailMock &&) = delete;
48+
~TailMock() override;
49+
50+
/**
51+
* Defines the methods and the corresponding arguments that are expected
52+
* to be called on this instance of {@link HdfsTool} for the given test case.
53+
*
54+
* @param test_case An {@link std::function} object that points to the
55+
* function defining the test case
56+
* @param args The arguments that are passed to this test case
57+
*/
58+
void SetExpectations(std::function<std::unique_ptr<TailMock>()> test_case,
59+
const std::vector<std::string> &args = {}) const;
60+
61+
MOCK_METHOD(bool, HandleHelp, (), (const, override));
62+
63+
MOCK_METHOD(bool, HandlePath, (const std::string &, const bool),
64+
(const, override));
65+
};
66+
} // namespace hdfs::tools::test
67+
68+
#endif

hadoop-hdfs-project/hadoop-hdfs-native-client/src/main/native/libhdfspp/tests/tools/hdfs-tool-tests.cc

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
#include "hdfs-rm-mock.h"
4141
#include "hdfs-setrep-mock.h"
4242
#include "hdfs-stat-mock.h"
43+
#include "hdfs-tail-mock.h"
4344
#include "hdfs-tool-test-fixtures.h"
4445
#include "hdfs-tool-tests.h"
4546

@@ -168,6 +169,12 @@ INSTANTIATE_TEST_SUITE_P(
168169
testing::Values(CallHelp<hdfs::tools::test::StatMock>,
169170
PassAPath<hdfs::tools::test::StatMock>));
170171

172+
INSTANTIATE_TEST_SUITE_P(
173+
HdfsTail, HdfsToolBasicTest,
174+
testing::Values(PassAPath<hdfs::tools::test::TailMock>,
175+
CallHelp<hdfs::tools::test::TailMock>,
176+
PassFOptAndAPath<hdfs::tools::test::TailMock>));
177+
171178
// Negative tests
172179
INSTANTIATE_TEST_SUITE_P(
173180
HdfsAllowSnapshot, HdfsToolNegativeTestThrows,
@@ -282,6 +289,20 @@ INSTANTIATE_TEST_SUITE_P(
282289
PassMOpt<hdfs::tools::test::StatMock>,
283290
PassNOpt<hdfs::tools::test::StatMock>));
284291

292+
INSTANTIATE_TEST_SUITE_P(
293+
HdfsTail, HdfsToolNegativeTestThrows,
294+
testing::Values(Pass2Paths<hdfs::tools::test::TailMock>,
295+
Pass3Paths<hdfs::tools::test::TailMock>,
296+
PassNOptAndAPath<hdfs::tools::test::TailMock>,
297+
PassRecursiveOwnerAndAPath<hdfs::tools::test::TailMock>,
298+
PassMOpt<hdfs::tools::test::TailMock>,
299+
PassRecursive<hdfs::tools::test::TailMock>,
300+
PassRecursivePath<hdfs::tools::test::TailMock>,
301+
PassNOpt<hdfs::tools::test::TailMock>,
302+
PassOwnerAndAPath<hdfs::tools::test::TailMock>,
303+
PassMPOptsPermissionsAndAPath<hdfs::tools::test::TailMock>,
304+
PassPermissionsAndAPath<hdfs::tools::test::TailMock>));
305+
285306
INSTANTIATE_TEST_SUITE_P(
286307
HdfsRm, HdfsToolNegativeTestNoThrow,
287308
testing::Values(PassRecursive<hdfs::tools::test::RmMock>));
@@ -341,3 +362,7 @@ INSTANTIATE_TEST_SUITE_P(
341362
INSTANTIATE_TEST_SUITE_P(
342363
HdfsSetrep, HdfsToolNegativeTestNoThrow,
343364
testing::Values(PassAPath<hdfs::tools::test::SetrepMock>));
365+
366+
INSTANTIATE_TEST_SUITE_P(
367+
HdfsTail, HdfsToolNegativeTestNoThrow,
368+
testing::Values(PassFOpt<hdfs::tools::test::TailMock>));

hadoop-hdfs-project/hadoop-hdfs-native-client/src/main/native/libhdfspp/tests/tools/hdfs-tool-tests.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,19 @@ template <class T> std::unique_ptr<T> PassRecursivePath() {
6969
return hdfs_tool;
7070
}
7171

72+
template <class T> std::unique_ptr<T> PassFOptAndAPath() {
73+
constexpr auto argc = 3;
74+
static std::string exe("hdfs_tool_name");
75+
static std::string arg1("-f");
76+
static std::string arg2("a/b/c");
77+
78+
static char *argv[] = {exe.data(), arg1.data(), arg2.data()};
79+
80+
auto hdfs_tool = std::make_unique<T>(argc, argv);
81+
hdfs_tool->SetExpectations(PassFOptAndAPath<T>, {arg1, arg2});
82+
return hdfs_tool;
83+
}
84+
7285
template <class T> std::unique_ptr<T> CallHelp() {
7386
constexpr auto argc = 2;
7487
static std::string exe("hdfs_tool_name");
@@ -226,6 +239,18 @@ template <class T> std::unique_ptr<T> PassMOpt() {
226239
return hdfs_tool;
227240
}
228241

242+
template <class T> std::unique_ptr<T> PassFOpt() {
243+
constexpr auto argc = 2;
244+
static std::string exe("hdfs_tool_name");
245+
static std::string arg1("-f");
246+
247+
static char *argv[] = {exe.data(), arg1.data()};
248+
249+
auto hdfs_tool = std::make_unique<T>(argc, argv);
250+
hdfs_tool->SetExpectations(PassFOpt<T>, {arg1});
251+
return hdfs_tool;
252+
}
253+
229254
template <class T> std::unique_ptr<T> PassPOptAndPath() {
230255
constexpr auto argc = 3;
231256
static std::string exe("hdfs_tool_name");

hadoop-hdfs-project/hadoop-hdfs-native-client/src/main/native/libhdfspp/tools/CMakeLists.txt

Lines changed: 1 addition & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -34,46 +34,24 @@ add_library(hdfs_tool_obj OBJECT hdfs-tool.cc)
3434
target_include_directories(hdfs_tool_obj PRIVATE ../tools)
3535

3636
add_subdirectory(hdfs-cat)
37-
3837
add_subdirectory(hdfs-chgrp)
39-
4038
add_subdirectory(hdfs-chown)
41-
4239
add_subdirectory(hdfs-chmod)
43-
4440
add_subdirectory(hdfs-find)
45-
4641
add_subdirectory(hdfs-mkdir)
47-
4842
add_subdirectory(hdfs-rm)
49-
5043
add_subdirectory(hdfs-ls)
51-
5244
add_subdirectory(hdfs-stat)
53-
5445
add_subdirectory(hdfs-count)
55-
5646
add_subdirectory(hdfs-df)
57-
5847
add_subdirectory(hdfs-du)
59-
6048
add_subdirectory(hdfs-get)
61-
6249
add_subdirectory(hdfs-copy-to-local)
63-
6450
add_subdirectory(hdfs-move-to-local)
65-
6651
add_subdirectory(hdfs-setrep)
67-
6852
add_subdirectory(hdfs-allow-snapshot)
69-
7053
add_subdirectory(hdfs-disallow-snapshot)
71-
7254
add_subdirectory(hdfs-create-snapshot)
73-
7455
add_subdirectory(hdfs-rename-snapshot)
75-
7656
add_subdirectory(hdfs-delete-snapshot)
77-
78-
add_executable(hdfs_tail hdfs_tail.cc)
79-
target_link_libraries(hdfs_tail tools_common hdfspp_static)
57+
add_subdirectory(hdfs-tail)
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#
2+
# Licensed to the Apache Software Foundation (ASF) under one
3+
# or more contributor license agreements. See the NOTICE file
4+
# distributed with this work for additional information
5+
# regarding copyright ownership. The ASF licenses this file
6+
# to you under the Apache License, Version 2.0 (the
7+
# "License"); you may not use this file except in compliance
8+
# with the License. You may obtain a copy of the License at
9+
#
10+
# http://www.apache.org/licenses/LICENSE-2.0
11+
#
12+
# Unless required by applicable law or agreed to in writing, software
13+
# distributed under the License is distributed on an "AS IS" BASIS,
14+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
# See the License for the specific language governing permissions and
16+
# limitations under the License.
17+
#
18+
19+
add_library(hdfs_tail_lib STATIC $<TARGET_OBJECTS:hdfs_tool_obj> hdfs-tail.cc)
20+
target_include_directories(hdfs_tail_lib PRIVATE ../../tools ${Boost_INCLUDE_DIRS})
21+
target_link_libraries(hdfs_tail_lib PRIVATE Boost::boost Boost::program_options tools_common hdfspp_static)
22+
23+
add_executable(hdfs_tail main.cc)
24+
target_include_directories(hdfs_tail PRIVATE ../../tools)
25+
target_link_libraries(hdfs_tail PRIVATE hdfs_tail_lib)
26+
27+
install(TARGETS hdfs_tail RUNTIME DESTINATION bin)

0 commit comments

Comments
 (0)