Merge changes I33cd59e6,I8a2e539f
[alexxy/gromacs.git] / src / gromacs / commandline / tests / cmdlinehelpwriter.cpp
1 /*
2  *
3  *                This source code is part of
4  *
5  *                 G   R   O   M   A   C   S
6  *
7  *          GROningen MAchine for Chemical Simulations
8  *
9  * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
10  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
11  * Copyright (c) 2001-2009, The GROMACS development team,
12  * check out http://www.gromacs.org for more information.
13
14  * This program is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU General Public License
16  * as published by the Free Software Foundation; either version 2
17  * of the License, or (at your option) any later version.
18  *
19  * If you want to redistribute modifications, please consider that
20  * scientific software is very special. Version control is crucial -
21  * bugs must be traceable. We will be happy to consider code for
22  * inclusion in the official distribution, but derived work must not
23  * be called official GROMACS. Details are found in the README & COPYING
24  * files - if they are missing, get the official version at www.gromacs.org.
25  *
26  * To help us fund GROMACS development, we humbly ask that you cite
27  * the papers on the package - you can find them in the top README file.
28  *
29  * For more info, check our website at http://www.gromacs.org
30  */
31 /*! \internal \file
32  * \brief
33  * Tests gmx::CommandLineHelpWriter.
34  *
35  * These tests fail for any change in the output, and it should be reviewed
36  * whether the change was intentional.
37  * For development, the tests can be run with a '-stdout' command-line option
38  * to print out the help to stdout instead of using the XML reference
39  * framework.
40  *
41  * \author Teemu Murtola <teemu.murtola@cbr.su.se>
42  * \ingroup module_commandline
43  */
44 #include <gtest/gtest.h>
45
46 #include "gromacs/legacyheaders/types/simple.h"
47
48 #include "gromacs/commandline/cmdlinehelpwriter.h"
49 #include "gromacs/onlinehelp/helpwritercontext.h"
50 #include "gromacs/options/basicoptions.h"
51 #include "gromacs/options/filenameoption.h"
52 #include "gromacs/options/options.h"
53 #include "gromacs/selection/selectioncollection.h"
54 #include "gromacs/selection/selectionfileoption.h"
55 #include "gromacs/selection/selectionoption.h"
56 #include "gromacs/selection/selectionoptioninfo.h"
57 #include "gromacs/selection/selectionoptionmanager.h"
58 #include "gromacs/utility/file.h"
59
60 #include "testutils/datapath.h"
61 #include "testutils/stringtest.h"
62
63 namespace
64 {
65
66 class CommandLineHelpWriterTest : public ::gmx::test::StringTestBase
67 {
68     public:
69         void checkHelp(gmx::CommandLineHelpWriter *writer);
70
71         gmx::test::TestFileManager tempFiles_;
72 };
73
74 void CommandLineHelpWriterTest::checkHelp(gmx::CommandLineHelpWriter *writer)
75 {
76     std::string filename = tempFiles_.getTemporaryFilePath("helptext.txt");
77     gmx::File file(filename, "w");
78     gmx::HelpWriterContext context(&file, gmx::eHelpOutputFormat_Console);
79     writer->writeHelp(context);
80     file.close();
81
82     checkFileContents(filename, "HelpText");
83 }
84
85
86 /********************************************************************
87  * Tests start here
88  */
89
90 /*
91  * Tests help printing for each option type, but doesn't contain much
92  * variablity in the options.
93  */
94 TEST_F(CommandLineHelpWriterTest, HandlesOptionTypes)
95 {
96     using namespace gmx;
97
98     Options options("test", "Short Description");
99     options.addOption(BooleanOption("bool").description("Boolean option")
100                         .defaultValue(true));
101     options.addOption(BooleanOption("hidden").description("Hidden option")
102                         .hidden().defaultValue(true));
103     options.addOption(IntegerOption("int").description("Integer option")
104                         .defaultValue(2));
105     ivec intvec = {1, 2, 3};
106     options.addOption(IntegerOption("ivec").description("Integer vector option")
107                         .vector().store(intvec));
108     options.addOption(DoubleOption("double").description("Double option")
109                         .defaultValue(2.5));
110     dvec dblvec = {1.1, 2.3, 3.2};
111     options.addOption(DoubleOption("dvec").description("Double vector option")
112                         .vector().store(dblvec));
113     options.addOption(DoubleOption("time").description("Time option (%t)")
114                         .timeValue().defaultValue(10.0));
115     options.addOption(StringOption("string").description("String option")
116                         .defaultValue("test"));
117     const char * const enumValues[] = {"no", "opt1", "opt2", NULL};
118     options.addOption(StringOption("enum").description("Enum option")
119                         .enumValue(enumValues).defaultEnumIndex(0));
120
121     std::string filename;
122     options.addOption(FileNameOption("f")
123                         .description("Input file description")
124                         .filetype(eftTrajectory).inputFile().required()
125                         .defaultValue("traj"));
126     options.addOption(FileNameOption("lib")
127                         .description("Library file description")
128                         .filetype(eftGenericData).inputFile().libraryFile()
129                         .defaultValueIfSet("libdata"));
130     options.addOption(FileNameOption("io")
131                         .store(&filename)
132                         .description("Input/Output file description")
133                         .filetype(eftGenericData).inputOutputFile()
134                         .defaultValueIfSet("inout"));
135     options.addOption(FileNameOption("o")
136                         .description("Output file description")
137                         .filetype(eftPlot).outputFile());
138
139     options.addOption(SelectionFileOption("sf"));
140     options.addOption(SelectionOption("sel").description("Selection option"));
141
142     CommandLineHelpWriter writer(options);
143     writer.setShowHidden(true);
144     checkHelp(&writer);
145 }
146
147 /*
148  * Tests help printing with file name options with various values that don't
149  * fit into the allocated columns.
150  */
151 TEST_F(CommandLineHelpWriterTest, HandlesLongFileOptions)
152 {
153     using gmx::FileNameOption;
154     using gmx::eftGenericData;
155     using gmx::eftTrajectory;
156
157     gmx::Options options(NULL, NULL);
158     options.addOption(FileNameOption("f")
159                         .description("File name option with a long value")
160                         .filetype(eftTrajectory).inputFile().required()
161                         .defaultValue("path/to/long/trajectory/name"));
162     options.addOption(FileNameOption("f2")
163                         .description("File name option with a long value")
164                         .filetype(eftTrajectory).inputFile().required()
165                         .defaultValue("path/to/long/trajectory"));
166     options.addOption(FileNameOption("lib")
167                         .description("File name option with a long value and type")
168                         .filetype(eftTrajectory).inputFile().libraryFile()
169                         .defaultValue("path/to/long/trajectory/name"));
170     options.addOption(FileNameOption("longfileopt")
171                         .description("File name option with a long name")
172                         .filetype(eftGenericData).inputFile()
173                         .defaultValue("deffile"));
174     options.addOption(FileNameOption("longfileopt2")
175                         .description("File name option with multiple long fields")
176                         .filetype(eftGenericData).inputFile().libraryFile()
177                         .defaultValue("path/to/long/file/name"));
178
179     gmx::CommandLineHelpWriter writer(options);
180     checkHelp(&writer);
181 }
182
183 /*
184  * Tests help printing with general options with various values that don't
185  * fit into the allocated columns.
186  */
187 TEST_F(CommandLineHelpWriterTest, HandlesLongOptions)
188 {
189     using gmx::BooleanOption;
190     using gmx::DoubleOption;
191     using gmx::StringOption;
192
193     gmx::Options options(NULL, NULL);
194     options.addOption(BooleanOption("longboolean")
195                         .description("Boolean option with a long name")
196                         .defaultValue(true));
197     dvec dblvec = {1.135, 2.32, 3.2132};
198     options.addOption(DoubleOption("dvec").description("Double vector option")
199                         .vector().store(dblvec));
200     std::vector<std::string> values;
201     values.push_back("A very long string value that overflows even the description column");
202     values.push_back("Another very long string value that overflows even the description column");
203     options.addOption(StringOption("string")
204                         .description("String option with very long values (may "
205                                      "be less relevant with selections having "
206                                      "their own option type)")
207                         .storeVector(&values));
208
209     gmx::CommandLineHelpWriter writer(options);
210     checkHelp(&writer);
211 }
212
213 /*
214  * Tests help printing with selection options with values.
215  */
216 TEST_F(CommandLineHelpWriterTest, HandlesSelectionOptions)
217 {
218     using gmx::SelectionFileOption;
219     using gmx::SelectionOption;
220
221     gmx::Options options(NULL, NULL);
222     options.addOption(SelectionFileOption("sf"));
223     options.addOption(SelectionOption("refsel").required()
224                         .description("Reference selection option"));
225     options.addOption(SelectionOption("sel").required().valueCount(2)
226                         .description("Selection option"));
227     gmx::SelectionCollection selections;
228     gmx::SelectionOptionManager manager(&selections);
229     setManagerForSelectionOptions(&options, &manager);
230     options.finish();
231     manager.parseRequestedFromString(
232             "resname SOL;"
233             "surface = within 0.5 of resname SOL;"
234             "group \"Protein\" and surface;"
235             "group \"Protein\" and not surface;");
236
237     gmx::CommandLineHelpWriter writer(options);
238     checkHelp(&writer);
239 }
240
241 /*
242  * Tests help printing for multiple sections.
243  */
244 TEST_F(CommandLineHelpWriterTest, HandlesMultipleSections)
245 {
246     using namespace gmx;
247
248     Options options("test", "Main Title");
249     Options subSect1("subsect1", "Subsection 1 Title");
250     Options subSect2("subsect2", "Subsection 2 Title");
251     Options subSect3("subsect3", NULL);
252     options.addSubSection(&subSect1);
253     options.addSubSection(&subSect2);
254     options.addSubSection(&subSect3);
255     options.setDescription("Description for main section.");
256     subSect1.setDescription("Description for subsection 1.");
257     subSect2.setDescription("Description for subsection 2.");
258     subSect3.setDescription("Description for subsection 3.");
259     options.addOption(IntegerOption("main")
260                         .description("Option in main section"));
261     subSect1.addOption(IntegerOption("sub1")
262                          .description("Option in subsection 1"));
263     subSect2.addOption(IntegerOption("sub2")
264                          .description("Option in subsection 2"));
265
266     CommandLineHelpWriter writer(options);
267     writer.setShowDescriptions(true);
268     checkHelp(&writer);
269 }
270
271 } // namespace