API
 
Loading...
Searching...
No Matches
sshDigger_test.cpp
Go to the documentation of this file.
1/** \file sshDigger_test.cpp
2 * \brief Catch2 tests for the sshDigger app.
3 * \author Jared R. Males (jaredmales@gmail.com)
4 *
5 * \ingroup sshDigger_files
6 */
7
8#include "../../../tests/testXWC.hpp"
9
10#define SSHDIGGER_TEST_NOINDI
11#define SSHDIGGER_TEST_NOLOG
12#include "../sshDigger.hpp"
13
14using namespace MagAOX::app;
15
16namespace libXWCTest
17{
18
19/** \defgroup sshDigger_unit_test sshDigger Unit Tests
20 * \brief Unit tests for the sshDigger application.
21 *
22 * \ingroup application_unit_test
23 */
24
25/// Namespace for `sshDigger` unit tests.
26/** \ingroup sshDigger_unit_test
27 */
28namespace sshDiggerTest
29{
30
31/// \cond DOXYGEN_SUPPRESS_TEST_HARNESS
32class sshDigger_test : public sshDigger
33{
34 public:
35 void configName( const std::string &cn )
36 {
37 m_configName = cn;
38 }
39
40 std::string remoteHost()
41 {
42 return m_remoteHost;
43 }
44 int localPort()
45 {
46 return m_localPort;
47 }
48 int remotePort()
49 {
50 return m_remotePort;
51 }
52 int monitorPort()
53 {
54 return m_monitorPort;
55 }
56};
57/// \endcond
58
59/// Verify `sshDigger::loadConfigImpl()` and command helpers interpret tunnel definitions correctly.
60/**
61 * \ingroup sshDigger_unit_test
62 */
63SCENARIO( "sshDigger Configuration", "[sshDigger]" )
64{
65 // clang-format off
66 #ifdef SSHDIGGER_TEST_DOXYGEN_REF
67 sshDigger::loadConfigImpl( *(mx::app::appConfigurator *)nullptr );
69 sshDigger::genArgsV( *(std::vector<std::string> *)nullptr );
70 #endif
71 // clang-format on
72
73 GIVEN( "a config file with 1 tunnel" )
74 {
75 WHEN( "the tunnel is fully specified and matches configName" )
76 {
77 mx::app::writeConfigFile( "/tmp/sshDigger_test.conf",
78 { "tunnel1", "tunnel1", "tunnel1" },
79 { "remoteHost", "localPort", "remotePort" },
80 { "exao2", "80", "81" } );
81
82 mx::app::appConfigurator config;
83 config.readConfig( "/tmp/sshDigger_test.conf" );
84
85 sshDigger_test dig;
86 dig.configName( "tunnel1" );
87 int rv;
88 rv = dig.loadConfigImpl( config );
89 REQUIRE( rv == 0 );
90
91 REQUIRE( dig.remoteHost() == "exao2" );
92 REQUIRE( dig.localPort() == 80 );
93 REQUIRE( dig.remotePort() == 81 );
94 REQUIRE( dig.monitorPort() == 0 );
95 }
96
97 WHEN( "the tunnel is fully specified and matches configName, includes monitorPort" )
98 {
99 mx::app::writeConfigFile( "/tmp/sshDigger_test.conf",
100 { "tunnel1", "tunnel1", "tunnel1", "tunnel1" },
101 { "remoteHost", "localPort", "remotePort", "monitorPort" },
102 { "exao2", "80", "81", "6000" } );
103
104 mx::app::appConfigurator config;
105 config.readConfig( "/tmp/sshDigger_test.conf" );
106
107 sshDigger_test dig;
108 dig.configName( "tunnel1" );
109 int rv;
110 rv = dig.loadConfigImpl( config );
111 REQUIRE( rv == 0 );
112
113 REQUIRE( dig.remoteHost() == "exao2" );
114 REQUIRE( dig.localPort() == 80 );
115 REQUIRE( dig.remotePort() == 81 );
116 REQUIRE( dig.monitorPort() == 6000 );
117 }
118
119 WHEN( "no unused sections" )
120 {
121 mx::app::writeConfigFile( "/tmp/sshDigger_test.conf", {}, {}, {} );
122
123 mx::app::appConfigurator config;
124 config.readConfig( "/tmp/sshDigger_test.conf" );
125
126 sshDigger_test dig;
127 dig.configName( "tunnel2" );
128 int rv;
129 rv = dig.loadConfigImpl( config );
130 REQUIRE( rv == SSHDIGGER_E_NOTUNNELS );
131 }
132
133 WHEN( "the tunnel does not match configName" )
134 {
135 mx::app::writeConfigFile( "/tmp/sshDigger_test.conf",
136 { "tunnel1", "tunnel1", "tunnel1" },
137 { "remoteHost", "localPort", "remotePort" },
138 { "exao2", "80", "81" } );
139
140 mx::app::appConfigurator config;
141 config.readConfig( "/tmp/sshDigger_test.conf" );
142
143 sshDigger_test dig;
144 dig.configName( "tunnel2" );
145 int rv;
146 rv = dig.loadConfigImpl( config );
147 REQUIRE( rv == SSHDIGGER_E_NOTUNNELFOUND );
148 }
149
150 WHEN( "no remote host" )
151 {
152 mx::app::writeConfigFile(
153 "/tmp/sshDigger_test.conf", { "tunnel1", "tunnel1" }, { "localPort", "remotePort" }, { "80", "81" } );
154
155 mx::app::appConfigurator config;
156 config.readConfig( "/tmp/sshDigger_test.conf" );
157
158 sshDigger_test dig;
159 dig.configName( "tunnel1" );
160 int rv;
161 rv = dig.loadConfigImpl( config );
162 REQUIRE( rv == SSHDIGGER_E_NOHOSTNAME );
163 }
164
165 WHEN( "no local port" )
166 {
167 mx::app::writeConfigFile( "/tmp/sshDigger_test.conf",
168 { "tunnel1", "tunnel1" },
169 { "remoteHost", "remotePort" },
170 { "exao2", "81" } );
171
172 mx::app::appConfigurator config;
173 config.readConfig( "/tmp/sshDigger_test.conf" );
174
175 sshDigger_test dig;
176 dig.configName( "tunnel1" );
177 int rv;
178 rv = dig.loadConfigImpl( config );
179 REQUIRE( rv == SSHDIGGER_E_NOLOCALPORT );
180 }
181
182 WHEN( "no remote port" )
183 {
184 mx::app::writeConfigFile( "/tmp/sshDigger_test.conf",
185 { "tunnel1", "tunnel1" },
186 { "remoteHost", "localPort" },
187 { "exao2", "80" } );
188
189 mx::app::appConfigurator config;
190 config.readConfig( "/tmp/sshDigger_test.conf" );
191
192 sshDigger_test dig;
193 dig.configName( "tunnel1" );
194 int rv;
195 rv = dig.loadConfigImpl( config );
196 REQUIRE( rv == SSHDIGGER_E_NOREMOTEPORT );
197 }
198 }
199 GIVEN( "a config file with 2 tunnels" )
200 {
201 WHEN( "the tunnels are fully specified and match their configNames" )
202 {
203 mx::app::writeConfigFile(
204 "/tmp/sshDigger_test.conf",
205 { "tunnel1", "tunnel1", "tunnel1", "tunnel2", "tunnel2", "tunnel2" },
206 { "remoteHost", "localPort", "remotePort", "remoteHost", "localPort", "remotePort" },
207 { "exao2", "80", "81", "exao3", "85", "86" } );
208
209 mx::app::appConfigurator config;
210 config.readConfig( "/tmp/sshDigger_test.conf" );
211
212 int rv;
213
214 sshDigger_test dig;
215 dig.configName( "tunnel1" );
216
217 rv = dig.loadConfigImpl( config );
218 REQUIRE( rv == 0 );
219 REQUIRE( dig.remoteHost() == "exao2" );
220 REQUIRE( dig.localPort() == 80 );
221 REQUIRE( dig.remotePort() == 81 );
222
223 dig.configName( "tunnel2" );
224
225 rv = dig.loadConfigImpl( config );
226 REQUIRE( rv == 0 );
227 REQUIRE( dig.remoteHost() == "exao3" );
228 REQUIRE( dig.localPort() == 85 );
229 REQUIRE( dig.remotePort() == 86 );
230 }
231
232 WHEN( "No tunnels match configName" )
233 {
234 mx::app::writeConfigFile(
235 "/tmp/sshDigger_test.conf",
236 { "tunnel1", "tunnel1", "tunnel1", "tunnel2", "tunnel2", "tunnel2" },
237 { "remoteHost", "localPort", "remotePort", "remoteHost", "localPort", "remotePort" },
238 { "exao2", "80", "81", "exao3", "85", "86" } );
239
240 mx::app::appConfigurator config;
241 config.readConfig( "/tmp/sshDigger_test.conf" );
242
243 sshDigger_test dig;
244 dig.configName( "tunnel3" );
245 int rv;
246 rv = dig.loadConfigImpl( config );
247 REQUIRE( rv == SSHDIGGER_E_NOTUNNELFOUND );
248 }
249
250 WHEN( "no remote host in first tunnel" )
251 {
252 mx::app::writeConfigFile( "/tmp/sshDigger_test.conf",
253 { "tunnel1", "tunnel1", "tunnel2", "tunnel2", "tunnel2" },
254 { "localPort", "remotePort", "remoteHost", "localPort", "remotePort" },
255 { "80", "81", "exao3", "85", "86" } );
256
257 mx::app::appConfigurator config;
258 config.readConfig( "/tmp/sshDigger_test.conf" );
259
260 sshDigger_test dig;
261 dig.configName( "tunnel1" );
262 int rv;
263 rv = dig.loadConfigImpl( config );
264 REQUIRE( rv == SSHDIGGER_E_NOHOSTNAME );
265
266 dig.configName( "tunnel2" );
267
268 rv = dig.loadConfigImpl( config );
269 REQUIRE( rv == 0 );
270 REQUIRE( dig.remoteHost() == "exao3" );
271 REQUIRE( dig.localPort() == 85 );
272 REQUIRE( dig.remotePort() == 86 );
273 }
274
275 WHEN( "no remote host in 2nd tunnel" )
276 {
277 mx::app::writeConfigFile( "/tmp/sshDigger_test.conf",
278 { "tunnel1", "tunnel1", "tunnel1", "tunnel2", "tunnel2" },
279 { "remoteHost", "localPort", "remotePort", "localPort", "remotePort" },
280 { "exao2", "80", "81", "85", "86" } );
281
282 mx::app::appConfigurator config;
283 config.readConfig( "/tmp/sshDigger_test.conf" );
284
285 sshDigger_test dig;
286 dig.configName( "tunnel2" );
287 int rv;
288 rv = dig.loadConfigImpl( config );
289 REQUIRE( rv == SSHDIGGER_E_NOHOSTNAME );
290
291 dig.configName( "tunnel1" );
292
293 rv = dig.loadConfigImpl( config );
294 REQUIRE( rv == 0 );
295 REQUIRE( dig.remoteHost() == "exao2" );
296 REQUIRE( dig.localPort() == 80 );
297 REQUIRE( dig.remotePort() == 81 );
298 }
299
300 WHEN( "no local port in first tunnel" )
301 {
302 mx::app::writeConfigFile( "/tmp/sshDigger_test.conf",
303 { "tunnel1", "tunnel1", "tunnel2", "tunnel2", "tunnel2" },
304 { "remoteHost", "remotePort", "remoteHost", "localPort", "remotePort" },
305 { "exao2", "81", "exao3", "85", "86" } );
306
307 mx::app::appConfigurator config;
308 config.readConfig( "/tmp/sshDigger_test.conf" );
309
310 sshDigger_test dig;
311 dig.configName( "tunnel1" );
312 int rv;
313 rv = dig.loadConfigImpl( config );
314 REQUIRE( rv == SSHDIGGER_E_NOLOCALPORT );
315
316 dig.configName( "tunnel2" );
317
318 rv = dig.loadConfigImpl( config );
319 REQUIRE( rv == 0 );
320 REQUIRE( dig.remoteHost() == "exao3" );
321 REQUIRE( dig.localPort() == 85 );
322 REQUIRE( dig.remotePort() == 86 );
323 }
324
325 WHEN( "no local port in second tunnel" )
326 {
327 mx::app::writeConfigFile( "/tmp/sshDigger_test.conf",
328 { "tunnel1", "tunnel1", "tunnel1", "tunnel2", "tunnel2" },
329 { "remoteHost", "localPort", "remotePort", "remoteHost", "remotePort" },
330 { "exao2", "80", "81", "exao3", "86" } );
331
332 mx::app::appConfigurator config;
333 config.readConfig( "/tmp/sshDigger_test.conf" );
334
335 sshDigger_test dig;
336 dig.configName( "tunnel2" );
337 int rv;
338 rv = dig.loadConfigImpl( config );
339 REQUIRE( rv == SSHDIGGER_E_NOLOCALPORT );
340
341 dig.configName( "tunnel1" );
342
343 rv = dig.loadConfigImpl( config );
344 REQUIRE( rv == 0 );
345 REQUIRE( dig.remoteHost() == "exao2" );
346 REQUIRE( dig.localPort() == 80 );
347 REQUIRE( dig.remotePort() == 81 );
348 }
349
350 WHEN( "no remote port in first tunnel" )
351 {
352 mx::app::writeConfigFile( "/tmp/sshDigger_test.conf",
353 { "tunnel1", "tunnel1", "tunnel2", "tunnel2", "tunnel2" },
354 { "remoteHost", "localPort", "remoteHost", "localPort", "remotePort" },
355 { "exao2", "80", "exao3", "85", "86" } );
356
357 mx::app::appConfigurator config;
358 config.readConfig( "/tmp/sshDigger_test.conf" );
359
360 sshDigger_test dig;
361 dig.configName( "tunnel1" );
362 int rv;
363 rv = dig.loadConfigImpl( config );
364 REQUIRE( rv == SSHDIGGER_E_NOREMOTEPORT );
365
366 dig.configName( "tunnel2" );
367
368 rv = dig.loadConfigImpl( config );
369 REQUIRE( rv == 0 );
370 REQUIRE( dig.remoteHost() == "exao3" );
371 REQUIRE( dig.localPort() == 85 );
372 REQUIRE( dig.remotePort() == 86 );
373 }
374
375 WHEN( "no remote port in second tunnel" )
376 {
377 mx::app::writeConfigFile( "/tmp/sshDigger_test.conf",
378 { "tunnel1", "tunnel1", "tunnel1", "tunnel2", "tunnel2" },
379 { "remoteHost", "localPort", "remotePort", "remoteHost", "localPort" },
380 { "exao2", "80", "81", "exao3", "85" } );
381
382 mx::app::appConfigurator config;
383 config.readConfig( "/tmp/sshDigger_test.conf" );
384
385 sshDigger_test dig;
386 dig.configName( "tunnel2" );
387 int rv;
388 rv = dig.loadConfigImpl( config );
389 REQUIRE( rv == SSHDIGGER_E_NOREMOTEPORT );
390
391 dig.configName( "tunnel1" );
392
393 rv = dig.loadConfigImpl( config );
394 REQUIRE( rv == 0 );
395 REQUIRE( dig.remoteHost() == "exao2" );
396 REQUIRE( dig.localPort() == 80 );
397 REQUIRE( dig.remotePort() == 81 );
398 }
399 }
400}
401
402} // namespace sshDiggerTest
403
404} // namespace libXWCTest
405
406SCENARIO( "sshDigger tunnel exec preparation", "[sshDigger]" )
407{
408 GIVEN( "a config file with 1 tunnel" )
409 {
410 WHEN( "creating the tunnelSpec" )
411 {
412 mx::app::writeConfigFile( "/tmp/sshDigger_test.conf",
413 { "tunnel1", "tunnel1", "tunnel1" },
414 { "remoteHost", "localPort", "remotePort" },
415 { "exao2", "80", "81" } );
416
417 mx::app::appConfigurator config;
418 config.readConfig( "/tmp/sshDigger_test.conf" );
419
420 sshDigger_test dig;
421 dig.configName( "tunnel1" );
422 int rv;
423 rv = dig.loadConfigImpl( config );
424 REQUIRE( rv == 0 );
425
426 REQUIRE( dig.tunnelSpec() == "80:localhost:81" );
427 }
428
429 WHEN( "creating the exec argv vector" )
430 {
431 mx::app::writeConfigFile( "/tmp/sshDigger_test.conf",
432 { "tunnel1", "tunnel1", "tunnel1" },
433 { "remoteHost", "localPort", "remotePort" },
434 { "exao2", "80", "81" } );
435
436 mx::app::appConfigurator config;
437 config.readConfig( "/tmp/sshDigger_test.conf" );
438
439 sshDigger_test dig;
440 dig.configName( "tunnel1" );
441 int rv;
442 rv = dig.loadConfigImpl( config );
443 REQUIRE( rv == 0 );
444
445 std::vector<std::string> argsV;
446 dig.genArgsV( argsV );
447
448 REQUIRE( argsV[0] == "autossh" );
449 REQUIRE( argsV[1] == "-M0" );
450 REQUIRE( argsV[2] == "" );
451 REQUIRE( argsV[3] == "-nNTL" );
452 REQUIRE( argsV[4] == "80:localhost:81" );
453 REQUIRE( argsV[5] == "exao2" );
454 }
455 }
456}
The MagAO-X SSH tunnel manager.
Definition sshDigger.hpp:55
int loadConfigImpl(mx::app::appConfigurator &_config)
Implementation of loadConfig logic, separated for testing.
std::string tunnelSpec()
Create the tunnel specification string, [localPort]:localhost:[remotePort].
void genArgsV(std::vector< std::string > &argsV)
Generate the argv vector for the exec of autossh.
SCENARIO("sshDigger Configuration", "[sshDigger]")
Verify sshDigger::loadConfigImpl() and command helpers interpret tunnel definitions correctly.
Namespace for all libXWC tests.
#define SSHDIGGER_E_NOLOCALPORT
Definition sshDigger.hpp:36
#define SSHDIGGER_E_NOTUNNELFOUND
Definition sshDigger.hpp:34
#define SSHDIGGER_E_NOREMOTEPORT
Definition sshDigger.hpp:37
#define SSHDIGGER_E_NOHOSTNAME
Definition sshDigger.hpp:35
#define SSHDIGGER_E_NOTUNNELS
Definition sshDigger.hpp:33
SCENARIO("sshDigger tunnel exec preparation", "[sshDigger]")