blob: ccfbf91ea9eaf7e631e1f4583dbaa1c197b0bfb9 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more contributor license
* agreements. See the NOTICE file distributed with this work for additional information regarding
* copyright ownership. The ASF licenses this file to You 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 org.apache.geode.management.internal.cli.commands;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Properties;
import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.apache.geode.distributed.DistributedMember;
import org.apache.geode.management.internal.cli.domain.AsyncEventQueueDetails;
import org.apache.geode.management.internal.functions.CliFunctionResult;
import org.apache.geode.management.internal.i18n.CliStrings;
import org.apache.geode.test.junit.categories.AEQTest;
import org.apache.geode.test.junit.rules.GfshParserRule;
@Category({AEQTest.class})
public class ListAsyncEventQueuesTest {
private static final String COMMAND = "list async-event-queues ";
@ClassRule
public static GfshParserRule gfsh = new GfshParserRule();
private static final String FUNCTION_EXCEPTION_MESSAGE =
"A mysterious test exception occurred during function execution.";
private ListAsyncEventQueuesCommand command;
private List<CliFunctionResult> memberCliResults;
private DistributedMember mockedMember;
private DistributedMember anotherMockedMember;
@Before
public void before() {
mockedMember = mock(DistributedMember.class);
anotherMockedMember = mock(DistributedMember.class);
command = spy(ListAsyncEventQueuesCommand.class);
}
@Test
public void noMembersFound() {
// Mock zero members
doReturn(Collections.emptySet()).when(command).getAllNormalMembers();
// Command should succeed with one row of data
gfsh.executeAndAssertThat(command, COMMAND).statusIsSuccess()
.containsOutput(CliStrings.NO_MEMBERS_FOUND_MESSAGE);
}
@Test
@SuppressWarnings("deprecation")
public void oneServerWithOneQueue() {
// Mock one member
doReturn(new HashSet<>(Collections.singletonList(mockedMember))).when(command)
.getAllNormalMembers();
// Mock member's queue details
FakeDetails details = new FakeDetails("server1", "s1-queue-id", 5, true, "diskStoreName", 10,
"my.listener.class", new Properties(), false, false);
CliFunctionResult memberResult = new CliFunctionResult(details.getMemberName(),
Collections.singletonList(details.asAsyncEventQueueDetails()));
memberCliResults = Collections.singletonList(memberResult);
doReturn(memberCliResults).when(command).executeAndGetFunctionResult(any(), any(), any());
// Command should succeed with one row of data
gfsh.executeAndAssertThat(command, COMMAND).statusIsSuccess()
.tableHasRowWithValues(details.expectedRowHeaderAndValue());
}
@Test
@SuppressWarnings("deprecation")
public void oneServerWithOneParameterizedQueue() {
// Mock one member
doReturn(new HashSet<>(Collections.singletonList(mockedMember))).when(command)
.getAllNormalMembers();
// Mock member's queue details
Properties listenerProperties = new Properties();
listenerProperties.setProperty("special-property", "special-value");
listenerProperties.setProperty("another-property", "mundane-value");
FakeDetails details = new FakeDetails("server1", "s1-queue-id", 5, true, "diskStoreName", 10,
"my.listener.class", listenerProperties, false, false);
CliFunctionResult memberResult = new CliFunctionResult(details.getMemberName(),
Collections.singletonList(details.asAsyncEventQueueDetails()));
memberCliResults = Collections.singletonList(memberResult);
doReturn(memberCliResults).when(command).executeAndGetFunctionResult(any(), any(), any());
// Command should succeed with one row of data
gfsh.executeAndAssertThat(command, COMMAND).statusIsSuccess()
.tableHasRowWithValues(details.expectedRowHeaderAndValue());
}
@Test
public void oneMemberButNoQueues() {
// Mock one member
doReturn(new HashSet<>(Collections.singletonList(mockedMember))).when(command)
.getAllNormalMembers();
// Mock member's lack of queue details
CliFunctionResult memberResult = new CliFunctionResult("server1", Collections.emptyList());
memberCliResults = Collections.singletonList(memberResult);
doReturn(memberCliResults).when(command).executeAndGetFunctionResult(any(), any(), any());
// Command should succeed, but indicate there were no queues
gfsh.executeAndAssertThat(command, COMMAND).statusIsSuccess()
.containsOutput(CliStrings.LIST_ASYNC_EVENT_QUEUES__NO_QUEUES_FOUND_MESSAGE);
}
@Test
public void oneMemberWhoErrorsOut() {
// Mock one member
doReturn(new HashSet<>(Collections.singletonList(mockedMember))).when(command)
.getAllNormalMembers();
// Mock member's error result
CliFunctionResult memberResult =
new CliFunctionResult("server1", new Exception(FUNCTION_EXCEPTION_MESSAGE));
memberCliResults = Collections.singletonList(memberResult);
doReturn(memberCliResults).when(command).executeAndGetFunctionResult(any(), any(), any());
// Command should succeed, but indicate there were no queues
gfsh.executeAndAssertThat(command, COMMAND).statusIsSuccess()
.containsOutput(CliStrings.LIST_ASYNC_EVENT_QUEUES__NO_QUEUES_FOUND_MESSAGE);
}
@Test
@SuppressWarnings("deprecation")
public void twoServersWithManyQueues() {
// Mock two members, even though they're not directly consumed
doReturn(new HashSet<>(Arrays.asList(mockedMember, anotherMockedMember))).when(command)
.getAllNormalMembers();
// Mock member's queue details
FakeDetails details1 = new FakeDetails("server1", "s1-queue-id1", 5, false, "diskStoreName", 1,
"my.listener.class", new Properties(), false, false);
FakeDetails details2 = new FakeDetails("server1", "s1-queue-id2", 15, true,
"otherDiskStoreName", 10, "my.listener.class", new Properties(), false, false);
FakeDetails details3 = new FakeDetails("server1", "s1-queue-id3", 25, true, "diskStoreName",
100, "my.listener.class", new Properties(), true, true);
CliFunctionResult member1Result =
new CliFunctionResult("server1", Arrays.asList(details1.asAsyncEventQueueDetails(),
details2.asAsyncEventQueueDetails(), details3.asAsyncEventQueueDetails()));
FakeDetails details4 = new FakeDetails("server2", "s2-queue-id1", 5, false, "diskStoreName", 1,
"my.listener.class", new Properties(), false, false);
FakeDetails details5 = new FakeDetails("server2", "s2-queue-id2", 15, true,
"otherDiskStoreName", 10, "my.listener.class", new Properties(), false, false);
FakeDetails details6 = new FakeDetails("server2", "s2-queue-id3", 25, true, "diskStoreName",
100, "my.listener.class", new Properties(), false, false);
CliFunctionResult member2Result =
new CliFunctionResult("server2", Arrays.asList(details4.asAsyncEventQueueDetails(),
details5.asAsyncEventQueueDetails(), details6.asAsyncEventQueueDetails()));
memberCliResults = Arrays.asList(member1Result, member2Result);
doReturn(memberCliResults).when(command).executeAndGetFunctionResult(any(), any(), any());
// Command should succeed with one row of data
gfsh.executeAndAssertThat(command, COMMAND).statusIsSuccess()
.tableHasRowWithValues(details1.expectedRowHeaderAndValue())
.tableHasRowWithValues(details2.expectedRowHeaderAndValue())
.tableHasRowWithValues(details3.expectedRowHeaderAndValue())
.tableHasRowWithValues(details4.expectedRowHeaderAndValue())
.tableHasRowWithValues(details5.expectedRowHeaderAndValue())
.tableHasRowWithValues(details6.expectedRowHeaderAndValue());
}
@Test
@SuppressWarnings("deprecation")
public void oneMemberSucceedsAndOneFails() {
// Mock two members, even though they're not directly consumed
doReturn(new HashSet<>(Arrays.asList(mockedMember, anotherMockedMember))).when(command)
.getAllNormalMembers();
// Mock member's queue details
FakeDetails details1 = new FakeDetails("server1", "s1-queue-id1", 5, false, "diskStoreName", 1,
"my.listener.class", new Properties(), false, false);
FakeDetails details2 = new FakeDetails("server1", "s1-queue-id2", 15, true,
"otherDiskStoreName", 10, "my.listener.class", new Properties(), false, false);
FakeDetails details3 = new FakeDetails("server1", "s1-queue-id3", 25, true, "diskStoreName",
100, "my.listener.class", new Properties(), false, false);
CliFunctionResult member1Result =
new CliFunctionResult("server1", Arrays.asList(details1.asAsyncEventQueueDetails(),
details2.asAsyncEventQueueDetails(), details3.asAsyncEventQueueDetails()));
// Mock the other's failure
CliFunctionResult member2Result =
new CliFunctionResult("server2", new Exception(FUNCTION_EXCEPTION_MESSAGE));
memberCliResults = Arrays.asList(member1Result, member2Result);
doReturn(memberCliResults).when(command).executeAndGetFunctionResult(any(), any(), any());
// Command should succeed with one row of data
gfsh.executeAndAssertThat(command, COMMAND).statusIsSuccess()
.tableHasRowWithValues(details1.expectedRowHeaderAndValue())
.tableHasRowWithValues(details2.expectedRowHeaderAndValue())
.tableHasRowWithValues(details3.expectedRowHeaderAndValue())
.containsOutput(FUNCTION_EXCEPTION_MESSAGE);
}
/**
* Wrapper for mocked AsyncEventQueueData, with convenience method for expected table output.
*/
static class FakeDetails {
private String memberName;
private String queueId;
private int batchSize;
private boolean persistent;
private String diskStoreName;
private int maxQueueMemory;
private String listener;
private Properties listenerProperties;
private boolean createWithPausedEventProcessing;
private boolean pausedEventProcessing;
private FakeDetails(String memberName, String queueId, int batchSize, boolean persistent,
String diskStoreName, int maxQueueMemory, String listener, Properties listenerProperties,
boolean createWithPausedEventProcessing, boolean pausedEventProcessing) {
this.memberName = memberName;
this.queueId = queueId;
this.batchSize = batchSize;
this.persistent = persistent;
this.diskStoreName = diskStoreName;
this.maxQueueMemory = maxQueueMemory;
this.listener = listener;
this.listenerProperties = listenerProperties;
this.createWithPausedEventProcessing = createWithPausedEventProcessing;
this.pausedEventProcessing = pausedEventProcessing;
}
public String getMemberName() {
return memberName;
}
private AsyncEventQueueDetails asAsyncEventQueueDetails() {
return new AsyncEventQueueDetails(queueId, batchSize, persistent, diskStoreName,
maxQueueMemory, listener, listenerProperties, createWithPausedEventProcessing,
pausedEventProcessing);
}
private String[] expectedRowHeaderAndValue() {
return new String[] {"Member", "ID", "Batch Size", "Persistent", "Disk Store", "Max Memory",
"Listener", "Created with paused event processing", "Currently Paused", memberName,
queueId, String.valueOf(batchSize),
String.valueOf(persistent),
diskStoreName, String.valueOf(maxQueueMemory), expectedListenerOutput(),
String.valueOf(createWithPausedEventProcessing), String.valueOf(pausedEventProcessing)};
}
private String expectedListenerOutput() {
return listener + ListAsyncEventQueuesCommand.propertiesToString(listenerProperties);
}
}
}