179 lines
6.2 KiB
C++
179 lines
6.2 KiB
C++
/* Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License, version 2.0,
|
|
as published by the Free Software Foundation.
|
|
|
|
This program is also distributed with certain software (including
|
|
but not limited to OpenSSL) that is licensed under separate terms,
|
|
as designated in a particular file or component or in included license
|
|
documentation. The authors of MySQL hereby grant you an additional
|
|
permission to link the program and your derivative works with the
|
|
separately licensed software that they have included with MySQL.
|
|
|
|
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, version 2.0, for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
|
|
|
|
#include <fcntl.h>
|
|
#include <gtest/gtest.h>
|
|
|
|
#include "my_inttypes.h"
|
|
#include "my_io.h"
|
|
#include "plugin/keyring/file_io.h"
|
|
#include "sql/auth/auth_acls.h"
|
|
#include "sql/current_thd.h"
|
|
#include "sql/sql_class.h"
|
|
#include "unittest/gunit/keyring/mock_logger.h"
|
|
#include "unittest/gunit/test_utils.h"
|
|
|
|
#if defined(HAVE_PSI_INTERFACE)
|
|
namespace keyring {
|
|
extern PSI_file_key keyring_file_data_key;
|
|
extern PSI_file_key keyring_backup_file_data_key;
|
|
} // namespace keyring
|
|
#endif
|
|
|
|
namespace keyring__file_io_unittest {
|
|
using keyring::Mock_logger;
|
|
using my_testing::Server_initializer;
|
|
using ::testing::StartsWith;
|
|
using ::testing::StrEq;
|
|
|
|
class File_io_test : public ::testing::Test {
|
|
protected:
|
|
virtual void SetUp() {
|
|
keyring::keyring_file_data_key = PSI_NOT_INSTRUMENTED;
|
|
keyring::keyring_backup_file_data_key = PSI_NOT_INSTRUMENTED;
|
|
logger = new Mock_logger();
|
|
initializer.SetUp();
|
|
|
|
// Set user as super
|
|
Security_context *sec_ctx = current_thd->security_context();
|
|
sec_ctx->set_master_access(sec_ctx->master_access() | SUPER_ACL);
|
|
}
|
|
|
|
virtual void TearDown() {
|
|
delete logger;
|
|
initializer.TearDown();
|
|
}
|
|
|
|
protected:
|
|
Server_initializer initializer; // needed to initialize current_thd
|
|
Mock_logger *logger;
|
|
};
|
|
|
|
// Those tests are to check if methods inside File_io do not call my_error but
|
|
// instead generate warnings for filesystem operations errors. If one of those
|
|
// functions would call my_error then error would be set and we would have to
|
|
// call initializer.set_expected_error. As we do not call this in any functions
|
|
// this proves that my_error is not called. Also these tests make sure that
|
|
// correct messages are generated
|
|
|
|
TEST_F(File_io_test, OpenNotExistingFile) {
|
|
keyring::File_io file_io(logger);
|
|
remove("./some_funny_name"); // just to be sure some_funny_name does not
|
|
// exist
|
|
|
|
EXPECT_CALL(*logger, log(ERROR_LEVEL,
|
|
StrEq("File './some_funny_name' not found "
|
|
"(OS errno 2 - No such file or directory)")));
|
|
File file = file_io.open(keyring::keyring_file_data_key, "./some_funny_name",
|
|
O_RDONLY, MYF(MY_WME));
|
|
ASSERT_TRUE(file < 0); // could not open the file
|
|
}
|
|
|
|
TEST_F(File_io_test, CloseTwiceTheSame) {
|
|
keyring::File_io file_io(logger);
|
|
|
|
File file = file_io.open(keyring::keyring_file_data_key, "./some_funny_name",
|
|
O_RDONLY | O_CREAT, MYF(MY_WME));
|
|
ASSERT_TRUE(file >= 0); // successfully created
|
|
file_io.close(file, MYF(MY_WME));
|
|
|
|
EXPECT_CALL(*logger, log(ERROR_LEVEL, StartsWith("Error on close of")));
|
|
ASSERT_TRUE(file_io.close(file, MYF(MY_WME)) != 0);
|
|
|
|
remove("./some_funny_name");
|
|
}
|
|
|
|
TEST_F(File_io_test, ReadFromInvalidFileDescriptor) {
|
|
keyring::File_io file_io(logger);
|
|
File file = 2050;
|
|
uchar buff[2];
|
|
|
|
EXPECT_CALL(*logger, log(ERROR_LEVEL, StartsWith("Error reading file")));
|
|
ASSERT_TRUE(file_io.read(file, buff, 10, MYF(MY_WME)) != 10);
|
|
}
|
|
|
|
TEST_F(File_io_test, WriteToInvalidFileDescriptor) {
|
|
keyring::File_io file_io(logger);
|
|
File file = 2050;
|
|
|
|
EXPECT_CALL(*logger, log(ERROR_LEVEL, StartsWith("Error writing file")));
|
|
ASSERT_TRUE(file_io.write(file, reinterpret_cast<const uchar *>("123"), 10,
|
|
MYF(MY_WME)) != 10);
|
|
}
|
|
|
|
TEST_F(File_io_test, SeekOnInvalidFileDescriptor) {
|
|
keyring::File_io file_io(logger);
|
|
File file = 2050;
|
|
|
|
EXPECT_CALL(*logger, log(ERROR_LEVEL, StartsWith("Cannot seek in file")));
|
|
ASSERT_TRUE(file_io.seek(file, 0, MY_SEEK_END, MYF(MY_WME)) ==
|
|
MY_FILEPOS_ERROR);
|
|
}
|
|
|
|
TEST_F(File_io_test, TellOnInvalidFileDescriptor) {
|
|
keyring::File_io file_io(logger);
|
|
File file = 2050;
|
|
|
|
EXPECT_CALL(*logger, log(ERROR_LEVEL, StartsWith("Cannot seek in file")));
|
|
ASSERT_TRUE(file_io.tell(file, MYF(MY_WME)) == ((my_off_t)-1));
|
|
}
|
|
|
|
TEST_F(File_io_test, SyncOnInvalidFileDescriptor) {
|
|
keyring::File_io file_io(logger);
|
|
File file = 2050;
|
|
|
|
EXPECT_CALL(*logger, log(ERROR_LEVEL, StartsWith("Can't sync file")));
|
|
ASSERT_TRUE(file_io.sync(file, MYF(MY_WME)) != 0);
|
|
}
|
|
|
|
TEST_F(File_io_test, FStatOnInvalidFileDescriptor) {
|
|
keyring::File_io file_io(logger);
|
|
File file = 2050;
|
|
|
|
EXPECT_CALL(*logger,
|
|
log(ERROR_LEVEL, StartsWith("Error while reading stat for")));
|
|
MY_STAT keyring_file_stat;
|
|
ASSERT_TRUE(file_io.fstat(file, &keyring_file_stat, MYF(MY_WME)) != 0);
|
|
}
|
|
|
|
TEST_F(File_io_test, RemoveNotExistingFile) {
|
|
keyring::File_io file_io(logger);
|
|
remove("./some_funny_name"); // just to be sure some_funny_name does not
|
|
// exist
|
|
|
|
EXPECT_CALL(
|
|
*logger,
|
|
log(ERROR_LEVEL, StrEq("Could not remove file ./some_funny_name OS "
|
|
"retuned this error: No such file or directory")));
|
|
ASSERT_TRUE(file_io.remove("./some_funny_name", MYF(MY_WME)) != 0);
|
|
}
|
|
|
|
TEST_F(File_io_test, TruncateOnNotExistingFile) {
|
|
keyring::File_io file_io(logger);
|
|
File file = 2050;
|
|
|
|
EXPECT_CALL(*logger, log(ERROR_LEVEL, StartsWith("Could not truncate file")));
|
|
ASSERT_TRUE(file_io.truncate(file, MYF(MY_WME)) != 0);
|
|
}
|
|
|
|
} // namespace keyring__file_io_unittest
|