|
11 | 11 | import com.google.common.collect.ImmutableList; |
12 | 12 | import com.google.common.collect.ImmutableMap; |
13 | 13 | import io.opentelemetry.api.baggage.Baggage; |
| 14 | +import io.opentelemetry.api.baggage.BaggageBuilder; |
14 | 15 | import io.opentelemetry.api.baggage.BaggageEntryMetadata; |
15 | 16 | import io.opentelemetry.context.Context; |
16 | 17 | import io.opentelemetry.context.propagation.TextMapGetter; |
| 18 | +import java.util.Arrays; |
17 | 19 | import java.util.Collections; |
18 | 20 | import java.util.HashMap; |
19 | 21 | import java.util.Iterator; |
20 | 22 | import java.util.LinkedHashMap; |
21 | 23 | import java.util.List; |
22 | 24 | import java.util.Map; |
| 25 | +import java.util.stream.Stream; |
23 | 26 | import javax.annotation.Nullable; |
24 | 27 | import org.junit.jupiter.api.Test; |
| 28 | +import org.junit.jupiter.params.ParameterizedTest; |
| 29 | +import org.junit.jupiter.params.provider.Arguments; |
| 30 | +import org.junit.jupiter.params.provider.MethodSource; |
25 | 31 |
|
26 | 32 | class W3CBaggagePropagatorTest { |
27 | 33 |
|
@@ -595,6 +601,114 @@ void inject_nullSetter() { |
595 | 601 | assertThat(carrier).isEmpty(); |
596 | 602 | } |
597 | 603 |
|
| 604 | + @ParameterizedTest |
| 605 | + @MethodSource |
| 606 | + void extract_limit_maxEntries(List<String> headers, Baggage expectedBaggage) { |
| 607 | + Context result = |
| 608 | + W3CBaggagePropagator.getInstance() |
| 609 | + .extract(Context.root(), ImmutableMap.of("baggage", headers), multiGetter); |
| 610 | + assertThat(Baggage.fromContext(result)).isEqualTo(expectedBaggage); |
| 611 | + } |
| 612 | + |
| 613 | + static Stream<Arguments> extract_limit_maxEntries() { |
| 614 | + return Stream.of( |
| 615 | + // Exactly at the limit — all 64 entries extracted |
| 616 | + Arguments.of(ImmutableList.of(baggageHeader(0, 64)), baggageWithEntries(0, 64)), |
| 617 | + // One over the limit — only the first 64 extracted |
| 618 | + Arguments.of(ImmutableList.of(baggageHeader(0, 65)), baggageWithEntries(0, 64)), |
| 619 | + // Split across two headers — only the first 64 total extracted |
| 620 | + Arguments.of( |
| 621 | + ImmutableList.of(baggageHeader(0, 32), baggageHeader(32, 33)), |
| 622 | + baggageWithEntries(0, 64))); |
| 623 | + } |
| 624 | + |
| 625 | + /** |
| 626 | + * Builds a {@link Baggage} with entries {@code k{start}=v{start}} through {@code |
| 627 | + * k{start+count-1}=v{start+count-1}}. |
| 628 | + */ |
| 629 | + private static Baggage baggageWithEntries(int start, int count) { |
| 630 | + BaggageBuilder builder = Baggage.builder(); |
| 631 | + for (int i = start; i < start + count; i++) { |
| 632 | + builder.put("k" + i, "v" + i); |
| 633 | + } |
| 634 | + return builder.build(); |
| 635 | + } |
| 636 | + |
| 637 | + /** Builds {@code "k{start}=v{start},...,k{start+count-1}=v{start+count-1}"}. */ |
| 638 | + private static String baggageHeader(int start, int count) { |
| 639 | + StringBuilder sb = new StringBuilder(); |
| 640 | + for (int i = start; i < start + count; i++) { |
| 641 | + if (i > start) { |
| 642 | + sb.append(","); |
| 643 | + } |
| 644 | + sb.append("k").append(i).append("=v").append(i); |
| 645 | + } |
| 646 | + return sb.toString(); |
| 647 | + } |
| 648 | + |
| 649 | + @Test |
| 650 | + void extract_limit_maxBytes_exceedsLimit() { |
| 651 | + W3CBaggagePropagator propagator = W3CBaggagePropagator.getInstance(); |
| 652 | + // Single header over 8192 bytes — dropped entirely; partial values must not be extracted |
| 653 | + String header = "k=" + fillChars('v', 8192); // 8194 bytes |
| 654 | + Context result = propagator.extract(Context.root(), ImmutableMap.of("baggage", header), getter); |
| 655 | + assertThat(Baggage.fromContext(result)).isEqualTo(Baggage.empty()); |
| 656 | + } |
| 657 | + |
| 658 | + @Test |
| 659 | + void extract_limit_maxBytes_acrossMultipleHeaders() { |
| 660 | + W3CBaggagePropagator propagator = W3CBaggagePropagator.getInstance(); |
| 661 | + // First header just under 8192 bytes is extracted; second header pushes total over the limit |
| 662 | + String almostMax = "k=" + fillChars('v', 8189); // "k=vvv..." |
| 663 | + String second = "k2=v2"; |
| 664 | + Context result = |
| 665 | + propagator.extract( |
| 666 | + Context.root(), |
| 667 | + ImmutableMap.of("baggage", ImmutableList.of(almostMax, second)), |
| 668 | + multiGetter); |
| 669 | + // Only the first header should have been extracted |
| 670 | + assertThat(Baggage.fromContext(result).size()).isEqualTo(1); |
| 671 | + assertThat(Baggage.fromContext(result).getEntryValue("k2")).isNull(); |
| 672 | + } |
| 673 | + |
| 674 | + @Test |
| 675 | + void inject_limit_maxEntries() { |
| 676 | + Map<String, String> carrier = new HashMap<>(); |
| 677 | + W3CBaggagePropagator.getInstance() |
| 678 | + .inject(Context.root().with(baggageWithEntries(0, 74)), carrier, Map::put); |
| 679 | + String header = carrier.get("baggage"); |
| 680 | + assertThat(header).isNotNull(); |
| 681 | + long count = header.chars().filter(c -> c == '=').count(); |
| 682 | + assertThat(count).isEqualTo(64); |
| 683 | + } |
| 684 | + |
| 685 | + @Test |
| 686 | + void inject_limit_maxBytes() { |
| 687 | + W3CBaggagePropagator propagator = W3CBaggagePropagator.getInstance(); |
| 688 | + // One entry whose encoded form alone exceeds the byte limit — should produce empty header |
| 689 | + Baggage baggage = Baggage.builder().put("k", fillChars('v', 8192)).build(); |
| 690 | + Map<String, String> carrier = new HashMap<>(); |
| 691 | + propagator.inject(Context.root().with(baggage), carrier, Map::put); |
| 692 | + assertThat(carrier).doesNotContainKey("baggage"); |
| 693 | + } |
| 694 | + |
| 695 | + @Test |
| 696 | + void inject_limit_maxBytes_metadata() { |
| 697 | + // Value alone fits easily (k=v is 3 bytes), but k=v;{metadata} exceeds 8192 bytes. |
| 698 | + // Verifies that metadata length is included in the byte limit check. |
| 699 | + Baggage baggage = |
| 700 | + Baggage.builder().put("k", "v", BaggageEntryMetadata.create(fillChars('x', 8190))).build(); |
| 701 | + Map<String, String> carrier = new HashMap<>(); |
| 702 | + W3CBaggagePropagator.getInstance().inject(Context.root().with(baggage), carrier, Map::put); |
| 703 | + assertThat(carrier).doesNotContainKey("baggage"); |
| 704 | + } |
| 705 | + |
| 706 | + private static String fillChars(char c, int count) { |
| 707 | + char[] chars = new char[count]; |
| 708 | + Arrays.fill(chars, c); |
| 709 | + return new String(chars); |
| 710 | + } |
| 711 | + |
598 | 712 | @Test |
599 | 713 | void toString_Valid() { |
600 | 714 | assertThat(W3CBaggagePropagator.getInstance().toString()).isEqualTo("W3CBaggagePropagator"); |
|
0 commit comments