From de6a03cd746b19033bec87bc3df862ae99b4fcf4 Mon Sep 17 00:00:00 2001 From: Tilmann Date: Sat, 22 Jun 2024 18:14:30 +0200 Subject: [PATCH] NPE with getStats() on empty tree (#36) * Empty tree getStats() --- CHANGELOG.md | 2 ++ .../ch/ethz/globis/phtree/v13/PhTree13.java | 3 +++ .../ch/ethz/globis/phtree/v16/PhTree16.java | 3 +++ .../ethz/globis/phtree/v16hd/PhTree16HD.java | 3 +++ .../globis/phtree/test/TestMultiMapF2.java | 26 ++++++++++++++----- 5 files changed, 31 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 84d4053..b15914a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +- getStats() for empty trees fails. [#36](https://github.com/tzaeschke/phtree/pull/36) + ## 2.8.0 - 2023-07-29 - Proper kNN implementation with MinMaxHeaps [#33](https://github.com/tzaeschke/phtree/pull/33) diff --git a/src/main/java/ch/ethz/globis/phtree/v13/PhTree13.java b/src/main/java/ch/ethz/globis/phtree/v13/PhTree13.java index f481e90..1e2ad93 100644 --- a/src/main/java/ch/ethz/globis/phtree/v13/PhTree13.java +++ b/src/main/java/ch/ethz/globis/phtree/v13/PhTree13.java @@ -154,6 +154,9 @@ public int size() { @Override public PhTreeStats getStats() { + if (getRoot() == null) { + return new PhTreeStats(DEPTH_64); + } return getStats(0, getRoot(), new PhTreeStats(DEPTH_64)); } diff --git a/src/main/java/ch/ethz/globis/phtree/v16/PhTree16.java b/src/main/java/ch/ethz/globis/phtree/v16/PhTree16.java index ef6a7f3..376ce4f 100644 --- a/src/main/java/ch/ethz/globis/phtree/v16/PhTree16.java +++ b/src/main/java/ch/ethz/globis/phtree/v16/PhTree16.java @@ -170,6 +170,9 @@ public int size() { @Override public PhTreeStats getStats() { + if (getRoot() == null) { + return new PhTreeStats(DEPTH_64); + } return getStats(0, getRoot(), new PhTreeStats(DEPTH_64)); } diff --git a/src/main/java/ch/ethz/globis/phtree/v16hd/PhTree16HD.java b/src/main/java/ch/ethz/globis/phtree/v16hd/PhTree16HD.java index 215211e..dfbbc61 100644 --- a/src/main/java/ch/ethz/globis/phtree/v16hd/PhTree16HD.java +++ b/src/main/java/ch/ethz/globis/phtree/v16hd/PhTree16HD.java @@ -174,6 +174,9 @@ public int size() { @Override public PhTreeStats getStats() { + if (getRoot() == null) { + return new PhTreeStats(DEPTH_64); + } return getStats(0, getRoot(), new PhTreeStats(DEPTH_64)); } diff --git a/src/test/java/ch/ethz/globis/phtree/test/TestMultiMapF2.java b/src/test/java/ch/ethz/globis/phtree/test/TestMultiMapF2.java index d67538e..71cfecc 100644 --- a/src/test/java/ch/ethz/globis/phtree/test/TestMultiMapF2.java +++ b/src/test/java/ch/ethz/globis/phtree/test/TestMultiMapF2.java @@ -12,6 +12,7 @@ import ch.ethz.globis.phtree.PhTreeMultiMapF2.*; import ch.ethz.globis.phtree.util.BitTools; import ch.ethz.globis.phtree.util.Bits; +import ch.ethz.globis.phtree.util.PhTreeStats; import org.junit.Test; import java.util.*; @@ -121,8 +122,8 @@ public void testCRUD_JDK8() { break; case 1: { final int id2 = id; - assertEquals(id2, (int) idx.computeIfAbsent(v, id2, (v2) -> id2)); - assertNull(idx.computeIfAbsent(v, id2, (v2) -> id2)); + assertEquals(id2, (int) idx.computeIfAbsent(v, id2, v2 -> id2)); + assertNull(idx.computeIfAbsent(v, id2, v2 -> id2)); break; } case 2: @@ -226,15 +227,15 @@ public void testKNN() { assertTrue(3 <= result.size()); result = toList(idx.nearestNeighbour(1, 1, 1)); - assertTrue(1 <= result.size()); + assertFalse(result.isEmpty()); check(result.get(0).getKey(), 1, 1); result = toList(idx.nearestNeighbour(1, 1, 3)); - assertTrue(1 <= result.size()); + assertFalse(result.isEmpty()); check(result.get(0).getKey(), 1, 3); result = toList(idx.nearestNeighbour(1, 3, 1)); - assertTrue(1 <= result.size()); + assertFalse(result.isEmpty()); check(result.get(0).getKey(), 3, 1); } @@ -273,7 +274,7 @@ public void testKnnLarge() { v[j] = R.nextDouble() * MAXV; } list.forEach(xx -> xx.dist = dist(v, xx.key)); - list.sort((o1, o2) -> Double.compare(o1.dist, o2.dist)); + list.sort(Comparator.comparingDouble(o -> o.dist)); List> nnList = toList(q.reset(MIN_RESULT, PhDistanceF.THIS, v)); assertFalse("i=" + i + " d=" + d, nnList.isEmpty()); for (int x = 0; x < MIN_RESULT; ++x) { @@ -483,4 +484,17 @@ public EntryDist(double[] key, T v, double dist) { this.dist = dist; } } + + @Test + public void testEmptyTreeStats() { + testEmptyTreeStats(2); + testEmptyTreeStats(60); + testEmptyTreeStats(600); + } + + private void testEmptyTreeStats(int dim) { + PhTreeMultiMapF2 ind = newTree(dim); + PhTreeStats stats = ind.getStats(); + assertEquals(0, stats.nNodes); + } }