summaryrefslogtreecommitdiffstats
path: root/src/lib/netlist/tests/test_pmfp_multibase.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/netlist/tests/test_pmfp_multibase.cpp')
-rw-r--r--src/lib/netlist/tests/test_pmfp_multibase.cpp360
1 files changed, 360 insertions, 0 deletions
diff --git a/src/lib/netlist/tests/test_pmfp_multibase.cpp b/src/lib/netlist/tests/test_pmfp_multibase.cpp
new file mode 100644
index 00000000000..20a1fc9aba8
--- /dev/null
+++ b/src/lib/netlist/tests/test_pmfp_multibase.cpp
@@ -0,0 +1,360 @@
+// license:BSD-3-Clause
+// copyright-holders:Couriersud
+
+///
+/// \file test_pmfp_multibase.cpp
+///
+/// tests for plib::pmfp
+///
+
+#include "plib/ptypes.h"
+#include "plib/pexception.h"
+#include "plib/ppmf.h"
+
+#include <utility>
+#include <memory>
+#include <type_traits>
+#include <typeinfo>
+#include <iostream>
+
+template <class F, class S>
+typename std::enable_if_t<!plib::has_ostream_operator<std::basic_ostream<char>, std::pair<F, S>>::value, std::basic_ostream<char>&>
+operator << (std::basic_ostream<char>& os, const std::pair<F, S> &p)
+{
+ os << "{ " << p.first << ", " << p.second << " }";
+ return os;
+}
+
+#include "plib/ptests.h"
+
+template <class T>
+typename std::enable_if_t<!plib::has_ostream_operator<std::basic_ostream<char>, T>::value, std::basic_ostream<char>&>
+operator << (std::basic_ostream<char>& os, const T &p)
+{
+ plib::unused_var(p);
+ os << std::string(typeid(T).name());
+ return os;
+}
+
+class pmfp_test_complex_return : public plib::testing::Test
+{
+protected:
+ using ret_t = std::pair<void *, int>;
+
+ //using test_delegate1 = plib::pmfp<ret_t (int, int)>;
+ using test_delegate = plib::pmfp<ret_t ()>;
+
+ class a
+ {
+ public:
+ ret_t ap() { return ret_t(static_cast<void *>(this), ax); }
+ int ax;
+ };
+
+ class b
+ {
+ public:
+ ret_t bp() { return ret_t(static_cast<void *>(this), bx); }
+ int bx;
+ };
+
+ class multibase : public a, public b
+ {
+ public:
+ };
+
+
+ class vtb
+ {
+ public:
+ virtual ~vtb() = default;
+ virtual ret_t vp1() { return ret_t(static_cast<void *>(this), 1); }
+ virtual ret_t vp2() { return ret_t(static_cast<void *>(this), 2); }
+ };
+
+ class vti1 : public vtb
+ {
+ public:
+ virtual ret_t vp1() override { return ret_t(static_cast<void *>(this), 3); }
+ virtual ret_t vp2() override { return ret_t(static_cast<void *>(this), 4); }
+ };
+
+ class vti2 : public a, public vtb
+ {
+ public:
+ virtual ret_t vp1() override { return ret_t(static_cast<void *>(this), 13); }
+ virtual ret_t vp2() override { return ret_t(static_cast<void *>(this), 14); }
+ };
+
+ class forward;
+
+ test_delegate make_forward_delegate(ret_t (forward::*func)(), forward *obj)
+ {
+ return test_delegate(func, obj);
+ }
+
+ class vb
+ {
+ public:
+ ret_t xp() { return ret_t(static_cast<void *>(this), x); }
+ int x=10;
+ };
+
+ class vd1 : public virtual vb
+ {
+ public:
+ ret_t yp() { return ret_t(static_cast<void *>(this), y); }
+ int y;
+ };
+
+ class vd2 : public virtual vb
+ {
+ public:
+ ret_t zp() { return ret_t(static_cast<void *>(this), z); }
+ int z;
+ };
+
+ class forward : public vd1, public vd2
+ {
+ public:
+ };
+
+};
+
+class pmfp_test_simple_return : public plib::testing::Test
+{
+protected:
+ using ret_t = std::pair<void *, int>;
+
+ //using test_delegate1 = plib::pmfp<ret_t (int, int)>;
+ using test_delegate = plib::pmfp<void (ret_t &)>;
+
+ class a
+ {
+ public:
+ void ap(ret_t &r) { r = ret_t(static_cast<void *>(this), ax); }
+ int ax;
+ };
+
+ class b
+ {
+ public:
+ void bp(ret_t &r) { r = ret_t(static_cast<void *>(this), bx); }
+ int bx;
+ };
+
+ class multibase : public a, public b
+ {
+ public:
+ };
+
+
+ class vtb
+ {
+ public:
+ virtual ~vtb() = default;
+ virtual void vp1(ret_t &r) { r = ret_t(static_cast<void *>(this), 1); }
+ virtual void vp2(ret_t &r) { r = ret_t(static_cast<void *>(this), 2); }
+ };
+
+ class vti1 : public vtb
+ {
+ public:
+ virtual void vp1(ret_t &r) override { r = ret_t(static_cast<void *>(this), 3); }
+ virtual void vp2(ret_t &r) override { r = ret_t(static_cast<void *>(this), 4); }
+ };
+
+ class vti2 : public a, public vtb
+ {
+ public:
+ virtual void vp1(ret_t &r) override { r = ret_t(static_cast<void *>(this), 13); }
+ virtual void vp2(ret_t &r) override { r = ret_t(static_cast<void *>(this), 14); }
+ };
+
+ class forward;
+
+ test_delegate make_forward_delegate(void (forward::*func)(ret_t &), forward *obj)
+ {
+ return test_delegate(func, obj);
+ }
+
+ class vb
+ {
+ public:
+ void xp(ret_t &r) { r = ret_t(static_cast<void *>(this), x); }
+ int x=10;
+ };
+
+ class vd1 : public virtual vb
+ {
+ public:
+ void yp(ret_t &r) { r = ret_t(static_cast<void *>(this), y); }
+ int y;
+ };
+
+ class vd2 : public virtual vb
+ {
+ public:
+ void zp(ret_t &r) { r = ret_t(static_cast<void *>(this), z); }
+ int z;
+ };
+
+ class forward : public vd1, public vd2
+ {
+ public:
+ };
+};
+
+PTEST_F(pmfp_test_complex_return, multibase_test)
+{
+ multibase obj;
+ obj.ax = 1;
+ obj.bx = 2;
+ test_delegate f(&multibase::ap, &obj);
+ test_delegate g(&multibase::bp, &obj);
+
+ // a=0x63fbf8
+ // b=0x63fbfc
+ // a=0x63fbf8(1)
+ // b=0x63fbfc(2)
+ // b=0x63fbfc(2)
+ // b=0x63fbfc(2)
+ PEXPECT_EQ(f(), ret_t(static_cast<void *>(static_cast<a *>(&obj)), 1));
+ auto g_ret = g();
+ PEXPECT_EQ(g_ret, ret_t(static_cast<void *>(static_cast<b *>(&obj)), 2));
+
+ test_delegate h = g;
+ PEXPECT_EQ(g_ret, h());
+ f = g;
+ PEXPECT_EQ(g_ret, f());
+
+ //vti1=0xdf6fb0.vp1
+ //vti1=0xdf6fb0.vp2
+
+ std::unique_ptr<vtb> ptr;
+ ptr.reset(new vti1);
+ f = test_delegate(&vtb::vp1, ptr.get());
+ auto f1_ret = f();
+ f = test_delegate(&vtb::vp2, ptr.get());
+ auto f2_ret = f();
+ PEXPECT_EQ(f1_ret.first, f2_ret.first);
+ PEXPECT_EQ(f1_ret.second, 3);
+ PEXPECT_EQ(f2_ret.second, 4);
+
+ // vti2=0xdf6d50.vp1
+ // vti2=0xdf6d50.vp2
+ ptr.reset(new vti2);
+ f = test_delegate(&vtb::vp1, ptr.get());
+ f1_ret = f();
+ f = test_delegate(&vtb::vp2, ptr.get());
+ f2_ret = f();
+ PEXPECT_EQ(f1_ret.first, f2_ret.first);
+ PEXPECT_EQ(f1_ret.second, 13);
+ PEXPECT_EQ(f2_ret.second, 14);
+
+ //vb=0x63fafc
+ //vd1=0x63fae0
+ //vd2=0x63faf0
+ //vd1=0x63fae0(8)
+ //vd2=0x63faf0(9)
+
+ forward obj2;
+ obj2.x = 7;
+ obj2.y = 8;
+ obj2.z = 9;
+ PEXPECT_NE(static_cast<void *>(static_cast<vb *>(&obj2)), static_cast<void *>(static_cast<vd1 *>(&obj2)));
+ PEXPECT_NE(static_cast<void *>(static_cast<vb *>(&obj2)), static_cast<void *>(static_cast<vd2 *>(&obj2)));
+
+#if defined(_MSC_VER) && !defined(__clang__)
+ f = make_forward_delegate(&forward::xp, &obj2);
+ PEXPECT_TRUE(f().second == 7);
+ std::cout << f().second << " " << obj2.xp().second << "\n";
+#endif
+ f = make_forward_delegate(&forward::yp, &obj2);
+ PEXPECT_EQ(f().second, 8);
+ f = make_forward_delegate(&forward::zp, &obj2);
+ PEXPECT_EQ(f().second, 9);
+}
+
+PTEST_F(pmfp_test_simple_return, multibase_test)
+{
+ multibase obj;
+ obj.ax = 1;
+ obj.bx = 2;
+ test_delegate f(&multibase::ap, &obj);
+ test_delegate g(&multibase::bp, &obj);
+
+ // a=0x63fbf8
+ // b=0x63fbfc
+ // a=0x63fbf8(1)
+ // b=0x63fbfc(2)
+ // b=0x63fbfc(2)
+ // b=0x63fbfc(2)
+ ret_t fr;
+ f(fr);
+ PEXPECT_EQ(fr, ret_t(static_cast<void *>(static_cast<a *>(&obj)), 1));
+ ret_t gr;
+ g(gr);
+ PEXPECT_EQ(gr, ret_t(static_cast<void *>(static_cast<b *>(&obj)), 2));
+ //PEXPECT_EQ(f, g);
+
+ test_delegate h = g;
+ ret_t hr;
+ h(hr);
+ PEXPECT_EQ(gr, hr);
+ f = g;
+ f(fr);
+ PEXPECT_EQ(gr, fr);
+
+ //vti1=0xdf6fb0.vp1
+ //vti1=0xdf6fb0.vp2
+
+ std::unique_ptr<vtb> ptr;
+ ptr.reset(new vti1);
+ f = test_delegate(&vtb::vp1, ptr.get());
+ ret_t f1_ret;
+ f(f1_ret);
+ f = test_delegate(&vtb::vp2, ptr.get());
+ ret_t f2_ret;
+ f(f2_ret);
+ PEXPECT_EQ(f1_ret.first, f2_ret.first);
+ PEXPECT_EQ(f1_ret.second, 3);
+ PEXPECT_EQ(f2_ret.second, 4);
+
+ // vti2=0xdf6d50.vp1
+ // vti2=0xdf6d50.vp2
+ ptr.reset(new vti2);
+ f = test_delegate(&vtb::vp1, ptr.get());
+ f(f1_ret);
+ f = test_delegate(&vtb::vp2, ptr.get());
+ f(f2_ret);
+ PEXPECT_EQ(f1_ret.first, f2_ret.first);
+ PEXPECT_EQ(f1_ret.second, 13);
+ PEXPECT_EQ(f2_ret.second, 14);
+
+ //vb=0x63fafc
+ //vd1=0x63fae0
+ //vd2=0x63faf0
+ //vd1=0x63fae0(8)
+ //vd2=0x63faf0(9)
+
+ forward obj2;
+ obj2.x = 7;
+ obj2.y = 8;
+ obj2.z = 9;
+ PEXPECT_NE(static_cast<void *>(static_cast<vb *>(&obj2)), static_cast<void *>(static_cast<vd1 *>(&obj2)));
+ PEXPECT_NE(static_cast<void *>(static_cast<vb *>(&obj2)), static_cast<void *>(static_cast<vd2 *>(&obj2)));
+
+#if defined(_MSC_VER) && !defined(__clang__)
+ f = make_forward_delegate(&forward::xp, &obj2);
+ f(fr);
+ PEXPECT_TRUE(fr.second == 7);
+ std::cout << fr.second << "\n";
+#endif
+ f = make_forward_delegate(&forward::yp, &obj2);
+ f(fr);
+ PEXPECT_EQ(fr.second, 8);
+ f = make_forward_delegate(&forward::zp, &obj2);
+ f(fr);
+ PEXPECT_EQ(fr.second, 9);
+}