b34d758cc5d7aa04f1fa681034626bc1ce5e850c
[packetcable.git] / packetcable-policy-server / src / test / java / org / opendaylight / controller / packetcable / provider / PCMMServiceTest.java
1 /*
2  * (c) 2015 Cable Television Laboratories, Inc.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8
9 package org.opendaylight.controller.packetcable.provider;
10
11 import static junit.framework.TestCase.assertEquals;
12
13 import static org.hamcrest.CoreMatchers.startsWith;
14 import static org.hamcrest.MatcherAssert.assertThat;
15 import static org.mockito.Mockito.mock;
16 import static org.mockito.Mockito.when;
17
18 import java.io.ByteArrayInputStream;
19 import java.io.ByteArrayOutputStream;
20 import java.io.IOException;
21 import java.io.InputStream;
22 import java.io.OutputStream;
23 import java.net.InetAddress;
24 import java.net.Socket;
25 import java.util.Collections;
26 import java.util.HashMap;
27 import java.util.HashSet;
28 import java.util.List;
29 import java.util.Map;
30 import java.util.Set;
31 import org.junit.After;
32 import org.junit.Assert;
33 import org.junit.Before;
34 import org.junit.Test;
35 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
36 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
37 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber;
38 import org.opendaylight.yang.gen.v1.urn.packetcable.rev161219.ServiceClassName;
39 import org.opendaylight.yang.gen.v1.urn.packetcable.rev161219.ServiceFlowDirection;
40 import org.opendaylight.yang.gen.v1.urn.packetcable.rev161219.TosByte;
41 import org.opendaylight.yang.gen.v1.urn.packetcable.rev161219.TpProtocol;
42 import org.opendaylight.yang.gen.v1.urn.packetcable.rev161219.ccap.attributes.AmId;
43 import org.opendaylight.yang.gen.v1.urn.packetcable.rev161219.ccap.attributes.Connection;
44 import org.opendaylight.yang.gen.v1.urn.packetcable.rev161219.ccaps.Ccap;
45 import org.opendaylight.yang.gen.v1.urn.packetcable.rev161219.classifier.attributes.Classifiers;
46 import org.opendaylight.yang.gen.v1.urn.packetcable.rev161219.classifier.attributes.classifiers.ClassifierContainer;
47 import org.opendaylight.yang.gen.v1.urn.packetcable.rev161219.classifier.attributes.classifiers.classifier.container.classifier.choice.QosClassifierChoice;
48 import org.opendaylight.yang.gen.v1.urn.packetcable.rev161219.pcmm.qos.classifier.Classifier;
49 import org.opendaylight.yang.gen.v1.urn.packetcable.rev161219.pcmm.qos.gate.spec.GateSpec;
50 import org.opendaylight.yang.gen.v1.urn.packetcable.rev161219.pcmm.qos.gates.apps.app.subscribers.subscriber.gates.Gate;
51 import org.opendaylight.yang.gen.v1.urn.packetcable.rev161219.pcmm.flow.spec.profile.FlowSpecProfile;
52 import org.opendaylight.yang.gen.v1.urn.packetcable.rev161219.pcmm.qos.traffic.profile.TrafficProfile;
53 import org.opendaylight.yang.gen.v1.urn.packetcable.rev161219.pcmm.qos.traffic.profile.TrafficProfileBuilder;
54 import org.opendaylight.yang.gen.v1.urn.packetcable.rev161219.pcmm.qos.traffic.profile.traffic.profile.TrafficProfileChoice;
55 import org.opendaylight.yang.gen.v1.urn.packetcable.rev161219.pcmm.qos.traffic.profile.traffic.profile.traffic.profile.choice.FlowSpecChoice;
56 import org.opendaylight.yang.gen.v1.urn.packetcable.rev161219.pcmm.qos.traffic.profile.traffic.profile.traffic.profile.choice.FlowSpecChoiceBuilder;
57 import org.opendaylight.yang.gen.v1.urn.packetcable.rev161219.pcmm.qos.traffic.profile.traffic.profile.traffic.profile.choice.ServiceClassNameChoice;
58 import org.opendaylight.yang.gen.v1.urn.packetcable.rev161219.pcmm.qos.traffic.profile.traffic.profile.traffic.profile.choice.ServiceClassNameChoiceBuilder;
59 import org.opendaylight.yang.gen.v1.urn.packetcable.rev161219.pcmm.serviceclass.name.profile.ServiceClassNameProfile;
60 import org.pcmm.PCMMPdpAgent;
61 import org.pcmm.gates.IPCMMGate;
62 import org.pcmm.rcd.IPCMMClient;
63 import org.pcmm.rcd.impl.CMTS;
64 import org.pcmm.rcd.impl.CMTSConfig;
65 import org.umu.cops.stack.COPSClientSI;
66 import org.umu.cops.stack.COPSContext;
67 import org.umu.cops.stack.COPSContext.RType;
68 import org.umu.cops.stack.COPSData;
69 import org.umu.cops.stack.COPSDecision;
70 import org.umu.cops.stack.COPSDecision.Command;
71 import org.umu.cops.stack.COPSDecision.DecisionFlag;
72 import org.umu.cops.stack.COPSDecisionMsg;
73 import org.umu.cops.stack.COPSHandle;
74 import org.umu.cops.stack.COPSMsg;
75 import org.umu.cops.stack.COPSMsgParser;
76 import org.umu.cops.stack.COPSObjHeader.CNum;
77 import org.umu.cops.stack.COPSObjHeader.CType;
78
79 /**
80  * Tests the PCMMService's ability to connect to a CMTS. Gate additions will not properly work as there is currently
81  * not any other means to receive acknowledgements. This functionality must be tested by the PCMMService's client
82  * PacketcableProvider.
83  */
84 public class PCMMServiceTest {
85
86     private static final String ccapId = "ccap-1";
87     private static final String gatePath = "testGatePath";
88
89     /**
90      * Denotes whether or not a real CMTS is being tested against.
91      * Ensure the checked-in value is always false else tests will most likely fail.
92      */
93     private static final boolean realCmts = false;
94
95
96     // The test objects/values to use that will be instantiated in @Before
97
98     /**
99      * The mock CMTS running on localhost with a dynamic port assigned.
100      */
101     private CMTS icmts;
102
103     /**
104      * The IP address object for the CMTS to test against
105      */
106     private Ipv4Address cmtsAddr;
107
108     /**
109      * The gate classifier's srcIp value, any valid IP should work.
110      */
111     private Ipv4Address srcAddr;
112
113     /**
114      * The gate classifier's dstIp value, any valid IP should work.
115      */
116     private Ipv4Address dstAddr;
117
118     /**
119      * Defines the CMTS to add to the PCMMService
120      */
121     private Ccap ccap;
122
123     /**
124      * The class under test
125      */
126     private PCMMService service;
127
128     /**
129      * The cable modem IP address to which a gate should be set
130      */
131     private InetAddress cmAddrInet;
132     private InetAddress invalidCmAddrInet;
133
134     @Before
135     public void setup() throws IOException {
136         srcAddr = new Ipv4Address("10.10.10.0");
137         dstAddr = new Ipv4Address("10.32.99.99");
138         invalidCmAddrInet = InetAddress.getByAddress(new byte[] {99, 99, 99, 99});
139
140         if (realCmts) {
141             cmAddrInet = InetAddress.getByAddress(new byte[] {10, 32, 110, (byte)172});
142
143
144             // Use me when testing against a CMTS or emulator not running in the same JVM
145             cmtsAddr = new Ipv4Address("10.32.10.3");
146             ccap = makeCcapObj(PCMMPdpAgent.WELL_KNOWN_PDP_PORT, cmtsAddr, ccapId);
147         } else {
148             cmAddrInet = InetAddress.getByAddress(new byte[] {10, 32, 110, (byte)180});
149
150             // Use me for automated testing and the CMTS emulator running in the same JVM
151             cmtsAddr = new Ipv4Address("127.0.0.1");
152
153             final Set<String> upSCN = new HashSet<>();
154             upSCN.add("extrm_up");
155             final Set<String> dnSCN = new HashSet<>();
156             dnSCN.add("extrm_dn");
157
158             final Map<String, Boolean> cmStatus = new HashMap<>();
159             cmStatus.put(cmAddrInet.getHostAddress(), true);
160             cmStatus.put(invalidCmAddrInet.getHostAddress(), false);
161
162             CMTSConfig config = new CMTSConfig(0, (short)4, upSCN, dnSCN, cmStatus);
163
164             icmts = new CMTS(config);
165             icmts.startServer();
166
167             ccap = makeCcapObj(icmts.getPort(), cmtsAddr, ccapId);
168         }
169
170         service = new PCMMService(IPCMMClient.CLIENT_TYPE, ccap);
171     }
172
173     @After
174     public void tearDown() {
175         if (icmts != null) icmts.stopServer();
176         service.disconect();
177     }
178
179     @Test
180     public void testAddCcap() {
181         connectToCmts(service);
182     }
183
184     @Test
185     public void testAddInvalidCcapBadPort() {
186         final int port;
187         if (icmts != null) port = icmts.getPort() + 1;
188         else port = PCMMPdpAgent.WELL_KNOWN_PDP_PORT + 1;
189         ccap = makeCcapObj(port, cmtsAddr, ccapId);
190         service = new PCMMService(IPCMMClient.CLIENT_TYPE, ccap);
191         final String message = service.addCcap();
192         Assert.assertNotNull(message);
193         final String expectedMsg = "404 Not Found - CCAP " + ccapId + " failed to connect @ " + cmtsAddr.getValue()
194                 + ':' + port + " - ";
195         Assert.assertTrue(expectedMsg, message.startsWith(expectedMsg));
196     }
197
198     @Test
199     public void testAddValidUpGateTwice() throws Exception {
200         connectToCmts(service);
201         final String expectedMsg1 = "200 OK - sendGateSet for " + ccapId + '/' + gatePath + " returned GateId";
202         addAndValidateGate(service, "extrm_up", srcAddr, dstAddr, ServiceFlowDirection.Us, cmAddrInet, gatePath,
203                 expectedMsg1);
204
205         final String expectedMsg2 = "404 Not Found - sendGateSet for " + ccapId + '/' + gatePath + " already exists";
206         addAndValidateGate(service, "extrm_up", srcAddr, dstAddr, ServiceFlowDirection.Us, cmAddrInet, gatePath,
207                 expectedMsg2);
208
209         Assert.assertTrue(deleteGate(service, gatePath));
210     }
211
212     @Test
213     public void testAddTwoValidUpGates() throws Exception {
214         connectToCmts(service);
215
216         final String gatePath1 = "gatePath1";
217         final String expectedMsg1 = "200 OK - sendGateSet for " + ccapId + '/' + gatePath1 + " returned GateId";
218         addAndValidateGate(service, "extrm_up", srcAddr, dstAddr, ServiceFlowDirection.Us, cmAddrInet, gatePath1,
219                 expectedMsg1);
220
221         final String gatePath2 = "gatePath2";
222         final String expectedMsg2 = "200 OK - sendGateSet for " + ccapId + '/' + gatePath2 + " returned GateId";
223         addAndValidateGate(service, "extrm_up", srcAddr, dstAddr, ServiceFlowDirection.Us, cmAddrInet, gatePath2,
224                 expectedMsg2);
225
226         Assert.assertTrue(deleteGate(service, gatePath1));
227         Assert.assertTrue(deleteGate(service, gatePath2));
228     }
229
230     @Test
231     public void testAddValidDownGateTwice() throws Exception {
232         connectToCmts(service);
233         final String expectedMsg1 = "200 OK - sendGateSet for " + ccapId + '/' + gatePath + " returned GateId";
234         addAndValidateGate(service, "extrm_dn", srcAddr, dstAddr, ServiceFlowDirection.Ds, cmAddrInet, gatePath,
235                 expectedMsg1);
236
237         final String expectedMsg2 = "404 Not Found - sendGateSet for " + ccapId + '/' + gatePath + " already exists";
238         addAndValidateGate(service, "extrm_dn", srcAddr, dstAddr, ServiceFlowDirection.Ds, cmAddrInet, gatePath,
239                 expectedMsg2);
240
241         Assert.assertTrue(deleteGate(service, gatePath));
242     }
243
244     @Test
245     public void testDeleteNonExistentGate() throws Exception {
246         connectToCmts(service);
247         Assert.assertFalse(deleteGate(service, gatePath));
248     }
249
250     @Test
251     public void testAddAndRemoveValidUpGate() throws Exception {
252         final String expectedMsgStart = "200 OK - sendGateSet for " + ccapId + '/' + gatePath + " returned GateId";
253         addRemoveValidateGate(service, "extrm_up", srcAddr, dstAddr, ServiceFlowDirection.Us, cmAddrInet, gatePath,
254                 expectedMsgStart);
255     }
256
257     @Test
258     public void testAddAndRemoveValidDownGate() throws Exception {
259         final String expectedMsgStart = "200 OK - sendGateSet for " + ccapId + '/' + gatePath + " returned GateId";
260         addRemoveValidateGate(service, "extrm_dn", srcAddr, dstAddr, ServiceFlowDirection.Ds, cmAddrInet, gatePath,
261                 expectedMsgStart);
262     }
263
264     @Test
265     public void testAddAndRemoveInvalidCmAddrUpGate() throws Exception {
266         // TODO - fix cmts emulator
267         final String expectedMsgStart = "404 Not Found - sendGateSet for " + ccapId + '/' + gatePath
268                 + " returned error - Error Code: 13 Subcode: 0  Invalid SubscriberID";
269         addInvalidGate(service, "extrm_up", srcAddr, dstAddr, ServiceFlowDirection.Us, invalidCmAddrInet, gatePath,
270                 expectedMsgStart);
271     }
272
273     @Test
274     public void testAddInvalidScnUpGate() throws Exception {
275         final String expectedMsgStart = "404 Not Found - sendGateSet for " + ccapId + '/' + gatePath
276                 + " returned error - Error Code: 11 Subcode: 0  Undefined Service Class Name";
277         addInvalidGate(service, "extrm_up_invalid", srcAddr, dstAddr, ServiceFlowDirection.Us, cmAddrInet, gatePath,
278                 expectedMsgStart);
279     }
280
281     @Test
282     public void testAddInvalidScnDownGate() throws Exception {
283         final String expectedMsgStart = "404 Not Found - sendGateSet for " + ccapId + '/' + gatePath
284                 + " returned error - Error Code: 11 Subcode: 0  Undefined Service Class Name";
285         addInvalidGate(service, "extrm_dn_invalid", srcAddr, dstAddr, ServiceFlowDirection.Ds, cmAddrInet, gatePath,
286                 expectedMsgStart);
287     }
288
289     /**
290      * This tests the instantiation of a COPSDecisionMsg object that is responsible for setting a gate request,
291      * streams it over a mock Socket object and parses the bytes into a new COPSDecisionMsg object which should
292      * be equivalent
293      * @throws Exception - test will fail should any exception be thrown during execution
294      */
295     @Test
296     public void testGateRequestDecisionMsg() throws Exception {
297         final Socket socket = new MockSocket();
298
299         final ServiceFlowDirection direction = ServiceFlowDirection.Us;
300         final Gate gate = makeGateObj("extrm_up", cmtsAddr, direction, new Ipv4Address("127.0.0.1"));
301         final IPCMMGate gateReq = makeGateRequest(ccap, gate, InetAddress.getByName("localhost"), direction);
302         final byte[] data = gateReq.getData();
303
304         final Set<COPSDecision> decisionSet = new HashSet<>();
305         decisionSet.add(new COPSDecision(CType.DEF, Command.INSTALL, DecisionFlag.REQERROR));
306         final Map<COPSContext, Set<COPSDecision>> decisionMap = new HashMap<>();
307         decisionMap.put(new COPSContext(RType.CONFIG, (short) 0), decisionSet);
308
309         final COPSClientSI clientSD = new COPSClientSI(CNum.DEC, CType.CSI, new COPSData(data, 0, data.length));
310         final COPSDecisionMsg decisionMsg = new COPSDecisionMsg(IPCMMClient.CLIENT_TYPE, new COPSHandle(new COPSData("123")),
311                 decisionMap, null, clientSD);
312         decisionMsg.writeData(socket);
313
314         final COPSMsg msg = COPSMsgParser.parseMessage(socket);
315         Assert.assertNotNull(msg);
316         Assert.assertEquals(decisionMsg, msg);
317     }
318
319     /**
320      * Attempts to create a gate against a CMTS, validates the results then attempts to delete it.
321      * @param service - the service used to connect to a CMTS for issuing requests
322      * @param scnName - the service class name (aka. gate name)
323      * @param srcAddr - the address to the CMTS subnet?
324      * @param dstAddr - the destination address
325      * @param direction - the gate direction
326      * @param cmAddrInet - the address to the cable modem to which the gate will be assigned
327      * @param gatePath - the path to the gate
328      * @param expGateSetMsgStart - the expected start of the gate set return message to be validated against
329      */
330     private void addRemoveValidateGate(final PCMMService service, final String scnName, final Ipv4Address srcAddr,
331                                        final Ipv4Address dstAddr, final ServiceFlowDirection direction,
332                                        final InetAddress cmAddrInet, final String gatePath,
333                                        final String expGateSetMsgStart) {
334         connectToCmts(service);
335         addAndValidateGate(service, scnName, srcAddr, dstAddr, direction, cmAddrInet, gatePath, expGateSetMsgStart);
336         deleteGate(service, gatePath);
337     }
338
339     private void addInvalidGate(final PCMMService service, final String scnName, final Ipv4Address srcAddr,
340             final Ipv4Address dstAddr, final ServiceFlowDirection direction,
341             final InetAddress cmAddrInet, final String gatePath,
342             final String expGateSetMsgStart) {
343         connectToCmts(service);
344         final int numRequestsBefore = service.gateRequests.size();
345         addAndValidateGate(service, scnName, srcAddr, dstAddr, direction, cmAddrInet, gatePath, expGateSetMsgStart);
346         assertEquals(numRequestsBefore, service.gateRequests.size());
347     }
348
349     private void connectToCmts(final PCMMService service) {
350         final String message = service.addCcap();
351         Assert.assertNotNull(message);
352         final String expectedMsg = "200 OK - CCAP " + ccapId + " connected @ "
353                 + ccap.getConnection().getIpAddress().getIpv4Address().getValue()
354                 + ":" + ccap.getConnection().getPort().getValue();
355         Assert.assertEquals(expectedMsg, message);
356         Assert.assertNotNull(service.ccapClient.pcmmPdp.getClientHandle());
357     }
358
359     /**
360      * Attempts to create a gate against a CMTS and validates the results.
361      * @param service - the service used to connect to a CMTS for issuing requests
362      * @param scnName - the service class name (aka. gate name)
363      * @param srcAddr - the address to the CMTS subnet?
364      * @param dstAddr - the destination address
365      * @param direction - the gate direction
366      * @param cmAddrInet - the address to the cable modem to which the gate will be assigned
367      * @param gatePath - the path to the gate
368      * @param expGateSetMsgStart - the expected start of the gate set return message to be validated against
369      */
370     private void addAndValidateGate(final PCMMService service, final String scnName, final Ipv4Address srcAddr,
371                                     final Ipv4Address dstAddr, final ServiceFlowDirection direction,
372                                     final InetAddress cmAddrInet, final String gatePath,
373                                     final String expGateSetMsgStart) {
374         final Gate gate = makeGateObj(scnName, srcAddr, direction, dstAddr);
375
376 //        final String gateSetMsg = service.sendGateSet(gatePath, cmAddrInet, gate, direction);
377 //        Assert.assertNotNull(gateSetMsg);
378 //        Assert.assertTrue(gateSetMsg, gateSetMsg.startsWith(expGateSetMsgStart));
379
380         // TODO update this method for the new GateSendStatus object
381         PCMMService.GateSendStatus status = service.sendGateSet(gatePath, cmAddrInet, gate);
382         Assert.assertNotNull(status);
383         assertThat(status.getMessage(), startsWith(expGateSetMsgStart));
384
385
386         // TODO - add validation to the PCMMGateReq contained within the map
387         if (status.didSucceed()) {
388             Assert.assertTrue((service.gateRequests.containsKey(gatePath)));
389             Assert.assertNotNull(service.gateRequests.get(gatePath));
390         }
391     }
392
393     /**
394      * Attempts to delete a gate
395      * @param service - the service used to connect to a CMTS for issuing requests
396      * @param gatePath - the path to the gate
397      */
398     private boolean deleteGate(final PCMMService service, final String gatePath) {
399         final boolean out = service.sendGateDelete(gatePath);
400
401         // Wait up to 1 sec for response to be processed
402         final long start = System.currentTimeMillis();
403         while (1000 < System.currentTimeMillis() - start) {
404             if (service.gateRequests.size() == 0) break;
405         }
406         Assert.assertNull(service.gateRequests.get(gatePath));
407         return out;
408     }
409
410     /**
411      * Creates a mock Ccap object that can be used for connecting to a CMTS
412      * @param inPort - the CMTS port number
413      * @param ipAddr - the CMTS IPv4 address string
414      * @param ccapId - the ID of the CCAP
415      * @return - the mock Ccap object
416      */
417     private Ccap makeCcapObj(final int inPort, final Ipv4Address ipAddr, final String ccapId) {
418         final Ccap ccap = mock(Ccap.class);
419         final Connection conn = mock(Connection.class);
420         when(ccap.getConnection()).thenReturn(conn);
421         final PortNumber port = mock(PortNumber.class);
422         when(conn.getPort()).thenReturn(port);
423         when(port.getValue()).thenReturn(inPort);
424
425         final IpAddress addr = mock(IpAddress.class);
426         when(conn.getIpAddress()).thenReturn(addr);
427         when(addr.getIpv4Address()).thenReturn(ipAddr);
428
429         when(ccap.getCcapId()).thenReturn(ccapId);
430         final AmId amid = mock(AmId.class);
431         when(ccap.getAmId()).thenReturn(amid);
432         when(amid.getAmTag()).thenReturn(0xcada);
433         when(amid.getAmType()).thenReturn(1);
434
435         return ccap;
436     }
437
438     /**
439      * Creates a mock Gate object
440      * @param scnValue - the service class name defined on the CMTS
441      * @param dstAddr - the CM address this gate should be set against
442      * @return - the gate request
443      */
444     private Gate makeGateObj(final String scnValue, final Ipv4Address srcAddr, final ServiceFlowDirection direction,
445                               final Ipv4Address dstAddr) {
446         final Gate gate = mock(Gate.class);
447         final GateSpec gateSpec = mock(GateSpec.class);
448         when(gate.getGateSpec()).thenReturn(gateSpec);
449         when(gateSpec.getDirection()).thenReturn(direction);
450         // TODO - make sure to write a test when this value is not null
451         when(gateSpec.getDscpTosOverwrite()).thenReturn(null);
452
453         // TODO - refactor to add flowspec profile testing as well
454         final TrafficProfile trafficProfile = mock(TrafficProfile.class);
455         final ServiceClassNameChoice serviceClassNameChoice = mock(ServiceClassNameChoice.class);
456         final ServiceClassNameProfile serviceClassNameProfile = mock(ServiceClassNameProfile.class);
457         final ServiceClassName serviceClassName = mock(ServiceClassName.class);
458         when(serviceClassName.getValue()).thenReturn(scnValue);
459         when(serviceClassNameProfile.getServiceClassName()).thenReturn(serviceClassName);
460         when(serviceClassNameChoice.getServiceClassNameProfile()).thenReturn(serviceClassNameProfile);
461         when(trafficProfile.getTrafficProfileChoice()).thenReturn(serviceClassNameChoice);
462         when(gate.getTrafficProfile()).thenReturn(trafficProfile);
463
464         // TODO - write tests when this is null and ExtClassifier or Ipv6Classifier objects are not null
465         final Classifier classifier = mock(Classifier.class);
466
467         // This is the address of the CM
468         when(classifier.getDstIp()).thenReturn(dstAddr);
469
470         final PortNumber dstPort = new PortNumber(4321);
471         when(classifier.getDstPort()).thenReturn(dstPort);
472         final TpProtocol protocol = new TpProtocol(0);
473         when(classifier.getProtocol()).thenReturn(protocol);
474         when(classifier.getSrcIp()).thenReturn(srcAddr);
475         final PortNumber srcPort = new PortNumber(1234);
476         when(classifier.getSrcPort()).thenReturn(srcPort);
477
478         // TODO - Can this value be any other value than 0 or 1 (See TosByte enumeration)
479         final TosByte tosByte = new TosByte((short)0);
480         when(classifier.getTosByte()).thenReturn(tosByte);
481         final TosByte tosMask = new TosByte((short)224);
482         when(classifier.getTosMask()).thenReturn(tosMask);
483
484         final QosClassifierChoice classifierChoice = mock(QosClassifierChoice.class);
485         when(classifierChoice.getClassifier()).thenReturn(classifier);
486
487         ClassifierContainer classifierContainer = mock(ClassifierContainer.class);
488         when(classifierContainer.getClassifierChoice()).thenReturn(classifierChoice);
489
490         final List<ClassifierContainer> containerList = Collections.singletonList(classifierContainer);
491
492         Classifiers classifiers = mock(Classifiers.class);
493         when(classifiers.getClassifierContainer()).thenReturn(containerList);
494
495         when(gate.getClassifiers()).thenReturn(classifiers);
496
497         return gate;
498     }
499
500     private IPCMMGate makeGateRequest(final Ccap ccap, final Gate gateReq, final InetAddress addrSubId,
501                                      final ServiceFlowDirection direction) {
502         final PCMMGateReqBuilder gateBuilder = new PCMMGateReqBuilder();
503         gateBuilder.setAmId(ccap.getAmId());
504         gateBuilder.setSubscriberId(addrSubId);
505         // force gateSpec.Direction to align with SCN direction
506         final ServiceClassName scn =
507             ((ServiceClassNameChoice)gateReq.getTrafficProfile().getTrafficProfileChoice()).getServiceClassNameProfile().getServiceClassName();
508         if (scn != null) {
509             gateBuilder.setGateSpec(gateReq.getGateSpec(), direction);
510         } else {
511             // not an SCN gate
512             gateBuilder.setGateSpec(gateReq.getGateSpec(), null);
513         }
514         gateBuilder.setTrafficProfile(gateReq.getTrafficProfile());
515
516         gateBuilder.setClassifiers(gateReq.getClassifiers().getClassifierContainer());
517
518         // assemble the final gate request
519         return gateBuilder.build();
520     }
521
522     private class MockSocket extends Socket {
523
524         private ByteArrayOutputStream os = new ByteArrayOutputStream();
525         private ByteArrayInputStream is;
526
527         @Override
528         public OutputStream getOutputStream() {
529             return os;
530         }
531
532         @Override
533         public InputStream getInputStream() {
534             if (is == null) is = new ByteArrayInputStream(os.toByteArray());
535             return is;
536         }
537     }
538
539 }