summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib/netlist/tests
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/netlist/tests')
-rw-r--r--src/lib/netlist/tests/test_penum.cpp254
-rw-r--r--src/lib/netlist/tests/test_pfunction.cpp60
-rw-r--r--src/lib/netlist/tests/test_pmfp.cpp77
-rw-r--r--src/lib/netlist/tests/test_pmfp_multibase.cpp451
-rw-r--r--src/lib/netlist/tests/test_precommit.cpp27
-rw-r--r--src/lib/netlist/tests/test_pstring.cpp19
6 files changed, 888 insertions, 0 deletions
diff --git a/src/lib/netlist/tests/test_penum.cpp b/src/lib/netlist/tests/test_penum.cpp
new file mode 100644
index 00000000000..6347a41d027
--- /dev/null
+++ b/src/lib/netlist/tests/test_penum.cpp
@@ -0,0 +1,254 @@
+// license:BSD-3-Clause
+// copyright-holders:Couriersud
+
+///
+/// \file test_penum.cpp
+///
+/// tests for penum
+///
+
+#include "plib/putil.h"
+
+#include "plib/pexception.h"
+#include "plib/pstring.h"
+
+#include <string>
+#include <type_traits>
+#include <string_view>
+
+#if 0
+namespace plib
+{
+ template <typename E>
+ struct functor { using is_defined = std::false_type; };
+ template <std::size_t N, typename E>
+ struct functor_base
+ {
+ public:
+ using is_defined = std::true_type;
+ using size = std::integral_constant<std::size_t, N>;
+ constexpr operator E () const noexcept { return m_v; }
+ constexpr functor_base(const E v) noexcept : m_v(v) { };
+ protected:
+ constexpr functor_base(const char *s, const char * const vals[size::value]) noexcept : m_v(E::PENUM_UNKNOWN)
+ { for (std::size_t i = 0; i < size::value; i++) if (vals[i] == s) { m_v = static_cast<E>(i); return; } }
+ E m_v;
+ private:
+ //static constexpr const char *m_str[PNARGS(__VA_ARGS__)] = { PSTRINGIFY_VA(__VA_ARGS__) };
+ };
+
+} // namespace plib
+
+#define PENUM(ename, ...) \
+ enum class ename { __VA_ARGS__ , PENUM_UNKNOWN }; \
+ PENUM_FUNCTOR(ename, __VA_ARGS__)
+
+#define PENUM_NS(ns, ename, ...) \
+ namespace ns { enum class ename { __VA_ARGS__ , PENUM_UNKNOWN }; } \
+ PENUM_FUNCTOR(ns :: ename, __VA_ARGS__)
+
+#define PENUM_FUNCTOR(ename, ...) \
+ template <> struct plib::functor<ename> : plib::functor_base<PNARGS(__VA_ARGS__), ename> \
+ { \
+ public: \
+ using plib::functor_base<size::value, ename>::functor_base; \
+ constexpr functor(const char *s) noexcept : functor_base(s, m_str) { } \
+ constexpr operator const char * () const noexcept { return m_str[static_cast<std::size_t>(m_v)]; } \
+ private: \
+ static constexpr const char *m_str[3] = { PSTRINGIFY_VA(__VA_ARGS__) }; \
+ };
+
+#else
+#if 1
+namespace plib::enum_static
+{
+ template <typename E>
+ struct functor_static
+ {
+ using is_defined = std::false_type;
+ using size = std::integral_constant<std::size_t, 0>;
+ static constexpr const char *m_str[1] = { "" };
+ };
+} // namespace plib::enum_static
+
+#endif
+namespace plib
+{
+ template <typename E>
+ struct functor
+ {
+ public:
+ using staticf = enum_static::functor_static<E>;
+ using is_defined = typename staticf::is_defined;
+ using size = typename staticf::size;
+ constexpr functor(const E v) noexcept : m_v(v) { }
+ constexpr functor(const char *s) noexcept : m_v(E::PENUM_UNKNOWN)
+ {
+ for (std::size_t i = 0; i < size::value; i++)
+ if (staticf::m_str[i] == s)
+ {
+ m_v = static_cast<E>(i);
+ return;
+ }
+ }
+ constexpr operator const char * () const noexcept { return staticf::m_str[static_cast<std::size_t>(m_v)]; }
+ constexpr operator E () const noexcept { return m_v; }
+ protected:
+ E m_v;
+ private:
+ //static constexpr const char *m_str[PNARGS(__VA_ARGS__)] = { PSTRINGIFY_VA(__VA_ARGS__) };
+ };
+
+ // template deduction guide
+ template<typename E> functor(E) -> functor<E>;
+
+ template<typename E>
+ static inline typename std::enable_if<plib::enum_static::functor_static<E>::is_defined::value, const char *>::type
+ penum_to_string(E e)
+ {
+ using staticf = enum_static::functor_static<E>;
+ return staticf::m_str[static_cast<std::size_t>(e)];
+ }
+
+ template<typename E>
+ static inline typename std::enable_if<plib::enum_static::functor_static<E>::is_defined::value, E>::type
+ string_to_penum(const char *s)
+ {
+ using staticf = enum_static::functor_static<E>;
+ for (std::size_t i = 0; i < staticf::size::value; i++)
+ if (staticf::m_str[i] == s)
+ return static_cast<E>(i);
+ return E::PENUM_UNKNOWN;
+ }
+
+} // namespace plib
+
+#define PENUM(ename, ...) \
+ enum class ename { __VA_ARGS__ , PENUM_UNKNOWN }; \
+ PENUM_FUNCTOR(ename, __VA_ARGS__)
+
+#define PENUM_NS(ns, ename, ...) \
+ namespace ns { enum class ename { __VA_ARGS__ , PENUM_UNKNOWN }; } \
+ PENUM_FUNCTOR(ns :: ename, __VA_ARGS__)
+
+#define PENUM_FUNCTOR(ename, ...) \
+ namespace plib::enum_static { \
+ template <> struct functor_static<ename> \
+ { \
+ public: \
+ using is_defined = std::true_type; \
+ using size = std::integral_constant<std::size_t, PNARGS(__VA_ARGS__) >; \
+ static constexpr const char *m_str[size::value] = { PSTRINGIFY_VA(__VA_ARGS__) }; \
+ }; \
+ } // namespace plib::enum_static
+
+#endif
+
+template <class O, class E>
+typename std::enable_if<!plib::has_ostream_operator<O, E>::value && plib::enum_static::functor_static<E>::is_defined::value, O&>::type
+operator << (O& os, const E &p)
+{
+ os << static_cast<const char *>(plib::functor<E>(p));
+ return os;
+}
+
+#if 1
+template <typename E>
+inline typename std::enable_if<plib::enum_static::functor_static<E>::is_defined::value, bool>::type
+operator == (const char * lhs, const E &rhs)
+{
+ return lhs == plib::functor<E>(rhs);
+}
+template <typename E>
+inline typename std::enable_if<plib::enum_static::functor_static<E>::is_defined::value, bool>::type
+operator == (const E &lhs, const char * rhs)
+{
+ return lhs == plib::functor<E>(rhs);
+}
+#endif
+
+// ---------------------------------------
+
+template <typename T>
+struct ret_t
+{
+ bool success;
+ T value;
+};
+
+template <typename T, T BASE>
+constexpr ret_t<T> stl_h(std::string_view sv)
+{
+ T r(0);
+ for (const auto &c : sv)
+ {
+ if (c >= '0' && c < '0' + std::min(10,BASE))
+ {
+ r = r * BASE + (c - '0');
+ }
+ else if (c >= 'A' && c < ('A' + BASE - 10))
+ {
+ r = r * BASE + (10 + c - 'A');
+ }
+ else if (c >= 'a' && c < ('a' + BASE - 10))
+ {
+ r = r * BASE + (10 + c - 'a');
+ }
+ else
+ return { false, T(0) };
+ }
+ return { true, r };
+}
+
+template <typename T, T BASE = 0>
+constexpr ret_t<T> stl(std::string_view sv)
+{
+ if constexpr (BASE == 0)
+ {
+ if (sv.size() > 2)
+ {
+ if (sv.substr(0,2) == "0x" || sv.substr(0,2) == "0X")
+ return stl_h<T,16>(sv.substr(2));
+ if (sv.substr(0,2) == "0b")
+ return stl_h<T,2>(sv.substr(2));
+ }
+ if (sv.size() > 1 && sv.substr(0,1) == "0" )
+ return stl_h<T,8>(sv.substr(1));
+ return stl_h<T, 10>(sv);
+ }
+ return stl_h<T, BASE>(sv);
+}
+
+#include "plib/ptests.h"
+
+//PENUM_NS(plibx, teste, A, B, C)
+
+namespace plibx { enum class teste; }
+PENUM(plibx::teste, A, B, C)
+
+enum class pure { X, Y };
+
+PENUM(testf, A, B, C)
+
+PTEST(penum, conversion)
+{
+ static_assert(stl<int,0>("0xa0bc").success,"no");
+ static_assert(stl<int,0>("0xa0bc").value==0xa0bc,"no");
+ static_assert(stl<int,0>("0b1010").value==0b1010,"no");
+ static_assert(stl<int,0>("0123").value==0123,"no");
+ //const auto x(stl<int,0>("123"));
+ //static_assert(x.value==123,"no");
+
+ plibx::teste x = plib::functor<plibx::teste>("A");
+ PEXPECT_NE(x, plibx::teste::B);
+ PEXPECT_NE(plib::functor<plibx::teste>("A"), plibx::teste::B);
+ PEXPECT_NE(plib::functor<testf>("A"), testf::B);
+ //PEXPECT_EQ(plib::functor("A"), testf::B);
+ PEXPECT_EQ(testf::B, "B");
+ PEXPECT_EQ("A", testf::A);
+ PEXPECT_NE(plib::functor(testf::A), "B");
+ PEXPECT_FALSE(plib::functor<pure>::is_defined::value);
+ PEXPECT_EQ(plib::penum_to_string(testf::B), "B");
+ PEXPECT_NE(plib::string_to_penum<testf>("B"), testf::A);
+ //PEXPECT_EQ(pure::X, pure::Y);
+}
diff --git a/src/lib/netlist/tests/test_pfunction.cpp b/src/lib/netlist/tests/test_pfunction.cpp
new file mode 100644
index 00000000000..fa100e7edb2
--- /dev/null
+++ b/src/lib/netlist/tests/test_pfunction.cpp
@@ -0,0 +1,60 @@
+// license:BSD-3-Clause
+// copyright-holders:Couriersud
+
+///
+/// \file test_pfunction.cpp
+///
+/// tests for `pfunction` class
+///
+
+#include "plib/ptests.h"
+
+#include "plib/pexception.h"
+#include "plib/pfunction.h"
+
+#define PFUNCEXPECT(formula, val) \
+ PEXPECT_EQ(val, plib::pfunction<double>(formula)())
+
+PTEST(pfunction, operators)
+{
+ PFUNCEXPECT("1==1", 1.0);
+ PFUNCEXPECT("1 *0 == 2-1-1", 1.0);
+ PFUNCEXPECT("0!=1", 1.0);
+ PFUNCEXPECT("0<1", 1.0);
+ PFUNCEXPECT("1>0", 1.0);
+ PFUNCEXPECT("0<=1", 1.0);
+ PFUNCEXPECT("1>=0", 1.0);
+ PFUNCEXPECT("1<=1", 1.0);
+ PFUNCEXPECT("1>=1", 1.0);
+ PEXPECT_EQ(1.0, plib::pfunction<double>("0!=a", {"a"})({1.0}));
+}
+
+PTEST(pfunction, func_if)
+{
+ PFUNCEXPECT("if(1>0, 2, 0)", 2.0);
+ PFUNCEXPECT("if(0>1, 2, 3)", 3.0);
+ PFUNCEXPECT("if(sin(1)>0, 2, 3)", 2.0); // fail
+ PEXPECT_EQ( 1.0, plib::pfunction<double>("if(A2>2.5, 0-A1, (0.07-(0.005*A1))*if(A0>2.5,1,0-1))", {"A0","A1","A2"})({1.0,-1.0,3.0}));
+ PEXPECT_EQ(-0.065, plib::pfunction<double>("if(A2>2.5, 0-A1, (0.07-(0.005*A1))*if(A0>2.5,1,0-1))", {"A0","A1","A2"})({1.0,1.0,1.0}));
+ PEXPECT_EQ( 0.065, plib::pfunction<double>("if(A2>2.5, 0-A1, (0.07-(0.005*A1))*if(A0>2.5,1,0-1))", {"A0","A1","A2"})({3.0,1.0,1.0}));
+ PEXPECT_TRUE(1.0 == plib::pfunction<double>("0!=a", {"a"})({1.0}));
+}
+
+PTEST(pfunction, unary_minus)
+{
+ PFUNCEXPECT("-1>-2", 1.0);
+ PFUNCEXPECT("(-3)*(-4)", 12.0);
+ PFUNCEXPECT("(-3)*-4", 12.0);
+ PFUNCEXPECT("-3*-4", 12.0);
+ PEXPECT_EQ( -3.0, plib::pfunction<double>("-A0", {"A0"})({3.0}));
+ PFUNCEXPECT("3*-trunc(3.2)", -9.0);
+ PFUNCEXPECT("3*-(3*2)", -18.0);
+ PFUNCEXPECT("3*-(2*1)^2", -12.0);
+ PEXPECT_NO_THROW(plib::pfunction<double>("(-3)")()); // fail
+}
+PTEST(pfunction, expect_throw)
+{
+ PEXPECT_THROW(plib::pfunction<double>("(3, 4)")(), plib::pexception);
+ PEXPECT_THROW(plib::pfunction<double>("((3)")(), plib::pexception);
+ PEXPECT_THROW(plib::pfunction<double>("(3))")(), plib::pexception);
+}
diff --git a/src/lib/netlist/tests/test_pmfp.cpp b/src/lib/netlist/tests/test_pmfp.cpp
new file mode 100644
index 00000000000..c6c9bf70daa
--- /dev/null
+++ b/src/lib/netlist/tests/test_pmfp.cpp
@@ -0,0 +1,77 @@
+// license:BSD-3-Clause
+// copyright-holders:Couriersud
+
+///
+/// \file test_pmfp.cpp
+///
+/// tests for `plib::pmfp` class
+///
+
+#include "plib/ptests.h"
+
+#include "plib/pexception.h"
+#include "plib/ppmf.h"
+
+#include <memory>
+#include <utility>
+
+/// `plib::late_pmfp<plib::pmfp<void, pstring>> a(&nld_7493::printer);`
+/// // Store the a object somewhere
+///
+/// // After full construction ...
+///
+/// ```
+/// auto dele = a(this);
+/// dele(pstring("Hello World!"));
+/// ```
+
+class test_late_pmfp : public plib::testing::Test
+{
+protected:
+ class late_pmfp_object
+ {
+ public:
+ void ap(int &r) { r = ax; }
+ int ax;
+ };
+
+};
+
+PTEST_F(test_late_pmfp, late_pmfp)
+{
+#if !PPMF_USE_MAME_DELEGATES
+ plib::late_pmfp<plib::pmfp<void (int &)>> late(&late_pmfp_object::ap);
+
+ late_pmfp_object a;
+ a.ax = 1;
+ auto mfp(late(&a));
+ int r(0);
+ mfp(r);
+ PEXPECT_TRUE(r == 1);
+#endif
+}
+
+PTEST(test_compile, compile)
+{
+#if !PPMF_USE_MAME_DELEGATES
+ plib::pmfp_base<plib::ppmf_type::PMF, void(int)> mfp_PPMF_TYPE_PMF;
+ plib::pmfp_base<plib::ppmf_type::INTERNAL_ITANIUM, void(int)> mfp_PPMF_TYPE_INTERNAL_ITANIUM;
+ plib::pmfp_base<plib::ppmf_type::INTERNAL_ARM, void(int)> mfp_PPMF_TYPE_INTERNAL_ARM;
+ plib::pmfp_base<plib::ppmf_type::INTERNAL_MSC, void(int)> mfp_PPMF_TYPE_INTERNAL_MSC;
+ PEXPECT_TRUE(mfp_PPMF_TYPE_PMF.isnull());
+ PEXPECT_TRUE(mfp_PPMF_TYPE_INTERNAL_ITANIUM.isnull());
+ PEXPECT_TRUE(mfp_PPMF_TYPE_INTERNAL_ARM.isnull());
+ PEXPECT_TRUE(mfp_PPMF_TYPE_INTERNAL_MSC.isnull());
+#endif
+ // FIXME: clang on linux seems to support GNUC_PMF_CONV - test needed
+ // Need to check for clang-cl here.
+#if defined(__GNUC__) && !defined(__clang__) && !defined(__NVCC__)
+ plib::pmfp_base<plib::ppmf_type::GNUC_PMF_CONV, void(int)> mfp_PPMF_TYPE_GNUC_PMF_CONV;
+ PEXPECT_TRUE(mfp_PPMF_TYPE_GNUC_PMF_CONV.isnull());
+#else
+ PEXPECT_NE("ppmf_type::GNUC_PMF_CONV not supported on this build", "");
+#endif
+#if defined(__EMSCRIPTEN__)
+ PEXPECT_EQ(int(plib::ppmf_internal_selector::value), int(plib::ppmf_type::INTERNAL_ARM));
+#endif
+}
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..8297792eae7
--- /dev/null
+++ b/src/lib/netlist/tests/test_pmfp_multibase.cpp
@@ -0,0 +1,451 @@
+// 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 <iostream>
+#include <memory>
+#include <type_traits>
+#include <typeinfo>
+#include <utility>
+
+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 << ([[maybe_unused]] std::basic_ostream<char>& os, [[maybe_unused]] const T &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>;
+
+ template <std::size_t N>
+ class tstruct
+ {
+ public:
+ struct r1type
+ {
+ char m[N];
+ };
+
+ r1type f1(const char v)
+ {
+ r1type r;
+ for (std::size_t i=0; i<N; i++) r.m[i] = v;
+ return r;
+ }
+
+ template <typename T>
+ T ft(const T v)
+ {
+ return v;
+ }
+
+ template <typename T>
+ T run_ft(const T v)
+ {
+ using pf_t = plib::pmfp<T (const T)>;
+ pf_t pf(&tstruct::ft<T>, this);
+ return pf(v);
+ }
+ };
+
+ //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);
+ //PEXPECT_EQ(plib::ppmf_internal::value, PPMF_TYPE_PMF);
+
+ // test return size handling
+
+ tstruct<3> ts3;
+ using pfmp3_t = plib::pmfp<tstruct<3>::r1type(char)>;
+ pfmp3_t pf3(&tstruct<3>::f1, &ts3);
+ auto r3 = pf3(3);
+ PEXPECT_EQ(static_cast<int>(r3.m[2]), 3);
+ PEXPECT_EQ(sizeof(r3), 3u);
+
+ tstruct<5> ts5;
+ using pfmp5_t = plib::pmfp<tstruct<5>::r1type(char)>;
+ pfmp5_t pf5(&tstruct<5>::f1, &ts5);
+ auto r5 = pf5(5);
+ PEXPECT_EQ(static_cast<int>(r5.m[3]), 5);
+ PEXPECT_EQ(sizeof(r5), 5u);
+
+ tstruct<8> ts8;
+ using pfmp8_t = plib::pmfp<tstruct<8>::r1type(char)>;
+ pfmp8_t pf8(&tstruct<8>::f1, &ts8);
+ auto r8 = pf8(8);
+ PEXPECT_EQ(static_cast<int>(r8.m[3]), 8);
+ PEXPECT_EQ(sizeof(r8), 8u);
+
+ tstruct<9> ts9;
+ using pfmp9_t = plib::pmfp<tstruct<9>::r1type (char)>;
+ pfmp9_t pf9(&tstruct<9>::f1, &ts9);
+ auto r9=pf9(9);
+ PEXPECT_EQ(static_cast<int>(r9.m[3]), 9);
+ PEXPECT_EQ(sizeof(r9), 9u);
+
+ tstruct<17> ts17;
+ using pfmp17_t = plib::pmfp<tstruct<17>::r1type(char)>;
+ pfmp17_t pf17(&tstruct<17>::f1, &ts17);
+ auto r17 = pf17(17);
+ PEXPECT_EQ(static_cast<int>(r17.m[3]), 17);
+ PEXPECT_EQ(sizeof(r17), 17u);
+
+#if !(defined(_MSC_VER) && !defined(__clang__))
+ if constexpr (plib::compile_info::has_int128::value)
+ {
+ PEXPECT_EQ(static_cast<int>(ts17.run_ft<INT128>(17)), 17); // FIXME: no operator << for INT128 yet
+ PEXPECT_EQ(sizeof(INT128), 16u);
+ }
+#endif
+ PEXPECT_EQ(ts17.run_ft<long double>(17), 17);
+ PEXPECT_EQ(ts17.run_ft<double>(17), 17);
+ PEXPECT_EQ(ts17.run_ft<int>(17), 17);
+ PEXPECT_EQ(ts17.run_ft<bool>(true), true);
+ PEXPECT_EQ(ts17.run_ft<std::size_t>(20), 20u);
+
+ struct tt1_t { int a; int b; };
+ tt1_t tt1 = { 8, 9 };
+ auto tt1r = ts17.run_ft<tt1_t>(tt1);
+ PEXPECT_EQ(tt1.a, tt1r.a);
+ PEXPECT_EQ(tt1.b, tt1r.b);
+
+ PEXPECT_EQ(sizeof(ret_t), 16u);
+
+}
+
+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);
+ //PEXPECT_EQ(plib::ppmf_internal::value, PPMF_TYPE_INTERNAL_MSC);
+}
diff --git a/src/lib/netlist/tests/test_precommit.cpp b/src/lib/netlist/tests/test_precommit.cpp
new file mode 100644
index 00000000000..6faf8029c0b
--- /dev/null
+++ b/src/lib/netlist/tests/test_precommit.cpp
@@ -0,0 +1,27 @@
+// license:BSD-3-Clause
+// copyright-holders:Couriersud
+
+///
+/// \file test_precommit.cpp
+///
+/// tests to check for experimental code before commit
+///
+
+#include "nl_config.h"
+
+#include "plib/pconfig.h"
+#include "plib/ppmf.h"
+#include "plib/ptests.h"
+
+PTEST(test_precommit, precommit)
+{
+ PEXPECT_EQ(PPMF_EXPERIMENTAL, 0);
+ PEXPECT_EQ(PPMF_USE_MAME_DELEGATES, 0);
+
+ PEXPECT_EQ(netlist::config::use_copy_instead_of_reference::value, false);
+ PEXPECT_EQ(NL_USE_BACKWARD_EULER, 1);
+ PEXPECT_EQ(PUSE_FLOAT128, 0);
+ PEXPECT_EQ(NL_USE_FLOAT128, PUSE_FLOAT128);
+ PEXPECT_EQ(NL_USE_INPLACE_CORE_TERMS, 0);
+ PEXPECT_EQ(netlist::config::avoid_noop_queue_pushes::value, false);
+}
diff --git a/src/lib/netlist/tests/test_pstring.cpp b/src/lib/netlist/tests/test_pstring.cpp
new file mode 100644
index 00000000000..3196e634ea6
--- /dev/null
+++ b/src/lib/netlist/tests/test_pstring.cpp
@@ -0,0 +1,19 @@
+// license:BSD-3-Clause
+// copyright-holders:Couriersud
+
+///
+/// \file test_pstring.cpp
+///
+/// tests for pstring
+///
+
+#include "plib/ptests.h"
+
+#include "plib/pexception.h"
+#include "plib/pstring.h"
+
+PTEST(pstring, conversion)
+{
+ PEXPECT_EQ( putf8string("Общая ком"), putf8string(putf16string(putf8string("Общая ком"))));
+ PEXPECT_EQ( putf8string("Общая ком"), putf8string(putf16string("Общая ком")));
+}