diff --git a/spectator-api/src/main/java/com/netflix/spectator/api/ArrayTagSet.java b/spectator-api/src/main/java/com/netflix/spectator/api/ArrayTagSet.java index fed23b148..aaf7967c0 100644 --- a/spectator-api/src/main/java/com/netflix/spectator/api/ArrayTagSet.java +++ b/spectator-api/src/main/java/com/netflix/spectator/api/ArrayTagSet.java @@ -22,6 +22,7 @@ import java.util.Collection; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.concurrent.ConcurrentMap; import java.util.function.BiPredicate; import java.util.function.Predicate; @@ -150,6 +151,11 @@ ArrayTagSet addAll(Iterable ts) { checkForNullValues(newTags); return addAll(newTags, newTags.length); } + } else if (ts instanceof TagList) { + if (ts instanceof ArrayTagSet) { + return addAll((ArrayTagSet) ts); + } + return addAll((TagList) ts); } else { List data = new ArrayList<>(); for (Tag t : ts) { @@ -210,6 +216,33 @@ private ArrayTagSet addAll(String[] ts, int tsLength) { } } + private ArrayTagSet addAll(ArrayTagSet ts) { + if (ts == this || ts.isEmpty()) { + return this; + } + if (isEmpty()) { + return ts; + } + String[] newTags = new String[length + ts.length]; + int newLength = merge(newTags, tags, length, ts.tags, ts.length); + return new ArrayTagSet(newTags, newLength); + } + + private ArrayTagSet addAll(TagList ts) { + int size = ts.size(); + + if (size == 0) { + return this; + } + String[] newTags = new String[size * 2]; + int j = 0; + for (int i = 0; i < size; i++) { + newTags[j++] = Objects.requireNonNull(ts.getKey(i), "tag keys cannot be null"); + newTags[j++] = Objects.requireNonNull(ts.getValue(i), "tag values cannot be null"); + } + return addAll(newTags, newTags.length); + } + /** Add a collection of tags to the set. */ ArrayTagSet addAll(Tag[] ts) { return addAll(ts, ts.length); diff --git a/spectator-api/src/test/java/com/netflix/spectator/api/ArrayTagSetTest.java b/spectator-api/src/test/java/com/netflix/spectator/api/ArrayTagSetTest.java index 71c158660..36c2c8169 100644 --- a/spectator-api/src/test/java/com/netflix/spectator/api/ArrayTagSetTest.java +++ b/spectator-api/src/test/java/com/netflix/spectator/api/ArrayTagSetTest.java @@ -226,6 +226,27 @@ public void testMergeTag() { Assertions.assertEquals(expected, initial.addAll(update)); } + @Test + public void testMergeWithSelf() { + ArrayTagSet tags = ArrayTagSet.create("k1", "v1"); + ArrayTagSet updated = tags.addAll(tags); + Assertions.assertSame(tags, updated); + } + + @Test + public void testMergeWithEmpty() { + ArrayTagSet tags = ArrayTagSet.create("k1", "v1"); + ArrayTagSet updated = tags.addAll(ArrayTagSet.EMPTY); + Assertions.assertSame(tags, updated); + } + + @Test + public void testEmptyMergeWithNonEmpty() { + ArrayTagSet tags = ArrayTagSet.create("k1", "v1"); + ArrayTagSet updated = ArrayTagSet.EMPTY.addAll(tags); + Assertions.assertSame(tags, updated); + } + @Test public void testMergeTagWithSameKey() { ArrayTagSet initial = ArrayTagSet.create("k1", "v1"); @@ -503,4 +524,53 @@ public void compareToDifferentSizes() { Assertions.assertEquals(-1, a.compareTo(b)); Assertions.assertEquals(1, b.compareTo(a)); } + + @Test + public void mergeTagList() { + TagList tagList = new TagList() { + @Override + public String getKey(int i) { + return "k" + ++i; + } + + @Override + public String getValue(int i) { + return "v" + ++i; + } + + @Override + public int size() { + return 3; + } + }; + ArrayTagSet tags = ArrayTagSet.create("k1", "v1", "k2", "v2"); + ArrayTagSet updated = tags.addAll(tagList); + ArrayTagSet expected = ArrayTagSet.create("k1", "v1", "k2", "v2", "k3", "v3"); + Assertions.assertEquals(expected, updated); + } + + @Test + public void mergeEmptyTagList() { + TagList empty = new TagList() { + @Override + public String getKey(int i) { + throw new IndexOutOfBoundsException(); + } + + @Override + public String getValue(int i) { + throw new IndexOutOfBoundsException(); + } + + @Override + public int size() { + return 0; + } + }; + + ArrayTagSet tags = ArrayTagSet.create("k1", "v1", "k2", "v2"); + ArrayTagSet updated = tags.addAll(empty); + + Assertions.assertSame(tags, updated); + } }