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