Allow passing raw CLI arguments in libsyncthing interface
This commit is contained in:
parent
f7dc8c93bd
commit
fbbf533a37
|
@ -1 +1 @@
|
|||
Subproject commit c5832cc1a8997ca06bfcf8a72a3b056f2e6c823d
|
||||
Subproject commit bdd181e36aaf1a7cc6ac817cea770df1d8e746e6
|
|
@ -8,6 +8,8 @@ using namespace std;
|
|||
|
||||
namespace LibSyncthing {
|
||||
|
||||
///! \cond
|
||||
|
||||
/*!
|
||||
* \brief Holds the user provided logging callback which is assigned via setLoggingCallback().
|
||||
*/
|
||||
|
@ -63,6 +65,38 @@ void handleLoggingCallback(int logLevelInt, const char *msg, size_t msgSize)
|
|||
loggingCallback(logLevel, msg, msgSize);
|
||||
}
|
||||
|
||||
class RunningState {
|
||||
public:
|
||||
RunningState();
|
||||
~RunningState();
|
||||
operator bool() const;
|
||||
|
||||
private:
|
||||
bool m_invalid;
|
||||
};
|
||||
|
||||
inline RunningState::RunningState()
|
||||
{
|
||||
if ((m_invalid = syncthingRunning.load())) {
|
||||
return;
|
||||
}
|
||||
::libst_loggingCallbackFunction = handleLoggingCallback;
|
||||
syncthingRunning.store(true);
|
||||
}
|
||||
|
||||
inline RunningState::~RunningState()
|
||||
{
|
||||
::libst_loggingCallbackFunction = nullptr;
|
||||
syncthingRunning.store(false);
|
||||
}
|
||||
|
||||
inline RunningState::operator bool() const
|
||||
{
|
||||
return !m_invalid;
|
||||
}
|
||||
|
||||
///! \endcond
|
||||
|
||||
/*!
|
||||
* \brief Sets the callback function for logging. It will be called when a new log message becomes available.
|
||||
* \remarks The callback is not necessarily invoked in the same thread it was registered.
|
||||
|
@ -91,15 +125,12 @@ void setLoggingCallback(LoggingCallback &&callback)
|
|||
*/
|
||||
long long runSyncthing(const RuntimeOptions &options)
|
||||
{
|
||||
if (syncthingRunning.load()) {
|
||||
const RunningState runningState;
|
||||
if (!runningState) {
|
||||
return -1;
|
||||
}
|
||||
syncthingRunning.store(true);
|
||||
::libst_loggingCallbackFunction = handleLoggingCallback;
|
||||
const auto exitCode = ::libst_runSyncthing(
|
||||
return ::libst_runSyncthingWithConfig(
|
||||
gostr(options.configDir), gostr(options.guiAddress), gostr(options.guiApiKey), gostr(options.logFile), options.verbose);
|
||||
syncthingRunning.store(false);
|
||||
return exitCode;
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -112,15 +143,35 @@ long long runSyncthing(const RuntimeOptions &options)
|
|||
*/
|
||||
long long runSyncthing(const std::string &configDir)
|
||||
{
|
||||
if (syncthingRunning.load()) {
|
||||
const RunningState runningState;
|
||||
if (!runningState) {
|
||||
return -1;
|
||||
}
|
||||
syncthingRunning.store(true);
|
||||
::libst_loggingCallbackFunction = handleLoggingCallback;
|
||||
const string empty;
|
||||
const auto exitCode = ::libst_runSyncthing(gostr(configDir), gostr(empty), gostr(empty), gostr(empty), false);
|
||||
syncthingRunning.store(false);
|
||||
return exitCode;
|
||||
return ::libst_runSyncthingWithConfig(gostr(configDir), gostr(empty), gostr(empty), gostr(empty), false);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Runs a Syncthing instance using the specified raw \a cliArguments.
|
||||
* \return Returns the exit code (as usual, zero means no error).
|
||||
* \remark
|
||||
* - Does nothing if Syncthing is already running.
|
||||
* - Blocks the current thread as long as the instance is running.
|
||||
* Use eg. std::thread(runSyncthing, options) to run it in another thread.
|
||||
*/
|
||||
long long runSyncthing(const std::vector<string> &cliArguments)
|
||||
{
|
||||
const RunningState runningState;
|
||||
if (!runningState) {
|
||||
return -1;
|
||||
}
|
||||
vector<const char *> argsAsGoStrings;
|
||||
argsAsGoStrings.reserve(cliArguments.size());
|
||||
for (const auto &arg : cliArguments) {
|
||||
argsAsGoStrings.emplace_back(arg.data());
|
||||
}
|
||||
const GoSlice slice{ argsAsGoStrings.data(), static_cast<GoInt>(argsAsGoStrings.size()), static_cast<GoInt>(argsAsGoStrings.capacity()) };
|
||||
return ::libst_runSyncthingWithArgs(slice);
|
||||
}
|
||||
|
||||
/*!
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace LibSyncthing {
|
||||
|
||||
|
@ -32,6 +33,7 @@ void LIB_SYNCTHING_EXPORT setLoggingCallback(const LoggingCallback &callback);
|
|||
void LIB_SYNCTHING_EXPORT setLoggingCallback(LoggingCallback &&callback);
|
||||
long long LIB_SYNCTHING_EXPORT runSyncthing(const RuntimeOptions &options);
|
||||
long long LIB_SYNCTHING_EXPORT runSyncthing(const std::string &configDir);
|
||||
long long LIB_SYNCTHING_EXPORT runSyncthing(const std::vector<std::string> &cliArguments);
|
||||
bool LIB_SYNCTHING_EXPORT isSyncthingRunning();
|
||||
void LIB_SYNCTHING_EXPORT stopSyncthing();
|
||||
void LIB_SYNCTHING_EXPORT restartSyncthing();
|
||||
|
|
|
@ -9,6 +9,9 @@
|
|||
#include <cppunit/TestFixture.h>
|
||||
#include <cppunit/extensions/HelperMacros.h>
|
||||
|
||||
#include <cstdlib>
|
||||
#include <functional>
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
using namespace std;
|
||||
|
@ -25,20 +28,25 @@ using namespace CPPUNIT_NS;
|
|||
*/
|
||||
class InterfaceTests : public TestFixture {
|
||||
CPPUNIT_TEST_SUITE(InterfaceTests);
|
||||
CPPUNIT_TEST(testRun);
|
||||
CPPUNIT_TEST(testRunWidthConfig);
|
||||
CPPUNIT_TEST(testRunWithArgs);
|
||||
CPPUNIT_TEST(testVersion);
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
|
||||
public:
|
||||
InterfaceTests();
|
||||
|
||||
void testRun();
|
||||
void testInitialState();
|
||||
void testRunWidthConfig();
|
||||
void testRunWithArgs();
|
||||
void testVersion();
|
||||
|
||||
void setUp();
|
||||
void tearDown();
|
||||
|
||||
private:
|
||||
static std::string setupConfigDir();
|
||||
void testRun(const std::function<long long(void)> &runFunction);
|
||||
};
|
||||
|
||||
CPPUNIT_TEST_SUITE_REGISTRATION(InterfaceTests);
|
||||
|
@ -57,26 +65,36 @@ void InterfaceTests::tearDown()
|
|||
}
|
||||
|
||||
/*!
|
||||
* \brief Tests running Syncthing.
|
||||
* \brief Initializes the Syncthing config for this fixture (currently using same config as in connector test).
|
||||
* \returns Returns the config directory.
|
||||
*/
|
||||
void InterfaceTests::testRun()
|
||||
string InterfaceTests::setupConfigDir()
|
||||
{
|
||||
// setup Syncthing config (currently using same config as in connector test)
|
||||
const auto configFilePath(workingCopyPath("testconfig/config.xml"));
|
||||
if (configFilePath.empty()) {
|
||||
throw runtime_error("Unable to setup Syncthing config directory.");
|
||||
}
|
||||
return directory(configFilePath);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Tests behavior in initial state, when Syncthing isn't supposed to be running.
|
||||
*/
|
||||
void InterfaceTests::testInitialState()
|
||||
{
|
||||
CPPUNIT_ASSERT_MESSAGE("initially not running", !isSyncthingRunning());
|
||||
|
||||
// stopping and restarting Syncthing when not running should not cause any trouble
|
||||
stopSyncthing();
|
||||
restartSyncthing();
|
||||
}
|
||||
|
||||
// setup Syncthing config (currently using same config as in connector test)
|
||||
const auto configFilePath(workingCopyPath("testconfig/config.xml"));
|
||||
if (configFilePath.empty()) {
|
||||
throw runtime_error("Unable to setup Syncthing config directory.");
|
||||
}
|
||||
|
||||
// setup runtime options
|
||||
RuntimeOptions options;
|
||||
options.configDir = directory(configFilePath);
|
||||
|
||||
/*!
|
||||
* \brief Tests running Syncthing.
|
||||
*/
|
||||
void InterfaceTests::testRun(const std::function<long long()> &runFunction)
|
||||
{
|
||||
// keep track of certain log messages
|
||||
const auto startTime(DateTime::gmtNow());
|
||||
bool myIdAnnounced = false, performanceAnnounced = false;
|
||||
|
@ -127,7 +145,7 @@ void InterfaceTests::testRun()
|
|||
}
|
||||
});
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("Syncthing exited without error", 0ll, runSyncthing(options));
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("Syncthing exited without error", 0ll, runFunction());
|
||||
|
||||
// assert whether all expected log messages were present
|
||||
CPPUNIT_ASSERT(myIdAnnounced);
|
||||
|
@ -142,6 +160,23 @@ void InterfaceTests::testRun()
|
|||
// FIXME: make this test pass, stop Syncthing correctly
|
||||
sleep(5);
|
||||
}
|
||||
|
||||
void InterfaceTests::testRunWidthConfig()
|
||||
{
|
||||
RuntimeOptions options;
|
||||
options.configDir = setupConfigDir();
|
||||
testRun(bind(static_cast<long long (*)(const RuntimeOptions &)>(&runSyncthing), cref(options)));
|
||||
}
|
||||
|
||||
void InterfaceTests::testRunWithArgs()
|
||||
{
|
||||
const std::vector<std::string> args{
|
||||
"-no-restart",
|
||||
"-no-browser",
|
||||
"-home",
|
||||
setupConfigDir(),
|
||||
};
|
||||
testRun(bind(static_cast<long long (*)(const decltype(args) &)>(&runSyncthing), cref(args)));
|
||||
}
|
||||
|
||||
/*!
|
||||
|
|
Loading…
Reference in New Issue