blob: 95cb3bc1f9f8f23a4d00d7da426dc263f5c4e6bd [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.ignite.raft.jraft.rpc.impl.cli;
import org.apache.ignite.raft.jraft.RaftMessagesFactory;
import org.apache.ignite.raft.jraft.JRaftUtils;
import org.apache.ignite.raft.jraft.Node;
import org.apache.ignite.raft.jraft.Status;
import org.apache.ignite.raft.jraft.entity.NodeId;
import org.apache.ignite.raft.jraft.entity.PeerId;
import org.apache.ignite.raft.jraft.error.RaftError;
import org.apache.ignite.raft.jraft.option.NodeOptions;
import org.apache.ignite.raft.jraft.rpc.Message;
import org.apache.ignite.raft.jraft.rpc.RaftRpcFactory;
import org.apache.ignite.raft.jraft.rpc.RpcRequests.ErrorResponse;
import org.apache.ignite.raft.jraft.rpc.RpcRequests.PingRequest;
import org.apache.ignite.raft.jraft.test.MockAsyncContext;
import org.apache.ignite.raft.jraft.test.TestUtils;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertSame;
@ExtendWith(MockitoExtension.class)
public class BaseCliRequestProcessorTest {
private static class MockCliRequestProcessor extends BaseCliRequestProcessor<PingRequest> {
private String peerId;
private String groupId;
private IgniteCliRpcRequestClosure done;
private CliRequestContext ctx;
MockCliRequestProcessor(String peerId, String groupId) {
super(null, new RaftMessagesFactory());
this.peerId = peerId;
this.groupId = groupId;
}
@Override
protected String getPeerId(PingRequest request) {
return this.peerId;
}
@Override
protected String getGroupId(PingRequest request) {
return this.groupId;
}
@Override
protected Message processRequest0(CliRequestContext ctx, PingRequest request, IgniteCliRpcRequestClosure done) {
this.ctx = ctx;
this.done = done;
return RaftRpcFactory.DEFAULT.newResponse(msgFactory(), Status.OK());
}
@Override
public String interest() {
return PingRequest.class.getName();
}
}
private MockCliRequestProcessor processor;
private PeerId peer;
private MockAsyncContext asyncContext;
@BeforeEach
public void setup() {
this.asyncContext = new MockAsyncContext();
this.peer = JRaftUtils.getPeerId("localhost:8081");
this.processor = new MockCliRequestProcessor(this.peer.toString(), "test");
}
@AfterEach
public void teardown() {
// No-op.
}
@Test
public void testOK() {
Node node = mockNode(false);
this.processor.handleRequest(asyncContext, TestUtils.createPingRequest());
ErrorResponse resp = (ErrorResponse) asyncContext.getResponseObject();
assertNotNull(this.processor.done);
assertSame(this.processor.ctx.node, node);
assertNotNull(resp);
assertEquals(0, resp.errorCode());
}
@Test
public void testDisableCli() {
mockNode(true);
this.processor.handleRequest(asyncContext, TestUtils.createPingRequest());
ErrorResponse resp = (ErrorResponse) asyncContext.getResponseObject();
assertNotNull(resp);
assertEquals(RaftError.EACCES.getNumber(), resp.errorCode());
assertEquals("Cli service is not allowed to access node <test/localhost:8081>", resp.errorMsg());
}
private Node mockNode(boolean disableCli) {
Node node = Mockito.mock(Node.class);
Mockito.when(node.getGroupId()).thenReturn("test");
Mockito.when(node.getNodeId()).thenReturn(new NodeId("test", this.peer.copy()));
NodeOptions opts = new NodeOptions();
opts.setDisableCli(disableCli);
Mockito.when(node.getOptions()).thenReturn(opts);
this.asyncContext.getNodeManager().add(node);
return node;
}
@Test
public void testInvalidPeerId() {
this.processor = new MockCliRequestProcessor("localhost", "test");
this.processor.handleRequest(asyncContext, TestUtils.createPingRequest());
ErrorResponse resp = (ErrorResponse) asyncContext.getResponseObject();
assertNotNull(resp);
assertEquals(RaftError.EINVAL.getNumber(), resp.errorCode());
assertEquals("Fail to parse peer: localhost", resp.errorMsg());
}
@Test
public void testEmptyNodes() {
this.processor = new MockCliRequestProcessor(null, "test");
this.processor.handleRequest(asyncContext, TestUtils.createPingRequest());
ErrorResponse resp = (ErrorResponse) asyncContext.getResponseObject();
assertNotNull(resp);
assertEquals(RaftError.ENOENT.getNumber(), resp.errorCode());
assertEquals("Empty nodes in group test", resp.errorMsg());
}
@Test
public void testManyNodes() {
Node node1 = Mockito.mock(Node.class);
Mockito.when(node1.getGroupId()).thenReturn("test");
Mockito.when(node1.getNodeId()).thenReturn(new NodeId("test", new PeerId("localhost", 8081)));
this.asyncContext.getNodeManager().add(node1);
Node node2 = Mockito.mock(Node.class);
Mockito.when(node2.getGroupId()).thenReturn("test");
Mockito.when(node2.getNodeId()).thenReturn(new NodeId("test", new PeerId("localhost", 8082)));
this.asyncContext.getNodeManager().add(node2);
this.processor = new MockCliRequestProcessor(null, "test");
this.processor.handleRequest(asyncContext, TestUtils.createPingRequest());
ErrorResponse resp = (ErrorResponse) asyncContext.getResponseObject();
assertNotNull(resp);
assertEquals(RaftError.EINVAL.getNumber(), resp.errorCode());
assertEquals("Peer must be specified since there're 2 nodes in group test", resp.errorMsg());
}
@Test
public void testSingleNode() {
Node node = this.mockNode(false);
this.processor = new MockCliRequestProcessor(null, "test");
this.processor.handleRequest(asyncContext, TestUtils.createPingRequest());
ErrorResponse resp = (ErrorResponse) asyncContext.getResponseObject();
assertNotNull(resp);
assertSame(this.processor.ctx.node, node);
assertNotNull(resp);
assertEquals(0, resp.errorCode());
}
@Test
public void testPeerIdNotFound() {
this.processor.handleRequest(asyncContext, TestUtils.createPingRequest());
ErrorResponse resp = (ErrorResponse) asyncContext.getResponseObject();
assertNotNull(resp);
assertEquals(RaftError.ENOENT.getNumber(), resp.errorCode());
assertEquals("Fail to find node localhost:8081 in group test", resp.errorMsg());
}
}