blob: 082b5d1b679b2592e00190e3e3deac876da33881 [file] [log] [blame]
// Copyright (C) 2023 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.ericsson.gerrit.plugins.highavailability.forwarder.jgroups;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import com.ericsson.gerrit.plugins.highavailability.Configuration;
import com.google.gerrit.server.events.EventGsonProvider;
import com.google.gerrit.server.git.WorkQueue;
import com.google.gson.Gson;
import java.time.Duration;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executors;
import org.jgroups.Address;
import org.jgroups.blocks.MessageDispatcher;
import org.jgroups.util.Rsp;
import org.jgroups.util.RspList;
import org.jgroups.util.UUID;
import org.junit.Before;
import org.junit.Test;
public class JGroupsForwarderTest {
private static final int MAX_TRIES = 3;
private static final int THREAD_POOLS_SIZE = 4;
private static final Address A1 = new UUID(1, 1);
private static final Address A2 = new UUID(2, 2);
private static final Rsp<Object> RSP_OK = new Rsp<>(true);
private static final Rsp<Object> RSP_FAIL = new Rsp<>(false);
private MessageDispatcher dispatcher;
private JGroupsForwarder forwarder;
@Before
public void setUp() throws Exception {
Gson eventGson = new EventGsonProvider().get();
Gson gson = new JGroupsForwarderModule().buildJGroupsGson(eventGson);
Configuration cfg = mock(Configuration.class, RETURNS_DEEP_STUBS);
when(cfg.jgroups().maxTries()).thenReturn(MAX_TRIES);
when(cfg.jgroups().retryInterval()).thenReturn(Duration.ofMillis(1));
when(cfg.jgroups().threadPoolSize()).thenReturn(THREAD_POOLS_SIZE);
dispatcher = mock(MessageDispatcher.class, RETURNS_DEEP_STUBS);
when(dispatcher.getChannel().getView().size()).thenReturn(2);
when(dispatcher.getChannel().getView().getMembers()).thenReturn(List.of(A1, A2));
WorkQueue workQueue = mock(WorkQueue.class);
when(workQueue.createQueue(THREAD_POOLS_SIZE, "JGroupsForwarder"))
.thenReturn(Executors.newScheduledThreadPool(THREAD_POOLS_SIZE));
forwarder =
new JGroupsForwarder(
dispatcher, cfg, gson, new FailsafeExecutorProvider(cfg, workQueue).get());
}
@Test
public void castMessageOK_returnsTrue() throws Exception {
RspList<Object> OK = new RspList<>(Map.of(A1, RSP_OK, A2, RSP_OK));
when(dispatcher.castMessage(any(), any(), any())).thenReturn(OK);
CompletableFuture<Boolean> result = forwarder.indexAccount(100, null);
assertThat(result.get()).isTrue();
verify(dispatcher, times(1)).castMessage(any(), any(), any());
}
@SuppressWarnings("unchecked")
@Test
public void castMessageRetriesWithSucess_returnsTrue() throws Exception {
RspList<Object> OK = new RspList<>(Map.of(A1, RSP_OK, A2, RSP_OK));
RspList<Object> FAIL = new RspList<>(Map.of(A1, RSP_OK, A2, RSP_FAIL));
when(dispatcher.castMessage(any(), any(), any())).thenReturn(FAIL, OK);
CompletableFuture<Boolean> result = forwarder.indexAccount(100, null);
assertThat(result.get()).isTrue();
verify(dispatcher, times(2)).castMessage(any(), any(), any());
}
@SuppressWarnings("unchecked")
@Test
public void castMessageFailsMaxTriesTimes_returnsFalse() throws Exception {
RspList<Object> FAIL = new RspList<>(Map.of(A1, RSP_FAIL, A2, RSP_FAIL));
// return FAIL x MAX_TRIES
when(dispatcher.castMessage(any(), any(), any())).thenReturn(FAIL, FAIL, FAIL);
CompletableFuture<Boolean> result = forwarder.indexAccount(100, null);
assertThat(result.get()).isFalse();
verify(dispatcher, times(MAX_TRIES)).castMessage(any(), any(), any());
}
}