You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
srsRAN_4G/lib/test/adt/observer_test.cc

260 lines
6.8 KiB
C++

/**
* Copyright 2013-2023 Software Radio Systems Limited
*
* This file is part of srsRAN.
*
* srsRAN is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsRAN 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 Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include "srsran/adt/observer.h"
#include "srsran/common/test_common.h"
static_assert(srsran::is_observer<srsran::observer<int> >::value, "is_observer<> meta-function failed");
static_assert(not srsran::is_observer<std::function<void(int)> >::value, "is_observer<> meta-function failed");
struct M {
M() = default;
explicit M(int v) : val(v) {}
M(M&&) noexcept = default;
M(const M&) = delete;
M& operator=(M&&) noexcept = default;
M& operator=(const M&) = delete;
M& operator+=(int i)
{
val += i;
return *this;
}
int val = 0;
};
struct lval_observer_tester {
void trigger(M v_) { v = std::move(v_); }
void foo(M v_)
{
v = std::move(v_);
v += 1;
}
M v;
};
struct cref_observer_tester {
void trigger(const M& v_) { v.val = v_.val; }
void foo(const M& v_) { v.val = v_.val + 1; }
M v;
};
struct lref_observer_tester {
void trigger(M& v_) { v.val = v_.val; }
void foo(M& v_) { v.val = v_.val + 1; }
M v;
};
struct rref_observer_tester {
void trigger(M&& v_) { v = std::move(v_); }
void foo(M&& v_)
{
v = std::move(v_);
v += 1;
}
M v;
};
int observable_test()
{
// TEST l-value arguments passed by value
{
M val;
srsran::observable<M> subject;
TESTASSERT(subject.nof_observers() == 0);
srsran::observer_id id1 = subject.subscribe([&val](M v) { val = std::move(v); });
lval_observer_tester observer{}, observer2{};
srsran::observer_id id2 = subject.subscribe(observer);
srsran::observer_id id3 = subject.subscribe(observer2, &lval_observer_tester::foo);
TESTASSERT(subject.nof_observers() == 3);
TESTASSERT(val.val == 0);
subject.dispatch(M{5});
TESTASSERT(val.val == 5);
TESTASSERT(observer.v.val == 5);
TESTASSERT(observer2.v.val == 6);
subject.unsubscribe(id1);
TESTASSERT(subject.nof_observers() == 2);
subject.unsubscribe(id2);
TESTASSERT(subject.nof_observers() == 1);
subject.unsubscribe(id3);
TESTASSERT(subject.nof_observers() == 0);
}
// Test l-value arguments passed by const ref
{
M val;
srsran::observable<const M&> subject;
TESTASSERT(subject.nof_observers() == 0);
subject.subscribe([&val](const M& v) { val.val = v.val; });
cref_observer_tester observer{}, observer2{};
subject.subscribe(observer);
subject.subscribe(observer2, &cref_observer_tester::foo);
M new_val{6};
subject.dispatch(new_val);
TESTASSERT(val.val == 6);
TESTASSERT(observer.v.val == 6);
TESTASSERT(observer2.v.val == 7);
}
// Test l-value arguments passed by ref
{
M val;
srsran::observable<M&> subject;
TESTASSERT(subject.nof_observers() == 0);
subject.subscribe([&val](M& v) { val = std::move(v); });
lref_observer_tester observer{}, observer2{};
subject.subscribe(observer);
subject.subscribe(observer2, &lref_observer_tester::foo);
M new_val{6};
subject.dispatch(new_val);
TESTASSERT(val.val == 6);
TESTASSERT(observer.v.val == 6);
TESTASSERT(observer2.v.val == 7);
}
// Test r-value arguments
{
M val;
srsran::observable<M&&> subject;
TESTASSERT(subject.nof_observers() == 0);
srsran::observer_id id1 = subject.subscribe([&val](M&& v) { val = std::move(v); });
rref_observer_tester observer{}, observer2{};
srsran::observer_id id2 = subject.subscribe(observer);
srsran::observer_id id3 = subject.subscribe(observer2, &rref_observer_tester::foo);
subject.dispatch(M{3});
TESTASSERT(val.val == 3);
TESTASSERT(observer.v.val == 3);
TESTASSERT(observer2.v.val == 4);
subject.unsubscribe(id1);
subject.unsubscribe(id2);
subject.unsubscribe(id3);
TESTASSERT(subject.nof_observers() == 0);
}
return SRSRAN_SUCCESS;
}
int event_dispatcher_test()
{
srsran::event_dispatcher<M> signaller;
M val;
signaller.subscribe([&val](const M& ev) { val.val = ev.val; });
cref_observer_tester observer, observer2;
signaller.subscribe(observer);
signaller.subscribe(observer2, &cref_observer_tester::foo);
TESTASSERT(val.val == 0);
TESTASSERT(observer.v.val == 0);
TESTASSERT(observer2.v.val == 0);
signaller.dispatch(M{2});
TESTASSERT(val.val == 2);
TESTASSERT(observer.v.val == 2);
TESTASSERT(observer2.v.val == 3);
val.val = 1;
observer.v.val = 0;
observer2.v.val = 5;
signaller.dispatch(M{2});
TESTASSERT(val.val == 2);
TESTASSERT(observer.v.val == 2);
TESTASSERT(observer2.v.val == 3);
return SRSRAN_SUCCESS;
}
int event_queue_test()
{
srsran::event_queue<M> signaller;
M val;
signaller.subscribe([&val](const M& ev) { val.val = ev.val; });
cref_observer_tester observer, observer2;
signaller.subscribe(observer);
signaller.subscribe(observer2, &cref_observer_tester::foo);
TESTASSERT(val.val == 0);
TESTASSERT(observer.v.val == 0);
TESTASSERT(observer2.v.val == 0);
signaller.enqueue(M{2});
TESTASSERT(val.val == 0);
TESTASSERT(observer.v.val == 0);
TESTASSERT(observer2.v.val == 0);
signaller.process();
TESTASSERT(val.val == 2);
TESTASSERT(observer.v.val == 2);
TESTASSERT(observer2.v.val == 3);
return SRSRAN_SUCCESS;
}
int unique_subscribe_test()
{
{
srsran::event_dispatcher<M> signaller;
cref_observer_tester observer;
TESTASSERT(signaller.nof_observers() == 0);
{
srsran::unique_observer_id<M> obs{signaller, observer};
TESTASSERT(signaller.nof_observers() == 1);
}
TESTASSERT(signaller.nof_observers() == 0);
}
{
srsran::event_queue<M> signaller;
cref_observer_tester observer;
TESTASSERT(signaller.nof_observers() == 0);
{
srsran::unique_observer_id<M> obs{signaller, observer};
TESTASSERT(signaller.nof_observers() == 1);
}
TESTASSERT(signaller.nof_observers() == 0);
}
return SRSRAN_SUCCESS;
}
int main()
{
TESTASSERT(observable_test() == SRSRAN_SUCCESS);
TESTASSERT(event_dispatcher_test() == SRSRAN_SUCCESS);
TESTASSERT(event_queue_test() == SRSRAN_SUCCESS);
TESTASSERT(unique_subscribe_test() == SRSRAN_SUCCESS);
printf("Success\n");
return 0;
}