Skip to content

Commit f148458

Browse files
Houlong66claude
andcommitted
test(metrics): add unit tests for snapshot defensive copy
- testSnapshotCreatesNewMetricData: verify delegate receives snapshotted MetricData, not the original reference - testSnapshotFallsBackToOriginal: verify catch block falls back to original when snapshot fails (e.g., mock without type) - testSnapshotPointsAreIndependentCopy: verify the snapshotted points collection is a separate instance from the original Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 8191501 commit f148458

File tree

1 file changed

+90
-0
lines changed

1 file changed

+90
-0
lines changed

broker/src/test/java/org/apache/rocketmq/broker/metrics/BatchSplittingMetricExporterTest.java

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -520,6 +520,96 @@ public void testSplitPointsContentPreserved() {
520520
.containsExactly(0L, 1L, 2L, 3L, 4L);
521521
}
522522

523+
@Test
524+
@SuppressWarnings("unchecked")
525+
public void testSnapshotCreatesNewMetricData() {
526+
// On fast path, delegate should receive
527+
// snapshotted MetricData, not the original.
528+
BatchSplittingMetricExporter exporter =
529+
new BatchSplittingMetricExporter(
530+
delegate, () -> 100);
531+
532+
MetricData original =
533+
createRealLongGaugeMetricData("test", 5);
534+
535+
exporter.export(
536+
Collections.singletonList(original));
537+
538+
ArgumentCaptor<Collection<MetricData>> captor =
539+
ArgumentCaptor.forClass(Collection.class);
540+
verify(delegate, times(1))
541+
.export(captor.capture());
542+
543+
MetricData exported =
544+
captor.getValue().iterator().next();
545+
assertThat(exported).isNotSameAs(original);
546+
assertThat(exported.getName())
547+
.isEqualTo("test");
548+
assertThat(exported.getType())
549+
.isEqualTo(MetricDataType.LONG_GAUGE);
550+
assertThat(exported.getData().getPoints())
551+
.hasSize(5);
552+
}
553+
554+
@Test
555+
@SuppressWarnings("unchecked")
556+
public void testSnapshotFallsBackToOriginal() {
557+
// Mock MetricData has no type set, so snapshot
558+
// will fail. Should fall back to original object.
559+
BatchSplittingMetricExporter exporter =
560+
new BatchSplittingMetricExporter(
561+
delegate, () -> 100);
562+
563+
MetricData mockMd =
564+
createMockMetricData("mock", 3);
565+
566+
exporter.export(
567+
Collections.singletonList(mockMd));
568+
569+
ArgumentCaptor<Collection<MetricData>> captor =
570+
ArgumentCaptor.forClass(Collection.class);
571+
verify(delegate, times(1))
572+
.export(captor.capture());
573+
574+
MetricData exported =
575+
captor.getValue().iterator().next();
576+
assertThat(exported).isSameAs(mockMd);
577+
}
578+
579+
@Test
580+
@SuppressWarnings("unchecked")
581+
public void testSnapshotPointsAreIndependentCopy() {
582+
// Verify snapshot points collection is a separate
583+
// copy from the original, preventing concurrent
584+
// modification issues.
585+
BatchSplittingMetricExporter exporter =
586+
new BatchSplittingMetricExporter(
587+
delegate, () -> 100);
588+
589+
MetricData original =
590+
createRealLongGaugeMetricData("test", 5);
591+
Collection<? extends PointData> originalPoints =
592+
original.getData().getPoints();
593+
594+
exporter.export(
595+
Collections.singletonList(original));
596+
597+
ArgumentCaptor<Collection<MetricData>> captor =
598+
ArgumentCaptor.forClass(Collection.class);
599+
verify(delegate, times(1))
600+
.export(captor.capture());
601+
602+
MetricData exported =
603+
captor.getValue().iterator().next();
604+
Collection<? extends PointData> exportedPoints =
605+
exported.getData().getPoints();
606+
607+
assertThat(exportedPoints)
608+
.isNotSameAs(originalPoints);
609+
assertThat(exportedPoints)
610+
.hasSize(originalPoints.size());
611+
}
612+
523613
/**
524614
* Creates a mock MetricData with the specified
525615
* number of data points.

0 commit comments

Comments
 (0)