656 lines
22 KiB
C++
656 lines
22 KiB
C++
/* Copyright (c) 2016, 2019, 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 <components/mysql_server/mysql_page_track.h>
|
|
#include <gtest/gtest.h>
|
|
#include <mysql.h>
|
|
#include <mysql/components/component_implementation.h>
|
|
#include <mysql/components/my_service.h>
|
|
#include <mysql/components/service_implementation.h>
|
|
#include <mysql/components/services/mysql_socket_bits.h>
|
|
#include <mysql/components/services/psi_statement_bits.h>
|
|
#include <mysql/components/services/psi_thread_bits.h>
|
|
#include <mysql/mysql_lex_string.h>
|
|
#include <stddef.h>
|
|
|
|
#include "m_ctype.h"
|
|
|
|
#include <audit_api_message_service_imp.h>
|
|
#include <component_status_var_service.h>
|
|
#include <component_sys_var_service.h>
|
|
#include <keyring_iterator_service_imp.h>
|
|
#include <mysql/components/services/backup_lock_service.h>
|
|
#include <mysql/components/services/clone_protocol_service.h>
|
|
#include <mysql/components/services/component_sys_var_service.h>
|
|
#include <mysql/components/services/ongoing_transaction_query_service.h>
|
|
#include <mysql/components/services/page_track_service.h>
|
|
#include <mysql/components/services/persistent_dynamic_loader.h>
|
|
#include <mysql_ongoing_transaction_query.h>
|
|
#include <persistent_dynamic_loader.h>
|
|
#include <security_context_imp.h>
|
|
#include <server_component.h>
|
|
#include <system_variable_source_imp.h>
|
|
|
|
#include "host_application_signal_imp.h"
|
|
#include "lex_string.h"
|
|
#include "my_compiler.h"
|
|
#include "my_io.h"
|
|
#include "mysql_current_thread_reader_imp.h"
|
|
#include "scope_guard.h"
|
|
#include "sql/auth/dynamic_privileges_impl.h"
|
|
#include "sql/udf_registration_imp.h"
|
|
|
|
extern mysql_component_t COMPONENT_REF(mysql_server);
|
|
|
|
struct mysql_component_t *mysql_builtin_components[] = {
|
|
&COMPONENT_REF(mysql_server), 0};
|
|
|
|
DEFINE_BOOL_METHOD(mysql_component_mysql_current_thread_reader_imp::get,
|
|
(MYSQL_THD *)) {
|
|
return true;
|
|
}
|
|
|
|
DEFINE_BOOL_METHOD(mysql_component_host_application_signal_imp::signal,
|
|
(int, void *)) {
|
|
return true;
|
|
}
|
|
|
|
DEFINE_BOOL_METHOD(mysql_persistent_dynamic_loader_imp::load,
|
|
(void *, const char *[], int)) {
|
|
return true;
|
|
}
|
|
|
|
DEFINE_BOOL_METHOD(mysql_persistent_dynamic_loader_imp::unload,
|
|
(void *, const char *[], int)) {
|
|
return true;
|
|
}
|
|
|
|
DEFINE_BOOL_METHOD(register_privilege, (const char *, size_t)) { return true; }
|
|
|
|
DEFINE_BOOL_METHOD(unregister_privilege, (const char *, size_t)) {
|
|
return true;
|
|
}
|
|
|
|
DEFINE_BOOL_METHOD(dynamic_privilege_services_impl::register_privilege,
|
|
(const char *, size_t)) {
|
|
return true;
|
|
}
|
|
|
|
DEFINE_BOOL_METHOD(dynamic_privilege_services_impl::unregister_privilege,
|
|
(const char *, size_t)) {
|
|
return true;
|
|
}
|
|
|
|
DEFINE_BOOL_METHOD(dynamic_privilege_services_impl::has_global_grant,
|
|
(Security_context_handle, const char *, size_t)) {
|
|
return true;
|
|
}
|
|
|
|
DEFINE_BOOL_METHOD(mysql_udf_registration_imp::udf_unregister,
|
|
(const char *, int *)) {
|
|
return true;
|
|
}
|
|
|
|
DEFINE_BOOL_METHOD(mysql_udf_registration_imp::udf_register_aggregate,
|
|
(const char *, enum Item_result, Udf_func_any, Udf_func_init,
|
|
Udf_func_deinit, Udf_func_add, Udf_func_clear)) {
|
|
return true;
|
|
}
|
|
|
|
DEFINE_BOOL_METHOD(mysql_udf_registration_imp::udf_register,
|
|
(const char *, Item_result, Udf_func_any, Udf_func_init,
|
|
Udf_func_deinit)) {
|
|
return true;
|
|
}
|
|
|
|
void component_sys_var_init() {}
|
|
|
|
void component_sys_var_deinit() {}
|
|
|
|
DEFINE_BOOL_METHOD(mysql_component_sys_variable_imp::register_variable,
|
|
(const char *, const char *, int, const char *,
|
|
mysql_sys_var_check_func, mysql_sys_var_update_func, void *,
|
|
void *)) {
|
|
return true;
|
|
}
|
|
|
|
DEFINE_BOOL_METHOD(mysql_component_sys_variable_imp::get_variable,
|
|
(const char *, const char *, void **, size_t *)) {
|
|
return true;
|
|
}
|
|
|
|
DEFINE_BOOL_METHOD(mysql_component_sys_variable_imp::unregister_variable,
|
|
(const char *, const char *)) {
|
|
return true;
|
|
}
|
|
|
|
DEFINE_BOOL_METHOD(mysql_status_variable_registration_imp::register_variable,
|
|
(SHOW_VAR *)) {
|
|
return true;
|
|
}
|
|
|
|
DEFINE_BOOL_METHOD(mysql_status_variable_registration_imp::unregister_variable,
|
|
(SHOW_VAR *)) {
|
|
return true;
|
|
}
|
|
|
|
DEFINE_BOOL_METHOD(mysql_system_variable_source_imp::get,
|
|
(const char *, unsigned int, enum enum_variable_source *)) {
|
|
return true;
|
|
}
|
|
|
|
DEFINE_BOOL_METHOD(mysql_acquire_backup_lock,
|
|
(MYSQL_THD, enum enum_backup_lock_service_lock_kind,
|
|
unsigned long)) {
|
|
return true;
|
|
}
|
|
|
|
DEFINE_BOOL_METHOD(mysql_release_backup_lock, (MYSQL_THD)) { return true; }
|
|
|
|
DEFINE_METHOD(void, mysql_clone_start_statement,
|
|
(THD *&, PSI_thread_key, PSI_statement_key)) {
|
|
return;
|
|
}
|
|
|
|
DEFINE_METHOD(void, mysql_clone_finish_statement, (THD *)) { return; }
|
|
|
|
DEFINE_METHOD(int, mysql_clone_get_charsets, (THD *, Mysql_Clone_Values &)) {
|
|
return (0);
|
|
}
|
|
|
|
DEFINE_METHOD(int, mysql_clone_validate_charsets,
|
|
(THD *, Mysql_Clone_Values &)) {
|
|
return (0);
|
|
}
|
|
|
|
DEFINE_METHOD(int, mysql_clone_get_configs, (THD *, Mysql_Clone_Key_Values &)) {
|
|
return (0);
|
|
}
|
|
|
|
DEFINE_METHOD(int, mysql_clone_validate_configs,
|
|
(THD *, Mysql_Clone_Key_Values &)) {
|
|
return (0);
|
|
}
|
|
|
|
DEFINE_METHOD(MYSQL *, mysql_clone_connect,
|
|
(THD *, const char *, uint32_t, const char *, const char *,
|
|
mysql_clone_ssl_context *, MYSQL_SOCKET *)) {
|
|
return nullptr;
|
|
}
|
|
|
|
DEFINE_METHOD(int, mysql_clone_send_command,
|
|
(THD *, MYSQL *, bool, uchar, uchar *, size_t)) {
|
|
return 0;
|
|
}
|
|
|
|
DEFINE_METHOD(int, mysql_clone_get_response,
|
|
(THD *, MYSQL *, bool, uint32_t, uchar **, size_t *, size_t *)) {
|
|
return 0;
|
|
}
|
|
|
|
DEFINE_METHOD(int, mysql_clone_kill, (MYSQL *, MYSQL *)) { return 0; }
|
|
|
|
DEFINE_METHOD(void, mysql_clone_disconnect, (THD *, MYSQL *, bool, bool)) {
|
|
return;
|
|
}
|
|
|
|
DEFINE_METHOD(void, mysql_clone_get_error, (THD *, uint32_t *, const char **)) {
|
|
return;
|
|
}
|
|
|
|
DEFINE_METHOD(int, mysql_clone_get_command,
|
|
(THD *, uchar *, uchar **, size_t *)) {
|
|
return 0;
|
|
}
|
|
|
|
DEFINE_METHOD(int, mysql_clone_send_response, (THD *, bool, uchar *, size_t)) {
|
|
return 0;
|
|
}
|
|
|
|
DEFINE_METHOD(int, mysql_clone_send_error, (THD *, uchar, bool)) { return 0; }
|
|
|
|
DEFINE_BOOL_METHOD(mysql_security_context_imp::get,
|
|
(void *, Security_context_handle *)) {
|
|
return true;
|
|
}
|
|
|
|
DEFINE_BOOL_METHOD(mysql_security_context_imp::set,
|
|
(void *, Security_context_handle)) {
|
|
return true;
|
|
}
|
|
|
|
DEFINE_BOOL_METHOD(mysql_security_context_imp::create,
|
|
(Security_context_handle *)) {
|
|
return true;
|
|
}
|
|
|
|
DEFINE_BOOL_METHOD(mysql_security_context_imp::destroy,
|
|
(Security_context_handle)) {
|
|
return true;
|
|
}
|
|
|
|
DEFINE_BOOL_METHOD(mysql_security_context_imp::copy,
|
|
(Security_context_handle, Security_context_handle *)) {
|
|
return true;
|
|
}
|
|
|
|
DEFINE_BOOL_METHOD(mysql_security_context_imp::lookup,
|
|
(Security_context_handle, const char *, const char *,
|
|
const char *, const char *)) {
|
|
return true;
|
|
}
|
|
|
|
DEFINE_BOOL_METHOD(mysql_security_context_imp::get,
|
|
(Security_context_handle, const char *, void *)) {
|
|
return true;
|
|
}
|
|
|
|
DEFINE_BOOL_METHOD(mysql_security_context_imp::set,
|
|
(Security_context_handle, const char *, void *)) {
|
|
return true;
|
|
}
|
|
|
|
DEFINE_BOOL_METHOD(
|
|
mysql_ongoing_transactions_query_imp::get_ongoing_server_transactions,
|
|
(unsigned long **, unsigned long *)) {
|
|
return 0;
|
|
}
|
|
|
|
DEFINE_BOOL_METHOD(
|
|
mysql_audit_api_message_imp::emit,
|
|
(mysql_event_message_subclass_t type MY_ATTRIBUTE((unused)),
|
|
const char *component MY_ATTRIBUTE((unused)),
|
|
size_t component_length MY_ATTRIBUTE((unused)),
|
|
const char *producer MY_ATTRIBUTE((unused)),
|
|
size_t producer_length MY_ATTRIBUTE((unused)),
|
|
const char *message MY_ATTRIBUTE((unused)),
|
|
size_t message_length MY_ATTRIBUTE((unused)),
|
|
mysql_event_message_key_value_t *key_value_map MY_ATTRIBUTE((unused)),
|
|
size_t key_value_map_length MY_ATTRIBUTE((unused)))) {
|
|
return true;
|
|
}
|
|
|
|
DEFINE_METHOD(int, Page_track_implementation::start,
|
|
(MYSQL_THD, Page_Track_SE, uint64_t *)) {
|
|
return (0);
|
|
}
|
|
|
|
DEFINE_METHOD(int, Page_track_implementation::stop,
|
|
(MYSQL_THD, Page_Track_SE, uint64_t *)) {
|
|
return (0);
|
|
}
|
|
|
|
DEFINE_METHOD(int, Page_track_implementation::get_page_ids,
|
|
(MYSQL_THD, Page_Track_SE, uint64_t *, uint64_t *,
|
|
unsigned char *, size_t, Page_Track_Callback, void *)) {
|
|
return (0);
|
|
}
|
|
|
|
DEFINE_METHOD(int, Page_track_implementation::get_num_page_ids,
|
|
(MYSQL_THD, Page_Track_SE, uint64_t *, uint64_t *, uint64_t *)) {
|
|
return (0);
|
|
}
|
|
|
|
DEFINE_METHOD(int, Page_track_implementation::purge,
|
|
(MYSQL_THD, Page_Track_SE, uint64_t *)) {
|
|
return (0);
|
|
}
|
|
|
|
DEFINE_METHOD(int, Page_track_implementation::get_status,
|
|
(MYSQL_THD, Page_Track_SE, uint64_t *, uint64_t *)) {
|
|
return (0);
|
|
}
|
|
|
|
DEFINE_BOOL_METHOD(mysql_keyring_iterator_imp::init,
|
|
(my_h_keyring_iterator * iterator MY_ATTRIBUTE((unused)))) {
|
|
return true;
|
|
}
|
|
|
|
DEFINE_BOOL_METHOD(mysql_keyring_iterator_imp::deinit,
|
|
(my_h_keyring_iterator iterator MY_ATTRIBUTE((unused)))) {
|
|
return true;
|
|
}
|
|
|
|
DEFINE_BOOL_METHOD(mysql_keyring_iterator_imp::get,
|
|
(my_h_keyring_iterator iterator MY_ATTRIBUTE((unused)),
|
|
char *key_id MY_ATTRIBUTE((unused)),
|
|
size_t key_id_size MY_ATTRIBUTE((unused)),
|
|
char *user_id MY_ATTRIBUTE((unused)),
|
|
size_t user_id_size MY_ATTRIBUTE((unused)))) {
|
|
return true;
|
|
}
|
|
|
|
/* TODO following code resembles symbols used in sql library, these should be
|
|
some day extracted to be reused both in sql library and server component unit
|
|
tests. */
|
|
struct CHARSET_INFO;
|
|
|
|
CHARSET_INFO *system_charset_info = &my_charset_latin1;
|
|
|
|
char opt_plugin_dir[FN_REFLEN];
|
|
|
|
bool check_string_char_length(const LEX_CSTRING &, const char *, size_t,
|
|
const CHARSET_INFO *, bool) {
|
|
MY_ASSERT_UNREACHABLE();
|
|
return true;
|
|
}
|
|
|
|
bool check_valid_path(const char *, size_t) {
|
|
MY_ASSERT_UNREACHABLE();
|
|
return true;
|
|
}
|
|
|
|
namespace registry_unittest {
|
|
|
|
using service_type_t = SERVICE_TYPE_NO_CONST(registry);
|
|
|
|
class registry : public ::testing::Test {
|
|
protected:
|
|
virtual void SetUp() { ASSERT_FALSE(mysql_services_bootstrap(®)); }
|
|
|
|
virtual void TearDown() {
|
|
ASSERT_FALSE(reg->release(
|
|
reinterpret_cast<my_h_service>(const_cast<service_type_t *>(reg))));
|
|
shutdown_dynamic_loader();
|
|
ASSERT_FALSE(mysql_services_shutdown());
|
|
}
|
|
SERVICE_TYPE(registry) * reg;
|
|
};
|
|
|
|
TEST_F(registry, bootstrap) { ASSERT_TRUE(reg != NULL); }
|
|
|
|
TEST_F(registry, basic_operations) {
|
|
my_h_service hreg, hreg2;
|
|
|
|
ASSERT_FALSE(reg->acquire("registry", &hreg));
|
|
ASSERT_TRUE(hreg != NULL);
|
|
ASSERT_FALSE(reg->acquire("registry.mysql_server", &hreg2));
|
|
ASSERT_TRUE(hreg == hreg2);
|
|
ASSERT_TRUE(hreg == reinterpret_cast<my_h_service>(
|
|
const_cast<service_type_t *>(reg)));
|
|
ASSERT_FALSE(reg->release(hreg));
|
|
ASSERT_FALSE(reg->release(hreg2));
|
|
ASSERT_TRUE(reg->release(my_h_service{}));
|
|
}
|
|
|
|
TEST_F(registry, register_twice) {
|
|
my_service<SERVICE_TYPE(registry_registration)> registration_service(
|
|
"registry_registration", reg);
|
|
ASSERT_FALSE(registration_service);
|
|
{
|
|
my_service<SERVICE_TYPE(registry)> service("test", reg);
|
|
ASSERT_TRUE(service);
|
|
}
|
|
ASSERT_FALSE(registration_service->register_service(
|
|
"test.test1", reinterpret_cast<my_h_service_imp *>(1)));
|
|
ASSERT_TRUE(registration_service->register_service(
|
|
"test.test1", reinterpret_cast<my_h_service_imp *>(1)));
|
|
{
|
|
my_service<SERVICE_TYPE(registry)> service("test", reg);
|
|
ASSERT_FALSE(service);
|
|
}
|
|
|
|
ASSERT_FALSE(registration_service->unregister("test.test1"));
|
|
{
|
|
my_service<SERVICE_TYPE(registry)> service("test", reg);
|
|
ASSERT_TRUE(service);
|
|
}
|
|
}
|
|
|
|
TEST_F(registry, unregister_activelly_used) {
|
|
my_service<SERVICE_TYPE(registry_registration)> registration_service(
|
|
"registry_registration", reg);
|
|
ASSERT_FALSE(registration_service);
|
|
{
|
|
my_service<SERVICE_TYPE(registry)> service("test", reg);
|
|
ASSERT_TRUE(service);
|
|
}
|
|
ASSERT_FALSE(registration_service->register_service(
|
|
"test.test1", reinterpret_cast<my_h_service_imp *>(1)));
|
|
{
|
|
my_service<SERVICE_TYPE(registry)> service("test", reg);
|
|
ASSERT_FALSE(service);
|
|
ASSERT_TRUE(registration_service->unregister("test.test1"));
|
|
}
|
|
|
|
ASSERT_FALSE(registration_service->unregister("test.test1"));
|
|
{
|
|
my_service<SERVICE_TYPE(registry)> service("test", reg);
|
|
ASSERT_TRUE(service);
|
|
}
|
|
}
|
|
|
|
TEST_F(registry, unregister_non_registered) {
|
|
my_service<SERVICE_TYPE(registry_registration)> registration_service(
|
|
"registry_registration", reg);
|
|
ASSERT_FALSE(registration_service);
|
|
ASSERT_TRUE(registration_service->unregister("test.test1"));
|
|
{
|
|
my_service<SERVICE_TYPE(registry)> service("test", reg);
|
|
ASSERT_TRUE(service);
|
|
}
|
|
}
|
|
|
|
TEST_F(registry, registration_and_default) {
|
|
my_service<SERVICE_TYPE(registry_registration)> registration_service(
|
|
"registry_registration", reg);
|
|
ASSERT_FALSE(registration_service);
|
|
{
|
|
my_service<SERVICE_TYPE(registry)> service("test", reg);
|
|
ASSERT_TRUE(service);
|
|
}
|
|
/* Null interface */
|
|
ASSERT_TRUE(registration_service->register_service("test", my_h_service{}));
|
|
/* Bad name */
|
|
ASSERT_TRUE(registration_service->register_service(
|
|
"test", reinterpret_cast<my_h_service_imp *>(1)));
|
|
ASSERT_TRUE(registration_service->register_service(
|
|
".test", reinterpret_cast<my_h_service_imp *>(1)));
|
|
ASSERT_TRUE(registration_service->register_service(
|
|
"test.", reinterpret_cast<my_h_service_imp *>(1)));
|
|
ASSERT_TRUE(registration_service->register_service(
|
|
"test.test.test", reinterpret_cast<my_h_service_imp *>(1)));
|
|
|
|
ASSERT_FALSE(registration_service->register_service(
|
|
"test.test1", reinterpret_cast<my_h_service_imp *>(1)));
|
|
{
|
|
my_service<SERVICE_TYPE(registry)> service("test", reg);
|
|
ASSERT_FALSE(service);
|
|
ASSERT_EQ(
|
|
static_cast<my_h_service_imp *>(static_cast<my_h_service>(service)),
|
|
reinterpret_cast<my_h_service_imp *>(1));
|
|
}
|
|
ASSERT_FALSE(registration_service->register_service(
|
|
"test.test2", reinterpret_cast<my_h_service_imp *>(2)));
|
|
ASSERT_TRUE(registration_service->register_service(
|
|
"test.test2", reinterpret_cast<my_h_service_imp *>(3)));
|
|
{
|
|
my_service<SERVICE_TYPE(registry)> service("test", reg);
|
|
ASSERT_FALSE(service);
|
|
ASSERT_EQ(
|
|
static_cast<my_h_service_imp *>(static_cast<my_h_service>(service)),
|
|
reinterpret_cast<my_h_service_imp *>(1));
|
|
}
|
|
ASSERT_FALSE(registration_service->set_default("test.test2"));
|
|
ASSERT_TRUE(registration_service->set_default("bad_name.test2"));
|
|
{
|
|
my_service<SERVICE_TYPE(registry)> service("test", reg);
|
|
ASSERT_FALSE(service);
|
|
ASSERT_EQ(
|
|
static_cast<my_h_service_imp *>(static_cast<my_h_service>(service)),
|
|
reinterpret_cast<my_h_service_imp *>(2));
|
|
}
|
|
ASSERT_FALSE(registration_service->unregister("test.test2"));
|
|
{
|
|
my_service<SERVICE_TYPE(registry)> service("test", reg);
|
|
ASSERT_FALSE(service);
|
|
ASSERT_EQ(
|
|
static_cast<my_h_service_imp *>(static_cast<my_h_service>(service)),
|
|
reinterpret_cast<my_h_service_imp *>(1));
|
|
}
|
|
ASSERT_FALSE(registration_service->unregister("test.test1"));
|
|
{
|
|
my_service<SERVICE_TYPE(registry)> service("test", reg);
|
|
ASSERT_TRUE(service);
|
|
}
|
|
}
|
|
TEST_F(registry, my_service) {
|
|
my_h_service hreg;
|
|
ASSERT_FALSE(reg->acquire("registry_query", &hreg));
|
|
ASSERT_TRUE(hreg != NULL);
|
|
|
|
{
|
|
my_service<SERVICE_TYPE(registry_query)> service("registry_query", reg);
|
|
ASSERT_FALSE(service);
|
|
ASSERT_TRUE(hreg == service);
|
|
}
|
|
|
|
ASSERT_FALSE(reg->release(hreg));
|
|
ASSERT_TRUE(reg->release(hreg));
|
|
}
|
|
TEST_F(registry, acquire_related) {
|
|
my_service<SERVICE_TYPE(registry_registration)> registration_service(
|
|
"registry_registration", reg);
|
|
ASSERT_FALSE(registration_service);
|
|
ASSERT_FALSE(registration_service->register_service(
|
|
"test.component1", reinterpret_cast<my_h_service_imp *>(1)));
|
|
ASSERT_FALSE(registration_service->register_service(
|
|
"test.component2", reinterpret_cast<my_h_service_imp *>(2)));
|
|
ASSERT_FALSE(registration_service->register_service(
|
|
"test.component3", reinterpret_cast<my_h_service_imp *>(3)));
|
|
ASSERT_FALSE(registration_service->register_service(
|
|
"another_service.component1", reinterpret_cast<my_h_service_imp *>(11)));
|
|
ASSERT_FALSE(registration_service->register_service(
|
|
"another_service.component2", reinterpret_cast<my_h_service_imp *>(12)));
|
|
|
|
{
|
|
my_service<SERVICE_TYPE(registry)> service1("test", reg);
|
|
ASSERT_FALSE(service1);
|
|
ASSERT_EQ(
|
|
static_cast<my_h_service_imp *>(static_cast<my_h_service>(service1)),
|
|
reinterpret_cast<my_h_service_imp *>(1));
|
|
|
|
my_service<SERVICE_TYPE(registry)> service2("test.component2", reg);
|
|
ASSERT_FALSE(service2);
|
|
ASSERT_EQ(
|
|
static_cast<my_h_service_imp *>(static_cast<my_h_service>(service2)),
|
|
reinterpret_cast<my_h_service_imp *>(2));
|
|
|
|
my_service<SERVICE_TYPE(registry)> service3("test.component3", reg);
|
|
ASSERT_FALSE(service3);
|
|
ASSERT_EQ(
|
|
static_cast<my_h_service_imp *>(static_cast<my_h_service>(service3)),
|
|
reinterpret_cast<my_h_service_imp *>(3));
|
|
|
|
my_service<SERVICE_TYPE(registry)> another_service1("another_service",
|
|
service1, reg);
|
|
ASSERT_FALSE(another_service1);
|
|
ASSERT_EQ(static_cast<my_h_service_imp *>(
|
|
static_cast<my_h_service>(another_service1)),
|
|
reinterpret_cast<my_h_service_imp *>(11));
|
|
|
|
my_service<SERVICE_TYPE(registry)> another_service2("another_service",
|
|
service2, reg);
|
|
ASSERT_FALSE(another_service2);
|
|
ASSERT_EQ(static_cast<my_h_service_imp *>(
|
|
static_cast<my_h_service>(another_service2)),
|
|
reinterpret_cast<my_h_service_imp *>(12));
|
|
|
|
my_service<SERVICE_TYPE(registry)> another_service3("another_service",
|
|
service3, reg);
|
|
ASSERT_FALSE(another_service3);
|
|
ASSERT_EQ(static_cast<my_h_service_imp *>(
|
|
static_cast<my_h_service>(another_service3)),
|
|
reinterpret_cast<my_h_service_imp *>(11));
|
|
}
|
|
|
|
ASSERT_FALSE(registration_service->unregister("test.component1"));
|
|
ASSERT_FALSE(registration_service->unregister("test.component2"));
|
|
ASSERT_FALSE(registration_service->unregister("test.component3"));
|
|
ASSERT_FALSE(registration_service->unregister("another_service.component1"));
|
|
ASSERT_FALSE(registration_service->unregister("another_service.component2"));
|
|
|
|
/* Bad service implementation pointer */
|
|
ASSERT_TRUE(reg->acquire_related("bad_name", my_h_service{}, NULL));
|
|
ASSERT_TRUE(reg->acquire_related(
|
|
"bad_name",
|
|
reinterpret_cast<my_h_service>(const_cast<service_type_t *>(reg)), NULL));
|
|
ASSERT_TRUE(reg->acquire_related(
|
|
"bad_name.with_component",
|
|
reinterpret_cast<my_h_service>(const_cast<service_type_t *>(reg)), NULL));
|
|
|
|
{
|
|
my_service<SERVICE_TYPE(registry)> scheme_file_service(
|
|
"dynamic_loader_scheme_file.mysql_server_path_filter", reg);
|
|
ASSERT_FALSE(scheme_file_service);
|
|
|
|
/*
|
|
No other services implemented with that implementation name, should
|
|
fallback to default.
|
|
*/
|
|
my_service<SERVICE_TYPE(registry)> another_service(
|
|
"registry", scheme_file_service, reg);
|
|
ASSERT_FALSE(another_service);
|
|
ASSERT_EQ(another_service, reg);
|
|
}
|
|
}
|
|
TEST_F(registry, iteration) {
|
|
my_service<SERVICE_TYPE(registry_query)> service("registry_query", reg);
|
|
ASSERT_FALSE(service);
|
|
|
|
my_h_service_iterator iterator;
|
|
const char *name;
|
|
int count = 0;
|
|
bool registrator_found = false;
|
|
|
|
ASSERT_TRUE(service->create("not_existing", &iterator));
|
|
ASSERT_FALSE(service->create("", &iterator));
|
|
|
|
auto guard = create_scope_guard(
|
|
[&service, &iterator]() { service->release(iterator); });
|
|
|
|
service->release(my_h_service_iterator{});
|
|
ASSERT_TRUE(service->get(my_h_service_iterator{}, &name));
|
|
ASSERT_TRUE(service->next(my_h_service_iterator{}));
|
|
ASSERT_TRUE(service->is_valid(my_h_service_iterator{}));
|
|
|
|
for (; !service->is_valid(iterator); service->next(iterator)) {
|
|
ASSERT_FALSE(service->get(iterator, &name));
|
|
|
|
count++;
|
|
registrator_found |= !strcmp(name, "registry_registration.mysql_server");
|
|
}
|
|
ASSERT_TRUE(service->get(iterator, &name));
|
|
ASSERT_TRUE(service->next(iterator));
|
|
ASSERT_TRUE(service->is_valid(iterator));
|
|
|
|
ASSERT_GE(count, 2); /* there should be at least 2 services in registry. */
|
|
ASSERT_TRUE(registrator_found);
|
|
}
|
|
} // namespace registry_unittest
|
|
|
|
/* mandatory main function */
|
|
int main(int argc, char **argv) {
|
|
::testing::InitGoogleTest(&argc, argv);
|
|
return RUN_ALL_TESTS();
|
|
}
|