コード例 #1
0
ファイル: test_handles.py プロジェクト: kml27/hpy
 def test_get_open_handles(self):
     from hpy.universal import _debug
     mod = self.make_leak_module()
     gen1 = _debug.new_generation()
     mod.leak('hello')
     mod.leak('world')
     gen2 = _debug.new_generation()
     mod.leak('a younger leak')
     leaks1 = _debug.get_open_handles(gen1)
     leaks2 = _debug.get_open_handles(gen2)
     leaks1 = [dh.obj for dh in leaks1]
     leaks2 = [dh.obj for dh in leaks2]
     assert leaks1 == ['a younger leak', 'world', 'hello']
     assert leaks2 == ['a younger leak']
コード例 #2
0
ファイル: test_handles.py プロジェクト: kml27/hpy
    def test_DebugHandle_compare(self):
        import pytest
        from hpy.universal import _debug
        mod = self.make_leak_module()
        gen = _debug.new_generation()
        mod.leak('a')
        mod.leak('a')
        a2, a1 = _debug.get_open_handles(gen)
        assert a1 != a2  # same underlying object, but different DebugHandle
        #
        a2_new, a1_new = _debug.get_open_handles(gen)
        assert a1 is not a1_new  # different objects...
        assert a2 is not a2_new
        assert a1 == a1_new  # ...but same DebugHandle
        assert a2 == a2_new
        #
        with pytest.raises(TypeError):
            a1 < a2
        with pytest.raises(TypeError):
            a1 <= a2
        with pytest.raises(TypeError):
            a1 > a2
        with pytest.raises(TypeError):
            a1 >= a2

        assert not a1 == 'hello'
        assert a1 != 'hello'
        with pytest.raises(TypeError):
            a1 < 'hello'
コード例 #3
0
 def test_DebugHandle_repr(self):
     from hpy.universal import _debug
     mod = self.make_leak_module()
     gen = _debug.new_generation()
     mod.leak('hello')
     h_hello, = _debug.get_open_handles(gen)
     assert repr(h_hello) == "<DebugHandle 0x%x for 'hello'>" % h_hello.id
コード例 #4
0
def test_DebugHandle_repr(compiler, with_alloc_trace):
    from hpy.universal import _debug
    mod = make_leak_module(compiler)
    gen = _debug.new_generation()
    mod.leak('hello')
    h_hello, = _debug.get_open_handles(gen)
    assert repr(h_hello).startswith("<DebugHandle 0x%x for 'hello'>" %
                                    h_hello.id)
コード例 #5
0
 def test_closed_handles(self):
     from hpy.universal import _debug
     mod = self.make_leak_module()
     gen = _debug.new_generation()
     mod.leak('hello')
     h_hello, = _debug.get_open_handles(gen)
     assert not h_hello.is_closed
     h_hello._force_close()
     assert h_hello.is_closed
     assert _debug.get_open_handles(gen) == []
     assert h_hello in _debug.get_closed_handles()
     assert repr(h_hello) == "<DebugHandle 0x%x CLOSED>" % h_hello.id
コード例 #6
0
def test_closed_handles(compiler, with_alloc_trace):
    from hpy.universal import _debug
    mod = make_leak_module(compiler)
    gen = _debug.new_generation()
    mod.leak('hello')
    h_hello, = _debug.get_open_handles(gen)
    assert not h_hello.is_closed
    h_hello._force_close()
    assert h_hello.is_closed
    assert _debug.get_open_handles(gen) == []
    assert h_hello in _debug.get_closed_handles()
    assert repr(h_hello).startswith("<DebugHandle 0x%x CLOSED>" % h_hello.id)
コード例 #7
0
    def test_reuse_closed_handles(self):
        from hpy.universal import _debug
        mod = self.make_module("""
            HPyDef_METH(f, "f", f_impl, HPyFunc_O)
            static HPy f_impl(HPyContext *ctx, HPy self, HPy arg)
            {
                return HPy_Dup(ctx, ctx->h_None);
            }
            HPyDef_METH(leak, "leak", leak_impl, HPyFunc_O)
            static HPy leak_impl(HPyContext *ctx, HPy self, HPy arg)
            {
                HPy_Dup(ctx, arg); // leak!
                return HPy_Dup(ctx, ctx->h_None);
            }
            @EXPORT(f)
            @EXPORT(leak)
            @INIT
        """)

        old_size = _debug.get_closed_handles_queue_max_size()
        try:
            gen = _debug.new_generation()
            # call f twice to open/closes a bunch of handles
            mod.f('hello')
            mod.f('world')
            #
            # make sure that the closed_handles queue is considered full: this
            # will force the reuse of existing closed handles
            _debug.set_closed_handles_queue_max_size(1)
            # during the call to leak, we create handles for:
            #   1. self
            #   2. arg
            #   3. HPy_Dup(arg) (leaking)
            #   4. result
            # So the leaked handle will be 3rd in the old closed_handles queue
            closed_handles = _debug.get_closed_handles()
            mod.leak('foo')
            assert not closed_handles[2].is_closed
            assert closed_handles[2].obj == 'foo'

            closed_handles = _debug.get_closed_handles()
            mod.leak('bar')
            assert not closed_handles[2].is_closed
            assert closed_handles[2].obj == 'bar'

            leaks = _debug.get_open_handles(gen)
            for h in leaks:
                h._force_close()
        finally:
            _debug.set_closed_handles_queue_max_size(old_size)
コード例 #8
0
ファイル: test_handles.py プロジェクト: kml27/hpy
 def test_DebugHandle_id(self):
     from hpy.universal import _debug
     mod = self.make_leak_module()
     gen = _debug.new_generation()
     mod.leak('a')
     mod.leak('b')
     b1, a1 = _debug.get_open_handles(gen)
     b2, a2 = _debug.get_open_handles(gen)
     assert a1.obj == a2.obj == 'a'
     assert b1.obj == b2.obj == 'b'
     #
     assert a1 is not a2
     assert b1 is not b2
     #
     assert a1.id == a2.id
     assert b1.id == b2.id
     assert a1.id != b1.id
コード例 #9
0
ファイル: test_handles_leak.py プロジェクト: timobure/hpy
def test_DebugHandle_id(compiler):
    from hpy.universal import _debug
    mod = make_leak_module(compiler)
    gen = _debug.new_generation()
    mod.leak('a')
    mod.leak('b')
    a1, b1 = _debug.get_open_handles(gen)
    a2, b2 = _debug.get_open_handles(gen)
    assert a1.obj == a2.obj == 'a'
    assert b1.obj == b2.obj == 'b'
    #
    assert a1 is not a2
    assert b1 is not b2
    #
    assert a1.id == a2.id
    assert b1.id == b2.id
    assert a1.id != b1.id
コード例 #10
0
ファイル: test_handles_leak.py プロジェクト: timobure/hpy
def test_leak_from_method(compiler):
    from hpy.universal import _debug
    mod = compiler.make_module("""
        HPyDef_METH(Dummy_leak, "leak", Dummy_leak_impl, HPyFunc_O)
        static HPy Dummy_leak_impl(HPyContext *ctx, HPy self, HPy arg) {
            HPy_Dup(ctx, arg); // leak!
            return HPy_Dup(ctx, ctx->h_None);
        }
        static HPyDef *Dummy_defines[] = {
            &Dummy_leak,
            NULL
        };
        static HPyType_Spec Dummy_spec = {
            .name = "mytest.Dummy",
            .defines = Dummy_defines,
        };
        @EXPORT_TYPE("Dummy", Dummy_spec)
        @INIT
   """)
    gen = _debug.new_generation()
    obj = mod.Dummy()
    obj.leak("a")
    leaks = [dh.obj for dh in _debug.get_open_handles(gen)]
    assert leaks == ["a"]
コード例 #11
0
 def start(self):
     if self.generation is not None:
         raise ValueError('LeakDetector already started')
     self.generation = _debug.new_generation()
コード例 #12
0
ファイル: test_charptr.py プロジェクト: oracle/graalpython
def test_charptr_limit_stress_test(compiler):
    from hpy.universal import _debug
    mod = compiler.make_module("""
        HPyDef_METH(f, "f", f_impl, HPyFunc_O)
        static HPy f_impl(HPyContext *ctx, HPy self, HPy arg)
        {
            HPy_ssize_t size;
            HPyUnicode_AsUTF8AndSize(ctx, arg, &size);
            if (size == 0) {
                return HPy_NULL;
            }
            return HPy_Dup(ctx, ctx->h_None);
        }

        // Dummy function just to force handle creation, but should not create
        // any raw data attached to those handles
        HPyDef_METH(g, "g", g_impl, HPyFunc_O)
        static HPy g_impl(HPyContext *ctx, HPy self, HPy arg)
        {
            int len = HPyLong_AsLong(ctx, arg);
            for (int i = 0; i < len; ++i) {
                HPy h = HPyLong_FromLong(ctx, i);
                HPy_Close(ctx, h);
            }
            return HPy_Dup(ctx, ctx->h_None);
        }

        @EXPORT(f)
        @EXPORT(g)
        @INIT
    """)

    def get_raw_data_sizes(handles):
        return list(map(lambda h: h.raw_data_size, handles))

    def clear_raw_data_in_closed_handles():
        closed_size = len(_debug.get_closed_handles())
        old_limit = _debug.get_closed_handles_queue_max_size()
        try:
            # make sure that the closed_handles queue is considered full: this
            # will force the reuse of existing closed handles.
            _debug.set_closed_handles_queue_max_size(closed_size)
            # Dummy call to force the reuse of the existing closed handles
            # -2 because 'self' and the 'arg' should already reuse 2 handles
            mod.g(closed_size - 2)
        finally:
            _debug.set_closed_handles_queue_max_size(old_limit)
        return closed_size

    old_raw_data_max_size = _debug.get_protected_raw_data_max_size()
    old_closed_handles_max_size = _debug.get_closed_handles_queue_max_size()
    _debug.set_protected_raw_data_max_size(100)
    try:
        # Reset the state as much as possible:
        closed_size = clear_raw_data_in_closed_handles()
        # Make enough room for the handles created by this test
        _debug.set_closed_handles_queue_max_size(closed_size + 100)
        # Sanity check: no raw data is now held by closed handles
        initial = get_raw_data_sizes(_debug.get_closed_handles())
        assert all(map(lambda x: x == -1, initial))

        # Large string that shouldn't be retained at all
        gen = _debug.new_generation()
        mod.f('abc' * 50)
        closed1 = get_raw_data_sizes(_debug.get_closed_handles(gen))
        assert closed1 == [-1, -1, -1]  # -1 for 'self' and the return value

        # Two small strings, should be kept, one large that should not fit in
        gen = _debug.new_generation()
        mod.f('a' * 31)
        mod.f('b' * 32)
        mod.f('c' * 50)
        closed2 = get_raw_data_sizes(_debug.get_closed_handles(gen))
        # -1 for 'self'/return value for each call, and the long string
        # note: C strings' size is +1 for the terminating '\0'
        assert sorted(closed2) == [-1] * 7 + [32, 33]

        # Another small string should still fit
        gen = _debug.new_generation()
        mod.f('a' * 13)
        closed3 = get_raw_data_sizes(_debug.get_closed_handles(gen))
        # 'self'/return, and the expected small string
        assert sorted(closed3) == [-1, -1, 14]

        # But another small-ish string not anymore
        gen = _debug.new_generation()
        mod.f('a' * 27)
        closed4 = get_raw_data_sizes(_debug.get_closed_handles(gen))
        # 'self'/return, and the string whose raw data didn't fit in
        assert sorted(closed4) == [-1, -1, -1]

        # Check that raw data of closed handles is freed when the handle
        # is reused
        closed_size = clear_raw_data_in_closed_handles()

        # None of the closed handles should now have any raw data attached
        all_closed = _debug.get_closed_handles()
        assert len(all_closed) == closed_size  # Sanity check
        for h in all_closed:
            assert h.raw_data_size == -1
    finally:
        _debug.set_protected_raw_data_max_size(old_raw_data_max_size)
        _debug.set_closed_handles_queue_max_size(old_closed_handles_max_size)