Expanded CMTS emulator to accept at least one type of gate request. Future work will...
[packetcable.git] / packetcable-policy-server / src / test / java / org / opendaylight / controller / packetcable / provider / PCMMServiceTest.java
1 package org.opendaylight.controller.packetcable.provider;
2
3 import org.junit.After;
4 import org.junit.Assert;
5 import org.junit.Before;
6 import org.junit.Test;
7 import org.mockito.Mockito;
8 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
9 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
10 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
11 import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.ServiceClassName;
12 import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.ServiceFlowDirection;
13 import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.TosByte;
14 import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.TpProtocol;
15 import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.ccap.Ccaps;
16 import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.ccap.attributes.AmId;
17 import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.ccap.attributes.Connection;
18 import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.pcmm.qos.classifier.Classifier;
19 import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.pcmm.qos.gate.spec.GateSpec;
20 import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.pcmm.qos.gates.apps.subs.Gates;
21 import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.pcmm.qos.traffic.profile.TrafficProfile;
22 import org.pcmm.gates.IPCMMGate;
23 import org.pcmm.rcd.IPCMMClient;
24 import org.pcmm.rcd.impl.CMTS;
25 import org.umu.cops.stack.*;
26 import org.umu.cops.stack.COPSContext.RType;
27 import org.umu.cops.stack.COPSDecision.Command;
28 import org.umu.cops.stack.COPSDecision.DecisionFlag;
29 import org.umu.cops.stack.COPSObjHeader.CNum;
30 import org.umu.cops.stack.COPSObjHeader.CType;
31
32 import java.io.ByteArrayInputStream;
33 import java.io.ByteArrayOutputStream;
34 import java.io.InputStream;
35 import java.io.OutputStream;
36 import java.net.InetAddress;
37 import java.net.Socket;
38 import java.util.HashMap;
39 import java.util.HashSet;
40 import java.util.Map;
41 import java.util.Set;
42
43 /**
44  * Tests the PCMMService's ability to connect to a CMTS. Gate additions will not properly work as there is currently
45  * not any other means to receive acknowledgements. This functionality must be tested by the PCMMService's client
46  * PacketcableProvider.
47  */
48 public class PCMMServiceTest {
49
50     /**
51      * The mock CMTS running on localhost with a dynamic port assigned.
52      */
53     private CMTS icmts;
54
55     /**
56      * Represents the IP address of the CM the gate should be set against.
57      */
58     private byte[] cmAddr = new byte[4];
59
60     @Before
61     public void setup() {
62         icmts = new CMTS();
63         icmts.startServer();
64
65         cmAddr[0] = 10;
66         cmAddr[1] = 32;
67         cmAddr[2] = 110;
68         cmAddr[3] = (byte)180;
69     }
70
71     @After
72     public void tearDown() {
73         if (icmts != null) icmts.stopServer();
74     }
75
76     @Test
77     public void testAddCcap() {
78
79         // TODO - comment out for testing
80         //        final Ipv4Address cmtsAddr = new Ipv4Address("10.32.10.3");
81 //        final Ccaps ccap = makeCcapsObj(PCMMPdpAgent.WELL_KNOWN_PDP_PORT, cmtsAddr.getValue(), "ccap-1");
82
83         // TODO - Use this instead for automated testing
84         final Ipv4Address cmtsAddr = new Ipv4Address("127.0.0.1");
85         final Ccaps ccap = makeCcapsObj(icmts.getPort(), cmtsAddr.getValue(), "ccap-1");
86
87         final PCMMService service = new PCMMService(IPCMMClient.CLIENT_TYPE, ccap);
88         final String message = service.addCcap();
89         Assert.assertNotNull(message);
90         Assert.assertTrue(message, message.startsWith("200"));
91         Assert.assertNotNull(service.ccapClient.pcmmPdp.getClientHandle());
92         service.disconect();
93     }
94
95     @Test
96     public void testAddAndRemoveUpGate() throws Exception {
97
98         // TODO - Use this block to test against a real CMTS
99 //        final Ipv4Address cmtsAddr = new Ipv4Address("10.32.10.3");
100 //        final Ccaps ccap = makeCcapsObj(PCMMPdpAgent.WELL_KNOWN_PDP_PORT, cmtsAddr.getValue(), "ccap-1");
101
102         // TODO - Use this block for automated testing
103         final Ipv4Address cmtsAddr = new Ipv4Address("127.0.0.1");
104         final Ccaps ccap = makeCcapsObj(icmts.getPort(), cmtsAddr.getValue(), "ccap-1");
105
106         final PCMMService service = new PCMMService(IPCMMClient.CLIENT_TYPE, ccap);
107         service.addCcap();
108
109         final Gates gate = makeGateObj("extrm_up", cmtsAddr, ServiceFlowDirection.Us);
110         final String gatePath = "testGatePath";
111
112         // Add gate
113         final String msg = service.sendGateSet(gatePath, InetAddress.getByAddress(cmAddr), gate,
114                 ServiceFlowDirection.Us);
115         Assert.assertTrue(msg, msg.startsWith("200"));
116
117         // TODO - add validation to the PCMMGateReq contained within the map
118         Assert.assertEquals(1, service.gateRequests.size());
119
120         // Remove gate
121         service.sendGateDelete(gatePath);
122
123         // Wait up to 1 sec for response to be processed
124         final long start = System.currentTimeMillis();
125         while (1000 < System.currentTimeMillis() - start) {
126             if (service.gateRequests.size() == 0) break;
127         }
128         Assert.assertEquals(0, service.gateRequests.size());
129         service.disconect();
130     }
131
132     /**
133      * This tests the instantiation of a COPSDecisionMsg object that is responsible for setting a gate request,
134      * streams it over a mock Socket object and parses the bytes into a new COPSDecisionMsg object which should
135      * be equivalent
136      * @throws Exception - test will fail should any exception be thrown during execution
137      */
138     @Test
139     public void testGateRequestDecisionMsg() throws Exception {
140         final Socket socket = new MockSocket();
141         final Ccaps ccap = makeCcapsObj(icmts.getPort(), "127.0.0.1", "ccap-1");
142         final Ipv4Address cmtsAddr = new Ipv4Address("127.0.0.1");
143         final Gates gate = makeGateObj("extrm_up", cmtsAddr, ServiceFlowDirection.Us);
144         final IPCMMGate gateReq = makeGateRequest(ccap, gate, InetAddress.getByName("localhost"),
145                 ServiceFlowDirection.Us);
146         final byte[] data = gateReq.getData();
147
148         final Set<COPSDecision> decisionSet = new HashSet<>();
149         decisionSet.add(new COPSDecision(CType.DEF, Command.INSTALL, DecisionFlag.REQERROR));
150         final Map<COPSContext, Set<COPSDecision>> decisionMap = new HashMap<>();
151         decisionMap.put(new COPSContext(RType.CONFIG, (short) 0), decisionSet);
152
153         final COPSClientSI clientSD = new COPSClientSI(CNum.DEC, CType.CSI, new COPSData(data, 0, data.length));
154         final COPSDecisionMsg decisionMsg = new COPSDecisionMsg(IPCMMClient.CLIENT_TYPE, new COPSHandle(new COPSData("123")),
155                 decisionMap, null, clientSD);
156         decisionMsg.writeData(socket);
157
158         final COPSMsg msg = COPSMsgParser.parseMessage(socket);
159         Assert.assertNotNull(msg);
160         Assert.assertEquals(decisionMsg, msg);
161     }
162
163     /**
164      * Creates a mock Ccaps object that can be used for connecting to a CMTS
165      * @param inPort - the CMTS port number
166      * @param ipAddr - the CMTS IPv4 address string
167      * @param ccapId - the ID of the CCAP
168      * @return - the mock Ccaps object
169      */
170     private Ccaps makeCcapsObj(final int inPort, final String ipAddr, final String ccapId) {
171         final Ccaps ccap = Mockito.mock(Ccaps.class);
172         final Connection conn = Mockito.mock(Connection.class);
173         Mockito.when(ccap.getConnection()).thenReturn(conn);
174         final PortNumber port = Mockito.mock(PortNumber.class);
175         Mockito.when(conn.getPort()).thenReturn(port);
176         Mockito.when(port.getValue()).thenReturn(inPort);
177
178         final IpAddress addr = Mockito.mock(IpAddress.class);
179         Mockito.when(conn.getIpAddress()).thenReturn(addr);
180         final Ipv4Address ipv4 = new Ipv4Address(ipAddr);
181         Mockito.when(addr.getIpv4Address()).thenReturn(ipv4);
182
183         Mockito.when(ccap.getCcapId()).thenReturn(ccapId);
184         final AmId amid = Mockito.mock(AmId.class);
185         Mockito.when(ccap.getAmId()).thenReturn(amid);
186         Mockito.when(amid.getAmTag()).thenReturn(0xcada);
187         Mockito.when(amid.getAmType()).thenReturn(1);
188
189         return ccap;
190     }
191
192     /**
193      * Creates a mock Gates object
194      * @param scnValue - the service class name defined on the CMTS
195      * @param dstAddr - the CM address this gate should be set against
196      * @return - the gate request
197      */
198     private Gates makeGateObj(final String scnValue, final Ipv4Address dstAddr, final ServiceFlowDirection direction) {
199         final Gates gate = Mockito.mock(Gates.class);
200         final GateSpec gateSpec = Mockito.mock(GateSpec.class);
201         Mockito.when(gate.getGateSpec()).thenReturn(gateSpec);
202         Mockito.when(gateSpec.getDirection()).thenReturn(direction);
203         // TODO - make sure to write a test when this value is not null
204         Mockito.when(gateSpec.getDscpTosOverwrite()).thenReturn(null);
205         final TrafficProfile trafficProfile = Mockito.mock(TrafficProfile.class);
206         final ServiceClassName scn = Mockito.mock(ServiceClassName.class);
207         Mockito.when(scn.getValue()).thenReturn(scnValue);
208         Mockito.when(trafficProfile.getServiceClassName()).thenReturn(scn);
209         Mockito.when(gate.getTrafficProfile()).thenReturn(trafficProfile);
210
211         // TODO - write tests when this is null and ExtClassifier or Ipv6Classifier objects are not null
212         final Classifier classifier = Mockito.mock(Classifier.class);
213
214         // This is the address of the CM
215         Mockito.when(classifier.getDstIp()).thenReturn(dstAddr);
216
217         final PortNumber dstPort = new PortNumber(4321);
218         Mockito.when(classifier.getDstPort()).thenReturn(dstPort);
219         final TpProtocol protocol = new TpProtocol(0);
220         Mockito.when(classifier.getProtocol()).thenReturn(protocol);
221         final Ipv4Address srcAddr = new Ipv4Address("127.0.0.1");
222         Mockito.when(classifier.getSrcIp()).thenReturn(srcAddr);
223         final PortNumber srcPort = new PortNumber(1234);
224         Mockito.when(classifier.getSrcPort()).thenReturn(srcPort);
225         final TosByte tosByte = new TosByte((short)160);
226         Mockito.when(classifier.getTosByte()).thenReturn(tosByte);
227         final TosByte tosMask = new TosByte((short)224);
228         Mockito.when(classifier.getTosMask()).thenReturn(tosMask);
229
230         // TODO - enhance to test support of the other classifier types
231         Mockito.when(gate.getClassifier()).thenReturn(classifier);
232         Mockito.when(gate.getExtClassifier()).thenReturn(null);
233         Mockito.when(gate.getIpv6Classifier()).thenReturn(null);
234         return gate;
235     }
236
237     private IPCMMGate makeGateRequest(final Ccaps ccap, final Gates gateReq, final InetAddress addrSubId,
238                                      final ServiceFlowDirection direction) {
239         final PCMMGateReqBuilder gateBuilder = new PCMMGateReqBuilder();
240         gateBuilder.build(ccap.getAmId());
241         gateBuilder.build(addrSubId);
242         // force gateSpec.Direction to align with SCN direction
243         final ServiceClassName scn = gateReq.getTrafficProfile().getServiceClassName();
244         if (scn != null) {
245             gateBuilder.build(gateReq.getGateSpec(), direction);
246         } else {
247             // not an SCN gate
248             gateBuilder.build(gateReq.getGateSpec(), null);
249         }
250         gateBuilder.build(gateReq.getTrafficProfile());
251
252         // pick a classifier type (only one for now)
253         if (gateReq.getClassifier() != null) {
254             gateBuilder.build(gateReq.getClassifier());
255         } else if (gateReq.getExtClassifier() != null) {
256             gateBuilder.build(gateReq.getExtClassifier());
257         } else if (gateReq.getIpv6Classifier() != null) {
258             gateBuilder.build(gateReq.getIpv6Classifier());
259         }
260         // assemble the final gate request
261         return gateBuilder.getGateReq();
262     }
263
264     private class MockSocket extends Socket {
265
266         private ByteArrayOutputStream os = new ByteArrayOutputStream();
267         private ByteArrayInputStream is;
268
269         @Override
270         public OutputStream getOutputStream() {
271             return os;
272         }
273
274         @Override
275         public InputStream getInputStream() {
276             if (is == null) is = new ByteArrayInputStream(os.toByteArray());
277             return is;
278         }
279     }
280
281 }