/*
* Mobicents, Communications Middleware
*
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Middleware LLC.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
*
* Boston, MA 02110-1301 USA
*/
package org.mobicents.slee.resources.diameter.tests.framework.validator;
import static org.jdiameter.client.impl.helpers.Parameters.AcctApplId;
import static org.jdiameter.client.impl.helpers.Parameters.ApplicationId;
import static org.jdiameter.client.impl.helpers.Parameters.Assembler;
import static org.jdiameter.client.impl.helpers.Parameters.AuthApplId;
import static org.jdiameter.client.impl.helpers.Parameters.OwnDiameterURI;
import static org.jdiameter.client.impl.helpers.Parameters.OwnRealm;
import static org.jdiameter.client.impl.helpers.Parameters.OwnVendorID;
import static org.jdiameter.client.impl.helpers.Parameters.PeerName;
import static org.jdiameter.client.impl.helpers.Parameters.PeerRating;
import static org.jdiameter.client.impl.helpers.Parameters.PeerTable;
import static org.jdiameter.client.impl.helpers.Parameters.RealmEntry;
import static org.jdiameter.client.impl.helpers.Parameters.RealmTable;
import static org.jdiameter.client.impl.helpers.Parameters.VendorId;
import net.java.slee.resource.diameter.base.DiameterAvpFactory;
import net.java.slee.resource.diameter.base.events.AccountingAnswer;
import net.java.slee.resource.diameter.base.events.avp.DiameterAvpType;
import net.java.slee.resource.diameter.base.events.avp.DiameterIdentity;
import net.java.slee.resource.diameter.cca.events.avp.CcMoneyAvp;
import net.java.slee.resource.diameter.cca.events.avp.CcRequestType;
import net.java.slee.resource.diameter.cca.events.avp.GrantedServiceUnitAvp;
import net.java.slee.resource.diameter.cca.events.avp.UnitValueAvp;
import org.jdiameter.api.AvpSet;
import org.jdiameter.api.IllegalDiameterStateException;
import org.jdiameter.api.InternalException;
import org.jdiameter.api.Stack;
import org.jdiameter.client.impl.helpers.EmptyConfiguration;
import org.jdiameter.common.impl.validation.DiameterMessageValidator;
import org.jdiameter.common.impl.validation.JAvpNotAllowedException;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mobicents.diameter.dictionary.AvpDictionary;
import org.mobicents.slee.resource.diameter.base.DiameterAvpFactoryImpl;
import org.mobicents.slee.resource.diameter.base.DiameterMessageFactoryImpl;
import org.mobicents.slee.resource.diameter.base.events.AccountingAnswerImpl;
import org.mobicents.slee.resource.diameter.base.events.avp.DiameterAvpImpl;
import org.mobicents.slee.resource.diameter.cca.CreditControlAVPFactoryImpl;
import org.mobicents.slee.resource.diameter.cca.CreditControlMessageFactoryImpl;
import org.mobicents.slee.resource.diameter.cca.events.CreditControlAnswerImpl;
import static org.junit.Assert.*;
/**
* Start time:14:15:19 2009-05-27<br>
* Project: diameter-parent<br>
*
* @author <a href="mailto:baranowb@gmail.com"> Bartosz Baranowski </a>
* @author <a href="mailto:brainslog@gmail.com"> Alexandre Mendonca </a>
*/
public class MessageValidatorTest {
private static String clientHost = "127.0.0.1";
private static String clientPort = "21812";
private static String clientURI = "aaa://" + clientHost + ":" + clientPort;
private static String serverHost = "localhost";
private static String serverPort = "1812";
private static String serverURI = "aaa://" + serverHost + ":" + serverPort;
private static String realmName = "mobicents.org";
private static DiameterMessageFactoryImpl baseFactory;
private static CreditControlMessageFactoryImpl ccaFactory;
private DiameterMessageValidator instance = null;
@Before
public void setUp() {
this.instance = DiameterMessageValidator.getInstance();
}
@After
public void tearDown() {
this.instance = null;
}
@Test
public void testBasicOperations() {
// Yeah, its akward :) - it laready shoudl have session id.
AccountingAnswerImpl answer = (AccountingAnswerImpl) baseFactory.createAccountingAnswer(baseFactory.createAccountingRequest(new DiameterAvpImpl[] { new DiameterAvpImpl(263, 0L, 0, 1, "xxx"
.getBytes(), DiameterAvpType.UTF8_STRING) }));
AvpSet set = answer.getGenericData().getAvps();
// nooooow, lets try some tests
// <avp name="Session-Id" code="263" vendor="0" multiplicity="1"
// index="0"/>
assertTrue("Session-Id is not allowed in this message, it should be.", this.instance.isAllowed(AccountingAnswer.commandCode, answer.getHeader().getApplicationId(), false, 263, 0));
if (answer.hasSessionId()) {
assertFalse("We should not allow to add more SessionIds than one, operation indicates that it could be done.", this.instance.isCountValidForMultiplicity(AccountingAnswer.commandCode,
answer.getHeader().getApplicationId(), false, set, 263, 0L));
} else {
assertTrue("We should allow to add ONE (1) Session-Id AVP, operation indicates that it could not be done.", this.instance.isCountValidForMultiplicity(AccountingAnswer.commandCode, answer
.getHeader().getApplicationId(), false, set, 263, 0L));
}
// <avp name="Origin-Host" code="264" vendor="0" multiplicity="1"
// index="-1"/>
assertTrue("Origin-Host is not allowed in this message, it should be.", this.instance.isAllowed(AccountingAnswer.commandCode, answer.getHeader().getApplicationId(), false, 264, 0));
if (answer.hasOriginHost()) {
assertFalse("We should allow to add more Origin-Host than zero, operation indicates that it could not be done.", this.instance.isCountValidForMultiplicity(AccountingAnswer.commandCode,
answer.getHeader().getApplicationId(), false, set, 264, 0L));
} else {
assertTrue("We should not allow to add more than one Origin-Host, operation indicates that it could be done.", this.instance.isCountValidForMultiplicity(AccountingAnswer.commandCode,
answer.getHeader().getApplicationId(), false, set, 264, 0L));
}
// <avp name="Event-Timestamp" code="55" vendor="0" multiplicity="0-1"
// index="-1"/>
assertTrue("Event-Timestamp is not allowed in this message, it should be.", this.instance.isAllowed(AccountingAnswer.commandCode, answer.getHeader().getApplicationId(), false, 55, 0));
assertTrue("We should allow to add more Event-Timestamp than zero, operation indicates that it could not be done.", this.instance.isCountValidForMultiplicity(AccountingAnswer.commandCode,
answer.getHeader().getApplicationId(), false, set, 55, 0L));
set.addAvp(55, 55L, 0L, true, false);
assertFalse("We should not allow to add more Event-Timestamp than one, operation indicates that it could be done.", this.instance.isCountValidForMultiplicity(AccountingAnswer.commandCode,
answer.getHeader().getApplicationId(), false, set, 55, 0L));
// <avp name="Proxy-Info" code="284" vendor="0" multiplicity="0+"
// index="-1"/>
assertTrue("Proxy-Info is not allowed in this message, it should be.", this.instance.isAllowed(AccountingAnswer.commandCode, answer.getHeader().getApplicationId(), false, 284, 0));
assertTrue("We should allow to add more Proxy-Info than zero, operation indicates that it could not note be done.", this.instance.isCountValidForMultiplicity(AccountingAnswer.commandCode,
answer.getHeader().getApplicationId(), false, set, 284, 0L));
set.addAvp(284, 284L, 0L, true, false);
assertTrue("We should allow to add more Proxy-Info than one, operation indicates that it could note be done.", this.instance.isCountValidForMultiplicity(AccountingAnswer.commandCode, answer
.getHeader().getApplicationId(), false, set, 284, 0L));
set.addAvp(284, 284L, 0L, true, false);
assertTrue("We should allow to add more Proxy-Info than two, operation indicates that it could note be done.", this.instance.isCountValidForMultiplicity(AccountingAnswer.commandCode, answer
.getHeader().getApplicationId(), false, set, 284, 0L));
// <!-- FORBBIDEN -->
// <avp name="Auth-Application-Id" code="258" vendor="0"
// multiplicity="0" index="-1"/>
assertFalse("Auth-Application-Id is allowed in this message, it should not be.", this.instance.isAllowed(AccountingAnswer.commandCode, answer.getHeader().getApplicationId(), false, 258, 0));
assertFalse("We should not allow to add more Auth-Application-Id than zero, operation indicates that it could be done.", this.instance.isCountValidForMultiplicity(
AccountingAnswer.commandCode, answer.getHeader().getApplicationId(), false, set, 258, 0L));
// <avp name="Destination-Realm" code="283" vendor="0" multiplicity="0"
// index="-1"/>
assertFalse("Auth-Application-Id is allowed in this message, it should not be.", this.instance.isAllowed(AccountingAnswer.commandCode, answer.getHeader().getApplicationId(), false, 258, 0));
assertFalse("We should not allow to add more Auth-Application-Id than zero, operation indicates that it could be done.", this.instance.isCountValidForMultiplicity(
AccountingAnswer.commandCode, answer.getHeader().getApplicationId(), false, set, 258, 0L));
}
@Test
public void testGroupedAvpValidationFail() {
// Yeah, its akward :) - it laready shoudl have session id.
CreditControlAnswerImpl answer = (CreditControlAnswerImpl) ccaFactory.createCreditControlAnswer(ccaFactory.createCreditControlRequest("xxxxxxxxxxxx"));
DiameterMessageValidator instance = DiameterMessageValidator.getInstance();
AvpSet set = answer.getGenericData().getAvps();
// nooooow, lets try some tests
// we shoudl test gropued avps bad behaviour.
// Must
// avp name="Auth-Application-Id" code="258" vendor="0" multiplicity="1"
// index="-1" />
//This is set by factory.
//answer.setAuthApplicationId(5);
// <avp name="CC-Request-Number" code="415" vendor="0" multiplicity="1"
// index="-1" />
// <avp name="Origin-Realm" code="296" vendor="0" multiplicity="1"
// index="-1" />
if (!answer.hasOriginRealm()) {
answer.setOriginRealm(new DiameterIdentity("aaa://mobicents.org"));
}
// <avp name="Result-Code" code="268" vendor="0" multiplicity="1"
// index="-1" />
answer.setResultCode(2066);
// <avp name="Session-Id" code="263" vendor="0" multiplicity="1"
// index="0" />
// should be there
// MAY, but we add this, since its multi grouped avp
// <avp name="Granted-Service-Unit" code="431" vendor="0"
// multiplicity="0-1" index="-1" />
// here we should fail.
try {
instance.validate(answer.getGenericData());
fail("Validation of message should fails: "+answer);
} catch (JAvpNotAllowedException ex) {
//we are ok,
//ex.printStackTrace();
}
answer.setCcRequestNumber(1);
// <avp name="CC-Request-Type" code="416" vendor="0" multiplicity="1"
// index="-1" />
answer.setCcRequestType(CcRequestType.EVENT_REQUEST);
// <avp name="Origin-Host" code="264" vendor="0" multiplicity="1"
// index="-1" />
if (!answer.hasOriginHost()) {
answer.setOriginHost(new DiameterIdentity("aaa://127.0.0.1:1818"));
}
// here we should not fail.
try {
instance.validate(answer.getGenericData());
} catch (JAvpNotAllowedException ex) {
ex.printStackTrace();
fail("Validation of message should not fails: "+answer);
return;
}
//MAY - but we will add this, since its multi gropued avp.
//<avp name="Granted-Service-Unit" code="431" vendor="0" multiplicity="0-1" index="-1" />
CreditControlAVPFactoryImpl ccaAvpFactory = new CreditControlAVPFactoryImpl(new DiameterAvpFactoryImpl());
GrantedServiceUnitAvp gsuAVP=ccaAvpFactory.createGrantedServiceUnit();
// <avp name="Granted-Service-Unit" code="431" mandatory="must" vendor-bit="mustnot" vendor-id="None" may-encrypt="yes" protected="may">
// <grouped>
// <gavp name="Tariff-Time-Change" multiplicity="0-1"/>
// <gavp name="CC-Time" multiplicity="0-1"/>
// <gavp name="CC-Money" multiplicity="0-1"/>
// <gavp name="CC-Total-Octets" multiplicity="0-1"/>
// <gavp name="CC-Input-Octets" multiplicity="0-1"/>
// <gavp name="CC-Output-Octets" multiplicity="0-1"/>
// <gavp name="Cost-Unit" multiplicity="0-1"/>
// </grouped>
// </avp>
// However CC-Money has mandatory field, which should be present - Unit-Value, which is grouped avp which also has mandatory Value-Digits
gsuAVP.setCreditControlInputOctets(8);
UnitValueAvp unitValue= ccaAvpFactory.createUnitValue();
unitValue.setExponent(12);
CcMoneyAvp ccMoney = ccaAvpFactory.createCcMoney(unitValue);
ccMoney.setCurrencyCode(1);
gsuAVP.setCreditControlMoneyAvp(ccMoney);
//this avp is bad, unit value does not have defined all fields.
answer.setGrantedServiceUnit(gsuAVP);
try {
instance.validate(answer.getGenericData());
fail("Validation of message should fails: "+answer);
} catch (JAvpNotAllowedException ex) {
//we are ok,
ex.printStackTrace();
}
}
@Test
public void testGroupedAvpValidationSuccess() {
// Yeah, its akward :) - it laready shoudl have session id.
CreditControlAnswerImpl answer = (CreditControlAnswerImpl) ccaFactory.createCreditControlAnswer(ccaFactory.createCreditControlRequest("xxxxxxxxxxxx"));
DiameterMessageValidator instance = DiameterMessageValidator.getInstance();
AvpSet set = answer.getGenericData().getAvps();
// nooooow, lets try some tests
// we shoudl test gropued avps bad behaviour.
// Must
// avp name="Auth-Application-Id" code="258" vendor="0" multiplicity="1"
// index="-1" />
//This is set by factory.
//answer.setAuthApplicationId(5);
// <avp name="CC-Request-Number" code="415" vendor="0" multiplicity="1"
// index="-1" />
// <avp name="Origin-Realm" code="296" vendor="0" multiplicity="1"
// index="-1" />
if (!answer.hasOriginRealm()) {
answer.setOriginRealm(new DiameterIdentity("aaa://mobicents.org"));
}
// <avp name="Result-Code" code="268" vendor="0" multiplicity="1"
// index="-1" />
answer.setResultCode(2066);
// <avp name="Session-Id" code="263" vendor="0" multiplicity="1"
// index="0" />
// should be there
// MAY, but we add this, since its multi grouped avp
// <avp name="Granted-Service-Unit" code="431" vendor="0"
// multiplicity="0-1" index="-1" />
// here we should fail.
try {
instance.validate(answer.getGenericData());
fail("Validation of message should fails: "+answer);
} catch (JAvpNotAllowedException ex) {
//we are ok,
//ex.printStackTrace();
}
answer.setCcRequestNumber(1);
// <avp name="CC-Request-Type" code="416" vendor="0" multiplicity="1"
// index="-1" />
answer.setCcRequestType(CcRequestType.EVENT_REQUEST);
// <avp name="Origin-Host" code="264" vendor="0" multiplicity="1"
// index="-1" />
if (!answer.hasOriginHost()) {
answer.setOriginHost(new DiameterIdentity("aaa://127.0.0.1:1818"));
}
// here we should not fail.
try {
instance.validate(answer.getGenericData());
} catch (JAvpNotAllowedException ex) {
ex.printStackTrace();
fail("Validation of message should not fails: "+answer);
return;
}
//MAY - but we will add this, since its multi gropued avp.
//<avp name="Granted-Service-Unit" code="431" vendor="0" multiplicity="0-1" index="-1" />
CreditControlAVPFactoryImpl ccaAvpFactory = new CreditControlAVPFactoryImpl(new DiameterAvpFactoryImpl());
GrantedServiceUnitAvp gsuAVP=ccaAvpFactory.createGrantedServiceUnit();
// <avp name="Granted-Service-Unit" code="431" mandatory="must" vendor-bit="mustnot" vendor-id="None" may-encrypt="yes" protected="may">
// <grouped>
// <gavp name="Tariff-Time-Change" multiplicity="0-1"/>
// <gavp name="CC-Time" multiplicity="0-1"/>
// <gavp name="CC-Money" multiplicity="0-1"/>
// <gavp name="CC-Total-Octets" multiplicity="0-1"/>
// <gavp name="CC-Input-Octets" multiplicity="0-1"/>
// <gavp name="CC-Output-Octets" multiplicity="0-1"/>
// <gavp name="Cost-Unit" multiplicity="0-1"/>
// </grouped>
// </avp>
// However CC-Money has mandatory field, which should be present - Unit-Value, which is grouped avp which also has mandatory Value-Digits
gsuAVP.setCreditControlInputOctets(8);
UnitValueAvp unitValue= ccaAvpFactory.createUnitValue();
unitValue.setExponent(12);
CcMoneyAvp ccMoney = ccaAvpFactory.createCcMoney(unitValue);
ccMoney.setCurrencyCode(1);
gsuAVP.setCreditControlMoneyAvp(ccMoney);
//this avp is bad, unit value does not have defined all fields.
answer.setGrantedServiceUnit(gsuAVP);
try {
instance.validate(answer.getGenericData());
fail("Validation of message should fails: "+answer);
} catch (JAvpNotAllowedException ex) {
//we are ok,
ex.printStackTrace();
}
}
static {
Stack stack = new org.jdiameter.client.impl.StackImpl();
try {
stack.init(new MyConfiguration());
} catch (Exception e) {
throw new RuntimeException("Failed to initialize the stack.");
}
baseFactory = new DiameterMessageFactoryImpl(stack);
// DiameterAvpFactoryImpl baseAvpFactory = new DiameterAvpFactoryImpl();
try {
ccaFactory = new CreditControlMessageFactoryImpl(baseFactory, stack.getSessionFactory().getNewSession(), stack, new CreditControlAVPFactoryImpl(new DiameterAvpFactoryImpl()));
} catch (InternalException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IllegalDiameterStateException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try {
AvpDictionary.INSTANCE.parseDictionary(MessageValidatorTest.class.getClassLoader().getResourceAsStream("dictionary.xml"));
} catch (Exception e) {
throw new RuntimeException("Failed to parse dictionary file.");
}
}
/**
* Class representing the Diameter Configuration
*/
public static class MyConfiguration extends EmptyConfiguration {
public MyConfiguration() {
super();
add(Assembler, Assembler.defValue());
add(OwnDiameterURI, clientURI);
add(OwnRealm, realmName);
add(OwnVendorID, 193L);
// Set Ericsson SDK feature
// add(UseUriAsFqdn, true);
// Set Common Applications
add(ApplicationId,
// AppId 1
getInstance().add(VendorId, 193L).add(AuthApplId, 0L).add(AcctApplId, 19302L));
// Set peer table
add(PeerTable,
// Peer 1
getInstance().add(PeerRating, 1).add(PeerName, serverURI));
// Set realm table
add(RealmTable,
// Realm 1
getInstance().add(RealmEntry, realmName + ":" + clientHost + "," + serverHost));
}
}
}