//------------------------------------------------------------------------------
//! @file PrepareManagerTest.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 .*
************************************************************************/
#include "unit_tests/mgm/bulk-request/MockPrepareMgmFSInterface.hh"
#include "unit_tests/mgm/bulk-request/PrepareManagerTest.hh"
#include "mgm/bulk-request/prepare/manager/PrepareManager.hh"
using ::testing::Return;
using ::testing::_;
using ::testing::Invoke;
using ::testing::NiceMock;
using ::testing::MatchesRegex;
USE_EOSBULKNAMESPACE
//------------------------------------------------------------------------------
// Test
//------------------------------------------------------------------------------
TEST_F(PrepareManagerTest, PrepareUtilsPrepareOptsToString)
{
using namespace eos::mgm;
{
const int opts = Prep_PRTY0;
ASSERT_EQ("PRTY0", PrepareUtils::prepareOptsToString(opts));
}
{
const int opts = Prep_PRTY1;
ASSERT_EQ("PRTY1", PrepareUtils::prepareOptsToString(opts));
}
{
const int opts = Prep_PRTY2;
ASSERT_EQ("PRTY2", PrepareUtils::prepareOptsToString(opts));
}
{
const int opts = Prep_PRTY3;
ASSERT_EQ("PRTY3", PrepareUtils::prepareOptsToString(opts));
}
{
const int opts = Prep_SENDAOK;
ASSERT_EQ("PRTY0,SENDAOK", PrepareUtils::prepareOptsToString(opts));
}
{
const int opts = Prep_SENDERR;
ASSERT_EQ("PRTY0,SENDERR", PrepareUtils::prepareOptsToString(opts));
}
{
const int opts = Prep_SENDACK;
ASSERT_EQ("PRTY0,SENDACK", PrepareUtils::prepareOptsToString(opts));
}
{
const int opts = Prep_WMODE;
ASSERT_EQ("PRTY0,WMODE", PrepareUtils::prepareOptsToString(opts));
}
{
const int opts = Prep_STAGE;
ASSERT_EQ("PRTY0,STAGE", PrepareUtils::prepareOptsToString(opts));
}
{
const int opts = Prep_COLOC;
ASSERT_EQ("PRTY0,COLOC", PrepareUtils::prepareOptsToString(opts));
}
{
const int opts = Prep_FRESH;
ASSERT_EQ("PRTY0,FRESH", PrepareUtils::prepareOptsToString(opts));
}
#if (XrdMajorVNUM(XrdVNUMBER) == 4 && XrdMinorVNUM(XrdVNUMBER) >= 10) || XrdMajorVNUM(XrdVNUMBER) >= 5
{
const int opts = Prep_CANCEL;
ASSERT_EQ("PRTY0,CANCEL", PrepareUtils::prepareOptsToString(opts));
}
{
const int opts = Prep_QUERY;
ASSERT_EQ("PRTY0,QUERY", PrepareUtils::prepareOptsToString(opts));
}
{
const int opts = Prep_EVICT;
ASSERT_EQ("PRTY0,EVICT", PrepareUtils::prepareOptsToString(opts));
}
#endif
}
TEST_F(PrepareManagerTest, pargsWrapperTest)
{
PrepareArgumentsWrapper pargs("reqid", Prep_CANCEL);
for (int i = 0; i < 10; ++i) {
pargs.addFile(std::to_string(i), std::to_string(i));
}
ASSERT_EQ(10, pargs.getNbFiles());
ASSERT_NE(nullptr, pargs.getPrepareArguments());
}
TEST_F(PrepareManagerTest, stagePrepareFilesWorkflow)
{
int nbFiles = 3;
std::vector paths = PrepareManagerTest::generateDefaultPaths(
nbFiles);
std::vector oinfos = PrepareManagerTest::generateEmptyOinfos(
nbFiles);
// Add twice the same file to verify that the prepare workflow will be triggered
// for duplicated path
paths.push_back("a");
paths.push_back("b");
paths.push_back("a");
oinfos.push_back("");
oinfos.push_back("");
oinfos.push_back("");
nbFiles += 3;
std::unique_ptr mgmOfsPtr =
std::make_unique();
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);
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::PrepareManager pm(std::move(mgmOfsPtr));
int retPrepare = pm.prepare(*(pargs.getPrepareArguments()), *error,
client.getClient());
ASSERT_EQ(SFS_DATA, retPrepare);
}
TEST_F(PrepareManagerTest, stagePrepareFileWithNoPath)
{
//prepare stage should be idempotent https://its.cern.ch/jira/projects/EOS/issues/EOS-4739
std::unique_ptr> mgmOfsPtr =
std::make_unique>();
NiceMock& 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::PrepareManager pm(std::move(mgmOfsPtr));
int retPrepare = pm.prepare(*(pargs.getPrepareArguments()), *error,
client.getClient());
//The prepare manager returns SFS_ERROR
ASSERT_EQ(SFS_ERROR, retPrepare);
}
TEST_F(PrepareManagerTest, stagePrepareAllFilesDoNotExist)
{
/**
* If all files do not exist, the prepare should not succeed
*/
int nbFiles = 3;
std::vector paths = PrepareManagerTest::generateDefaultPaths(
nbFiles);
std::vector oinfos = PrepareManagerTest::generateEmptyOinfos(
nbFiles);
std::unique_ptr> mgmOfsPtr =
std::make_unique>();
NiceMock& 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::PrepareManager pm(std::move(mgmOfsPtr));
int retPrepare = pm.prepare(*(pargs.getPrepareArguments()), *error,
client.getClient());
ASSERT_EQ(SFS_ERROR, retPrepare);
}
TEST_F(PrepareManagerTest, stagePrepareOneFileDoNotExistReturnsSfsData)
{
/**
* If all files do not exist, the prepare should succeed
* Prepare is now idempotent (https://its.cern.ch/jira/projects/EOS/issues/EOS-4739)
*/
int nbFiles = 3;
std::vector paths = PrepareManagerTest::generateDefaultPaths(
nbFiles);
std::vector oinfos = PrepareManagerTest::generateEmptyOinfos(
nbFiles);
std::unique_ptr> mgmOfsPtr =
std::make_unique>();
NiceMock& 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);
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::PrepareManager pm(std::move(mgmOfsPtr));
int retPrepare = pm.prepare(*(pargs.getPrepareArguments()), *error,
client.getClient());
//We failed the second file, the prepare is a success
ASSERT_EQ(SFS_DATA, retPrepare);
}
TEST_F(PrepareManagerTest, abortPrepareFilesWorkflow)
{
int nbFiles = 3;
std::vector paths = PrepareManagerTest::generateDefaultPaths(
nbFiles);
std::vector oinfos = PrepareManagerTest::generateEmptyOinfos(
nbFiles);
std::unique_ptr mgmOfsPtr =
std::make_unique();
MockPrepareMgmFSInterface& mgmOfs = *mgmOfsPtr;
//addStats should be called only two times
EXPECT_CALL(mgmOfs, addStats).Times(nbFiles - 1);
//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);
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::PrepareManager pm(std::move(mgmOfsPtr));
int retPrepare = pm.prepare(*(pargs.getPrepareArguments()), *error,
client.getClient());
//Abort prepare returns SFS_OK
ASSERT_EQ(SFS_OK, retPrepare);
}
TEST_F(PrepareManagerTest, abortPrepareOneFileExistsOthersDoNotExist)
{
/**
* If one file does not exist, the prepare abort should fail
*/
int nbFiles = 3;
std::vector paths = PrepareManagerTest::generateDefaultPaths(
nbFiles);
std::vector oinfos = PrepareManagerTest::generateEmptyOinfos(
nbFiles);
std::unique_ptr> mgmOfsPtr =
std::make_unique>();
NiceMock& mgmOfs = *mgmOfsPtr;
//isTapeEnabled should not be called
EXPECT_CALL(mgmOfs, isTapeEnabled).Times(0);
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);
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::PrepareManager pm(std::move(mgmOfsPtr));
int retPrepare = pm.prepare(*(pargs.getPrepareArguments()), *error,
client.getClient());
ASSERT_EQ(SFS_ERROR, retPrepare);
}
TEST_F(PrepareManagerTest, evictPrepareFilesWorkflow)
{
int nbFiles = 3;
std::vector paths = PrepareManagerTest::generateDefaultPaths(
nbFiles);
std::vector oinfos = PrepareManagerTest::generateEmptyOinfos(
nbFiles);
std::unique_ptr mgmOfsPtr =
std::make_unique();
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);
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::PrepareManager pm(std::move(mgmOfsPtr));
int retPrepare = pm.prepare(*(pargs.getPrepareArguments()), *error,
client.getClient());
//Evict prepare returns SFS_OK
ASSERT_EQ(SFS_OK, retPrepare);
}
TEST_F(PrepareManagerTest, evictPrepareOneFileExistsOthersDoNotExist)
{
/**
* 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 paths = PrepareManagerTest::generateDefaultPaths(
nbFiles);
std::vector oinfos = PrepareManagerTest::generateEmptyOinfos(
nbFiles);
std::unique_ptr> mgmOfsPtr =
std::make_unique>();
NiceMock& mgmOfs = *mgmOfsPtr;
//isTapeEnabled should not be called
EXPECT_CALL(mgmOfs, isTapeEnabled).Times(0);
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);
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::PrepareManager pm(std::move(mgmOfsPtr));
int retPrepare = pm.prepare(*(pargs.getPrepareArguments()), *error,
client.getClient());
ASSERT_EQ(SFS_ERROR, retPrepare);
}
TEST_F(PrepareManagerTest, queryPrepare)
{
int nbFiles = 2;
std::vector paths = PrepareManagerTest::generateDefaultPaths(
nbFiles);
std::vector oinfos = PrepareManagerTest::generateEmptyOinfos(
nbFiles);
//Add twice the same file to verify that query prepare will return the result twice for the same file
paths.push_back("a");
//One file in the middle to test that the order will be preserved
paths.push_back("b");
paths.push_back("a");
oinfos.push_back("");
oinfos.push_back("");
oinfos.push_back("");
nbFiles += 3;
std::unique_ptr> mgmOfsPtr =
std::make_unique>();
NiceMock& mgmOfs = *mgmOfsPtr;
//Exist will first return true for the first 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));
//stat with one file on disk, on file on disk and tape
EXPECT_CALL(mgmOfs, _stat(_, _, _, _, _, _, _, _)).Times(1).WillOnce(Invoke(
MockPrepareMgmFSInterface::_STAT_FILE_ON_DISK_AND_TAPE));
//Attr ls should work for the files that exist
EXPECT_CALL(mgmOfs, _attr_ls(_, _, _, _, _, _)).Times(1)
.WillRepeatedly(Invoke(
MockPrepareMgmFSInterface::_ATTR_LS_STAGE_PREPARE_LAMBDA
));
ClientWrapper client = PrepareManagerTest::getDefaultClient();
std::string requestId = "testReqId";
PrepareArgumentsWrapper pargs(requestId, Prep_QUERY, paths, oinfos);
ErrorWrapper errorWrapper = PrepareManagerTest::getDefaultError();
XrdOucErrInfo* error = errorWrapper.getError();
eos::mgm::bulk::PrepareManager pm(std::move(mgmOfsPtr));
std::unique_ptr retQueryPrepare =
pm.queryPrepare(*(pargs.getPrepareArguments()), *error, client.getClient());
const auto& response = retQueryPrepare->getResponse();
ASSERT_EQ(requestId, response->request_id);
const auto& existingFile = response->responses.front();
ASSERT_TRUE(existingFile.is_online);
ASSERT_TRUE(existingFile.is_on_tape);
ASSERT_TRUE(existingFile.is_exists);
ASSERT_EQ(paths.front(), existingFile.path);
const auto& notExistingFile = response->responses.back();
ASSERT_FALSE(notExistingFile.is_online);
ASSERT_FALSE(notExistingFile.is_on_tape);
ASSERT_FALSE(notExistingFile.is_exists);
ASSERT_EQ("USER ERROR: file does not exist or is not accessible to you",
notExistingFile.error_text);
ASSERT_EQ(paths.back(), notExistingFile.path);
//Test that the files are returned in the same order as they were submitted by the client
for (int i = 0; i < nbFiles; ++i) {
ASSERT_EQ(paths[i], retQueryPrepare->getResponse()->responses[i].path);
}
ASSERT_EQ(SFS_DATA, retQueryPrepare->getReturnCode());
}
TEST_F(PrepareManagerTest, queryPrepareFileDoesNotExist)
{
int nbFiles = 1;
std::vector paths = PrepareManagerTest::generateDefaultPaths(
nbFiles);
std::vector oinfos = PrepareManagerTest::generateEmptyOinfos(
nbFiles);
std::unique_ptr> mgmOfsPtr =
std::make_unique>();
NiceMock& mgmOfs = *mgmOfsPtr;
//First file does not exist
EXPECT_CALL(mgmOfs, _exists(_, _, _, _, _, _)).Times(nbFiles).WillRepeatedly(
Invoke(
MockPrepareMgmFSInterface::_EXISTS_VID_FILE_DOES_NOT_EXIST_LAMBDA)
);
EXPECT_CALL(mgmOfs, _stat(_, _, _, _, _, _, _, _)).Times(0);
EXPECT_CALL(mgmOfs, _attr_ls(_, _, _, _, _, _)).Times(0);
EXPECT_CALL(mgmOfs, _access(_, _, _, _, _)).Times(0);
ClientWrapper client = PrepareManagerTest::getDefaultClient();
std::string requestId = "testReqId";
PrepareArgumentsWrapper pargs(requestId, Prep_QUERY, paths, oinfos);
ErrorWrapper errorWrapper = PrepareManagerTest::getDefaultError();
XrdOucErrInfo* error = errorWrapper.getError();
eos::mgm::bulk::PrepareManager pm(std::move(mgmOfsPtr));
std::unique_ptr retQueryPrepare =
pm.queryPrepare(*(pargs.getPrepareArguments()), *error, client.getClient());
const auto& response = retQueryPrepare->getResponse();
ASSERT_EQ(requestId, response->request_id);
const auto& fileDoesNotExist = response->responses[0];
ASSERT_FALSE(fileDoesNotExist.is_online);
ASSERT_FALSE(fileDoesNotExist.is_on_tape);
ASSERT_FALSE(fileDoesNotExist.is_exists);
ASSERT_FALSE(fileDoesNotExist.is_reqid_present);
ASSERT_FALSE(fileDoesNotExist.is_requested);
ASSERT_FALSE(fileDoesNotExist.error_text.empty());
ASSERT_TRUE(fileDoesNotExist.request_time.empty());
ASSERT_EQ(paths[0], fileDoesNotExist.path);
}
TEST_F(PrepareManagerTest, queryPrepareFileStatFails)
{
int nbFiles = 1;
std::vector paths = PrepareManagerTest::generateDefaultPaths(
nbFiles);
std::vector oinfos = PrepareManagerTest::generateEmptyOinfos(
nbFiles);
std::unique_ptr> mgmOfsPtr =
std::make_unique>();
NiceMock& mgmOfs = *mgmOfsPtr;
EXPECT_CALL(mgmOfs, _exists(_, _, _, _, _, _)).Times(nbFiles).WillRepeatedly(
Invoke(
MockPrepareMgmFSInterface::_EXISTS_VID_FILE_EXISTS_LAMBDA)
);
EXPECT_CALL(mgmOfs, _stat(_, _, _, _, _, _, _, _)).Times(nbFiles).
WillRepeatedly(
Invoke(
//Stat fails for one file
MockPrepareMgmFSInterface::_STAT_ERROR
));
EXPECT_CALL(mgmOfs, _attr_ls(_, _, _, _, _, _)).Times(0);
EXPECT_CALL(mgmOfs, _access(_, _, _, _, _)).Times(0);
ClientWrapper client = PrepareManagerTest::getDefaultClient();
std::string requestId = "testReqId";
PrepareArgumentsWrapper pargs(requestId, Prep_QUERY, paths, oinfos);
ErrorWrapper errorWrapper = PrepareManagerTest::getDefaultError();
XrdOucErrInfo* error = errorWrapper.getError();
eos::mgm::bulk::PrepareManager pm(std::move(mgmOfsPtr));
std::unique_ptr retQueryPrepare =
pm.queryPrepare(*(pargs.getPrepareArguments()), *error, client.getClient());
const auto& response = retQueryPrepare->getResponse();
ASSERT_EQ(requestId, response->request_id);
const auto& file = response->responses[0];
ASSERT_FALSE(file.is_online);
ASSERT_FALSE(file.is_on_tape);
ASSERT_TRUE(file.is_exists);
ASSERT_FALSE(file.is_reqid_present);
ASSERT_FALSE(file.is_requested);
ASSERT_EQ(MockPrepareMgmFSInterface::ERROR_STAT_STR, file.error_text);
ASSERT_TRUE(file.request_time.empty());
ASSERT_EQ(paths[0], file.path);
}
TEST_F(PrepareManagerTest, queryPrepareFileOnTapeRetrieveError)
{
int nbFiles = 1;
std::vector paths = PrepareManagerTest::generateDefaultPaths(
nbFiles);
std::vector oinfos = PrepareManagerTest::generateEmptyOinfos(
nbFiles);
std::unique_ptr> mgmOfsPtr =
std::make_unique>();
NiceMock& mgmOfs = *mgmOfsPtr;
EXPECT_CALL(mgmOfs, _exists(_, _, _, _, _, _)).Times(nbFiles).WillRepeatedly(
Invoke(
MockPrepareMgmFSInterface::_EXISTS_VID_FILE_EXISTS_LAMBDA)
);
EXPECT_CALL(mgmOfs, _stat(_, _, _, _, _, _, _, _)).WillRepeatedly(
Invoke(
//File could not be recalled
MockPrepareMgmFSInterface::_STAT_FILE_ON_TAPE_ONLY
));
EXPECT_CALL(mgmOfs, _attr_ls(_, _, _, _, _, _)).Times(nbFiles).WillRepeatedly(
Invoke(
MockPrepareMgmFSInterface::_ATTR_LS_RETRIEVE_ERROR_LAMBDA
));
EXPECT_CALL(mgmOfs, _access(_, _, _, _, _)).Times(nbFiles);
ClientWrapper client = PrepareManagerTest::getDefaultClient();
std::string requestId = MockPrepareMgmFSInterface::RETRIEVE_REQ_ID;
PrepareArgumentsWrapper pargs(requestId, Prep_QUERY, paths, oinfos);
ErrorWrapper errorWrapper = PrepareManagerTest::getDefaultError();
XrdOucErrInfo* error = errorWrapper.getError();
eos::mgm::bulk::PrepareManager pm(std::move(mgmOfsPtr));
std::unique_ptr retQueryPrepare =
pm.queryPrepare(*(pargs.getPrepareArguments()), *error, client.getClient());
const auto& response = retQueryPrepare->getResponse();
ASSERT_EQ(requestId, response->request_id);
const auto& file = response->responses[0];
ASSERT_FALSE(file.is_online);
ASSERT_TRUE(file.is_on_tape);
ASSERT_TRUE(file.is_exists);
ASSERT_TRUE(file.is_reqid_present);
ASSERT_TRUE(file.is_requested);
ASSERT_EQ(MockPrepareMgmFSInterface::ERROR_RETRIEVE_STR, file.error_text);
ASSERT_EQ(MockPrepareMgmFSInterface::RETRIEVE_REQ_TIME, file.request_time);
ASSERT_EQ(paths[0], file.path);
}
TEST_F(PrepareManagerTest, queryPrepareFileOnDiskArchiveError)
{
int nbFiles = 1;
std::vector paths = PrepareManagerTest::generateDefaultPaths(
nbFiles);
std::vector oinfos = PrepareManagerTest::generateEmptyOinfos(
nbFiles);
std::unique_ptr> mgmOfsPtr =
std::make_unique>();
NiceMock& mgmOfs = *mgmOfsPtr;
EXPECT_CALL(mgmOfs, _exists(_, _, _, _, _, _)).Times(nbFiles).WillRepeatedly(
Invoke(
MockPrepareMgmFSInterface::_EXISTS_VID_FILE_EXISTS_LAMBDA)
);
EXPECT_CALL(mgmOfs, _stat(_, _, _, _, _, _, _, _)).WillRepeatedly(
Invoke(
//File could not be recalled
MockPrepareMgmFSInterface::_STAT_FILE_ON_DISK_ONLY
));
EXPECT_CALL(mgmOfs, _attr_ls(_, _, _, _, _, _)).Times(nbFiles).WillRepeatedly(
Invoke(
MockPrepareMgmFSInterface::_ATTR_LS_ARCHIVE_ERROR_LAMBDA
));
EXPECT_CALL(mgmOfs, _access(_, _, _, _, _)).Times(nbFiles);
ClientWrapper client = PrepareManagerTest::getDefaultClient();
std::string requestId = "testReqId";
PrepareArgumentsWrapper pargs(requestId, Prep_QUERY, paths, oinfos);
ErrorWrapper errorWrapper = PrepareManagerTest::getDefaultError();
XrdOucErrInfo* error = errorWrapper.getError();
eos::mgm::bulk::PrepareManager pm(std::move(mgmOfsPtr));
std::unique_ptr retQueryPrepare =
pm.queryPrepare(*(pargs.getPrepareArguments()), *error, client.getClient());
const auto& response = retQueryPrepare->getResponse();
ASSERT_EQ(requestId, response->request_id);
const auto& file = response->responses[0];
ASSERT_TRUE(file.is_online);
ASSERT_FALSE(file.is_on_tape);
ASSERT_TRUE(file.is_exists);
ASSERT_FALSE(file.is_reqid_present);
ASSERT_FALSE(file.is_requested);
ASSERT_EQ(MockPrepareMgmFSInterface::ERROR_ARCHIVE_STR, file.error_text);
ASSERT_TRUE(file.request_time.empty());
ASSERT_EQ(paths[0], file.path);
}
TEST_F(PrepareManagerTest, queryPrepareFileNoPreparePermissionOnDirectory)
{
int nbFiles = 1;
std::vector paths = PrepareManagerTest::generateDefaultPaths(
nbFiles);
std::vector oinfos = PrepareManagerTest::generateEmptyOinfos(
nbFiles);
std::unique_ptr> mgmOfsPtr =
std::make_unique>();
NiceMock& mgmOfs = *mgmOfsPtr;
EXPECT_CALL(mgmOfs, _exists(_, _, _, _, _, _)).Times(nbFiles).WillRepeatedly(
Invoke(
MockPrepareMgmFSInterface::_EXISTS_VID_FILE_EXISTS_LAMBDA)
);
EXPECT_CALL(mgmOfs, _stat(_, _, _, _, _, _, _, _)).WillRepeatedly(
Invoke(
//File could not be recalled
MockPrepareMgmFSInterface::_STAT_FILE_ON_TAPE_ONLY
));
EXPECT_CALL(mgmOfs, _attr_ls(_, _, _, _, _, _)).Times(nbFiles).WillRepeatedly(
Invoke(
//Set all possible errors, we want to see the "USER ERROR: you don't have prepare permission" error message in all cases.
MockPrepareMgmFSInterface::_ATTR_LS_ARCHIVE_RETRIEVE_ERROR_LAMBDA
));
EXPECT_CALL(mgmOfs, _access(_, _, _, _, _)).Times(nbFiles).WillRepeatedly(
Invoke(
MockPrepareMgmFSInterface::_ACCESS_FILE_NO_PREPARE_PERMISSION_LAMBDA
)
);
ClientWrapper client = PrepareManagerTest::getDefaultClient();
std::string requestId = "testReqId";
PrepareArgumentsWrapper pargs(requestId, Prep_QUERY, paths, oinfos);
ErrorWrapper errorWrapper = PrepareManagerTest::getDefaultError();
XrdOucErrInfo* error = errorWrapper.getError();
eos::mgm::bulk::PrepareManager pm(std::move(mgmOfsPtr));
std::unique_ptr retQueryPrepare =
pm.queryPrepare(*(pargs.getPrepareArguments()), *error, client.getClient());
const auto& response = retQueryPrepare->getResponse();
ASSERT_EQ(requestId, response->request_id);
const auto& file = response->responses[0];
ASSERT_FALSE(file.is_online);
ASSERT_TRUE(file.is_on_tape);
ASSERT_TRUE(file.is_exists);
ASSERT_FALSE(file.is_reqid_present);
ASSERT_FALSE(file.is_requested);
ASSERT_FALSE(file.error_text.empty());
ASSERT_EQ("USER ERROR: you don't have prepare permission", file.error_text);
ASSERT_TRUE(file.request_time.empty());
ASSERT_EQ(paths[0], file.path);
}