28class ListenerListTests :
public UnitTest
35 explicit TestListener (std::function<
void()> cb) :
callback (std::
move (cb)) {}
43 int getNumCalls()
const {
return numCalls; }
53 void addListener (std::function<
void()> cb)
55 listeners.push_back (std::make_unique<TestListener> (std::move (cb)));
56 listenerList.add (listeners.back().get());
59 void removeListener (
int i) { listenerList.remove (listeners[(
size_t)
i].
get()); }
64 listenerList.call ([] (
auto&
l) {
l.doCallback(); });
68 int getNumListeners()
const {
return (
int) listeners.size(); }
70 auto& getListener (
int i) {
return *listeners[(size_t)
i]; }
72 int getCallLevel()
const
77 bool wereAllNonRemovedListenersCalled (
int numCalls)
const
79 return std::all_of (std::begin (listeners),
83 return (! listenerList.contains (listener.get())) || listener->getNumCalls() == numCalls;
88 std::vector<std::unique_ptr<TestListener>> listeners;
89 ListenerList<TestListener> listenerList;
94 ListenerListTests() : UnitTest (
"ListenerList", UnitTestCategories::containers) {}
96 void runTest()
override
99 beginTest (
"All non-removed listeners should be called - removing an already called listener");
103 for (
int i = 0;
i < 20; ++
i)
108 test.removeListener (6);
112 test.callListeners();
113 expect (
test.wereAllNonRemovedListenersCalled (1));
117 beginTest (
"All non-removed listeners should be called - removing a yet uncalled listener");
121 for (
int i = 0;
i < 20; ++
i)
126 test.removeListener (4);
130 test.callListeners();
131 expect (
test.wereAllNonRemovedListenersCalled (1));
135 beginTest (
"All non-removed listeners should be called - one callback removes multiple listeners");
139 for (
int i = 0;
i < 20; ++
i)
145 test.removeListener (19);
146 test.removeListener (0);
151 test.callListeners();
152 expect (
test.wereAllNonRemovedListenersCalled (1));
155 beginTest (
"All non-removed listeners should be called - removing listeners randomly");
157 auto random = getRandom();
161 const auto numListeners = random.nextInt ({ 10, 100 });
162 const auto listenersThatRemoveListeners = chooseUnique (random,
164 random.nextInt ({ 0, numListeners / 2 }));
167 std::map<int, std::set<int>> removals;
169 for (
auto i : listenersThatRemoveListeners)
172 removals[
i] = chooseUnique (random,
174 random.nextInt ({ 1, std::max (2, numListeners / 10) }));
179 for (
int i = 0;
i < numListeners; ++
i)
183 const auto iter = removals.find (
i);
185 if (iter == removals.end())
188 for (
auto j : iter->second)
190 test.removeListener (
j);
195 test.callListeners();
196 expect (
test.wereAllNonRemovedListenersCalled (1));
201 beginTest (
"All non-removed listeners should be called - add listener during iteration");
204 const auto numStartingListeners = 20;
206 for (
int i = 0;
i < numStartingListeners; ++
i)
210 if (
i == 5 ||
i == 6)
211 test.addListener ([] {});
215 test.callListeners();
220 for (
int i = 0;
i < numStartingListeners; ++
i)
221 success = success &&
test.getListener (
i).getNumCalls() == 1;
224 for (
int i = numStartingListeners;
i <
test.getNumListeners(); ++
i)
225 success = success &&
test.getListener (
i).getNumCalls() == 0;
230 beginTest (
"All non-removed listeners should be called - nested ListenerList::call()");
234 for (
int i = 0;
i < 20; ++
i)
238 const auto callLevel =
test.getCallLevel();
240 if (
i == 6 && callLevel == 1)
242 test.callListeners();
248 test.removeListener (4);
249 else if (callLevel == 2)
250 test.removeListener (6);
255 test.callListeners();
256 expect (
test.wereAllNonRemovedListenersCalled (2));
259 beginTest (
"All non-removed listeners should be called - random ListenerList::call()");
261 const auto numListeners = 20;
262 auto random = getRandom();
269 auto listenersToRemove = chooseUnique (random, numListeners, numListeners / 2);
271 for (
int i = 0;
i < numListeners; ++
i)
274 test.addListener ([&]
276 const auto callLevel =
test.getCallLevel();
278 if (callLevel < 4 && random.nextFloat() < 0.05f)
281 test.callListeners();
284 if (random.nextFloat() < 0.5f)
286 const auto listenerToRemove = random.nextInt ({ 0, numListeners });
288 if (listenersToRemove.erase (listenerToRemove) > 0)
289 test.removeListener (listenerToRemove);
294 while (listenersToRemove.size() > 0)
296 test.callListeners();
300 expect (
test.wereAllNonRemovedListenersCalled (numCalls));
306 static std::set<int> chooseUnique (Random& random,
int max,
int numChosen)
310 while ((
int)
result.size() < numChosen)
311 result.insert (random.nextInt ({ 0, max }));
317static ListenerListTests listenerListTests;
static void run(LV2_Handle instance, uint32_t n_samples)
Definition bindings_test_plugin.c:112
int * l
Definition inflate.c:1579
register unsigned j
Definition inflate.c:1576
register unsigned i
Definition inflate.c:1575
void move(void *from, void *to)
Definition juce_FixedSizeFunction.h:53
auto & get(ProcessorChain< Processors... > &chain) noexcept
Definition juce_ProcessorChain.h:133
Definition carla_juce.cpp:31
#define max(x, y)
Definition os.h:78
static int test(SerdEnv *env, bool top_level, bool pretty_numbers)
Definition sratom_test.c:79
RECT const char void(* callback)(const char *droppath))) SWELL_API_DEFINE(BOOL
Definition swell-functions.h:1004
int result
Definition process.c:1455
#define void
Definition unzip.h:396