2008-03-19 12:29:14 +01:00
/*
2009-03-25 15:21:04 +01:00
* Copyright ( C ) 2008 - 2009 Patrick Ohly < patrick . ohly @ gmx . de >
* Copyright ( C ) 2009 Intel Corporation
2009-04-30 18:14:03 +02:00
*
* This library is free software ; you can redistribute it and / or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation ; either
* version 2.1 of the License , or ( at your option ) version 3.
*
* This library is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* Lesser General Public License for more details .
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library ; if not , write to the Free Software
* Foundation , Inc . , 51 Franklin Street , Fifth Floor , Boston , MA
* 02110 - 1301 USA
2008-03-19 12:29:14 +01:00
*/
# include "SyncEvolutionCmdline.h"
# include "FilterConfigNode.h"
# include "VolatileConfigNode.h"
# include "EvolutionSyncSource.h"
# include "EvolutionSyncClient.h"
# include "SyncEvolutionUtil.h"
2008-03-19 17:43:31 +01:00
# include <unistd.h>
# include <errno.h>
2008-03-19 12:29:14 +01:00
# include <iostream>
2009-04-15 21:03:26 +02:00
# include <iomanip>
2008-03-28 23:32:00 +01:00
# include <sstream>
2008-03-19 12:29:14 +01:00
# include <memory>
# include <set>
2008-03-19 15:35:22 +01:00
# include <algorithm>
2008-03-19 12:29:14 +01:00
using namespace std ;
# include <boost/shared_ptr.hpp>
2009-06-10 17:28:45 +02:00
# include <boost/algorithm/string/join.hpp>
2008-03-29 16:41:11 +01:00
# include <boost/algorithm/string.hpp>
2008-03-30 15:11:45 +02:00
# include <boost/foreach.hpp>
2008-03-19 12:29:14 +01:00
2008-03-29 15:16:34 +01:00
SyncEvolutionCmdline : : SyncEvolutionCmdline ( int argc , const char * const * argv , ostream & out , ostream & err ) :
2008-03-19 12:29:14 +01:00
m_argc ( argc ) ,
m_argv ( argv ) ,
m_out ( out ) ,
m_err ( err ) ,
m_validSyncProps ( EvolutionSyncConfig : : getRegistry ( ) ) ,
m_validSourceProps ( EvolutionSyncSourceConfig : : getRegistry ( ) )
{ }
bool SyncEvolutionCmdline : : parse ( )
{
int opt = 1 ;
while ( opt < m_argc ) {
if ( m_argv [ opt ] [ 0 ] ! = ' - ' ) {
break ;
}
2008-03-29 16:41:11 +01:00
if ( boost : : iequals ( m_argv [ opt ] , " --sync " ) | |
boost : : iequals ( m_argv [ opt ] , " -s " ) ) {
2008-03-19 12:29:14 +01:00
opt + + ;
string param ;
string cmdopt ( m_argv [ opt - 1 ] ) ;
2008-03-19 13:11:39 +01:00
if ( ! parseProp ( m_validSourceProps , m_sourceProps ,
2008-03-19 12:29:14 +01:00
m_argv [ opt - 1 ] , opt = = m_argc ? NULL : m_argv [ opt ] ,
2008-06-15 23:31:36 +02:00
EvolutionSyncSourceConfig : : m_sourcePropSync . getName ( ) . c_str ( ) ) ) {
2008-03-19 12:29:14 +01:00
return false ;
}
2008-08-03 22:48:45 +02:00
// disable requirement to add --run explicitly in order to
// be compatible with traditional command lines
m_run = true ;
2008-03-29 16:41:11 +01:00
} else if ( boost : : iequals ( m_argv [ opt ] , " --sync-property " ) | |
boost : : iequals ( m_argv [ opt ] , " -y " ) ) {
2008-03-19 12:29:14 +01:00
opt + + ;
if ( ! parseProp ( m_validSyncProps , m_syncProps ,
m_argv [ opt - 1 ] , opt = = m_argc ? NULL : m_argv [ opt ] ) ) {
return false ;
}
2008-03-29 16:41:11 +01:00
} else if ( boost : : iequals ( m_argv [ opt ] , " --source-property " ) | |
boost : : iequals ( m_argv [ opt ] , " -z " ) ) {
2008-03-19 12:29:14 +01:00
opt + + ;
if ( ! parseProp ( m_validSourceProps , m_sourceProps ,
m_argv [ opt - 1 ] , opt = = m_argc ? NULL : m_argv [ opt ] ) ) {
return false ;
}
2008-03-29 16:41:11 +01:00
} else if ( boost : : iequals ( m_argv [ opt ] , " --template " ) | |
boost : : iequals ( m_argv [ opt ] , " -l " ) ) {
2008-03-19 12:29:14 +01:00
opt + + ;
if ( opt > = m_argc ) {
usage ( true , string ( " missing parameter for " ) + cmdOpt ( m_argv [ opt - 1 ] ) ) ;
return false ;
}
m_template = m_argv [ opt ] ;
2008-03-30 23:50:51 +02:00
m_configure = true ;
2008-03-30 15:11:45 +02:00
if ( boost : : trim_copy ( m_template ) = = " ? " ) {
2008-03-19 17:43:31 +01:00
dumpServers ( " Available configuration templates: " ,
EvolutionSyncConfig : : getServerTemplates ( ) ) ;
m_dontrun = true ;
}
2008-03-29 16:41:11 +01:00
} else if ( boost : : iequals ( m_argv [ opt ] , " --print-servers " ) ) {
2008-03-19 12:29:14 +01:00
m_printServers = true ;
2008-03-29 16:41:11 +01:00
} else if ( boost : : iequals ( m_argv [ opt ] , " --print-config " ) | |
boost : : iequals ( m_argv [ opt ] , " -p " ) ) {
2008-03-19 12:29:14 +01:00
m_printConfig = true ;
2009-04-15 15:58:05 +02:00
} else if ( boost : : iequals ( m_argv [ opt ] , " --print-sessions " ) ) {
m_printSessions = true ;
2008-03-29 16:41:11 +01:00
} else if ( boost : : iequals ( m_argv [ opt ] , " --configure " ) | |
boost : : iequals ( m_argv [ opt ] , " -c " ) ) {
2008-03-19 12:29:14 +01:00
m_configure = true ;
2009-04-15 14:02:09 +02:00
} else if ( boost : : iequals ( m_argv [ opt ] , " --remove " ) ) {
m_remove = true ;
2008-08-03 15:00:51 +02:00
} else if ( boost : : iequals ( m_argv [ opt ] , " --run " ) | |
boost : : iequals ( m_argv [ opt ] , " -r " ) ) {
m_run = true ;
2009-04-23 16:47:07 +02:00
} else if ( boost : : iequals ( m_argv [ opt ] , " --restore " ) ) {
opt + + ;
if ( opt > = m_argc ) {
usage ( true , string ( " missing parameter for " ) + cmdOpt ( m_argv [ opt - 1 ] ) ) ;
return false ;
}
m_restore = m_argv [ opt ] ;
if ( m_restore . empty ( ) ) {
usage ( true , string ( " missing parameter for " ) + cmdOpt ( m_argv [ opt - 1 ] ) ) ;
return false ;
}
if ( ! isDir ( m_restore ) ) {
usage ( true , string ( " parameter ' " ) + m_restore + " ' for " + cmdOpt ( m_argv [ opt - 1 ] ) + " must be log directory " ) ;
return false ;
}
} else if ( boost : : iequals ( m_argv [ opt ] , " --before " ) ) {
m_before = true ;
} else if ( boost : : iequals ( m_argv [ opt ] , " --after " ) ) {
m_after = true ;
} else if ( boost : : iequals ( m_argv [ opt ] , " --dry-run " ) ) {
m_dryrun = true ;
2008-03-29 16:41:11 +01:00
} else if ( boost : : iequals ( m_argv [ opt ] , " --migrate " ) ) {
2008-03-19 12:29:14 +01:00
m_migrate = true ;
2008-03-29 16:41:11 +01:00
} else if ( boost : : iequals ( m_argv [ opt ] , " --status " ) | |
boost : : iequals ( m_argv [ opt ] , " -t " ) ) {
2008-03-19 12:29:14 +01:00
m_status = true ;
2008-03-29 16:41:11 +01:00
} else if ( boost : : iequals ( m_argv [ opt ] , " --quiet " ) | |
boost : : iequals ( m_argv [ opt ] , " -q " ) ) {
2008-03-19 12:29:14 +01:00
m_quiet = true ;
2008-03-29 16:41:11 +01:00
} else if ( boost : : iequals ( m_argv [ opt ] , " --help " ) | |
boost : : iequals ( m_argv [ opt ] , " -h " ) ) {
2008-03-19 12:29:14 +01:00
m_usage = true ;
2008-03-29 16:41:11 +01:00
} else if ( boost : : iequals ( m_argv [ opt ] , " --version " ) ) {
2008-03-19 12:29:14 +01:00
m_version = true ;
2008-03-19 13:11:39 +01:00
} else {
usage ( false , string ( m_argv [ opt ] ) + " : unknown parameter " ) ;
return false ;
2008-03-19 12:29:14 +01:00
}
opt + + ;
}
if ( opt < m_argc ) {
m_server = m_argv [ opt + + ] ;
while ( opt < m_argc ) {
m_sources . insert ( m_argv [ opt + + ] ) ;
}
}
return true ;
}
bool SyncEvolutionCmdline : : run ( ) {
2009-04-23 16:47:07 +02:00
// --dry-run is only supported by some operations.
// Be very strict about it and make sure it is off in all
// potentially harmful operations, otherwise users might
// expect it to have an effect when it doesn't.
2008-03-19 12:29:14 +01:00
if ( m_usage ) {
usage ( true ) ;
} else if ( m_version ) {
printf ( " SyncEvolution %s \n " , VERSION ) ;
2008-10-10 23:57:55 +02:00
printf ( " %s " , EDSAbiWrapperInfo ( ) ) ;
2008-03-30 15:11:45 +02:00
} else if ( m_printServers | | boost : : trim_copy ( m_server ) = = " ? " ) {
2008-03-19 17:43:31 +01:00
dumpServers ( " Configured servers: " ,
EvolutionSyncConfig : : getServers ( ) ) ;
2008-03-19 12:29:14 +01:00
} else if ( m_dontrun ) {
// user asked for information
} else if ( m_argc = = 1 ) {
2009-04-23 16:47:07 +02:00
// no parameters: list databases and short usage
2008-03-19 12:29:14 +01:00
const SourceRegistry & registry ( EvolutionSyncSource : : getSourceRegistry ( ) ) ;
boost : : shared_ptr < FilterConfigNode > configNode ( new VolatileConfigNode ( ) ) ;
boost : : shared_ptr < FilterConfigNode > hiddenNode ( new VolatileConfigNode ( ) ) ;
boost : : shared_ptr < FilterConfigNode > trackingNode ( new VolatileConfigNode ( ) ) ;
SyncSourceNodes nodes ( configNode , hiddenNode , trackingNode ) ;
EvolutionSyncSourceParams params ( " list " , nodes , " " ) ;
2008-07-11 22:25:02 +02:00
BOOST_FOREACH ( const RegisterSyncSource * source , registry ) {
BOOST_FOREACH ( const Values : : value_type & alias , source - > m_typeValues ) {
if ( ! alias . empty ( ) & & source - > m_enabled ) {
configNode - > setProperty ( " type " , * alias . begin ( ) ) ;
2008-03-19 12:29:14 +01:00
auto_ptr < EvolutionSyncSource > source ( EvolutionSyncSource : : createSource ( params , false ) ) ;
if ( source . get ( ) ! = NULL ) {
2008-07-11 22:25:02 +02:00
listSources ( * source , boost : : join ( alias , " = " ) ) ;
2008-03-30 17:15:00 +02:00
m_out < < " \n " ;
2008-03-19 12:29:14 +01:00
}
}
}
}
usage ( false ) ;
} else if ( m_printConfig ) {
2008-03-19 15:35:22 +01:00
boost : : shared_ptr < EvolutionSyncConfig > config ;
if ( m_template . empty ( ) ) {
2008-03-30 13:43:36 +02:00
if ( m_server . empty ( ) ) {
m_err < < " ERROR: --print-config requires either a --template or a server name. " < < endl ;
return false ;
}
2008-03-19 15:35:22 +01:00
config . reset ( new EvolutionSyncConfig ( m_server ) ) ;
if ( ! config - > exists ( ) ) {
2008-03-30 13:43:36 +02:00
m_err < < " ERROR: server ' " < < m_server < < " ' has not been configured yet. " < < endl ;
2008-03-19 15:35:22 +01:00
return false ;
}
} else {
config = EvolutionSyncConfig : : createServerTemplate ( m_template ) ;
if ( ! config . get ( ) ) {
2008-03-30 13:43:36 +02:00
m_err < < " ERROR: no configuration template for ' " < < m_template < < " ' available. " < < endl ;
2008-03-19 15:35:22 +01:00
return false ;
}
}
2008-08-03 15:00:51 +02:00
if ( m_sources . empty ( ) | |
m_sources . find ( " main " ) ! = m_sources . end ( ) ) {
2008-03-19 15:35:22 +01:00
boost : : shared_ptr < FilterConfigNode > syncProps ( config - > getProperties ( ) ) ;
2008-03-19 12:29:14 +01:00
syncProps - > setFilter ( m_syncProps ) ;
2008-03-19 15:35:22 +01:00
dumpProperties ( * syncProps , config - > getRegistry ( ) ) ;
2008-03-19 12:29:14 +01:00
}
2008-07-06 22:49:19 +02:00
list < string > sources = config - > getSyncSources ( ) ;
sources . sort ( ) ;
2008-07-11 22:25:02 +02:00
BOOST_FOREACH ( const string & name , sources ) {
2008-03-19 12:29:14 +01:00
if ( m_sources . empty ( ) | |
2008-07-11 22:25:02 +02:00
m_sources . find ( name ) ! = m_sources . end ( ) ) {
m_out < < endl < < " [ " < < name < < " ] " < < endl ;
ConstSyncSourceNodes nodes = config - > getSyncSourceNodes ( name ) ;
2008-03-20 23:05:10 +01:00
boost : : shared_ptr < FilterConfigNode > sourceProps ( new FilterConfigNode ( boost : : shared_ptr < const ConfigNode > ( nodes . m_configNode ) ) ) ;
2008-03-19 12:29:14 +01:00
sourceProps - > setFilter ( m_sourceProps ) ;
2008-03-20 23:05:10 +01:00
dumpProperties ( * sourceProps , EvolutionSyncSourceConfig : : getRegistry ( ) ) ;
2008-03-19 12:29:14 +01:00
}
}
2008-03-19 15:35:22 +01:00
} else if ( m_server = = " " & & m_argc > 1 ) {
// Options given, but no server - not sure what the user wanted?!
usage ( true , " server name missing " ) ;
return false ;
2008-03-19 12:29:14 +01:00
} else if ( m_configure | | m_migrate ) {
2009-04-23 16:47:07 +02:00
if ( m_dryrun ) {
EvolutionSyncClient : : throwError ( " --dry-run not supported for configuration changes " ) ;
}
2008-03-30 15:11:45 +02:00
bool fromScratch = false ;
2008-03-19 17:43:31 +01:00
// Both config changes and migration are implemented as copying from
// another config (template resp. old one). Migration also moves
// the old config.
boost : : shared_ptr < EvolutionSyncConfig > from ;
if ( m_migrate ) {
from . reset ( new EvolutionSyncConfig ( m_server ) ) ;
if ( ! from - > exists ( ) ) {
2008-03-30 13:43:36 +02:00
m_err < < " ERROR: server ' " < < m_server < < " ' has not been configured yet. " < < endl ;
2008-03-19 17:43:31 +01:00
return false ;
}
int counter = 0 ;
string oldRoot = from - > getRootPath ( ) ;
string suffix ;
while ( true ) {
string newname ;
ostringstream newsuffix ;
newsuffix < < " .old " ;
if ( counter ) {
newsuffix < < " . " < < counter ;
}
suffix = newsuffix . str ( ) ;
newname = oldRoot + suffix ;
if ( ! rename ( oldRoot . c_str ( ) ,
newname . c_str ( ) ) ) {
break ;
} else if ( errno ! = EEXIST & & errno ! = ENOTEMPTY ) {
m_err < < " ERROR: renaming " < < oldRoot < < " to " < <
newname < < " : " < < strerror ( errno ) < < endl ;
return false ;
}
counter + + ;
}
from . reset ( new EvolutionSyncConfig ( m_server + suffix ) ) ;
} else {
from . reset ( new EvolutionSyncConfig ( m_server ) ) ;
if ( ! from - > exists ( ) ) {
// creating from scratch, look for template
2008-03-30 15:11:45 +02:00
fromScratch = true ;
2008-03-19 17:43:31 +01:00
string configTemplate = m_template . empty ( ) ? m_server : m_template ;
from = EvolutionSyncConfig : : createServerTemplate ( configTemplate ) ;
if ( ! from . get ( ) ) {
2008-03-30 13:43:36 +02:00
m_err < < " ERROR: no configuration template for ' " < < configTemplate < < " ' available. " < < endl ;
2008-03-19 17:43:31 +01:00
dumpServers ( " Available configuration templates: " ,
EvolutionSyncConfig : : getServerTemplates ( ) ) ;
return false ;
}
}
}
// apply config changes on-the-fly
from - > setConfigFilter ( true , m_syncProps ) ;
from - > setConfigFilter ( false , m_sourceProps ) ;
// write into the requested configuration, creating it if necessary
boost : : shared_ptr < EvolutionSyncConfig > to ( new EvolutionSyncConfig ( m_server ) ) ;
2008-03-30 15:41:56 +02:00
to - > copy ( * from , ! fromScratch & & ! m_sources . empty ( ) ? & m_sources : NULL ) ;
2008-03-30 15:11:45 +02:00
2008-07-02 21:36:02 +02:00
// Sources are active now according to the server default.
// Disable all sources not selected by user (if any selected)
// and those which have no database.
if ( fromScratch ) {
2008-03-30 15:11:45 +02:00
list < string > configuredSources = to - > getSyncSources ( ) ;
2008-07-02 21:36:02 +02:00
set < string > sources = m_sources ;
2008-03-30 15:11:45 +02:00
BOOST_FOREACH ( const string & source , configuredSources ) {
boost : : shared_ptr < PersistentEvolutionSyncSourceConfig > sourceConfig ( to - > getSyncSourceConfig ( source ) ) ;
2008-07-02 21:36:02 +02:00
string disable = " " ;
set < string > : : iterator entry = sources . find ( source ) ;
bool selected = entry ! = sources . end ( ) ;
if ( ! m_sources . empty ( ) & &
! selected ) {
disable = " not selected " ;
} else {
if ( entry ! = sources . end ( ) ) {
// The command line parameter matched a valid source.
// All entries left afterwards must have been typos.
sources . erase ( entry ) ;
}
// check whether the sync source works
EvolutionSyncSourceParams params ( " list " , to - > getSyncSourceNodes ( source ) , " " ) ;
auto_ptr < EvolutionSyncSource > syncSource ( EvolutionSyncSource : : createSource ( params , false ) ) ;
if ( syncSource . get ( ) = = NULL ) {
disable = " no backend available " ;
} else {
try {
2008-07-10 21:17:42 +02:00
EvolutionSyncSource : : Databases databases = syncSource - > getDatabases ( ) ;
if ( databases . empty ( ) ) {
2008-07-02 21:36:02 +02:00
disable = " no database to synchronize " ;
}
} catch ( . . . ) {
disable = " backend failed " ;
}
}
}
if ( ! disable . empty ( ) ) {
// abort if the user explicitly asked for the sync source
// and it cannot be enabled, otherwise disable it silently
if ( selected ) {
EvolutionSyncClient : : throwError ( source + " : " + disable ) ;
}
sourceConfig - > setSync ( " disabled " ) ;
} else if ( selected ) {
// user absolutely wants it: enable even if off by default
FilterConfigNode : : ConfigFilter : : const_iterator sync =
m_sourceProps . find ( EvolutionSyncSourceConfig : : m_sourcePropSync . getName ( ) ) ;
sourceConfig - > setSync ( sync = = m_sourceProps . end ( ) ? " two-way " : sync - > second ) ;
}
}
if ( ! sources . empty ( ) ) {
EvolutionSyncClient : : throwError ( string ( " no such source(s): " ) + boost : : join ( sources , " " ) ) ;
2008-03-30 15:11:45 +02:00
}
}
2008-03-19 17:43:31 +01:00
// done, now write it
to - > flush ( ) ;
2009-04-15 14:02:09 +02:00
} else if ( m_remove ) {
2009-04-23 16:47:07 +02:00
if ( m_dryrun ) {
EvolutionSyncClient : : throwError ( " --dry-run not supported for removing configurations " ) ;
}
2009-04-15 14:02:09 +02:00
// extra sanity check
if ( ! m_sources . empty ( ) | |
! m_syncProps . empty ( ) | |
! m_sourceProps . empty ( ) ) {
usage ( true , " too many parameters for --remove " ) ;
return false ;
} else {
boost : : shared_ptr < EvolutionSyncConfig > config ;
config . reset ( new EvolutionSyncConfig ( m_server ) ) ;
config - > remove ( ) ;
return true ;
}
2008-03-19 12:29:14 +01:00
} else {
EvolutionSyncClient client ( m_server , true , m_sources ) ;
client . setQuiet ( m_quiet ) ;
2009-04-23 16:47:07 +02:00
client . setDryRun ( m_dryrun ) ;
2008-03-19 12:29:14 +01:00
client . setConfigFilter ( true , m_syncProps ) ;
client . setConfigFilter ( false , m_sourceProps ) ;
if ( m_status ) {
client . status ( ) ;
2009-04-15 15:58:05 +02:00
} else if ( m_printSessions ) {
vector < string > dirs ;
client . getSessions ( dirs ) ;
2009-04-16 12:07:49 +02:00
bool first = true ;
2009-04-15 15:58:05 +02:00
BOOST_FOREACH ( const string & dir , dirs ) {
2009-04-16 12:07:49 +02:00
if ( first ) {
first = false ;
} else if ( ! m_quiet ) {
cout < < endl ;
}
2009-04-15 15:58:05 +02:00
cout < < dir < < endl ;
2009-04-16 12:07:49 +02:00
if ( ! m_quiet ) {
SyncReport report ;
client . readSessionInfo ( dir , report ) ;
cout < < report ;
}
2009-04-15 15:58:05 +02:00
}
2009-04-23 16:47:07 +02:00
} else if ( ! m_restore . empty ( ) ) {
// sanity checks: either --after or --before must be given, sources must be selected
if ( ( ! m_after & & ! m_before ) | |
( m_after & & m_before ) ) {
usage ( false , " --restore <log dir> must be used with either --after (restore database as it was after that sync) or --before (restore data from before sync) " ) ;
return false ;
}
if ( m_sources . empty ( ) ) {
usage ( false , " Sources must be selected explicitly for --restore to prevent accidental restore. " ) ;
return false ;
}
client . restore ( m_restore ,
m_after ?
EvolutionSyncClient : : DATABASE_AFTER_SYNC :
EvolutionSyncClient : : DATABASE_BEFORE_SYNC ) ;
2008-03-19 12:29:14 +01:00
} else {
2009-04-23 16:47:07 +02:00
if ( m_dryrun ) {
EvolutionSyncClient : : throwError ( " --dry-run not supported for running a synchronization " ) ;
}
2008-08-03 15:00:51 +02:00
// safety catch: if props are given, then --run
// is required
if ( ! m_run & &
( m_syncProps . size ( ) | | m_sourceProps . size ( ) ) ) {
usage ( false , " Properties specified, but neither '--configure' nor '--run' - what did you want? " ) ;
return false ;
}
2009-07-02 06:28:33 +02:00
return ( client . sync ( ) = = STATUS_OK ) ;
2008-03-19 12:29:14 +01:00
}
}
return true ;
}
string SyncEvolutionCmdline : : cmdOpt ( const char * opt , const char * param )
{
string res = " ' " ;
res + = opt ;
if ( param ) {
res + = " " ;
res + = param ;
}
res + = " ' " ;
return res ;
}
bool SyncEvolutionCmdline : : parseProp ( const ConfigPropertyRegistry & validProps ,
FilterConfigNode : : ConfigFilter & props ,
const char * opt ,
const char * param ,
const char * propname )
{
if ( ! param ) {
usage ( true , string ( " missing parameter for " ) + cmdOpt ( opt , param ) ) ;
return false ;
2008-03-30 15:11:45 +02:00
} else if ( boost : : trim_copy ( string ( param ) ) = = " ? " ) {
2008-03-19 12:29:14 +01:00
m_dontrun = true ;
if ( propname ) {
return listPropValues ( validProps , propname , opt ) ;
} else {
return listProperties ( validProps , opt ) ;
}
} else {
string propstr ;
string paramstr ;
if ( propname ) {
propstr = propname ;
paramstr = param ;
} else {
const char * equal = strchr ( param , ' = ' ) ;
if ( ! equal ) {
usage ( true , string ( " the '=<value>' part is missing in: " ) + cmdOpt ( opt , param ) ) ;
return false ;
}
propstr . assign ( param , equal - param ) ;
paramstr . assign ( equal + 1 ) ;
}
2008-03-30 15:11:45 +02:00
boost : : trim ( propstr ) ;
boost : : trim_left ( paramstr ) ;
if ( boost : : trim_copy ( paramstr ) = = " ? " ) {
2008-03-19 12:29:14 +01:00
m_dontrun = true ;
return listPropValues ( validProps , propstr , cmdOpt ( opt , param ) ) ;
} else {
const ConfigProperty * prop = validProps . find ( propstr ) ;
if ( ! prop ) {
2008-03-19 13:11:39 +01:00
m_err < < " ERROR: " < < cmdOpt ( opt , param ) < < " : no such property " < < endl ;
2008-03-19 12:29:14 +01:00
return false ;
} else {
string error ;
if ( ! prop - > checkValue ( paramstr , error ) ) {
m_err < < " ERROR: " < < cmdOpt ( opt , param ) < < " : " < < error < < endl ;
return false ;
} else {
2008-07-06 22:26:23 +02:00
props [ propstr ] = paramstr ;
2008-03-19 12:29:14 +01:00
return true ;
}
}
}
}
}
bool SyncEvolutionCmdline : : listPropValues ( const ConfigPropertyRegistry & validProps ,
const string & propName ,
const string & opt )
{
const ConfigProperty * prop = validProps . find ( propName ) ;
if ( ! prop ) {
2008-03-19 13:11:39 +01:00
m_err < < " ERROR: " < < opt < < " : no such property " < < endl ;
2008-03-19 12:29:14 +01:00
return false ;
} else {
m_out < < opt < < endl ;
string comment = prop - > getComment ( ) ;
if ( comment ! = " " ) {
list < string > commentLines ;
ConfigProperty : : splitComment ( comment , commentLines ) ;
2008-07-11 22:25:02 +02:00
BOOST_FOREACH ( const string & line , commentLines ) {
m_out < < " " < < line < < endl ;
2008-03-19 12:29:14 +01:00
}
} else {
2008-04-01 21:44:12 +02:00
m_out < < " no documentation available " < < endl ;
2008-03-19 12:29:14 +01:00
}
return true ;
}
}
bool SyncEvolutionCmdline : : listProperties ( const ConfigPropertyRegistry & validProps ,
const string & opt )
{
// The first of several related properties has a comment.
// Remember that comment and print it as late as possible,
// that way related properties preceed their comment.
string comment ;
2008-07-11 22:25:02 +02:00
BOOST_FOREACH ( const ConfigProperty * prop , validProps ) {
if ( ! prop - > isHidden ( ) ) {
string newComment = prop - > getComment ( ) ;
2008-03-19 12:29:14 +01:00
if ( newComment ! = " " ) {
2008-03-30 17:15:00 +02:00
if ( ! comment . empty ( ) ) {
dumpComment ( m_out , " " , comment ) ;
m_out < < endl ;
}
2008-03-19 12:29:14 +01:00
comment = newComment ;
}
2008-07-11 22:25:02 +02:00
m_out < < prop - > getName ( ) < < " : " < < endl ;
2008-03-19 12:29:14 +01:00
}
}
dumpComment ( m_out , " " , comment ) ;
return true ;
}
void SyncEvolutionCmdline : : listSources ( EvolutionSyncSource & syncSource , const string & header )
{
m_out < < header < < " : \n " ;
2008-07-10 21:17:42 +02:00
EvolutionSyncSource : : Databases databases = syncSource . getDatabases ( ) ;
2008-03-19 12:29:14 +01:00
2008-07-10 21:17:42 +02:00
BOOST_FOREACH ( const EvolutionSyncSource : : Database & database , databases ) {
m_out < < " " < < database . m_name < < " ( " < < database . m_uri < < " ) " ;
if ( database . m_isDefault ) {
2008-03-30 21:08:19 +02:00
m_out < < " <default> " ;
}
m_out < < endl ;
2008-03-19 12:29:14 +01:00
}
}
2008-03-19 17:43:31 +01:00
void SyncEvolutionCmdline : : dumpServers ( const string & preamble ,
const EvolutionSyncConfig : : ServerList & servers )
{
m_out < < preamble < < endl ;
2008-07-11 22:25:02 +02:00
BOOST_FOREACH ( const EvolutionSyncConfig : : ServerList : : value_type & server , servers ) {
m_out < < " " < < server . first < < " = " < < server . second < < endl ;
2008-03-19 17:43:31 +01:00
}
if ( ! servers . size ( ) ) {
m_out < < " none " < < endl ;
}
}
2008-03-19 12:29:14 +01:00
void SyncEvolutionCmdline : : dumpProperties ( const ConfigNode & configuredProps ,
const ConfigPropertyRegistry & allProps )
{
2008-07-11 22:25:02 +02:00
BOOST_FOREACH ( const ConfigProperty * prop , allProps ) {
if ( prop - > isHidden ( ) ) {
2008-03-19 17:43:31 +01:00
continue ;
}
2008-03-19 12:29:14 +01:00
if ( ! m_quiet ) {
2008-07-11 22:25:02 +02:00
string comment = prop - > getComment ( ) ;
2008-03-19 15:38:19 +01:00
if ( ! comment . empty ( ) ) {
m_out < < endl ;
dumpComment ( m_out , " # " , comment ) ;
}
2008-03-19 12:29:14 +01:00
}
2008-03-30 23:50:51 +02:00
bool isDefault ;
2008-07-11 22:25:02 +02:00
prop - > getProperty ( configuredProps , & isDefault ) ;
2008-03-30 23:50:51 +02:00
if ( isDefault ) {
m_out < < " # " ;
}
2008-07-11 22:25:02 +02:00
m_out < < prop - > getName ( ) < < " = " < < prop - > getProperty ( configuredProps ) < < endl ;
2008-03-19 12:29:14 +01:00
}
}
void SyncEvolutionCmdline : : dumpComment ( ostream & stream ,
const string & prefix ,
const string & comment )
{
list < string > commentLines ;
ConfigProperty : : splitComment ( comment , commentLines ) ;
2008-07-11 22:25:02 +02:00
BOOST_FOREACH ( const string & line , commentLines ) {
stream < < prefix < < line < < endl ;
2008-03-19 12:29:14 +01:00
}
}
void SyncEvolutionCmdline : : usage ( bool full , const string & error , const string & param )
{
2008-03-29 18:04:26 +01:00
ostream & out ( error . empty ( ) ? m_out : m_err ) ;
2008-08-03 15:00:51 +02:00
out < < " Show available sources: " < < endl ;
out < < " " < < m_argv [ 0 ] < < endl ;
2009-04-15 15:58:05 +02:00
out < < " Show information about configuration(s) and sync sessions: " < < endl ;
2008-08-03 15:00:51 +02:00
out < < " " < < m_argv [ 0 ] < < " --print-servers " < < endl ;
out < < " " < < m_argv [ 0 ] < < " --print-config [--quiet] <server> [sync|<source ...] " < < endl ;
2009-04-23 17:34:31 +02:00
out < < " " < < m_argv [ 0 ] < < " --print-sessions [--quiet] <server> " < < endl ;
2008-08-03 15:00:51 +02:00
out < < " Show information about SyncEvolution: " < < endl ;
out < < " " < < m_argv [ 0 ] < < " --help|-h " < < endl ;
out < < " " < < m_argv [ 0 ] < < " --version " < < endl ;
out < < " Run a synchronization: " < < endl ;
out < < " " < < m_argv [ 0 ] < < " <server> [<source> ...] " < < endl ;
out < < " " < < m_argv [ 0 ] < < " --run <options for run> <server> [<source> ...] " < < endl ;
2009-04-23 16:47:07 +02:00
out < < " Restore data from the automatic backups: " < < endl ;
out < < " " < < m_argv [ 0 ] < < " --restore <session directory> --before|--after [--dry-run] <server> <source> ... " < < endl ;
2009-04-15 14:02:09 +02:00
out < < " Remove a configuration: " < < endl ;
out < < " " < < m_argv [ 0 ] < < " --remove <server> " < < endl ;
2008-08-03 15:00:51 +02:00
out < < " Modify configuration: " < < endl ;
out < < " " < < m_argv [ 0 ] < < " --configure <options for configuration> <server> [<source> ...] " < < endl ;
out < < " " < < m_argv [ 0 ] < < " --migrate <server> " < < endl ;
2008-03-19 12:29:14 +01:00
if ( full ) {
2008-03-29 18:04:26 +01:00
out < < endl < <
2008-03-19 12:29:14 +01:00
" Options: " < < endl < <
2008-04-10 21:36:57 +02:00
" --sync|-s <mode> " < < endl < <
" --sync|-s ? " < < endl < <
" Temporarily synchronize the active sources in that mode. Useful " < < endl < <
" for a \" refresh-from-server \" or \" refresh-from-client \" sync which " < < endl < <
" clears all data at one end and copies all items from the other. " < < endl < <
" " < < endl < <
" --print-servers " < < endl < <
" Prints the names of all configured servers to stdout. " < < endl < <
" " < < endl < <
" --print-config|-p " < < endl < <
" Prints the complete configuration for the selected server " < < endl < <
" to stdout, including up-to-date comments for all properties. The " < < endl < <
" format is the normal .ini format with source configurations in " < < endl < <
" different sections introduced with [<source>] lines. Can be combined " < < endl < <
" with --sync-property and --source-property to modify the configuration " < < endl < <
" on-the-fly. When one or more sources are listed after the <server> " < < endl < <
" name on the command line, then only the configs of those sources are " < < endl < <
" printed. Using --quiet suppresses the comments for each property. " < < endl < <
" When setting a --template, then the reference configuration for " < < endl < <
" that server is printed instead of an existing configuration. " < < endl < <
" " < < endl < <
2009-04-15 15:58:05 +02:00
" --print-sessions " < < endl < <
2009-04-16 12:07:49 +02:00
" Prints a list of all previous log directories. Unless --quiet is used, each " < < endl < <
" file name is followed by the original sync report. " < < endl < <
2009-04-15 15:58:05 +02:00
" " < < endl < <
2008-04-10 21:36:57 +02:00
" -– configure|-c " < < endl < <
" Modify the configuration files for the selected server. If no such " < < endl < <
" configuration exists, then a new one is created using one of the " < < endl < <
" template configurations (see --template option). When creating " < < endl < <
" a new configuration only the active sources will be set to active " < < endl < <
" in the new configuration, i.e. \" syncevolution -c scheduleworld addressbook \" " < < endl < <
" followed by \" syncevolution scheduleworld \" will only synchronize the " < < endl < <
" address book. The other sources are created in a disabled state. " < < endl < <
" When modifying an existing configuration and sources are specified, " < < endl < <
" then the source properties of only those sources are modified. " < < endl < <
" " < < endl < <
" --migrate " < < endl < <
" In SyncEvolution <= 0.7 a different layout of configuration files " < < endl < <
" was used. Using --migrate will automatically migrate to the new " < < endl < <
" layout and rename the old directory $HOME/.sync4j/evolution/<server> " < < endl < <
" into $HOME/.sync4j/evolution/<server>.old to prevent accidental use " < < endl < <
" of the old configuration. WARNING: old SyncEvolution releases cannot " < < endl < <
" use the new configuration! " < < endl < <
" The switch can also be used to migrate a configuration in the current " < < endl < <
" configuration directory: this preserves all property values, discards " < < endl < <
" obsolete properties and sets all comments exactly as if the configuration " < < endl < <
" had been created from scratch. WARNING: custom comments in the " < < endl < <
" configuration are not preserved. " < < endl < <
" --migrate implies --configure and can be combined with modifying " < < endl < <
" properties. " < < endl < <
" " < < endl < <
2009-04-23 16:47:07 +02:00
" --restore " < < endl < <
" Restores the data of the selected sources to the state from before or after the " < < endl < <
" selected synchronization. The synchronization is selected via its log directory " < < endl < <
" (see --print-sessions). Other directories can also be given as long as " < < endl < <
" they contain database dumps in the format created by SyncEvolution. " < < endl < <
" The output includes information about the changes made during the " < < endl < <
" restore, both in terms of item changes and content changes (which is " < < endl < <
" not always the same, see manual for details). This output can be suppressed " < < endl < <
" with --quiet. " < < endl < <
" In combination with --dry-run, the changes to local data are only simulated. " < < endl < <
" This can be used to check that --restore will not remove valuable information. " < < endl < <
" " < < endl < <
2009-04-16 08:42:11 +02:00
" --remove " < < endl < <
" This removes only the configuration files and related meta information. " < < endl < <
" If other files were added to the config directory of the server, then " < < endl < <
" those and the directory will not be removed. Log directories will also " < < endl < <
" not be removed. " < < endl < <
" " < < endl < <
2008-04-10 21:36:57 +02:00
" --sync-property|-y <property>=<value> " < < endl < <
" --sync-property|-y ? " < < endl < <
" --sync-property|-y <property>=? " < < endl < <
" Overrides a configuration property in the <server>/config.ini file " < < endl < <
" for the current synchronization run or permanently when --configure " < < endl < <
" is used to update the configuration. Can be used multiple times. " < < endl < <
" Specifying an unused property will trigger an error message. " < < endl < <
" " < < endl < <
" --source-property|-z <property>=<value> " < < endl < <
" --source-property|-z ? " < < endl < <
" --source-property|-z <property>=? " < < endl < <
" Same as --sync-option, but applies to the configuration of all active " < < endl < <
" sources. \" --sync <mode> \" is a shortcut for \" --source-option sync=<mode> \" . " < < endl < <
" " < < endl < <
" --template|-l <server name>|default|? " < < endl < <
" Can be used to select from one of the built-in default configurations " < < endl < <
" for known SyncML servers. Defaults to the <server> name, so --template " < < endl < <
" only has to be specified when creating multiple different configurations " < < endl < <
" for the same server. \" default \" is an alias for \" scheduleworld \" and can be " < < endl < <
" used as the starting point for servers which do not have a built-in " < < endl < <
" configuration. " < < endl < <
" Each template contains a pseudo-random device ID. Therefore setting the " < < endl < <
" \" deviceId \" sync property is only necessary when manually recreating a " < < endl < <
" configuration or when a more descriptive name is desired. " < < endl < <
" " < < endl < <
" --status|-t " < < endl < <
" The changes made to local data since the last synchronization are " < < endl < <
" shown without starting a new one. This can be used to see in advance " < < endl < <
" whether the local data needs to be synchronized with the server. " < < endl < <
" " < < endl < <
" --quiet|-q " < < endl < <
" Suppresses most of the normal output during a synchronization. The " < < endl < <
" log file still contains all the information. " < < endl < <
" " < < endl < <
" --help|-h " < < endl < <
" Prints usage information. " < < endl < <
" " < < endl < <
" --version " < < endl < <
" Prints the SyncEvolution version. " < < endl ;
2008-03-19 12:29:14 +01:00
}
if ( error ! = " " ) {
2008-03-29 18:04:26 +01:00
out < < endl < < " ERROR: " < < error < < endl ;
2008-03-19 12:29:14 +01:00
}
if ( param ! = " " ) {
2008-03-29 18:04:26 +01:00
out < < " INFO: use ' " < < param < < ( param [ param . size ( ) - 1 ] = = ' = ' ? " " : " " ) < <
2008-03-19 12:29:14 +01:00
" ?' to get a list of valid parameters " < < endl ;
}
}
2008-03-28 23:32:00 +01:00
2008-04-17 20:27:53 +02:00
# ifdef ENABLE_UNIT_TESTS
2009-07-13 18:24:55 +02:00
# include "test.h"
2008-03-28 23:32:00 +01:00
2008-03-29 18:04:26 +01:00
/** simple line-by-line diff */
static string diffStrings ( const string & lhs , const string & rhs )
{
ostringstream res ;
typedef boost : : split_iterator < string : : const_iterator > string_split_iterator ;
string_split_iterator lit =
boost : : make_split_iterator ( lhs , boost : : first_finder ( " \n " , boost : : is_iequal ( ) ) ) ;
string_split_iterator rit =
boost : : make_split_iterator ( rhs , boost : : first_finder ( " \n " , boost : : is_iequal ( ) ) ) ;
while ( lit ! = string_split_iterator ( ) & &
rit ! = string_split_iterator ( ) ) {
if ( * lit ! = * rit ) {
res < < " < " < < * lit < < endl ;
res < < " > " < < * rit < < endl ;
}
+ + lit ;
+ + rit ;
}
while ( lit ! = string_split_iterator ( ) ) {
res < < " < " < < * lit < < endl ;
+ + lit ;
}
2008-03-29 18:26:23 +01:00
while ( rit ! = string_split_iterator ( ) ) {
2008-03-29 18:04:26 +01:00
res < < " > " < < * rit < < endl ;
+ + rit ;
}
return res . str ( ) ;
}
# define CPPUNIT_ASSERT_EQUAL_DIFF( expected, actual ) \
do { \
2008-03-30 11:02:07 +02:00
string expected_ = ( expected ) ; \
string actual_ = ( actual ) ; \
if ( expected_ ! = actual_ ) { \
2008-03-29 18:04:26 +01:00
CPPUNIT_NS : : Message cpputMsg_ ( string ( " expected: \n " ) + \
2008-03-30 11:02:07 +02:00
expected_ ) ; \
2008-03-29 18:04:26 +01:00
cpputMsg_ . addDetail ( string ( " actual: \n " ) + \
2008-03-30 11:02:07 +02:00
actual_ ) ; \
2008-03-29 18:04:26 +01:00
cpputMsg_ . addDetail ( string ( " diff: \n " ) + \
2008-03-30 11:02:07 +02:00
diffStrings ( expected_ , actual_ ) ) ; \
2008-03-29 18:04:26 +01:00
CPPUNIT_NS : : Asserter : : fail ( cpputMsg_ , \
CPPUNIT_SOURCELINE ( ) ) ; \
} \
} while ( false )
2008-03-30 13:43:36 +02:00
// returns last line, including trailing line break, empty if input is empty
static string lastLine ( const string & buffer )
{
if ( buffer . size ( ) < 2 ) {
return buffer ;
}
size_t line = buffer . rfind ( " \n " , buffer . size ( ) - 2 ) ;
if ( line = = buffer . npos ) {
return buffer ;
}
return buffer . substr ( line + 1 ) ;
}
2008-03-30 23:50:51 +02:00
// true if <word> =
static bool isPropAssignment ( const string & buffer ) {
size_t start = 0 ;
while ( start < buffer . size ( ) & &
! isspace ( buffer [ start ] ) ) {
start + + ;
}
if ( start + 3 < = buffer . size ( ) & &
buffer . substr ( start , 3 ) = = " = " ) {
return true ;
} else {
return false ;
}
}
// remove pure comment lines from buffer,
// also empty lines
2008-03-30 13:43:36 +02:00
static string filterConfig ( const string & buffer )
{
ostringstream res ;
typedef boost : : split_iterator < string : : const_iterator > string_split_iterator ;
for ( string_split_iterator it =
boost : : make_split_iterator ( buffer , boost : : first_finder ( " \n " , boost : : is_iequal ( ) ) ) ;
it ! = string_split_iterator ( ) ;
+ + it ) {
2008-03-30 23:50:51 +02:00
string line = boost : : copy_range < string > ( * it ) ;
if ( ! line . empty ( ) & &
( ! boost : : starts_with ( line , " # " ) | |
isPropAssignment ( line . substr ( 2 ) ) ) ) {
res < < line < < endl ;
2008-03-30 13:43:36 +02:00
}
}
return res . str ( ) ;
}
2008-03-30 17:15:00 +02:00
// remove lines indented with spaces
static string filterIndented ( const string & buffer )
{
ostringstream res ;
bool first = true ;
typedef boost : : split_iterator < string : : const_iterator > string_split_iterator ;
for ( string_split_iterator it =
boost : : make_split_iterator ( buffer , boost : : first_finder ( " \n " , boost : : is_iequal ( ) ) ) ;
it ! = string_split_iterator ( ) ;
+ + it ) {
if ( ! boost : : starts_with ( * it , " " ) ) {
if ( ! first ) {
res < < endl ;
} else {
first = false ;
}
res < < * it ;
}
}
return res . str ( ) ;
}
2008-03-30 13:43:36 +02:00
// convert the internal config dump to .ini style
static string internalToIni ( const string & config )
{
ostringstream res ;
string section ;
typedef boost : : split_iterator < string : : const_iterator > string_split_iterator ;
for ( string_split_iterator it =
boost : : make_split_iterator ( config , boost : : first_finder ( " \n " , boost : : is_iequal ( ) ) ) ;
it ! = string_split_iterator ( ) ;
+ + it ) {
string line ( it - > begin ( ) , it - > end ( ) ) ;
if ( line . empty ( ) ) {
continue ;
}
size_t colon = line . find ( ' : ' ) ;
string prefix = line . substr ( 0 , colon ) ;
2008-03-30 18:13:08 +02:00
if ( boost : : contains ( prefix , " .internal.ini " ) | |
boost : : contains ( line , " = internal value " ) ) {
2008-03-30 13:43:36 +02:00
continue ;
}
2008-03-30 18:13:08 +02:00
// sources/<name>/config.ini or
// spds/sources/<name>/config.ini
2008-03-30 17:15:00 +02:00
size_t endslash = prefix . rfind ( ' / ' ) ;
2008-03-30 18:13:08 +02:00
if ( endslash ! = line . npos & & endslash > 1 ) {
size_t slash = prefix . rfind ( ' / ' , endslash - 1 ) ;
if ( slash ! = line . npos ) {
string newsource = prefix . substr ( slash + 1 , endslash - slash - 1 ) ;
if ( newsource ! = section & &
newsource ! = " syncml " ) {
res < < endl < < " [ " < < newsource < < " ] " < < endl ;
section = newsource ;
}
2008-03-30 13:43:36 +02:00
}
}
string assignment = line . substr ( colon + 1 ) ;
// substitude aliases with generic values
boost : : replace_first ( assignment , " = F " , " = 0 " ) ;
boost : : replace_first ( assignment , " = T " , " = 1 " ) ;
2009-06-10 14:27:16 +02:00
boost : : replace_first ( assignment , " = syncml:auth-md5 " , " = md5 " ) ;
boost : : replace_first ( assignment , " = syncml:auth-basix " , " = basic " ) ;
2008-03-30 13:43:36 +02:00
res < < assignment < < endl ;
}
return res . str ( ) ;
}
2008-03-29 18:04:26 +01:00
2008-03-28 23:32:00 +01:00
/**
* Testing is based on a text representation of a directory
* hierarchy where each line is of the format
* < file path > : < line in file >
*
* The order of files is alphabetical , of lines in the file as
* in the file . Lines in the file without line break cannot
* be represented .
*
* The root of the hierarchy is not part of the representation
* itself .
*/
class SyncEvolutionCmdlineTest : public CppUnit : : TestFixture {
CPPUNIT_TEST_SUITE ( SyncEvolutionCmdlineTest ) ;
CPPUNIT_TEST ( testFramework ) ;
2008-03-29 15:16:34 +01:00
CPPUNIT_TEST ( testSetupScheduleWorld ) ;
2008-03-29 18:26:23 +01:00
CPPUNIT_TEST ( testSetupDefault ) ;
CPPUNIT_TEST ( testSetupRenamed ) ;
2008-03-29 18:04:26 +01:00
CPPUNIT_TEST ( testSetupFunambol ) ;
CPPUNIT_TEST ( testSetupSynthesis ) ;
2008-03-29 18:26:23 +01:00
CPPUNIT_TEST ( testPrintServers ) ;
2008-03-30 13:43:36 +02:00
CPPUNIT_TEST ( testPrintConfig ) ;
2008-03-29 18:04:26 +01:00
CPPUNIT_TEST ( testTemplate ) ;
2008-03-30 11:02:07 +02:00
CPPUNIT_TEST ( testSync ) ;
2008-03-30 15:41:56 +02:00
CPPUNIT_TEST ( testConfigure ) ;
2008-03-30 18:13:08 +02:00
CPPUNIT_TEST ( testOldConfigure ) ;
2008-03-30 17:15:00 +02:00
CPPUNIT_TEST ( testListSources ) ;
CPPUNIT_TEST ( testMigrate ) ;
2008-03-28 23:32:00 +01:00
CPPUNIT_TEST_SUITE_END ( ) ;
2008-03-29 15:16:34 +01:00
public :
SyncEvolutionCmdlineTest ( ) :
m_testDir ( " SyncEvolutionCmdlineTest " ) ,
2009-06-25 10:55:22 +02:00
m_scheduleWorldConfig ( " .internal.ini:# HashCode = 0 \n "
" .internal.ini:# ConfigDate = \n "
" config.ini:syncURL = http://sync.scheduleworld.com/funambol/ds \n "
2008-03-29 15:16:34 +01:00
" config.ini:username = your SyncML server account name \n "
" config.ini:password = your SyncML server password \n "
2008-03-30 23:50:51 +02:00
" config.ini:# logdir = \n "
" config.ini:# loglevel = 0 \n "
2009-04-21 11:22:32 +02:00
" config.ini:# printChanges = 1 \n "
2009-04-16 17:22:31 +02:00
" config.ini:# maxlogdirs = 10 \n "
2008-03-30 23:50:51 +02:00
" config.ini:# useProxy = 0 \n "
" config.ini:# proxyHost = \n "
" config.ini:# proxyUsername = \n "
" config.ini:# proxyPassword = \n "
2009-06-10 14:27:16 +02:00
" config.ini:# clientAuthType = md5 \n "
2008-03-30 20:39:15 +02:00
" config.ini:deviceId = fixed-devid \n " /* this is not the default! */
2009-06-25 11:06:07 +02:00
" config.ini:# enableWBXML = 1 \n "
2009-06-10 13:32:49 +02:00
" config.ini:# maxMsgSize = 20000 \n "
" config.ini:# maxObjSize = 4000000 \n "
2008-03-30 23:50:51 +02:00
" config.ini:# enableCompression = 0 \n "
2008-04-16 22:33:38 +02:00
" config.ini:# SSLServerCertificates = \n "
" config.ini:# SSLVerifyServer = 1 \n "
" config.ini:# SSLVerifyHost = 1 \n "
2009-04-07 20:33:18 +02:00
" config.ini:WebURL = http://sync.scheduleworld.com \n "
" config.ini:# IconURI = \n "
2009-06-29 20:32:26 +02:00
" config.ini:ConsumerReady = 1 \n "
2008-03-30 23:50:51 +02:00
" sources/addressbook/.internal.ini:# last = 0 \n "
2008-03-30 17:15:00 +02:00
" sources/addressbook/config.ini:sync = two-way \n "
2008-07-12 21:45:50 +02:00
" sources/addressbook/config.ini:type = addressbook:text/vcard \n "
2008-03-30 23:50:51 +02:00
" sources/addressbook/config.ini:# evolutionsource = \n "
2008-03-30 17:15:00 +02:00
" sources/addressbook/config.ini:uri = card3 \n "
2008-03-30 23:50:51 +02:00
" sources/addressbook/config.ini:# evolutionuser = \n "
" sources/addressbook/config.ini:# evolutionpassword = \n "
" sources/calendar/.internal.ini:# last = 0 \n "
2008-03-30 17:15:00 +02:00
" sources/calendar/config.ini:sync = two-way \n "
" sources/calendar/config.ini:type = calendar \n "
2008-03-30 23:50:51 +02:00
" sources/calendar/config.ini:# evolutionsource = \n "
2008-06-12 20:55:01 +02:00
" sources/calendar/config.ini:uri = cal2 \n "
2008-03-30 23:50:51 +02:00
" sources/calendar/config.ini:# evolutionuser = \n "
" sources/calendar/config.ini:# evolutionpassword = \n "
" sources/memo/.internal.ini:# last = 0 \n "
2008-03-30 17:15:00 +02:00
" sources/memo/config.ini:sync = two-way \n "
" sources/memo/config.ini:type = memo \n "
2008-03-30 23:50:51 +02:00
" sources/memo/config.ini:# evolutionsource = \n "
2008-03-30 17:15:00 +02:00
" sources/memo/config.ini:uri = note \n "
2008-03-30 23:50:51 +02:00
" sources/memo/config.ini:# evolutionuser = \n "
" sources/memo/config.ini:# evolutionpassword = \n "
" sources/todo/.internal.ini:# last = 0 \n "
2008-03-30 17:15:00 +02:00
" sources/todo/config.ini:sync = two-way \n "
" sources/todo/config.ini:type = todo \n "
2008-03-30 23:50:51 +02:00
" sources/todo/config.ini:# evolutionsource = \n "
2008-03-30 17:15:00 +02:00
" sources/todo/config.ini:uri = task2 \n "
2008-03-30 23:50:51 +02:00
" sources/todo/config.ini:# evolutionuser = \n "
2009-03-17 14:16:49 +01:00
" sources/todo/config.ini:# evolutionpassword = \n " )
2009-07-17 16:21:25 +02:00
{
# ifdef ENABLE_LIBSOUP
// path to SSL certificates has to be set only for libsoup
boost : : replace_first ( m_scheduleWorldConfig ,
" SSLServerCertificates = " ,
" SSLServerCertificates = /etc/ssl/certs/ca-certificates.crt:/etc/pki/tls/certs/ca-bundle.crt:/usr/share/ssl/certs/ca-bundle.crt " ) ;
# endif
}
2008-03-28 23:32:00 +01:00
protected :
2008-03-29 15:16:34 +01:00
/** verify that createFiles/scanFiles themselves work */
2008-03-28 23:32:00 +01:00
void testFramework ( ) {
2008-03-29 15:16:34 +01:00
const string root ( m_testDir ) ;
2008-03-28 23:32:00 +01:00
const string content ( " baz:line \n "
2008-03-29 15:16:34 +01:00
" caz/subdir:booh \n "
2008-03-30 23:50:51 +02:00
" caz/subdir2/sub:# comment \n "
" caz/subdir2/sub:# foo = bar \n "
" caz/subdir2/sub:# empty = \n "
" caz/subdir2/sub:# another comment \n "
2008-03-28 23:32:00 +01:00
" foo:bar1 \n "
2008-03-30 23:50:51 +02:00
" foo: \n "
" foo: \n "
2008-03-28 23:32:00 +01:00
" foo:bar2 \n " ) ;
2008-03-30 23:50:51 +02:00
const string filtered ( " baz:line \n "
" caz/subdir:booh \n "
" caz/subdir2/sub:# foo = bar \n "
" caz/subdir2/sub:# empty = \n "
" foo:bar1 \n "
" foo: \n "
" foo:bar2 \n " ) ;
2008-03-28 23:32:00 +01:00
createFiles ( root , content ) ;
string res = scanFiles ( root ) ;
2008-03-30 23:50:51 +02:00
CPPUNIT_ASSERT_EQUAL_DIFF ( filtered , res ) ;
2008-03-28 23:32:00 +01:00
}
2008-03-30 20:02:32 +02:00
void removeRandomUUID ( string & buffer ) {
2008-07-12 21:45:50 +02:00
string uuidstr = " deviceId = sc-pim- " ;
2008-03-30 20:02:32 +02:00
size_t uuid = buffer . find ( uuidstr ) ;
CPPUNIT_ASSERT ( uuid ! = buffer . npos ) ;
size_t end = buffer . find ( " \n " , uuid + uuidstr . size ( ) ) ;
CPPUNIT_ASSERT ( end ! = buffer . npos ) ;
buffer . replace ( uuid , end - uuid , " deviceId = fixed-devid " ) ;
}
2008-03-29 18:04:26 +01:00
/** create new configurations */
2008-03-29 15:16:34 +01:00
void testSetupScheduleWorld ( ) {
2008-03-29 18:04:26 +01:00
string root ;
2008-03-29 15:16:34 +01:00
ScopedEnvChange xdg ( " XDG_CONFIG_HOME " , m_testDir ) ;
ScopedEnvChange home ( " HOME " , m_testDir ) ;
2008-03-29 18:04:26 +01:00
root = m_testDir ;
root + = " /syncevolution/scheduleworld " ;
2008-03-30 15:11:45 +02:00
{
rm_r ( root ) ;
TestCmdline cmdline ( " --configure " ,
" --sync-property " , " proxyHost = proxy " ,
" scheduleworld " ,
" addressbook " ,
NULL ) ;
cmdline . doit ( ) ;
string res = scanFiles ( root ) ;
2008-03-30 20:02:32 +02:00
removeRandomUUID ( res ) ;
2009-04-07 20:33:18 +02:00
string expected = ScheduleWorldConfig ( ) ;
2008-03-30 15:11:45 +02:00
boost : : replace_first ( expected ,
2008-03-30 23:50:51 +02:00
" # proxyHost = " ,
2008-03-30 15:11:45 +02:00
" proxyHost = proxy " ) ;
boost : : replace_all ( expected ,
" sync = two-way " ,
" sync = disabled " ) ;
boost : : replace_first ( expected ,
" addressbook/config.ini:sync = disabled " ,
" addressbook/config.ini:sync = two-way " ) ;
CPPUNIT_ASSERT_EQUAL_DIFF ( expected , res ) ;
}
{
rm_r ( root ) ;
TestCmdline cmdline ( " --configure " ,
2008-03-30 20:02:32 +02:00
" --sync-property " , " deviceID = fixed-devid " ,
2008-03-30 15:11:45 +02:00
" scheduleworld " ,
NULL ) ;
cmdline . doit ( ) ;
string res = scanFiles ( root ) ;
2009-04-07 20:33:18 +02:00
CPPUNIT_ASSERT_EQUAL_DIFF ( ScheduleWorldConfig ( ) , res ) ;
2008-03-30 15:11:45 +02:00
}
2008-03-29 15:16:34 +01:00
}
2008-03-30 23:50:51 +02:00
2008-03-29 18:26:23 +01:00
void testSetupDefault ( ) {
string root ;
ScopedEnvChange xdg ( " XDG_CONFIG_HOME " , m_testDir ) ;
ScopedEnvChange home ( " HOME " , m_testDir ) ;
root = m_testDir ;
root + = " /syncevolution/some-other-server " ;
rm_r ( root ) ;
TestCmdline cmdline ( " --configure " ,
" --template " , " default " ,
2008-03-30 20:02:32 +02:00
" --sync-property " , " deviceID = fixed-devid " ,
2008-03-29 18:26:23 +01:00
" some-other-server " ,
NULL ) ;
cmdline . doit ( ) ;
string res = scanFiles ( root ) ;
2009-04-07 20:33:18 +02:00
CPPUNIT_ASSERT_EQUAL_DIFF ( ScheduleWorldConfig ( ) , res ) ;
2008-03-29 18:26:23 +01:00
}
void testSetupRenamed ( ) {
string root ;
ScopedEnvChange xdg ( " XDG_CONFIG_HOME " , m_testDir ) ;
ScopedEnvChange home ( " HOME " , m_testDir ) ;
root = m_testDir ;
root + = " /syncevolution/scheduleworld2 " ;
rm_r ( root ) ;
TestCmdline cmdline ( " --configure " ,
" --template " , " scheduleworld " ,
2008-03-30 20:02:32 +02:00
" --sync-property " , " deviceID = fixed-devid " ,
2008-03-29 18:26:23 +01:00
" scheduleworld2 " ,
NULL ) ;
cmdline . doit ( ) ;
string res = scanFiles ( root ) ;
2009-04-07 20:33:18 +02:00
CPPUNIT_ASSERT_EQUAL_DIFF ( ScheduleWorldConfig ( ) , res ) ;
2008-03-29 18:26:23 +01:00
}
2008-03-29 18:04:26 +01:00
void testSetupFunambol ( ) {
string root ;
ScopedEnvChange xdg ( " XDG_CONFIG_HOME " , m_testDir ) ;
ScopedEnvChange home ( " HOME " , m_testDir ) ;
root = m_testDir ;
root + = " /syncevolution/funambol " ;
rm_r ( root ) ;
TestCmdline cmdline ( " --configure " ,
2008-03-30 20:02:32 +02:00
" --sync-property " , " deviceID = fixed-devid " ,
2009-04-08 16:32:05 +02:00
// templates are case-insensitive
" FunamBOL " ,
2008-03-29 18:04:26 +01:00
NULL ) ;
cmdline . doit ( ) ;
string res = scanFiles ( root ) ;
2008-03-30 13:43:36 +02:00
CPPUNIT_ASSERT_EQUAL_DIFF ( FunambolConfig ( ) , res ) ;
2008-03-29 18:04:26 +01:00
}
void testSetupSynthesis ( ) {
string root ;
ScopedEnvChange xdg ( " XDG_CONFIG_HOME " , m_testDir ) ;
ScopedEnvChange home ( " HOME " , m_testDir ) ;
root = m_testDir ;
root + = " /syncevolution/synthesis " ;
rm_r ( root ) ;
TestCmdline cmdline ( " --configure " ,
2008-03-30 20:02:32 +02:00
" --sync-property " , " deviceID = fixed-devid " ,
2008-03-29 18:04:26 +01:00
" synthesis " ,
NULL ) ;
cmdline . doit ( ) ;
string res = scanFiles ( root ) ;
2008-03-30 13:43:36 +02:00
CPPUNIT_ASSERT_EQUAL_DIFF ( SynthesisConfig ( ) , res ) ;
2008-03-29 18:04:26 +01:00
}
void testTemplate ( ) {
TestCmdline failure ( " --template " , NULL ) ;
CPPUNIT_ASSERT ( ! failure . m_cmdline - > parse ( ) ) ;
CPPUNIT_ASSERT_EQUAL_DIFF ( " " , failure . m_out . str ( ) ) ;
2008-03-30 13:43:36 +02:00
CPPUNIT_ASSERT_EQUAL ( string ( " ERROR: missing parameter for '--template' \n " ) , lastLine ( failure . m_err . str ( ) ) ) ;
2008-03-29 18:04:26 +01:00
2008-03-30 15:11:45 +02:00
TestCmdline help ( " --template " , " ? " , NULL ) ;
2008-03-29 18:04:26 +01:00
help . doit ( ) ;
CPPUNIT_ASSERT_EQUAL_DIFF ( " Available configuration templates: \n "
2009-04-08 16:32:05 +02:00
" Funambol = http://my.funambol.com \n "
2009-06-18 15:25:53 +02:00
" Google = http://m.google.com/sync \n "
2009-04-08 16:32:05 +02:00
" Memotoo = http://www.memotoo.com \n "
2009-08-07 09:11:43 +02:00
" Mobical = http://www.mobical.net \n "
2009-04-08 16:32:05 +02:00
" ScheduleWorld = http://sync.scheduleworld.com \n "
2009-07-18 16:40:29 +02:00
" Synthesis = http://www.synthesis.ch \n "
" ZYB = http://www.zyb.com \n " ,
2008-03-29 18:04:26 +01:00
help . m_out . str ( ) ) ;
CPPUNIT_ASSERT_EQUAL_DIFF ( " " , help . m_err . str ( ) ) ;
}
2008-03-29 18:26:23 +01:00
void testPrintServers ( ) {
ScopedEnvChange xdg ( " XDG_CONFIG_HOME " , m_testDir ) ;
ScopedEnvChange home ( " HOME " , m_testDir ) ;
rm_r ( m_testDir ) ;
testSetupScheduleWorld ( ) ;
testSetupSynthesis ( ) ;
testSetupFunambol ( ) ;
TestCmdline cmdline ( " --print-servers " , NULL ) ;
cmdline . doit ( ) ;
CPPUNIT_ASSERT_EQUAL_DIFF ( " Configured servers: \n "
" scheduleworld = SyncEvolutionCmdlineTest/syncevolution/scheduleworld \n "
" synthesis = SyncEvolutionCmdlineTest/syncevolution/synthesis \n "
" funambol = SyncEvolutionCmdlineTest/syncevolution/funambol \n " ,
cmdline . m_out . str ( ) ) ;
CPPUNIT_ASSERT_EQUAL_DIFF ( " " , cmdline . m_err . str ( ) ) ;
}
2008-03-30 13:43:36 +02:00
void testPrintConfig ( ) {
ScopedEnvChange xdg ( " XDG_CONFIG_HOME " , m_testDir ) ;
ScopedEnvChange home ( " HOME " , m_testDir ) ;
rm_r ( m_testDir ) ;
testSetupFunambol ( ) ;
{
TestCmdline failure ( " --print-config " , NULL ) ;
CPPUNIT_ASSERT ( failure . m_cmdline - > parse ( ) ) ;
CPPUNIT_ASSERT ( ! failure . m_cmdline - > run ( ) ) ;
CPPUNIT_ASSERT_EQUAL_DIFF ( " " , failure . m_out . str ( ) ) ;
CPPUNIT_ASSERT_EQUAL ( string ( " ERROR: --print-config requires either a --template or a server name. \n " ) ,
lastLine ( failure . m_err . str ( ) ) ) ;
}
{
TestCmdline failure ( " --print-config " , " foo " , NULL ) ;
CPPUNIT_ASSERT ( failure . m_cmdline - > parse ( ) ) ;
CPPUNIT_ASSERT ( ! failure . m_cmdline - > run ( ) ) ;
CPPUNIT_ASSERT_EQUAL_DIFF ( " " , failure . m_out . str ( ) ) ;
CPPUNIT_ASSERT_EQUAL ( string ( " ERROR: server 'foo' has not been configured yet. \n " ) ,
lastLine ( failure . m_err . str ( ) ) ) ;
}
{
TestCmdline failure ( " --print-config " , " --template " , " foo " , NULL ) ;
CPPUNIT_ASSERT ( failure . m_cmdline - > parse ( ) ) ;
CPPUNIT_ASSERT ( ! failure . m_cmdline - > run ( ) ) ;
CPPUNIT_ASSERT_EQUAL_DIFF ( " " , failure . m_out . str ( ) ) ;
CPPUNIT_ASSERT_EQUAL ( string ( " ERROR: no configuration template for 'foo' available. \n " ) ,
lastLine ( failure . m_err . str ( ) ) ) ;
}
{
TestCmdline cmdline ( " --print-config " , " --template " , " scheduleworld " , NULL ) ;
cmdline . doit ( ) ;
CPPUNIT_ASSERT_EQUAL_DIFF ( " " , cmdline . m_err . str ( ) ) ;
string actual = cmdline . m_out . str ( ) ;
2008-03-30 20:02:32 +02:00
removeRandomUUID ( actual ) ;
2008-03-30 13:43:36 +02:00
string filtered = filterConfig ( actual ) ;
2009-04-07 20:33:18 +02:00
CPPUNIT_ASSERT_EQUAL_DIFF ( filterConfig ( internalToIni ( ScheduleWorldConfig ( ) ) ) ,
2008-03-30 13:43:36 +02:00
filtered ) ;
// there should have been comments
CPPUNIT_ASSERT ( actual . size ( ) > filtered . size ( ) ) ;
}
{
2009-04-08 16:32:05 +02:00
TestCmdline cmdline ( " --print-config " , " --template " , " Default " , NULL ) ;
2008-03-30 13:43:36 +02:00
cmdline . doit ( ) ;
CPPUNIT_ASSERT_EQUAL_DIFF ( " " , cmdline . m_err . str ( ) ) ;
2008-03-30 20:02:32 +02:00
string actual = filterConfig ( cmdline . m_out . str ( ) ) ;
removeRandomUUID ( actual ) ;
2009-04-07 20:33:18 +02:00
CPPUNIT_ASSERT_EQUAL_DIFF ( filterConfig ( internalToIni ( ScheduleWorldConfig ( ) ) ) ,
2008-03-30 20:02:32 +02:00
actual ) ;
2008-03-30 13:43:36 +02:00
}
{
TestCmdline cmdline ( " --print-config " , " funambol " , NULL ) ;
cmdline . doit ( ) ;
CPPUNIT_ASSERT_EQUAL_DIFF ( " " , cmdline . m_err . str ( ) ) ;
CPPUNIT_ASSERT_EQUAL_DIFF ( filterConfig ( internalToIni ( FunambolConfig ( ) ) ) ,
filterConfig ( cmdline . m_out . str ( ) ) ) ;
}
{
TestCmdline cmdline ( " --print-config " , " --template " , " scheduleworld " ,
" --sync-property " , " syncURL=foo " ,
" --source-property " , " sync=disabled " ,
NULL ) ;
cmdline . doit ( ) ;
CPPUNIT_ASSERT_EQUAL_DIFF ( " " , cmdline . m_err . str ( ) ) ;
2009-04-07 20:33:18 +02:00
string expected = filterConfig ( internalToIni ( ScheduleWorldConfig ( ) ) ) ;
2008-03-30 13:43:36 +02:00
boost : : replace_first ( expected ,
2008-06-28 15:27:07 +02:00
" syncURL = http://sync.scheduleworld.com/funambol/ds " ,
2008-03-30 13:43:36 +02:00
" syncURL = foo " ) ;
boost : : replace_all ( expected ,
" sync = two-way " ,
" sync = disabled " ) ;
2008-03-30 20:02:32 +02:00
string actual = filterConfig ( cmdline . m_out . str ( ) ) ;
removeRandomUUID ( actual ) ;
2008-03-30 13:43:36 +02:00
CPPUNIT_ASSERT_EQUAL_DIFF ( expected ,
2008-03-30 20:02:32 +02:00
actual ) ;
2008-03-30 13:43:36 +02:00
}
{
TestCmdline cmdline ( " --print-config " , " --quiet " ,
" --template " , " scheduleworld " ,
" funambol " ,
NULL ) ;
cmdline . doit ( ) ;
CPPUNIT_ASSERT_EQUAL_DIFF ( " " , cmdline . m_err . str ( ) ) ;
2008-03-30 20:02:32 +02:00
string actual = cmdline . m_out . str ( ) ;
removeRandomUUID ( actual ) ;
2009-04-07 20:33:18 +02:00
CPPUNIT_ASSERT_EQUAL_DIFF ( internalToIni ( ScheduleWorldConfig ( ) ) ,
2008-03-30 20:02:32 +02:00
actual ) ;
2008-03-30 13:43:36 +02:00
}
}
2008-03-30 11:02:07 +02:00
void testSync ( ) {
TestCmdline failure ( " --sync " , NULL ) ;
CPPUNIT_ASSERT ( ! failure . m_cmdline - > parse ( ) ) ;
CPPUNIT_ASSERT_EQUAL_DIFF ( " " , failure . m_out . str ( ) ) ;
2008-03-30 13:43:36 +02:00
CPPUNIT_ASSERT_EQUAL ( string ( " ERROR: missing parameter for '--sync' \n " ) , lastLine ( failure . m_err . str ( ) ) ) ;
2008-03-30 11:02:07 +02:00
TestCmdline failure2 ( " --sync " , " foo " , NULL ) ;
CPPUNIT_ASSERT ( ! failure2 . m_cmdline - > parse ( ) ) ;
CPPUNIT_ASSERT_EQUAL_DIFF ( " " , failure2 . m_out . str ( ) ) ;
2008-03-30 13:43:36 +02:00
CPPUNIT_ASSERT_EQUAL ( string ( " ERROR: '--sync foo': not one of the valid values (two-way, slow, refresh-from-client = refresh-client, refresh-from-server = refresh-server = refresh, one-way-from-client = one-way-client, one-way-from-server = one-way-server = one-way, disabled = none) \n " ) , lastLine ( failure2 . m_err . str ( ) ) ) ;
2008-03-30 11:02:07 +02:00
2008-03-30 15:11:45 +02:00
TestCmdline help ( " --sync " , " ? " , NULL ) ;
2008-03-30 11:02:07 +02:00
help . doit ( ) ;
CPPUNIT_ASSERT_EQUAL_DIFF ( " --sync \n "
" requests a certain synchronization mode: \n "
" two-way = only send/receive changes since last sync \n "
" slow = exchange all items \n "
" refresh-from-client = discard all remote items and replace with \n "
" the items on the client \n "
" refresh-from-server = discard all local items and replace with \n "
" the items on the server \n "
" one-way-from-client = transmit changes from client \n "
" one-way-from-server = transmit changes from server \n "
2008-03-30 20:39:15 +02:00
" none (or disabled) = synchronization disabled \n " ,
2008-03-30 11:02:07 +02:00
help . m_out . str ( ) ) ;
CPPUNIT_ASSERT_EQUAL_DIFF ( " " , help . m_err . str ( ) ) ;
TestCmdline filter ( " --sync " , " refresh-from-server " , NULL ) ;
CPPUNIT_ASSERT ( filter . m_cmdline - > parse ( ) ) ;
CPPUNIT_ASSERT ( ! filter . m_cmdline - > run ( ) ) ;
CPPUNIT_ASSERT_EQUAL_DIFF ( " " , filter . m_out . str ( ) ) ;
CPPUNIT_ASSERT_EQUAL_DIFF ( " sync = refresh-from-server " ,
string ( filter . m_cmdline - > m_sourceProps ) ) ;
CPPUNIT_ASSERT_EQUAL_DIFF ( " " ,
string ( filter . m_cmdline - > m_syncProps ) ) ;
TestCmdline filter2 ( " --source-property " , " sync=refresh " , NULL ) ;
CPPUNIT_ASSERT ( filter2 . m_cmdline - > parse ( ) ) ;
CPPUNIT_ASSERT ( ! filter2 . m_cmdline - > run ( ) ) ;
CPPUNIT_ASSERT_EQUAL_DIFF ( " " , filter2 . m_out . str ( ) ) ;
CPPUNIT_ASSERT_EQUAL_DIFF ( " sync = refresh " ,
string ( filter2 . m_cmdline - > m_sourceProps ) ) ;
CPPUNIT_ASSERT_EQUAL_DIFF ( " " ,
string ( filter2 . m_cmdline - > m_syncProps ) ) ;
}
2008-03-30 15:41:56 +02:00
void testConfigure ( ) {
ScopedEnvChange xdg ( " XDG_CONFIG_HOME " , m_testDir ) ;
ScopedEnvChange home ( " HOME " , m_testDir ) ;
2008-03-30 17:15:00 +02:00
rm_r ( m_testDir ) ;
2008-03-30 15:41:56 +02:00
testSetupScheduleWorld ( ) ;
2008-03-30 18:13:08 +02:00
doConfigure ( ScheduleWorldConfig ( ) , " sources/addressbook/config.ini: " ) ;
2008-03-30 15:41:56 +02:00
2008-03-30 17:15:00 +02:00
string syncProperties ( " syncURL: \n "
" \n "
" username: \n "
2008-04-03 22:01:56 +02:00
" \n "
2008-03-30 17:15:00 +02:00
" password: \n "
" \n "
" logdir: \n "
" \n "
" loglevel: \n "
" \n "
2009-04-21 11:22:32 +02:00
" printChanges: \n "
" \n "
2008-03-30 17:15:00 +02:00
" maxlogdirs: \n "
" \n "
" useProxy: \n "
" \n "
" proxyHost: \n "
" \n "
" proxyUsername: \n "
2008-04-03 22:01:56 +02:00
" \n "
2008-03-30 17:15:00 +02:00
" proxyPassword: \n "
" \n "
" clientAuthType: \n "
" \n "
2008-03-30 20:39:15 +02:00
" deviceId: \n "
" \n "
2009-03-17 14:16:49 +01:00
" enableWBXML: \n "
" \n "
2008-03-30 17:15:00 +02:00
" maxMsgSize: \n "
" maxObjSize: \n "
" \n "
2008-04-16 22:33:38 +02:00
" enableCompression: \n "
" \n "
" SSLServerCertificates: \n "
" \n "
" SSLVerifyServer: \n "
" \n "
2009-04-07 20:33:18 +02:00
" SSLVerifyHost: \n "
" \n "
" WebURL: \n "
" \n "
2009-06-29 20:32:26 +02:00
" IconURI: \n "
" \n "
" ConsumerReady: \n " ) ;
2008-03-30 17:15:00 +02:00
string sourceProperties ( " sync: \n "
" \n "
" type: \n "
" \n "
" evolutionsource: \n "
" \n "
" uri: \n "
" \n "
" evolutionuser: \n "
2009-03-17 14:16:49 +01:00
" evolutionpassword: \n " ) ;
2008-03-30 17:15:00 +02:00
{
TestCmdline cmdline ( " --sync-property " , " ? " ,
NULL ) ;
cmdline . doit ( ) ;
CPPUNIT_ASSERT_EQUAL_DIFF ( " " , cmdline . m_err . str ( ) ) ;
CPPUNIT_ASSERT_EQUAL_DIFF ( syncProperties ,
filterIndented ( cmdline . m_out . str ( ) ) ) ;
}
{
TestCmdline cmdline ( " --source-property " , " ? " ,
NULL ) ;
cmdline . doit ( ) ;
CPPUNIT_ASSERT_EQUAL_DIFF ( " " , cmdline . m_err . str ( ) ) ;
CPPUNIT_ASSERT_EQUAL_DIFF ( sourceProperties ,
filterIndented ( cmdline . m_out . str ( ) ) ) ;
}
{
TestCmdline cmdline ( " --source-property " , " ? " ,
" --sync-property " , " ? " ,
NULL ) ;
cmdline . doit ( ) ;
CPPUNIT_ASSERT_EQUAL_DIFF ( " " , cmdline . m_err . str ( ) ) ;
CPPUNIT_ASSERT_EQUAL_DIFF ( sourceProperties + syncProperties ,
filterIndented ( cmdline . m_out . str ( ) ) ) ;
}
{
TestCmdline cmdline ( " --sync-property " , " ? " ,
" --source-property " , " ? " ,
NULL ) ;
cmdline . doit ( ) ;
CPPUNIT_ASSERT_EQUAL_DIFF ( " " , cmdline . m_err . str ( ) ) ;
CPPUNIT_ASSERT_EQUAL_DIFF ( syncProperties + sourceProperties ,
filterIndented ( cmdline . m_out . str ( ) ) ) ;
}
2008-03-30 18:13:08 +02:00
}
void testOldConfigure ( ) {
ScopedEnvChange xdg ( " XDG_CONFIG_HOME " , m_testDir ) ;
ScopedEnvChange home ( " HOME " , m_testDir ) ;
string oldConfig = OldScheduleWorldConfig ( ) ;
InitList < string > props = InitList < string > ( " serverNonce " ) +
" clientNonce " +
" devInfoHash " +
2009-06-25 10:55:22 +02:00
" HashCode " +
" ConfigDate " +
2008-03-30 18:13:08 +02:00
" last " ;
BOOST_FOREACH ( string & prop , props ) {
boost : : replace_all ( oldConfig ,
prop + " = " ,
prop + " = internal value " ) ;
}
rm_r ( m_testDir ) ;
createFiles ( m_testDir + " /.sync4j/evolution/scheduleworld " , oldConfig ) ;
doConfigure ( oldConfig , " spds/sources/addressbook/config.txt: " ) ;
}
2008-03-30 17:15:00 +02:00
2008-03-30 18:13:08 +02:00
void doConfigure ( const string & SWConfig , const string & addressbookPrefix ) {
2008-03-30 15:41:56 +02:00
string expected ;
{
TestCmdline cmdline ( " --configure " ,
" --source-property " , " sync = disabled " ,
" scheduleworld " ,
NULL ) ;
cmdline . doit ( ) ;
CPPUNIT_ASSERT_EQUAL_DIFF ( " " , cmdline . m_err . str ( ) ) ;
CPPUNIT_ASSERT_EQUAL_DIFF ( " " , cmdline . m_out . str ( ) ) ;
2008-03-30 18:13:08 +02:00
expected = filterConfig ( internalToIni ( SWConfig ) ) ;
2008-03-30 15:41:56 +02:00
boost : : replace_all ( expected ,
" sync = two-way " ,
" sync = disabled " ) ;
CPPUNIT_ASSERT_EQUAL_DIFF ( expected ,
filterConfig ( printConfig ( " scheduleworld " ) ) ) ;
}
{
TestCmdline cmdline ( " --configure " ,
" --source-property " , " sync = one-way-from-server " ,
" scheduleworld " ,
" addressbook " ,
NULL ) ;
cmdline . doit ( ) ;
CPPUNIT_ASSERT_EQUAL_DIFF ( " " , cmdline . m_err . str ( ) ) ;
CPPUNIT_ASSERT_EQUAL_DIFF ( " " , cmdline . m_out . str ( ) ) ;
2008-03-30 18:13:08 +02:00
expected = SWConfig ;
2008-03-30 15:41:56 +02:00
boost : : replace_all ( expected ,
" sync = two-way " ,
" sync = disabled " ) ;
boost : : replace_first ( expected ,
2008-03-30 18:13:08 +02:00
addressbookPrefix + " sync = disabled " ,
addressbookPrefix + " sync = one-way-from-server " ) ;
2008-03-30 15:41:56 +02:00
expected = filterConfig ( internalToIni ( expected ) ) ;
CPPUNIT_ASSERT_EQUAL_DIFF ( expected ,
filterConfig ( printConfig ( " scheduleworld " ) ) ) ;
}
{
TestCmdline cmdline ( " --configure " ,
" --sync " , " two-way " ,
2008-03-30 17:15:00 +02:00
" -z " , " evolutionsource=source " ,
2009-04-16 17:22:31 +02:00
" --sync-property " , " maxlogdirs=20 " ,
2008-03-30 17:15:00 +02:00
" -y " , " LOGDIR=logdir " ,
2008-03-30 15:41:56 +02:00
" scheduleworld " ,
NULL ) ;
cmdline . doit ( ) ;
CPPUNIT_ASSERT_EQUAL_DIFF ( " " , cmdline . m_err . str ( ) ) ;
CPPUNIT_ASSERT_EQUAL_DIFF ( " " , cmdline . m_out . str ( ) ) ;
boost : : replace_all ( expected ,
" sync = one-way-from-server " ,
" sync = two-way " ) ;
boost : : replace_all ( expected ,
" sync = disabled " ,
" sync = two-way " ) ;
boost : : replace_all ( expected ,
2008-03-30 23:50:51 +02:00
" # evolutionsource = " ,
2008-03-30 15:41:56 +02:00
" evolutionsource = source " ) ;
boost : : replace_all ( expected ,
2009-04-16 17:22:31 +02:00
" # maxlogdirs = 10 " ,
" maxlogdirs = 20 " ) ;
2008-03-30 15:41:56 +02:00
boost : : replace_all ( expected ,
2008-03-30 23:50:51 +02:00
" # logdir = " ,
2008-03-30 15:41:56 +02:00
" logdir = logdir " ) ;
CPPUNIT_ASSERT_EQUAL_DIFF ( expected ,
filterConfig ( printConfig ( " scheduleworld " ) ) ) ;
}
}
2008-03-30 17:15:00 +02:00
void testListSources ( ) {
TestCmdline cmdline ( NULL ) ;
cmdline . doit ( ) ;
CPPUNIT_ASSERT_EQUAL_DIFF ( " " , cmdline . m_err . str ( ) ) ;
// exact output varies, do not test
}
void testMigrate ( ) {
ScopedEnvChange xdg ( " XDG_CONFIG_HOME " , m_testDir ) ;
ScopedEnvChange home ( " HOME " , m_testDir ) ;
rm_r ( m_testDir ) ;
string oldRoot = m_testDir + " /.sync4j/evolution/scheduleworld " ;
string newRoot = m_testDir + " /syncevolution/scheduleworld " ;
2008-03-30 18:13:08 +02:00
string oldConfig = OldScheduleWorldConfig ( ) ;
2008-03-30 17:15:00 +02:00
{
// migrate old config
createFiles ( oldRoot , oldConfig ) ;
string createdConfig = scanFiles ( oldRoot ) ;
TestCmdline cmdline ( " --migrate " ,
" scheduleworld " ,
NULL ) ;
cmdline . doit ( ) ;
CPPUNIT_ASSERT_EQUAL_DIFF ( " " , cmdline . m_err . str ( ) ) ;
CPPUNIT_ASSERT_EQUAL_DIFF ( " " , cmdline . m_out . str ( ) ) ;
string migratedConfig = scanFiles ( newRoot ) ;
CPPUNIT_ASSERT_EQUAL_DIFF ( m_scheduleWorldConfig , migratedConfig ) ;
string renamedConfig = scanFiles ( oldRoot + " .old " ) ;
CPPUNIT_ASSERT_EQUAL_DIFF ( createdConfig , renamedConfig ) ;
}
{
// rewrite existing config
createFiles ( newRoot ,
" config.ini:# obsolete comment \n "
" config.ini:obsoleteprop = foo \n " ,
true ) ;
string createdConfig = scanFiles ( newRoot ) ;
TestCmdline cmdline ( " --migrate " ,
" scheduleworld " ,
NULL ) ;
cmdline . doit ( ) ;
CPPUNIT_ASSERT_EQUAL_DIFF ( " " , cmdline . m_err . str ( ) ) ;
CPPUNIT_ASSERT_EQUAL_DIFF ( " " , cmdline . m_out . str ( ) ) ;
string migratedConfig = scanFiles ( newRoot ) ;
CPPUNIT_ASSERT_EQUAL_DIFF ( m_scheduleWorldConfig , migratedConfig ) ;
string renamedConfig = scanFiles ( newRoot + " .old " ) ;
CPPUNIT_ASSERT_EQUAL_DIFF ( createdConfig , renamedConfig ) ;
}
{
// migrate old config with changes, a second time
createFiles ( oldRoot , oldConfig ) ;
createFiles ( oldRoot ,
" spds/sources/addressbook/changes/config.txt:foo = bar \n "
" spds/sources/addressbook/changes/config.txt:foo2 = bar2 \n " ,
true ) ;
string createdConfig = scanFiles ( oldRoot ) ;
rm_r ( newRoot ) ;
TestCmdline cmdline ( " --migrate " ,
" scheduleworld " ,
NULL ) ;
cmdline . doit ( ) ;
CPPUNIT_ASSERT_EQUAL_DIFF ( " " , cmdline . m_err . str ( ) ) ;
CPPUNIT_ASSERT_EQUAL_DIFF ( " " , cmdline . m_out . str ( ) ) ;
string migratedConfig = scanFiles ( newRoot ) ;
string expected = m_scheduleWorldConfig ;
boost : : replace_first ( expected ,
" sources/addressbook/config.ini " ,
" sources/addressbook/.other.ini:foo = bar \n "
" sources/addressbook/.other.ini:foo2 = bar2 \n "
" sources/addressbook/config.ini " ) ;
CPPUNIT_ASSERT_EQUAL_DIFF ( expected , migratedConfig ) ;
string renamedConfig = scanFiles ( oldRoot + " .old.1 " ) ;
CPPUNIT_ASSERT_EQUAL_DIFF ( createdConfig , renamedConfig ) ;
}
}
2008-03-29 15:16:34 +01:00
const string m_testDir ;
2009-07-17 16:21:25 +02:00
string m_scheduleWorldConfig ;
2008-03-29 15:16:34 +01:00
2008-03-28 23:32:00 +01:00
private :
2008-03-29 15:16:34 +01:00
/**
* vararg constructor with NULL termination ,
* out and error stream into stringstream members
*/
class TestCmdline {
public :
TestCmdline ( const char * arg , . . . ) {
va_list argList ;
va_start ( argList , arg ) ;
for ( const char * curr = arg ;
curr ;
curr = va_arg ( argList , const char * ) ) {
m_argvstr . push_back ( curr ) ;
}
va_end ( argList ) ;
m_argv . reset ( new const char * [ m_argvstr . size ( ) + 1 ] ) ;
m_argv [ 0 ] = " client-test " ;
for ( size_t index = 0 ;
index < m_argvstr . size ( ) ;
+ + index ) {
m_argv [ index + 1 ] = m_argvstr [ index ] . c_str ( ) ;
}
m_cmdline . set ( new SyncEvolutionCmdline ( m_argvstr . size ( ) + 1 , m_argv . get ( ) , m_out , m_err ) , " cmdline " ) ;
}
void doit ( ) {
bool success ;
success = m_cmdline - > parse ( ) & &
m_cmdline - > run ( ) ;
if ( m_err . str ( ) . size ( ) ) {
2009-07-23 13:07:24 +02:00
cout < < endl < < m_err . str ( ) ;
2008-03-29 15:16:34 +01:00
}
CPPUNIT_ASSERT ( success ) ;
}
ostringstream m_out , m_err ;
cxxptr < SyncEvolutionCmdline > m_cmdline ;
private :
vector < string > m_argvstr ;
boost : : scoped_array < const char * > m_argv ;
} ;
2008-03-30 18:13:08 +02:00
string ScheduleWorldConfig ( ) {
2009-04-07 20:33:18 +02:00
string config = m_scheduleWorldConfig ;
2009-04-08 16:32:05 +02:00
if ( isDir ( string ( TEMPLATE_DIR ) + " /ScheduleWorld " ) ) {
2009-04-07 20:33:18 +02:00
boost : : replace_all ( config ,
" # IconURI = " ,
2009-04-08 16:36:41 +02:00
" IconURI = file:// " TEMPLATE_DIR " /ScheduleWorld/icon.png " ) ;
2009-04-07 20:33:18 +02:00
}
return config ;
2008-03-30 18:13:08 +02:00
}
string OldScheduleWorldConfig ( ) {
string oldConfig = m_scheduleWorldConfig ;
boost : : replace_all ( oldConfig ,
" .internal.ini " ,
" config.ini " ) ;
InitList < string > sources = InitList < string > ( " addressbook " ) +
" calendar " +
" memo " +
" todo " ;
BOOST_FOREACH ( string & source , sources ) {
boost : : replace_all ( oldConfig ,
string ( " sources/ " ) + source + " /config.ini " ,
string ( " spds/sources/ " ) + source + " /config.txt " ) ;
}
boost : : replace_all ( oldConfig ,
" config.ini " ,
" spds/syncml/config.txt " ) ;
return oldConfig ;
}
2008-03-30 13:43:36 +02:00
string FunambolConfig ( ) {
string config = m_scheduleWorldConfig ;
boost : : replace_first ( config ,
2008-06-28 15:27:07 +02:00
" syncURL = http://sync.scheduleworld.com/funambol/ds " ,
2008-06-28 23:32:16 +02:00
" syncURL = http://my.funambol.com/sync " ) ;
2008-03-30 13:43:36 +02:00
2009-04-07 20:33:18 +02:00
boost : : replace_first ( config ,
" WebURL = http://sync.scheduleworld.com " ,
" WebURL = http://my.funambol.com " ) ;
2009-06-25 11:06:07 +02:00
boost : : replace_first ( config ,
" # enableWBXML = 1 " ,
" enableWBXML = 0 " ) ;
2008-03-30 13:43:36 +02:00
boost : : replace_first ( config ,
" addressbook/config.ini:uri = card3 " ,
" addressbook/config.ini:uri = card " ) ;
boost : : replace_first ( config ,
2008-07-12 21:45:50 +02:00
" addressbook/config.ini:type = addressbook:text/vcard " ,
" addressbook/config.ini:type = addressbook " ) ;
2008-03-30 13:43:36 +02:00
boost : : replace_first ( config ,
2008-06-12 20:55:01 +02:00
" calendar/config.ini:uri = cal2 " ,
2008-03-30 13:43:36 +02:00
" calendar/config.ini:uri = event " ) ;
boost : : replace_first ( config ,
2009-07-08 17:56:49 +02:00
" calendar/config.ini:type = calendar " ,
" calendar/config.ini:type = calendar:text/calendar! " ) ;
2008-03-30 13:43:36 +02:00
boost : : replace_first ( config ,
" todo/config.ini:uri = task2 " ,
" todo/config.ini:uri = task " ) ;
boost : : replace_first ( config ,
2009-07-08 17:56:49 +02:00
" todo/config.ini:type = todo " ,
" todo/config.ini:type = todo:text/calendar! " ) ;
2008-03-30 13:43:36 +02:00
return config ;
}
string SynthesisConfig ( ) {
string config = m_scheduleWorldConfig ;
boost : : replace_first ( config ,
2008-06-28 15:27:07 +02:00
" syncURL = http://sync.scheduleworld.com/funambol/ds " ,
2008-03-30 13:43:36 +02:00
" syncURL = http://www.synthesis.ch/sync " ) ;
2009-04-07 20:33:18 +02:00
boost : : replace_first ( config ,
" WebURL = http://sync.scheduleworld.com " ,
" WebURL = http://www.synthesis.ch " ) ;
2009-06-29 20:32:26 +02:00
boost : : replace_first ( config ,
" ConsumerReady = 1 " ,
" # ConsumerReady = 0 " ) ;
2008-03-30 13:43:36 +02:00
boost : : replace_first ( config ,
" addressbook/config.ini:uri = card3 " ,
" addressbook/config.ini:uri = contacts " ) ;
2008-07-12 21:45:50 +02:00
boost : : replace_first ( config ,
" addressbook/config.ini:type = addressbook:text/vcard " ,
" addressbook/config.ini:type = addressbook " ) ;
2008-03-30 13:43:36 +02:00
boost : : replace_first ( config ,
2008-06-12 20:55:01 +02:00
" calendar/config.ini:uri = cal2 " ,
2008-03-30 13:43:36 +02:00
" calendar/config.ini:uri = events " ) ;
boost : : replace_first ( config ,
" calendar/config.ini:sync = two-way " ,
" calendar/config.ini:sync = disabled " ) ;
boost : : replace_first ( config ,
" memo/config.ini:uri = note " ,
" memo/config.ini:uri = notes " ) ;
boost : : replace_first ( config ,
" todo/config.ini:uri = task2 " ,
" todo/config.ini:uri = tasks " ) ;
boost : : replace_first ( config ,
" todo/config.ini:sync = two-way " ,
" todo/config.ini:sync = disabled " ) ;
return config ;
}
2008-03-29 15:16:34 +01:00
/** temporarily set env variable, restore old value on destruction */
class ScopedEnvChange {
public :
ScopedEnvChange ( const string & var , const string & value ) :
m_var ( var )
{
const char * oldval = getenv ( var . c_str ( ) ) ;
if ( oldval ) {
m_oldvalset = true ;
m_oldval = oldval ;
} else {
m_oldvalset = false ;
}
setenv ( var . c_str ( ) , value . c_str ( ) , 1 ) ;
}
~ ScopedEnvChange ( )
{
if ( m_oldvalset ) {
setenv ( m_var . c_str ( ) , m_oldval . c_str ( ) , 1 ) ;
} else {
unsetenv ( m_var . c_str ( ) ) ;
}
}
private :
string m_var , m_oldval ;
bool m_oldvalset ;
} ;
2008-03-28 23:32:00 +01:00
/** create directory hierarchy, overwriting previous content */
2008-03-30 17:15:00 +02:00
void createFiles ( const string & root , const string & content , bool append = false ) {
if ( ! append ) {
rm_r ( root ) ;
}
2008-03-28 23:32:00 +01:00
size_t start = 0 ;
ofstream out ;
string outname ;
out . exceptions ( ios_base : : badbit | ios_base : : failbit ) ;
while ( start < content . size ( ) ) {
size_t delim = content . find ( ' : ' , start ) ;
size_t end = content . find ( ' \n ' , start ) ;
if ( delim = = content . npos | |
end = = content . npos ) {
// invalid content ?!
break ;
}
string newname = content . substr ( start , delim - start ) ;
string line = content . substr ( delim + 1 , end - delim - 1 ) ;
if ( newname ! = outname ) {
if ( out . is_open ( ) ) {
out . close ( ) ;
}
string fullpath = root + " / " + newname ;
size_t fileoff = fullpath . rfind ( ' / ' ) ;
mkdir_p ( fullpath . substr ( 0 , fileoff ) ) ;
2008-03-30 17:15:00 +02:00
out . open ( fullpath . c_str ( ) ,
append ? ios_base : : out : ( ios_base : : out | ios_base : : trunc ) ) ;
2008-03-28 23:32:00 +01:00
outname = newname ;
}
out < < line < < endl ;
start = end + 1 ;
}
}
/** turn directory hierarchy into string */
2008-03-29 15:16:34 +01:00
string scanFiles ( const string & root , bool onlyProps = true ) {
2008-03-28 23:32:00 +01:00
ostringstream out ;
2008-03-29 15:16:34 +01:00
scanFiles ( root , " " , out , onlyProps ) ;
2008-03-28 23:32:00 +01:00
return out . str ( ) ;
}
2008-03-30 23:50:51 +02:00
2008-03-29 15:16:34 +01:00
void scanFiles ( const string & root , const string & dir , ostringstream & out , bool onlyProps ) {
string newroot = root ;
newroot + = " / " ;
newroot + = dir ;
ReadDir readDir ( newroot ) ;
2008-03-28 23:32:00 +01:00
sort ( readDir . begin ( ) , readDir . end ( ) ) ;
2008-07-11 22:25:02 +02:00
BOOST_FOREACH ( const string & entry , readDir ) {
if ( isDir ( newroot + " / " + entry ) ) {
scanFiles ( root , dir + ( dir . empty ( ) ? " " : " / " ) + entry , out , onlyProps ) ;
2008-03-29 15:16:34 +01:00
} else {
ifstream in ;
in . exceptions ( ios_base : : badbit /* failbit must not trigger exception because is set when reaching eof ?! */ ) ;
2008-07-11 22:25:02 +02:00
in . open ( ( newroot + " / " + entry ) . c_str ( ) ) ;
2008-03-29 15:16:34 +01:00
string line ;
while ( ! in . eof ( ) ) {
getline ( in , line ) ;
if ( ( line . size ( ) | | ! in . eof ( ) ) & &
( ! onlyProps | |
2008-03-30 23:50:51 +02:00
( boost : : starts_with ( line , " # " ) ?
isPropAssignment ( line . substr ( 2 ) ) :
! line . empty ( ) ) ) ) {
2008-03-29 15:16:34 +01:00
if ( dir . size ( ) ) {
out < < dir < < " / " ;
}
2008-07-11 22:25:02 +02:00
out < < entry < < " : " ;
2008-03-29 15:16:34 +01:00
out < < line < < ' \n ' ;
2008-03-28 23:32:00 +01:00
}
}
}
}
}
2008-03-30 15:41:56 +02:00
string printConfig ( const string & server ) {
ScopedEnvChange xdg ( " XDG_CONFIG_HOME " , m_testDir ) ;
ScopedEnvChange home ( " HOME " , m_testDir ) ;
TestCmdline cmdline ( " --print-config " , server . c_str ( ) , NULL ) ;
cmdline . doit ( ) ;
CPPUNIT_ASSERT_EQUAL_DIFF ( " " , cmdline . m_err . str ( ) ) ;
return cmdline . m_out . str ( ) ;
}
2008-03-28 23:32:00 +01:00
} ;
SYNCEVOLUTION_TEST_SUITE_REGISTRATION ( SyncEvolutionCmdlineTest ) ;
# endif // ENABLE_UNIT_TESTS