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

grpc / grpc-java / #19740

18 Mar 2025 09:05PM UTC coverage: 88.588% (+0.05%) from 88.536%
#19740

push

github

web-flow
xds: Use XdsDependencyManager for XdsNameResolver

Contributes to the gRFC A74 effort.
https://github.com/grpc/proposal/blob/master/A74-xds-config-tears.md

The alternative to using Mockito's ArgumentMatcher is to use Hamcrest.
However, Hamcrest did not impress me. ArgumentMatcher is trivial if you
don't care about the error message.

This fixes a pre-existing issue where ConfigSelector.releaseCluster
could revert the LB config back to using cluster manager after releasing
all RPCs using a cluster have committed.

Co-authored-by: Larry Safran <lsafran@google.com>

34583 of 39038 relevant lines covered (88.59%)

0.89 hits per line

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

92.77
/../xds/src/main/java/io/grpc/xds/XdsConfig.java
1
/*
2
 * Copyright 2024 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.xds;
18

19
import static com.google.common.base.Preconditions.checkNotNull;
20

21
import com.google.common.collect.ImmutableMap;
22
import io.grpc.StatusOr;
23
import io.grpc.xds.XdsClusterResource.CdsUpdate;
24
import io.grpc.xds.XdsEndpointResource.EdsUpdate;
25
import io.grpc.xds.XdsListenerResource.LdsUpdate;
26
import io.grpc.xds.XdsRouteConfigureResource.RdsUpdate;
27
import java.io.Closeable;
28
import java.util.HashMap;
29
import java.util.Map;
30
import java.util.Objects;
31
import java.util.Set;
32

33
/**
34
 * Represents the xDS configuration tree for a specified Listener.
35
 */
36
final class XdsConfig {
37
  private final LdsUpdate listener;
38
  private final RdsUpdate route;
39
  private final VirtualHost virtualHost;
40
  private final ImmutableMap<String, StatusOr<XdsClusterConfig>> clusters;
41
  private final int hashCode;
42

43
  XdsConfig(LdsUpdate listener, RdsUpdate route, Map<String, StatusOr<XdsClusterConfig>> clusters,
44
            VirtualHost virtualHost) {
45
    this(listener, route, virtualHost, ImmutableMap.copyOf(clusters));
1✔
46
  }
1✔
47

48
  public XdsConfig(LdsUpdate listener, RdsUpdate route, VirtualHost virtualHost,
49
                   ImmutableMap<String, StatusOr<XdsClusterConfig>> clusters) {
1✔
50
    this.listener = listener;
1✔
51
    this.route = route;
1✔
52
    this.virtualHost = virtualHost;
1✔
53
    this.clusters = clusters;
1✔
54

55
    hashCode = Objects.hash(listener, route, virtualHost, clusters);
1✔
56
  }
1✔
57

58
  @Override
59
  public boolean equals(Object obj) {
60
    if (!(obj instanceof XdsConfig)) {
1✔
61
      return false;
×
62
    }
63

64
    XdsConfig o = (XdsConfig) obj;
1✔
65

66
    return hashCode() == o.hashCode() && Objects.equals(listener, o.listener)
1✔
67
        && Objects.equals(route, o.route) && Objects.equals(virtualHost, o.virtualHost)
1✔
68
        && Objects.equals(clusters, o.clusters);
1✔
69
  }
70

71
  @Override
72
  public int hashCode() {
73
    return hashCode;
1✔
74
  }
75

76
  @Override
77
  public String toString() {
78
    StringBuilder builder = new StringBuilder();
1✔
79
    builder.append("XdsConfig{")
1✔
80
        .append("\n  listener=").append(listener)
1✔
81
        .append(",\n  route=").append(route)
1✔
82
        .append(",\n  virtualHost=").append(virtualHost)
1✔
83
        .append(",\n  clusters=").append(clusters)
1✔
84
        .append("\n}");
1✔
85
    return builder.toString();
1✔
86
  }
87

88
  public LdsUpdate getListener() {
89
    return listener;
1✔
90
  }
91

92
  public RdsUpdate getRoute() {
93
    return route;
×
94
  }
95

96
  public VirtualHost getVirtualHost() {
97
    return virtualHost;
1✔
98
  }
99

100
  public ImmutableMap<String, StatusOr<XdsClusterConfig>> getClusters() {
101
    return clusters;
1✔
102
  }
103

104
  static final class XdsClusterConfig {
105
    private final String clusterName;
106
    private final CdsUpdate clusterResource;
107
    private final ClusterChild children; // holds details
108

109
    XdsClusterConfig(String clusterName, CdsUpdate clusterResource, ClusterChild details) {
1✔
110
      this.clusterName = checkNotNull(clusterName, "clusterName");
1✔
111
      this.clusterResource = checkNotNull(clusterResource, "clusterResource");
1✔
112
      this.children = checkNotNull(details, "details");
1✔
113
    }
1✔
114

115
    @Override
116
    public int hashCode() {
117
      return clusterName.hashCode() + clusterResource.hashCode() + children.hashCode();
1✔
118
    }
119

120
    @Override
121
    public boolean equals(Object obj) {
122
      if (!(obj instanceof XdsClusterConfig)) {
1✔
123
        return false;
×
124
      }
125
      XdsClusterConfig o = (XdsClusterConfig) obj;
1✔
126
      return Objects.equals(clusterName, o.clusterName)
1✔
127
          && Objects.equals(clusterResource, o.clusterResource)
1✔
128
          && Objects.equals(children, o.children);
1✔
129
    }
130

131
    @Override
132
    public String toString() {
133
      StringBuilder builder = new StringBuilder();
1✔
134
      builder.append("XdsClusterConfig{clusterName=").append(clusterName)
1✔
135
          .append(", clusterResource=").append(clusterResource)
1✔
136
          .append(", children={").append(children)
1✔
137
          .append("}");
1✔
138
      return builder.toString();
1✔
139
    }
140

141
    public String getClusterName() {
142
      return clusterName;
×
143
    }
144

145
    public CdsUpdate getClusterResource() {
146
      return clusterResource;
1✔
147
    }
148

149
    public ClusterChild getChildren() {
150
      return children;
1✔
151
    }
152

153
    interface ClusterChild {}
154

155
    /** Endpoint info for EDS and LOGICAL_DNS clusters.  If there was an
156
     * error, endpoints will be null and resolution_note will be set.
157
     */
158
    static final class EndpointConfig implements ClusterChild {
159
      private final StatusOr<EdsUpdate> endpoint;
160

161
      public EndpointConfig(StatusOr<EdsUpdate> endpoint) {
1✔
162
        this.endpoint = checkNotNull(endpoint, "endpoint");
1✔
163
      }
1✔
164

165
      @Override
166
      public int hashCode() {
167
        return endpoint.hashCode();
1✔
168
      }
169

170
      @Override
171
      public boolean equals(Object obj) {
172
        if (!(obj instanceof EndpointConfig)) {
1✔
173
          return false;
×
174
        }
175
        return Objects.equals(endpoint, ((EndpointConfig)obj).endpoint);
1✔
176
      }
177

178
      public StatusOr<EdsUpdate> getEndpoint() {
179
        return endpoint;
1✔
180
      }
181

182
      @Override
183
      public String toString() {
184
        if (endpoint.hasValue()) {
1✔
185
          return "EndpointConfig{endpoint=" + endpoint.getValue() + "}";
1✔
186
        } else {
187
          return "EndpointConfig{error=" + endpoint.getStatus() + "}";
1✔
188
        }
189
      }
190
    }
191

192
    // The list of leaf clusters for an aggregate cluster.
193
    static final class AggregateConfig implements ClusterChild {
194
      private final Set<String> leafNames;
195

196
      public AggregateConfig(Set<String> leafNames) {
1✔
197
        this.leafNames = checkNotNull(leafNames, "leafNames");
1✔
198
      }
1✔
199

200
      @Override
201
      public int hashCode() {
202
        return leafNames.hashCode();
1✔
203
      }
204

205
      @Override
206
      public boolean equals(Object obj) {
207
        if (!(obj instanceof AggregateConfig)) {
1✔
208
          return false;
×
209
        }
210
        return Objects.equals(leafNames, ((AggregateConfig) obj).leafNames);
1✔
211
      }
212
    }
213
  }
214

215
  static final class XdsConfigBuilder {
1✔
216
    private LdsUpdate listener;
217
    private RdsUpdate route;
218
    private Map<String, StatusOr<XdsClusterConfig>> clusters = new HashMap<>();
1✔
219
    private VirtualHost virtualHost;
220

221
    XdsConfigBuilder setListener(LdsUpdate listener) {
222
      this.listener = checkNotNull(listener, "listener");
1✔
223
      return this;
1✔
224
    }
225

226
    XdsConfigBuilder setRoute(RdsUpdate route) {
227
      this.route = checkNotNull(route, "route");
1✔
228
      return this;
1✔
229
    }
230

231
    XdsConfigBuilder addCluster(String name, StatusOr<XdsClusterConfig> clusterConfig) {
232
      checkNotNull(name, "name");
1✔
233
      checkNotNull(clusterConfig, "clusterConfig");
1✔
234
      clusters.put(name, clusterConfig);
1✔
235
      return this;
1✔
236
    }
237

238
    XdsConfigBuilder setVirtualHost(VirtualHost virtualHost) {
239
      this.virtualHost = checkNotNull(virtualHost, "virtualHost");
1✔
240
      return this;
1✔
241
    }
242

243
    XdsConfig build() {
244
      checkNotNull(listener, "listener");
1✔
245
      checkNotNull(route, "route");
1✔
246
      checkNotNull(virtualHost, "virtualHost");
1✔
247
      return new XdsConfig(listener, route, clusters, virtualHost);
1✔
248
    }
249
  }
250

251
  public interface XdsClusterSubscriptionRegistry {
252
    Closeable subscribeToCluster(String clusterName);
253
  }
254
}
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

© 2025 Coveralls, Inc