//------------------------------------------------------------------------------ //! @file BulkRequestPrepareManagerTest.cc //! @author Cedric Caffy - CERN //------------------------------------------------------------------------------ /************************************************************************ * EOS - the CERN Disk Storage System * * Copyright (C) 2017 CERN/Switzerland * * * * This program is free software: you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation, either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see <http://www.gnu.org/licenses/>.* ************************************************************************/ #include "unit_tests/mgm/bulk-request/PrepareManagerTest.hh" #include "unit_tests/mgm/bulk-request/MockPrepareMgmFSInterface.hh" #include "mgm/bulk-request/prepare/manager/BulkRequestPrepareManager.hh" #include "mgm/bulk-request/BulkRequestFactory.hh" #include "mgm/Namespace.hh" #include "common/VirtualIdentity.hh" TEST_F(BulkRequestPrepareManagerTest, bulkRequestTest) { USE_EOSBULKNAMESPACE std::unique_ptr<StageBulkRequest> request = BulkRequestFactory::createStageBulkRequest("requestId", eos::common::VirtualIdentity::Root()); //Let's add 10 files uint8_t nbFiles = 10; for (uint8_t i = 0; i < nbFiles; ++i) { std::stringstream ss; ss << "path" << i; std::unique_ptr<File> fileToAdd = std::make_unique<File>(ss.str()); request->addFile(std::move(fileToAdd)); } ASSERT_EQ(nbFiles, request->getFiles()->size()); } using ::testing::MatchesRegex; TEST_F(BulkRequestPrepareManagerTest, stagePrepareFilesWorkflow) { int nbFiles = 3; std::vector<std::string> paths = PrepareManagerTest::generateDefaultPaths( nbFiles); std::vector<std::string> oinfos = PrepareManagerTest::generateEmptyOinfos( nbFiles); std::unique_ptr<MockPrepareMgmFSInterface> mgmOfsPtr = std::make_unique<MockPrepareMgmFSInterface>(); MockPrepareMgmFSInterface& mgmOfs = *mgmOfsPtr; //addStats should be called only two times EXPECT_CALL(mgmOfs, addStats).Times(2); //isTapeEnabled should not be called as we are in the case where everything is fine EXPECT_CALL(mgmOfs, isTapeEnabled).Times(0); //As everything is fine, no Emsg should be called EXPECT_CALL(mgmOfs, Emsg).Times(0); //Everything is fine, all the files exist ON_CALL(mgmOfs, _exists(_, _, _, _, _, _)).WillByDefault(Invoke( MockPrepareMgmFSInterface::_EXISTS_VID_FILE_EXISTS_LAMBDA)); //the _exists method should be called for all files EXPECT_CALL(mgmOfs, _exists(_, _, _, _, _, _)).Times(nbFiles); ON_CALL(mgmOfs, _attr_ls(_, _, _, _, _, _)) .WillByDefault(Invoke( MockPrepareMgmFSInterface::_ATTR_LS_STAGE_PREPARE_LAMBDA )); EXPECT_CALL(mgmOfs, _attr_ls(_, _, _, _, _, _)).Times(nbFiles); EXPECT_CALL(mgmOfs, Emsg).Times(0); EXPECT_CALL(mgmOfs, _access).Times(nbFiles); EXPECT_CALL(mgmOfs, FSctl).Times(nbFiles); // EOS-CTA reporter EXPECT_CALL(mgmOfs, get_logId()).Times(nbFiles); EXPECT_CALL(mgmOfs, get_host()).Times(nbFiles); EXPECT_CALL(mgmOfs, writeEosReportRecord(MatchesRegex( MockPrepareMgmFSInterface::EOS_REPORT_STR_FORMAT))).Times(nbFiles); ClientWrapper client = PrepareManagerTest::getDefaultClient(); PrepareArgumentsWrapper pargs("testReqId", Prep_STAGE, paths, oinfos); ErrorWrapper errorWrapper = PrepareManagerTest::getDefaultError(); XrdOucErrInfo* error = errorWrapper.getError(); eos::mgm::bulk::BulkRequestPrepareManager pm(std::move(mgmOfsPtr)); int retPrepare = pm.prepare(*(pargs.getPrepareArguments()), *error, client.getClient()); ASSERT_EQ(nbFiles, pm.getBulkRequest()->getFiles()->size()); ASSERT_EQ(SFS_DATA, retPrepare); } TEST_F(BulkRequestPrepareManagerTest, stagePrepareFileWithNoPath) { //prepare stage should be idempotent https://its.cern.ch/jira/projects/EOS/issues/EOS-4739 std::unique_ptr<NiceMock<MockPrepareMgmFSInterface>> mgmOfsPtr = std::make_unique<NiceMock<MockPrepareMgmFSInterface>>(); NiceMock<MockPrepareMgmFSInterface>& mgmOfs = *mgmOfsPtr; //No path exist, but Emsg should not be called EXPECT_CALL(mgmOfs, Emsg).Times(0); //No path are set, no mgmOfs method should be called EXPECT_CALL(mgmOfs, _exists(_, _, _, _, _, _)).Times(0); EXPECT_CALL(mgmOfs, _attr_ls(_, _, _, _, _, _)).Times(0); EXPECT_CALL(mgmOfs, _access).Times(0); EXPECT_CALL(mgmOfs, FSctl).Times(0); ClientWrapper client = PrepareManagerTest::getDefaultClient(); PrepareArgumentsWrapper pargs("testReqId", Prep_STAGE, {}, {}); ErrorWrapper errorWrapper = PrepareManagerTest::getDefaultError(); XrdOucErrInfo* error = errorWrapper.getError(); eos::mgm::bulk::BulkRequestPrepareManager pm(std::move(mgmOfsPtr)); int retPrepare = pm.prepare(*(pargs.getPrepareArguments()), *error, client.getClient()); //The bulk-request is created, 0 files are supposed to be there ASSERT_EQ(0, pm.getBulkRequest()->getFiles()->size()); //The prepare manager returns SFS_DATA ASSERT_EQ(SFS_DATA, retPrepare); } TEST_F(BulkRequestPrepareManagerTest, stagePrepareFileWithEmptyStringPaths) { //prepare stage should be idempotent https://its.cern.ch/jira/projects/EOS/issues/EOS-4739 std::unique_ptr<NiceMock<MockPrepareMgmFSInterface>> mgmOfsPtr = std::make_unique<NiceMock<MockPrepareMgmFSInterface>>(); NiceMock<MockPrepareMgmFSInterface>& mgmOfs = *mgmOfsPtr; //No path exist, but Emsg should not be called EXPECT_CALL(mgmOfs, Emsg).Times(1); //No path are set, no mgmOfs method should be called EXPECT_CALL(mgmOfs, _exists(_, _, _, _, _, _)).Times(0); EXPECT_CALL(mgmOfs, _attr_ls(_, _, _, _, _, _)).Times(0); EXPECT_CALL(mgmOfs, _access).Times(0); EXPECT_CALL(mgmOfs, FSctl).Times(0); ClientWrapper client = PrepareManagerTest::getDefaultClient(); PrepareArgumentsWrapper pargs("testReqId", Prep_STAGE, {""}, {""}); ErrorWrapper errorWrapper = PrepareManagerTest::getDefaultError(); XrdOucErrInfo* error = errorWrapper.getError(); eos::mgm::bulk::BulkRequestPrepareManager pm(std::move(mgmOfsPtr)); int retPrepare = pm.prepare(*(pargs.getPrepareArguments()), *error, client.getClient()); //The bulk-request is created, 0 files are supposed to be there ASSERT_EQ(0, pm.getBulkRequest()->getFiles()->size()); //The prepare manager returns SFS_DATA ASSERT_EQ(SFS_DATA, retPrepare); } TEST_F(BulkRequestPrepareManagerTest, stagePrepareAllFilesDoNotExist) { /** * If all files do not exist, the prepare should succeed */ int nbFiles = 3; std::vector<std::string> paths = PrepareManagerTest::generateDefaultPaths( nbFiles); std::vector<std::string> oinfos = PrepareManagerTest::generateEmptyOinfos( nbFiles); std::unique_ptr<NiceMock<MockPrepareMgmFSInterface>> mgmOfsPtr = std::make_unique<NiceMock<MockPrepareMgmFSInterface>>(); NiceMock<MockPrepareMgmFSInterface>& mgmOfs = *mgmOfsPtr; //One file does not exist, Emsg should be called once EXPECT_CALL(mgmOfs, Emsg).Times(nbFiles); ON_CALL(mgmOfs, _exists(_, _, _, _, _, _)).WillByDefault(Invoke( MockPrepareMgmFSInterface::_EXISTS_VID_FILE_DOES_NOT_EXIST_LAMBDA)); //The current behaviour is that the prepare logic returns an error if at least one file does not exist. EXPECT_CALL(mgmOfs, _exists(_, _, _, _, _, _)).Times(3); EXPECT_CALL(mgmOfs, _attr_ls(_, _, _, _, _, _)).Times(0); EXPECT_CALL(mgmOfs, _access).Times(0); EXPECT_CALL(mgmOfs, FSctl).Times(0); ClientWrapper client = PrepareManagerTest::getDefaultClient(); PrepareArgumentsWrapper pargs("testReqId", Prep_STAGE, paths, oinfos); ErrorWrapper errorWrapper = PrepareManagerTest::getDefaultError(); XrdOucErrInfo* error = errorWrapper.getError(); eos::mgm::bulk::BulkRequestPrepareManager pm(std::move(mgmOfsPtr)); int retPrepare = pm.prepare(*(pargs.getPrepareArguments()), *error, client.getClient()); auto bulkRequest = pm.getBulkRequest(); ASSERT_EQ(3, bulkRequest->getFiles()->size()); ASSERT_EQ(3, bulkRequest->getAllFilesInError()->size()); auto filesInError = bulkRequest->getAllFilesInError(); for (auto fileInError : *filesInError) { ASSERT_EQ(0, fileInError.getError().value().find("prepare - file does not exist or is not accessible to you")); } ASSERT_EQ(SFS_DATA, retPrepare); } TEST_F(BulkRequestPrepareManagerTest, stagePrepareOneFileDoNotExistReturnsSfsData) { /** * If one file does not exist, the prepare should succeed */ int nbFiles = 3; std::vector<std::string> paths = PrepareManagerTest::generateDefaultPaths( nbFiles); std::vector<std::string> oinfos = PrepareManagerTest::generateEmptyOinfos( nbFiles); std::unique_ptr<NiceMock<MockPrepareMgmFSInterface>> mgmOfsPtr = std::make_unique<NiceMock<MockPrepareMgmFSInterface>>(); NiceMock<MockPrepareMgmFSInterface>& mgmOfs = *mgmOfsPtr; //isTapeEnabled should not be called EXPECT_CALL(mgmOfs, isTapeEnabled).Times(0); //One file does not exist, Emsg should be called once EXPECT_CALL(mgmOfs, Emsg).Times(1); //Exist will first return true for the existing file, then return false, EXPECT_CALL(mgmOfs, _exists(_, _, _, _, _, _)).Times(nbFiles).WillOnce( Invoke(MockPrepareMgmFSInterface::_EXISTS_VID_FILE_EXISTS_LAMBDA) ).WillOnce(Invoke( MockPrepareMgmFSInterface::_EXISTS_VID_FILE_DOES_NOT_EXIST_LAMBDA) ).WillRepeatedly( Invoke(MockPrepareMgmFSInterface::_EXISTS_VID_FILE_EXISTS_LAMBDA) ); //Attr ls should work for the files that exist EXPECT_CALL(mgmOfs, _attr_ls(_, _, _, _, _, _)).Times(nbFiles - 1) .WillRepeatedly(Invoke( MockPrepareMgmFSInterface::_ATTR_LS_STAGE_PREPARE_LAMBDA )); EXPECT_CALL(mgmOfs, _access).Times(nbFiles - 1); EXPECT_CALL(mgmOfs, FSctl).Times(nbFiles - 1); ClientWrapper client = PrepareManagerTest::getDefaultClient(); PrepareArgumentsWrapper pargs("testReqId", Prep_STAGE, paths, oinfos); ErrorWrapper errorWrapper = PrepareManagerTest::getDefaultError(); XrdOucErrInfo* error = errorWrapper.getError(); eos::mgm::bulk::BulkRequestPrepareManager pm(std::move(mgmOfsPtr)); int retPrepare = pm.prepare(*(pargs.getPrepareArguments()), *error, client.getClient()); //All the files should be in the bulk-request, even the one that does not exist auto bulkRequest = pm.getBulkRequest(); const auto& bulkReqPaths = bulkRequest->getFiles(); ASSERT_EQ(nbFiles, bulkReqPaths->size()); for (uint8_t i = 0; i < bulkReqPaths->size(); ++i) { ASSERT_EQ(paths[i], (*bulkReqPaths)[i]->getPath()); } //Prepare is a success ASSERT_EQ(SFS_DATA, retPrepare); } TEST_F(BulkRequestPrepareManagerTest, stagePrepareNoPreparePermission) { int nbFiles = 3; std::vector<std::string> paths = PrepareManagerTest::generateDefaultPaths( nbFiles); std::vector<std::string> oinfos = PrepareManagerTest::generateEmptyOinfos( nbFiles); std::unique_ptr<MockPrepareMgmFSInterface> mgmOfsPtr = std::make_unique<MockPrepareMgmFSInterface>(); MockPrepareMgmFSInterface& mgmOfs = *mgmOfsPtr; //addStats should be called only two times EXPECT_CALL(mgmOfs, addStats).Times(2); //isTapeEnabled should not be called as we are in the case where everything is fine EXPECT_CALL(mgmOfs, isTapeEnabled).Times(0); //As there is no prepare permission, Emsg should be called for each file EXPECT_CALL(mgmOfs, Emsg).Times(nbFiles); //Everything is fine, all the files exist ON_CALL(mgmOfs, _exists(_, _, _, _, _, _)).WillByDefault(Invoke( MockPrepareMgmFSInterface::_EXISTS_VID_FILE_EXISTS_LAMBDA)); //the _exists method should be called for all files EXPECT_CALL(mgmOfs, _exists(_, _, _, _, _, _)).Times(nbFiles); ON_CALL(mgmOfs, _attr_ls(_, _, _, _, _, _)) .WillByDefault(Invoke( MockPrepareMgmFSInterface::_ATTR_LS_STAGE_PREPARE_LAMBDA )); EXPECT_CALL(mgmOfs, _attr_ls(_, _, _, _, _, _)).Times(nbFiles); //Access should EXPECT_CALL(mgmOfs, _access).Times(nbFiles).WillRepeatedly(Return(SFS_ERROR)); EXPECT_CALL(mgmOfs, FSctl).Times(0); // EOS-CTA reporter EXPECT_CALL(mgmOfs, get_logId()).Times(nbFiles); EXPECT_CALL(mgmOfs, get_host()).Times(nbFiles); EXPECT_CALL(mgmOfs, writeEosReportRecord(MatchesRegex( MockPrepareMgmFSInterface::EOS_REPORT_STR_FORMAT))).Times(nbFiles); ClientWrapper client = PrepareManagerTest::getDefaultClient(); PrepareArgumentsWrapper pargs("testReqId", Prep_STAGE, paths, oinfos); ErrorWrapper errorWrapper = PrepareManagerTest::getDefaultError(); XrdOucErrInfo* error = errorWrapper.getError(); eos::mgm::bulk::BulkRequestPrepareManager pm(std::move(mgmOfsPtr)); int retPrepare = pm.prepare(*(pargs.getPrepareArguments()), *error, client.getClient()); ASSERT_EQ(nbFiles, pm.getBulkRequest()->getFiles()->size()); ASSERT_EQ(SFS_DATA, retPrepare); } TEST_F(BulkRequestPrepareManagerTest, abortPrepareFilesWorkflow) { int nbFiles = 3; std::vector<std::string> paths = PrepareManagerTest::generateDefaultPaths( nbFiles); std::vector<std::string> oinfos = PrepareManagerTest::generateEmptyOinfos( nbFiles); std::unique_ptr<MockPrepareMgmFSInterface> mgmOfsPtr = std::make_unique<MockPrepareMgmFSInterface>(); MockPrepareMgmFSInterface& mgmOfs = *mgmOfsPtr; //addStats should be called only two times EXPECT_CALL(mgmOfs, addStats).Times(2); //isTapeEnabled should not be called as we are in the case where everything is fine EXPECT_CALL(mgmOfs, isTapeEnabled).Times(0); //As everything is fine, no Emsg should be called EXPECT_CALL(mgmOfs, Emsg).Times(0); //Everything is fine, all the files exist ON_CALL(mgmOfs, _exists(_, _, _, _, _, _)).WillByDefault(Invoke( MockPrepareMgmFSInterface::_EXISTS_VID_FILE_EXISTS_LAMBDA)); //the _exists method should be called for all files EXPECT_CALL(mgmOfs, _exists(_, _, _, _, _, _)).Times(nbFiles); ON_CALL(mgmOfs, _attr_ls(_, _, _, _, _, _)) .WillByDefault(Invoke( MockPrepareMgmFSInterface::_ATTR_LS_ABORT_PREPARE_LAMBDA )); EXPECT_CALL(mgmOfs, _attr_ls(_, _, _, _, _, _)).Times(nbFiles); EXPECT_CALL(mgmOfs, Emsg).Times(0); EXPECT_CALL(mgmOfs, _access).Times(nbFiles); EXPECT_CALL(mgmOfs, FSctl).Times(nbFiles); // EOS-CTA reporter EXPECT_CALL(mgmOfs, get_logId()).Times(nbFiles); EXPECT_CALL(mgmOfs, get_host()).Times(nbFiles); EXPECT_CALL(mgmOfs, writeEosReportRecord(MatchesRegex( MockPrepareMgmFSInterface::EOS_REPORT_STR_FORMAT))).Times(nbFiles); ClientWrapper client = PrepareManagerTest::getDefaultClient(); PrepareArgumentsWrapper pargs("testReqId", Prep_CANCEL, paths, oinfos); ErrorWrapper errorWrapper = PrepareManagerTest::getDefaultError(); XrdOucErrInfo* error = errorWrapper.getError(); eos::mgm::bulk::BulkRequestPrepareManager pm(std::move(mgmOfsPtr)); int retPrepare = pm.prepare(*(pargs.getPrepareArguments()), *error, client.getClient()); //Abort prepare generates a bulk-request ASSERT_NE(nullptr, pm.getBulkRequest()); //Abort prepare returns SFS_OK ASSERT_EQ(SFS_OK, retPrepare); } TEST_F(BulkRequestPrepareManagerTest, abortPrepareOnFileExistsOtherDoNotExist) { int nbFiles = 3; std::vector<std::string> paths = PrepareManagerTest::generateDefaultPaths( nbFiles); std::vector<std::string> oinfos = PrepareManagerTest::generateEmptyOinfos( nbFiles); std::unique_ptr<NiceMock<MockPrepareMgmFSInterface>> mgmOfsPtr = std::make_unique<NiceMock<MockPrepareMgmFSInterface>>(); NiceMock<MockPrepareMgmFSInterface>& mgmOfs = *mgmOfsPtr; //isTapeEnabled should not be called EXPECT_CALL(mgmOfs, isTapeEnabled).Times(0); //One file does not exist, but as we are idempotent, no error should be returned EXPECT_CALL(mgmOfs, Emsg).Times(nbFiles - 1); //Exist will first return true for the existing file, then return false EXPECT_CALL(mgmOfs, _exists(_, _, _, _, _, _)).Times(nbFiles).WillOnce(Invoke( MockPrepareMgmFSInterface::_EXISTS_VID_FILE_EXISTS_LAMBDA)).WillRepeatedly( Invoke( MockPrepareMgmFSInterface::_EXISTS_VID_FILE_DOES_NOT_EXIST_LAMBDA)); //Attr ls should work for the file that exists EXPECT_CALL(mgmOfs, _attr_ls(_, _, _, _, _, _)).Times(1) .WillRepeatedly(Invoke( MockPrepareMgmFSInterface::_ATTR_LS_ABORT_PREPARE_LAMBDA )); EXPECT_CALL(mgmOfs, _access).Times(1); EXPECT_CALL(mgmOfs, FSctl).Times(1); ClientWrapper client = PrepareManagerTest::getDefaultClient(); PrepareArgumentsWrapper pargs("testReqId", Prep_CANCEL, paths, oinfos); ErrorWrapper errorWrapper = PrepareManagerTest::getDefaultError(); XrdOucErrInfo* error = errorWrapper.getError(); eos::mgm::bulk::BulkRequestPrepareManager pm(std::move(mgmOfsPtr)); int retPrepare = pm.prepare(*(pargs.getPrepareArguments()), *error, client.getClient()); ASSERT_EQ(SFS_OK, retPrepare); } TEST_F(BulkRequestPrepareManagerTest, evictPrepareFilesWorkflow) { int nbFiles = 3; std::vector<std::string> paths = PrepareManagerTest::generateDefaultPaths( nbFiles); std::vector<std::string> oinfos = PrepareManagerTest::generateEmptyOinfos( nbFiles); std::unique_ptr<MockPrepareMgmFSInterface> mgmOfsPtr = std::make_unique<MockPrepareMgmFSInterface>(); MockPrepareMgmFSInterface& mgmOfs = *mgmOfsPtr; //addStats should be called only two times EXPECT_CALL(mgmOfs, addStats).Times(2); //isTapeEnabled should not be called as we are in the case where everything is fine EXPECT_CALL(mgmOfs, isTapeEnabled).Times(0); //As everything is fine, no Emsg should be called EXPECT_CALL(mgmOfs, Emsg).Times(0); //Everything is fine, all the files exist ON_CALL(mgmOfs, _exists(_, _, _, _, _, _)).WillByDefault(Invoke( MockPrepareMgmFSInterface::_EXISTS_VID_FILE_EXISTS_LAMBDA)); //the _exists method should be called for all files EXPECT_CALL(mgmOfs, _exists(_, _, _, _, _, _)).Times(nbFiles); ON_CALL(mgmOfs, _attr_ls(_, _, _, _, _, _)) .WillByDefault(Invoke( MockPrepareMgmFSInterface::_ATTR_LS_EVICT_PREPARE_LAMBDA )); EXPECT_CALL(mgmOfs, _attr_ls(_, _, _, _, _, _)).Times(nbFiles); EXPECT_CALL(mgmOfs, Emsg).Times(0); EXPECT_CALL(mgmOfs, _access).Times(nbFiles); EXPECT_CALL(mgmOfs, FSctl).Times(nbFiles); // EOS-CTA reporter EXPECT_CALL(mgmOfs, get_logId()).Times(nbFiles); EXPECT_CALL(mgmOfs, get_host()).Times(nbFiles); EXPECT_CALL(mgmOfs, writeEosReportRecord(MatchesRegex( MockPrepareMgmFSInterface::EOS_REPORT_STR_FORMAT))).Times(nbFiles); ClientWrapper client = PrepareManagerTest::getDefaultClient(); PrepareArgumentsWrapper pargs("testReqId", Prep_EVICT, paths, oinfos); ErrorWrapper errorWrapper = PrepareManagerTest::getDefaultError(); XrdOucErrInfo* error = errorWrapper.getError(); eos::mgm::bulk::BulkRequestPrepareManager pm(std::move(mgmOfsPtr)); int retPrepare = pm.prepare(*(pargs.getPrepareArguments()), *error, client.getClient()); //Evict prepare does not generate a bulk-request, so the bulk-request should be equal to nullptr std::unique_ptr<BulkRequest> bulkRequest = pm.getBulkRequest(); ASSERT_EQ(nullptr, bulkRequest); //Evict prepare returns SFS_OK ASSERT_EQ(SFS_OK, retPrepare); } TEST_F(BulkRequestPrepareManagerTest, evictPrepareOneFileExistsOtherDoNotExist) { /** * If one file does not exist, the prepare evict should succeed * Prepare is now idempotent (https://its.cern.ch/jira/projects/EOS/issues/EOS-4739) */ int nbFiles = 3; std::vector<std::string> paths = PrepareManagerTest::generateDefaultPaths( nbFiles); std::vector<std::string> oinfos = PrepareManagerTest::generateEmptyOinfos( nbFiles); std::unique_ptr<NiceMock<MockPrepareMgmFSInterface>> mgmOfsPtr = std::make_unique<NiceMock<MockPrepareMgmFSInterface>>(); NiceMock<MockPrepareMgmFSInterface>& mgmOfs = *mgmOfsPtr; //isTapeEnabled should not be called EXPECT_CALL(mgmOfs, isTapeEnabled).Times(0); //One file does not exist, Emsg should not be called as we are idempotent EXPECT_CALL(mgmOfs, Emsg).Times(nbFiles - 1); //Exist will first return true for the existing file, then return false EXPECT_CALL(mgmOfs, _exists(_, _, _, _, _, _)).Times(nbFiles).WillOnce(Invoke( MockPrepareMgmFSInterface::_EXISTS_VID_FILE_EXISTS_LAMBDA)).WillRepeatedly( Invoke( MockPrepareMgmFSInterface::_EXISTS_VID_FILE_DOES_NOT_EXIST_LAMBDA)); //Attr ls should work for the files that exist EXPECT_CALL(mgmOfs, _attr_ls(_, _, _, _, _, _)).Times(1) .WillRepeatedly(Invoke( MockPrepareMgmFSInterface::_ATTR_LS_EVICT_PREPARE_LAMBDA )); EXPECT_CALL(mgmOfs, _access).Times(1); EXPECT_CALL(mgmOfs, FSctl).Times(1); ClientWrapper client = PrepareManagerTest::getDefaultClient(); PrepareArgumentsWrapper pargs("testReqId", Prep_EVICT, paths, oinfos); ErrorWrapper errorWrapper = PrepareManagerTest::getDefaultError(); XrdOucErrInfo* error = errorWrapper.getError(); eos::mgm::bulk::BulkRequestPrepareManager pm(std::move(mgmOfsPtr)); int retPrepare = pm.prepare(*(pargs.getPrepareArguments()), *error, client.getClient()); ASSERT_EQ(SFS_OK, retPrepare); }