summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'Swiften/QA/FileTransferTest/FileTransferTest.cpp')
-rw-r--r--Swiften/QA/FileTransferTest/FileTransferTest.cpp45
1 files changed, 34 insertions, 11 deletions
diff --git a/Swiften/QA/FileTransferTest/FileTransferTest.cpp b/Swiften/QA/FileTransferTest/FileTransferTest.cpp
index 8597033..7a50e9f 100644
--- a/Swiften/QA/FileTransferTest/FileTransferTest.cpp
+++ b/Swiften/QA/FileTransferTest/FileTransferTest.cpp
@@ -22,234 +22,256 @@
#include <Swiften/Elements/Presence.h>
#include <Swiften/EventLoop/SimpleEventLoop.h>
#include <Swiften/FileTransfer/FileReadBytestream.h>
#include <Swiften/FileTransfer/FileTransferManager.h>
#include <Swiften/FileTransfer/FileWriteBytestream.h>
#include <Swiften/FileTransfer/OutgoingFileTransfer.h>
#include <Swiften/FileTransfer/ReadBytestream.h>
#include <Swiften/Network/BoostNetworkFactories.h>
#include <Swiften/Network/Timer.h>
#include <Swiften/Network/TimerFactory.h>
using namespace Swift;
static const std::string CLIENT_NAME = "Swiften FT Test";
static const std::string CLIENT_NODE = "http://swift.im";
static boost::shared_ptr<SimpleEventLoop> eventLoop;
static boost::shared_ptr<BoostNetworkFactories> networkFactories;
BoostRandomGenerator randGen;
enum Candidate {
InBandBytestream = 1,
S5B_Direct = 2,
S5B_Proxied = 4,
S5B_Assisted = 8,
};
class FileTransferTest {
public:
- FileTransferTest(int senderCandidates, int receiverCandidates) : senderCandidates_(senderCandidates), senderIsDone_(false), receiverCandidates_(receiverCandidates), receiverIsDone_(false) {
+ FileTransferTest(int senderCandidates, int receiverCandidates) : senderCandidates_(senderCandidates), senderError_(FileTransferError::UnknownError), senderIsDone_(false), receiverCandidates_(receiverCandidates), receiverError_(FileTransferError::UnknownError), receiverIsDone_(false) {
sender_ = boost::make_shared<Client>(JID(getenv("SWIFT_FILETRANSFERTEST_JID")), getenv("SWIFT_FILETRANSFERTEST_PASS"), networkFactories.get());
sender_->onDisconnected.connect(boost::bind(&FileTransferTest::handleSenderDisconnected, this, _1));
sender_->onConnected.connect(boost::bind(&FileTransferTest::handleSenderConnected, this));
sender_->getEntityCapsProvider()->onCapsChanged.connect(boost::bind(&FileTransferTest::handleSenderCapsChanged, this, _1));
receiver_ = boost::make_shared<Client>(JID(getenv("SWIFT_FILETRANSFERTEST2_JID")), getenv("SWIFT_FILETRANSFERTEST2_PASS"), networkFactories.get());
receiver_->onConnected.connect(boost::bind(&FileTransferTest::handleReceiverConnected, this));
receiver_->onDisconnected.connect(boost::bind(&FileTransferTest::handleReceiverDisconnected, this, _1));
senderTracer_ = new ClientXMLTracer(sender_.get());
receiverTracer_ = new ClientXMLTracer(receiver_.get());
ClientOptions options;
options.useTLS = ClientOptions::NeverUseTLS;
options.useStreamCompression = false;
options.useStreamResumption = false;
options.useAcks = false;
sender_->connect(options);
receiver_->connect(options);
timeOut_ = networkFactories->getTimerFactory()->createTimer(60000);
timeOut_->onTick.connect(boost::bind(&FileTransferTest::handleTimeOut, this));
// Create randomly sized data to exchange.
sendFilePath_ = boost::filesystem::unique_path("ft_send_%%%%%%%%%%%%%%%%.bin");
receiveFilePath_ = boost::filesystem::unique_path("ft_receive_%%%%%%%%%%%%%%%%.bin");
size_t size = 1024 + boost::numeric_cast<size_t>(randGen.generateRandomInteger(1024 * 10));
sendData_.resize(size);
for (size_t n = 0; n < sendData_.size(); n++) {
sendData_[n] = boost::numeric_cast<unsigned char>(randGen.generateRandomInteger(255));
}
std::ofstream outfile(sendFilePath_.native().c_str(), std::ios::out | std::ios::binary);
outfile.write(reinterpret_cast<char *>(&sendData_[0]), boost::numeric_cast<ptrdiff_t>(sendData_.size()));
outfile.close();
}
~FileTransferTest() {
timeOut_->stop();
delete senderTracer_;
delete receiverTracer_;
// Free file-transfer objects so file handles are closed and files can be removed afterwards.
assert(!outgoingFileTransfer_ && incomingFileTransfers_.empty());
if(boost::filesystem::exists(sendFilePath_)) {
boost::filesystem::remove(sendFilePath_);
}
if(boost::filesystem::exists(receiveFilePath_)) {
boost::filesystem::remove(receiveFilePath_);
}
}
void handleSenderConnected() {
+ DiscoInfo discoInfo;
+ discoInfo.addIdentity(DiscoInfo::Identity(CLIENT_NAME, "client", "pc"));
+ discoInfo.addFeature(DiscoInfo::JingleFeature);
+ discoInfo.addFeature(DiscoInfo::JingleFTFeature);
+ discoInfo.addFeature(DiscoInfo::Bytestream);
+ if (senderCandidates_ & InBandBytestream) {
+ discoInfo.addFeature(DiscoInfo::JingleTransportsIBBFeature);
+ }
+ if (senderCandidates_ & (S5B_Direct | S5B_Assisted | S5B_Proxied)) {
+ discoInfo.addFeature(DiscoInfo::JingleTransportsS5BFeature);
+ }
+ sender_->getDiscoManager()->setCapsNode(CLIENT_NODE);
+ sender_->getDiscoManager()->setDiscoInfo(discoInfo);
sender_->sendPresence(Presence::create());
}
void handleReceiverConnected() {
receiver_->getFileTransferManager()->onIncomingFileTransfer.connect(boost::bind(&FileTransferTest::handleReceiverIncomingFileTransfer, this, _1));
DiscoInfo discoInfo;
discoInfo.addIdentity(DiscoInfo::Identity(CLIENT_NAME, "client", "pc"));
discoInfo.addFeature(DiscoInfo::JingleFeature);
discoInfo.addFeature(DiscoInfo::JingleFTFeature);
discoInfo.addFeature(DiscoInfo::Bytestream);
- discoInfo.addFeature(DiscoInfo::JingleTransportsIBBFeature);
- discoInfo.addFeature(DiscoInfo::JingleTransportsS5BFeature);
+ if (receiverCandidates_ & InBandBytestream) {
+ discoInfo.addFeature(DiscoInfo::JingleTransportsIBBFeature);
+ }
+ if (receiverCandidates_ & (S5B_Direct | S5B_Assisted | S5B_Proxied)) {
+ discoInfo.addFeature(DiscoInfo::JingleTransportsS5BFeature);
+ }
receiver_->getDiscoManager()->setCapsNode(CLIENT_NODE);
receiver_->getDiscoManager()->setDiscoInfo(discoInfo);
receiver_->getPresenceSender()->sendPresence(Presence::create());
}
void handleReceiverIncomingFileTransfer(IncomingFileTransfer::ref transfer) {
incomingFileTransfers_.push_back(transfer);
boost::shared_ptr<FileWriteBytestream> out = boost::make_shared<FileWriteBytestream>(receiveFilePath_.native());
transfer->onFinished.connect(boost::bind(&FileTransferTest::handleReceiverFileTransferFinished, this, _1, out));
FileTransferOptions options;
options = options.withInBandAllowed(receiverCandidates_ & InBandBytestream);
options = options.withDirectAllowed(receiverCandidates_ & S5B_Direct);
options = options.withAssistedAllowed(receiverCandidates_ & S5B_Assisted);
options = options.withProxiedAllowed(receiverCandidates_ & S5B_Proxied);
std::cout << "Incoming transfer options: " << "IBB (" << options.isInBandAllowed() << ")" << ", ";
std::cout << "S5B Direct (" << options.isDirectAllowed() << ")" << ", ";
std::cout << "S5B Assisted (" << options.isAssistedAllowed() << ")" << ", ";
std::cout << "S5B Proxied (" << options.isProxiedAllowed() << ")" << std::endl;
transfer->accept(out, options);
}
void handleSenderCapsChanged(const JID &jid) {
if (receiver_ && (receiver_->getJID().toBare() == jid.toBare())) {
boost::shared_ptr<FileReadBytestream> fileStream = boost::make_shared<FileReadBytestream>(sendFilePath_);
FileTransferOptions options;
options = options.withInBandAllowed(senderCandidates_ & InBandBytestream);
options = options.withDirectAllowed(senderCandidates_ & S5B_Direct);
options = options.withAssistedAllowed(senderCandidates_ & S5B_Assisted);
options = options.withProxiedAllowed(senderCandidates_ & S5B_Proxied);
std::cout << "Outgoing transfer options: " << "IBB (" << options.isInBandAllowed() << ")" << ", ";
std::cout << "S5B Direct (" << options.isDirectAllowed() << ")" << ", ";
std::cout << "S5B Assisted (" << options.isAssistedAllowed() << ")" << ", ";
std::cout << "S5B Proxied (" << options.isProxiedAllowed() << ")" << std::endl;
outgoingFileTransfer_ = sender_->getFileTransferManager()->createOutgoingFileTransfer(jid.toBare(), sendFilePath_, "Some File!", fileStream, options);
if (outgoingFileTransfer_) {
outgoingFileTransfer_->onFinished.connect(boost::bind(&FileTransferTest::handleSenderFileTransferFinished, this, _1));
outgoingFileTransfer_->start();
} else {
std::cout << "ERROR: No outgoing file transfer returned." << std::endl;
+ receiverIsDone_ = true;
+ senderIsDone_ = true;
endTest();
}
}
}
void handleReceiverFileTransferFinished(const boost::optional<FileTransferError>& error, boost::shared_ptr<FileWriteBytestream> out) {
out->close();
receiverError_ = error;
receiverIsDone_ = true;
if (senderIsDone_) {
timeOut_->stop();
timeOut_ = networkFactories->getTimerFactory()->createTimer(1000);
timeOut_->onTick.connect(boost::bind(&FileTransferTest::endTest, this));
timeOut_->start();
}
}
void handleSenderDisconnected(const boost::optional<ClientError>& error) {
if (error) {
std::cout << this << " " << "handleSenderDisconnected: error: " << error.get() << std::endl;
}
// All file-transfers related to a Client instance need to be freed
// *before* freeing the Client instance.
outgoingFileTransfer_.reset();
sender_.reset();
if (!sender_ && !receiver_) {
eventLoop->stop();
}
}
void handleReceiverDisconnected(const boost::optional<ClientError>& error) {
if (error) {
std::cout << this << " " << "handleReceiverDisconnected: error: " << error.get() << std::endl;
}
// All file-transfers related to a Client instance need to be freed
// *before* freeing the Client instance.
incomingFileTransfers_.clear();
receiver_.reset();
if (!sender_ && !receiver_) {
eventLoop->stop();
}
}
void handleSenderFileTransferFinished(const boost::optional<FileTransferError>& error) {
senderError_ = error;
senderIsDone_ = true;
if (receiverIsDone_) {
timeOut_->stop();
timeOut_ = networkFactories->getTimerFactory()->createTimer(1000);
timeOut_->onTick.connect(boost::bind(&FileTransferTest::endTest, this));
timeOut_->start();
}
+ else if (error) {
+ endTest();
+ }
}
void run() {
timeOut_->start();
eventLoop->run();
}
void endTest() {
if (sender_) {
sender_->disconnect();
}
if (receiver_) {
receiver_->disconnect();
}
}
void handleTimeOut() {
std::cout << "Test timed out!!!" << std::endl;
endTest();
}
bool isDone() const {
return senderIsDone_ && receiverIsDone_;
}
bool wasSuccessful() const {
return !senderError_ && !receiverError_;
}
private:
@@ -260,70 +282,71 @@ class FileTransferTest {
OutgoingFileTransfer::ref outgoingFileTransfer_;
boost::filesystem::path sendFilePath_;
boost::optional<FileTransferError> senderError_;
bool senderIsDone_;
int receiverCandidates_;
boost::shared_ptr<Client> receiver_;
ClientXMLTracer* receiverTracer_;
ByteArray receiveData_;
std::vector<IncomingFileTransfer::ref> incomingFileTransfers_;
boost::filesystem::path receiveFilePath_;
boost::optional<FileTransferError> receiverError_;
bool receiverIsDone_;
Timer::ref timeOut_;
};
static bool runTest(int senderCandidates, int receiverCandidates) {
bool success = false;
std::cout << "senderCandidates: " << senderCandidates << ", receiverCandidates: " << receiverCandidates << std::endl;
bool expectSuccess = (senderCandidates & receiverCandidates) > 0;
eventLoop = boost::make_shared<SimpleEventLoop>();
networkFactories = boost::make_shared<BoostNetworkFactories>(eventLoop.get());
boost::shared_ptr<FileTransferTest> testRun = boost::make_shared<FileTransferTest>(senderCandidates, receiverCandidates);
testRun->run();
- if (testRun->isDone()) {
- bool wasSuccessful = testRun->wasSuccessful();
- if (expectSuccess == wasSuccessful) {
- success = true;
- } else {
- std::cout << "expected success: " << expectSuccess << ", wasSuccessful: " << wasSuccessful << std::endl;
+ bool wasSuccessful = testRun->wasSuccessful();
+ if (expectSuccess == wasSuccessful) {
+ success = true;
+ }
+ else {
+ if (!testRun->isDone()) {
+ std::cout << "Test did not finish transfer. Sender candidates = " << senderCandidates << ", receiver candidates = " << receiverCandidates << "." << std::endl;
}
- } else {
- std::cout << "Failed to run test! Sender candidates = " << senderCandidates << ", receiver candidates = " << receiverCandidates << "." << std::endl;
}
+ std::cout << "expected success: " << expectSuccess << ", wasSuccessful: " << wasSuccessful << std::endl;
+
testRun.reset();
networkFactories.reset();
eventLoop->runUntilEvents();
eventLoop->stop();
eventLoop.reset();
return success;
}
/**
* This program test file-transfer interop between Swift and itself with various connection candidates.
* The all combinations of the candidates, IBB, S5B (direct) and S5B (proxied), on sender and receiver side are tested.
*/
int main(int argc, char** argv) {
int failedTests = 0;
std::vector<std::pair<int, int> > failedTestPairs;
std::cout << "Swiften File-Transfer Connectivity Test Suite" << std::endl;
if (argc == 1) {
if (getenv("SWIFT_FILETRANSFERTEST_CONFIG")) {
// test configuration described in SWIFT_FILETRANSFERTEST_CONFIG environment variable, e.g. "1:1|2:2"
std::vector<std::string> configurations;
std::string configs_env = std::string(getenv("SWIFT_FILETRANSFERTEST_CONFIG"));
boost::split(configurations, configs_env, boost::is_any_of("|"));
foreach(const std::string& config, configurations) {
std::vector<std::string> split_config;
boost::split(split_config, config, boost::is_any_of(":"));
assert(split_config.size() == 2);