• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

grpc / grpc-java / #20166

05 Feb 2026 04:38PM UTC coverage: 88.71% (+0.005%) from 88.705%
#20166

push

github

web-flow
api: Remove obsolete TODO in EquivalentAddressGroup#toString (#12627)

### Background

EquivalentAddressGroup is intended to represent a small set of addresses
for the same endpoint (e.g., IPv4/IPv6). A long-standing TODO in
EquivalentAddressGroup#toString() suggested adding summarization for
very large address lists.

During review, maintainers noted that large address lists within a
single EquivalentAddressGroup are no longer expected in current designs,
and the historical behavior that could create a very large group (e.g.,
by aggregating many groups into one) has been removed. As a result, the
TODO is now obsolete.

### Changes

Remove the obsolete TODO comment in EquivalentAddressGroup#toString().

Add a brief explanatory comment capturing why summarization is no longer
needed.

### Purpose

Avoid leaving stale TODOs that imply work is still required.

Align the codebase with the intended semantics and current behavior of
EquivalentAddressGroup.

### Note

This change is comment-only and does not alter any runtime behavior or
output format.

Fixes https://github.com/grpc/grpc-java/issues/12593

---------

35415 of 39922 relevant lines covered (88.71%)

0.89 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

94.29
/../api/src/main/java/io/grpc/EquivalentAddressGroup.java
1
/*
2
 * Copyright 2015 The gRPC Authors
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *     http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16

17
package io.grpc;
18

19
import com.google.common.base.Preconditions;
20
import java.lang.annotation.Documented;
21
import java.lang.annotation.Retention;
22
import java.lang.annotation.RetentionPolicy;
23
import java.net.SocketAddress;
24
import java.util.ArrayList;
25
import java.util.Collections;
26
import java.util.List;
27

28
/**
29
 * A group of {@link SocketAddress}es that are considered equivalent when channel makes connections.
30
 *
31
 * <p>Usually the addresses are addresses resolved from the same host name, and connecting to any of
32
 * them is equally sufficient. They do have order. An address appears earlier on the list is likely
33
 * to be tried earlier.
34
 */
35
@ExperimentalApi("https://github.com/grpc/grpc-java/issues/1770")
36
public final class EquivalentAddressGroup {
37

38
  /**
39
   * The authority to be used when constructing Subchannels for this EquivalentAddressGroup.
40
   * However, if the channel has overridden authority via
41
   * {@link ManagedChannelBuilder#overrideAuthority(String)}, the transport will use the channel's
42
   * authority override.
43
   *
44
   * <p>The authority <strong>must</strong> be from a trusted source, because if the authority is
45
   * tampered with, RPCs may be sent to attackers which may leak sensitive user data. If the
46
   * authority was acquired by doing I/O, the communication must be authenticated (e.g., via TLS).
47
   * Recognize that the server that provided the authority can trivially impersonate the service.
48
   */
49
  @Attr
50
  @ExperimentalApi("https://github.com/grpc/grpc-java/issues/6138")
51
  public static final Attributes.Key<String> ATTR_AUTHORITY_OVERRIDE =
1✔
52
      Attributes.Key.create("io.grpc.EquivalentAddressGroup.ATTR_AUTHORITY_OVERRIDE");
1✔
53
  /**
54
   * The name of the locality that this EquivalentAddressGroup is in.
55
   */
56
  public static final Attributes.Key<String> ATTR_LOCALITY_NAME =
1✔
57
      Attributes.Key.create("io.grpc.EquivalentAddressGroup.LOCALITY");
1✔
58
  /**
59
   * Endpoint weight for load balancing purposes. While the type is Long, it must be a valid uint32.
60
   * Must not be zero. The weight is proportional to the other endpoints; if an endpoint's weight is
61
   * twice that of another endpoint, it is intended to receive twice the load.
62
   */
63
  @Attr
64
  static final Attributes.Key<Long> ATTR_WEIGHT =
1✔
65
      Attributes.Key.create("io.grpc.EquivalentAddressGroup.ATTR_WEIGHT");
1✔
66

67
  private final List<SocketAddress> addrs;
68
  private final Attributes attrs;
69

70
  /**
71
   * {@link SocketAddress} docs say that the addresses are immutable, so we cache the hashCode.
72
   */
73
  private final int hashCode;
74

75
  /**
76
   * List constructor without {@link Attributes}.
77
   */
78
  public EquivalentAddressGroup(List<SocketAddress> addrs) {
79
    this(addrs, Attributes.EMPTY);
1✔
80
  }
1✔
81

82
  /**
83
   * List constructor with {@link Attributes}.
84
   */
85
  public EquivalentAddressGroup(List<SocketAddress> addrs, @Attr Attributes attrs) {
1✔
86
    Preconditions.checkArgument(!addrs.isEmpty(), "addrs is empty");
1✔
87
    this.addrs = Collections.unmodifiableList(new ArrayList<>(addrs));
1✔
88
    this.attrs = Preconditions.checkNotNull(attrs, "attrs");
1✔
89
    // Attributes may contain mutable objects, which means Attributes' hashCode may change over
90
    // time, thus we don't cache Attributes' hashCode.
91
    hashCode = this.addrs.hashCode();
1✔
92
  }
1✔
93

94
  /**
95
   * Singleton constructor without Attributes.
96
   */
97
  public EquivalentAddressGroup(SocketAddress addr) {
98
    this(addr, Attributes.EMPTY);
1✔
99
  }
1✔
100

101
  /**
102
   * Singleton constructor with Attributes.
103
   */
104
  public EquivalentAddressGroup(SocketAddress addr, @Attr Attributes attrs) {
105
    this(Collections.singletonList(addr), attrs);
1✔
106
  }
1✔
107

108
  /**
109
   * Returns an immutable list of the addresses.
110
   */
111
  public List<SocketAddress> getAddresses() {
112
    return addrs;
1✔
113
  }
114

115
  /**
116
   * Returns the attributes.
117
   */
118
  @Attr
119
  public Attributes getAttributes() {
120
    return attrs;
1✔
121
  }
122

123
  @Override
124
  public String toString() {
125
    // EquivalentAddressGroup is intended to contain a small number of addresses for the same
126
    // endpoint(e.g., IPv4/IPv6). Aggregating many groups into a single EquivalentAddressGroup
127
    // is no longer done, so this no longer needs summarization.
128
    return "[" + addrs + "/" + attrs + "]";
1✔
129
  }
130

131
  @Override
132
  public int hashCode() {
133
    // Avoids creating an iterator on the underlying array list.
134
    return hashCode;
1✔
135
  }
136

137
  /**
138
   * Returns true if the given object is also an {@link EquivalentAddressGroup} with an equal
139
   * address list and equal attribute values.
140
   *
141
   * <p>Note that if the attributes include mutable values, it is possible for two objects to be
142
   * considered equal at one point in time and not equal at another (due to concurrent mutation of
143
   * attribute values).
144
   */
145
  @Override
146
  public boolean equals(Object other) {
147
    if (this == other) {
1✔
148
      return true;
1✔
149
    }
150
    if (!(other instanceof EquivalentAddressGroup)) {
1✔
151
      return false;
×
152
    }
153
    EquivalentAddressGroup that = (EquivalentAddressGroup) other;
1✔
154
    if (addrs.size() != that.addrs.size()) {
1✔
155
      return false;
×
156
    }
157
    // Avoids creating an iterator on the underlying array list.
158
    for (int i = 0; i < addrs.size(); i++) {
1✔
159
      if (!addrs.get(i).equals(that.addrs.get(i))) {
1✔
160
        return false;
1✔
161
      }
162
    }
163
    if (!attrs.equals(that.attrs)) {
1✔
164
      return false;
1✔
165
    }
166
    return true;
1✔
167
  }
168

169
  /**
170
   * Annotation for {@link EquivalentAddressGroup}'s attributes. It follows the annotation semantics
171
   * defined by {@link Attributes}.
172
   */
173
  @ExperimentalApi("https://github.com/grpc/grpc-java/issues/4972")
174
  @Retention(RetentionPolicy.SOURCE)
175
  @Documented
176
  public @interface Attr {}
177
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc