tests: complain about memory leaks
Currently this detects leaking VM (and all subclasses), Qubes and libvirt-related objects. Usable only with --failfast.
This commit is contained in:
		
							parent
							
								
									7df8f51011
								
							
						
					
					
						commit
						5aa9fa2db4
					
				@ -374,9 +374,29 @@ class QubesTestCase(unittest.TestCase):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    def setUp(self):
 | 
					    def setUp(self):
 | 
				
			||||||
        super().setUp()
 | 
					        super().setUp()
 | 
				
			||||||
 | 
					        self.addCleanup(self.cleanup_gc)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.loop = asyncio.get_event_loop()
 | 
					        self.loop = asyncio.get_event_loop()
 | 
				
			||||||
        self.addCleanup(self.cleanup_loop)
 | 
					        self.addCleanup(self.cleanup_loop)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def cleanup_gc(self):
 | 
				
			||||||
 | 
					        gc.collect()
 | 
				
			||||||
 | 
					        leaked = [obj for obj in gc.get_objects() + gc.garbage
 | 
				
			||||||
 | 
					            if isinstance(obj,
 | 
				
			||||||
 | 
					                (qubes.Qubes, qubes.vm.BaseVM,
 | 
				
			||||||
 | 
					                libvirt.virConnect, libvirt.virDomain))]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if leaked:
 | 
				
			||||||
 | 
					            try:
 | 
				
			||||||
 | 
					                import objgraph
 | 
				
			||||||
 | 
					                objgraph.show_backrefs(leaked,
 | 
				
			||||||
 | 
					                    max_depth=15, extra_info=extra_info,
 | 
				
			||||||
 | 
					                    filename='/tmp/objgraph-{}.png'.format(self.id()))
 | 
				
			||||||
 | 
					            except ImportError:
 | 
				
			||||||
 | 
					                pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        assert not leaked
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def cleanup_loop(self):
 | 
					    def cleanup_loop(self):
 | 
				
			||||||
        '''Check if the loop is empty'''
 | 
					        '''Check if the loop is empty'''
 | 
				
			||||||
        # XXX BEWARE this is touching undocumented, implementation-specific
 | 
					        # XXX BEWARE this is touching undocumented, implementation-specific
 | 
				
			||||||
@ -1013,6 +1033,23 @@ def list_templates():
 | 
				
			|||||||
            _templates = ()
 | 
					            _templates = ()
 | 
				
			||||||
    return _templates
 | 
					    return _templates
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def extra_info(obj):
 | 
				
			||||||
 | 
					    '''Return short info identifying object.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    For example, if obj is a qube, return its name. This is for use with
 | 
				
			||||||
 | 
					    :py:mod:`objgraph` package.
 | 
				
			||||||
 | 
					    '''
 | 
				
			||||||
 | 
					    # Feel free to extend to other cases.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if isinstance(obj, qubes.vm.qubesvm.QubesVM):
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            return obj.name
 | 
				
			||||||
 | 
					        except AttributeError:
 | 
				
			||||||
 | 
					            pass
 | 
				
			||||||
 | 
					    if isinstance(obj, unittest.TestCase):
 | 
				
			||||||
 | 
					        return obj.id()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return ''
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def load_tests(loader, tests, pattern): # pylint: disable=unused-argument
 | 
					def load_tests(loader, tests, pattern): # pylint: disable=unused-argument
 | 
				
			||||||
    # discard any tests from this module, because it hosts base classes
 | 
					    # discard any tests from this module, because it hosts base classes
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user