improve tests

This commit is contained in:
Cosmos Nicolaou
2020-03-09 17:23:16 -07:00
parent d3e1ddf13e
commit 521091b1f1
4 changed files with 106 additions and 21 deletions
+43 -12
View File
@@ -26,18 +26,6 @@ int get_int_from_float(double from_float, int multiplier)
return (int) from_float*multiplier;
}
char *return_c_string_to_be_freed()
{
char *test = (char *)malloc(12 * sizeof(char));
strcpy(test, "testingonly");
return test;
}
ToBeFreed *return_class_to_be_freed()
{
return new ToBeFreed();
}
std::string SomeObject::staticData = std::string("Hello Static World!");
SomeObject::~SomeObject ()
@@ -568,3 +556,46 @@ test_args_kwargs(const char *args, const char *kwargs)
return (int) (kwargs - args);
}
ToBeFreed::ToBeFreed(int size) {
m_size = size;
m = return_c_string_to_be_freed(size);
}
ToBeFreed::~ToBeFreed() {
free(m);
m = nullptr;
}
ToBeFreed::ToBeFreed(const ToBeFreed& from) {
m_size = from.m_size;
m = return_c_string_to_be_freed(m_size);
}
char *ToBeFreed::value() {
return m;
}
char *return_c_string_to_be_freed(int size)
{
char *test = (char *)malloc(size * sizeof(char));
strcpy(test, "testingonly");
return test;
}
ToBeFreed *
return_class_to_be_freed(int size)
{
return new ToBeFreed(size);
}
char *
return_c_string_to_not_be_freed(int size)
{
return return_c_string_to_be_freed(size);
}
ToBeFreed *
return_class_to_not_be_freed(int size)
{
return new ToBeFreed(size);
}
+12 -5
View File
@@ -1370,20 +1370,27 @@ private:
};
// -#- name=return_c_string_to_be_freed; @return(free_after_copy=true) -#-
char *return_c_string_to_be_freed();
char *return_c_string_to_be_freed(int size);
// -#- name=return_c_string_to_not_be_freed; @return(free_after_copy=false) -#-
char *return_c_string_to_not_be_freed(int size);
class ToBeFreed
{
public:
ToBeFreed() { m = return_c_string_to_be_freed(); }
~ToBeFreed() { free(m); }
ToBeFreed(int size);
~ToBeFreed();
ToBeFreed(const ToBeFreed&);
char *value();
private:
char *m;
int m_size;
};
// -#- name=return_class_to_be_freed; @return(free_after_copy=true) -#-
ToBeFreed *return_class_to_be_freed();
ToBeFreed *return_class_to_be_freed(int size);
// -#- name=return_class_to_not_be_freed; @return(free_after_copy=false) -#-
ToBeFreed *return_class_to_not_be_freed(int size);
#endif /* !FOO_H_ */
+11 -3
View File
@@ -116,14 +116,22 @@ int %s::custom_method_added_by_a_hook(int x)
## test free_after_copy.
mod.add_function('return_c_string_to_be_freed',
ReturnValue.new('char *', free_after_copy=True ),
[])
ReturnValue.new('char *', free_after_copy=True),
[Parameter.new('int', 'size')])
mod.add_function('return_c_string_to_not_be_freed',
ReturnValue.new('char *', free_after_copy=False),
[Parameter.new('int', 'size')])
ToBeFreed = mod.add_class('ToBeFreed')
ToBeFreed.add_constructor([Parameter.new('int', 'size')])
ToBeFreed.add_copy_constructor()
ToBeFreed.add_method('value', ReturnValue.new('char *'), [])
mod.add_function('return_class_to_be_freed',
ReturnValue.new('ToBeFreed *', free_after_copy=True),
[])
[Parameter.new('int', 'size')])
mod.add_function('return_class_to_not_be_freed',
ReturnValue.new('ToBeFreed *', free_after_copy=False),
[Parameter.new('int', 'size')])
SomeObject = mod.add_class('SomeObject', allow_subclassing=True)
+40 -1
View File
@@ -4,6 +4,8 @@ import weakref
import gc
import os.path
import copy
import resource
sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)),
'..', 'build', 'tests'))
@@ -1536,7 +1538,7 @@ class TestFoo(unittest.TestCase):
value = x.ReturnMyAStruct()
self.assertEqual(value.a, 123)
def test_free_after_copy_string(self):
def test_free_after_copy_string_examine_code(self):
seen_free_comment = False
seen_free = False
seen_delete_comment = False
@@ -1556,5 +1558,42 @@ class TestFoo(unittest.TestCase):
self.assertTrue(seen_free)
self.assertTrue(seen_delete)
def test_free_after_copy(self):
v = foo.return_c_string_to_be_freed(20)
self.assertEqual(v, "testingonly")
c = foo.return_class_to_be_freed(20)
self.assertEqual(c.value(), "testingonly")
def _runner(self, n, size, fn):
while gc.collect():
pass
before = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss
for i in range(n):
fn(size)
while gc.collect():
pass
after = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss
# maxrss is in kB.
return (after - before) * 1024
def test_free_after_copy_leak(self):
n = 200
size = 1024*32
# run once to bump up overall maxrss if's going to be bumped up.
self._runner(n, size, foo.return_c_string_to_be_freed)
diff = self._runner(n, size, foo.return_c_string_to_be_freed)
#diff += self._runner(n, size, foo.return_class_to_be_freed)
# maxrss should only grow marginally here.
self.assertTrue(diff < (size*2))
leaky = self._runner(n, size, foo.return_c_string_to_not_be_freed)
leaky += self._runner(n, size, foo.return_class_to_not_be_freed)
# maxrss should have grown significantly
self.assertTrue(diff < leaky)
self.assertTrue(leaky > size * 10)
if __name__ == '__main__':
unittest.main()