From 5718e4d0807fd3b6a8187dde140069120b81ecef Mon Sep 17 00:00:00 2001 From: rwgk Date: Tue, 25 Jul 2023 15:39:54 -0700 Subject: [PATCH] Add python_multiple_inheritance_test To clearly show the behavior differences between PyCLIF-C-API and PyCLIF-pybind11. GitHub testing: https://github.com/google/clif/pull/66 PiperOrigin-RevId: 551017585 --- clif/testing/python/CMakeLists.txt | 2 + .../python/python_multiple_inheritance.clif | 27 ++++++ .../python_multiple_inheritance_test.py | 85 +++++++++++++++++++ clif/testing/python_multiple_inheritance.h | 46 ++++++++++ 4 files changed, 160 insertions(+) create mode 100644 clif/testing/python/python_multiple_inheritance.clif create mode 100644 clif/testing/python/python_multiple_inheritance_test.py create mode 100644 clif/testing/python_multiple_inheritance.h diff --git a/clif/testing/python/CMakeLists.txt b/clif/testing/python/CMakeLists.txt index bd2dcf9d..bed3908d 100644 --- a/clif/testing/python/CMakeLists.txt +++ b/clif/testing/python/CMakeLists.txt @@ -230,3 +230,5 @@ add_pyclif_library_for_test(pyobject_ptr pyobject_ptr.clif ) add_pyclif_library_for_test(property_get_set_cpp_derived property_get_set_cpp_derived.clif) + +add_pyclif_library_for_test(python_multiple_inheritance python_multiple_inheritance.clif) diff --git a/clif/testing/python/python_multiple_inheritance.clif b/clif/testing/python/python_multiple_inheritance.clif new file mode 100644 index 00000000..e72663cd --- /dev/null +++ b/clif/testing/python/python_multiple_inheritance.clif @@ -0,0 +1,27 @@ +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from "clif/testing/python_multiple_inheritance.h": + namespace `clif_testing_python_multiple_inheritance`: + class CppBase: + def __init__(self, value: int) + def get_base_value(self) -> int + def reset_base_value(self, new_value: int) + + class CppDrvd(CppBase): + def __init__(self, value: int) + def get_drvd_value(self) -> int + def reset_drvd_value(self, new_value: int) + def get_base_value_from_drvd(self) -> int + def reset_base_value_from_drvd(self, new_value: int) diff --git a/clif/testing/python/python_multiple_inheritance_test.py b/clif/testing/python/python_multiple_inheritance_test.py new file mode 100644 index 00000000..47d81a96 --- /dev/null +++ b/clif/testing/python/python_multiple_inheritance_test.py @@ -0,0 +1,85 @@ +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from absl.testing import absltest + +from clif.testing.python import python_multiple_inheritance as tm + + +class PC(tm.CppBase): + pass + + +class PPCC(PC, tm.CppDrvd): + pass + + +class PPCCInit(PC, tm.CppDrvd): + + def __init__(self, value): + PC.__init__(self, value) + tm.CppDrvd.__init__(self, value + 1) + + +class PythonMultipleInheritanceTest(absltest.TestCase): + + def testPC(self): + d = PC(11) + self.assertEqual(d.get_base_value(), 11) + d.reset_base_value(13) + self.assertEqual(d.get_base_value(), 13) + + @absltest.skipIf( + "pybind11" in tm.__doc__, + "Preempt `__init__() must be called when overriding __init__` exception.", + ) + def testPPCC(self): + d = PPCC(11) + self.assertEqual(d.get_drvd_value(), 33) + d.reset_drvd_value(55) + self.assertEqual(d.get_drvd_value(), 55) + + # PyCLIF-C-API: CppBase is not initialized and never used. + self.assertEqual(d.get_base_value(), 11) + self.assertEqual(d.get_base_value_from_drvd(), 11) + d.reset_base_value(20) + self.assertEqual(d.get_base_value(), 20) + self.assertEqual(d.get_base_value_from_drvd(), 20) + d.reset_base_value_from_drvd(30) + self.assertEqual(d.get_base_value(), 30) + self.assertEqual(d.get_base_value_from_drvd(), 30) + + def testPPCCInit(self): + d = PPCCInit(11) + self.assertEqual(d.get_drvd_value(), 36) + d.reset_drvd_value(55) + self.assertEqual(d.get_drvd_value(), 55) + + # PyCLIF-C-API: CppBase is initialized but never used. + # PyCLIF-pybind11: CppBase is initialized and used when CppBase methods + # are called, but CppDrvd is used when CppDrvd methods + # are called. + i = 1 if "pybind11" in tm.__doc__ else 0 + self.assertEqual(d.get_base_value(), (12, 11)[i]) + self.assertEqual(d.get_base_value_from_drvd(), 12) + d.reset_base_value(20) + self.assertEqual(d.get_base_value(), 20) + self.assertEqual(d.get_base_value_from_drvd(), (20, 12)[i]) + d.reset_base_value_from_drvd(30) + self.assertEqual(d.get_base_value(), (30, 20)[i]) + self.assertEqual(d.get_base_value_from_drvd(), 30) + + +if __name__ == "__main__": + absltest.main() diff --git a/clif/testing/python_multiple_inheritance.h b/clif/testing/python_multiple_inheritance.h new file mode 100644 index 00000000..9dceafdc --- /dev/null +++ b/clif/testing/python_multiple_inheritance.h @@ -0,0 +1,46 @@ +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef CLIF_TESTING_PROPERTY_PYTHON_MULTIPLE_INHERITANCE_H_ +#define CLIF_TESTING_PROPERTY_PYTHON_MULTIPLE_INHERITANCE_H_ + +namespace clif_testing_python_multiple_inheritance { + +struct CppBase { + CppBase(int value) : base_value(value) {} + int get_base_value() const { return base_value; } + void reset_base_value(int new_value) { base_value = new_value; } + + private: + int base_value; +}; + +struct CppDrvd : CppBase { + CppDrvd(int value) : CppBase(value), drvd_value(value * 3) {} + int get_drvd_value() const { return drvd_value; } + void reset_drvd_value(int new_value) { drvd_value = new_value; } + + int get_base_value_from_drvd() const { return get_base_value(); } + void reset_base_value_from_drvd(int new_value) { + reset_base_value(new_value); + } + + private: + int drvd_value; +}; + +} // namespace clif_testing_python_multiple_inheritance + +#endif // CLIF_TESTING_PYTHON_MULTIPLE_INHERITANCE_H_