Skip to content

Commit 461a9b3

Browse files
BoxStore: assert native Entity instances are not leaked (#825)
1 parent 488e477 commit 461a9b3

File tree

3 files changed

+29
-3
lines changed

3 files changed

+29
-3
lines changed

objectbox-java/src/main/java/io/objectbox/BoxStore.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,15 @@ public static String getVersionNative() {
148148

149149
static native void nativeDropAllData(long store);
150150

151+
/**
152+
* A static counter for the alive entity types (entity schema instances); this can be useful to test against leaks.
153+
* This number depends on the number of currently opened stores; no matter how often stores were closed and
154+
* (re-)opened. E.g. when stores are regularly opened, but not closed by the user, the number should increase. When
155+
* all stores are properly closed, this value should be 0.
156+
*/
157+
@Internal
158+
static native long nativeGloballyActiveEntityTypes();
159+
151160
static native long nativeBeginTx(long store);
152161

153162
static native long nativeBeginReadTx(long store);

tests/objectbox-java-test/src/test/java/io/objectbox/BoxStoreTest.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,10 +77,16 @@ public void testCloseThreadResources() {
7777

7878
@Test
7979
public void testClose() {
80+
// This test suite uses a single entity (TestEntity) by default
81+
// and all other tests close the store after being done. So should be 1.
82+
assertEquals(1, BoxStore.nativeGloballyActiveEntityTypes());
83+
8084
BoxStore store = this.store;
8185
assertFalse(store.isClosed());
8286
store.close();
8387
assertTrue(store.isClosed());
88+
// Assert native Entity instances are not leaked.
89+
assertEquals(0, BoxStore.nativeGloballyActiveEntityTypes());
8490

8591
// Double close should be fine
8692
store.close();
@@ -154,8 +160,13 @@ public void openSamePath_fails() {
154160
@Test
155161
public void openSamePath_afterClose_works() {
156162
store.close();
163+
// Assert native Entity instances are not leaked.
164+
assertEquals(0, BoxStore.nativeGloballyActiveEntityTypes());
165+
157166
BoxStore store2 = createBoxStore();
158167
store2.close();
168+
// Assert native Entity instances are not leaked.
169+
assertEquals(0, BoxStore.nativeGloballyActiveEntityTypes());
159170
}
160171

161172
@Test

tests/objectbox-java-test/src/test/java/io/objectbox/query/QueryTest.java

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,7 @@ public void useAfterStoreClose_failsIfUsingStore() {
160160
).build();
161161
store.close();
162162

163+
// All methods accessing the store throw.
163164
assertThrowsStoreIsClosed(query::count);
164165
assertThrowsStoreIsClosed(query::find);
165166
assertThrowsStoreIsClosed(() -> query.find(0, 1));
@@ -171,9 +172,14 @@ public void useAfterStoreClose_failsIfUsingStore() {
171172
assertThrowsStoreIsClosed(query::findUnique);
172173
assertThrowsStoreIsClosed(query::remove);
173174

174-
// describe and setParameter continue to work as store is not accessed.
175-
assertFalse(query.describe().isEmpty());
176-
assertFalse(query.describeParameters().isEmpty());
175+
// describe works, but returns no property info.
176+
assertEquals("Query for entity <deleted entity type> with 15 conditions", query.describe());
177+
178+
// describeParameters does not work.
179+
IllegalStateException exc = assertThrows(IllegalStateException.class, query::describeParameters);
180+
assertEquals("Query cannot be used after entity type was deleted (e.g. store was closed)", exc.getMessage());
181+
182+
// setParameter continues to work.
177183
query.setParameter(simpleString, "value");
178184
query.setParameters(stringObjectMap, "a", "b");
179185
query.setParameter(simpleInt, 1);

0 commit comments

Comments
 (0)