2015-10-29 19:34:36 +01:00
# pragma once
# ifndef MESSMER_CRYFS_TEST_CLI_TESTUTILS_CLITEST_H
# define MESSMER_CRYFS_TEST_CLI_TESTUTILS_CLITEST_H
2016-02-11 16:39:42 +01:00
# include <gtest/gtest.h>
# include <gmock/gmock.h>
# include <cpp-utils/tempfile/TempDir.h>
# include <cpp-utils/tempfile/TempFile.h>
2016-02-23 21:07:23 +01:00
# include <cryfs-cli/Cli.h>
# include <cryfs-cli/VersionChecker.h>
2016-02-11 16:39:42 +01:00
# include <cpp-utils/logging/logging.h>
# include <cpp-utils/process/subprocess.h>
# include <cpp-utils/network/FakeHttpClient.h>
2016-02-23 21:07:23 +01:00
# include "../../cryfs/testutils/MockConsole.h"
2017-09-30 10:18:46 +02:00
# include "../../cryfs/testutils/TestWithFakeHomeDirectory.h"
2018-02-02 01:08:01 +01:00
# include <cryfs/ErrorCodes.h>
# include <cpp-utils/testutils/CaptureStderrRAII.h>
2015-10-29 19:34:36 +01:00
2017-09-30 10:18:46 +02:00
class CliTest : public : : testing : : Test , TestWithFakeHomeDirectory {
2015-10-29 19:34:36 +01:00
public :
2016-01-25 15:01:34 +01:00
CliTest ( ) : _basedir ( ) , _mountdir ( ) , basedir ( _basedir . path ( ) ) , mountdir ( _mountdir . path ( ) ) , logfile ( ) , configfile ( false ) , console ( std : : make_shared < MockConsole > ( ) ) { }
2015-10-29 19:34:36 +01:00
2015-10-30 17:23:08 +01:00
cpputils : : TempDir _basedir ;
cpputils : : TempDir _mountdir ;
boost : : filesystem : : path basedir ;
boost : : filesystem : : path mountdir ;
2015-10-29 19:34:36 +01:00
cpputils : : TempFile logfile ;
cpputils : : TempFile configfile ;
2016-01-25 15:01:34 +01:00
std : : shared_ptr < MockConsole > console ;
2015-10-29 19:34:36 +01:00
2017-09-30 23:24:33 +02:00
cpputils : : unique_ref < cpputils : : HttpClient > _httpClient ( ) {
cpputils : : unique_ref < cpputils : : FakeHttpClient > httpClient = cpputils : : make_unique_ref < cpputils : : FakeHttpClient > ( ) ;
2016-01-28 18:55:26 +01:00
httpClient - > addWebsite ( " https://www.cryfs.org/version_info.json " , " { \" version_info \" :{ \" current \" : \" 0.8.5 \" }} " ) ;
2017-10-08 17:14:51 +02:00
return std : : move ( httpClient ) ;
2016-01-28 18:55:26 +01:00
}
2018-02-02 01:08:01 +01:00
int run ( std : : vector < const char * > args ) {
2016-05-10 01:07:02 +02:00
std : : vector < const char * > _args ;
2015-10-29 19:34:36 +01:00
_args . reserve ( args . size ( ) + 1 ) ;
2016-05-10 01:07:02 +02:00
_args . push_back ( " cryfs " ) ;
2015-10-29 19:34:36 +01:00
for ( const char * arg : args ) {
2016-05-10 01:07:02 +02:00
_args . push_back ( arg ) ;
2015-10-29 19:34:36 +01:00
}
2015-11-03 21:22:35 +01:00
auto & keyGenerator = cpputils : : Random : : PseudoRandom ( ) ;
2016-02-13 15:06:28 +01:00
// Write 2x 'pass\n' to stdin so Cryfs can read it as password (+ password confirmation prompt)
std : : cin . putback ( ' \n ' ) ; std : : cin . putback ( ' s ' ) ; std : : cin . putback ( ' s ' ) ; std : : cin . putback ( ' a ' ) ; std : : cin . putback ( ' p ' ) ;
std : : cin . putback ( ' \n ' ) ; std : : cin . putback ( ' s ' ) ; std : : cin . putback ( ' s ' ) ; std : : cin . putback ( ' a ' ) ; std : : cin . putback ( ' p ' ) ;
// Run Cryfs
2018-02-02 01:21:51 +01:00
return cryfs : : Cli ( keyGenerator , cpputils : : SCrypt : : TestSettings , console ) . main ( _args . size ( ) , _args . data ( ) , _httpClient ( ) ) ;
2015-10-29 19:34:36 +01:00
}
2018-02-02 01:08:01 +01:00
void EXPECT_EXIT_WITH_HELP_MESSAGE ( std : : vector < const char * > args , const std : : string & message , cryfs : : ErrorCode errorCode ) {
EXPECT_RUN_ERROR ( args , ( " .*Usage:.* " + message ) . c_str ( ) , errorCode ) ;
2015-10-29 19:34:36 +01:00
}
2018-02-02 01:08:01 +01:00
void EXPECT_RUN_ERROR ( std : : vector < const char * > args , const char * message , cryfs : : ErrorCode errorCode ) {
cpputils : : CaptureStderrRAII capturedStderr ;
int exit_code = run ( args ) ;
capturedStderr . EXPECT_MATCHES ( string ( " .* " ) + message + " .* " ) ;
EXPECT_EQ ( exitCode ( errorCode ) , exit_code ) ;
2015-10-29 19:34:36 +01:00
}
2015-10-30 22:24:18 +01:00
void EXPECT_RUN_SUCCESS ( std : : vector < const char * > args , const boost : : filesystem : : path & mountDir ) {
2015-11-03 22:02:04 +01:00
//TODO Make this work when run in background
ASSERT ( std : : find ( args . begin ( ) , args . end ( ) , string ( " -f " ) ) ! = args . end ( ) , " Currently only works if run in foreground " ) ;
2015-11-02 21:20:10 +01:00
std : : thread unmountThread ( [ & mountDir ] {
int returncode = - 1 ;
while ( returncode ! = 0 ) {
2017-08-24 22:58:41 +02:00
# ifdef __APPLE__
2018-05-20 09:14:17 +02:00
returncode = cpputils : : Subprocess : : call ( std : : string ( " umount " ) + mountDir . c_str ( ) + " 2>/dev/null " ) . exitcode ;
2017-08-24 22:58:41 +02:00
# else
2018-05-20 09:14:17 +02:00
returncode = cpputils : : Subprocess : : call ( std : : string ( " fusermount -u " ) + mountDir . c_str ( ) + " 2>/dev/null " ) . exitcode ;
2017-08-24 22:58:41 +02:00
# endif
//std::this_thread::sleep_for(std::chrono::milliseconds(50)); // TODO Is this the test case duration? Does a shorter interval make the test case faster?
2015-11-02 21:20:10 +01:00
}
} ) ;
2015-11-04 05:27:00 +01:00
testing : : internal : : CaptureStdout ( ) ;
2015-11-02 21:20:10 +01:00
run ( args ) ;
unmountThread . join ( ) ;
2015-11-04 05:27:00 +01:00
EXPECT_THAT ( testing : : internal : : GetCapturedStdout ( ) , testing : : MatchesRegex ( " .*Mounting filesystem.* " ) ) ;
2015-10-29 19:34:36 +01:00
}
} ;
# endif