diff options
Diffstat (limited to 'sources/shiboken6/tests/minimalbinding')
13 files changed, 1067 insertions, 0 deletions
diff --git a/sources/shiboken6/tests/minimalbinding/CMakeLists.txt b/sources/shiboken6/tests/minimalbinding/CMakeLists.txt new file mode 100644 index 000000000..7f132bd34 --- /dev/null +++ b/sources/shiboken6/tests/minimalbinding/CMakeLists.txt @@ -0,0 +1,47 @@ +# Copyright (C) 2023 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +project(minimal) + +set(minimal_TYPESYSTEM +${CMAKE_CURRENT_SOURCE_DIR}/typesystem_minimal.xml +) + +set(minimal_SRC +${CMAKE_CURRENT_BINARY_DIR}/minimal/minimal_module_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/minimal/containeruser_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/minimal/obj_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/minimal/val_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/minimal/listuser_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/minimal/spanuser_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/minimal/minbooluser_wrapper.cpp +) + +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/minimal-binding.txt.in" + "${CMAKE_CURRENT_BINARY_DIR}/minimal-binding.txt" @ONLY) + +shiboken_get_tool_shell_wrapper(shiboken tool_wrapper) + +add_custom_command( + OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/mjb_rejected_classes.log" + BYPRODUCTS ${minimal_SRC} + COMMAND + ${tool_wrapper} + $<TARGET_FILE:Shiboken6::shiboken6> + --project-file=${CMAKE_CURRENT_BINARY_DIR}/minimal-binding.txt + ${GENERATOR_EXTRA_FLAGS} + DEPENDS ${minimal_TYPESYSTEM} ${CMAKE_CURRENT_SOURCE_DIR}/global.h Shiboken6::shiboken6 + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + COMMENT "Running generator for 'minimal' test binding..." +) + +add_library(minimal MODULE ${minimal_SRC}) +target_include_directories(minimal PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) +target_link_libraries(minimal PUBLIC libminimal libshiboken) +set_property(TARGET minimal PROPERTY PREFIX "") +set_property(TARGET minimal PROPERTY OUTPUT_NAME "minimal${PYTHON_EXTENSION_SUFFIX}") +if(WIN32) + set_property(TARGET minimal PROPERTY SUFFIX ".pyd") +endif() + +create_generator_target(minimal) diff --git a/sources/shiboken6/tests/minimalbinding/brace_pattern_test.py b/sources/shiboken6/tests/minimalbinding/brace_pattern_test.py new file mode 100644 index 000000000..a45c6edb2 --- /dev/null +++ b/sources/shiboken6/tests/minimalbinding/brace_pattern_test.py @@ -0,0 +1,88 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +from __future__ import annotations + +import os +import re +import sys +import unittest + +from pathlib import Path +sys.path.append(os.fspath(Path(__file__).resolve().parents[1])) +from shiboken_paths import init_paths +init_paths() + +from shiboken6 import Shiboken # noqa: F401 + +from shibokensupport.signature.lib.tool import build_brace_pattern + +""" +This test tests the brace pattern from signature.lib.tool +against a slower reference implementation. +The pattern is crucial, because it is used heavily in signature.parser . +""" + + +def check(s): + """A slow reference parser for braces and strings""" + open, close = "[{(<", "]})>" + escape, quote = "\\", '"' + instring = blind = False + stack = [] + for c in s: + if instring: + if blind: + blind = False + elif c == escape: + blind = True + elif c == quote: + instring = False + stack.pop() + continue + if c in open: + stack.append(c) + elif c in close: + pos = close.index(c) + if len(stack) > 0 and open[pos] == stack[len(stack) - 1]: + stack.pop() + else: + return False + elif c == escape: + return False + elif c == quote: + instring = True + stack.append(c) + return len(stack) == 0 + + +class TestBracePattern(unittest.TestCase): + tests = [ + (r'{[]{()}}', True), + (r'[{}{})(]', False), + (r'[{}{} ")(" ]', True), + (r'[{}{} ")(\" ]', False), + (r'[{}{} ")(\" ]"]', True), + (r'a < b ( c [ d { "} \"\"}" } ] ) >', True), + (r'a < b ( c [ d { } ] ) >', True), + (r'a < b ( c [ d { "huh" } ] ) >', True), + (r'a < b ( c [ d { "huh\" \" \\\"" } ] ) >', True), + ] + + def test_checkfunc(self): + for test, result in self.tests: + if result: + self.assertTrue(check(test)) + else: + self.assertFalse(check(test)) + + def test_the_brace_pattern(self): + func = re.compile(build_brace_pattern(5, ",") + "$", re.VERBOSE).match + for test, result in self.tests: + if result: + self.assertTrue(func(test)) + else: + self.assertFalse(func(test)) + + +if __name__ == '__main__': + unittest.main() diff --git a/sources/shiboken6/tests/minimalbinding/containeruser_test.py b/sources/shiboken6/tests/minimalbinding/containeruser_test.py new file mode 100644 index 000000000..cda4f32b2 --- /dev/null +++ b/sources/shiboken6/tests/minimalbinding/containeruser_test.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python +# Copyright (C) 2023 The Qt Company Ltd. +# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +from __future__ import annotations + +import os +import sys +import unittest + +from pathlib import Path +sys.path.append(os.fspath(Path(__file__).resolve().parents[1])) +from shiboken_paths import init_paths +init_paths() + +from minimal import ContainerUser + + +class ContainerTest(unittest.TestCase): + """Simple test for converting std::vector and using an opaque container. + For advanced tests, see ListUser.""" + def testVectorConversion(self): + v = ContainerUser.createIntVector(4) + self.assertEqual(ContainerUser.sumIntVector(v), 6) + + def testVectorOpaqueContainer(self): + cu = ContainerUser() + oc = cu.intVector() + self.assertEqual(oc[0], 1) + oc[0] = 42 + self.assertEqual(cu.intVector()[0], 42) + + def testArrayConversion(self): + v = ContainerUser.createIntArray() + self.assertEqual(ContainerUser.sumIntArray(v), 6) + + def testArrayOpaqueContainer(self): + cu = ContainerUser() + oc = cu.intArray() + self.assertEqual(oc[0], 1) + oc[0] = 42 + self.assertEqual(cu.intArray()[0], 42) + + +if __name__ == '__main__': + unittest.main() diff --git a/sources/shiboken6/tests/minimalbinding/global.h b/sources/shiboken6/tests/minimalbinding/global.h new file mode 100644 index 000000000..fc5c59a26 --- /dev/null +++ b/sources/shiboken6/tests/minimalbinding/global.h @@ -0,0 +1,10 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#include "obj.h" +#include "containeruser.h" +#include "val.h" +#include "minbool.h" +#include "listuser.h" +#include "spanuser.h" +#include "typedef.h" diff --git a/sources/shiboken6/tests/minimalbinding/listuser_test.py b/sources/shiboken6/tests/minimalbinding/listuser_test.py new file mode 100644 index 000000000..bf09eeffb --- /dev/null +++ b/sources/shiboken6/tests/minimalbinding/listuser_test.py @@ -0,0 +1,377 @@ +#!/usr/bin/env python +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +from __future__ import annotations + +from functools import reduce +import os +import sys +import unittest + +from pathlib import Path +sys.path.append(os.fspath(Path(__file__).resolve().parents[1])) +from shiboken_paths import init_paths +init_paths() + +from minimal import ListUser, Val, Obj, StdIntList + + +class ExtListUser(ListUser): + def __init__(self): + super().__init__() + self._stdIntList = StdIntList() + self._stdIntList.append(1) + self._stdIntList.append(2) + + def createIntList(self, num): + return list(range(0, num * 2, 2)) + + def sumIntList(self, intList): + return sum(intList) * 2 + + def createMinBoolList(self, mb1, mb2): + return [not mb1, not mb2] + + def oredMinBoolList(self, minBoolList): + return not reduce(lambda a, b: a | b, minBoolList) + + def createValList(self, num): + return [Val(i) for i in range(0, num * 2, 2)] + + def sumValList(self, valList): + return sum([val.valId() for val in valList]) * 2 + + def createObjList(self, o1, o2): + o1.setObjId(o1.objId() * 2) + o2.setObjId(o2.objId() * 2) + return [o1, o2] + + def sumObjList(self, objList): + return sum([obj.objId() for obj in objList]) * 2 + + def createListOfIntLists(self, num): + return [self.createIntList(num)] * 4 + + def sumListOfIntLists(self, intListList): + return sum([sum(line) for line in intListList]) * 2 + + def returnIntListByPtr(self): + return self._stdIntList + + +class IntListConversionTest(unittest.TestCase): + + def testCreateIntList(self): + num = 4 + lu = ListUser() + lst = lu.createIntList(num) + self.assertEqual(type(lst), list) + self.assertEqual(len(lst), num) + for i in lst: + self.assertEqual(type(i), int) + self.assertEqual(lst, list(range(num))) + lst = lu.callCreateIntList(num) + self.assertEqual(type(lst), list) + self.assertEqual(len(lst), num) + for i in lst: + self.assertEqual(type(i), int) + self.assertEqual(lst, list(range(num))) + + def testCreateIntListFromExtendedClass(self): + lu = ExtListUser() + num = 4 + lst = lu.createIntList(num) + self.assertEqual(type(lst), list) + self.assertEqual(len(lst), num) + for i in lst: + self.assertEqual(type(i), int) + self.assertEqual(lst, list(range(0, num * 2, 2))) + lst = lu.callCreateIntList(num) + self.assertEqual(type(lst), list) + self.assertEqual(len(lst), num) + for i in lst: + self.assertEqual(type(i), int) + self.assertEqual(lst, list(range(0, num * 2, 2))) + + def testSumIntList(self): + lu = ListUser() + lst = range(4) + expected = sum(lst) + self.assertEqual(lu.sumIntList(lst), expected) + self.assertEqual(lu.callSumIntList(lst), expected) + self.assertEqual(lu.sumIntListDefaultParam(lst), expected) + self.assertEqual(lu.sumIntListDefaultParamConstRef(lst), expected) + # PYSIDE-2454: Check container default parameters (1,2,3) + self.assertEqual(lu.sumIntListDefaultParam(), 6) + self.assertEqual(lu.sumIntListDefaultParamConstRef(), 6) + + def testSumIntListFromExtendedClass(self): + lu = ExtListUser() + lst = range(4) + self.assertEqual(lu.sumIntList(lst), sum(lst) * 2) + self.assertEqual(lu.callSumIntList(lst), sum(lst) * 2) + + +class MinBoolListConversionTest(unittest.TestCase): + + def testCreateMinBoolList(self): + lu = ListUser() + lst = lu.createMinBoolList(True, False) + self.assertEqual(type(lst), list) + self.assertEqual(len(lst), 2) + for i in lst: + self.assertEqual(type(i), bool) + self.assertEqual(lst, [True, False]) + + lst = lu.callCreateMinBoolList(False, True) + self.assertEqual(type(lst), list) + self.assertEqual(len(lst), 2) + for i in lst: + self.assertEqual(type(i), bool) + self.assertEqual(lst, [False, True]) + + def testCreateMinBoolListFromExtendedClass(self): + lu = ExtListUser() + lst = lu.createMinBoolList(True, False) + self.assertEqual(type(lst), list) + self.assertEqual(len(lst), 2) + for i in lst: + self.assertEqual(type(i), bool) + self.assertEqual(lst, [False, True]) + + lst = lu.callCreateMinBoolList(False, True) + self.assertEqual(type(lst), list) + self.assertEqual(len(lst), 2) + for i in lst: + self.assertEqual(type(i), bool) + self.assertEqual(lst, [True, False]) + + def testOredMinBoolList(self): + lu = ListUser() + lst = [False, False, True] + self.assertTrue(lu.oredMinBoolList(lst)) + self.assertTrue(lu.callOredMinBoolList(lst)) + lst = [False, False, False] + self.assertFalse(lu.oredMinBoolList(lst)) + self.assertFalse(lu.callOredMinBoolList(lst)) + + def testOredMinBoolListFromExtendedClass(self): + lu = ExtListUser() + lst = [False, False, True] + self.assertFalse(lu.oredMinBoolList(lst)) + self.assertFalse(lu.callOredMinBoolList(lst)) + lst = [False, False, False] + self.assertTrue(lu.oredMinBoolList(lst)) + self.assertTrue(lu.callOredMinBoolList(lst)) + + +class ValListConversionTest(unittest.TestCase): + + def testCreateValList(self): + num = 4 + lu = ListUser() + lst = lu.createValList(num) + self.assertEqual(type(lst), list) + self.assertEqual(len(lst), num) + for i in lst: + self.assertEqual(type(i), Val) + self.assertEqual([val.valId() for val in lst], list(range(num))) + lst = lu.callCreateValList(num) + self.assertEqual(type(lst), list) + self.assertEqual(len(lst), num) + for i in lst: + self.assertEqual(type(i), Val) + self.assertEqual([val.valId() for val in lst], list(range(num))) + + def testCreateValListFromExtendedClass(self): + lu = ExtListUser() + num = 4 + lst = lu.createValList(num) + self.assertEqual(type(lst), list) + self.assertEqual(len(lst), num) + for i in lst: + self.assertEqual(type(i), Val) + self.assertEqual([val.valId() for val in lst], list(range(0, num * 2, 2))) + lst = lu.callCreateValList(num) + self.assertEqual(type(lst), list) + self.assertEqual(len(lst), num) + for i in lst: + self.assertEqual(type(i), Val) + self.assertEqual([val.valId() for val in lst], list(range(0, num * 2, 2))) + + def testSumValList(self): + lu = ListUser() + lst = [Val(i) for i in range(4)] + self.assertEqual(lu.sumValList(lst), sum([val.valId() for val in lst])) + self.assertEqual(lu.callSumValList(lst), sum([val.valId() for val in lst])) + + def testSumValListFromExtendedClass(self): + lu = ExtListUser() + lst = [Val(i) for i in range(4)] + self.assertEqual(lu.sumValList(lst), sum([val.valId() for val in lst]) * 2) + self.assertEqual(lu.callSumValList(lst), sum([val.valId() for val in lst]) * 2) + + +class ObjListConversionTest(unittest.TestCase): + + def testCreateObjList(self): + o1 = Obj(1) + o2 = Obj(2) + lu = ListUser() + lst = lu.createObjList(o1, o2) + self.assertEqual(type(lst), list) + self.assertEqual(len(lst), 2) + for i in lst: + self.assertEqual(type(i), Obj) + self.assertEqual(lst, [o1, o2]) + self.assertEqual([obj.objId() for obj in lst], [1, 2]) + + lst = lu.callCreateObjList(o1, o2) + self.assertEqual(type(lst), list) + self.assertEqual(len(lst), 2) + for i in lst: + self.assertEqual(type(i), Obj) + self.assertEqual(lst, [o1, o2]) + self.assertEqual([obj.objId() for obj in lst], [1, 2]) + + def testCreateObjListFromExtendedClass(self): + o1 = Obj(1) + o2 = Obj(2) + lu = ExtListUser() + lst = lu.createObjList(o1, o2) + self.assertEqual(type(lst), list) + self.assertEqual(len(lst), 2) + for i in lst: + self.assertEqual(type(i), Obj) + self.assertEqual(lst, [o1, o2]) + self.assertEqual([obj.objId() for obj in lst], [2, 4]) + + lst = lu.callCreateObjList(o1, o2) + self.assertEqual(type(lst), list) + self.assertEqual(len(lst), 2) + for i in lst: + self.assertEqual(type(i), Obj) + self.assertEqual(lst, [o1, o2]) + self.assertEqual([obj.objId() for obj in lst], [4, 8]) + + def testSumObjList(self): + lu = ListUser() + lst = [Obj(i) for i in list(range(4))] + self.assertEqual(lu.sumObjList(lst), sum([obj.objId() for obj in lst])) + self.assertEqual(lu.callSumObjList(lst), sum([obj.objId() for obj in lst])) + + def testSumObjListFromExtendedClass(self): + lu = ExtListUser() + lst = [Obj(i) for i in list(range(4))] + self.assertEqual(lu.sumObjList(lst), sum([obj.objId() for obj in lst]) * 2) + self.assertEqual(lu.callSumObjList(lst), sum([obj.objId() for obj in lst]) * 2) + + +class ListOfIntListConversionTest(unittest.TestCase): + + def testCreateListOfIntLists(self): + num = 4 + lu = ListUser() + lst = lu.createListOfIntLists(num) + self.assertEqual(type(lst), list) + self.assertEqual(len(lst), num) + for i in lst: + self.assertEqual(type(i), list) + self.assertEqual(i, list(range(num))) + for j in i: + self.assertEqual(type(j), int) + self.assertEqual(lst, [list(range(num))] * 4) + + def testCreateListOfIntListsFromExtendedClass(self): + num = 4 + lu = ExtListUser() + lst = lu.createListOfIntLists(num) + self.assertEqual(type(lst), list) + self.assertEqual(len(lst), num) + for i in lst: + self.assertEqual(type(i), list) + self.assertEqual(i, list(range(0, num * 2, 2))) + for j in i: + self.assertEqual(type(j), int) + self.assertEqual(lst, [list(range(0, num * 2, 2))] * 4) + + def testSumListIntLists(self): + lu = ListUser() + lst = [range(4)] * 4 + self.assertEqual(lu.sumListOfIntLists(lst), sum([sum(line) for line in [range(4)] * 4])) + self.assertEqual(lu.callSumListOfIntLists(lst), sum([sum(line) for line in [range(4)] * 4])) + + def testSumListOfIntListsFromExtendedClass(self): + lu = ExtListUser() + lst = [range(4)] * 4 + self.assertEqual(lu.sumListOfIntLists(lst), + sum([sum(line) for line in [range(4)] * 4]) * 2) + self.assertEqual(lu.callSumListOfIntLists(lst), + sum([sum(line) for line in [range(4)] * 4]) * 2) + + def testOpaqueContainer(self): + lu = ListUser() + + # Set via Python + python_list = [1, 2] + lu.setStdIntList(python_list) + self.assertEqual(len(lu.m_stdIntList), 2) + self.assertEqual(lu.m_stdIntList[0], 1) + self.assertEqual(lu.m_stdIntList[1], 2) + + # Set via C++ + cpp_list = StdIntList() + cpp_list.append(3) + cpp_list.append(4) + lu.setStdIntList(cpp_list) + self.assertEqual(len(lu.m_stdIntList), 2) + self.assertEqual(lu.m_stdIntList[0], 3) + self.assertEqual(lu.m_stdIntList[1], 4) + + # Access field directly via reference + lu.m_stdIntList.append(5) + self.assertEqual(len(lu.m_stdIntList), 3) + self.assertEqual(lu.m_stdIntList[2], 5) + + # Access list via getter + il = lu.getIntList() + il.append(6) + self.assertEqual(len(lu.m_stdIntList), 4) + self.assertEqual(lu.m_stdIntList[3], 6) + + # Access a const list via getter and verify that it cannot be modified + const_l = lu.getConstIntList() + self.assertEqual(len(const_l), 4) + self.assertRaises(TypeError, const_l.append, 6) + + def testListByPtrOpaque(self): + """Test a function taking C++ list by pointer for which an opaque + container exists.""" + lu = ListUser() + python_list = [1, 2] + self.assertEqual(lu.modifyIntListPtr(python_list), 2) + + # Pass an opaque container and verify whether it is modified by C++ + cpp_list = StdIntList() + cpp_list.append(1) + cpp_list.append(2) + self.assertEqual(lu.modifyIntListPtr(cpp_list), 2) + self.assertEqual(len(cpp_list), 3) + + def testListByPtr(self): + """Test a function taking C++ list by pointer for which no opaque + container exists.""" + lu = ListUser() + python_list = [1.1, 22.2] + self.assertEqual(lu.modifyDoubleListPtr(python_list), 2) + + def testReturnListByPtr(self): + """Test that a virtual function returning a list by pointer can be + reimplemented by a Python function returning an opaque container.""" + lu = ExtListUser() + size = lu.callReturnIntListByPtr() # Call virtual from C++ + self.assertEqual(size, 2) + + +if __name__ == '__main__': + unittest.main() diff --git a/sources/shiboken6/tests/minimalbinding/minbool_test.py b/sources/shiboken6/tests/minimalbinding/minbool_test.py new file mode 100644 index 000000000..0f033e4d1 --- /dev/null +++ b/sources/shiboken6/tests/minimalbinding/minbool_test.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +from __future__ import annotations + +import os +import sys +import unittest + +from pathlib import Path +sys.path.append(os.fspath(Path(__file__).resolve().parents[1])) +from shiboken_paths import init_paths +init_paths() + +from minimal import MinBoolUser + + +class DerivedMinBoolUser (MinBoolUser): + def returnMyselfVirtual(self): + return MinBoolUser() + + +class MinBoolTest(unittest.TestCase): + + def testMinBoolUser(self): + mbuTrue = MinBoolUser() + mbuFalse = MinBoolUser() + mbuTrue.setMinBool(True) + self.assertFalse(mbuFalse.minBool()) + self.assertTrue(mbuTrue.minBool()) + self.assertFalse(mbuTrue.callInvertedMinBool()) + + self.assertTrue(mbuTrue.minBool()) + self.assertFalse(mbuFalse.minBool()) + self.assertTrue(mbuTrue.minBool() != mbuFalse.minBool()) + + self.assertFalse(mbuFalse.minBool()) + self.assertFalse(mbuFalse.minBool()) + self.assertTrue(mbuTrue.minBool() != mbuFalse.minBool()) + + def testVirtuals(self): + dmbu = DerivedMinBoolUser() + self.assertEqual(dmbu.invertedMinBool(), True) + + +if __name__ == '__main__': + unittest.main() diff --git a/sources/shiboken6/tests/minimalbinding/minimal-binding.txt.in b/sources/shiboken6/tests/minimalbinding/minimal-binding.txt.in new file mode 100644 index 000000000..101567070 --- /dev/null +++ b/sources/shiboken6/tests/minimalbinding/minimal-binding.txt.in @@ -0,0 +1,16 @@ +[generator-project] + +generator-set = shiboken + +header-file = @CMAKE_CURRENT_SOURCE_DIR@/global.h +typesystem-file = @minimal_TYPESYSTEM@ + +output-directory = @CMAKE_CURRENT_BINARY_DIR@ + +include-path = @libminimal_SOURCE_DIR@ + +typesystem-path = @CMAKE_CURRENT_SOURCE_DIR@ + +enable-parent-ctor-heuristic +use-isnull-as-nb_nonzero +lean-headers diff --git a/sources/shiboken6/tests/minimalbinding/minimalbinding.pyproject b/sources/shiboken6/tests/minimalbinding/minimalbinding.pyproject new file mode 100644 index 000000000..ab19dc443 --- /dev/null +++ b/sources/shiboken6/tests/minimalbinding/minimalbinding.pyproject @@ -0,0 +1,10 @@ +{ + "files": ["brace_pattern_test.py", + "containeruser_test.py", + "listuser_test.py", + "minbool_test.py", + "obj_test.py", + "typedef_test.py", + "val_test.py", + "typesystem_minimal.xml"] +} diff --git a/sources/shiboken6/tests/minimalbinding/obj_test.py b/sources/shiboken6/tests/minimalbinding/obj_test.py new file mode 100644 index 000000000..82dc89d38 --- /dev/null +++ b/sources/shiboken6/tests/minimalbinding/obj_test.py @@ -0,0 +1,95 @@ +#!/usr/bin/env python +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +from __future__ import annotations + +import os +import sys +import unittest + +from pathlib import Path +sys.path.append(os.fspath(Path(__file__).resolve().parents[1])) +from shiboken_paths import init_paths +init_paths() +from minimal import Obj + + +class ExtObj(Obj): + def __init__(self, objId): + Obj.__init__(self, objId) + self.virtual_method_called = False + + def virtualMethod(self, val): + self.virtual_method_called = True + return not Obj.virtualMethod(self, val) + + def passObjectType(self, obj): + obj.setObjId(obj.objId() + 1) + return obj + + def passObjectTypeReference(self, obj): + obj.setObjId(obj.objId() + 1) + return obj + + +class ObjTest(unittest.TestCase): + + def testNormalMethod(self): + objId = 123 + obj = Obj(objId) + self.assertEqual(obj.objId(), objId) + + def testNormalMethodFromExtendedClass(self): + objId = 123 + obj = ExtObj(objId) + self.assertEqual(obj.objId(), objId) + + def testVirtualMethod(self): + obj = Obj(0) + even_number = 8 + self.assertEqual(obj.virtualMethod(even_number), obj.callVirtualMethod(even_number)) + + def testVirtualMethodFromExtendedClass(self): + obj = ExtObj(0) + even_number = 8 + self.assertEqual(obj.virtualMethod(even_number), obj.callVirtualMethod(even_number)) + self.assertTrue(obj.virtual_method_called) + + def testPassObjectType(self): + obj = Obj(0) + self.assertEqual(obj, obj.passObjectType(obj)) + self.assertEqual(obj, obj.callPassObjectType(obj)) + + def testPassObjectTypeNone(self): + obj = Obj(0) + self.assertEqual(None, obj.passObjectType(None)) + self.assertEqual(None, obj.callPassObjectType(None)) + + def testPassObjectTypeReference(self): + obj = Obj(0) + self.assertEqual(obj, obj.passObjectTypeReference(obj)) + self.assertEqual(obj, obj.callPassObjectTypeReference(obj)) + + def testPassObjectTypeFromExtendedClass(self): + obj = ExtObj(0) + self.assertEqual(obj.objId(), 0) + sameObj = obj.passObjectType(obj) + self.assertEqual(obj, sameObj) + self.assertEqual(sameObj.objId(), 1) + sameObj = obj.callPassObjectType(obj) + self.assertEqual(obj, sameObj) + self.assertEqual(sameObj.objId(), 2) + + def testPassObjectTypeReferenceFromExtendedClass(self): + obj = ExtObj(0) + self.assertEqual(obj.objId(), 0) + sameObj = obj.passObjectTypeReference(obj) + self.assertEqual(obj, sameObj) + self.assertEqual(sameObj.objId(), 1) + sameObj = obj.callPassObjectTypeReference(obj) + self.assertEqual(obj, sameObj) + self.assertEqual(sameObj.objId(), 2) + + +if __name__ == '__main__': + unittest.main() diff --git a/sources/shiboken6/tests/minimalbinding/spanuser_test.py b/sources/shiboken6/tests/minimalbinding/spanuser_test.py new file mode 100644 index 000000000..4239fe9a2 --- /dev/null +++ b/sources/shiboken6/tests/minimalbinding/spanuser_test.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python +# Copyright (C) 2023 The Qt Company Ltd. +# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +from __future__ import annotations + +import os +import sys +import unittest + +from pathlib import Path +sys.path.append(os.fspath(Path(__file__).resolve().parents[1])) +from shiboken_paths import init_paths +init_paths() + +from minimal import SpanUser + + +class IntSpanTest(unittest.TestCase): + + def testCreateIntSpan(self): + if not SpanUser.enabled(): + return + expected = [1, 2, 3] + self.assertEqual(SpanUser.getIntSpan3(), expected) + self.assertEqual(SpanUser.getIntSpan(), expected) + self.assertEqual(SpanUser.getConstIntSpan3(), expected) + + self.assertEqual(SpanUser.sumIntSpan3(expected), 6) + self.assertEqual(SpanUser.sumIntSpan(expected), 6) + self.assertEqual(SpanUser.sumConstIntSpan3(expected), 6) + + def testSpanOpaqueContainer(self): + if not SpanUser.enabled(): + return + oc = SpanUser.getIntSpan3_OpaqueContainer() # 1,2,3 + oc[1] = 10 + oc = SpanUser.getIntSpan3_OpaqueContainer() + # note: This converts to std::vector + self.assertEqual(SpanUser.sumIntSpan3(oc), 14) + + +if __name__ == '__main__': + unittest.main() diff --git a/sources/shiboken6/tests/minimalbinding/typedef_test.py b/sources/shiboken6/tests/minimalbinding/typedef_test.py new file mode 100644 index 000000000..c69a1c3c5 --- /dev/null +++ b/sources/shiboken6/tests/minimalbinding/typedef_test.py @@ -0,0 +1,108 @@ +#!/usr/bin/env python +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +from __future__ import annotations + +import os +import sys +import unittest + +from pathlib import Path +sys.path.append(os.fspath(Path(__file__).resolve().parents[1])) +from shiboken_paths import init_paths +init_paths() +from minimal import (arrayFunc, arrayFuncInt, arrayFuncIntReturn, + arrayFuncIntReturnTypedef, arrayFuncIntTypedef, + arrayFuncReturn, arrayFuncReturnTypedef, arrayFuncTypedef) + +try: + import numpy as np +except ImportError as e: + print(e) + np = None + + +class TypedefTest(unittest.TestCase): + + def setUp(self): + self.the_size = 8 + + def test_arrayFuncInt(self): + none = () + full = range(self.the_size) + self.assertTrue(arrayFuncInt(none), "None is empty, arrayFuncInt should return true") + self.assertFalse(arrayFuncInt(full), "Full is NOT empty, arrayFuncInt should return false") + + self.assertTrue(arrayFuncInt(np.array(none)), + "None is empty, arrayFuncInt should return true") + self.assertFalse(arrayFuncInt(np.array(full)), + "Full is NOT empty, arrayFuncInt should return false") + + def test_arrayFuncIntTypedef(self): + none = () + full = (1, 2, 3) + self.assertTrue(arrayFuncIntTypedef(none), + "None is empty, arrayFuncIntTypedef should return true") + self.assertFalse(arrayFuncIntTypedef(full), + "Full is NOT empty, arrayFuncIntTypedef should return false") + + self.assertTrue(arrayFuncIntTypedef(np.array(none)), + "None is empty, arrayFuncIntTypedef should return true") + self.assertFalse(arrayFuncIntTypedef(np.array(full)), + "Full is NOT empty, arrayFuncIntTypedef should return false") + + def test_arrayFuncIntReturn(self): + none = arrayFuncIntReturn(0) + full = arrayFuncIntReturn(self.the_size) + self.assertTrue((len(none) == 0), "none should be empty") + self.assertTrue((len(full) == self.the_size), + f"full should have {self.the_size} elements") + + def test_arrayFuncIntReturnTypedef(self): + none = arrayFuncIntReturnTypedef(0) + full = arrayFuncIntReturnTypedef(self.the_size) + self.assertTrue((len(none) == 0), "none should be empty") + self.assertTrue((len(full) == self.the_size), + f"full should have {self.the_size} elements") + + def test_arrayFunc(self): + none = () + full = range(self.the_size) + self.assertTrue(arrayFunc(none), "None is empty, arrayFunc should return true") + self.assertFalse(arrayFunc(full), "Full is NOT empty, arrayFunc should return false") + + self.assertTrue(arrayFunc(np.array(none)), "None is empty, arrayFunc should return true") + self.assertFalse(arrayFunc(np.array(full)), + "Full is NOT empty, arrayFunc should return false") + + def test_arrayFuncTypedef(self): + none = () + full = (1, 2, 3) + self.assertTrue(arrayFuncTypedef(none), + "None is empty, arrayFuncTypedef should return true") + self.assertFalse(arrayFuncTypedef(full), + "Full is NOT empty, arrayFuncTypedef should return false") + + self.assertTrue(arrayFuncTypedef(np.array(none)), + "None is empty, arrayFuncTypedef should return true") + self.assertFalse(arrayFuncTypedef(np.array(full)), + "Full is NOT empty, arrayFuncTypedef should return false") + + def test_arrayFuncReturn(self): + none = arrayFuncReturn(0) + full = arrayFuncReturn(self.the_size) + self.assertTrue((len(none) == 0), "none should be empty") + self.assertTrue((len(full) == self.the_size), + f"full should have {self.the_size} elements") + + def test_arrayFuncReturnTypedef(self): + none = arrayFuncReturnTypedef(0) + full = arrayFuncReturnTypedef(self.the_size) + self.assertTrue((len(none) == 0), "none should be empty") + self.assertTrue((len(full) == self.the_size), + f"full should have {self.the_size} elements") + + +if __name__ == '__main__': + if np is not None: + unittest.main() diff --git a/sources/shiboken6/tests/minimalbinding/typesystem_minimal.xml b/sources/shiboken6/tests/minimalbinding/typesystem_minimal.xml new file mode 100644 index 000000000..e18bf8686 --- /dev/null +++ b/sources/shiboken6/tests/minimalbinding/typesystem_minimal.xml @@ -0,0 +1,86 @@ +<?xml version="1.0" encoding="UTF-8"?> +<typesystem package="minimal"> + + <primitive-type name="MinBool" target-lang-api-name="PyBool" default-constructor="MinBool(false)"> + <include file-name="minbool.h" location="global"/> + <conversion-rule> + <native-to-target> + return PyBool_FromLong(%in.value()); + </native-to-target> + <target-to-native> + <add-conversion type="PyBool" check="PyBool_Check(%in)"> + %out = %OUTTYPE(%in == Py_True); + </add-conversion> + </target-to-native> + </conversion-rule> + </primitive-type> + + <opaque-container name="std::list" opaque-containers="int:StdIntList"/> + + <opaque-container name="std::vector" opaque-containers="int:StdIntVector"/> + + <opaque-container name="std::array" opaque-containers="int,3:StdIntArray"/> + + <?if c++20?> <!-- FIXME PYSIDE 7: Remove "if" --> + <opaque-container name="std::span" opaque-containers="int,3:StdIntSpan3"/> + <?endif?> + + <object-type name="Obj"/> + <value-type name="Val"> + <enum-type name="ValEnum"/> + </value-type> + <value-type name="ListUser"> + <modify-field name="m_stdIntList" opaque-container="yes"/> + <modify-function signature="getIntList()"> + <modify-argument index="return"> + <replace-type modified-type="StdIntList"/> + </modify-argument> + </modify-function> + <modify-function signature="getConstIntList()const"> + <modify-argument index="return"> + <replace-type modified-type="StdIntList"/> + </modify-argument> + </modify-function> + </value-type> + + <value-type name="SpanUser"> + <?if c++20?> <!-- FIXME PYSIDE 7: Remove "if" --> + <modify-function signature="getIntSpan3_OpaqueContainer()"> + <modify-argument index="return"> + <replace-type modified-type="StdIntSpan3"/> + </modify-argument> + </modify-function> + <?endif?> + </value-type> + + <value-type name="MinBoolUser"/> + + <value-type name="ContainerUser"> + <modify-function signature="intVector()"> + <modify-argument index="return"> + <replace-type modified-type="StdIntVector"/> + </modify-argument> + </modify-function> + <modify-function signature="intArray()"> + <modify-argument index="return"> + <replace-type modified-type="StdIntArray"/> + </modify-argument> + </modify-function> + </value-type> + + <!-- Test wrapping of a typedef --> + <function signature="arrayFuncInt(std::vector<int>)" /> + <!-- Note manual expansion of the typedef --> + <function signature="arrayFuncIntTypedef(std::vector<int>)" /> + + <function signature="arrayFuncIntReturn(int)" /> + <function signature="arrayFuncIntReturnTypedef(int)" /> + + <!-- Test wrapping of a typedef of a typedef --> + <function signature="arrayFunc(std::vector<int>)" /> + <!-- Note manual expansion of the typedef --> + <function signature="arrayFuncTypedef(std::vector<int>)" /> + + <function signature="arrayFuncReturn(int)" /> + <function signature="arrayFuncReturnTypedef(int)" /> +</typesystem> diff --git a/sources/shiboken6/tests/minimalbinding/val_test.py b/sources/shiboken6/tests/minimalbinding/val_test.py new file mode 100644 index 000000000..25642dc3f --- /dev/null +++ b/sources/shiboken6/tests/minimalbinding/val_test.py @@ -0,0 +1,95 @@ +#!/usr/bin/env python +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +from __future__ import annotations + +import os +import sys +import unittest + +from pathlib import Path +sys.path.append(os.fspath(Path(__file__).resolve().parents[1])) +from shiboken_paths import init_paths +init_paths() +from minimal import Val + + +class ExtVal(Val): + def __init__(self, valId): + Val.__init__(self, valId) + + def passValueType(self, val): + return ExtVal(val.valId() + 1) + + def passValueTypePointer(self, val): + val.setValId(val.valId() + 1) + return val + + def passValueTypeReference(self, val): + val.setValId(val.valId() + 1) + return val + + +class ValTest(unittest.TestCase): + + def testNormalMethod(self): + valId = 123 + val = Val(valId) + self.assertEqual(val.valId(), valId) + + def testPassValueType(self): + val = Val(123) + val1 = val.passValueType(val) + self.assertNotEqual(val, val1) + self.assertEqual(val1.valId(), 123) + val2 = val.callPassValueType(val) + self.assertNotEqual(val, val2) + self.assertEqual(val2.valId(), 123) + + def testPassValueTypePointer(self): + val = Val(0) + self.assertEqual(val, val.passValueTypePointer(val)) + self.assertEqual(val, val.callPassValueTypePointer(val)) + + def testPassValueTypeReference(self): + val = Val(0) + self.assertEqual(val, val.passValueTypeReference(val)) + self.assertEqual(val, val.callPassValueTypeReference(val)) + + def testPassAndReceiveEnumValue(self): + val = Val(0) + self.assertEqual(val.oneOrTheOtherEnumValue(Val.One), Val.Other) + self.assertEqual(val.oneOrTheOtherEnumValue(Val.Other), Val.One) + + def testPassValueTypeFromExtendedClass(self): + val = ExtVal(0) + val1 = val.passValueType(val) + self.assertNotEqual(val, val1) + self.assertEqual(val1.valId(), val.valId() + 1) + val2 = val.callPassValueType(val) + self.assertNotEqual(val, val2) + self.assertEqual(val2.valId(), val.valId() + 1) + + def testPassValueTypePointerFromExtendedClass(self): + val = ExtVal(0) + self.assertEqual(val.valId(), 0) + sameVal = val.passValueTypePointer(val) + self.assertEqual(val, sameVal) + self.assertEqual(sameVal.valId(), 1) + sameVal = val.callPassValueTypePointer(val) + self.assertEqual(val, sameVal) + self.assertEqual(sameVal.valId(), 2) + + def testPassValueTypeReferenceFromExtendedClass(self): + val = ExtVal(0) + self.assertEqual(val.valId(), 0) + sameVal = val.passValueTypeReference(val) + self.assertEqual(val, sameVal) + self.assertEqual(sameVal.valId(), 1) + sameVal = val.callPassValueTypeReference(val) + self.assertEqual(val, sameVal) + self.assertEqual(sameVal.valId(), 2) + + +if __name__ == '__main__': + unittest.main() |