diff --git a/test/unittest/castor/tape/tapebridge/BridgeProtocolEngineTest.hpp b/test/unittest/castor/tape/tapebridge/BridgeProtocolEngineTest.hpp
index faad91e4cc65ef1b364583bbeb25bccd24e36b4a..d916985a559c355096f1fa3a871a168ba302c4c9 100644
--- a/test/unittest/castor/tape/tapebridge/BridgeProtocolEngineTest.hpp
+++ b/test/unittest/castor/tape/tapebridge/BridgeProtocolEngineTest.hpp
@@ -26,12 +26,14 @@
 #define TEST_UNITTEST_CASTOR_TAPE_TAPEBRIDGE_BRIDGEPROTOCOLENGINETEST_HPP 1
 
 #include "castor/Constants.hpp"
+#include "castor/Services.hpp"
 #include "castor/tape/legacymsg/CommonMarshal.hpp"
 #include "castor/tape/legacymsg/RtcpMarshal.hpp"
 #include "castor/tape/net/net.hpp"
 #include "castor/tape/tapebridge/BridgeProtocolEngine.hpp"
 #include "castor/tape/tapebridge/ClientProxy.hpp"
 #include "castor/tape/tapebridge/ClientAddressLocal.hpp"
+#include "castor/tape/tapebridge/LegacyTxRx.hpp"
 #include "castor/tape/tapegateway/EndNotificationErrorReport.hpp"
 #include "castor/tape/tapegateway/FilesToMigrateList.hpp"
 #include "castor/tape/tapegateway/FilesToMigrateListRequest.hpp"
@@ -86,6 +88,125 @@ private:
    */
   const char *const m_bridgeListenSockPath;
 
+  /**
+   * The local-domain socket that the client would listen on for incoming
+   * connections from the tapegatewayd daemon.
+   */
+  int m_clientListenSock;
+
+  /**
+   * The local-domain socket that the BridgeProtocolEngine will listen
+   * for incoming connections from the rtcpd daemon.
+   */
+  int m_bridgeListenSock;
+
+  /**
+   * The rtcpd daemon side of the initial rtcpd-connection with the tapebridged
+   * daemon.
+   */
+  int m_initialRtcpdSockRtcpdSide;
+
+  /**
+   * The tapebridged daemon side of the initial rtcpd-connection with the
+   * tapebridged daemon.
+   */
+  int m_initialRtcpdSockBridgeSide;
+
+  /**
+   * The rtcpd daemon side of the IO control connection.
+   */
+  int m_ioControlConnectionSock;
+
+  /**
+   * The unique universal-identifier to be used for logging.
+   */
+  const Cuuid_t &m_cuuid;
+
+  /**
+   * The volume identifier of the tape to be mounted.
+   */
+  const std::string m_volumeVid;
+
+  /**
+   * The density of the tape to be mounted.
+   */
+  const std::string m_volumeDensity;
+
+  /**
+   * The label of the tape to be mounted.
+   */
+  const std::string m_volumeLabel;
+
+  /**
+   * The device-group name of the tape to be mounted.
+   */
+  const std::string m_volumeDgn;
+
+  /**
+   * The name of the drive unit.
+   */
+  const std::string m_driveUnit;
+
+  /**
+   * The job-request structure sent from the vdqmd daemon.
+   */
+  legacymsg::RtcpJobRqstMsgBody m_jobRequest;
+
+  /**
+   * The volume message from the client of the tapebridged demon.
+   */
+  tapegateway::Volume m_volume;
+
+  /**
+   * The counter used to generate tape-bridge transaction ids.
+   */
+  Counter<uint64_t> m_tapebridgeTransactionCounter;
+
+  /**
+   * The tapebridged daemon configuration parameters that specifiy the
+   * the bulk requests the daemon shall send to the tapegatewayd daemon.
+   */
+  TestingBulkRequestConfigParams m_bulkRequestConfigParams;
+
+  /**
+   * The tapebridged daemon configuration parameters that specifiy the
+   * the tape-drive flush-logic.
+   */
+  TestingTapeFlushConfigParams m_tapeFlushConfigParams;
+
+  /**
+   * The file-closer to be ised by the BridgeProtocolEngine.
+   */
+  TraceableSystemFileCloser m_fileCloser;
+
+  /**
+   * The mount transaction id.
+   */
+  const uint32_t m_mountTransactionId;
+
+  /**
+   * The timeout in seconds for network operations.
+   */
+  const int m_netTimeout;
+
+  /**
+   * The address of the client of the tapebridged daemon.
+   */
+  ClientAddressLocal m_clientAddress;
+
+  /**
+   * The proxy-object representing the client of the tapebridged daemon.
+   */
+  ClientProxy m_clientProxy;
+
+  /**
+   * The number of files on the destination tape at the beginning of the mount.
+   */
+  const uint32_t m_nbFilesOnDestinationTape;
+
+  /**
+   * A castor::tape::utils::BoolFunctor that always returns false.
+   */
   class AlwaysFalseBoolFunctor: public utils::BoolFunctor {
   public:
 
@@ -98,6 +219,28 @@ private:
      }
   };
 
+  /**
+   * Functor that returns true if the tapebridged daemon should stop
+   * gracefully.
+   */
+  AlwaysFalseBoolFunctor m_stoppingGracefully;
+
+  /**
+   * Pointer to the BridgeProtocolEngine.
+   */
+  TestingBridgeProtocolEngine *m_engine;
+
+  /**
+   * The id of the mount or volume request.
+   */
+  const uint32_t m_volReqId;
+
+  /**
+   * The list of thread with which the main thread should join with when
+   * tearing down a test.
+   */
+  std::list<pthread_t> m_threadsToJoinWithAtTearDown;
+
   /**
    * Creates a new ClientProxy object converting any thrown exceptions to a
    * std::exception.
@@ -129,96 +272,214 @@ private:
     }
   }
 
+  struct StartRtcpdSessionThreadParams {
+    TestingBridgeProtocolEngine *inEngine;
+    bool                        outAnErrorOccurred;
+    std::ostringstream          outErrorStream;
+
+    StartRtcpdSessionThreadParams():
+      inEngine(NULL),
+      outAnErrorOccurred(false) {
+      // Do nothing
+    }
+  };
+
+  static void* runStartRtcpdSessionThread(void *arg) {
+    StartRtcpdSessionThreadParams *const threadParams =
+      (StartRtcpdSessionThreadParams*)arg;
+
+    try {
+      if(NULL == threadParams) {
+        test_exception te("Pointer to the thread-parameters is NULL");
+        throw te;
+      }
+
+      if(NULL == threadParams->inEngine) {
+        test_exception te("Pointer to the bridge protocol-engine is NULL");
+        throw te;
+      }
+
+      threadParams->inEngine->run();
+    } catch(castor::exception::Exception &ce) {
+      threadParams->outAnErrorOccurred = true;
+      threadParams->outErrorStream <<
+        "ERROR"
+        ": " << __FUNCTION__ <<
+        ": Caught a castor::exception::Exception"
+        ": " << ce.getMessage().str() << std::endl;
+    } catch(std::exception &se) {
+      threadParams->outAnErrorOccurred = true;
+      threadParams->outErrorStream <<
+        "ERROR"
+        ": " << __FUNCTION__ <<
+        ": Caught an std::exception"
+        ": " << se.what() << std::endl;
+    } catch(...) {
+      threadParams->outAnErrorOccurred = true;
+      threadParams->outErrorStream <<
+        "ERROR"
+        ": " << __FUNCTION__ <<
+        ": Caught an unknown exception";
+    }
+
+    try {
+      delete castor::BaseObject::services();
+    } catch(...) {
+      // Ignore any exception
+    }
+
+    return arg;
+  }
+
 public:
 
+  /**
+   * Constructor.
+   */
   BridgeProtocolEngineTest():
     m_clientListenSockPath("/tmp/clientListenSockForBridgeProtocolEngineTest"),
-    m_bridgeListenSockPath("/tmp/brigdeListenSockForBridgeProtocolEngineTest") {
+    m_bridgeListenSockPath("/tmp/brigdeListenSockForBridgeProtocolEngineTest"),
+    m_cuuid(nullCuuid),
+    m_volumeVid("vid"),
+    m_volumeDensity("density"),
+    m_volumeLabel("label"),
+    m_volumeDgn("dgn"),
+    m_driveUnit("unit"),
+    m_tapebridgeTransactionCounter(0),
+    m_mountTransactionId(5678),
+    m_netTimeout(1),
+    m_clientAddress(m_clientListenSockPath),
+    m_clientProxy(
+      m_cuuid,
+      m_mountTransactionId,
+      m_netTimeout,
+      m_clientAddress,
+      m_volumeDgn,
+      m_driveUnit),
+    m_nbFilesOnDestinationTape(2),
+    m_volReqId(m_mountTransactionId) {
     // Do nothing
   }
 
   void setUp() {
+    // Make sure the local-domain socket-files are deleted
     unlink(m_clientListenSockPath);
     unlink(m_bridgeListenSockPath);
+
+    // Create the socket on which the client would listen for incoming
+    // connections from the BridgeProtocolEngine
+    m_clientListenSock =
+      unittest::createLocalListenSocket(m_clientListenSockPath);
+
+    // Create the socket on which the BridgeProtocolEngine will listen for
+    // incoming connections from the rtcpd daemon
+    m_bridgeListenSock =
+      unittest::createLocalListenSocket(m_bridgeListenSockPath);
+
+    // Create the initial rtcpd-connection using socketpair()
+    int initialRtcpdSockPair[2] = {-1, -1};
+    socketpair(PF_LOCAL, SOCK_STREAM, 0, initialRtcpdSockPair);
+    m_initialRtcpdSockRtcpdSide  = initialRtcpdSockPair[0];
+    m_initialRtcpdSockBridgeSide = initialRtcpdSockPair[1];
+
+    // Create a socket for the disk/tape I/O control-connection
+    m_ioControlConnectionSock = socket(PF_LOCAL, SOCK_STREAM, 0);
+
+    // Initialise the job-request structure
+    m_jobRequest.volReqId   = m_volReqId;
+    m_jobRequest.clientPort = 0;
+    m_jobRequest.clientEuid = 0;
+    m_jobRequest.clientEgid = 0;
+    memset(m_jobRequest.clientHost, '\0', sizeof(m_jobRequest.clientHost));
+    strncpy(m_jobRequest.clientHost, "clientHost",
+      sizeof(m_jobRequest.clientHost) - 1);
+    memset(m_jobRequest.dgn, '\0', sizeof(m_jobRequest.dgn));
+    strncpy(m_jobRequest.dgn, m_volumeDgn.c_str(),
+      sizeof(m_jobRequest.dgn) - 1);
+    memset(m_jobRequest.driveUnit, '\0', sizeof(m_jobRequest.driveUnit));
+    strncpy(m_jobRequest.driveUnit, m_driveUnit.c_str(),
+      sizeof(m_jobRequest.driveUnit) - 1);
+    memset(m_jobRequest.clientUserName, '\0',
+      sizeof(m_jobRequest.clientUserName));
+    strncpy(m_jobRequest.clientUserName, "user",
+      sizeof(m_jobRequest.clientUserName) - 1);
+
+    // Initialise the volume message for migrations
+    m_volume.setVid(m_volumeVid);
+    m_volume.setDensity(m_volumeDensity);
+    m_volume.setLabel(m_volumeLabel);
+    m_volume.setMode(tapegateway::WRITE);
+    m_volume.setClientType(tapegateway::TAPE_GATEWAY);
+
+    // Reset the tapebridgeTransactionCounter
+    m_tapebridgeTransactionCounter.reset(0);
+
+    // Initialise the BulkRequestConfigParams
+    m_bulkRequestConfigParams.setBulkRequestMigrationMaxBytes(1,
+      ConfigParamSource::UNDEFINED);
+    m_bulkRequestConfigParams.setBulkRequestMigrationMaxFiles(2,
+      ConfigParamSource::UNDEFINED);
+    m_bulkRequestConfigParams.setBulkRequestRecallMaxBytes(3,
+      ConfigParamSource::UNDEFINED);
+    m_bulkRequestConfigParams.setBulkRequestRecallMaxFiles(4,
+      ConfigParamSource::UNDEFINED);
+
+    // Initialise the TapeFlushConfigParams
+    m_tapeFlushConfigParams.setTapeFlushMode(TAPEBRIDGE_N_FLUSHES_PER_FILE,
+      ConfigParamSource::UNDEFINED);
+    m_tapeFlushConfigParams.setMaxBytesBeforeFlush(1,
+      ConfigParamSource::UNDEFINED);
+    m_tapeFlushConfigParams.setMaxFilesBeforeFlush(1,
+      ConfigParamSource::UNDEFINED);
+
+    // Create the BridgeProtocolEngine
+    const bool logPeerOfCallbackConnectionsFromRtcpd = false;
+    const bool checkRtcpdIsConnectingFromLocalHost = false;
+    m_engine = newTestingBridgeProtocolEngine(
+      m_fileCloser,
+      m_bulkRequestConfigParams,
+      m_tapeFlushConfigParams,
+      m_cuuid,
+      m_bridgeListenSock,
+      m_initialRtcpdSockBridgeSide,
+      m_jobRequest,
+      m_volume,
+      m_nbFilesOnDestinationTape,
+      m_stoppingGracefully,
+      m_tapebridgeTransactionCounter,
+      logPeerOfCallbackConnectionsFromRtcpd,
+      checkRtcpdIsConnectingFromLocalHost,
+      m_clientProxy);
+
+    // Clear the list of threads to join with at tearDown
+    m_threadsToJoinWithAtTearDown.clear();
   }
 
   void tearDown() {
-    unlink(m_clientListenSockPath);
-    unlink(m_bridgeListenSockPath);
-  }
+    // Join with any thread created during the test that has not yet been
+    // joined with
+    for(std::list<pthread_t>::const_iterator itor =
+      m_threadsToJoinWithAtTearDown.begin();
+      itor != m_threadsToJoinWithAtTearDown.end();
+      itor++) {
+      pthread_join(*itor, NULL);
+    }
 
-  void testConstructor() {
-    TraceableDummyFileCloser fileCloser;
-    const int initialRtcpdSock = 12;
+    // Delete the BridgeProtocolEngine
+    delete m_engine;
 
-    {
-      TestingBulkRequestConfigParams      bulkRequestConfigParams;
-      TestingTapeFlushConfigParams        tapeFlushConfigParams;
-      const Cuuid_t                       &cuuid = nullCuuid;
-      const int                           rtcpdListenSock  = 11;
-      const uint32_t                      mountTransactionId = 12;
-      const legacymsg::RtcpJobRqstMsgBody jobRequest = {
-        mountTransactionId, // volReqId
-        0, // clientPort;
-        0, // clientEuid;
-        0, // clientEgid;
-        "clientHost", // clientHost
-        "dgn", // dgn
-        "unit", // driveUnit
-        "user", // clientUserName
-      };
-      const tapegateway::Volume volume;
-      const uint32_t            nbFilesOnDestinationTape = 0;
-      AlwaysFalseBoolFunctor    stoppingGracefully;
-      Counter<uint64_t>         tapebridgeTransactionCounter(0);
-      const bool                logPeerOfCallbackConnectionsFromRtcpd = false;
-      const bool                checkRtcpdIsConnectingFromLocalHost = false;
-      DummyClientProxy          clientProxy;
-      std::auto_ptr<TestingBridgeProtocolEngine> smartEngine;
-
-      bulkRequestConfigParams.setBulkRequestMigrationMaxBytes(1,
-        ConfigParamSource::UNDEFINED);
-      bulkRequestConfigParams.setBulkRequestMigrationMaxFiles(1,
-        ConfigParamSource::UNDEFINED);
-      bulkRequestConfigParams.setBulkRequestRecallMaxBytes(1,
-        ConfigParamSource::UNDEFINED);
-      bulkRequestConfigParams.setBulkRequestRecallMaxFiles(1,
-        ConfigParamSource::UNDEFINED);
-
-      tapeFlushConfigParams.setTapeFlushMode(TAPEBRIDGE_N_FLUSHES_PER_FILE,
-        ConfigParamSource::UNDEFINED);
-      tapeFlushConfigParams.setMaxBytesBeforeFlush(1,
-        ConfigParamSource::UNDEFINED);
-      tapeFlushConfigParams.setMaxFilesBeforeFlush(1,
-        ConfigParamSource::UNDEFINED);
+    // Clear the TraceableSystemFileCloser
+    m_fileCloser.m_closedFds.clear();
 
-      CPPUNIT_ASSERT_NO_THROW_MESSAGE(
-        "Check newTestingBridgeProtocolEngine()",
-        smartEngine.reset(newTestingBridgeProtocolEngine(
-          fileCloser,
-          bulkRequestConfigParams,
-          tapeFlushConfigParams,
-          cuuid,
-          rtcpdListenSock,
-          initialRtcpdSock,
-          jobRequest,
-          volume,
-          nbFilesOnDestinationTape,
-          stoppingGracefully,
-          tapebridgeTransactionCounter,
-          logPeerOfCallbackConnectionsFromRtcpd,
-          checkRtcpdIsConnectingFromLocalHost,
-          clientProxy)));
-    }
+    // Close all sockets accept those owned by the BridgeProtocolEngine
+    close(m_ioControlConnectionSock);
+    close(m_initialRtcpdSockRtcpdSide);
+    close(m_bridgeListenSock);
+    close(m_clientListenSock);
 
-    CPPUNIT_ASSERT_EQUAL_MESSAGE(
-      "Check that only one socket has been closed",
-      (std::vector<int>::size_type)1,
-      fileCloser.m_closedFds.size());
-    CPPUNIT_ASSERT_EQUAL_MESSAGE(
-      "Check that initialRtcpdSock was the socket that was closed",
-      initialRtcpdSock,
-      fileCloser.m_closedFds.front());
+    // Make sure the local-domain socket-files are deleted
+    unlink(m_clientListenSockPath);
+    unlink(m_bridgeListenSockPath);
   }
 
   /**
@@ -272,787 +533,402 @@ public:
     return engine;
   }
 
+  /**
+   * This unit-test checks that the BridgeProtocolEngine correctly handles the
+   * shutdown logic of the legacy RTCOPY-protocol.
+   */
   void testShutdownOfProtocolUsingLocalDomain() {
-    // Create the socket on which the client would listen for incoming
-    // connections from the BridgeProtocolEngine
-    utils::SmartFd smartClientListenSock;
-    CPPUNIT_ASSERT_NO_THROW_MESSAGE(
-      "Create local client listen socket",
-       smartClientListenSock.reset(
-        unittest::createLocalListenSocket(m_clientListenSockPath)));
-
-    // Create the initial rtcpd-connection using socketpair()
-    int initialRtcpdSockPair[2] = {-1, -1};
     CPPUNIT_ASSERT_EQUAL_MESSAGE(
-      "Check socket pair for the intital rtcpd-connection has been created",
+      "Check there are no I/O control-connections",
       0,
-      socketpair(PF_LOCAL, SOCK_STREAM, 0, initialRtcpdSockPair));
-    utils::SmartFd smartInitialRtcpdSockRtcpdSide(initialRtcpdSockPair[0]);
-    utils::SmartFd smartInitialRtcpdSockBridgeSide(initialRtcpdSockPair[1]);
-    const int initialRtcpdSockBridgeSide =
-      smartInitialRtcpdSockBridgeSide.get();
-
-    // Create the socket on which the BridgeProtocolEngine will listen for
-    // incoming connections from the rtcpd daemon
-    utils::SmartFd smartBridgeListenSock;
-    CPPUNIT_ASSERT_NO_THROW_MESSAGE(
-      "Create local rtcpd listen socket",
-       smartBridgeListenSock.reset(
-        unittest::createLocalListenSocket(m_bridgeListenSockPath)));
-
-    // Create a socket for the disk/tape I/O control-connection
-    utils::SmartFd
-      smartIoControlConnectionSock(socket(PF_LOCAL, SOCK_STREAM, 0));
-    CPPUNIT_ASSERT_MESSAGE(
-      "Create a socket for the first disk/tape I/O control-connection",
-      -1 != smartIoControlConnectionSock.get());
+      m_engine->getNbDiskTapeIOControlConns());
+    CPPUNIT_ASSERT_EQUAL_MESSAGE(
+      "Check no RTCP_ENDOF_REQ messages have been received",
+      (uint32_t)0,
+      m_engine->getNbReceivedENDOF_REQs());
+    CPPUNIT_ASSERT_EQUAL_MESSAGE(
+      "Check the session with the rtcpd daemon is not being shutdown",
+      false,
+      m_engine->shuttingDownRtcpdSession());
+    CPPUNIT_ASSERT_EQUAL_MESSAGE(
+      "Check rtcpd session has not finished",
+      false,
+      m_engine->sessionWithRtcpdIsFinished());
+    CPPUNIT_ASSERT_EQUAL_MESSAGE(
+      "Check BridgeProtocolEngine should continue processing sockets",
+      true,
+      m_engine->continueProcessingSocks());
 
-    TraceableSystemFileCloser fileCloser;
+    // Check the BridgeProtocolEngine can handle the case of no select events
     {
-      TestingBulkRequestConfigParams      bulkRequestConfigParams;
-      TestingTapeFlushConfigParams        tapeFlushConfigParams;
-      const Cuuid_t                       &cuuid = nullCuuid;
-      const legacymsg::RtcpJobRqstMsgBody jobRequest = {
-        0, // volReqId
-        0, // clientPort;
-        0, // clientEuid;
-        0, // clientEgid;
-        "clientHost", // clientHost
-        "dgn", // dgn
-        "unit", // driveUnit
-        "user", // clientUserName
-      };
-
-      tapegateway::Volume        volume;
-      const uint32_t             nbFilesOnDestinationTape = 2;
-      AlwaysFalseBoolFunctor     stoppingGracefully;
-      Counter<uint64_t>          tapebridgeTransactionCounter(0);
-      const bool                 logPeerOfCallbackConnectionsFromRtcpd = false;
-      const bool                 checkRtcpdIsConnectingFromLocalHost = false;
-      const uint32_t             mountTransactionId = 1;
-      const int                  netTimeout = 1;
-      ClientAddressLocal         clientAddress(m_clientListenSockPath);
-      const std::string          dgn("dgn");
-      const std::string          driveUnit("unit");
-      std::auto_ptr<ClientProxy> smartClientProxy;
-      std::auto_ptr<TestingBridgeProtocolEngine> smartEngine;
-
-      bulkRequestConfigParams.setBulkRequestMigrationMaxBytes(1,
-        ConfigParamSource::UNDEFINED);
-      bulkRequestConfigParams.setBulkRequestMigrationMaxFiles(2,
-        ConfigParamSource::UNDEFINED);
-      bulkRequestConfigParams.setBulkRequestRecallMaxBytes(3,
-        ConfigParamSource::UNDEFINED);
-      bulkRequestConfigParams.setBulkRequestRecallMaxFiles(4,
-        ConfigParamSource::UNDEFINED);
-
-      tapeFlushConfigParams.setTapeFlushMode(TAPEBRIDGE_N_FLUSHES_PER_FILE,
-        ConfigParamSource::UNDEFINED);
-      tapeFlushConfigParams.setMaxBytesBeforeFlush(1,
-        ConfigParamSource::UNDEFINED);
-      tapeFlushConfigParams.setMaxFilesBeforeFlush(1,
-        ConfigParamSource::UNDEFINED);
-
-      // Create a client proxy
-      CPPUNIT_ASSERT_NO_THROW_MESSAGE(
-        "Check newClientProxy()",
-        smartClientProxy.reset(newClientProxy(
-          cuuid,
-          mountTransactionId,
-          netTimeout,
-          clientAddress,
-          dgn,
-          driveUnit)));
-
-      // Create a BridgeProtocolEngine
-      volume.setVid("vid");
-      volume.setDensity("density");
-      volume.setLabel("label");
-      volume.setMode(tapegateway::WRITE); // Test migration-logic
-      volume.setClientType(tapegateway::TAPE_GATEWAY);
+      struct timeval selectTimeout = {0, 0};
       CPPUNIT_ASSERT_NO_THROW_MESSAGE(
-        "Check newTestingBridgeProtocolEngine()",
-        smartEngine.reset(newTestingBridgeProtocolEngine(
-          fileCloser,
-          bulkRequestConfigParams,
-          tapeFlushConfigParams,
-          cuuid,
-          smartBridgeListenSock.get(),
-          initialRtcpdSockBridgeSide,
-          jobRequest,
-          volume,
-          nbFilesOnDestinationTape,
-          stoppingGracefully,
-          tapebridgeTransactionCounter,
-          logPeerOfCallbackConnectionsFromRtcpd,
-          checkRtcpdIsConnectingFromLocalHost,
-          *smartClientProxy.get())));
-      CPPUNIT_ASSERT_EQUAL_MESSAGE(
-        "Check there are no I/O control-connections",
-        0,
-        smartEngine->getNbDiskTapeIOControlConns());
-      CPPUNIT_ASSERT_EQUAL_MESSAGE(
-        "Check no RTCP_ENDOF_REQ messages have been received",
-        (uint32_t)0,
-        smartEngine->getNbReceivedENDOF_REQs());
-      CPPUNIT_ASSERT_EQUAL_MESSAGE(
-        "Check the session with the rtcpd daemon is not being shutdown",
-        false,
-        smartEngine->shuttingDownRtcpdSession());
-      CPPUNIT_ASSERT_EQUAL_MESSAGE(
-        "Check rtcpd session has not finished",
-        false,
-        smartEngine->sessionWithRtcpdIsFinished());
-      CPPUNIT_ASSERT_EQUAL_MESSAGE(
-        "Check BridgeProtocolEngine should continue processing sockets",
-        true,
-        smartEngine->continueProcessingSocks());
-
-      // Check the BridgeProtocolEngine can handle the case of no select events
-      {
-        struct timeval selectTimeout = {0, 0};
-        CPPUNIT_ASSERT_NO_THROW_MESSAGE(
-          "Check handling of no select events",
-          smartEngine->handleSelectEvents(selectTimeout));
-      }
-      CPPUNIT_ASSERT_EQUAL_MESSAGE(
-        "Check there are no I/O control-connections",
-        0,
-        smartEngine->getNbDiskTapeIOControlConns());
-      CPPUNIT_ASSERT_EQUAL_MESSAGE(
-        "Check no RTCP_ENDOF_REQ messages have been received",
-        (uint32_t)0,
-        smartEngine->getNbReceivedENDOF_REQs());
-      CPPUNIT_ASSERT_EQUAL_MESSAGE(
-        "Check the session with the rtcpd daemon is not being shutdown",
-        false,
-        smartEngine->shuttingDownRtcpdSession());
-      CPPUNIT_ASSERT_EQUAL_MESSAGE(
-        "Check rtcpd session has not finished",
-        false,
-        smartEngine->sessionWithRtcpdIsFinished());
-      CPPUNIT_ASSERT_EQUAL_MESSAGE(
-        "Check BridgeProtocolEngine should continue processing sockets",
-        true,
-        smartEngine->continueProcessingSocks());
+        "Check handling of no select events",
+        m_engine->handleSelectEvents(selectTimeout));
+    }
+    CPPUNIT_ASSERT_EQUAL_MESSAGE(
+      "Check there are no I/O control-connections",
+      0,
+      m_engine->getNbDiskTapeIOControlConns());
+    CPPUNIT_ASSERT_EQUAL_MESSAGE(
+      "Check no RTCP_ENDOF_REQ messages have been received",
+      (uint32_t)0,
+      m_engine->getNbReceivedENDOF_REQs());
+    CPPUNIT_ASSERT_EQUAL_MESSAGE(
+      "Check the session with the rtcpd daemon is not being shutdown",
+      false,
+      m_engine->shuttingDownRtcpdSession());
+    CPPUNIT_ASSERT_EQUAL_MESSAGE(
+      "Check rtcpd session has not finished",
+      false,
+      m_engine->sessionWithRtcpdIsFinished());
+    CPPUNIT_ASSERT_EQUAL_MESSAGE(
+      "Check BridgeProtocolEngine should continue processing sockets",
+      true,
+      m_engine->continueProcessingSocks());
 
-      // Act as the rtcpd daemon and create a disk/tape I/O control-connection
-      // with the BridgeProtocolEngine
-      {
-        struct sockaddr_un listenAddr;
-        memset(&listenAddr, 0, sizeof(listenAddr));
-        listenAddr.sun_family = PF_LOCAL;
-        strncpy(listenAddr.sun_path, m_bridgeListenSockPath,
-          sizeof(listenAddr.sun_path) - 1);
+    // Act as the rtcpd daemon and create a disk/tape I/O control-connection
+    // with the BridgeProtocolEngine
+    {
+      struct sockaddr_un listenAddr;
+      memset(&listenAddr, 0, sizeof(listenAddr));
+      listenAddr.sun_family = PF_LOCAL;
+      strncpy(listenAddr.sun_path, m_bridgeListenSockPath,
+        sizeof(listenAddr.sun_path) - 1);
 
-        CPPUNIT_ASSERT_EQUAL_MESSAGE(
-          "Check creation of disk/tape I/O control-connection",
-          0,
-          connect(smartIoControlConnectionSock.get(),
-            (const struct sockaddr *)&listenAddr, sizeof(listenAddr)));
-      }
-        
-      // Acts as the BridgeProtocolEngine and accept the disk/tape I/O
-      // control-connection from the rtcpd daemon
-      {
-        struct timeval selectTimeout = {0, 0};
-        CPPUNIT_ASSERT_NO_THROW_MESSAGE(
-          "Check handling of the I/O control-connection connect event",
-          smartEngine->handleSelectEvents(selectTimeout));
-      }
       CPPUNIT_ASSERT_EQUAL_MESSAGE(
-        "Check the new I/O control-connection has been counted",
-        1,
-        smartEngine->getNbDiskTapeIOControlConns());
-      CPPUNIT_ASSERT_EQUAL_MESSAGE(
-        "Check no RTCP_ENDOF_REQ messages have been received",
-        (uint32_t)0,
-        smartEngine->getNbReceivedENDOF_REQs());
-      CPPUNIT_ASSERT_EQUAL_MESSAGE(
-        "Check the session with the rtcpd daemon is not being shutdown",
-        false,
-        smartEngine->shuttingDownRtcpdSession());
-      CPPUNIT_ASSERT_EQUAL_MESSAGE(
-        "Check rtcpd session has not finished",
-        false,
-        smartEngine->sessionWithRtcpdIsFinished());
-      CPPUNIT_ASSERT_EQUAL_MESSAGE(
-        "Check BridgeProtocolEngine should continue processing sockets",
-        true,
-        smartEngine->continueProcessingSocks());
-
-      // Act as the rtcpd daemon and write a end of disk/tape I/O
-      // control-connection message to the BridgeProtocolEngine
+        "Check creation of disk/tape I/O control-connection",
+        0,
+        connect(m_ioControlConnectionSock,
+          (const struct sockaddr *)&listenAddr, sizeof(listenAddr)));
+    }
+      
+    // Acts as the BridgeProtocolEngine and accept the disk/tape I/O
+    // control-connection from the rtcpd daemon
+    {
+      struct timeval selectTimeout = {0, 0};
       CPPUNIT_ASSERT_NO_THROW_MESSAGE(
-        "Check writeRTCP_ENDOF_REQ to I/O control-connection",
-        unittest::writeRTCP_ENDOF_REQ(smartIoControlConnectionSock.get()));
-
-      {
-        struct timeval selectTimeout = {0, 0};
-        CPPUNIT_ASSERT_NO_THROW_MESSAGE(
-          "Check handling of read of RTCP_ENDOF_REQ message",
-          smartEngine->handleSelectEvents(selectTimeout));
-      }
+        "Check handling of the I/O control-connection connect event",
+        m_engine->handleSelectEvents(selectTimeout));
+    }
+    CPPUNIT_ASSERT_EQUAL_MESSAGE(
+      "Check the new I/O control-connection has been counted",
+      1,
+      m_engine->getNbDiskTapeIOControlConns());
+    CPPUNIT_ASSERT_EQUAL_MESSAGE(
+      "Check no RTCP_ENDOF_REQ messages have been received",
+      (uint32_t)0,
+      m_engine->getNbReceivedENDOF_REQs());
+    CPPUNIT_ASSERT_EQUAL_MESSAGE(
+      "Check the session with the rtcpd daemon is not being shutdown",
+      false,
+      m_engine->shuttingDownRtcpdSession());
+    CPPUNIT_ASSERT_EQUAL_MESSAGE(
+      "Check rtcpd session has not finished",
+      false,
+      m_engine->sessionWithRtcpdIsFinished());
+    CPPUNIT_ASSERT_EQUAL_MESSAGE(
+      "Check BridgeProtocolEngine should continue processing sockets",
+      true,
+      m_engine->continueProcessingSocks());
 
-      // Act as the rtcpd daemon and read in the positive acknowledgement from
-      // BridgeProtocolEngine
-      CPPUNIT_ASSERT_NO_THROW_MESSAGE(
-        "Check BridgeProtocolEngine has sent positive acknowledge",
-        unittest::readAck(smartIoControlConnectionSock.get(), RTCOPY_MAGIC,
-          RTCP_ENDOF_REQ, 0));
+    // Act as the rtcpd daemon and write a end of disk/tape I/O
+    // control-connection message to the BridgeProtocolEngine
+    CPPUNIT_ASSERT_NO_THROW_MESSAGE(
+      "Check writeRTCP_ENDOF_REQ to I/O control-connection",
+      unittest::writeRTCP_ENDOF_REQ(m_ioControlConnectionSock));
 
+    {
+      struct timeval selectTimeout = {0, 0};
       CPPUNIT_ASSERT_NO_THROW_MESSAGE(
-        "Check BridgeProtocolEngine has closed its end of the I/O"
-        " control-connection",
-        unittest::connectionHasBeenClosedByPeer(
-          smartIoControlConnectionSock.get()));
-
-      CPPUNIT_ASSERT_EQUAL_MESSAGE(
-        "Check the number of I/O control-connection is now 0",
-        0,
-        smartEngine->getNbDiskTapeIOControlConns());
-
-      CPPUNIT_ASSERT_EQUAL_MESSAGE(
-        "Check 1 RTCP_ENDOF_REQ message has been received",
-        (uint32_t)1,
-        smartEngine->getNbReceivedENDOF_REQs());
-
-      CPPUNIT_ASSERT_EQUAL_MESSAGE(
-        "Check rtcpd session has finished",
-        true,
-        smartEngine->sessionWithRtcpdIsFinished());
-
-      CPPUNIT_ASSERT_EQUAL_MESSAGE(
-        "Check BridgeProtocolEngine should not continue processing sockets",
-        false,
-        smartEngine->continueProcessingSocks());
+        "Check handling of read of RTCP_ENDOF_REQ message",
+        m_engine->handleSelectEvents(selectTimeout));
     }
 
-    // Two sockets should have been closed by the BridgeProtocolEngine:
-    // * The initial connection from rtcpd
-    // * The disk/tape I/O control-connection
-    CPPUNIT_ASSERT_EQUAL_MESSAGE(
-      "Check that two sockets have been closed by the BridgeProtocolEngine",
-      (std::vector<int>::size_type)2,
-      fileCloser.m_closedFds.size());
-
-    CPPUNIT_ASSERT_MESSAGE(
-      "Check that the initialRtcpdSock was one of the two closed-sockets",
-      fileCloser.m_closedFds[0] == initialRtcpdSockBridgeSide ||
-      fileCloser.m_closedFds[1] == initialRtcpdSockBridgeSide);
-  }
+    // Act as the rtcpd daemon and read in the positive acknowledgement from
+    // BridgeProtocolEngine
+    CPPUNIT_ASSERT_NO_THROW_MESSAGE(
+      "Check BridgeProtocolEngine has sent positive acknowledge",
+      unittest::readAck(m_ioControlConnectionSock, RTCOPY_MAGIC,
+        RTCP_ENDOF_REQ, 0));
 
-  // The BridgeProtocolEngine must wait for all of its requests to the client
-  // for more work to be answered by the clinet before ending a tape session,
-  // even in the event the client reports a DISABLED tape.
-  //
-  // Here is a description of the following bug where a migration job gets
-  // stuck forever because it exists after the end of its parent tape-session:
-  //
-  //     https://savannah.cern.ch/bugs/index.php?92460
-  //     bug #92460: tapebridged should gracefully shutdown a migration
-  //     tape-session when tapegatewayd reports a disabled tape
-  //
-  // Assume that the rtcpd daemon has enough memory to carry out the
-  // concurrent recalls to memory of two migration jobs know as J1 and J2.
-  //
-  // The rtcpd daemon requests more work and gets the first file to migrate.
-  // Knowing the size of the file, the rtcpd daemon reservers only the memory
-  // needed to migrate that file.  The rtcpd daemon has more memory and
-  // therefore requests a second file by sending a second request more work.
-  //
-  // RTCPD            BRIDGE              GATE            VMGR     SOMEBODY
-  //   |                 |                  |               |          |
-  //   | J1: more work?  |                  |               |          |
-  //   |---------------->|                  |               |          |
-  //   |                 | J1: more work?   |               |          |
-  //   |                 |----------------->|               |          |
-  //   |                 |                  |               |          |
-  //   |                 |   J1: work       |               |          |
-  //   |                 |<-----------------|               |          |
-  //   |   J1: work      |                  |               |          |
-  //   |<----------------|                  |               |          |
-  //   |                 |                  |               |          |
-  //   | J2: more work?  |                  |               |          |
-  //   |---------------->|                  |               |          |
-  //   |                 | J2: more work?   |               |          |
-  //   |                 |----------------->|               |          |
-  //   |                 |                  |               |          |
-  //
-  //  The tapegateway is slow in processing job J2'S request for more work.
-  //
-  //  In the meantime somebody disables the tape and then the rtcpd daemon
-  //  completes job J1.  The VMGR reports the tape is DISABLED when the
-  //  tapegateway tries to update the tape.
-  //
-  // RTCPD            BRIDGE              GATE            VMGR     SOMEBODY
-  //   |                 |                  |               |          |
-  //   |                 |                  |               |  DISABLE |
-  //   |                 |                  |               |<---------|
-  //   |                 |   J1: done       |               |          |
-  //   |                 |----------------->|               |          |
-  //   |                 |                  |  J1: update   |          |
-  //   |                 |                  |-------------->|          |
-  //   |                 |                  |               |          |
-  //   |                 |                  |  J1: DISABLED |          |
-  //   |                 |                  |<--------------|          |
-  //   |                 |  J1: DISABLED    |               |          |
-  //   |                 |<-----------------|               |          |
-  //
-  // The BridgeProtocolEngine incorrectly responds to the disabled-tape
-  // message by immediately telling the tapegateway to end the tape session.
-  // The tapebridge should have first waited for the reply to it's request for
-  // more work for job J2.
-  //
-  // RTCPD            BRIDGE              GATE            VMGR     SOMEBODY
-  //   |                 |                  |               |          |
-  //   |                 | J2: END SESSION  |               |          |
-  //   |                 |----------------->|               |          |
-  //   |                 |                  |               |          |
-  //
-  // The tape session is now over (protocol details are not shown).
-  //
-  // After a delay the tapegateway processes the j2 request for more work
-  //
-  // RTCPD            BRIDGE              GATE            VMGR     SOMEBODY
-  //   |                 |                  |               |          |
-  //   |                 |   J2: work       |               |          |
-  //   |                 |<-----------------|               |          |
-  //
-  // Now job j2 is outside of its tape session and is therefore stuck forever.
-  //
-  void testMigrationToDisabledTapeUsingLocalDomain() {
-    // Create the socket on which the client would listen for incoming
-    // connections from the BridgeProtocolEngine
-    utils::SmartFd smartClientListenSock;
     CPPUNIT_ASSERT_NO_THROW_MESSAGE(
-      "Create local client listen socket",
-       smartClientListenSock.reset(
-        unittest::createLocalListenSocket(m_clientListenSockPath)));
+      "Check BridgeProtocolEngine has closed its end of the I/O"
+      " control-connection",
+      unittest::connectionHasBeenClosedByPeer(m_ioControlConnectionSock));
 
-    // Create the initial rtcpd-connection using socketpair()
-    int initialRtcpdSockPair[2] = {-1, -1};
     CPPUNIT_ASSERT_EQUAL_MESSAGE(
-      "Check socket pair for the intital rtcpd-connection has been created",
+      "Check the number of I/O control-connection is now 0",
       0,
-      socketpair(PF_LOCAL, SOCK_STREAM, 0, initialRtcpdSockPair));
-    utils::SmartFd smartInitialRtcpdSockRtcpdSide(initialRtcpdSockPair[0]);
-    utils::SmartFd smartInitialRtcpdSockBridgeSide(initialRtcpdSockPair[1]);
-    const int initialRtcpdSockBridgeSide =
-      smartInitialRtcpdSockBridgeSide.get();
-
-    // Create the socket on which the BridgeProtocolEngine will listen for
-    // incoming connections from the rtcpd daemon
-    utils::SmartFd smartBridgeListenSock;
-    CPPUNIT_ASSERT_NO_THROW_MESSAGE(
-      "Create local rtcpd listen socket",
-       smartBridgeListenSock.reset(
-        unittest::createLocalListenSocket(m_bridgeListenSockPath)));
-
-    // Create a socket for the disk/tape I/O control-connection
-    utils::SmartFd
-      smartIoControlConnectionSock(socket(PF_LOCAL, SOCK_STREAM, 0));
-    CPPUNIT_ASSERT_MESSAGE(
-      "Create a socket for the first disk/tape I/O control-connection",
-      -1 != smartIoControlConnectionSock.get());
-
-    TraceableSystemFileCloser fileCloser;
-    {
-      TestingBulkRequestConfigParams      bulkRequestConfigParams;
-      TestingTapeFlushConfigParams        tapeFlushConfigParams;
-      const Cuuid_t                       &cuuid = nullCuuid;
-      const uint32_t                      volReqId = 5678;
-      const char *const                   tapePath = "";
-      const legacymsg::RtcpJobRqstMsgBody jobRequest = {
-        volReqId, // volReqId
-        0, // clientPort;
-        0, // clientEuid;
-        0, // clientEgid;
-        "clientHost", // clientHost
-        "dgn", // dgn
-        "unit", // driveUnit
-        "user", // clientUserName
-      };
-      tapegateway::Volume        volume;
-      const uint32_t             nbFilesOnDestinationTape = 2;
-      AlwaysFalseBoolFunctor     stoppingGracefully;
-      Counter<uint64_t>          tapebridgeTransactionCounter(0);
-      const bool                 logPeerOfCallbackConnectionsFromRtcpd = false;
-      const bool                 checkRtcpdIsConnectingFromLocalHost = false;
-      const uint32_t             mountTransactionId = 1;
-      const int                  netTimeout = 1;
-      ClientAddressLocal         clientAddress(m_clientListenSockPath);
-      const std::string          dgn("dgn");
-      const std::string          driveUnit("unit");
-      std::auto_ptr<ClientProxy> smartClientProxy;
-      std::auto_ptr<TestingBridgeProtocolEngine> smartEngine;
-
-      bulkRequestConfigParams.setBulkRequestMigrationMaxBytes(1,
-        ConfigParamSource::UNDEFINED);
-      bulkRequestConfigParams.setBulkRequestMigrationMaxFiles(2,
-        ConfigParamSource::UNDEFINED);
-      bulkRequestConfigParams.setBulkRequestRecallMaxBytes(3,
-        ConfigParamSource::UNDEFINED);
-      bulkRequestConfigParams.setBulkRequestRecallMaxFiles(4,
-        ConfigParamSource::UNDEFINED);
-
-      tapeFlushConfigParams.setTapeFlushMode(TAPEBRIDGE_N_FLUSHES_PER_FILE,
-        ConfigParamSource::UNDEFINED);
-      tapeFlushConfigParams.setMaxBytesBeforeFlush(1,
-        ConfigParamSource::UNDEFINED);
-      tapeFlushConfigParams.setMaxFilesBeforeFlush(1,
-        ConfigParamSource::UNDEFINED);
-
-      // Create a client proxy
-      CPPUNIT_ASSERT_NO_THROW_MESSAGE(
-        "Check newClientProxy()",
-        smartClientProxy.reset(newClientProxy(
-          cuuid,
-          mountTransactionId,
-          netTimeout,
-          clientAddress,
-          dgn,
-          driveUnit)));
-
-      // Create a BridgeProtocolEngine
-      volume.setVid("vid");
-      volume.setDensity("density");
-      volume.setLabel("label");
-      volume.setMode(tapegateway::WRITE); // Test migration-logic
-      volume.setClientType(tapegateway::TAPE_GATEWAY);
-      CPPUNIT_ASSERT_NO_THROW_MESSAGE(
-        "Check newTestingBridgeProtocolEngine()",
-        smartEngine.reset(newTestingBridgeProtocolEngine(
-          fileCloser,
-          bulkRequestConfigParams,
-          tapeFlushConfigParams,
-          cuuid,
-          smartBridgeListenSock.get(),
-          initialRtcpdSockBridgeSide,
-          jobRequest,
-          volume,
-          nbFilesOnDestinationTape,
-          stoppingGracefully,
-          tapebridgeTransactionCounter,
-          logPeerOfCallbackConnectionsFromRtcpd,
-          checkRtcpdIsConnectingFromLocalHost,
-          *smartClientProxy.get())));
-      CPPUNIT_ASSERT_EQUAL_MESSAGE(
-        "Check there are no I/O control-connections",
-        0,
-        smartEngine->getNbDiskTapeIOControlConns());
-      CPPUNIT_ASSERT_EQUAL_MESSAGE(
-        "Check no RTCP_ENDOF_REQ messages have been received",
-        (uint32_t)0,
-        smartEngine->getNbReceivedENDOF_REQs());
-      CPPUNIT_ASSERT_EQUAL_MESSAGE(
-        "Check the session with the rtcpd daemon is not being shutdown",
-        false,
-        smartEngine->shuttingDownRtcpdSession());
-      CPPUNIT_ASSERT_EQUAL_MESSAGE(
-        "Check rtcpd session has not finished",
-        false,
-        smartEngine->sessionWithRtcpdIsFinished());
-      CPPUNIT_ASSERT_EQUAL_MESSAGE(
-        "Check BridgeProtocolEngine should continue processing sockets",
-        true,
-        smartEngine->continueProcessingSocks());
+      m_engine->getNbDiskTapeIOControlConns());
 
-      // Check the BridgeProtocolEngine can handle the case of no select events
-      struct timeval selectTimeout = {0, 0};
-      CPPUNIT_ASSERT_NO_THROW_MESSAGE(
-        "Check handling of no select events",
-        smartEngine->handleSelectEvents(selectTimeout));
-      CPPUNIT_ASSERT_EQUAL_MESSAGE(
-        "Check there are no I/O control-connections",
-        0,
-        smartEngine->getNbDiskTapeIOControlConns());
-      CPPUNIT_ASSERT_EQUAL_MESSAGE(
-        "Check no RTCP_ENDOF_REQ messages have been received",
-        (uint32_t)0,
-        smartEngine->getNbReceivedENDOF_REQs());
-      CPPUNIT_ASSERT_EQUAL_MESSAGE(
-        "Check the session with the rtcpd daemon is not being shutdown",
-        false,
-        smartEngine->shuttingDownRtcpdSession());
-      CPPUNIT_ASSERT_EQUAL_MESSAGE(
-        "Check rtcpd session has not finished",
-        false,
-        smartEngine->sessionWithRtcpdIsFinished());
-      CPPUNIT_ASSERT_EQUAL_MESSAGE(
-        "Check BridgeProtocolEngine should continue processing sockets",
-        true,
-        smartEngine->continueProcessingSocks());
+    CPPUNIT_ASSERT_EQUAL_MESSAGE(
+      "Check 1 RTCP_ENDOF_REQ message has been received",
+      (uint32_t)1,
+      m_engine->getNbReceivedENDOF_REQs());
 
-      // Act as the rtcpd daemon and create a disk/tape I/O control-connection
-      // with the BridgeProtocolEngine
-      {
-        struct sockaddr_un listenAddr;
-        memset(&listenAddr, 0, sizeof(listenAddr));
-        listenAddr.sun_family = PF_LOCAL;
-        strncpy(listenAddr.sun_path, m_bridgeListenSockPath,
-          sizeof(listenAddr.sun_path) - 1);
+    CPPUNIT_ASSERT_EQUAL_MESSAGE(
+      "Check rtcpd session has finished",
+      true,
+      m_engine->sessionWithRtcpdIsFinished());
 
-        CPPUNIT_ASSERT_EQUAL_MESSAGE(
-          "Check creation of disk/tape I/O control-connection",
-          0,
-          connect(smartIoControlConnectionSock.get(),
-            (const struct sockaddr *)&listenAddr, sizeof(listenAddr)));
-      }
-        
-      // Act as the BridgeProtocolEngine and accept the disk/tape I/O
-      // control-connection from the rtcpd daemon
-      CPPUNIT_ASSERT_NO_THROW_MESSAGE(
-        "Check handling of the I/O control-connection connect event",
-        smartEngine->handleSelectEvents(selectTimeout));
-      CPPUNIT_ASSERT_EQUAL_MESSAGE(
-        "Check the new I/O control-connection has been counted",
-        1,
-        smartEngine->getNbDiskTapeIOControlConns());
-      CPPUNIT_ASSERT_EQUAL_MESSAGE(
-        "Check no RTCP_ENDOF_REQ messages have been received",
-        (uint32_t)0,
-        smartEngine->getNbReceivedENDOF_REQs());
-      CPPUNIT_ASSERT_EQUAL_MESSAGE(
-        "Check the session with the rtcpd daemon is not being shutdown",
-        false,
-        smartEngine->shuttingDownRtcpdSession());
-      CPPUNIT_ASSERT_EQUAL_MESSAGE(
-        "Check rtcpd session has not finished",
-        false,
-        smartEngine->sessionWithRtcpdIsFinished());
-      CPPUNIT_ASSERT_EQUAL_MESSAGE(
-        "Check BridgeProtocolEngine should continue processing sockets",
-        true,
-        smartEngine->continueProcessingSocks());
+    CPPUNIT_ASSERT_EQUAL_MESSAGE(
+      "Check BridgeProtocolEngine should not continue processing sockets",
+      false,
+      m_engine->continueProcessingSocks());
 
-      // Act as the rtcpd daemon and send a request for more work using the
-      // newly created disk/tape I/O control-connection
-      CPPUNIT_ASSERT_NO_THROW_MESSAGE(
-        "Check writeRTCP_REQUEST_MORE_WORK()",
-        unittest::writeRTCP_REQUEST_MORE_WORK(
-          smartIoControlConnectionSock.get(),
-          volReqId,
-          tapePath));
+    // One socket should have been closed by the BridgeProtocolEngine:
+    // * The disk/tape I/O control-connection
+    CPPUNIT_ASSERT_EQUAL_MESSAGE(
+      "Check that two sockets have been closed by the BridgeProtocolEngine",
+      (std::vector<int>::size_type)1,
+      m_fileCloser.m_closedFds.size());
+  }
 
-      // Act as the BridgeProtocolEngine and handle the first
-      // RTCP_REQUEST_MORE_WORK message from the rtcpd daemon
-      CPPUNIT_ASSERT_NO_THROW_MESSAGE(
-        "Check handling of the first RTCP_REQUEST_MORE_WORK message",
-        smartEngine->handleSelectEvents(selectTimeout));
-      CPPUNIT_ASSERT_EQUAL_MESSAGE(
-        "Check the there is still only one I/O control-connection",
-        1,
-        smartEngine->getNbDiskTapeIOControlConns());
-      CPPUNIT_ASSERT_EQUAL_MESSAGE(
-        "Check no RTCP_ENDOF_REQ messages have been received",
-        (uint32_t)0,
-        smartEngine->getNbReceivedENDOF_REQs());
-      CPPUNIT_ASSERT_EQUAL_MESSAGE(
-        "Check the session with the rtcpd daemon is not being shutdown",
-        false,
-        smartEngine->shuttingDownRtcpdSession());
-      CPPUNIT_ASSERT_EQUAL_MESSAGE(
-        "Check rtcpd session has not finished",
-        false,
-        smartEngine->sessionWithRtcpdIsFinished());
-      CPPUNIT_ASSERT_EQUAL_MESSAGE(
-        "Check BridgeProtocolEngine should continue processing sockets",
-        true,
-        smartEngine->continueProcessingSocks());
 
-      // Act as the client and accept the connection for more work from the
-      // BridgeProtocolEngine
-      const int acceptTimeout = 1;
-      int clientConnection1Fd = -1;
+  /**
+   * This unit-test checks that the bridge protocol-engine handles a tape being
+   * disabled when the bridge protocol-engine requests the first file to be
+   * migrated.
+   *
+   * RTCPD            BRIDGE                         GATE
+   *   |                 |                             |
+   *   |                 |                             |
+   *   |                 |                             |
+   *   |                 |         First file?         |
+   *   |                 |---------------------------->|
+   *   |                 |                             |
+   *   |                 |        Tape disabled        |
+   *   |                 |<----------------------------|
+   *   |                 |                             |
+   *   |  RTCP_ENDOF_REQ |                             |
+   *   |<----------------|                             |
+   *   |                 |                             |
+   *   |     Ack         |                             |
+   *   |---------------->|                             |
+   *   |                 |                             |
+   *   |                 | EndNotificationErrorReport  |
+   *   |                 |---------------------------->|
+   *   |                 |                             |
+   *   |                 |   NotificationAcknowledge   |
+   *   |                 |<----------------------------|
+   *   |                 |                             |
+   */
+  void testGetFirstFileToMigrateFromDisabledTapeUsingLocalDomain() {
+    CPPUNIT_ASSERT_EQUAL_MESSAGE(
+      "Check there are no I/O control-connections",
+      0,
+      m_engine->getNbDiskTapeIOControlConns());
+    CPPUNIT_ASSERT_EQUAL_MESSAGE(
+      "Check no RTCP_ENDOF_REQ messages have been received",
+      (uint32_t)0,
+      m_engine->getNbReceivedENDOF_REQs());
+    CPPUNIT_ASSERT_EQUAL_MESSAGE(
+      "Check the session with the rtcpd daemon is not being shutdown",
+      false,
+      m_engine->shuttingDownRtcpdSession());
+    CPPUNIT_ASSERT_EQUAL_MESSAGE(
+      "Check rtcpd session has not finished",
+      false,
+      m_engine->sessionWithRtcpdIsFinished());
+    CPPUNIT_ASSERT_EQUAL_MESSAGE(
+      "Check BridgeProtocolEngine should continue processing sockets",
+      true,
+      m_engine->continueProcessingSocks());
+
+    // Create the thread the "start rtcpd-session" thread
+    //
+    // The thread will first send a FilesToMigrateListRequest to the client,
+    // it will block waiting for the reply
+    StartRtcpdSessionThreadParams startRtcpdSessionThreadParams;
+    startRtcpdSessionThreadParams.inEngine = m_engine;
+    pthread_t startRtcpdSessionThreadId;
+    CPPUNIT_ASSERT_EQUAL_MESSAGE("pthread_create", 0,
+      pthread_create(&startRtcpdSessionThreadId, NULL,
+      runStartRtcpdSessionThread, &startRtcpdSessionThreadParams));
+
+    // Push the id of the "start rtcpd-session" thread onto the back of the
+    // list of threads to be joined with at tearDown, because an exception may
+    // be thrown before this test has a chance to call join itself
+    m_threadsToJoinWithAtTearDown.push_back(startRtcpdSessionThreadId);
+
+    // Act as the client and accept the connection for more work from the
+    // BridgeProtocolEngine
+    const int acceptTimeout = 10;
+    int clientConnection1Fd = -1;
+    CPPUNIT_ASSERT_NO_THROW_MESSAGE(
+      "Check accept of first client-connection from the BridgeProtcolEngine",
+       clientConnection1Fd = unittest::netAcceptConnection(
+         m_clientListenSock, acceptTimeout));
+    castor::io::AbstractTCPSocket clientMarshallingSock1(clientConnection1Fd);
+    clientMarshallingSock1.setTimeout(1);
+
+    // Act as the client and read in the first request for more work
+    std::auto_ptr<IObject> moreWorkRequestObj;
+    tapegateway::FilesToMigrateListRequest *moreWorkRequest = NULL;
+    {
       CPPUNIT_ASSERT_NO_THROW_MESSAGE(
-        "Check accept of first client-connection from the BridgeProtcolEngine",
-         clientConnection1Fd = unittest::netAcceptConnection(
-           smartClientListenSock.get(), acceptTimeout));
-      castor::io::AbstractTCPSocket clientMarshallingSock1(clientConnection1Fd);
-      clientMarshallingSock1.setTimeout(1);
-
-      // Act as the client and read in the first request for more work
-      std::auto_ptr<IObject> moreWorkRequestObj;
-      tapegateway::FilesToMigrateListRequest *moreWorkRequest = NULL;
-      {
-        CPPUNIT_ASSERT_NO_THROW_MESSAGE(
-          "Read in request for more migration-work from the"
-          " BridgeProtocolEngine",
-          moreWorkRequestObj.reset(clientMarshallingSock1.readObject()));
-        CPPUNIT_ASSERT_MESSAGE(
-          "Check request for more migration-work from the"
-          " BridgeProtocolEngine was read in",
-          NULL != moreWorkRequestObj.get());
-        CPPUNIT_ASSERT_EQUAL_MESSAGE(
-          "Check FilesToMigrateListRequest message is of the correct type",
-          (int)castor::OBJ_FilesToMigrateListRequest,
-          moreWorkRequestObj->type());
-        moreWorkRequest = dynamic_cast<tapegateway::FilesToMigrateListRequest*>
-          (moreWorkRequestObj.get());
-        CPPUNIT_ASSERT_MESSAGE(
-          "Check dynamic_cast to FilesToMigrateListRequest",
-          NULL != moreWorkRequest);
-        CPPUNIT_ASSERT_EQUAL_MESSAGE(
-          "Check mountTransactionId of request for more work",
-          (u_signed64)mountTransactionId,
-          moreWorkRequest->mountTransactionId());
-        CPPUNIT_ASSERT_EQUAL_MESSAGE(
-          "Check maxFiles of request for more migration-work",
-          bulkRequestConfigParams.getBulkRequestMigrationMaxFiles().getValue(),
-          (uint64_t)moreWorkRequest->maxFiles());
-        CPPUNIT_ASSERT_EQUAL_MESSAGE(
-          "Check maxBytes of request for more migration-work",
-          bulkRequestConfigParams.getBulkRequestMigrationMaxBytes().getValue(),
-          (uint64_t)moreWorkRequest->maxBytes());
-      }
+        "Read in request for more migration-work from the"
+        " BridgeProtocolEngine",
+        moreWorkRequestObj.reset(clientMarshallingSock1.readObject()));
+      CPPUNIT_ASSERT_MESSAGE(
+        "Check request for more migration-work from the"
+        " BridgeProtocolEngine was read in",
+        NULL != moreWorkRequestObj.get());
+      CPPUNIT_ASSERT_EQUAL_MESSAGE(
+        "Check FilesToMigrateListRequest message is of the correct type",
+        (int)castor::OBJ_FilesToMigrateListRequest,
+        moreWorkRequestObj->type());
+      moreWorkRequest = dynamic_cast<tapegateway::FilesToMigrateListRequest*>
+        (moreWorkRequestObj.get());
+      CPPUNIT_ASSERT_MESSAGE(
+        "Check dynamic_cast to FilesToMigrateListRequest",
+        NULL != moreWorkRequest);
+      CPPUNIT_ASSERT_EQUAL_MESSAGE(
+        "Check mountTransactionId of request for more work",
+        (u_signed64)m_mountTransactionId,
+        moreWorkRequest->mountTransactionId());
+      CPPUNIT_ASSERT_EQUAL_MESSAGE(
+        "Check maxFiles of request for more migration-work for first file",
+        (u_signed64)1,
+        moreWorkRequest->maxFiles());
+      CPPUNIT_ASSERT_EQUAL_MESSAGE(
+        "Check maxBytes of request for more migration-work for first file",
+        (u_signed64)1,
+        moreWorkRequest->maxBytes());
+    }
+
+    // Act as the client and send back a tape DISABLED message
+    {
+      tapegateway::EndNotificationErrorReport errorReport;
 
-      // Act as the client and send back the first file to be migrated
-      const char *const nsHostOfFirstFileToMigrate   = "Name-server host";
-      const uint64_t    nsFileIdOfFirstFileToMigrate = 2;
-      const uint32_t    tapeFSeqOfFirstFileToMigrate = 3;
-      const uint64_t    sizeOfFirstFileToMigrate     = 4;
-      std::auto_ptr<tapegateway::FileToMigrateStruct> fileToMigrateStruct(
-        new tapegateway::FileToMigrateStruct());
-      fileToMigrateStruct->setFileTransactionId(1);
-      fileToMigrateStruct->setNshost(nsHostOfFirstFileToMigrate);
-      fileToMigrateStruct->setFileid(nsFileIdOfFirstFileToMigrate);
-      fileToMigrateStruct->setFseq(tapeFSeqOfFirstFileToMigrate);
-      fileToMigrateStruct->setPositionCommandCode(tapegateway::TPPOSIT_FSEQ);
-      fileToMigrateStruct->setFileSize(sizeOfFirstFileToMigrate);
-      fileToMigrateStruct->setLastKnownFilename("Last known filename");
-      fileToMigrateStruct->setLastModificationTime(5);
-      fileToMigrateStruct->setPath("path");
-      fileToMigrateStruct->setUmask(6);
-      tapegateway::FilesToMigrateList filesToMigrateList;
-      filesToMigrateList.setMountTransactionId(mountTransactionId);
-      filesToMigrateList.setAggregatorTransactionId(
+      errorReport.setMountTransactionId(m_mountTransactionId);
+      errorReport.setAggregatorTransactionId(
         moreWorkRequest->aggregatorTransactionId());
-      filesToMigrateList.addFilesToMigrate(fileToMigrateStruct.release());
+      errorReport.setErrorCode(ETHELD);
+      errorReport.setErrorMessage("castor::tape::tapegateway::"
+        "VmgrTapeGatewayHelper::getTapeStatusInVmgr tape is not available:"
+        " DISABLED");
+
       CPPUNIT_ASSERT_NO_THROW_MESSAGE(
-        "Send first file to migrate",
-        clientMarshallingSock1.sendObject(filesToMigrateList));
+        "Send tape DISABLED message",
+        clientMarshallingSock1.sendObject(errorReport));
       clientMarshallingSock1.close();
+    }
 
-      // Create a thread to act as the rtcpd daemon which should read in,
-      // acknowledge and then drop the following 3 RTCOPY messages that will
-      // soon be sent by the BridgeProtocolEngine:
-      //
-      //   1. The file to be migrated message
-      //   2. The request more work message
-      //   3. The end of file-list message
-      pthread_t localRtcpdThread;
-      memset(&localRtcpdThread, '\0', sizeof(localRtcpdThread));
-      const pthread_attr_t *const localRtcpdThreadAttr = NULL;
-      const int ioControlConnectionSockFd = smartIoControlConnectionSock.get();
-      std::pair<int, int> ioControlConnectionSockFdAndNMsgs(
-        ioControlConnectionSockFd, 3);
-      CPPUNIT_ASSERT_EQUAL_MESSAGE(
-        "Create local rtcpd thread to read and drop 3 messages",
-        0,
-        pthread_create(&localRtcpdThread, localRtcpdThreadAttr,
-          unittest::readInAckAndDropNRtcopyMsgs,
-          (void *)&ioControlConnectionSockFdAndNMsgs));
-
-      // Act as the BridgeProtocolEngine and handle the first file to be
-      // migrated from the client
+    // Act as the rtcpd daemon and recieve the RTCP_ENDOF_REQ message from the
+    // initial rtcpd-connection
+    {
+      legacymsg::MessageHeader rtcpEndOfReqMsg;
       CPPUNIT_ASSERT_NO_THROW_MESSAGE(
-        "Check handling of the first file to be migrated from the client",
-        smartEngine->handleSelectEvents(selectTimeout));
-      CPPUNIT_ASSERT_EQUAL_MESSAGE(
-        "Check the there is still only one I/O control-connection",
-        1,
-        smartEngine->getNbDiskTapeIOControlConns());
-      CPPUNIT_ASSERT_EQUAL_MESSAGE(
-        "Check no RTCP_ENDOF_REQ messages have been received",
+        "Receive header of RTCP_ENDOF_REQ message from BridgeProtocolEngine",
+        LegacyTxRx::receiveMsgHeader(m_cuuid, m_volReqId,
+        m_initialRtcpdSockRtcpdSide, m_netTimeout, rtcpEndOfReqMsg));
+      CPPUNIT_ASSERT_EQUAL_MESSAGE(
+        "Check magic number of RTCP_ENDOF_REQ message from"
+        " BridgeProtocolEngine",
+        (uint32_t)RTCOPY_MAGIC,
+        rtcpEndOfReqMsg.magic);
+      CPPUNIT_ASSERT_EQUAL_MESSAGE(
+        "Check request type of RTCP_ENDOF_REQ message from"
+        " BridgeProtocolEngine",
+        (uint32_t)RTCP_ENDOF_REQ,
+        rtcpEndOfReqMsg.reqType);
+      CPPUNIT_ASSERT_EQUAL_MESSAGE(
+        "Check staus of RTCP_ENDOF_REQ message from"
+        " BridgeProtocolEngine",
         (uint32_t)0,
-        smartEngine->getNbReceivedENDOF_REQs());
-      CPPUNIT_ASSERT_EQUAL_MESSAGE(
-        "Check the session with the rtcpd daemon is not being shutdown",
-        false,
-        smartEngine->shuttingDownRtcpdSession());
-      CPPUNIT_ASSERT_EQUAL_MESSAGE(
-        "Check rtcpd session has not finished",
-        false,
-        smartEngine->sessionWithRtcpdIsFinished());
-      CPPUNIT_ASSERT_EQUAL_MESSAGE(
-        "Check BridgeProtocolEngine should continue processing sockets",
-        true,
-        smartEngine->continueProcessingSocks());
-
-      // Join with the rtcpd thread
-      void *localRtcpdThreadVoidResult = NULL; 
-      CPPUNIT_ASSERT_EQUAL_MESSAGE(
-        "Join with local rtcpd thread that read and dropped 3 messages",
-        0,
-        pthread_join(localRtcpdThread, &localRtcpdThreadVoidResult));
-
-      // Act as the rtcpd daemon and read in from the disk/tape-I/O
-      // control-connection socket the delayed ACK of the request for more work
-      {
-         char ackBuf[12];
+        rtcpEndOfReqMsg.lenOrStatus);
+    }
 
-         CPPUNIT_ASSERT_EQUAL_MESSAGE(
-           "Read in delayed ACK of the request for more work",
-           (ssize_t)sizeof(ackBuf),
-           read(ioControlConnectionSockFd, ackBuf, sizeof(ackBuf)));
-      }
+    // Act as the rtcpd daemon and send back an acknowledge to the
+    // BridgeProtocolEngine
+    {
+      legacymsg::MessageHeader ackMsg;
+      ackMsg.magic       = RTCOPY_MAGIC;
+      ackMsg.reqType     = RTCP_ENDOF_REQ;
+      ackMsg.lenOrStatus = 0;
 
-      // Act as the rtcpd daemon and send a transfer-completed message using
-      // the disk/tape-I/O control-connection with the BridgeProtocolEngine
-      {
-        const int32_t     positionMethod = tapegateway::TPPOSIT_FSEQ;
-        const uint32_t    diskFseq       = 0;
-        const uint64_t    bytesIn        = sizeOfFirstFileToMigrate;
-        const uint64_t    bytesOut       = sizeOfFirstFileToMigrate;
-        struct legacymsg::RtcpSegmentAttributes segAttr;
-        memset(&segAttr, '\0', sizeof(segAttr));
-        strncpy(segAttr.nameServerHostName, nsHostOfFirstFileToMigrate,
-          sizeof(segAttr.nameServerHostName) - 1);
-        strncpy(segAttr.segmCksumAlgorithm, "alder32",
-          sizeof(segAttr.segmCksumAlgorithm) - 1);
-        segAttr.segmCksum = 0xDEADFACE;
-        segAttr.castorFileId = nsFileIdOfFirstFileToMigrate;
+      CPPUNIT_ASSERT_NO_THROW_MESSAGE(
+        "Send ack of RTCP_ENDOF_REQ message to BridgeProtocolEngine",
+        LegacyTxRx::sendMsgHeader(m_cuuid, m_volReqId,
+          m_initialRtcpdSockRtcpdSide, m_netTimeout, ackMsg));
+    }
 
-        CPPUNIT_ASSERT_NO_THROW_MESSAGE(
-          "Check writeRTCP_FINISHED()",
-          unittest::writeRTCP_FINISHED(
-            smartIoControlConnectionSock.get(),
-            volReqId,
-            tapePath,
-            positionMethod,
-            tapeFSeqOfFirstFileToMigrate,
-            diskFseq,
-            bytesIn,
-            bytesOut,
-            segAttr));
-      }
+    // Act as the client and accept the second connection from the
+    // BridgeProtocolEngine.  This connection will be used by the
+    // BridgeProtocolEngine to send the EndNotificationError report that
+    // effective mirrors the EndNotificationError report sent to the
+    // BridgeProtocolEngine by the client to report the DISABLED tape.
+    int clientConnection2Fd = -1;
+    CPPUNIT_ASSERT_NO_THROW_MESSAGE(
+      "Check accept of second client-connection from the BridgeProtcolEngine",
+      clientConnection2Fd = unittest::netAcceptConnection(
+        m_clientListenSock, acceptTimeout));
+    castor::io::AbstractTCPSocket clientMarshallingSock2(clientConnection2Fd);
+    clientMarshallingSock2.setTimeout(1);
+
+    // Act as the client and read in the mirrored EndNotificationError from
+    // the BridgeProtocolEngine.
+    {
+      std::auto_ptr<IObject> errorReportObj;
+      CPPUNIT_ASSERT_NO_THROW_MESSAGE(
+        "Read in the mirrored EndNotificationErrorReport from the"
+        " BridgeProtocolEngine",
+        errorReportObj.reset(clientMarshallingSock2.readObject()));
+      CPPUNIT_ASSERT_MESSAGE(
+        "Check the mirrored EndNotificationErrorReport from the"
+        " BridgeProtocolEngine was read in",
+        NULL != errorReportObj.get());
+      CPPUNIT_ASSERT_EQUAL_MESSAGE(
+        "Check EndNotificationErrorReport message is of the correct type",
+        (int)castor::OBJ_EndNotificationErrorReport,
+        errorReportObj->type());
+      tapegateway::EndNotificationErrorReport *const errorReport =
+        dynamic_cast<tapegateway::EndNotificationErrorReport*>
+        (errorReportObj.get());
+      CPPUNIT_ASSERT_MESSAGE(
+        "Check dynamic_cast to EndNotificationErrorReport",
+        NULL != errorReport);
+      CPPUNIT_ASSERT_EQUAL_MESSAGE(
+        "Check mountTransactionId of EndNotificationErrorReport",
+        (u_signed64)m_mountTransactionId,
+        errorReport->mountTransactionId());
+      CPPUNIT_ASSERT_EQUAL_MESSAGE(
+        "Check errorCode of EndNotificationErrorReport",
+        ETHELD,
+        errorReport->errorCode());
+    }
 
-      // Act as the BridgeProtocolEngine and handle the transfer-completed
-      // message from the rtcpd daemon
+/*
+    // Act as the client a send back a NotificationAcknowledge message
+    {
+      tapegateway::NotificationAcknowledge ack;
+      ack.setMountTransactionId(m_mountTransactionId);
+      ack.setAggregatorTransactionId();
+    }
+*/
+    // Join with the start rtcpd session thread
+    void *startRtcpdSessionThreadResult = NULL;
+    CPPUNIT_ASSERT_EQUAL_MESSAGE("pthread_join", 0,
+      pthread_join(startRtcpdSessionThreadId,
+      &startRtcpdSessionThreadResult));
+
+    // Remove the id of the "start rtcpd session" thread from the list of
+    // threads that should be joined with at tearDown
+    m_threadsToJoinWithAtTearDown.remove(startRtcpdSessionThreadId);
+
+    CPPUNIT_ASSERT_EQUAL_MESSAGE("Thread results are same structure",
+      (void *)&startRtcpdSessionThreadParams, startRtcpdSessionThreadResult);
+
+    if(startRtcpdSessionThreadParams.outAnErrorOccurred) {
+      test_exception te(startRtcpdSessionThreadParams.outErrorStream.str());
       CPPUNIT_ASSERT_NO_THROW_MESSAGE(
-        "Check handling of the first file being migrated",
-        smartEngine->handleSelectEvents(selectTimeout));
-      CPPUNIT_ASSERT_EQUAL_MESSAGE(
-        "Check the there is still only one I/O control-connection",
-        1,
-        smartEngine->getNbDiskTapeIOControlConns());
-      CPPUNIT_ASSERT_EQUAL_MESSAGE(
-        "Check no RTCP_ENDOF_REQ messages have been received",
-        (uint32_t)0,
-        smartEngine->getNbReceivedENDOF_REQs());
-      CPPUNIT_ASSERT_EQUAL_MESSAGE(
-        "Check the session with the rtcpd daemon is not being shutdown",
-        false,
-        smartEngine->shuttingDownRtcpdSession());
-      CPPUNIT_ASSERT_EQUAL_MESSAGE(
-        "Check rtcpd session has not finished",
-        false,
-        smartEngine->sessionWithRtcpdIsFinished());
-      CPPUNIT_ASSERT_EQUAL_MESSAGE(
-        "Check BridgeProtocolEngine should continue processing sockets",
-        true,
-        smartEngine->continueProcessingSocks());
+        "The startRtcpdSessionThread thread encountered an error",
+        throw te);
+    }
+return;
+/*
 
       // Act as the rtcpd daemon and read back the ACK from the
       // BridgeProtocolEngine
@@ -1077,29 +953,32 @@ public:
 
       // Act as the BridgeProtocolEngine and handle the flushed-to-tape message
       // sent by the rtcpd daemon
-      CPPUNIT_ASSERT_NO_THROW_MESSAGE(
-        "Check handling of the first flushed-to-tape message",
-        smartEngine->handleSelectEvents(selectTimeout));
+      {
+        struct timeval selectTimeout = {0, 0};
+        CPPUNIT_ASSERT_NO_THROW_MESSAGE(
+          "Check handling of the first flushed-to-tape message",
+          m_engine->handleSelectEvents(selectTimeout));
+      }
       CPPUNIT_ASSERT_EQUAL_MESSAGE(
         "Check the there is still only one I/O control-connection",
         1,
-        smartEngine->getNbDiskTapeIOControlConns());
+        m_engine->getNbDiskTapeIOControlConns());
       CPPUNIT_ASSERT_EQUAL_MESSAGE(
         "Check no RTCP_ENDOF_REQ messages have been received",
         (uint32_t)0,
-        smartEngine->getNbReceivedENDOF_REQs());
+        m_engine->getNbReceivedENDOF_REQs());
       CPPUNIT_ASSERT_EQUAL_MESSAGE(
         "Check the session with the rtcpd daemon is not being shutdown",
         false,
-        smartEngine->shuttingDownRtcpdSession());
+        m_engine->shuttingDownRtcpdSession());
       CPPUNIT_ASSERT_EQUAL_MESSAGE(
         "Check rtcpd session has not finished",
         false,
-        smartEngine->sessionWithRtcpdIsFinished());
+        m_engine->sessionWithRtcpdIsFinished());
       CPPUNIT_ASSERT_EQUAL_MESSAGE(
         "Check BridgeProtocolEngine should continue processing sockets",
         true,
-        smartEngine->continueProcessingSocks());
+        m_engine->continueProcessingSocks());
 
       // Act as the rtcpd daemon and read in the ACK from the
       // BridgeProtocolEngine of the flushed-to-tape message
@@ -1121,7 +1000,7 @@ public:
       CPPUNIT_ASSERT_NO_THROW_MESSAGE(
         "Check accept of second client-connection from the BridgeProtcolEngine",
         clientConnection2Fd = unittest::netAcceptConnection(
-          smartClientListenSock.get(), acceptTimeout));
+          m_clientListenSock, acceptTimeout));
       castor::io::AbstractTCPSocket clientMarshallingSock2(clientConnection2Fd);
       clientMarshallingSock2.setTimeout(1);
 
@@ -1139,29 +1018,32 @@ public:
 
       // Act as the BridgeProtocolEngine and handle the second
       // RTCP_REQUEST_MORE_WORK message from the rtcpd daemon
-      CPPUNIT_ASSERT_NO_THROW_MESSAGE(
-        "Check handling of the second RTCP_REQUEST_MORE_WORK message",
-        smartEngine->handleSelectEvents(selectTimeout));
+      {
+        struct timeval selectTimeout = {0, 0};
+        CPPUNIT_ASSERT_NO_THROW_MESSAGE(
+          "Check handling of the second RTCP_REQUEST_MORE_WORK message",
+          m_engine->handleSelectEvents(selectTimeout));
+      }
       CPPUNIT_ASSERT_EQUAL_MESSAGE(
         "Check the there is still only one I/O control-connection",
         1,
-        smartEngine->getNbDiskTapeIOControlConns());
+        m_engine->getNbDiskTapeIOControlConns());
       CPPUNIT_ASSERT_EQUAL_MESSAGE(
         "Check no RTCP_ENDOF_REQ messages have been received",
         (uint32_t)0,
-        smartEngine->getNbReceivedENDOF_REQs());
+        m_engine->getNbReceivedENDOF_REQs());
       CPPUNIT_ASSERT_EQUAL_MESSAGE(
         "Check the session with the rtcpd daemon is not being shutdown",
         false,
-        smartEngine->shuttingDownRtcpdSession());
+        m_engine->shuttingDownRtcpdSession());
       CPPUNIT_ASSERT_EQUAL_MESSAGE(
         "Check rtcpd session has not finished",
         false,
-        smartEngine->sessionWithRtcpdIsFinished());
+        m_engine->sessionWithRtcpdIsFinished());
       CPPUNIT_ASSERT_EQUAL_MESSAGE(
         "Check BridgeProtocolEngine should continue processing sockets",
         true,
-        smartEngine->continueProcessingSocks());
+        m_engine->continueProcessingSocks());
 
       // The client now catches up
 
@@ -1207,123 +1089,690 @@ public:
 
       // Act as the BridgeProtocolEngine and handle the error report from the
       // client about the first migrated-file
-      CPPUNIT_ASSERT_NO_THROW_MESSAGE(
-        "Check handling of the first file's error report from the client",
-        smartEngine->handleSelectEvents(selectTimeout));
+      {
+        struct timeval selectTimeout = {0, 0};
+        CPPUNIT_ASSERT_NO_THROW_MESSAGE(
+          "Check handling of the first file's error report from the client",
+          m_engine->handleSelectEvents(selectTimeout));
+      }
       CPPUNIT_ASSERT_EQUAL_MESSAGE(
         "Check the there is still only one I/O control-connection",
         1,
-        smartEngine->getNbDiskTapeIOControlConns());
+        m_engine->getNbDiskTapeIOControlConns());
       CPPUNIT_ASSERT_EQUAL_MESSAGE(
         "Check no RTCP_ENDOF_REQ messages have been received",
         (uint32_t)0,
-        smartEngine->getNbReceivedENDOF_REQs());
+        m_engine->getNbReceivedENDOF_REQs());
       CPPUNIT_ASSERT_EQUAL_MESSAGE(
         "Check the session with the rtcpd daemon is being gracefully shutdown",
         true,
-        smartEngine->shuttingDownRtcpdSession());
+        m_engine->shuttingDownRtcpdSession());
       CPPUNIT_ASSERT_EQUAL_MESSAGE(
         "Check rtcpd session has not finished",
         false,
-        smartEngine->sessionWithRtcpdIsFinished());
+        m_engine->sessionWithRtcpdIsFinished());
       CPPUNIT_ASSERT_EQUAL_MESSAGE(
         "Check BridgeProtocolEngine should continue processing sockets",
         true,
-        smartEngine->continueProcessingSocks());
+        m_engine->continueProcessingSocks());
     }
+  */
   }
 
-  void testGenerateMigrationTapeFileId() {
-    TraceableDummyFileCloser fileCloser;
-    const int initialRtcpdSock = 12;
+  /**
+   * This unit-test check that the BridgeProtocolEngine waits for all of its
+   * requests to the client for more work to be answered by the client before
+   * ending a tape session, even in the event the client reports a DISABLED
+   * tape.
+   *
+   * Here is a description of the following bug where a migration job gets
+   * stuck forever because it exists after the end of its parent tape-session:
+   *
+   *     https://savannah.cern.ch/bugs/index.php?92460
+   *     bug #92460: tapebridged should gracefully shutdown a migration
+   *     tape-session when tapegatewayd reports a disabled tape
+   *
+   * Assume that the rtcpd daemon has enough memory to carry out the
+   * concurrent recalls to memory of two migration jobs know as J1 and J2.
+   *
+   * The rtcpd daemon requests more work and gets the first file to migrate.
+   * Knowing the size of the file, the rtcpd daemon reservers only the memory
+   * needed to migrate that file.  The rtcpd daemon has more memory and
+   * therefore requests a second file by sending a second request more work.
+   *
+   * RTCPD            BRIDGE              GATE            VMGR     SOMEBODY
+   *   |                 |                  |               |          |
+   *   | J1: more work?  |                  |               |          |
+   *   |---------------->|                  |               |          |
+   *   |                 | J1: more work?   |               |          |
+   *   |                 |----------------->|               |          |
+   *   |                 |                  |               |          |
+   *   |                 |   J1: work       |               |          |
+   *   |                 |<-----------------|               |          |
+   *   |   J1: work      |                  |               |          |
+   *   |<----------------|                  |               |          |
+   *   |                 |                  |               |          |
+   *   | J2: more work?  |                  |               |          |
+   *   |---------------->|                  |               |          |
+   *   |                 | J2: more work?   |               |          |
+   *   |                 |----------------->|               |          |
+   *   |                 |                  |               |          |
+   *
+   *  The tapegateway is slow in processing job J2'S request for more work.
+   *
+   *  In the meantime somebody disables the tape and then the rtcpd daemon
+   *  completes job J1.  The VMGR reports the tape is DISABLED when the
+   *  tapegateway tries to update the tape.
+   *
+   * RTCPD            BRIDGE              GATE            VMGR     SOMEBODY
+   *   |                 |                  |               |          |
+   *   |                 |                  |               |  DISABLE |
+   *   |                 |                  |               |<---------|
+   *   |                 |   J1: done       |               |          |
+   *   |                 |----------------->|               |          |
+   *   |                 |                  |  J1: update   |          |
+   *   |                 |                  |-------------->|          |
+   *   |                 |                  |               |          |
+   *   |                 |                  |  J1: DISABLED |          |
+   *   |                 |                  |<--------------|          |
+   *   |                 |  J1: DISABLED    |               |          |
+   *   |                 |<-----------------|               |          |
+   *
+   * The BridgeProtocolEngine incorrectly responds to the disabled-tape
+   * message by immediately telling the tapegateway to end the tape session.
+   * The tapebridge should have first waited for the reply to it's request for
+   * more work for job J2.
+   *
+   * RTCPD            BRIDGE              GATE            VMGR     SOMEBODY
+   *   |                 |                  |               |          |
+   *   |                 | J2: END SESSION  |               |          |
+   *   |                 |----------------->|               |          |
+   *   |                 |                  |               |          |
+   *
+   * The tape session is now over (protocol details are not shown).
+   *
+   * After a delay the tapegateway processes the j2 request for more work
+   *
+   * RTCPD            BRIDGE              GATE            VMGR     SOMEBODY
+   *   |                 |                  |               |          |
+   *   |                 |   J2: work       |               |          |
+   *   |                 |<-----------------|               |          |
+   *
+   * Now job j2 is outside of its tape session and is therefore stuck forever.
+   */
+  void testMigrationToDisabledTapeUsingLocalDomain() {
+    CPPUNIT_ASSERT_EQUAL_MESSAGE(
+      "Check there are no I/O control-connections",
+      0,
+      m_engine->getNbDiskTapeIOControlConns());
+    CPPUNIT_ASSERT_EQUAL_MESSAGE(
+      "Check no RTCP_ENDOF_REQ messages have been received",
+      (uint32_t)0,
+      m_engine->getNbReceivedENDOF_REQs());
+    CPPUNIT_ASSERT_EQUAL_MESSAGE(
+      "Check the session with the rtcpd daemon is not being shutdown",
+      false,
+      m_engine->shuttingDownRtcpdSession());
+    CPPUNIT_ASSERT_EQUAL_MESSAGE(
+      "Check rtcpd session has not finished",
+      false,
+      m_engine->sessionWithRtcpdIsFinished());
+    CPPUNIT_ASSERT_EQUAL_MESSAGE(
+      "Check BridgeProtocolEngine should continue processing sockets",
+      true,
+      m_engine->continueProcessingSocks());
+
+    // Check the BridgeProtocolEngine can handle the case of no select events
+    {
+      struct timeval selectTimeout = {0, 0};
+      CPPUNIT_ASSERT_NO_THROW_MESSAGE(
+        "Check handling of no select events",
+        m_engine->handleSelectEvents(selectTimeout));
+    }
+    CPPUNIT_ASSERT_EQUAL_MESSAGE(
+      "Check there are no I/O control-connections",
+      0,
+      m_engine->getNbDiskTapeIOControlConns());
+    CPPUNIT_ASSERT_EQUAL_MESSAGE(
+      "Check no RTCP_ENDOF_REQ messages have been received",
+      (uint32_t)0,
+      m_engine->getNbReceivedENDOF_REQs());
+    CPPUNIT_ASSERT_EQUAL_MESSAGE(
+      "Check the session with the rtcpd daemon is not being shutdown",
+      false,
+      m_engine->shuttingDownRtcpdSession());
+    CPPUNIT_ASSERT_EQUAL_MESSAGE(
+      "Check rtcpd session has not finished",
+      false,
+      m_engine->sessionWithRtcpdIsFinished());
+    CPPUNIT_ASSERT_EQUAL_MESSAGE(
+      "Check BridgeProtocolEngine should continue processing sockets",
+      true,
+      m_engine->continueProcessingSocks());
+
+    // Act as the rtcpd daemon and create a disk/tape I/O control-connection
+    // with the BridgeProtocolEngine
+    {
+      struct sockaddr_un listenAddr;
+      memset(&listenAddr, 0, sizeof(listenAddr));
+      listenAddr.sun_family = PF_LOCAL;
+      strncpy(listenAddr.sun_path, m_bridgeListenSockPath,
+        sizeof(listenAddr.sun_path) - 1);
+
+      CPPUNIT_ASSERT_EQUAL_MESSAGE(
+        "Check creation of disk/tape I/O control-connection",
+        0,
+        connect(m_ioControlConnectionSock,
+          (const struct sockaddr *)&listenAddr, sizeof(listenAddr)));
+    }
+      
+    // Act as the BridgeProtocolEngine and accept the disk/tape I/O
+    // control-connection from the rtcpd daemon
+    {
+      struct timeval selectTimeout = {0, 0};
+      CPPUNIT_ASSERT_NO_THROW_MESSAGE(
+        "Check handling of the I/O control-connection connect event",
+        m_engine->handleSelectEvents(selectTimeout));
+    }
+    CPPUNIT_ASSERT_EQUAL_MESSAGE(
+      "Check the new I/O control-connection has been counted",
+      1,
+      m_engine->getNbDiskTapeIOControlConns());
+    CPPUNIT_ASSERT_EQUAL_MESSAGE(
+      "Check no RTCP_ENDOF_REQ messages have been received",
+      (uint32_t)0,
+      m_engine->getNbReceivedENDOF_REQs());
+    CPPUNIT_ASSERT_EQUAL_MESSAGE(
+      "Check the session with the rtcpd daemon is not being shutdown",
+      false,
+      m_engine->shuttingDownRtcpdSession());
+    CPPUNIT_ASSERT_EQUAL_MESSAGE(
+      "Check rtcpd session has not finished",
+      false,
+      m_engine->sessionWithRtcpdIsFinished());
+    CPPUNIT_ASSERT_EQUAL_MESSAGE(
+      "Check BridgeProtocolEngine should continue processing sockets",
+      true,
+      m_engine->continueProcessingSocks());
+
+    // Act as the rtcpd daemon and send a request for more work using the
+    // newly created disk/tape I/O control-connection
+    const char *const tapePath = "";
+    CPPUNIT_ASSERT_NO_THROW_MESSAGE(
+      "Check writeRTCP_REQUEST_MORE_WORK()",
+      unittest::writeRTCP_REQUEST_MORE_WORK(
+        m_ioControlConnectionSock,
+        m_volReqId,
+        tapePath));
+
+    // Act as the BridgeProtocolEngine and handle the first
+    // RTCP_REQUEST_MORE_WORK message from the rtcpd daemon
+    {
+      struct timeval selectTimeout = {0, 0};
+      CPPUNIT_ASSERT_NO_THROW_MESSAGE(
+        "Check handling of the first RTCP_REQUEST_MORE_WORK message",
+        m_engine->handleSelectEvents(selectTimeout));
+    }
+    CPPUNIT_ASSERT_EQUAL_MESSAGE(
+      "Check the there is still only one I/O control-connection",
+      1,
+      m_engine->getNbDiskTapeIOControlConns());
+    CPPUNIT_ASSERT_EQUAL_MESSAGE(
+      "Check no RTCP_ENDOF_REQ messages have been received",
+      (uint32_t)0,
+      m_engine->getNbReceivedENDOF_REQs());
+    CPPUNIT_ASSERT_EQUAL_MESSAGE(
+      "Check the session with the rtcpd daemon is not being shutdown",
+      false,
+      m_engine->shuttingDownRtcpdSession());
+    CPPUNIT_ASSERT_EQUAL_MESSAGE(
+      "Check rtcpd session has not finished",
+      false,
+      m_engine->sessionWithRtcpdIsFinished());
+    CPPUNIT_ASSERT_EQUAL_MESSAGE(
+      "Check BridgeProtocolEngine should continue processing sockets",
+      true,
+      m_engine->continueProcessingSocks());
+
+    // Act as the client and accept the connection for more work from the
+    // BridgeProtocolEngine
+    const int acceptTimeout = 1;
+    int clientConnection1Fd = -1;
+    CPPUNIT_ASSERT_NO_THROW_MESSAGE(
+      "Check accept of first client-connection from the BridgeProtcolEngine",
+       clientConnection1Fd = unittest::netAcceptConnection(
+         m_clientListenSock, acceptTimeout));
+    castor::io::AbstractTCPSocket clientMarshallingSock1(clientConnection1Fd);
+    clientMarshallingSock1.setTimeout(1);
+
+    // Act as the client and read in the first request for more work
+    std::auto_ptr<IObject> moreWorkRequestObj;
+    tapegateway::FilesToMigrateListRequest *moreWorkRequest = NULL;
+    {
+      CPPUNIT_ASSERT_NO_THROW_MESSAGE(
+        "Read in request for more migration-work from the"
+        " BridgeProtocolEngine",
+        moreWorkRequestObj.reset(clientMarshallingSock1.readObject()));
+      CPPUNIT_ASSERT_MESSAGE(
+        "Check request for more migration-work from the"
+        " BridgeProtocolEngine was read in",
+        NULL != moreWorkRequestObj.get());
+      CPPUNIT_ASSERT_EQUAL_MESSAGE(
+        "Check FilesToMigrateListRequest message is of the correct type",
+        (int)castor::OBJ_FilesToMigrateListRequest,
+        moreWorkRequestObj->type());
+      moreWorkRequest = dynamic_cast<tapegateway::FilesToMigrateListRequest*>
+        (moreWorkRequestObj.get());
+      CPPUNIT_ASSERT_MESSAGE(
+        "Check dynamic_cast to FilesToMigrateListRequest",
+        NULL != moreWorkRequest);
+      CPPUNIT_ASSERT_EQUAL_MESSAGE(
+        "Check mountTransactionId of request for more work",
+        (u_signed64)m_mountTransactionId,
+        moreWorkRequest->mountTransactionId());
+      CPPUNIT_ASSERT_EQUAL_MESSAGE(
+        "Check maxFiles of request for more migration-work",
+        m_bulkRequestConfigParams.getBulkRequestMigrationMaxFiles().getValue(),
+        (uint64_t)moreWorkRequest->maxFiles());
+      CPPUNIT_ASSERT_EQUAL_MESSAGE(
+        "Check maxBytes of request for more migration-work",
+        m_bulkRequestConfigParams.getBulkRequestMigrationMaxBytes().getValue(),
+        (uint64_t)moreWorkRequest->maxBytes());
+    }
+
+    // Act as the client and send back the first file to be migrated
+    const char *const nsHostOfFirstFileToMigrate   = "Name-server host";
+    const uint64_t    nsFileIdOfFirstFileToMigrate = 2;
+    const uint32_t    tapeFSeqOfFirstFileToMigrate = 3;
+    const uint64_t    sizeOfFirstFileToMigrate     = 4;
+    std::auto_ptr<tapegateway::FileToMigrateStruct> fileToMigrateStruct(
+      new tapegateway::FileToMigrateStruct());
+    fileToMigrateStruct->setFileTransactionId(1);
+    fileToMigrateStruct->setNshost(nsHostOfFirstFileToMigrate);
+    fileToMigrateStruct->setFileid(nsFileIdOfFirstFileToMigrate);
+    fileToMigrateStruct->setFseq(tapeFSeqOfFirstFileToMigrate);
+    fileToMigrateStruct->setPositionCommandCode(tapegateway::TPPOSIT_FSEQ);
+    fileToMigrateStruct->setFileSize(sizeOfFirstFileToMigrate);
+    fileToMigrateStruct->setLastKnownFilename("Last known filename");
+    fileToMigrateStruct->setLastModificationTime(5);
+    fileToMigrateStruct->setPath("path");
+    fileToMigrateStruct->setUmask(6);
+    tapegateway::FilesToMigrateList filesToMigrateList;
+    filesToMigrateList.setMountTransactionId(m_mountTransactionId);
+    filesToMigrateList.setAggregatorTransactionId(
+      moreWorkRequest->aggregatorTransactionId());
+    filesToMigrateList.addFilesToMigrate(fileToMigrateStruct.release());
+    CPPUNIT_ASSERT_NO_THROW_MESSAGE(
+      "Send first file to migrate",
+      clientMarshallingSock1.sendObject(filesToMigrateList));
+    clientMarshallingSock1.close();
+
+    // Create a thread to act as the rtcpd daemon which should read in,
+    // acknowledge and then drop the following 3 RTCOPY messages that will
+    // soon be sent by the BridgeProtocolEngine:
+    //
+    //   1. The file to be migrated message
+    //   2. The request more work message
+    //   3. The end of file-list message
+    pthread_t localRtcpdThread;
+    memset(&localRtcpdThread, '\0', sizeof(localRtcpdThread));
+    const pthread_attr_t *const localRtcpdThreadAttr = NULL;
+    std::pair<int, int> ioControlConnectionSockFdAndNMsgs(
+      m_ioControlConnectionSock, 3);
+    CPPUNIT_ASSERT_EQUAL_MESSAGE(
+      "Create local rtcpd thread to read and drop 3 messages",
+      0,
+      pthread_create(&localRtcpdThread, localRtcpdThreadAttr,
+        unittest::readInAckAndDropNRtcopyMsgs,
+        (void *)&ioControlConnectionSockFdAndNMsgs));
+
+    // Push the id of the "local rtcpd" thread onto the back of the
+    // list of threads to be joined with at tearDown, because an exception may
+    // be thrown before this test has a chance to call join itself
+    m_threadsToJoinWithAtTearDown.push_back(localRtcpdThread);
+
+    // Act as the BridgeProtocolEngine and handle the first file to be
+    // migrated from the client
+    {
+      struct timeval selectTimeout = {0, 0};
+      CPPUNIT_ASSERT_NO_THROW_MESSAGE(
+        "Check handling of the first file to be migrated from the client",
+        m_engine->handleSelectEvents(selectTimeout));
+    }
+    CPPUNIT_ASSERT_EQUAL_MESSAGE(
+      "Check the there is still only one I/O control-connection",
+      1,
+      m_engine->getNbDiskTapeIOControlConns());
+    CPPUNIT_ASSERT_EQUAL_MESSAGE(
+      "Check no RTCP_ENDOF_REQ messages have been received",
+      (uint32_t)0,
+      m_engine->getNbReceivedENDOF_REQs());
+    CPPUNIT_ASSERT_EQUAL_MESSAGE(
+      "Check the session with the rtcpd daemon is not being shutdown",
+      false,
+      m_engine->shuttingDownRtcpdSession());
+    CPPUNIT_ASSERT_EQUAL_MESSAGE(
+      "Check rtcpd session has not finished",
+      false,
+      m_engine->sessionWithRtcpdIsFinished());
+    CPPUNIT_ASSERT_EQUAL_MESSAGE(
+      "Check BridgeProtocolEngine should continue processing sockets",
+      true,
+      m_engine->continueProcessingSocks());
+
+    // Join with the rtcpd thread
+    void *localRtcpdThreadVoidResult = NULL; 
+    CPPUNIT_ASSERT_EQUAL_MESSAGE(
+      "Join with local rtcpd thread that read and dropped 3 messages",
+      0,
+      pthread_join(localRtcpdThread, &localRtcpdThreadVoidResult));
+
+    // Remove the id of the "local rtcpd" thread from the list of
+    // threads that should be joined with at tearDown
+    m_threadsToJoinWithAtTearDown.remove(localRtcpdThread);
+
+    // Act as the rtcpd daemon and read in from the disk/tape-I/O
+    // control-connection socket the delayed ACK of the request for more work
+    {
+       char ackBuf[12];
+
+       CPPUNIT_ASSERT_EQUAL_MESSAGE(
+         "Read in delayed ACK of the request for more work",
+         (ssize_t)sizeof(ackBuf),
+         read(m_ioControlConnectionSock, ackBuf, sizeof(ackBuf)));
+    }
 
+    // Act as the rtcpd daemon and send a transfer-completed message using
+    // the disk/tape-I/O control-connection with the BridgeProtocolEngine
     {
-      TestingBulkRequestConfigParams      bulkRequestConfigParams;
-      TestingTapeFlushConfigParams        tapeFlushConfigParams;
-      const Cuuid_t                       &cuuid = nullCuuid;
-      const int                           rtcpdListenSock  = 11;
-      const legacymsg::RtcpJobRqstMsgBody jobRequest = {
-        0, // volReqId
-        0, // clientPort;
-        0, // clientEuid;
-        0, // clientEgid;
-        "clientHost", // clientHost
-        "dgn", // dgn
-        "unit", // driveUnit
-        "user", // clientUserName
-      };
-      const tapegateway::Volume volume;
-      const uint32_t            nbFilesOnDestinationTape = 0;
-      AlwaysFalseBoolFunctor    stoppingGracefully;
-      Counter<uint64_t>         tapebridgeTransactionCounter(0);
-      const bool                logPeerOfCallbackConnectionsFromRtcpd = false;
-      const bool                checkRtcpdIsConnectingFromLocalHost = false;
-      DummyClientProxy          clientProxy;
-      std::auto_ptr<TestingBridgeProtocolEngine> smartEngine;
-
-      bulkRequestConfigParams.setBulkRequestMigrationMaxBytes(1,
-        ConfigParamSource::UNDEFINED);
-      bulkRequestConfigParams.setBulkRequestMigrationMaxFiles(1,
-        ConfigParamSource::UNDEFINED);
-      bulkRequestConfigParams.setBulkRequestRecallMaxBytes(1,
-        ConfigParamSource::UNDEFINED);
-      bulkRequestConfigParams.setBulkRequestRecallMaxFiles(1,
-        ConfigParamSource::UNDEFINED);
-
-      tapeFlushConfigParams.setTapeFlushMode(TAPEBRIDGE_N_FLUSHES_PER_FILE,
-        ConfigParamSource::UNDEFINED);
-      tapeFlushConfigParams.setMaxBytesBeforeFlush(1,
-        ConfigParamSource::UNDEFINED);
-      tapeFlushConfigParams.setMaxFilesBeforeFlush(1,
-        ConfigParamSource::UNDEFINED);
+      const int32_t     positionMethod = tapegateway::TPPOSIT_FSEQ;
+      const uint32_t    diskFseq       = 0;
+      const uint64_t    bytesIn        = sizeOfFirstFileToMigrate;
+      const uint64_t    bytesOut       = sizeOfFirstFileToMigrate;
+      struct legacymsg::RtcpSegmentAttributes segAttr;
+      memset(&segAttr, '\0', sizeof(segAttr));
+      strncpy(segAttr.nameServerHostName, nsHostOfFirstFileToMigrate,
+        sizeof(segAttr.nameServerHostName) - 1);
+      strncpy(segAttr.segmCksumAlgorithm, "alder32",
+        sizeof(segAttr.segmCksumAlgorithm) - 1);
+      segAttr.segmCksum = 0xDEADFACE;
+      segAttr.castorFileId = nsFileIdOfFirstFileToMigrate;
 
       CPPUNIT_ASSERT_NO_THROW_MESSAGE(
-        "Check newTestingBridgeProtocolEngine()",
-        smartEngine.reset(newTestingBridgeProtocolEngine(
-          fileCloser,
-          bulkRequestConfigParams,
-          tapeFlushConfigParams,
-          cuuid,
-          rtcpdListenSock,
-          initialRtcpdSock,
-          jobRequest,
-          volume,
-          nbFilesOnDestinationTape,
-          stoppingGracefully,
-          tapebridgeTransactionCounter,
-          logPeerOfCallbackConnectionsFromRtcpd,
-          checkRtcpdIsConnectingFromLocalHost,
-          clientProxy)));
-
-      const uint64_t i               = 0xdeadfacedeadface;
-      const char     *expectedResult =  "DEADFACEDEADFACE";
-      char dst[CA_MAXPATHLEN+1];
-      memset(dst, '\0', sizeof(dst));
+        "Check writeRTCP_FINISHED()",
+        unittest::writeRTCP_FINISHED(
+          m_ioControlConnectionSock,
+          m_volReqId,
+          tapePath,
+          positionMethod,
+          tapeFSeqOfFirstFileToMigrate,
+          diskFseq,
+          bytesIn,
+          bytesOut,
+          segAttr));
+    }
 
+    // Act as the BridgeProtocolEngine and handle the transfer-completed
+    // message from the rtcpd daemon
+    {
+      struct timeval selectTimeout = {0, 0};
       CPPUNIT_ASSERT_NO_THROW_MESSAGE(
-        "Checking engine.generateMigrationTapeFileId()",
-        smartEngine->generateMigrationTapeFileId(i, dst));
+        "Check handling of the first file being migrated",
+        m_engine->handleSelectEvents(selectTimeout));
+    }
+    CPPUNIT_ASSERT_EQUAL_MESSAGE(
+      "Check the there is still only one I/O control-connection",
+      1,
+      m_engine->getNbDiskTapeIOControlConns());
+    CPPUNIT_ASSERT_EQUAL_MESSAGE(
+      "Check no RTCP_ENDOF_REQ messages have been received",
+      (uint32_t)0,
+      m_engine->getNbReceivedENDOF_REQs());
+    CPPUNIT_ASSERT_EQUAL_MESSAGE(
+      "Check the session with the rtcpd daemon is not being shutdown",
+      false,
+      m_engine->shuttingDownRtcpdSession());
+    CPPUNIT_ASSERT_EQUAL_MESSAGE(
+      "Check rtcpd session has not finished",
+      false,
+      m_engine->sessionWithRtcpdIsFinished());
+    CPPUNIT_ASSERT_EQUAL_MESSAGE(
+      "Check BridgeProtocolEngine should continue processing sockets",
+      true,
+      m_engine->continueProcessingSocks());
 
-      CPPUNIT_ASSERT_EQUAL_MESSAGE(
-        "Check result of engine.generateMigrationTapeFileId()",
-        std::string(expectedResult),
-        std::string(dst));
+    // Act as the rtcpd daemon and read back the ACK from the
+    // BridgeProtocolEngine
+    CPPUNIT_ASSERT_NO_THROW_MESSAGE(
+      "Check read back of ACK of RTCP_FINISHED message",
+      unittest::readAck(m_ioControlConnectionSock, RTCOPY_MAGIC,
+        RTCP_FILEERR_REQ, 0));
+
+    // Act as the rtcpd daemon and send the BridgeProtocolEngine a
+    // flushed-to-tape message
+    {
+      tapeBridgeFlushedToTapeMsgBody_t flushedMsgBody;
+      memset(&flushedMsgBody, '\0', sizeof(flushedMsgBody));
+      flushedMsgBody.volReqId = m_volReqId;
+      flushedMsgBody.tapeFseq = tapeFSeqOfFirstFileToMigrate;
+
+      CPPUNIT_ASSERT_MESSAGE(
+        "Check tapebridge_sendTapeBridgeFlushedToTape()",
+        0 < tapebridge_sendTapeBridgeFlushedToTape(
+          m_ioControlConnectionSock, m_netTimeout, &flushedMsgBody));
+    }
+
+    // Act as the BridgeProtocolEngine and handle the flushed-to-tape message
+    // sent by the rtcpd daemon
+    {
+      struct timeval selectTimeout = {0, 0};
+      CPPUNIT_ASSERT_NO_THROW_MESSAGE(
+        "Check handling of the first flushed-to-tape message",
+        m_engine->handleSelectEvents(selectTimeout));
+    }
+    CPPUNIT_ASSERT_EQUAL_MESSAGE(
+      "Check the there is still only one I/O control-connection",
+      1,
+      m_engine->getNbDiskTapeIOControlConns());
+    CPPUNIT_ASSERT_EQUAL_MESSAGE(
+      "Check no RTCP_ENDOF_REQ messages have been received",
+      (uint32_t)0,
+      m_engine->getNbReceivedENDOF_REQs());
+    CPPUNIT_ASSERT_EQUAL_MESSAGE(
+      "Check the session with the rtcpd daemon is not being shutdown",
+      false,
+      m_engine->shuttingDownRtcpdSession());
+    CPPUNIT_ASSERT_EQUAL_MESSAGE(
+      "Check rtcpd session has not finished",
+      false,
+      m_engine->sessionWithRtcpdIsFinished());
+    CPPUNIT_ASSERT_EQUAL_MESSAGE(
+      "Check BridgeProtocolEngine should continue processing sockets",
+      true,
+      m_engine->continueProcessingSocks());
+
+    // Act as the rtcpd daemon and read in the ACK from the
+    // BridgeProtocolEngine of the flushed-to-tape message
+    {
+      tapeBridgeFlushedToTapeAckMsg_t flushedAckMsg;
+      memset(&flushedAckMsg, '\0', sizeof(flushedAckMsg));
+
+      CPPUNIT_ASSERT_MESSAGE(
+        "Check tapebridge_recvTapeBridgeFlushedToTapeAck()",
+        0 <= tapebridge_recvTapeBridgeFlushedToTapeAck(
+          m_ioControlConnectionSock, m_netTimeout, &flushedAckMsg));
     }
 
+    // Act as the client and accept the second connection from the
+    // BridgeProtocolEngine.  This connection will be used by the
+    // BridgeProtocolEngine to send the FileMigrationReportList message of
+    // the first migrated file.
+    int clientConnection2Fd = -1;
+    CPPUNIT_ASSERT_NO_THROW_MESSAGE(
+      "Check accept of second client-connection from the BridgeProtcolEngine",
+      clientConnection2Fd = unittest::netAcceptConnection(
+        m_clientListenSock, acceptTimeout));
+    castor::io::AbstractTCPSocket clientMarshallingSock2(clientConnection2Fd);
+    clientMarshallingSock2.setTimeout(1);
+
+    // The client is now slow to process the second connection from the
+    // BridgeProtocolEngine so does nothing at this very moment in time.
+
+    // Act as the rtcpd daemon and send a request for more work using the
+    // the already existant disk/tape I/O control-connection
+    CPPUNIT_ASSERT_NO_THROW_MESSAGE(
+      "Check writeRTCP_REQUEST_MORE_WORK()",
+      unittest::writeRTCP_REQUEST_MORE_WORK(
+        m_ioControlConnectionSock,
+        m_volReqId,
+        tapePath));
+
+    // Act as the BridgeProtocolEngine and handle the second
+    // RTCP_REQUEST_MORE_WORK message from the rtcpd daemon
+    {
+      struct timeval selectTimeout = {0, 0};
+      CPPUNIT_ASSERT_NO_THROW_MESSAGE(
+        "Check handling of the second RTCP_REQUEST_MORE_WORK message",
+        m_engine->handleSelectEvents(selectTimeout));
+    }
     CPPUNIT_ASSERT_EQUAL_MESSAGE(
-      "Check that only one socket has been closed",
-      (std::vector<int>::size_type)1,
-      fileCloser.m_closedFds.size());
+      "Check the there is still only one I/O control-connection",
+      1,
+      m_engine->getNbDiskTapeIOControlConns());
+    CPPUNIT_ASSERT_EQUAL_MESSAGE(
+      "Check no RTCP_ENDOF_REQ messages have been received",
+      (uint32_t)0,
+      m_engine->getNbReceivedENDOF_REQs());
+    CPPUNIT_ASSERT_EQUAL_MESSAGE(
+      "Check the session with the rtcpd daemon is not being shutdown",
+      false,
+      m_engine->shuttingDownRtcpdSession());
+    CPPUNIT_ASSERT_EQUAL_MESSAGE(
+      "Check rtcpd session has not finished",
+      false,
+      m_engine->sessionWithRtcpdIsFinished());
+    CPPUNIT_ASSERT_EQUAL_MESSAGE(
+      "Check BridgeProtocolEngine should continue processing sockets",
+      true,
+      m_engine->continueProcessingSocks());
+
+    // The client now catches up
+
+    // Act as the client and read in the FileMigrationReportList message of
+    // the first file to be migrated from the seond connection made with the
+    // client by the BridgeProtocolEngine
+    std::auto_ptr<IObject> fileMigrationReportListObj;
+    tapegateway::FileMigrationReportList *fileMigrationReportList = NULL;
+    {
+      CPPUNIT_ASSERT_NO_THROW_MESSAGE(
+        "Read in FileMigrationReportList the BridgeProtocolEngine",
+        fileMigrationReportListObj.reset(
+          clientMarshallingSock2.readObject()));
+      CPPUNIT_ASSERT_MESSAGE(
+        "Check FileMigrationReportList was read in from the"
+        " BridgeProtocolEngine",
+        NULL != fileMigrationReportListObj.get());
+      CPPUNIT_ASSERT_EQUAL_MESSAGE(
+        "Check FileMigrationReportList is of the correct type",
+        (int)castor::OBJ_FileMigrationReportList,
+        fileMigrationReportListObj->type());
+      fileMigrationReportList =
+        dynamic_cast<tapegateway::FileMigrationReportList*>
+        (fileMigrationReportListObj.get());
+      CPPUNIT_ASSERT_MESSAGE(
+        "Check dynamic_cast to FileMigrationReportList",
+        NULL != fileMigrationReportList);
+    }
+
+    // Act as the client and reply to the BridgeProtocolEngine with an error
+    // report
+    {
+      tapegateway::EndNotificationErrorReport errorReport;
+      errorReport.setErrorCode(ECANCELED);
+      errorReport.setErrorMessage("Error message");
+
+      CPPUNIT_ASSERT_NO_THROW_MESSAGE(
+        "Send error report in response to first file migrated",
+        clientMarshallingSock2.sendObject(errorReport));
+
+      clientMarshallingSock2.close();
+    }
+
+    // Act as the BridgeProtocolEngine and handle the error report from the
+    // client about the first migrated-file
+    {
+      struct timeval selectTimeout = {0, 0};
+      CPPUNIT_ASSERT_NO_THROW_MESSAGE(
+        "Check handling of the first file's error report from the client",
+        m_engine->handleSelectEvents(selectTimeout));
+    }
+    CPPUNIT_ASSERT_EQUAL_MESSAGE(
+      "Check the there is still only one I/O control-connection",
+      1,
+      m_engine->getNbDiskTapeIOControlConns());
+    CPPUNIT_ASSERT_EQUAL_MESSAGE(
+      "Check no RTCP_ENDOF_REQ messages have been received",
+      (uint32_t)0,
+      m_engine->getNbReceivedENDOF_REQs());
+    CPPUNIT_ASSERT_EQUAL_MESSAGE(
+      "Check the session with the rtcpd daemon is being gracefully shutdown",
+      true,
+      m_engine->shuttingDownRtcpdSession());
+    CPPUNIT_ASSERT_EQUAL_MESSAGE(
+      "Check rtcpd session has not finished",
+      false,
+      m_engine->sessionWithRtcpdIsFinished());
+    CPPUNIT_ASSERT_EQUAL_MESSAGE(
+      "Check BridgeProtocolEngine should continue processing sockets",
+      true,
+      m_engine->continueProcessingSocks());
+  }
+
+  /**
+   * This unit-test checks that the BridgeProtocolEngine correctly generates
+   * the hexadecimal tape-file identifiers used by the legacy RTCOPY-protocol.
+   */
+  void testGenerateMigrationTapeFileId() {
+    CPPUNIT_ASSERT_EQUAL_MESSAGE(
+      "Check there are no I/O control-connections",
+      0,
+      m_engine->getNbDiskTapeIOControlConns());
+    CPPUNIT_ASSERT_EQUAL_MESSAGE(
+      "Check no RTCP_ENDOF_REQ messages have been received",
+      (uint32_t)0,
+      m_engine->getNbReceivedENDOF_REQs());
+    CPPUNIT_ASSERT_EQUAL_MESSAGE(
+      "Check the session with the rtcpd daemon is not being shutdown",
+      false,
+      m_engine->shuttingDownRtcpdSession());
+    CPPUNIT_ASSERT_EQUAL_MESSAGE(
+      "Check rtcpd session has not finished",
+      false,
+      m_engine->sessionWithRtcpdIsFinished());
+    CPPUNIT_ASSERT_EQUAL_MESSAGE(
+      "Check BridgeProtocolEngine should continue processing sockets",
+      true,
+      m_engine->continueProcessingSocks());
+
+    const uint64_t i               = 0xdeadfacedeadface;
+    const char     *expectedResult =  "DEADFACEDEADFACE";
+    char dst[CA_MAXPATHLEN+1];
+    memset(dst, '\0', sizeof(dst));
+
+    CPPUNIT_ASSERT_NO_THROW_MESSAGE(
+      "Checking engine.generateMigrationTapeFileId()",
+      m_engine->generateMigrationTapeFileId(i, dst));
+
     CPPUNIT_ASSERT_EQUAL_MESSAGE(
-      "Check that initialRtcpdSock was the socket that was closed",
-      initialRtcpdSock,
-      fileCloser.m_closedFds.front());
+      "Check result of engine.generateMigrationTapeFileId()",
+      std::string(expectedResult),
+      std::string(dst));
   }
 
   CPPUNIT_TEST_SUITE(BridgeProtocolEngineTest);
 
-  CPPUNIT_TEST(testConstructor);
   CPPUNIT_TEST(testShutdownOfProtocolUsingLocalDomain);
+  CPPUNIT_TEST(testGetFirstFileToMigrateFromDisabledTapeUsingLocalDomain);
   CPPUNIT_TEST(testMigrationToDisabledTapeUsingLocalDomain);
   CPPUNIT_TEST(testGenerateMigrationTapeFileId);