summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--pyuno/qa/pytests/testcollections_XCellRange.py34
-rw-r--r--pyuno/qa/pytests/testcollections_XEnumeration.py11
-rw-r--r--pyuno/qa/pytests/testcollections_XEnumerationAccess.py15
-rw-r--r--pyuno/qa/pytests/testcollections_XIndexAccess.py24
-rw-r--r--pyuno/qa/pytests/testcollections_XIndexContainer.py2
-rw-r--r--pyuno/qa/pytests/testcollections_XIndexReplace.py18
-rw-r--r--pyuno/qa/pytests/testcollections_XNameAccess.py22
-rw-r--r--pyuno/qa/pytests/testcollections_XNameContainer.py12
-rw-r--r--pyuno/qa/pytests/testcollections_XNameReplace.py6
-rw-r--r--pyuno/qa/pytests/testcollections_misc.py8
-rw-r--r--pyuno/qa/pytests/testcollections_mixednameindex.py2
-rw-r--r--pyuno/source/module/pyuno_module.cxx33
-rw-r--r--sfx2/qa/python/check_sidebar.py3
-rw-r--r--sfx2/qa/python/check_sidebar_registry.py1
-rw-r--r--solenv/gbuild/PythonTest.mk7
-rw-r--r--sw/qa/python/check_bookmarks.py4
-rw-r--r--sw/qa/python/check_change_color.py1
-rw-r--r--sw/qa/python/check_cross_references.py4
-rw-r--r--sw/qa/python/check_fields.py8
-rw-r--r--sw/qa/python/check_flies.py8
-rw-r--r--sw/qa/python/check_indexed_property_values.py1
-rw-r--r--sw/qa/python/check_named_property_values.py1
-rw-r--r--sw/qa/python/check_table.py4
-rw-r--r--sw/qa/python/get_expression.py4
-rw-r--r--sw/qa/python/set_expression.py4
-rw-r--r--sw/qa/python/text_portion_enumeration_test.py5
-rw-r--r--sw/qa/python/var_fields.py3
-rw-r--r--test/source/bootstrapfixture.cxx6
-rw-r--r--unotest/source/python/org/libreoffice/unittest.py29
-rw-r--r--unotest/source/python/org/libreoffice/unotest.py7
30 files changed, 266 insertions, 21 deletions
diff --git a/pyuno/qa/pytests/testcollections_XCellRange.py b/pyuno/qa/pytests/testcollections_XCellRange.py
index 6754ef52814c..2e0ef8a7d3d7 100644
--- a/pyuno/qa/pytests/testcollections_XCellRange.py
+++ b/pyuno/qa/pytests/testcollections_XCellRange.py
@@ -43,6 +43,8 @@ class TestXCellRange(CollectionsTestBase):
self.assertEqual(0, cell.CellAddress.Row)
self.assertEqual(0, cell.CellAddress.Column)
+ spr.close(True)
+
# Tests syntax:
# cell = cellrange[0,0] # Access cell by indices
# For:
@@ -63,6 +65,8 @@ class TestXCellRange(CollectionsTestBase):
# Then
self.assertEqual('A1', cell.CellName)
+ doc.close(True)
+
# Tests syntax:
# cell = cellrange[0,0] # Access cell by indices
# For:
@@ -81,6 +85,8 @@ class TestXCellRange(CollectionsTestBase):
self.assertEqual(3, rng.CellAddress.Row)
self.assertEqual(7, rng.CellAddress.Column)
+ spr.close(True)
+
# Tests syntax:
# cell = cellrange[0,0] # Access cell by indices
# For:
@@ -101,6 +107,8 @@ class TestXCellRange(CollectionsTestBase):
# Then
self.assertEqual('H4', cell.CellName)
+ doc.close(True)
+
# Tests syntax:
# rng = cellrange[0,1:2] # Access cell range by index,slice
# For:
@@ -120,6 +128,8 @@ class TestXCellRange(CollectionsTestBase):
self.assertEqual(0, rng.RangeAddress.EndRow)
self.assertEqual(2, rng.RangeAddress.EndColumn)
+ spr.close(True)
+
# Tests syntax:
# rng = cellrange[0,1:2] # Access cell range by index,slice
# For:
@@ -142,6 +152,8 @@ class TestXCellRange(CollectionsTestBase):
# Then
self.assertEqual((('101', '102'),), rng.DataArray)
+ doc.close(True)
+
# Tests syntax:
# rng = cellrange[1:2,0] # Access cell range by slice,index
# For:
@@ -161,6 +173,8 @@ class TestXCellRange(CollectionsTestBase):
self.assertEqual(2, rng.RangeAddress.EndRow)
self.assertEqual(0, rng.RangeAddress.EndColumn)
+ spr.close(True)
+
# Tests syntax:
# rng = cellrange[1:2,0] # Access cell range by index,slice
# For:
@@ -183,6 +197,8 @@ class TestXCellRange(CollectionsTestBase):
# Then
self.assertEqual((('110',), ('120',)), rng.DataArray)
+ doc.close(True)
+
# Tests syntax:
# rng = cellrange[0:1,2:3] # Access cell range by slices
# For:
@@ -202,6 +218,8 @@ class TestXCellRange(CollectionsTestBase):
self.assertEqual(2, rng.RangeAddress.EndRow)
self.assertEqual(4, rng.RangeAddress.EndColumn)
+ spr.close(True)
+
# Tests syntax:
# rng = cellrange[0:1,2:3] # Access cell range by slices
# For:
@@ -218,6 +236,8 @@ class TestXCellRange(CollectionsTestBase):
with self.assertRaises(KeyError):
rng = sht[1:3, 3:3]
+ spr.close(True)
+
# Tests syntax:
# rng = cellrange[0:1,2:3] # Access cell range by slices
# For:
@@ -240,6 +260,8 @@ class TestXCellRange(CollectionsTestBase):
# Then
self.assertEqual((('113', '114'), ('123', '124')), rng.DataArray)
+ doc.close(True)
+
# Tests syntax:
# rng = cellrange['A1:B2'] # Access cell range by descriptor
# For:
@@ -259,6 +281,8 @@ class TestXCellRange(CollectionsTestBase):
self.assertEqual(3, rng.RangeAddress.EndRow)
self.assertEqual(1, rng.RangeAddress.EndColumn)
+ spr.close(True)
+
# Tests syntax:
# rng = cellrange['A1:B2'] # Access cell range by descriptor
# For:
@@ -281,6 +305,8 @@ class TestXCellRange(CollectionsTestBase):
# Then
self.assertEqual((('120', '121'), ('130', '131')), rng.DataArray)
+ doc.close(True)
+
# Tests syntax:
# rng = cellrange['Name'] # Access cell range by name
# For:
@@ -303,6 +329,8 @@ class TestXCellRange(CollectionsTestBase):
self.assertEqual(9, rng.RangeAddress.EndRow)
self.assertEqual(5, rng.RangeAddress.EndColumn)
+ spr.close(True)
+
# Tests syntax:
# rng = cellrange[0] # Access cell range by row index
# For:
@@ -322,6 +350,8 @@ class TestXCellRange(CollectionsTestBase):
self.assertEqual(0, rng.RangeAddress.EndRow)
self.assertEqual(1023, rng.RangeAddress.EndColumn)
+ spr.close(True)
+
# Tests syntax:
# rng = cellrange[0,:] # Access cell range by row index
# For:
@@ -341,6 +371,8 @@ class TestXCellRange(CollectionsTestBase):
self.assertEqual(0, rng.RangeAddress.EndRow)
self.assertEqual(1023, rng.RangeAddress.EndColumn)
+ spr.close(True)
+
# Tests syntax:
# rng = cellrange[:,0] # Access cell range by column index
# For:
@@ -360,6 +392,8 @@ class TestXCellRange(CollectionsTestBase):
self.assertEqual(1048575, rng.RangeAddress.EndRow)
self.assertEqual(0, rng.RangeAddress.EndColumn)
+ spr.close(True)
+
if __name__ == '__main__':
unittest.main()
diff --git a/pyuno/qa/pytests/testcollections_XEnumeration.py b/pyuno/qa/pytests/testcollections_XEnumeration.py
index 6edc77f44952..8d1f8eece046 100644
--- a/pyuno/qa/pytests/testcollections_XEnumeration.py
+++ b/pyuno/qa/pytests/testcollections_XEnumeration.py
@@ -38,6 +38,8 @@ class TestXEnumeration(CollectionsTestBase):
# Then
self.assertEqual(1, len(paragraphs))
+ doc.close(True)
+
# Tests syntax:
# if val in itr: ... # Test value presence
# For:
@@ -54,6 +56,8 @@ class TestXEnumeration(CollectionsTestBase):
# Then
self.assertTrue(result)
+ doc.close(True)
+
# Tests syntax:
# if val in itr: ... # Test value presence
# For:
@@ -71,6 +75,9 @@ class TestXEnumeration(CollectionsTestBase):
# Then
self.assertFalse(result)
+ doc1.close(True)
+ doc2.close(True)
+
# Tests syntax:
# if val in itr: ... # Test value presence
# For:
@@ -86,6 +93,8 @@ class TestXEnumeration(CollectionsTestBase):
# Then
self.assertFalse(result)
+ doc.close(True)
+
# Tests syntax:
# if val in itr: ... # Test value presence
# For:
@@ -104,6 +113,8 @@ class TestXEnumeration(CollectionsTestBase):
# Then
self.assertFalse(result)
+ doc.close(True)
+
if __name__ == '__main__':
unittest.main()
diff --git a/pyuno/qa/pytests/testcollections_XEnumerationAccess.py b/pyuno/qa/pytests/testcollections_XEnumerationAccess.py
index dc5a52f54537..a62b05ce9c5f 100644
--- a/pyuno/qa/pytests/testcollections_XEnumerationAccess.py
+++ b/pyuno/qa/pytests/testcollections_XEnumerationAccess.py
@@ -37,6 +37,8 @@ class TestXEnumerationAccess(CollectionsTestBase):
# Then
self.assertEqual(1, len(paragraphs))
+ doc.close(True)
+
# Tests syntax:
# itr = iter(obj) # Named iterator
# For:
@@ -53,6 +55,8 @@ class TestXEnumerationAccess(CollectionsTestBase):
with self.assertRaises(StopIteration):
next(itr)
+ doc.close(True)
+
# Tests syntax:
# if val in obj: ... # Test value presence
# For:
@@ -68,6 +72,8 @@ class TestXEnumerationAccess(CollectionsTestBase):
# Then
self.assertTrue(result)
+ doc.close(True)
+
# Tests syntax:
# if val in obj: ... # Test value presence
# For:
@@ -84,6 +90,9 @@ class TestXEnumerationAccess(CollectionsTestBase):
# Then
self.assertFalse(result)
+ doc1.close(True)
+ doc2.close(True)
+
# Tests syntax:
# if val in obj: ... # Test value presence
# For:
@@ -98,6 +107,8 @@ class TestXEnumerationAccess(CollectionsTestBase):
# Then
self.assertFalse(result)
+ doc.close(True)
+
# Tests syntax:
# if val in obj: ... # Test value presence
# For:
@@ -112,6 +123,8 @@ class TestXEnumerationAccess(CollectionsTestBase):
# Then
self.assertFalse(result)
+ doc.close(True)
+
# Tests syntax:
# if val in obj: ... # Test value presence
# For:
@@ -124,6 +137,8 @@ class TestXEnumerationAccess(CollectionsTestBase):
with self.assertRaises(TypeError):
result = {} in doc.Text
+ doc.close(True)
+
if __name__ == '__main__':
unittest.main()
diff --git a/pyuno/qa/pytests/testcollections_XIndexAccess.py b/pyuno/qa/pytests/testcollections_XIndexAccess.py
index 4631ca3706ed..7228ed87336b 100644
--- a/pyuno/qa/pytests/testcollections_XIndexAccess.py
+++ b/pyuno/qa/pytests/testcollections_XIndexAccess.py
@@ -77,6 +77,8 @@ class TestXIndexAccess(CollectionsTestBase):
# Then
self.assertEqual(0, count)
+ doc.close(True);
+
# Tests syntax:
# num = len(obj) # Number of elements
# For:
@@ -94,6 +96,8 @@ class TestXIndexAccess(CollectionsTestBase):
# Then
self.assertEqual(1, count)
+ doc.close(True);
+
# Tests syntax:
# val = obj[0] # Access by index
# For:
@@ -117,6 +121,7 @@ class TestXIndexAccess(CollectionsTestBase):
self.readValuesTestFixture(doc, 2, 1, 1)
self.readValuesTestFixture(doc, 2, 2, IndexError)
self.readValuesTestFixture(doc, 2, 3, IndexError)
+ doc.close(True);
def test_XIndexAccess_ReadIndex_Single_Invalid(self):
doc = self.createBlankTextDocument()
@@ -126,6 +131,7 @@ class TestXIndexAccess(CollectionsTestBase):
self.readValuesTestFixture(doc, 0, (0, 1), TypeError)
self.readValuesTestFixture(doc, 0, [0, 1], TypeError)
self.readValuesTestFixture(doc, 0, {'a': 'b'}, TypeError)
+ doc.close(True);
# Tests syntax:
# val1,val2 = obj[2:4] # Access by slice
@@ -139,6 +145,7 @@ class TestXIndexAccess(CollectionsTestBase):
key = slice(j, k)
expected = t[key]
self.readValuesTestFixture(doc, i, key, expected)
+ doc.close(True);
# Tests syntax:
# val1,val2 = obj[0:3:2] # Access by extended slice
@@ -153,6 +160,7 @@ class TestXIndexAccess(CollectionsTestBase):
key = slice(j, k, l)
expected = t[key]
self.readValuesTestFixture(doc, i, key, expected)
+ doc.close(True);
# Tests syntax:
# if val in obj: ... # Test value presence
@@ -173,6 +181,8 @@ class TestXIndexAccess(CollectionsTestBase):
# Then
self.assertTrue(present)
+ doc.close(True);
+
# Tests syntax:
# if val in obj: ... # Test value presence
# For:
@@ -187,6 +197,8 @@ class TestXIndexAccess(CollectionsTestBase):
# Then
self.assertFalse(present)
+ doc.close(True);
+
# Tests syntax:
# if val in obj: ... # Test value presence
# For:
@@ -201,6 +213,8 @@ class TestXIndexAccess(CollectionsTestBase):
# Then
self.assertFalse(present)
+ doc.close(True);
+
# Tests syntax:
# if val in obj: ... # Test value presence
# For:
@@ -213,6 +227,8 @@ class TestXIndexAccess(CollectionsTestBase):
with self.assertRaises(TypeError):
present = {} in doc.Footnotes
+ doc.close(True);
+
# Tests syntax:
# for val in obj: ... # Implicit iterator (values)
# For:
@@ -229,6 +245,8 @@ class TestXIndexAccess(CollectionsTestBase):
# Then
self.assertEqual(0, len(read_footnotes))
+ doc.close(True);
+
# Tests syntax:
# for val in obj: ... # Implicit iterator (values)
# For:
@@ -250,6 +268,8 @@ class TestXIndexAccess(CollectionsTestBase):
self.assertEqual(1, len(read_footnotes))
self.assertEqual('foo', read_footnotes[0].Label)
+ doc.close(True);
+
# Tests syntax:
# for val in obj: ... # Implicit iterator (values)
# For:
@@ -275,6 +295,8 @@ class TestXIndexAccess(CollectionsTestBase):
self.assertEqual('foo', read_footnotes[0].Label)
self.assertEqual('bar', read_footnotes[1].Label)
+ doc.close(True);
+
# Tests syntax:
# itr = iter(obj) # Named iterator (values)
# For:
@@ -295,6 +317,8 @@ class TestXIndexAccess(CollectionsTestBase):
with self.assertRaises(StopIteration):
next(itr)
+ doc.close(True);
+
if __name__ == '__main__':
unittest.main()
diff --git a/pyuno/qa/pytests/testcollections_XIndexContainer.py b/pyuno/qa/pytests/testcollections_XIndexContainer.py
index 7bf9e5223039..73be6b57c25d 100644
--- a/pyuno/qa/pytests/testcollections_XIndexContainer.py
+++ b/pyuno/qa/pytests/testcollections_XIndexContainer.py
@@ -145,6 +145,8 @@ class TestXIndexContainer(CollectionsTestBase):
# Then
self.assertEqual('foo', doc.DrawPage.Forms[0].Name)
+ doc.close(True)
+
# Tests syntax:
# obj[0:3:2] = val1,val2 # Replace by extended slice
# For:
diff --git a/pyuno/qa/pytests/testcollections_XIndexReplace.py b/pyuno/qa/pytests/testcollections_XIndexReplace.py
index 45d1cc075f33..bbf424f0bdfb 100644
--- a/pyuno/qa/pytests/testcollections_XIndexReplace.py
+++ b/pyuno/qa/pytests/testcollections_XIndexReplace.py
@@ -78,6 +78,8 @@ class TestXIndexReplace(CollectionsTestBase):
# Then
self.assertEqual(('Caption',), index.LevelParagraphStyles[0])
+ doc.close(True)
+
# Tests syntax:
# obj[0] = val # Replace by index
# For:
@@ -91,6 +93,8 @@ class TestXIndexReplace(CollectionsTestBase):
with self.assertRaises(TypeError):
index.LevelParagraphStyles[0] = None
+ doc.close(True)
+
# Tests syntax:
# obj[0] = val # Replace by index
# For:
@@ -104,6 +108,8 @@ class TestXIndexReplace(CollectionsTestBase):
with self.assertRaises(TypeError):
index.LevelParagraphStyles[0] = 'foo'
+ doc.close(True)
+
# Tests syntax:
# obj[0] = val # Replace by index
# For:
@@ -117,6 +123,8 @@ class TestXIndexReplace(CollectionsTestBase):
with self.assertRaises(TypeError):
index.LevelParagraphStyles[0] = 12.34
+ doc.close(True)
+
# Tests syntax:
# obj[0] = val # Replace by index
# For:
@@ -130,6 +138,8 @@ class TestXIndexReplace(CollectionsTestBase):
with self.assertRaises(TypeError):
index.LevelParagraphStyles[0] = [0, 1]
+ doc.close(True)
+
# Tests syntax:
# obj[0] = val # Replace by index
# For:
@@ -143,6 +153,8 @@ class TestXIndexReplace(CollectionsTestBase):
with self.assertRaises(TypeError):
index.LevelParagraphStyles[0] = {'a': 'b'}
+ doc.close(True)
+
# Tests syntax:
# obj[0] = val # Replace by index
# For:
@@ -156,6 +168,8 @@ class TestXIndexReplace(CollectionsTestBase):
with self.assertRaises(TypeError):
index.LevelParagraphStyles[0] = ('Caption', ())
+ doc.close(True)
+
# Tests syntax:
# obj[2:4] = val1,val2 # Replace by slice
# For:
@@ -177,6 +191,7 @@ class TestXIndexReplace(CollectionsTestBase):
if (len(expected) != 10):
expected = ValueError()
self.assignValuesTestFixture(doc, key, assign, expected)
+ doc.close(True)
# Tests syntax:
# obj[2:4] = val1,val2 # Replace by slice
@@ -194,6 +209,8 @@ class TestXIndexReplace(CollectionsTestBase):
12.34
)
+ doc.close(True)
+
# Tests syntax:
# obj[0:3:2] = val1,val2 # Replace by extended slice
# For:
@@ -214,6 +231,7 @@ class TestXIndexReplace(CollectionsTestBase):
except Exception as e:
expected = e
self.assignValuesTestFixture(doc, key, assign, expected)
+ doc.close(True)
if __name__ == '__main__':
diff --git a/pyuno/qa/pytests/testcollections_XNameAccess.py b/pyuno/qa/pytests/testcollections_XNameAccess.py
index a93064e78bb1..7f987a370077 100644
--- a/pyuno/qa/pytests/testcollections_XNameAccess.py
+++ b/pyuno/qa/pytests/testcollections_XNameAccess.py
@@ -35,6 +35,8 @@ class TestXNameAccess(CollectionsTestBase):
# Then
self.assertEqual(2, length)
+ drw.close(True)
+
# Tests syntax:
# val = obj[key] # Access by key
# For:
@@ -50,6 +52,8 @@ class TestXNameAccess(CollectionsTestBase):
# Then
self.assertEqual('foo', link.getName())
+ drw.close(True)
+
# Tests syntax:
# val = obj[key] # Access by key
# For:
@@ -62,6 +66,8 @@ class TestXNameAccess(CollectionsTestBase):
with self.assertRaises(KeyError):
link = drw.Links['foo']
+ drw.close(True)
+
# Tests syntax:
# val = obj[key] # Access by key
# For:
@@ -74,6 +80,8 @@ class TestXNameAccess(CollectionsTestBase):
with self.assertRaises(TypeError):
link = drw.Links[None]
+ drw.close(True)
+
# Tests syntax:
# val = obj[key] # Access by key
# For:
@@ -86,6 +94,8 @@ class TestXNameAccess(CollectionsTestBase):
with self.assertRaises(TypeError):
link = drw.Links[12.34]
+ drw.close(True)
+
# Tests syntax:
# val = obj[key] # Access by key
# For:
@@ -98,6 +108,8 @@ class TestXNameAccess(CollectionsTestBase):
with self.assertRaises(TypeError):
link = drw.Links[(1, 2)]
+ drw.close(True)
+
# Tests syntax:
# val = obj[key] # Access by key
# For:
@@ -110,6 +122,8 @@ class TestXNameAccess(CollectionsTestBase):
with self.assertRaises(TypeError):
link = drw.Links[[1, 2]]
+ drw.close(True)
+
# Tests syntax:
# val = obj[key] # Access by key
# For:
@@ -122,6 +136,8 @@ class TestXNameAccess(CollectionsTestBase):
with self.assertRaises(TypeError):
link = drw.Links[{'a': 'b'}]
+ drw.close(True)
+
# Tests syntax:
# if key in obj: ... # Test key presence
# For:
@@ -137,6 +153,8 @@ class TestXNameAccess(CollectionsTestBase):
# Then
self.assertTrue(present)
+ drw.close(True)
+
# Tests syntax:
# for key in obj: ... # Implicit iterator (keys)
# For:
@@ -157,6 +175,8 @@ class TestXNameAccess(CollectionsTestBase):
# Then
self.assertEqual(['foo0', 'foo1'], read_links)
+ drw.close(True)
+
# Tests syntax:
# itr = iter(obj) # Named iterator (keys)
# For:
@@ -174,6 +194,8 @@ class TestXNameAccess(CollectionsTestBase):
with self.assertRaises(StopIteration):
next(itr)
+ drw.close(True)
+
if __name__ == '__main__':
unittest.main()
diff --git a/pyuno/qa/pytests/testcollections_XNameContainer.py b/pyuno/qa/pytests/testcollections_XNameContainer.py
index 48b63a786f7e..5c8b676c0f6e 100644
--- a/pyuno/qa/pytests/testcollections_XNameContainer.py
+++ b/pyuno/qa/pytests/testcollections_XNameContainer.py
@@ -41,6 +41,8 @@ class TestXNameContainer(CollectionsTestBase):
# Then
self.assertEqual(1, len(ranges.ElementNames))
+ spr.close(True)
+
# Tests syntax:
# obj[key] = val # Insert by key
# For:
@@ -55,6 +57,8 @@ class TestXNameContainer(CollectionsTestBase):
with self.assertRaises(TypeError):
ranges[12.34] = new_range
+ spr.close(True)
+
# Tests syntax:
# obj[key] = val # Replace by key
def test_XNameContainer_ReplaceName(self):
@@ -73,6 +77,8 @@ class TestXNameContainer(CollectionsTestBase):
read_range = ranges['foo']
self.assertEqual(6, read_range.CellAddress.Column)
+ spr.close(True)
+
# Tests syntax:
# del obj[key] # Delete by key
# For:
@@ -89,6 +95,8 @@ class TestXNameContainer(CollectionsTestBase):
self.assertEqual(1, len(spr.Sheets))
self.assertFalse('foo' in spr.Sheets)
+ spr.close(True)
+
# Tests syntax:
# del obj[key] # Delete by key
# For:
@@ -101,6 +109,8 @@ class TestXNameContainer(CollectionsTestBase):
with self.assertRaises(KeyError):
del spr.Sheets['foo']
+ spr.close(True)
+
# Tests syntax:
# del obj[key] # Delete by key
# For:
@@ -113,6 +123,8 @@ class TestXNameContainer(CollectionsTestBase):
with self.assertRaises(TypeError):
del spr.Sheets[12.34]
+ spr.close(True)
+
if __name__ == '__main__':
unittest.main()
diff --git a/pyuno/qa/pytests/testcollections_XNameReplace.py b/pyuno/qa/pytests/testcollections_XNameReplace.py
index 2176f935d9dc..18476fd2b447 100644
--- a/pyuno/qa/pytests/testcollections_XNameReplace.py
+++ b/pyuno/qa/pytests/testcollections_XNameReplace.py
@@ -40,6 +40,8 @@ class TestXNameReplace(CollectionsTestBase):
on_save = [p.Value for p in doc.Events['OnSave'] if p.Name == 'Script'][0]
self.assertEqual(getScriptName(), on_save)
+ doc.close(True)
+
# Tests syntax:
# obj[key] = val # Replace by key
# For:
@@ -53,6 +55,8 @@ class TestXNameReplace(CollectionsTestBase):
with self.assertRaises(KeyError):
doc.Events['qqqqq'] = event_properties
+ doc.close(True)
+
# Tests syntax:
# obj[key] = val # Replace by key
# For:
@@ -66,6 +70,8 @@ class TestXNameReplace(CollectionsTestBase):
with self.assertRaises(TypeError):
doc.Events[12.34] = event_properties
+ doc.close(True)
+
if __name__ == '__main__':
unittest.main()
diff --git a/pyuno/qa/pytests/testcollections_misc.py b/pyuno/qa/pytests/testcollections_misc.py
index 04dcf595931a..1dba098eeccd 100644
--- a/pyuno/qa/pytests/testcollections_misc.py
+++ b/pyuno/qa/pytests/testcollections_misc.py
@@ -32,6 +32,8 @@ class TestMisc(CollectionsTestBase):
for val in doc.UIConfigurationManager:
pass
+ doc.close(True)
+
# Tests syntax:
# if val in itr: ... # Test value presence
# For:
@@ -44,6 +46,8 @@ class TestMisc(CollectionsTestBase):
with self.assertRaises(TypeError):
foo = "bar" in doc.UIConfigurationManager
+ doc.close(True)
+
# Tests syntax:
# num = len(obj) # Number of elements
# For:
@@ -56,6 +60,8 @@ class TestMisc(CollectionsTestBase):
with self.assertRaises(TypeError):
len(doc.UIConfigurationManager)
+ doc.close(True)
+
# Tests syntax:
# val = obj[0] # Access by index
# For:
@@ -68,6 +74,8 @@ class TestMisc(CollectionsTestBase):
with self.assertRaises(TypeError):
doc.UIConfigurationManager[0]
+ doc.close(True)
+
if __name__ == '__main__':
unittest.main()
diff --git a/pyuno/qa/pytests/testcollections_mixednameindex.py b/pyuno/qa/pytests/testcollections_mixednameindex.py
index 67e97a88dd90..b4c7958c6996 100644
--- a/pyuno/qa/pytests/testcollections_mixednameindex.py
+++ b/pyuno/qa/pytests/testcollections_mixednameindex.py
@@ -41,6 +41,8 @@ class TestMixedNameIndex(CollectionsTestBase):
self.assertEqual('foo', table_by_index.Name)
self.assertEqual(table_by_name, table_by_index)
+ doc.close(True)
+
if __name__ == '__main__':
unittest.main()
diff --git a/pyuno/source/module/pyuno_module.cxx b/pyuno/source/module/pyuno_module.cxx
index e212e8de9f8d..0f08ebc53367 100644
--- a/pyuno/source/module/pyuno_module.cxx
+++ b/pyuno/source/module/pyuno_module.cxx
@@ -22,6 +22,7 @@
#include "pyuno_impl.hxx"
+#include <cassert>
#include <unordered_map>
#include <utility>
@@ -318,12 +319,22 @@ static PyObject* getComponentContext(
return ret.getAcquired();
}
+// While pyuno.private_initTestEnvironment is called from individual Python tests (e.g., from
+// UnoInProcess in unotest/source/python/org/libreoffice/unotest.py, which makes sure to call it
+// only once), pyuno.private_deinitTestEnvironment is called centrally from
+// unotest/source/python/org/libreoffice/unittest.py at the end of every PythonTest (to DeInitVCL
+// exactly once near the end of the process, if InitVCL has ever been called via
+// pyuno.private_initTestEnvironment):
+
+static osl::Module * testModule = nullptr;
+
static PyObject* initTestEnvironment(
SAL_UNUSED_PARAMETER PyObject*, SAL_UNUSED_PARAMETER PyObject*)
{
// this tries to bootstrap enough of the soffice from python to run
// unit tests, which is only possible indirectly because pyuno is URE
// so load "test" library and invoke a function there to do the work
+ assert(testModule == nullptr);
try
{
PyObject *const ctx(getComponentContext(nullptr, nullptr));
@@ -353,6 +364,7 @@ static PyObject* initTestEnvironment(
mod.getFunctionSymbol("test_init"));
if (!pFunc) { abort(); }
reinterpret_cast<void (SAL_CALL *)(XMultiServiceFactory*)>(pFunc)(xMSF.get());
+ testModule = &mod;
}
catch (const css::uno::Exception &)
{
@@ -361,6 +373,26 @@ static PyObject* initTestEnvironment(
return Py_None;
}
+static PyObject* deinitTestEnvironment(
+ SAL_UNUSED_PARAMETER PyObject*, SAL_UNUSED_PARAMETER PyObject*)
+{
+ if (testModule != nullptr)
+ {
+ try
+ {
+ oslGenericFunction const pFunc(
+ testModule->getFunctionSymbol("test_deinit"));
+ if (!pFunc) { abort(); }
+ reinterpret_cast<void (SAL_CALL *)()>(pFunc)();
+ }
+ catch (const css::uno::Exception &)
+ {
+ abort();
+ }
+ }
+ return Py_None;
+}
+
PyObject * extractOneStringArg( PyObject *args, char const *funcName )
{
if( !PyTuple_Check( args ) || PyTuple_Size( args) != 1 )
@@ -843,6 +875,7 @@ static PyObject *sal_debug(
struct PyMethodDef PyUNOModule_methods [] =
{
{"private_initTestEnvironment", initTestEnvironment, METH_VARARGS, nullptr},
+ {"private_deinitTestEnvironment", deinitTestEnvironment, METH_VARARGS, nullptr},
{"getComponentContext", getComponentContext, METH_VARARGS, nullptr},
{"_createUnoStructHelper", reinterpret_cast<PyCFunction>(createUnoStructHelper), METH_VARARGS | METH_KEYWORDS, nullptr},
{"getTypeByName", getTypeByName, METH_VARARGS, nullptr},
diff --git a/sfx2/qa/python/check_sidebar.py b/sfx2/qa/python/check_sidebar.py
index e8fd50338b27..59cc955b8016 100644
--- a/sfx2/qa/python/check_sidebar.py
+++ b/sfx2/qa/python/check_sidebar.py
@@ -24,7 +24,6 @@ class CheckSidebar(unittest.TestCase):
def setUpClass(cls):
cls._uno = UnoInProcess()
cls._uno.setUp()
- cls._xDoc = cls._uno.openEmptyDoc( url = "private:factory/scalc", bHidden = False, bReadOnly = False)
@classmethod
def tearDownClass(cls):
@@ -32,7 +31,7 @@ class CheckSidebar(unittest.TestCase):
def test_check_sidebar(self):
- xDoc = self.__class__._xDoc
+ xDoc = self.__class__._uno.openEmptyDoc( url = "private:factory/scalc", bHidden = False, bReadOnly = False)
xController = xDoc.getCurrentController()
xSidebar = xController.getSidebar()
diff --git a/sfx2/qa/python/check_sidebar_registry.py b/sfx2/qa/python/check_sidebar_registry.py
index 86f22f4fd44a..47b8eecdefb9 100644
--- a/sfx2/qa/python/check_sidebar_registry.py
+++ b/sfx2/qa/python/check_sidebar_registry.py
@@ -19,7 +19,6 @@ class CheckSidebarRegistry(unittest.TestCase):
def setUpClass(cls):
cls._uno = UnoInProcess()
cls._uno.setUp()
- cls._xDoc = cls._uno.openEmptyDoc( url = "private:factory/scalc", bHidden = False, bReadOnly = False)
@classmethod
def tearDownClass(cls):
diff --git a/solenv/gbuild/PythonTest.mk b/solenv/gbuild/PythonTest.mk
index a2bac3819e02..329009c4b1d2 100644
--- a/solenv/gbuild/PythonTest.mk
+++ b/solenv/gbuild/PythonTest.mk
@@ -21,7 +21,7 @@ gb_PythonTest_EXECUTABLE_GDB := $(PYTHON_FOR_BUILD)
gb_PythonTest_DEPS :=
endif
-gb_PythonTest_COMMAND := $(gb_PythonTest_EXECUTABLE) -m unittest
+gb_PythonTest_COMMAND := $(gb_PythonTest_EXECUTABLE) -m org.libreoffice.unittest
.PHONY : $(call gb_PythonTest_get_clean_target,%)
$(call gb_PythonTest_get_clean_target,%) :
@@ -31,7 +31,10 @@ $(call gb_PythonTest_get_clean_target,%) :
ifneq ($(DISABLE_PYTHON),TRUE)
.PHONY : $(call gb_PythonTest_get_target,%)
-$(call gb_PythonTest_get_target,%) :| $(gb_PythonTest_DEPS)
+$(call gb_PythonTest_get_target,%) :\
+ $(call gb_Library_get_target,pyuno) \
+ $(if $(filter-out WNT,$(OS)),$(call gb_Library_get_target,pyuno_wrapper)) \
+ | $(gb_PythonTest_DEPS)
ifneq ($(gb_SUPPRESS_TESTS),)
@true
else
diff --git a/sw/qa/python/check_bookmarks.py b/sw/qa/python/check_bookmarks.py
index 73fd9bb6b98e..8210b4eb005a 100644
--- a/sw/qa/python/check_bookmarks.py
+++ b/sw/qa/python/check_bookmarks.py
@@ -47,6 +47,10 @@ class CheckBookmarks(unittest.TestCase):
@classmethod
def tearDownClass(cls):
cls._uno.tearDown()
+ # HACK in case cls._xDoc holds a UNO proxy to an SwXTextDocument (whose dtor calls
+ # Application::GetSolarMutex via sw::UnoImplPtrDeleter), which would potentially only be
+ # garbage-collected after VCL has already been deinitialized:
+ cls._xDoc = None
def test_bookmarks(self):
self.xDoc = self.__class__._xDoc
diff --git a/sw/qa/python/check_change_color.py b/sw/qa/python/check_change_color.py
index d8562bc77b52..07b622031a61 100644
--- a/sw/qa/python/check_change_color.py
+++ b/sw/qa/python/check_change_color.py
@@ -27,7 +27,6 @@ class CheckChangeColor(unittest.TestCase):
def setUpClass(cls):
cls._uno = UnoInProcess()
cls._uno.setUp()
- cls._xEmptyDoc = cls._uno.openEmptyWriterDoc()
cls.RED = 0xFF0000
cls.BLUE = 0x0000FF
cls.GREEN = 0x008000
diff --git a/sw/qa/python/check_cross_references.py b/sw/qa/python/check_cross_references.py
index 742cc0d94ad5..6aad1c47ca3a 100644
--- a/sw/qa/python/check_cross_references.py
+++ b/sw/qa/python/check_cross_references.py
@@ -46,6 +46,10 @@ class CheckCrossReferences(unittest.TestCase):
@classmethod
def tearDownClass(cls):
cls._uno.tearDown()
+ # HACK in case cls.document holds a UNO proxy to an SwXTextDocument (whose dtor calls
+ # Application::GetSolarMutex via sw::UnoImplPtrDeleter), which would potentially only be
+ # garbage-collected after VCL has already been deinitialized:
+ cls.document = None
def getNextField(self):
while True:
diff --git a/sw/qa/python/check_fields.py b/sw/qa/python/check_fields.py
index 60418a93001d..eb6dd2dc1c8a 100644
--- a/sw/qa/python/check_fields.py
+++ b/sw/qa/python/check_fields.py
@@ -17,8 +17,6 @@ class CheckFields(unittest.TestCase):
def setUpClass(cls):
cls._uno = UnoInProcess()
cls._uno.setUp()
- cls._xDoc = cls._uno.openTemplateFromTDOC("fdo39694.ott")
- cls._xEmptyDoc = cls._uno.openEmptyWriterDoc()
@classmethod
def tearDownClass(cls):
@@ -26,7 +24,7 @@ class CheckFields(unittest.TestCase):
def test_fdo39694_load(self):
placeholders = ["<Kadr1>", "<Kadr2>", "<Kadr3>", "<Kadr4>", "<Pnname>", "<Pvname>", "<Pgeboren>"]
- xDoc = self.__class__._xDoc
+ xDoc = self.__class__._uno.openTemplateFromTDOC("fdo39694.ott")
xEnumerationAccess = xDoc.getTextFields()
xFieldEnum = xEnumerationAccess.createEnumeration()
for xField in xFieldEnum:
@@ -35,9 +33,10 @@ class CheckFields(unittest.TestCase):
read_content = xAnchor.getString()
self.assertTrue(read_content in placeholders,
"field %s is not contained: " % read_content)
+ xDoc.close(True)
def test_fdo42073(self):
- xDoc = self.__class__._xEmptyDoc
+ xDoc = self.__class__._uno.openEmptyWriterDoc()
xBodyText = xDoc.getText()
xCursor = xBodyText.createTextCursor()
xTextField = xDoc.createInstance("com.sun.star.text.TextField.Input")
@@ -48,6 +47,7 @@ class CheckFields(unittest.TestCase):
xTextField.setPropertyValue("Content", content)
read_content = xTextField.getPropertyValue("Content")
self.assertEqual(content, read_content)
+ xDoc.close(True)
if __name__ == '__main__':
unittest.main()
diff --git a/sw/qa/python/check_flies.py b/sw/qa/python/check_flies.py
index 6353ccda150d..0e60b2195e89 100644
--- a/sw/qa/python/check_flies.py
+++ b/sw/qa/python/check_flies.py
@@ -26,18 +26,18 @@ class CheckFlies(unittest.TestCase):
def setUpClass(cls):
cls._uno = UnoInProcess()
cls._uno.setUp()
- cls.document = cls._uno.openDocFromTDOC("CheckFlies.odt")
@classmethod
def tearDownClass(cls):
cls._uno.tearDown()
def test_checkFlies(self):
- xTFS = self.__class__.document
+ document = self.__class__._uno.openDocFromTDOC("CheckFlies.odt")
+ xTFS = document
self.checkTextFrames(xTFS)
- xTGOS = self.__class__.document
+ xTGOS = document
self.checkGraphicFrames(xTGOS)
- xTEOS = self.__class__.document
+ xTEOS = document
self.checkEmbeddedFrames(xTEOS)
def checkEmbeddedFrames(self, xTGOS):
diff --git a/sw/qa/python/check_indexed_property_values.py b/sw/qa/python/check_indexed_property_values.py
index 5609aa4225cb..ceaf82a6cac6 100644
--- a/sw/qa/python/check_indexed_property_values.py
+++ b/sw/qa/python/check_indexed_property_values.py
@@ -34,7 +34,6 @@ class CheckIndexedPropertyValues(unittest.TestCase):
cls._uno = UnoInProcess()
cls._uno.setUp()
cls.xContext = cls._uno.getContext()
- cls.xDoc = cls._uno.openEmptyWriterDoc()
@classmethod
def tearDownClass(cls):
diff --git a/sw/qa/python/check_named_property_values.py b/sw/qa/python/check_named_property_values.py
index dd06adc60313..1a81d13a6323 100644
--- a/sw/qa/python/check_named_property_values.py
+++ b/sw/qa/python/check_named_property_values.py
@@ -36,7 +36,6 @@ class CheckNamedPropertyValues(unittest.TestCase):
cls._uno = UnoInProcess()
cls._uno.setUp()
cls.xContext = cls._uno.getContext()
- cls.xDoc = cls._uno.openEmptyWriterDoc()
@classmethod
def tearDownClass(cls):
diff --git a/sw/qa/python/check_table.py b/sw/qa/python/check_table.py
index 35da08fe8195..8fd888f187bd 100644
--- a/sw/qa/python/check_table.py
+++ b/sw/qa/python/check_table.py
@@ -583,6 +583,8 @@ class CheckTable(unittest.TestCase):
xCellRangeString = xChartDataProvider.convertRangeFromXML("Table1.$A$1:.$C$3")
self.assertEqual("Table1.A1:C3", xCellRangeString)
+ xDoc.dispose()
+
def test_splitRangeHorizontal(self):
xDoc = CheckTable._uno.openEmptyWriterDoc()
xTable = xDoc.createInstance("com.sun.star.text.TextTable")
@@ -600,6 +602,7 @@ class CheckTable(unittest.TestCase):
self.assertTrue(math.isnan(xTable.Data[1][1]))
self.assertTrue(math.isnan(xTable.Data[2][0]))
self.assertTrue(math.isnan(xTable.Data[2][1]))
+ xDoc.dispose()
def test_mergeRangeHorizontal(self):
xDoc = CheckTable._uno.openEmptyWriterDoc()
@@ -618,6 +621,7 @@ class CheckTable(unittest.TestCase):
self.assertEqual(xTable.Data[1][1], float(5))
self.assertEqual(xTable.Data[1][2], float(6))
self.assertEqual(xTable.Data[2], (float(7), float(8), float(9)))
+ xDoc.dispose()
if __name__ == '__main__':
unittest.main()
diff --git a/sw/qa/python/get_expression.py b/sw/qa/python/get_expression.py
index 7462db68a730..98e9402bb602 100644
--- a/sw/qa/python/get_expression.py
+++ b/sw/qa/python/get_expression.py
@@ -22,6 +22,10 @@ class TestGetExpression(unittest.TestCase):
@classmethod
def tearDownClass(cls):
cls._uno.tearDown()
+ # HACK in case cls._xDoc holds a UNO proxy to an SwXTextDocument (whose dtor calls
+ # Application::GetSolarMutex via sw::UnoImplPtrDeleter), which would potentially only be
+ # garbage-collected after VCL has already been deinitialized:
+ cls._xDoc = None
def test_get_expression(self):
self.__class__._uno.checkProperties(
diff --git a/sw/qa/python/set_expression.py b/sw/qa/python/set_expression.py
index 220952536fea..c5dc5e6ae2e9 100644
--- a/sw/qa/python/set_expression.py
+++ b/sw/qa/python/set_expression.py
@@ -18,15 +18,15 @@ class TestSetExpression(unittest.TestCase):
def setUpClass(cls):
cls._uno = UnoInProcess()
cls._uno.setUp()
- cls._xDoc = cls._uno.openEmptyWriterDoc()
@classmethod
def tearDownClass(cls):
cls._uno.tearDown()
def test_set_expression(self):
+ xDoc = self.__class__._uno.openEmptyWriterDoc()
self.__class__._uno.checkProperties(
- self.__class__._xDoc.createInstance("com.sun.star.text.textfield.SetExpression"),
+ xDoc.createInstance("com.sun.star.text.textfield.SetExpression"),
{"NumberingType": 0,
"Content": "foo",
"CurrentPresentation": "bar",
diff --git a/sw/qa/python/text_portion_enumeration_test.py b/sw/qa/python/text_portion_enumeration_test.py
index 3a7e9d8586be..c379138db303 100644
--- a/sw/qa/python/text_portion_enumeration_test.py
+++ b/sw/qa/python/text_portion_enumeration_test.py
@@ -934,6 +934,11 @@ class TextPortionEnumerationTest(unittest.TestCase):
@classmethod
def tearDownClass(cls):
cls.xDoc.close(True)
+ cls._uno.tearDown()
+ # HACK in case cls.xDoc holds a UNO proxy to an SwXTextDocument (whose dtor calls
+ # Application::GetSolarMutex via sw::UnoImplPtrDeleter), which would potentially only be
+ # garbage-collected after VCL has already been deinitialized:
+ cls.xDoc = None
def test_text(self):
root = TreeNode()
diff --git a/sw/qa/python/var_fields.py b/sw/qa/python/var_fields.py
index c2af7a40f408..52fe3ddd6938 100644
--- a/sw/qa/python/var_fields.py
+++ b/sw/qa/python/var_fields.py
@@ -19,7 +19,6 @@ class TestVarFields(unittest.TestCase):
def setUpClass(cls):
cls._uno = UnoInProcess()
cls._uno.setUp()
- cls._xDoc = cls._uno.openEmptyWriterDoc()
@classmethod
def tearDownClass(cls):
@@ -32,7 +31,7 @@ class TestVarFields(unittest.TestCase):
sw/qa/complex/writer/VarFields.java
"""
- xDoc = self.__class__._xDoc
+ xDoc = self.__class__._uno.openEmptyWriterDoc()
xBodyText = xDoc.getText()
xCursor = xBodyText.createTextCursor()
# 0. create text field
diff --git a/test/source/bootstrapfixture.cxx b/test/source/bootstrapfixture.cxx
index a26b79a00c10..a8da11caed92 100644
--- a/test/source/bootstrapfixture.cxx
+++ b/test/source/bootstrapfixture.cxx
@@ -99,6 +99,12 @@ SAL_DLLPUBLIC_EXPORT void test_init(lang::XMultiServiceFactory *pFactory)
catch (...) { abort(); }
}
+// this is called from pyuno
+SAL_DLLPUBLIC_EXPORT void test_deinit()
+{
+ DeInitVCL();
+}
+
} // extern "C"
void test::BootstrapFixture::setUp()
diff --git a/unotest/source/python/org/libreoffice/unittest.py b/unotest/source/python/org/libreoffice/unittest.py
new file mode 100644
index 000000000000..364462ed3827
--- /dev/null
+++ b/unotest/source/python/org/libreoffice/unittest.py
@@ -0,0 +1,29 @@
+# -*- tab-width: 4; indent-tabs-mode: nil; py-indent-offset: 4 -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+import gc
+import pyuno
+import unittest
+
+class LoTestResult(unittest.TextTestResult):
+ def stopTestRun(self):
+ # HACK calling gc.collect() to get rid of as many still existing UNO proxies to
+ # SwXTextDocument and friends as possible; those C++ classes' dtors call
+ # Application::GetSolarMutex via sw::UnoImplPtrDeleter, so the dtors must be called before
+ # DeInitVCL in the call to pyuno.private_deinitTestEnvironment(); any remainging proxies
+ # that are still referenced (UnoInProcess' self.xDoc in
+ # unotest/source/python/org/libreoffice/unotest.py, or per-class variables in the various
+ # PythonTests) need to be individually released (each marked as "HACK" in the code):
+ gc.collect()
+ pyuno.private_deinitTestEnvironment()
+
+if __name__ == '__main__':
+ unittest.main(module=None, testRunner=unittest.TextTestRunner(resultclass=LoTestResult))
+
+# vim: set shiftwidth=4 softtabstop=4 expandtab:
diff --git a/unotest/source/python/org/libreoffice/unotest.py b/unotest/source/python/org/libreoffice/unotest.py
index 000a148b353f..804ddafc5518 100644
--- a/unotest/source/python/org/libreoffice/unotest.py
+++ b/unotest/source/python/org/libreoffice/unotest.py
@@ -246,7 +246,12 @@ class UnoInProcess:
def postTest(self):
assert(self.xContext)
def tearDown(self):
- self.xDoc.close(True)
+ if hasattr(self, 'xDoc'):
+ self.xDoc.close(True)
+ # HACK in case self.xDoc holds a UNO proxy to an SwXTextDocument (whose dtor calls
+ # Application::GetSolarMutex via sw::UnoImplPtrDeleter), which would potentially only be
+ # garbage-collected after VCL has already been deinitialized:
+ self.xDoc = None
def simpleInvoke(connection, test):
try: