This is an automated email from the ASF dual-hosted git repository.
zhangduo pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/hbase.git
The following commit(s) were added to refs/heads/master by this push:
new 6724289abdc HBASE-29899 TestRowStatisticsCompactionObserver fails with
NPE (#7756)
6724289abdc is described below
commit 6724289abdcac592b4aab6166989fb11a803ebc5
Author: Liu Xiao <[email protected]>
AuthorDate: Mon Feb 23 23:29:14 2026 +0800
HBASE-29899 TestRowStatisticsCompactionObserver fails with NPE (#7756)
Signed-off-by: Duo Zhang <[email protected]>
---
hbase-examples/pom.xml | 5 ++
.../stats/TestRowStatisticsCompactionObserver.java | 91 +++++++++++-----------
2 files changed, 50 insertions(+), 46 deletions(-)
diff --git a/hbase-examples/pom.xml b/hbase-examples/pom.xml
index fab0d719fad..87e91667075 100644
--- a/hbase-examples/pom.xml
+++ b/hbase-examples/pom.xml
@@ -162,6 +162,11 @@
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.awaitility</groupId>
+ <artifactId>awaitility</artifactId>
+ <scope>test</scope>
+ </dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk18on</artifactId>
diff --git
a/hbase-examples/src/test/java/org/apache/hadoop/hbase/coprocessor/example/row/stats/TestRowStatisticsCompactionObserver.java
b/hbase-examples/src/test/java/org/apache/hadoop/hbase/coprocessor/example/row/stats/TestRowStatisticsCompactionObserver.java
index d0ee8d3bc57..7e7573d63bf 100644
---
a/hbase-examples/src/test/java/org/apache/hadoop/hbase/coprocessor/example/row/stats/TestRowStatisticsCompactionObserver.java
+++
b/hbase-examples/src/test/java/org/apache/hadoop/hbase/coprocessor/example/row/stats/TestRowStatisticsCompactionObserver.java
@@ -17,16 +17,18 @@
*/
package org.apache.hadoop.hbase.coprocessor.example.row.stats;
-import static org.apache.hadoop.hbase.util.TestRegionSplitCalculator.TEST_UTIL;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
+import static org.awaitility.Awaitility.await;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
import java.io.IOException;
+import java.time.Duration;
import java.util.Optional;
import java.util.concurrent.ThreadLocalRandom;
import org.apache.hadoop.hbase.Cell;
import org.apache.hadoop.hbase.CellScanner;
+import org.apache.hadoop.hbase.HBaseTestingUtil;
import org.apache.hadoop.hbase.HConstants;
import org.apache.hadoop.hbase.SingleProcessHBaseCluster;
import org.apache.hadoop.hbase.TableName;
@@ -36,14 +38,23 @@ import org.apache.hadoop.hbase.client.Delete;
import org.apache.hadoop.hbase.client.Put;
import org.apache.hadoop.hbase.client.Table;
import
org.apache.hadoop.hbase.coprocessor.example.row.stats.recorder.RowStatisticsRecorder;
+import org.apache.hadoop.hbase.testclassification.MediumTests;
import org.apache.hadoop.hbase.util.Bytes;
-import org.junit.AfterClass;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Test;
-
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Tag;
+import org.junit.jupiter.api.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Tag(MediumTests.TAG)
public class TestRowStatisticsCompactionObserver {
+ private static final Logger LOG =
+ LoggerFactory.getLogger(TestRowStatisticsCompactionObserver.class);
+
+ public static final HBaseTestingUtil TEST_UTIL = new HBaseTestingUtil();
public static final TestableRowStatisticsRecorder RECORDER = new
TestableRowStatisticsRecorder();
private static final TableName TABLE_NAME = TableName.valueOf("test-table");
private static final byte[] FAMILY = Bytes.toBytes("0");
@@ -51,7 +62,7 @@ public class TestRowStatisticsCompactionObserver {
private static Connection connection;
private static Table table;
- @BeforeClass
+ @BeforeAll
public static void setUpClass() throws Exception {
cluster = TEST_UTIL.startMiniCluster(1);
connection = ConnectionFactory.createConnection(cluster.getConf());
@@ -59,12 +70,7 @@ public class TestRowStatisticsCompactionObserver {
HConstants.DEFAULT_BLOCKSIZE,
TestableRowStatisticsCompactionObserver.class.getName());
}
- @Before
- public void setUp() throws Exception {
- RECORDER.clear();
- }
-
- @AfterClass
+ @AfterAll
public static void afterClass() throws Exception {
cluster.close();
TEST_UTIL.shutdownMiniCluster();
@@ -72,6 +78,11 @@ public class TestRowStatisticsCompactionObserver {
connection.close();
}
+ @BeforeEach
+ public void setUp() throws Exception {
+ RECORDER.clear();
+ }
+
@Test
public void itRecordsStats() throws IOException, InterruptedException {
int numRows = 10;
@@ -121,42 +132,29 @@ public class TestRowStatisticsCompactionObserver {
table.delete(d);
}
- System.out.println("Final flush");
- connection.getAdmin().flush(table.getName());
- Thread.sleep(5000);
- System.out.println("Compacting");
+ LOG.info("Final flush");
+ await().atMost(Duration.ofSeconds(10))
+ .untilAsserted(() -> connection.getAdmin().flush(table.getName()));
- RowStatisticsImpl lastStats = RECORDER.getLastStats(); // Just initialize
- Boolean lastIsMajor = RECORDER.getLastIsMajor();
+ LOG.info("Compacting");
connection.getAdmin().compact(table.getName());
- while (lastStats == null) {
- Thread.sleep(1000);
-
- System.out.println("Checking stats");
- lastStats = RECORDER.getLastStats();
- lastIsMajor = RECORDER.getLastIsMajor();
- }
- assertFalse(lastIsMajor);
- assertEquals(lastStats.getTotalDeletesCount(), 10);
- assertEquals(lastStats.getTotalRowsCount(), 10);
+ await().during(Duration.ofSeconds(1)).atMost(Duration.ofSeconds(10))
+ .until(() -> RECORDER.getLastStats() != null);
+ assertFalse(RECORDER.getLastIsMajor());
+ assertEquals(10, RECORDER.getLastStats().getTotalDeletesCount());
+ assertEquals(10, RECORDER.getLastStats().getTotalRowsCount());
RECORDER.clear();
- lastStats = RECORDER.getLastStats();
- lastIsMajor = RECORDER.getLastIsMajor();
connection.getAdmin().majorCompact(table.getName());
// Must wait for async majorCompaction to complete
- while (lastStats == null) {
- Thread.sleep(1000);
-
- System.out.println("Checking stats");
- lastStats = RECORDER.getLastStats();
- lastIsMajor = RECORDER.getLastIsMajor();
- }
- assertTrue(lastIsMajor);
+ await().during(Duration.ofSeconds(1)).atMost(Duration.ofSeconds(10))
+ .until(() -> RECORDER.getLastStats() != null);
+ assertTrue(RECORDER.getLastIsMajor());
// no deletes after major compact
- assertEquals(lastStats.getTotalDeletesCount(), 0);
- assertEquals(lastStats.getTotalRowsCount(), 10);
+ RowStatisticsImpl lastStats = RECORDER.getLastStats();
+ assertEquals(0, lastStats.getTotalDeletesCount());
+ assertEquals(10, lastStats.getTotalRowsCount());
// can only check largest values after major compact, since the above
minor compact might not
// contain all storefiles
assertEquals(Bytes.toInt(lastStats.getLargestRow()), largestRowNum);
@@ -184,9 +182,10 @@ public class TestRowStatisticsCompactionObserver {
@Override
public void record(RowStatisticsImpl stats, Optional<byte[]>
fullRegionName) {
- System.out.println("Record called with isMajor=" + stats.isMajor() + ",
stats=" + stats
- + ", fullRegionName=" + fullRegionName);
+ LOG.info("Record called with isMajor={}, stats={}, fullRegionName={}",
stats.isMajor(), stats,
+ fullRegionName);
lastStats = stats;
+ lastIsMajor = stats.isMajor();
}
public void clear() {