Carp/test/managed.carp
Erik Svedäng 6f7aeaff73
feat: 'delete' interface (deciding whether a type is managed or not) (#1061)
* feat: 'delete' interface (deciding whether a type is managed or not)

* refactor: Move implements function to Interface module

* feat: Automatically implement 'delete' for types defined with `deftype`

* fix: Don't implement `delete` for Pointer

* refactor: Clarify `memberInfo` function

* fix: Also check if function types are managed

* fix: Implement 'delete' for String and StaticArray.

* fix: Manage String and Pattern. Tests run!

* feat: Add `managed?` primitive

* docs: Note about primitiveIsManaged

* test: Basic test cases for managed / nonmanaged external types

* test: Make sure `managed?` primitive works

* test: Inactivate sanitizer since we're creating leaks intentionally

* feat: Removed 'isExternalType' function

* refactor: Decide if struct member takes ref or not when printing

..based on blitable interface, and 'prn' implemntation

* refactor: Use 'blit' everywhere

* refactor: Implement `strTakesRefOrNot` in terms of `memberStrCallingConvention`

* refactor: Use `remove` over `filter not`
2020-12-20 21:21:14 +01:00

67 lines
1.6 KiB
Plaintext

(load-and-use Test)
(defn assert-memory-balance [state f expected-balance descr]
(do
(Debug.reset-memory-balance!)
(f)
(assert-equal state expected-balance (Debug.memory-balance) descr)))
(register-type A "void*")
(register-type B "void*")
(defmodule A
(deftemplate init (Fn [] A)
"void* $NAME()" "$DECL { return CARP_MALLOC(128); }")
(deftemplate copy (Fn [&A] A)
"void* $NAME(void **p)" "$DECL { return CARP_MALLOC(128); }")
(implements copy A.copy)
(deftemplate delete (Fn [A] ())
"void $NAME(void *p)" "$DECL { CARP_FREE(p); }")
(implements delete A.delete))
(defmodule B
(deftemplate init (Fn [] B)
"void* $NAME()" "$DECL { return CARP_MALLOC(128); }")
(deftemplate copy (Fn [&B] B)
"void* $NAME(void **p)" "$DECL { return CARP_MALLOC(128); }")
(implements copy B.copy)
;; 'B' does *not* implement delete!
;; The user would have to call delete / free on it manually to avoid a leak.
)
(defn f-a []
(let [a (A)]
()))
(defn f-b []
(let [b (B)]
()))
(defn f-copy-a []
(let [a (A)
a2 @&a]
()))
(defn f-copy-b []
(let [b (B)
b2 @&b]
()))
(eval ;; temporary workaround to force evaluation of top-level 'when'
(when (not (managed? A))
(macro-error "Fail - A should be managed.")))
(eval
(when (managed? B)
(macro-error "Fail - B should not be managed.")))
(deftest test
(assert-memory-balance test f-a 0l "f-a correct, does not leak")
(assert-memory-balance test f-b 1l "f-b correct, leaks 1 value")
(assert-memory-balance test f-copy-a 0l "f-copy-a correct, does not leak")
(assert-memory-balance test f-copy-b 2l "f-copy-b correct, leaks 2 values"))