Remove all unnecessary HAVE_CONFIG_H
[alexxy/gromacs.git] / src / gromacs / commandline / tests / cmdlinemodulemanager.cpp
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 2012,2013,2014, by the GROMACS development team, led by
5  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
6  * and including many others, as listed in the AUTHORS file in the
7  * top-level source directory and at http://www.gromacs.org.
8  *
9  * GROMACS is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public License
11  * as published by the Free Software Foundation; either version 2.1
12  * of the License, or (at your option) any later version.
13  *
14  * GROMACS is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with GROMACS; if not, see
21  * http://www.gnu.org/licenses, or write to the Free Software Foundation,
22  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
23  *
24  * If you want to redistribute modifications to GROMACS, please
25  * consider that scientific software is very special. Version
26  * control is crucial - bugs must be traceable. We will be happy to
27  * consider code for inclusion in the official distribution, but
28  * derived work must not be called official GROMACS. Details are found
29  * in the README & COPYING files - if they are missing, get the
30  * official version at http://www.gromacs.org.
31  *
32  * To help us fund GROMACS development, we humbly ask that you cite
33  * the research papers on the package. Check out http://www.gromacs.org.
34  */
35 /*! \internal \file
36  * \brief
37  * Tests gmx::CommandLineModuleManager.
38  *
39  * \author Teemu Murtola <teemu.murtola@gmail.com>
40  * \ingroup module_commandline
41  */
42 // For GMX_BINARY_SUFFIX
43 #include "config.h"
44
45 #include <vector>
46
47 #include <gmock/gmock.h>
48
49 #include "gromacs/commandline/cmdlinehelpcontext.h"
50 #include "gromacs/commandline/cmdlinemodule.h"
51 #include "gromacs/commandline/cmdlinemodulemanager.h"
52 #include "gromacs/commandline/cmdlineprogramcontext.h"
53 #include "gromacs/utility/file.h"
54
55 #include "gromacs/onlinehelp/tests/mock_helptopic.h"
56 #include "testutils/cmdlinetest.h"
57 #include "testutils/testasserts.h"
58 #include "testutils/testfilemanager.h"
59
60 namespace
61 {
62
63 using gmx::test::CommandLine;
64 using gmx::test::MockHelpTopic;
65
66 /********************************************************************
67  * MockModule
68  */
69
70 /*! \internal \brief
71  * Mock implementation of gmx::CommandLineModuleInterface.
72  *
73  * \ingroup module_commandline
74  */
75 class MockModule : public gmx::CommandLineModuleInterface
76 {
77     public:
78         //! Creates a mock module with the given name and description.
79         MockModule(const char *name, const char *description);
80
81         virtual const char *name() const { return name_; }
82         virtual const char *shortDescription() const { return descr_; }
83
84         MOCK_METHOD2(run, int(int argc, char *argv[]));
85         MOCK_CONST_METHOD1(writeHelp, void(const gmx::CommandLineHelpContext &context));
86
87         //! Sets the expected display name for writeHelp() calls.
88         void setExpectedDisplayName(const char *expected)
89         {
90             expectedDisplayName_ = expected;
91         }
92
93     private:
94         //! Checks the context passed to writeHelp().
95         void checkHelpContext(const gmx::CommandLineHelpContext &context) const;
96
97         const char             *name_;
98         const char             *descr_;
99         std::string             expectedDisplayName_;
100 };
101
102 MockModule::MockModule(const char *name, const char *description)
103     : name_(name), descr_(description)
104 {
105     using ::testing::_;
106     using ::testing::Invoke;
107     using ::testing::WithArg;
108     ON_CALL(*this, writeHelp(_))
109         .WillByDefault(WithArg<0>(Invoke(this, &MockModule::checkHelpContext)));
110 }
111
112 void MockModule::checkHelpContext(const gmx::CommandLineHelpContext &context) const
113 {
114     EXPECT_EQ(expectedDisplayName_, context.moduleDisplayName());
115
116     gmx::TextLineWrapperSettings settings;
117     std::string                  moduleName =
118         context.writerContext().substituteMarkupAndWrapToString(
119                 settings, "[THISMODULE]");
120     EXPECT_EQ(expectedDisplayName_, moduleName);
121 }
122
123 /********************************************************************
124  * Test fixture for the tests
125  */
126
127 class CommandLineModuleManagerTest : public ::testing::Test
128 {
129     public:
130         void initManager(const CommandLine &args, const char *realBinaryName);
131         MockModule    &addModule(const char *name, const char *description);
132         MockHelpTopic &addHelpTopic(const char *name, const char *title);
133
134         gmx::CommandLineModuleManager &manager() { return *manager_; }
135
136         void ignoreManagerOutput();
137
138     private:
139         boost::scoped_ptr<gmx::CommandLineProgramContext> programContext_;
140         boost::scoped_ptr<gmx::CommandLineModuleManager>  manager_;
141         gmx::test::TestFileManager                        fileManager_;
142         boost::scoped_ptr<gmx::File>                      outputFile_;
143 };
144
145 void CommandLineModuleManagerTest::initManager(
146         const CommandLine &args, const char *realBinaryName)
147 {
148     manager_.reset();
149     programContext_.reset(
150             new gmx::CommandLineProgramContext(args.argc(), args.argv()));
151     manager_.reset(new gmx::CommandLineModuleManager(realBinaryName,
152                                                      programContext_.get()));
153     manager_->setQuiet(true);
154 }
155
156 MockModule &
157 CommandLineModuleManagerTest::addModule(const char *name, const char *description)
158 {
159     MockModule *module = new MockModule(name, description);
160     manager().addModule(gmx::CommandLineModulePointer(module));
161     return *module;
162 }
163
164 MockHelpTopic &
165 CommandLineModuleManagerTest::addHelpTopic(const char *name, const char *title)
166 {
167     MockHelpTopic *topic = new MockHelpTopic(name, title, "Help text");
168     manager().addHelpTopic(gmx::HelpTopicPointer(topic));
169     return *topic;
170 }
171
172 void CommandLineModuleManagerTest::ignoreManagerOutput()
173 {
174     outputFile_.reset(
175             new gmx::File(fileManager_.getTemporaryFilePath("out.txt"), "w"));
176     manager().setOutputRedirect(outputFile_.get());
177 }
178
179 /********************************************************************
180  * Actual tests
181  */
182
183 TEST_F(CommandLineModuleManagerTest, RunsGeneralHelp)
184 {
185     const char *const cmdline[] = {
186         "test"
187     };
188     CommandLine       args(cmdline);
189     initManager(args, "test");
190     ignoreManagerOutput();
191     addModule("module", "First module");
192     addModule("other", "Second module");
193     int rc = 0;
194     ASSERT_NO_THROW_GMX(rc = manager().run(args.argc(), args.argv()));
195     ASSERT_EQ(0, rc);
196 }
197
198 TEST_F(CommandLineModuleManagerTest, RunsModule)
199 {
200     const char *const cmdline[] = {
201         "test", "module", "-flag", "yes"
202     };
203     CommandLine       args(cmdline);
204     initManager(args, "test");
205     MockModule       &mod1 = addModule("module", "First module");
206     addModule("other", "Second module");
207     using ::testing::_;
208     using ::testing::Args;
209     using ::testing::ElementsAreArray;
210     EXPECT_CALL(mod1, run(_, _))
211         .With(Args<1, 0>(ElementsAreArray(args.argv() + 1, args.argc() - 1)));
212     int rc = 0;
213     ASSERT_NO_THROW_GMX(rc = manager().run(args.argc(), args.argv()));
214     ASSERT_EQ(0, rc);
215 }
216
217 TEST_F(CommandLineModuleManagerTest, RunsModuleHelp)
218 {
219     const char *const cmdline[] = {
220         "test", "help", "module"
221     };
222     CommandLine       args(cmdline);
223     initManager(args, "test");
224     MockModule       &mod1 = addModule("module", "First module");
225     addModule("other", "Second module");
226     using ::testing::_;
227     EXPECT_CALL(mod1, writeHelp(_));
228     mod1.setExpectedDisplayName("test module");
229     int rc = 0;
230     ASSERT_NO_THROW_GMX(rc = manager().run(args.argc(), args.argv()));
231     ASSERT_EQ(0, rc);
232 }
233
234 TEST_F(CommandLineModuleManagerTest, RunsModuleHelpWithDashH)
235 {
236     const char *const cmdline[] = {
237         "test", "module", "-h"
238     };
239     CommandLine       args(cmdline);
240     initManager(args, "test");
241     MockModule       &mod1 = addModule("module", "First module");
242     addModule("other", "Second module");
243     using ::testing::_;
244     EXPECT_CALL(mod1, writeHelp(_));
245     mod1.setExpectedDisplayName("test module");
246     int rc = 0;
247     ASSERT_NO_THROW_GMX(rc = manager().run(args.argc(), args.argv()));
248     ASSERT_EQ(0, rc);
249 }
250
251 TEST_F(CommandLineModuleManagerTest, RunsModuleHelpWithDashHWithSymLink)
252 {
253     const char *const cmdline[] = {
254         "g_module", "-h"
255     };
256     CommandLine       args(cmdline);
257     initManager(args, "test");
258     MockModule       &mod1 = addModule("module", "First module");
259     addModule("other", "Second module");
260     using ::testing::_;
261     EXPECT_CALL(mod1, writeHelp(_));
262     mod1.setExpectedDisplayName("test module");
263     int rc = 0;
264     ASSERT_NO_THROW_GMX(rc = manager().run(args.argc(), args.argv()));
265     ASSERT_EQ(0, rc);
266 }
267
268 TEST_F(CommandLineModuleManagerTest, RunsModuleHelpWithDashHWithSingleModule)
269 {
270     const char *const cmdline[] = {
271         "g_module", "-h"
272     };
273     CommandLine       args(cmdline);
274     initManager(args, "g_module");
275     MockModule        mod(NULL, NULL);
276     manager().setSingleModule(&mod);
277     using ::testing::_;
278     EXPECT_CALL(mod, writeHelp(_));
279     mod.setExpectedDisplayName("g_module");
280     int rc = 0;
281     ASSERT_NO_THROW_GMX(rc = manager().run(args.argc(), args.argv()));
282     ASSERT_EQ(0, rc);
283 }
284
285 TEST_F(CommandLineModuleManagerTest, PrintsHelpOnTopic)
286 {
287     const char *const cmdline[] = {
288         "test", "help", "topic"
289     };
290     CommandLine       args(cmdline);
291     initManager(args, "test");
292     addModule("module", "First module");
293     MockHelpTopic &topic = addHelpTopic("topic", "Test topic");
294     using ::testing::_;
295     EXPECT_CALL(topic, writeHelp(_));
296     int rc = 0;
297     ASSERT_NO_THROW_GMX(rc = manager().run(args.argc(), args.argv()));
298     ASSERT_EQ(0, rc);
299 }
300
301 TEST_F(CommandLineModuleManagerTest, RunsModuleBasedOnBinaryName)
302 {
303     const char *const cmdline[] = {
304         "g_module", "-flag", "yes"
305     };
306     CommandLine       args(cmdline);
307     initManager(args, "test");
308     MockModule       &mod1 = addModule("module", "First module");
309     addModule("other", "Second module");
310     using ::testing::_;
311     using ::testing::Args;
312     using ::testing::ElementsAreArray;
313     EXPECT_CALL(mod1, run(_, _))
314         .With(Args<1, 0>(ElementsAreArray(args.argv(), args.argc())));
315     int rc = 0;
316     ASSERT_NO_THROW_GMX(rc = manager().run(args.argc(), args.argv()));
317     ASSERT_EQ(0, rc);
318 }
319
320 TEST_F(CommandLineModuleManagerTest, RunsModuleBasedOnBinaryNameWithPathAndSuffix)
321 {
322     const char *const cmdline[] = {
323         "/usr/local/gromacs/bin/g_module" GMX_BINARY_SUFFIX ".exe", "-flag", "yes"
324     };
325     CommandLine       args(cmdline);
326     initManager(args, "test");
327     MockModule       &mod1 = addModule("module", "First module");
328     addModule("other", "Second module");
329     using ::testing::_;
330     using ::testing::Args;
331     using ::testing::ElementsAreArray;
332     EXPECT_CALL(mod1, run(_, _))
333         .With(Args<1, 0>(ElementsAreArray(args.argv(), args.argc())));
334     int rc = 0;
335     ASSERT_NO_THROW_GMX(rc = manager().run(args.argc(), args.argv()));
336     ASSERT_EQ(0, rc);
337 }
338
339 TEST_F(CommandLineModuleManagerTest, HandlesConflictingBinaryAndModuleNames)
340 {
341     const char *const cmdline[] = {
342         "test", "test", "-flag", "yes"
343     };
344     CommandLine       args(cmdline);
345     initManager(args, "test");
346     MockModule       &mod1 = addModule("test", "Test module");
347     addModule("other", "Second module");
348     using ::testing::_;
349     using ::testing::Args;
350     using ::testing::ElementsAreArray;
351     EXPECT_CALL(mod1, run(_, _))
352         .With(Args<1, 0>(ElementsAreArray(args.argv() + 1, args.argc() - 1)));
353     int rc = 0;
354     ASSERT_NO_THROW_GMX(rc = manager().run(args.argc(), args.argv()));
355     ASSERT_EQ(0, rc);
356 }
357
358 } // namespace