Commit eaeab401 authored by Eric Cano's avatar Eric Cano
Browse files

Created a new ClientSimSingleReply class and extended unit tests for ClientInterface.

The new ClientSimSingleReply template allows the planning of a single reply of any type.
The request-reply combinations for all the currently implemented calls in ClientInterface
have been validated using it.
parent a4acc5cd
......@@ -139,6 +139,7 @@ throw (castor::tape::Exception) {
EndOfSession eos("Client replied noMoreFiles directly to volume request: ");
eos.getMessage() << "errorCode=" << errorReport->errorCode()
<< "errorReport=\"" << errorReport->errorMessage() << "\"";
throw eos;
// Unexpected response type
} else {
throw UnexpectedResponse(response.get(), "Unexpected response from client in response "
......
/******************************************************************************
* clientSimulator.hpp
*
* This file is part of the Castor project.
* See http://castor.web.cern.ch/castor
*
* Copyright (C) 2003 CERN
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program 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 General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*
*
* @author Castor Dev team, castor-dev@cern.ch
*****************************************************************************/
#pragma once
#include "../../tpcp/TpcpCommand.hpp"
#include <memory>
#include "castor/tape/tapegateway/FileToMigrateStruct.hpp"
#include "castor/tape/tapegateway/FilesToMigrateList.hpp"
namespace castor {
namespace tape {
namespace tapeserver {
namespace daemon {
/**
* A templated class, reusing code of TpcpCommand which simulates the
* tapegateway part of the client communication with the server. The
* constructor will hence setup a client callback socket and wait. The
* method processRequest will wait for a message and reply with the type
* chosen on template implementation.
*/
template<class ReplyType>
class ClientSimSingleReply: public tpcp::TpcpCommand {
public:
ClientSimSingleReply(uint32_t volReqId, const std::string & vid,
const std::string & density, bool breakTransaction = false):
TpcpCommand("clientSimulator::clientSimulator"), m_vid(vid),
m_density(density), m_breakTransaction(breakTransaction)
{
m_volReqId = volReqId;
setupCallbackSock();
}
virtual ~ClientSimSingleReply() throw () {}
struct ipPort {
ipPort(uint32_t i, uint16_t p): ip(i), port(p) {}
union {
uint32_t ip;
struct {
uint8_t a;
uint8_t b;
uint8_t c;
uint8_t d;
};
};
uint16_t port;
};
struct ipPort getCallbackAddress() {
unsigned short port = 0;
/* This is a workaround for the usage of unsigned long for ips in castor
* (it's not fine anymore on 64 bits systems).
*/
unsigned long ip = 0;
m_callbackSock.getPortIp(port, ip);
return ipPort(ip,port);
}
void sessionLoop() {
processFirstRequest();
m_callbackSock.close();
}
protected:
// Place holders for pure virtual members of TpcpCommand we don't
// use in the simulator
virtual void usage(std::ostream &) const throw () {}
virtual void parseCommandLine(const int, char **)
throw(castor::exception::Exception) {}
virtual void checkAccessToDisk()
const throw(castor::exception::Exception) {}
virtual void checkAccessToTape()
const throw(castor::exception::Exception) {}
virtual void requestDriveFromVdqm(char *const)
throw(castor::exception::Exception) {}
virtual void performTransfer() throw(castor::exception::Exception) {}
// The functions we actually implement in the simulator
virtual void sendVolumeToTapeBridge(
const tapegateway::VolumeRequest &volumeRequest,
castor::io::AbstractTCPSocket &connection)
const throw(castor::exception::Exception) {}
virtual bool dispatchMsgHandler(castor::IObject *const obj,
castor::io::AbstractSocket &sock) throw(castor::exception::Exception) {
return false;
}
private:
// Process the first request which should be getVolume
void processFirstRequest() throw(castor::exception::Exception) {
// Accept the next connection
std::auto_ptr<castor::io::ServerSocket> clientConnection(m_callbackSock.accept());
// Read in the message sent by the tapebridge
std::auto_ptr<castor::IObject> obj(clientConnection->readObject());
// Convert to a gateway message (for transactionId)
tapegateway::GatewayMessage & gm =
dynamic_cast<tapegateway::GatewayMessage &>(*obj);
// Reply with our own type and transaction id
ReplyType repl;
repl.setAggregatorTransactionId(gm.aggregatorTransactionId() ^
(m_breakTransaction?666:0));
repl.setMountTransactionId(m_volReqId);
clientConnection->sendObject(repl);
}
// Notify the client
void sendEndNotificationErrorReport(
const uint64_t tapebridgeTransactionId,
const int errorCode,
const std::string &errorMessage,
castor::io::AbstractSocket &sock)
throw();
std::string m_vid;
std::string m_volLabel;
std::string m_density;
bool m_breakTransaction;
};
/**
* Specific version for the FilesToMigrateList: we want
* to pass a non empty list, so it has to be a little bit less trivial.
*/
template<>
void ClientSimSingleReply<castor::tape::tapegateway::FilesToMigrateList>::processFirstRequest()
throw(castor::exception::Exception) {
using namespace castor::tape::tapegateway;
// Accept the next connection
std::auto_ptr<castor::io::ServerSocket> clientConnection(m_callbackSock.accept());
// Read in the message sent by the tapebridge
std::auto_ptr<castor::IObject> obj(clientConnection->readObject());
// Convert to a gateway message (for transactionId)
GatewayMessage & gm =
dynamic_cast<tapegateway::GatewayMessage &>(*obj);
// Reply with our own type and transaction id
FilesToMigrateList repl;
repl.setAggregatorTransactionId(gm.aggregatorTransactionId() ^
(m_breakTransaction?666:0));
repl.setMountTransactionId(m_volReqId);
repl.filesToMigrate().push_back(new FileToMigrateStruct());
clientConnection->sendObject(repl);
}
}
}
}
}
......@@ -67,6 +67,7 @@ namespace daemon {
}
void sessionLoop() {
processFirstRequest();
m_callbackSock.close();
}
protected:
......
......@@ -24,12 +24,17 @@
#include <gtest/gtest.h>
#include "ClientSimulator.hpp"
#include "ClientSimSingleReply.hpp"
#include "ClientInterface.hpp"
#include "../threading/Threading.hpp"
#include "castor/log/StringLogger.hpp"
#include "MountSession.hpp"
#include "../system/Wrapper.hpp"
#include "Ctape.h"
#include "castor/tape/tapegateway/Volume.hpp"
#include "castor/tape/tapegateway/NoMoreFiles.hpp"
#include "castor/tape/tapegateway/EndNotificationErrorReport.hpp"
#include "castor/tape/tapegateway/NotificationAcknowledge.hpp"
using namespace castor::tape::tapeserver::daemon;
......@@ -88,4 +93,416 @@ TEST(tapeServer, MountSessionGoodday) {
ASSERT_EQ("V12345", sess.getVid());
}
template <class Repl>
class clientSingleReplRunner: public castor::tape::threading::Thread {
public:
clientSingleReplRunner(ClientSimSingleReply<Repl> &client): m_sim(client) {}
private:
void run() {
m_sim.sessionLoop();
}
ClientSimSingleReply<Repl> & m_sim;
};
TEST(tapeServerClientInterface, VolReqVol) {
using namespace castor::tape::tapegateway;
// Create the "client" that will just reply a scripted reply
uint32_t volReq = 0xBEEF;
std::string vid = "V12345";
std::string density = "8000GC";
ClientSimSingleReply<Volume> csVol(volReq, vid, density);
struct ClientSimSingleReply<Volume>::ipPort clientAddr = csVol.getCallbackAddress();
clientSingleReplRunner<Volume> csVolRun(csVol);
csVolRun.start();
// Setup a clientInterface to talk to it
castor::tape::legacymsg::RtcpJobRqstMsgBody VDQMjob;
snprintf(VDQMjob.clientHost, CA_MAXHOSTNAMELEN+1, "%d.%d.%d.%d",
clientAddr.a, clientAddr.b, clientAddr.c, clientAddr.d);
snprintf(VDQMjob.driveUnit, CA_MAXUNMLEN+1, "T10D6116");
snprintf(VDQMjob.dgn, CA_MAXDGNLEN+1, "LIBXX");
VDQMjob.clientPort = clientAddr.port;
VDQMjob.volReqId = volReq;
// Setup an interface to it.
ClientInterface cInterf(VDQMjob);
ClientInterface::VolumeInfo volInfo;
ClientInterface::RequestReport reqRep;
ASSERT_NO_THROW(cInterf.fetchVolumeId(volInfo, reqRep));
// Cleanup
csVolRun.wait();
}
TEST(tapeServerClientInterface, VolReqNoMore) {
using namespace castor::tape::tapegateway;
// Create the "client" that will just reply a scripted reply
uint32_t volReq = 0xBEEF;
std::string vid = "V12345";
std::string density = "8000GC";
ClientSimSingleReply<NoMoreFiles> csVol(volReq, vid, density);
struct ClientSimSingleReply<NoMoreFiles>::ipPort clientAddr =
csVol.getCallbackAddress();
clientSingleReplRunner<NoMoreFiles> csVolRun(csVol);
csVolRun.start();
// Setup a clientInterface to talk to it
castor::tape::legacymsg::RtcpJobRqstMsgBody VDQMjob;
snprintf(VDQMjob.clientHost, CA_MAXHOSTNAMELEN+1, "%d.%d.%d.%d",
clientAddr.a, clientAddr.b, clientAddr.c, clientAddr.d);
snprintf(VDQMjob.driveUnit, CA_MAXUNMLEN+1, "T10D6116");
snprintf(VDQMjob.dgn, CA_MAXDGNLEN+1, "LIBXX");
VDQMjob.clientPort = clientAddr.port;
VDQMjob.volReqId = volReq;
// Setup an interface to it.
ClientInterface cInterf(VDQMjob);
ClientInterface::VolumeInfo volInfo;
ClientInterface::RequestReport reqRep;
ASSERT_THROW(cInterf.fetchVolumeId(volInfo, reqRep), ClientInterface::EndOfSession);
// Cleanup
csVolRun.wait();
}
TEST(tapeServerClientInterface, VolReqEndError) {
using namespace castor::tape::tapegateway;
// Create the "client" that will just reply a scripted reply
uint32_t volReq = 0xBEEF;
std::string vid = "V12345";
std::string density = "8000GC";
ClientSimSingleReply<EndNotificationErrorReport> csVol(volReq, vid, density);
struct ClientSimSingleReply<EndNotificationErrorReport>::ipPort clientAddr =
csVol.getCallbackAddress();
clientSingleReplRunner<EndNotificationErrorReport> csVolRun(csVol);
csVolRun.start();
// Setup a clientInterface to talk to it
castor::tape::legacymsg::RtcpJobRqstMsgBody VDQMjob;
snprintf(VDQMjob.clientHost, CA_MAXHOSTNAMELEN+1, "%d.%d.%d.%d",
clientAddr.a, clientAddr.b, clientAddr.c, clientAddr.d);
snprintf(VDQMjob.driveUnit, CA_MAXUNMLEN+1, "T10D6116");
snprintf(VDQMjob.dgn, CA_MAXDGNLEN+1, "LIBXX");
VDQMjob.clientPort = clientAddr.port;
VDQMjob.volReqId = volReq;
// Setup an interface to it.
ClientInterface cInterf(VDQMjob);
ClientInterface::VolumeInfo volInfo;
ClientInterface::RequestReport reqRep;
ASSERT_THROW(cInterf.fetchVolumeId(volInfo, reqRep), ClientInterface::EndOfSession);
// Cleanup
csVolRun.wait();
}
TEST(tapeServerClientInterface, VolReqVolReq) {
using namespace castor::tape::tapegateway;
// Create the "client" that will just reply a scripted reply
uint32_t volReq = 0xBEEF;
std::string vid = "V12345";
std::string density = "8000GC";
ClientSimSingleReply<VolumeRequest> csVol(volReq, vid, density);
struct ClientSimSingleReply<VolumeRequest>::ipPort clientAddr =
csVol.getCallbackAddress();
clientSingleReplRunner<VolumeRequest> csVolRun(csVol);
csVolRun.start();
// Setup a clientInterface to talk to it
castor::tape::legacymsg::RtcpJobRqstMsgBody VDQMjob;
snprintf(VDQMjob.clientHost, CA_MAXHOSTNAMELEN+1, "%d.%d.%d.%d",
clientAddr.a, clientAddr.b, clientAddr.c, clientAddr.d);
snprintf(VDQMjob.driveUnit, CA_MAXUNMLEN+1, "T10D6116");
snprintf(VDQMjob.dgn, CA_MAXDGNLEN+1, "LIBXX");
VDQMjob.clientPort = clientAddr.port;
VDQMjob.volReqId = volReq;
// Setup an interface to it.
ClientInterface cInterf(VDQMjob);
ClientInterface::VolumeInfo volInfo;
ClientInterface::RequestReport reqRep;
ASSERT_THROW(cInterf.fetchVolumeId(volInfo, reqRep), ClientInterface::UnexpectedResponse);
// Cleanup
csVolRun.wait();
}
TEST(tapeServerClientInterface, VolReqVolSeqBreak) {
using namespace castor::tape::tapegateway;
// Create the "client" that will just reply a scripted reply
uint32_t volReq = 0xBEEF;
std::string vid = "V12345";
std::string density = "8000GC";
ClientSimSingleReply<VolumeRequest> csVol(volReq, vid, density, true);
struct ClientSimSingleReply<VolumeRequest>::ipPort clientAddr =
csVol.getCallbackAddress();
clientSingleReplRunner<VolumeRequest> csVolRun(csVol);
csVolRun.start();
// Setup a clientInterface to talk to it
castor::tape::legacymsg::RtcpJobRqstMsgBody VDQMjob;
snprintf(VDQMjob.clientHost, CA_MAXHOSTNAMELEN+1, "%d.%d.%d.%d",
clientAddr.a, clientAddr.b, clientAddr.c, clientAddr.d);
snprintf(VDQMjob.driveUnit, CA_MAXUNMLEN+1, "T10D6116");
snprintf(VDQMjob.dgn, CA_MAXDGNLEN+1, "LIBXX");
VDQMjob.clientPort = clientAddr.port;
VDQMjob.volReqId = volReq;
// Setup an interface to it.
ClientInterface cInterf(VDQMjob);
ClientInterface::VolumeInfo volInfo;
ClientInterface::RequestReport reqRep;
ASSERT_THROW(cInterf.fetchVolumeId(volInfo, reqRep), ClientInterface::UnexpectedResponse);
// Cleanup
csVolRun.wait();
}
TEST(tapeServerClientInterface, EndSessionNotifAck) {
using namespace castor::tape::tapegateway;
// Create the "client" that will just reply a scripted reply
uint32_t volReq = 0xBEEF;
std::string vid = "V12345";
std::string density = "8000GC";
ClientSimSingleReply<NotificationAcknowledge> csVol(volReq, vid, density);
struct ClientSimSingleReply<NotificationAcknowledge>::ipPort clientAddr =
csVol.getCallbackAddress();
clientSingleReplRunner<NotificationAcknowledge> csVolRun(csVol);
csVolRun.start();
// Setup a clientInterface to talk to it
castor::tape::legacymsg::RtcpJobRqstMsgBody VDQMjob;
snprintf(VDQMjob.clientHost, CA_MAXHOSTNAMELEN+1, "%d.%d.%d.%d",
clientAddr.a, clientAddr.b, clientAddr.c, clientAddr.d);
snprintf(VDQMjob.driveUnit, CA_MAXUNMLEN+1, "T10D6116");
snprintf(VDQMjob.dgn, CA_MAXDGNLEN+1, "LIBXX");
VDQMjob.clientPort = clientAddr.port;
VDQMjob.volReqId = volReq;
// Setup an interface to it.
ClientInterface cInterf(VDQMjob);
ClientInterface::VolumeInfo volInfo;
ClientInterface::RequestReport reqRep;
ASSERT_NO_THROW(cInterf.reportEndOfSession(reqRep));
// Cleanup
csVolRun.wait();
}
TEST(tapeServerClientInterface, EndSessionNotifAckSeqBreak) {
using namespace castor::tape::tapegateway;
// Create the "client" that will just reply a scripted reply
uint32_t volReq = 0xBEEF;
std::string vid = "V12345";
std::string density = "8000GC";
ClientSimSingleReply<NotificationAcknowledge> csVol(volReq, vid, density, true);
struct ClientSimSingleReply<NotificationAcknowledge>::ipPort clientAddr =
csVol.getCallbackAddress();
clientSingleReplRunner<NotificationAcknowledge> csVolRun(csVol);
csVolRun.start();
// Setup a clientInterface to talk to it
castor::tape::legacymsg::RtcpJobRqstMsgBody VDQMjob;
snprintf(VDQMjob.clientHost, CA_MAXHOSTNAMELEN+1, "%d.%d.%d.%d",
clientAddr.a, clientAddr.b, clientAddr.c, clientAddr.d);
snprintf(VDQMjob.driveUnit, CA_MAXUNMLEN+1, "T10D6116");
snprintf(VDQMjob.dgn, CA_MAXDGNLEN+1, "LIBXX");
VDQMjob.clientPort = clientAddr.port;
VDQMjob.volReqId = volReq;
// Setup an interface to it.
ClientInterface cInterf(VDQMjob);
ClientInterface::VolumeInfo volInfo;
ClientInterface::RequestReport reqRep;
ASSERT_THROW(cInterf.reportEndOfSession(reqRep), ClientInterface::UnexpectedResponse);
// Cleanup
csVolRun.wait();
}
TEST(tapeServerClientInterface, EndSessionVolReq) {
using namespace castor::tape::tapegateway;
// Create the "client" that will just reply a scripted reply
uint32_t volReq = 0xBEEF;
std::string vid = "V12345";
std::string density = "8000GC";
ClientSimSingleReply<VolumeRequest> csVol(volReq, vid, density);
struct ClientSimSingleReply<VolumeRequest>::ipPort clientAddr =
csVol.getCallbackAddress();
clientSingleReplRunner<VolumeRequest> csVolRun(csVol);
csVolRun.start();
// Setup a clientInterface to talk to it
castor::tape::legacymsg::RtcpJobRqstMsgBody VDQMjob;
snprintf(VDQMjob.clientHost, CA_MAXHOSTNAMELEN+1, "%d.%d.%d.%d",
clientAddr.a, clientAddr.b, clientAddr.c, clientAddr.d);
snprintf(VDQMjob.driveUnit, CA_MAXUNMLEN+1, "T10D6116");
snprintf(VDQMjob.dgn, CA_MAXDGNLEN+1, "LIBXX");
VDQMjob.clientPort = clientAddr.port;
VDQMjob.volReqId = volReq;
// Setup an interface to it.
ClientInterface cInterf(VDQMjob);
ClientInterface::VolumeInfo volInfo;
ClientInterface::RequestReport reqRep;
ASSERT_THROW(cInterf.reportEndOfSession(reqRep), ClientInterface::UnexpectedResponse);
// Cleanup
csVolRun.wait();
}
TEST(tapeServerClientInterface, EndSessionErrorNotifAck) {
using namespace castor::tape::tapegateway;
// Create the "client" that will just reply a scripted reply
uint32_t volReq = 0xBEEF;
std::string vid = "V12345";
std::string density = "8000GC";
ClientSimSingleReply<NotificationAcknowledge> csVol(volReq, vid, density);
struct ClientSimSingleReply<NotificationAcknowledge>::ipPort clientAddr =
csVol.getCallbackAddress();
clientSingleReplRunner<NotificationAcknowledge> csVolRun(csVol);
csVolRun.start();
// Setup a clientInterface to talk to it
castor::tape::legacymsg::RtcpJobRqstMsgBody VDQMjob;
snprintf(VDQMjob.clientHost, CA_MAXHOSTNAMELEN+1, "%d.%d.%d.%d",
clientAddr.a, clientAddr.b, clientAddr.c, clientAddr.d);
snprintf(VDQMjob.driveUnit, CA_MAXUNMLEN+1, "T10D6116");
snprintf(VDQMjob.dgn, CA_MAXDGNLEN+1, "LIBXX");
VDQMjob.clientPort = clientAddr.port;
VDQMjob.volReqId = volReq;
// Setup an interface to it.
ClientInterface cInterf(VDQMjob);
ClientInterface::VolumeInfo volInfo;
ClientInterface::RequestReport reqRep;
ASSERT_NO_THROW(cInterf.reportEndOfSessionWithError("SNAFU!", SEINTERNAL, reqRep));
// Cleanup
csVolRun.wait();
}
TEST(tapeServerClientInterface, EndSessionErrorVolReq) {
using namespace castor::tape::tapegateway;
// Create the "client" that will just reply a scripted reply
uint32_t volReq = 0xBEEF;
std::string vid = "V12345";
std::string density = "8000GC";
ClientSimSingleReply<VolumeRequest> csVol(volReq, vid, density);
struct ClientSimSingleReply<VolumeRequest>::ipPort clientAddr =
csVol.getCallbackAddress();
clientSingleReplRunner<VolumeRequest> csVolRun(csVol);
csVolRun.start();
// Setup a clientInterface to talk to it
castor::tape::legacymsg::RtcpJobRqstMsgBody VDQMjob;
snprintf(VDQMjob.clientHost, CA_MAXHOSTNAMELEN+1, "%d.%d.%d.%d",
clientAddr.a, clientAddr.b, clientAddr.c, clientAddr.d);
snprintf(VDQMjob.driveUnit, CA_MAXUNMLEN+1, "T10D6116");
snprintf(VDQMjob.dgn, CA_MAXDGNLEN+1, "LIBXX");
VDQMjob.clientPort = clientAddr.port;
VDQMjob.volReqId = volReq;
// Setup an interface to it.
ClientInterface cInterf(VDQMjob);
ClientInterface::VolumeInfo volInfo;
ClientInterface::RequestReport reqRep;
ASSERT_THROW(cInterf.reportEndOfSessionWithError("SNAFU!", SEINTERNAL, reqRep),
ClientInterface::UnexpectedResponse);
// Cleanup
csVolRun.wait();
}
TEST(tapeServerClientInterface, EndSessionErrorNotifAckSeqBreak) {
using namespace castor::tape::tapegateway;
// Create the "client" that will just reply a scripted reply
uint32_t volReq = 0xBEEF;
std::string vid = "V12345";
std::string density = "8000GC";
ClientSimSingleReply<NotificationAcknowledge> csVol(volReq, vid, density, true);
struct ClientSimSingleReply<NotificationAcknowledge>::ipPort clientAddr =
csVol.getCallbackAddress();
clientSingleReplRunner<NotificationAcknowledge> csVolRun(csVol);
csVolRun.start();
// Setup a clientInterface to talk to it
castor::tape::legacymsg::RtcpJobRqstMsgBody VDQMjob;
snprintf(VDQMjob.clientHost, CA_MAXHOSTNAMELEN+1, "%d.%d.%d.%d",
clientAddr.a, clientAddr.b, clientAddr.c, clientAddr.d);
snprintf(VDQMjob.driveUnit, CA_MAXUNMLEN+1, "T10D6116");
snprintf(VDQMjob.dgn, CA_MAXDGNLEN+1, "LIBXX");
VDQMjob.clientPort = clientAddr.port;
VDQMjob.volReqId = volReq;
// Setup an interface to it.
ClientInterface cInterf(VDQMjob);
ClientInterface::VolumeInfo volInfo;
ClientInterface::RequestReport reqRep;
ASSERT_THROW(cInterf.reportEndOfSessionWithError("SNAFU!", SEINTERNAL, reqRep),
ClientInterface::UnexpectedResponse);
// Cleanup
csVolRun.wait();
}
TEST(tapeServerClientInterface, FilesToMigrateReqFilesToMigrate) {
using namespace castor::tape::tapegateway;
// Create the "client" that will just reply a scripted reply
uint32_t volReq = 0xBEEF;
std::string vid = "V12345";
std::string density = "8000GC";
ClientSimSingleReply<FilesToMigrateList> csVol(volReq, vid, density);
struct ClientSimSingleReply<FilesToMigrateList>::ipPort clientAddr =
csVol.getCallbackAddress();
clientSingleReplRunner<FilesToMigrateList> csVolRun(csVol);
csVolRun.start();
// Setup a clientInterface to talk to it
castor::tape::legacymsg::RtcpJobRqstMsgBody VDQMjob;
snprintf(VDQMjob.clientHost, CA_MAXHOSTNAMELEN+1, "%d.%d.%d.%d",
clientAddr.a, clientAddr.b, clientAddr.c, clientAddr.d);
snprintf(VDQMjob.driveUnit, CA_MAXUNMLEN+1, "T10D6116");
snprintf(VDQMjob.dgn, CA_MAXDGNLEN+1, "LIBXX");
VDQMjob.clientPort = clientAddr.port;
VDQMjob.volReqId = volReq;
// Setup an interface to it.
ClientInterface cInterf(VDQMjob);
ClientInterface::VolumeInfo volInfo;
ClientInterface::RequestReport reqRep;
// We are responsible for the freeing of the result: chuck it into an auto_ptr.
std::auto_ptr<FilesToMigrateList> resp;
ASSERT_NO_THROW(resp.reset(cInterf.getFilesToMigrate(10, 10, reqRep)));
ASSERT_NE((FilesToMigrateList*)NULL, resp.get());
// Cleanup
csVolRun.wait();
}
TEST(tapeServerClientInterface, FilesToMigrateReqNoMore) {
using namespace castor::tape::tapegateway;
// Create the "client" that will just reply a scripted reply
uint32_t volReq = 0xBEEF;
std::string vid = "V12345";
std::string density = "8000GC";
ClientSimSingleReply<NoMoreFiles> csVol(volReq, vid, density);
struct ClientSimSingleReply<NoMoreFiles>::ipPort clientAddr =
csVol.getCallbackAddress();
clientSingleReplRunner<NoMoreFiles> csVolRun(csVol);
csVolRun.start();
// Setup a clientInterface to talk to it
castor::tape::legacymsg::RtcpJobRqstMsgBody VDQMjob;
snprintf(VDQMjob.clientHost, CA_MAXHOSTNAMELEN+1, "%d.%d.%d.%d",
clientAddr.a, clientAddr.b, clientAddr.c, clientAddr.d);
snprintf(VDQMjob.driveUnit, CA_MAXUNMLEN+1, "T10D6116");
snprintf(VDQMjob.dgn, CA_MAXDGNLEN+1, "LIBXX");
VDQMjob.clientPort = clientAddr.port;
VDQMjob.volReqId = volReq;
// Setup an interface to it.
ClientInterface cInterf(VDQMjob);
ClientInterface::VolumeInfo volInfo;
ClientInterface::RequestReport reqRep;
// We are responsible for the freeing of the result: chuck it into an auto_ptr.
std::auto_ptr<FilesToMigrateList> resp;
ASSERT_NO_THROW(resp.reset