use of io.grpc.LoadBalancer.Subchannel in project grpc-java by grpc.
the class GrpclbLoadBalancerTest method grpclbWorking_lbSendsFallbackMessage.
@Test
public void grpclbWorking_lbSendsFallbackMessage() {
InOrder inOrder = inOrder(helper, subchannelPool);
List<EquivalentAddressGroup> backendList = createResolvedBackendAddresses(2);
List<EquivalentAddressGroup> grpclbBalancerList = createResolvedBalancerAddresses(2);
deliverResolvedAddresses(backendList, grpclbBalancerList);
// Fallback timer is started as soon as the addresses are resolved.
assertEquals(1, fakeClock.numPendingTasks(FALLBACK_MODE_TASK_FILTER));
verify(helper).createOobChannel(eq(xattr(grpclbBalancerList)), eq(lbAuthority(0) + NO_USE_AUTHORITY_SUFFIX));
assertEquals(1, fakeOobChannels.size());
ManagedChannel oobChannel = fakeOobChannels.poll();
verify(mockLbService).balanceLoad(lbResponseObserverCaptor.capture());
StreamObserver<LoadBalanceResponse> lbResponseObserver = lbResponseObserverCaptor.getValue();
assertEquals(1, lbRequestObservers.size());
StreamObserver<LoadBalanceRequest> lbRequestObserver = lbRequestObservers.poll();
verify(lbRequestObserver).onNext(eq(LoadBalanceRequest.newBuilder().setInitialRequest(InitialLoadBalanceRequest.newBuilder().setName(SERVICE_AUTHORITY).build()).build()));
// Simulate receiving LB response
ServerEntry backend1a = new ServerEntry("127.0.0.1", 2000, "token0001");
ServerEntry backend1b = new ServerEntry("127.0.0.1", 2010, "token0002");
List<ServerEntry> backends1 = Arrays.asList(backend1a, backend1b);
inOrder.verify(helper, never()).updateBalancingState(any(ConnectivityState.class), any(SubchannelPicker.class));
logs.clear();
lbResponseObserver.onNext(buildInitialResponse());
assertThat(logs).containsExactly("INFO: [grpclb-<api.google.com>] Got an LB initial response: " + buildInitialResponse());
logs.clear();
lbResponseObserver.onNext(buildLbResponse(backends1));
inOrder.verify(subchannelPool).takeOrCreateSubchannel(eq(new EquivalentAddressGroup(backend1a.addr, LB_BACKEND_ATTRS)), any(Attributes.class));
inOrder.verify(subchannelPool).takeOrCreateSubchannel(eq(new EquivalentAddressGroup(backend1b.addr, LB_BACKEND_ATTRS)), any(Attributes.class));
assertEquals(2, mockSubchannels.size());
Subchannel subchannel1 = mockSubchannels.poll();
Subchannel subchannel2 = mockSubchannels.poll();
verify(subchannel1).requestConnection();
verify(subchannel2).requestConnection();
assertEquals(new EquivalentAddressGroup(backend1a.addr, LB_BACKEND_ATTRS), subchannel1.getAddresses());
assertEquals(new EquivalentAddressGroup(backend1b.addr, LB_BACKEND_ATTRS), subchannel2.getAddresses());
deliverSubchannelState(subchannel1, ConnectivityStateInfo.forNonError(CONNECTING));
deliverSubchannelState(subchannel2, ConnectivityStateInfo.forNonError(CONNECTING));
inOrder.verify(helper).updateBalancingState(eq(CONNECTING), pickerCaptor.capture());
RoundRobinPicker picker0 = (RoundRobinPicker) pickerCaptor.getValue();
assertThat(picker0.dropList).containsExactly(null, null);
assertThat(picker0.pickList).containsExactly(BUFFER_ENTRY);
inOrder.verifyNoMoreInteractions();
assertThat(logs).containsExactly("DEBUG: [grpclb-<api.google.com>] Got an LB response: " + buildLbResponse(backends1)).inOrder();
logs.clear();
// Let subchannels be connected
deliverSubchannelState(subchannel2, ConnectivityStateInfo.forNonError(READY));
inOrder.verify(helper).updateBalancingState(eq(READY), pickerCaptor.capture());
RoundRobinPicker picker1 = (RoundRobinPicker) pickerCaptor.getValue();
assertThat(picker1.dropList).containsExactly(null, null);
assertThat(picker1.pickList).containsExactly(new BackendEntry(subchannel2, getLoadRecorder(), "token0002"));
deliverSubchannelState(subchannel1, ConnectivityStateInfo.forNonError(READY));
inOrder.verify(helper).updateBalancingState(eq(READY), pickerCaptor.capture());
RoundRobinPicker picker2 = (RoundRobinPicker) pickerCaptor.getValue();
assertThat(picker2.dropList).containsExactly(null, null);
assertThat(picker2.pickList).containsExactly(new BackendEntry(subchannel1, getLoadRecorder(), "token0001"), new BackendEntry(subchannel2, getLoadRecorder(), "token0002")).inOrder();
// Balancer forces entering fallback mode
lbResponseObserver.onNext(buildLbFallbackResponse());
// existing subchannels must be returned immediately to gracefully shutdown.
verify(subchannelPool).returnSubchannel(eq(subchannel1), eq(ConnectivityStateInfo.forNonError(READY)));
verify(subchannelPool).returnSubchannel(eq(subchannel2), eq(ConnectivityStateInfo.forNonError(READY)));
// verify fallback
fallbackTestVerifyUseOfFallbackBackendLists(inOrder, backendList);
assertFalse(oobChannel.isShutdown());
verify(lbRequestObserver, never()).onCompleted();
// ////////////////////////////////////////////////////////////////////
// Name resolver sends new resolution results without any backend addr
// ////////////////////////////////////////////////////////////////////
deliverResolvedAddresses(Collections.<EquivalentAddressGroup>emptyList(), grpclbBalancerList);
// Still in fallback logic, except that the backend list is empty
for (Subchannel subchannel : mockSubchannels) {
verify(subchannelPool).returnSubchannel(eq(subchannel), any(ConnectivityStateInfo.class));
}
// RPC error status includes message of fallback requested by balancer
inOrder.verify(helper).updateBalancingState(eq(TRANSIENT_FAILURE), pickerCaptor.capture());
PickResult result = pickerCaptor.getValue().pickSubchannel(mock(PickSubchannelArgs.class));
assertThat(result.getStatus().getCode()).isEqualTo(Code.UNAVAILABLE);
assertThat(result.getStatus().getDescription()).startsWith(GrpclbState.NO_FALLBACK_BACKENDS_STATUS.getDescription());
assertThat(result.getStatus().getDescription()).contains(GrpclbState.BALANCER_REQUESTED_FALLBACK_STATUS.getDescription());
// exit fall back by providing two new backends
ServerEntry backend2a = new ServerEntry("127.0.0.1", 8000, "token1001");
ServerEntry backend2b = new ServerEntry("127.0.0.1", 8010, "token1002");
List<ServerEntry> backends2 = Arrays.asList(backend2a, backend2b);
inOrder.verify(helper, never()).updateBalancingState(any(ConnectivityState.class), any(SubchannelPicker.class));
logs.clear();
lbResponseObserver.onNext(buildLbResponse(backends2));
inOrder.verify(subchannelPool).takeOrCreateSubchannel(eq(new EquivalentAddressGroup(backend2a.addr, LB_BACKEND_ATTRS)), any(Attributes.class));
inOrder.verify(subchannelPool).takeOrCreateSubchannel(eq(new EquivalentAddressGroup(backend2b.addr, LB_BACKEND_ATTRS)), any(Attributes.class));
assertEquals(2, mockSubchannels.size());
Subchannel subchannel3 = mockSubchannels.poll();
Subchannel subchannel4 = mockSubchannels.poll();
verify(subchannel3).requestConnection();
verify(subchannel4).requestConnection();
assertEquals(new EquivalentAddressGroup(backend2a.addr, LB_BACKEND_ATTRS), subchannel3.getAddresses());
assertEquals(new EquivalentAddressGroup(backend2b.addr, LB_BACKEND_ATTRS), subchannel4.getAddresses());
deliverSubchannelState(subchannel3, ConnectivityStateInfo.forNonError(CONNECTING));
deliverSubchannelState(subchannel4, ConnectivityStateInfo.forNonError(CONNECTING));
inOrder.verify(helper).updateBalancingState(eq(CONNECTING), pickerCaptor.capture());
RoundRobinPicker picker6 = (RoundRobinPicker) pickerCaptor.getValue();
assertThat(picker6.dropList).containsExactly(null, null);
assertThat(picker6.pickList).containsExactly(BUFFER_ENTRY);
inOrder.verifyNoMoreInteractions();
assertThat(logs).containsExactly("DEBUG: [grpclb-<api.google.com>] Got an LB response: " + buildLbResponse(backends2)).inOrder();
logs.clear();
// Let new subchannels be connected
deliverSubchannelState(subchannel3, ConnectivityStateInfo.forNonError(READY));
inOrder.verify(helper).updateBalancingState(eq(READY), pickerCaptor.capture());
RoundRobinPicker picker3 = (RoundRobinPicker) pickerCaptor.getValue();
assertThat(picker3.dropList).containsExactly(null, null);
assertThat(picker3.pickList).containsExactly(new BackendEntry(subchannel3, getLoadRecorder(), "token1001"));
deliverSubchannelState(subchannel4, ConnectivityStateInfo.forNonError(READY));
inOrder.verify(helper).updateBalancingState(eq(READY), pickerCaptor.capture());
RoundRobinPicker picker4 = (RoundRobinPicker) pickerCaptor.getValue();
assertThat(picker4.dropList).containsExactly(null, null);
assertThat(picker4.pickList).containsExactly(new BackendEntry(subchannel3, getLoadRecorder(), "token1001"), new BackendEntry(subchannel4, getLoadRecorder(), "token1002")).inOrder();
}
use of io.grpc.LoadBalancer.Subchannel in project grpc-java by grpc.
the class GrpclbLoadBalancerTest method grpclbWorking_pickFirstMode_lbSendsEmptyAddress.
@Test
public void grpclbWorking_pickFirstMode_lbSendsEmptyAddress() throws Exception {
InOrder inOrder = inOrder(helper);
List<EquivalentAddressGroup> grpclbBalancerList = createResolvedBalancerAddresses(1);
deliverResolvedAddresses(Collections.<EquivalentAddressGroup>emptyList(), grpclbBalancerList, GrpclbConfig.create(Mode.PICK_FIRST));
assertEquals(1, fakeOobChannels.size());
verify(mockLbService).balanceLoad(lbResponseObserverCaptor.capture());
StreamObserver<LoadBalanceResponse> lbResponseObserver = lbResponseObserverCaptor.getValue();
assertEquals(1, lbRequestObservers.size());
StreamObserver<LoadBalanceRequest> lbRequestObserver = lbRequestObservers.poll();
verify(lbRequestObserver).onNext(eq(LoadBalanceRequest.newBuilder().setInitialRequest(InitialLoadBalanceRequest.newBuilder().setName(SERVICE_AUTHORITY).build()).build()));
// Simulate receiving LB response
List<ServerEntry> backends1 = Arrays.asList(new ServerEntry("127.0.0.1", 2000, "token0001"), new ServerEntry("127.0.0.1", 2010, "token0002"));
inOrder.verify(helper, never()).updateBalancingState(any(ConnectivityState.class), any(SubchannelPicker.class));
lbResponseObserver.onNext(buildInitialResponse());
lbResponseObserver.onNext(buildLbResponse(backends1));
inOrder.verify(helper).createSubchannel(createSubchannelArgsCaptor.capture());
CreateSubchannelArgs createSubchannelArgs = createSubchannelArgsCaptor.getValue();
assertThat(createSubchannelArgs.getAddresses()).containsExactly(new EquivalentAddressGroup(backends1.get(0).addr, eagAttrsWithToken("token0001")), new EquivalentAddressGroup(backends1.get(1).addr, eagAttrsWithToken("token0002")));
// Initially IDLE
inOrder.verify(helper).updateBalancingState(eq(IDLE), pickerCaptor.capture());
RoundRobinPicker picker0 = (RoundRobinPicker) pickerCaptor.getValue();
// Only one subchannel is created
assertThat(mockSubchannels).hasSize(1);
Subchannel subchannel = mockSubchannels.poll();
assertThat(picker0.dropList).containsExactly(null, null);
assertThat(picker0.pickList).containsExactly(new IdleSubchannelEntry(subchannel, syncContext));
// PICK_FIRST doesn't eagerly connect
verify(subchannel, never()).requestConnection();
// CONNECTING
deliverSubchannelState(subchannel, ConnectivityStateInfo.forNonError(CONNECTING));
inOrder.verify(helper).updateBalancingState(eq(CONNECTING), pickerCaptor.capture());
RoundRobinPicker picker1 = (RoundRobinPicker) pickerCaptor.getValue();
assertThat(picker1.dropList).containsExactly(null, null);
assertThat(picker1.pickList).containsExactly(BUFFER_ENTRY);
// TRANSIENT_FAILURE
Status error = Status.UNAVAILABLE.withDescription("Simulated connection error");
deliverSubchannelState(subchannel, ConnectivityStateInfo.forTransientFailure(error));
inOrder.verify(helper).updateBalancingState(eq(TRANSIENT_FAILURE), pickerCaptor.capture());
RoundRobinPicker picker2 = (RoundRobinPicker) pickerCaptor.getValue();
assertThat(picker2.dropList).containsExactly(null, null);
assertThat(picker2.pickList).containsExactly(new ErrorEntry(error));
// READY
deliverSubchannelState(subchannel, ConnectivityStateInfo.forNonError(READY));
inOrder.verify(helper).updateBalancingState(eq(READY), pickerCaptor.capture());
RoundRobinPicker picker3 = (RoundRobinPicker) pickerCaptor.getValue();
assertThat(picker3.dropList).containsExactly(null, null);
assertThat(picker3.pickList).containsExactly(new BackendEntry(subchannel, new TokenAttachingTracerFactory(getLoadRecorder())));
inOrder.verify(helper, never()).updateBalancingState(any(ConnectivityState.class), any(SubchannelPicker.class));
// Empty addresses from LB
lbResponseObserver.onNext(buildLbResponse(Collections.<ServerEntry>emptyList()));
// new addresses will be updated to the existing subchannel
// createSubchannel() has ever been called only once
inOrder.verify(helper, never()).createSubchannel(any(CreateSubchannelArgs.class));
assertThat(mockSubchannels).isEmpty();
verify(subchannel).shutdown();
// RPC error status includes message of no backends provided by balancer
inOrder.verify(helper).updateBalancingState(eq(TRANSIENT_FAILURE), pickerCaptor.capture());
RoundRobinPicker errorPicker = (RoundRobinPicker) pickerCaptor.getValue();
assertThat(errorPicker.pickList).containsExactly(new ErrorEntry(GrpclbState.NO_AVAILABLE_BACKENDS_STATUS));
lbResponseObserver.onNext(buildLbResponse(Collections.<ServerEntry>emptyList()));
// Test recover from new LB response with addresses
// New server list with drops
List<ServerEntry> backends2 = Arrays.asList(new ServerEntry("127.0.0.1", 2000, "token0001"), // drop
new ServerEntry("token0003"), new ServerEntry("127.0.0.1", 2020, "token0004"));
inOrder.verify(helper, never()).updateBalancingState(any(ConnectivityState.class), any(SubchannelPicker.class));
lbResponseObserver.onNext(buildLbResponse(backends2));
// new addresses will be updated to the existing subchannel
inOrder.verify(helper, times(1)).createSubchannel(any(CreateSubchannelArgs.class));
inOrder.verify(helper).updateBalancingState(eq(IDLE), pickerCaptor.capture());
subchannel = mockSubchannels.poll();
// Subchannel became READY
deliverSubchannelState(subchannel, ConnectivityStateInfo.forNonError(CONNECTING));
deliverSubchannelState(subchannel, ConnectivityStateInfo.forNonError(READY));
inOrder.verify(helper).updateBalancingState(eq(READY), pickerCaptor.capture());
RoundRobinPicker picker4 = (RoundRobinPicker) pickerCaptor.getValue();
assertThat(picker4.pickList).containsExactly(new BackendEntry(subchannel, new TokenAttachingTracerFactory(getLoadRecorder())));
}
use of io.grpc.LoadBalancer.Subchannel in project grpc-java by grpc.
the class GrpclbLoadBalancerTest method grpclbFallback_noBalancerAddress.
@Test
public void grpclbFallback_noBalancerAddress() {
InOrder inOrder = inOrder(helper, subchannelPool);
// Create 5 distinct backends
List<EquivalentAddressGroup> backends = createResolvedBackendAddresses(5);
// Name resolver gives the first two backend addresses
List<EquivalentAddressGroup> backendList = backends.subList(0, 2);
deliverResolvedAddresses(backendList, Collections.<EquivalentAddressGroup>emptyList());
assertThat(logs).contains("INFO: [grpclb-<api.google.com>] Using fallback backends");
// Fall back to the backends from resolver
fallbackTestVerifyUseOfFallbackBackendLists(inOrder, backendList);
// No fallback timeout timer scheduled.
assertEquals(0, fakeClock.numPendingTasks(FALLBACK_MODE_TASK_FILTER));
verify(helper, never()).createOobChannel(ArgumentMatchers.<EquivalentAddressGroup>anyList(), anyString());
logs.clear();
// ///////////////////////////////////////////////////////////////////////////////////////
// Name resolver sends new resolution results with new backend addr but no balancer addr
// ///////////////////////////////////////////////////////////////////////////////////////
// Name resolver then gives the last three backends
backendList = backends.subList(2, 5);
deliverResolvedAddresses(backendList, Collections.<EquivalentAddressGroup>emptyList());
assertThat(logs).contains("INFO: [grpclb-<api.google.com>] Using fallback backends");
// Shift to use updated backends
fallbackTestVerifyUseOfFallbackBackendLists(inOrder, backendList);
logs.clear();
// /////////////////////////////////////////////////////////////////////////////////////
// Name resolver sends new resolution results without any backend addr or balancer addr
// /////////////////////////////////////////////////////////////////////////////////////
deliverResolvedAddresses(Collections.<EquivalentAddressGroup>emptyList(), Collections.<EquivalentAddressGroup>emptyList());
assertThat(logs).containsExactly("DEBUG: [grpclb-<api.google.com>] Error: Status{code=UNAVAILABLE, " + "description=No backend or balancer addresses found, cause=null}");
// Keep using existing fallback addresses without interruption
for (Subchannel subchannel : mockSubchannels) {
verify(subchannelPool, never()).returnSubchannel(eq(subchannel), any(ConnectivityStateInfo.class));
}
verify(helper, never()).updateBalancingState(eq(TRANSIENT_FAILURE), any(SubchannelPicker.class));
}
use of io.grpc.LoadBalancer.Subchannel in project grpc-java by grpc.
the class GrpclbLoadBalancerTest method roundRobinPickerNoDrop.
@Test
public void roundRobinPickerNoDrop() {
GrpclbClientLoadRecorder loadRecorder = new GrpclbClientLoadRecorder(fakeClock.getTimeProvider());
Subchannel subchannel = mock(Subchannel.class);
BackendEntry b1 = new BackendEntry(subchannel, loadRecorder, "LBTOKEN0001");
BackendEntry b2 = new BackendEntry(subchannel, loadRecorder, "LBTOKEN0002");
List<BackendEntry> pickList = Arrays.asList(b1, b2);
RoundRobinPicker picker = new RoundRobinPicker(Collections.<DropEntry>emptyList(), pickList);
PickSubchannelArgs args1 = mock(PickSubchannelArgs.class);
Metadata headers1 = new Metadata();
// The existing token on the headers will be replaced
headers1.put(GrpclbConstants.TOKEN_METADATA_KEY, "LBTOKEN__OLD");
when(args1.getHeaders()).thenReturn(headers1);
assertSame(b1.result, picker.pickSubchannel(args1));
verify(args1).getHeaders();
assertThat(headers1.getAll(GrpclbConstants.TOKEN_METADATA_KEY)).containsExactly("LBTOKEN0001");
PickSubchannelArgs args2 = mock(PickSubchannelArgs.class);
Metadata headers2 = new Metadata();
when(args2.getHeaders()).thenReturn(headers2);
assertSame(b2.result, picker.pickSubchannel(args2));
verify(args2).getHeaders();
assertThat(headers2.getAll(GrpclbConstants.TOKEN_METADATA_KEY)).containsExactly("LBTOKEN0002");
PickSubchannelArgs args3 = mock(PickSubchannelArgs.class);
Metadata headers3 = new Metadata();
when(args3.getHeaders()).thenReturn(headers3);
assertSame(b1.result, picker.pickSubchannel(args3));
verify(args3).getHeaders();
assertThat(headers3.getAll(GrpclbConstants.TOKEN_METADATA_KEY)).containsExactly("LBTOKEN0001");
verify(subchannel, never()).getAttributes();
}
use of io.grpc.LoadBalancer.Subchannel in project grpc-java by grpc.
the class GrpclbLoadBalancerTest method switchMode.
@Test
public void switchMode() throws Exception {
InOrder inOrder = inOrder(helper);
List<EquivalentAddressGroup> grpclbBalancerList = createResolvedBalancerAddresses(1);
deliverResolvedAddresses(Collections.<EquivalentAddressGroup>emptyList(), grpclbBalancerList, GrpclbConfig.create(Mode.ROUND_ROBIN));
assertEquals(1, fakeOobChannels.size());
ManagedChannel oobChannel = fakeOobChannels.poll();
verify(mockLbService).balanceLoad(lbResponseObserverCaptor.capture());
StreamObserver<LoadBalanceResponse> lbResponseObserver = lbResponseObserverCaptor.getValue();
assertEquals(1, lbRequestObservers.size());
StreamObserver<LoadBalanceRequest> lbRequestObserver = lbRequestObservers.poll();
verify(lbRequestObserver).onNext(eq(LoadBalanceRequest.newBuilder().setInitialRequest(InitialLoadBalanceRequest.newBuilder().setName(SERVICE_AUTHORITY).build()).build()));
// Simulate receiving LB response
List<ServerEntry> backends1 = Arrays.asList(new ServerEntry("127.0.0.1", 2000, "token0001"), new ServerEntry("127.0.0.1", 2010, "token0002"));
inOrder.verify(helper, never()).updateBalancingState(any(ConnectivityState.class), any(SubchannelPicker.class));
lbResponseObserver.onNext(buildInitialResponse());
lbResponseObserver.onNext(buildLbResponse(backends1));
// ROUND_ROBIN: create one subchannel per server
verify(subchannelPool).takeOrCreateSubchannel(eq(new EquivalentAddressGroup(backends1.get(0).addr, LB_BACKEND_ATTRS)), any(Attributes.class));
verify(subchannelPool).takeOrCreateSubchannel(eq(new EquivalentAddressGroup(backends1.get(1).addr, LB_BACKEND_ATTRS)), any(Attributes.class));
inOrder.verify(helper).updateBalancingState(eq(CONNECTING), any(SubchannelPicker.class));
assertEquals(2, mockSubchannels.size());
Subchannel subchannel1 = mockSubchannels.poll();
Subchannel subchannel2 = mockSubchannels.poll();
verify(subchannelPool, never()).returnSubchannel(any(Subchannel.class), any(ConnectivityStateInfo.class));
// Switch to PICK_FIRST
deliverResolvedAddresses(Collections.<EquivalentAddressGroup>emptyList(), grpclbBalancerList, GrpclbConfig.create(Mode.PICK_FIRST));
// GrpclbState will be shutdown, and a new one will be created
assertThat(oobChannel.isShutdown()).isTrue();
verify(subchannelPool).returnSubchannel(same(subchannel1), eq(ConnectivityStateInfo.forNonError(IDLE)));
verify(subchannelPool).returnSubchannel(same(subchannel2), eq(ConnectivityStateInfo.forNonError(IDLE)));
// A new LB stream is created
assertEquals(1, fakeOobChannels.size());
verify(mockLbService, times(2)).balanceLoad(lbResponseObserverCaptor.capture());
lbResponseObserver = lbResponseObserverCaptor.getValue();
assertEquals(1, lbRequestObservers.size());
lbRequestObserver = lbRequestObservers.poll();
verify(lbRequestObserver).onNext(eq(LoadBalanceRequest.newBuilder().setInitialRequest(InitialLoadBalanceRequest.newBuilder().setName(SERVICE_AUTHORITY).build()).build()));
// Simulate receiving LB response
inOrder.verify(helper, never()).updateBalancingState(any(ConnectivityState.class), any(SubchannelPicker.class));
lbResponseObserver.onNext(buildInitialResponse());
lbResponseObserver.onNext(buildLbResponse(backends1));
// PICK_FIRST Subchannel
inOrder.verify(helper).createSubchannel(createSubchannelArgsCaptor.capture());
CreateSubchannelArgs createSubchannelArgs = createSubchannelArgsCaptor.getValue();
assertThat(createSubchannelArgs.getAddresses()).containsExactly(new EquivalentAddressGroup(backends1.get(0).addr, eagAttrsWithToken("token0001")), new EquivalentAddressGroup(backends1.get(1).addr, eagAttrsWithToken("token0002")));
inOrder.verify(helper).updateBalancingState(eq(IDLE), any(SubchannelPicker.class));
}
Aggregations