MySQL 9.6.0
Source Code Documentation
oom_test.h
Go to the documentation of this file.
1// Copyright (c) 2024, 2025, Oracle and/or its affiliates.
2//
3// This program is free software; you can redistribute it and/or modify
4// it under the terms of the GNU General Public License, version 2.0,
5// as published by the Free Software Foundation.
6//
7// This program is designed to work with certain software (including
8// but not limited to OpenSSL) that is licensed under separate terms,
9// as designated in a particular file or component or in included license
10// documentation. The authors of MySQL hereby grant you an additional
11// permission to link the program and your derivative works with the
12// separately licensed software that they have either included with
13// the program or referenced in the documentation.
14//
15// This program is distributed in the hope that it will be useful,
16// but WITHOUT ANY WARRANTY; without even the implied warranty of
17// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18// GNU General Public License, version 2.0, for more details.
19//
20// You should have received a copy of the GNU General Public License
21// along with this program; if not, write to the Free Software
22// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23
24#ifndef MYSQL_DEBUGGING_OOM_TEST_H
25#define MYSQL_DEBUGGING_OOM_TEST_H
26
27/// @file
28/// Experimental API header
29
30#include <concepts> // invocable
31#include "mysql/allocators/memory_resource.h" // Memory_resource
32#include "mysql/utils/call_and_catch.h" // call_and_catch
33#include "mysql/utils/return_status.h" // Return_status
34
35/// @addtogroup GroupLibsMysqlDebugging
36/// @{
37
38namespace mysql::debugging {
39
40/// Repeatedly call function(). In the Nth iteration, simulate out-of-memory
41/// error on the Nth allocation. Return as soon as it succeeds.
42///
43/// @tparam Initializer_t Type of initialization function.
44///
45/// @tparam Function_t Type of function to call.
46///
47/// @param initialize Function called in each iteration, taking the
48/// Memory_resource object which will later simulate allocation failures as
49/// argument. This may, for instance, create and populate an object that uses
50/// the memory_resource. For the duration of the call to initializer, the
51/// Memory_resource will behave exactly like std::malloc.
52///
53/// @param function Function to test, which should take no parameters. This
54/// function may use the memory_resource that was previously passed to
55/// `initialize`. The Nth time it calls the `allocate` member, `allocate` will
56/// fail. The function is allowed two ways to report error: (1) If it returns
57/// mysql::utils::Return_status, Return_status::ok should indicate success and
58/// Return_status::error indicate out-of-memory. Otherwise, function return
59/// should indicate success and bad_alloc exception should indicate error.
60///
61/// @return The number of iterations until function() succeeded. If function is
62/// deterministic, this equals the number of allocations performed by the call
63/// to function().
64template <std::invocable<mysql::allocators::Memory_resource> Initializer_t,
65 std::invocable Function_t>
66int oom_test(const Initializer_t &initialize, const Function_t &function) {
67 int calls_until_oom{-1};
69 [&](std::size_t size) -> void * {
70 if (calls_until_oom == 0) return nullptr;
71 if (calls_until_oom > 0) --calls_until_oom;
72 return std::malloc(size);
73 },
74 std::free);
75 for (int i = 0; true; ++i) {
76 calls_until_oom = -1;
77 initialize(memory_resource);
78 calls_until_oom = i;
79 if (mysql::utils::call_and_catch(function) ==
81 return i;
82 }
83}
84
85/// Repeatedly construct copies of object and call function(copy). In the Nth
86/// iteration, simulate out-of-memory error on the Nth allocation. Return as
87/// soon as it succeeds.
88///
89/// @tparam Object_t Type of the object. This must have a constructor taking
90/// `(const Object_t& , Memory_resource)` parameters.
91///
92/// @param object Object to test.
93///
94/// @param function Function to test, which should take an Object& as its only
95/// parameter. This function may use the memory_resource that was previously
96/// passed to `initialize`. The Nth time it calls the `allocate` member,
97/// `allocate` will fail. The function is allowed two ways to report error: (1)
98/// If it returns mysql::utils::Return_status, Return_status::ok should indicate
99/// success and Return_status::error indicate out-of-memory. Otherwise, function
100/// return should indicate success and bad_alloc exception should indicate
101/// error.
102///
103/// @return The number of iterations until function(copy) succeeded. If function
104/// is deterministic, this equals the number of allocations performed by the
105/// call to function(copy).
106template <class Object_t>
107int oom_test_copyable_object(const Object_t &object,
108 std::invocable<Object_t &> auto function) {
109 Object_t copy{};
110 return oom_test(
111 [&](const mysql::allocators::Memory_resource &memory_resource) {
112 copy = std::move(Object_t(object, memory_resource));
113 },
114 [&] { return function(copy); });
115}
116
117/// Repeatedly construct copies of `object` and call `function(copy)`. In the
118/// Nth iteration, simulate out-of-memory error on the Nth allocation. Return as
119/// soon as it succeeds.
120///
121/// This is intended for use with non-throwing containers which do not have a
122/// copy constructor.
123///
124/// @tparam Object_t Type of the object. This must have a constructor taking a
125/// `Memory_resource` as parameter, and a member function `assign` taking
126/// another `Object_t` as argument. The `assign` member must not replace the
127/// memory resource used by the object to allocate.
128///
129/// @param object Object to test.
130///
131/// @param function Function to test, which should take an Object& as its only
132/// parameter. This function may use the memory_resource that was previously
133/// passed to `initialize`. The Nth time it calls the `allocate` member,
134/// `allocate` will fail. The function is allowed two ways to report error: (1)
135/// If it returns mysql::utils::Return_status, Return_status::ok should indicate
136/// success and Return_status::error indicate out-of-memory. Otherwise, function
137/// return should indicate success and bad_alloc exception should indicate
138/// error.
139///
140/// @return The number of iterations until function(copy) succeeded. If function
141/// is deterministic, this equals the number of allocations performed by the
142/// call to function(copy).
143template <class Object_t>
144int oom_test_assignable_object(const Object_t &object,
145 std::invocable<Object_t &> auto function) {
146 Object_t copy{};
147 return oom_test(
148 [&](const mysql::allocators::Memory_resource &memory_resource) {
149 // Move-assign empty object with the given Memory_resource
150 auto o = Object_t(memory_resource);
151 copy.assign(std::move(o));
152 // Copy-assign the contents.
153 [[maybe_unused]] auto ret = copy.assign(object);
154 // As this is for testing only, fail with assertion if out-of-memory
155 // occurred in this initialization function.
156 assert(ret == mysql::utils::Return_status::ok);
157 },
158 [&] { return function(copy); });
159}
160
161} // namespace mysql::debugging
162
163// addtogroup GroupLibsMysqlDebugging
164/// @}
165
166#endif // ifndef MYSQL_DEBUGGING_OOM_TEST_H
Experimental API header.
Polymorphism-free memory resource class with custom allocator and deallocator functions.
Definition: memory_resource.h:88
#define malloc(A)
Definition: lexyy.cc:914
#define free(A)
Definition: lexyy.cc:915
Class that wraps resources in a polymorphic manner.
void copy(Shards< COUNT > &dst, const Shards< COUNT > &src) noexcept
Copy the counters, overwrite destination.
Definition: ut0counter.h:354
MYSQL_STRINGS_EXPORT void initialize(const char *charset_dir=nullptr, MY_CHARSET_LOADER *loader=nullptr)
Initialize character set/collation library.
Definition: collations.cc:60
Definition: object_lifetime_tracker.h:37
int oom_test_copyable_object(const Object_t &object, std::invocable< Object_t & > auto function)
Repeatedly construct copies of object and call function(copy).
Definition: oom_test.h:107
int oom_test(const Initializer_t &initialize, const Function_t &function)
Repeatedly call function().
Definition: oom_test.h:66
int oom_test_assignable_object(const Object_t &object, std::invocable< Object_t & > auto function)
Repeatedly construct copies of object and call function(copy).
Definition: oom_test.h:144
@ ok
operation succeeded
size_t size(const char *const c)
Definition: base64.h:46
Experimental API header.