Files
scylladb/test/boost/service_level_controller_test.cc
Kefu Chai f5b05cf981 treewide: use defaulted operator!=() and operator==()
in C++20, compiler generate operator!=() if the corresponding
operator==() is already defined, the language now understands
that the comparison is symmetric in the new standard.

fortunately, our operator!=() is always equivalent to
`! operator==()`, this matches the behavior of the default
generated operator!=(). so, in this change, all `operator!=`
are removed.

in addition to the defaulted operator!=, C++20 also brings to us
the defaulted operator==() -- it is able to generated the
operator==() if the member-wise lexicographical comparison.
under some circumstances, this is exactly what we need. so,
in this change, if the operator==() is also implemented as
a lexicographical comparison of all memeber variables of the
class/struct in question, it is implemented using the default
generated one by removing its body and mark the function as
`default`. moreover, if the class happen to have other comparison
operators which are implemented using lexicographical comparison,
the default generated `operator<=>` is used in place of
the defaulted `operator==`.

sometimes, we fail to mark the operator== with the `const`
specifier, in this change, to fulfil the need of C++ standard,
and to be more correct, the `const` specifier is added.

also, to generate the defaulted operator==, the operand should
be `const class_name&`, but it is not always the case, in the
class of `version`, we use `version` as the parameter type, to
fulfill the need of the C++ standard, the parameter type is
changed to `const version&` instead. this does not change
the semantic of the comparison operator. and is a more idiomatic
way to pass non-trivial struct as function parameters.

please note, because in C++20, both operator= and operator<=> are
symmetric, some of the operators in `multiprecision` are removed.
they are the symmetric form of the another variant. if they were
not removed, compiler would, for instance, find ambiguous
overloaded operator '=='.

this change is a cleanup to modernize the code base with C++20
features.

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>

Closes #13687
2023-04-27 10:24:46 +03:00

111 lines
3.6 KiB
C++

/*
* Copyright (C) 2021-present ScyllaDB
*/
/*
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
#include <boost/test/unit_test.hpp>
#include <stdlib.h>
#include <iostream>
#include "seastarx.hh"
#include "test/lib/scylla_test_case.hh"
#include <seastar/testing/thread_test_case.hh>
#include <seastar/core/future-util.hh>
#include <algorithm>
#include "service/qos/service_level_controller.hh"
#include "service/qos/qos_configuration_change_subscriber.hh"
#include "auth/service.hh"
#include "utils/overloaded_functor.hh"
using namespace qos;
struct add_op {
sstring name;
service_level_options slo;
bool operator==(const add_op& other) const = default;
};
struct remove_op {
sstring name;
bool operator==(const remove_op& other) const = default;
};
struct change_op {
sstring name;
service_level_options slo_before;
service_level_options slo_after;
bool operator==(const change_op& other) const = default;
};
using service_level_op = std::variant<add_op, remove_op, change_op>;
struct qos_configuration_change_suscriber_simple : public qos_configuration_change_subscriber {
std::vector<service_level_op> ops;
virtual future<> on_before_service_level_add(service_level_options slo, service_level_info sl_info) override {
ops.push_back(add_op{sl_info.name, slo});
return make_ready_future<>();
}
virtual future<> on_after_service_level_remove(service_level_info sl_info) override {
ops.push_back(remove_op{sl_info.name});
return make_ready_future<>();
}
virtual future<> on_before_service_level_change(service_level_options slo_before, service_level_options slo_after, service_level_info sl_info) override {
ops.push_back(change_op{sl_info.name, slo_before, slo_after});
return make_ready_future<>();
}
};
std::ostream& operator<<(std::ostream& os, const add_op& op) {
return os << "Service Level: added '" << op.name << "' with " << op.slo.workload;
}
std::ostream& operator<<(std::ostream& os, const change_op& op) {
return os << "Service Level: changed '" << op.name << "' from " << op.slo_before.workload << " to " << op.slo_after.workload;
}
std::ostream& operator<<(std::ostream& os, const remove_op& op) {
return os << "Service Level: removed '" << op.name << "'";
}
std::ostream& operator<<(std::ostream& os, const service_level_op& op) {
std::visit(overloaded_functor {
[&os] (const add_op& op) { os << op; },
[&os] (const remove_op& op) { os << op; },
[&os] (const change_op& op) { os << op; },
}, op);
return os;
}
SEASTAR_THREAD_TEST_CASE(subscriber_simple) {
sharded<service_level_controller> sl_controller;
sharded<auth::service> auth_service;
sl_controller.start(std::ref(auth_service), service_level_options{}).get();
qos_configuration_change_suscriber_simple ccss;
sl_controller.local().register_subscriber(&ccss);
sl_controller.local().add_service_level("sl1", service_level_options{}).get();
sl_controller.local().add_service_level("sl2", service_level_options{}).get();
service_level_options slo;
slo.workload = service_level_options::workload_type::interactive;
sl_controller.local().add_service_level("sl1", slo).get();
sl_controller.local().remove_service_level("sl2", false).get();
std::vector<service_level_op> expected_result = {
add_op{"sl1", service_level_options{}},
add_op{"sl2", service_level_options{}},
change_op{"sl1", service_level_options{}, slo},
remove_op{"sl2"},
};
sl_controller.local().unregister_subscriber(&ccss).get();
BOOST_REQUIRE_EQUAL(ccss.ops, expected_result);
sl_controller.stop().get();
}