/* ==================================================================== * Limited Evaluation License: * * This software is open source, but licensed. The license with this package * is an evaluation license, which may not be used for productive systems. If * you want a full license, please contact us. * * The exclusive owner of this work is the OpenRate project. * This work, including all associated documents and components * is Copyright of the OpenRate project 2006-2015. * * The following restrictions apply unless they are expressly relaxed in a * contractual agreement between the license holder or one of its officially * assigned agents and you or your organisation: * * 1) This work may not be disclosed, either in full or in part, in any form * electronic or physical, to any third party. This includes both in the * form of source code and compiled modules. * 2) This work contains trade secrets in the form of architecture, algorithms * methods and technologies. These trade secrets may not be disclosed to * third parties in any form, either directly or in summary or paraphrased * form, nor may these trade secrets be used to construct products of a * similar or competing nature either by you or third parties. * 3) This work may not be included in full or in part in any application. * 4) You may not remove or alter any proprietary legends or notices contained * in or on this work. * 5) This software may not be reverse-engineered or otherwise decompiled, if * you received this work in a compiled form. * 6) This work is licensed, not sold. Possession of this software does not * imply or grant any right to you. * 7) You agree to disclose any changes to this work to the copyright holder * and that the copyright holder may include any such changes at its own * discretion into the work * 8) You agree not to derive other works from the trade secrets in this work, * and that any such derivation may make you liable to pay damages to the * copyright holder * 9) You agree to use this software exclusively for evaluation purposes, and * that you shall not use this software to derive commercial profit or * support your business or personal activities. * * This software is provided "as is" and any expressed or impled warranties, * including, but not limited to, the impled warranties of merchantability * and fitness for a particular purpose are disclaimed. In no event shall * The OpenRate Project or its officially assigned agents be liable to any * direct, indirect, incidental, special, exemplary, or consequential damages * (including but not limited to, procurement of substitute goods or services; * Loss of use, data, or profits; or any business interruption) however caused * and on theory of liability, whether in contract, strict liability, or tort * (including negligence or otherwise) arising in any way out of the use of * this software, even if advised of the possibility of such damage. * This software contains portions by The Apache Software Foundation, Robert * Half International. * ==================================================================== */ package OpenRate.process; import OpenRate.OpenRate; import OpenRate.exception.InitializationException; import OpenRate.exception.ProcessingException; import OpenRate.record.ChargePacket; import OpenRate.record.IRecord; import OpenRate.record.TimePacket; import OpenRate.utils.ConversionUtils; import TestUtils.FrameworkUtils; import TestUtils.TestRatingRecord; import java.net.URL; import java.sql.Connection; import java.sql.SQLException; import org.junit.*; import static org.junit.Assert.assertEquals; /** * Test the RUM expansion functions. These take a price group and perform RUM * expansion on it so that it reflects all the elements of the price group. * * This is in effect the first part of the RUM rating module. * * @author TGDSPIA1 */ public class AbstractRUMMapTest { private static URL FQConfigFileName; private static AbstractRUMMap instance; // Used for logging and exception handling private static String message; private static OpenRate appl; @BeforeClass public static void setUpClass() throws Exception { FQConfigFileName = new URL("File:src/test/resources/TestRUMMap.properties.xml"); // Set up the OpenRate internal logger - this is normally done by app startup appl = OpenRate.getApplicationInstance(); // Load the properties into the OpenRate object FrameworkUtils.loadProperties(FQConfigFileName); // Get the loggers FrameworkUtils.startupLoggers(); // Get the transaction manager FrameworkUtils.startupTransactionManager(); // Get Data Sources FrameworkUtils.startupDataSources(); // Get a connection Connection JDBCChcon = FrameworkUtils.getDBConnection("RUMMapTestCache"); try { JDBCChcon.prepareStatement("DROP TABLE TEST_RUM_MAP").execute(); } catch (SQLException ex) { if ((ex.getMessage().startsWith("Unknown table")) || // Mysql (ex.getMessage().startsWith("user lacks"))) // HSQL { // It's OK } else { // Not OK, fail the case message = "Error dropping table TEST_RUM_MAP in test <AbstractRUMRateCalcTest>."; Assert.fail(message); } } // ********************************** RUM MAP ****************************** // Create the test table JDBCChcon.prepareStatement("CREATE TABLE TEST_RUM_MAP (ID int, PRICE_GROUP varchar(24), STEP int, PRICE_MODEL varchar(24), RUM varchar(24), RESOURCE varchar(24), RESOURCE_ID int, RUM_TYPE varchar(24), CONSUME_FLAG int)").execute(); // Simplest price model possible - 1 (FACTOR) per minute (CHARGE_BASE), with a charge increment of 1 (BEAT) = "per second rating" JDBCChcon.prepareStatement("INSERT INTO TEST_RUM_MAP (ID,PRICE_GROUP,STEP,PRICE_MODEL,RUM,RESOURCE,RESOURCE_ID,RUM_TYPE,CONSUME_FLAG) VALUES (1,'TestModel1',1,'TestModel1','DUR','EUR',978,'TIERED',0)").execute(); // Two model RUM group - one with a setup price model and one with a scaled price model JDBCChcon.prepareStatement("INSERT INTO TEST_RUM_MAP (ID,PRICE_GROUP,STEP,PRICE_MODEL,RUM,RESOURCE,RESOURCE_ID,RUM_TYPE,CONSUME_FLAG) VALUES (1,'TestModel2',1,'TestModel2a','DUR','EUR',978,'TIERED',0)").execute(); JDBCChcon.prepareStatement("INSERT INTO TEST_RUM_MAP (ID,PRICE_GROUP,STEP,PRICE_MODEL,RUM,RESOURCE,RESOURCE_ID,RUM_TYPE,CONSUME_FLAG) VALUES (1,'TestModel2',1,'TestModel2b','DUR','EUR',978,'TIERED',0)").execute(); // Event price model JDBCChcon.prepareStatement("INSERT INTO TEST_RUM_MAP (ID,PRICE_GROUP,STEP,PRICE_MODEL,RUM,RESOURCE,RESOURCE_ID,RUM_TYPE,CONSUME_FLAG) VALUES (1,'TestModel3',1,'TestModel3','EVT','EUR',978,'EVENT',0)").execute(); // Threshold model JDBCChcon.prepareStatement("INSERT INTO TEST_RUM_MAP (ID,PRICE_GROUP,STEP,PRICE_MODEL,RUM,RESOURCE,RESOURCE_ID,RUM_TYPE,CONSUME_FLAG) VALUES (1,'TestModel4',1,'TestModel4','DUR','EUR',978,'THRESHOLD',0)").execute(); // Super nasty model JDBCChcon.prepareStatement("INSERT INTO TEST_RUM_MAP (ID,PRICE_GROUP,STEP,PRICE_MODEL,RUM,RESOURCE,RESOURCE_ID,RUM_TYPE,CONSUME_FLAG) VALUES (1,'TestModel5a',1,'TestModel5a1','DUR','EUR',978,'TIERED',0)").execute(); JDBCChcon.prepareStatement("INSERT INTO TEST_RUM_MAP (ID,PRICE_GROUP,STEP,PRICE_MODEL,RUM,RESOURCE,RESOURCE_ID,RUM_TYPE,CONSUME_FLAG) VALUES (1,'TestModel5b',1,'TestModel5b1','DUR','EUR',978,'TIERED',0)").execute(); JDBCChcon.prepareStatement("INSERT INTO TEST_RUM_MAP (ID,PRICE_GROUP,STEP,PRICE_MODEL,RUM,RESOURCE,RESOURCE_ID,RUM_TYPE,CONSUME_FLAG) VALUES (1,'TestModel5b',1,'TestModel5b2','DUR','EUR',978,'TIERED',0)").execute(); // Tiered beat rounding model. Changes beat between first and second step JDBCChcon.prepareStatement("INSERT INTO TEST_RUM_MAP (ID,PRICE_GROUP,STEP,PRICE_MODEL,RUM,RESOURCE,RESOURCE_ID,RUM_TYPE,CONSUME_FLAG) VALUES (1,'TestModel6a',1,'TestModel6a','DUR','EUR',978,'TIERED',0)").execute(); JDBCChcon.prepareStatement("INSERT INTO TEST_RUM_MAP (ID,PRICE_GROUP,STEP,PRICE_MODEL,RUM,RESOURCE,RESOURCE_ID,RUM_TYPE,CONSUME_FLAG) VALUES (1,'TestModel6b',1,'TestModel6b','DUR','EUR',978,'TIERED',0)").execute(); // Model with a setup step JDBCChcon.prepareStatement("INSERT INTO TEST_RUM_MAP (ID,PRICE_GROUP,STEP,PRICE_MODEL,RUM,RESOURCE,RESOURCE_ID,RUM_TYPE,CONSUME_FLAG) VALUES (1,'TestModel7a',1,'TestModel7a1','DUR','EUR',978,'TIERED',0)").execute(); JDBCChcon.prepareStatement("INSERT INTO TEST_RUM_MAP (ID,PRICE_GROUP,STEP,PRICE_MODEL,RUM,RESOURCE,RESOURCE_ID,RUM_TYPE,CONSUME_FLAG) VALUES (1,'TestModel7b',1,'TestModel7b1','DUR','EUR',978,'TIERED',0)").execute(); // Get the caches that we are using FrameworkUtils.startupCaches(); } @AfterClass public static void tearDownClass() throws Exception { // Deallocate the resources OpenRate.getApplicationInstance().finaliseApplication(); } @Before public void setUp() { getInstance(); } @After public void tearDown() { releaseInstance(); } /** * Test the RUM expansion for a simple 1 model group. This should result * in a single charge packet populated according to the RUM map. * * @throws java.lang.Exception */ @Test public void testRUMMapSingleModel() throws Exception { TestRatingRecord ratingRecord; System.out.println("testRUMMapSingleModel"); ConversionUtils conv = ConversionUtils.getConversionUtilsObject(); conv.setInputDateFormat("yyyy-MM-dd hh:mm:ss"); long CDRDate = conv.convertInputDateToUTC("2010-01-23 00:00:00"); ratingRecord = getNewRatingRecordDUR(CDRDate, "TestModel1", 0); instance.evaluateRUMPriceGroup(ratingRecord); assertEquals(1, ratingRecord.getChargePacketCount()); assertEquals(1, ratingRecord.getChargePacket(0).getTimeZones().size()); ChargePacket tmpCP = ratingRecord.getChargePacket(0); TimePacket tmpTZ = ratingRecord.getChargePacket(0).getTimeZones().get(0); assertEquals("TestModel1", tmpTZ.priceGroup); assertEquals("TestModel1", tmpTZ.priceModel); assertEquals("DUR", tmpCP.rumName); assertEquals("EUR", tmpCP.resource); assertEquals(2, tmpCP.ratingType); assertEquals("TIERED", tmpCP.ratingTypeDesc); } /** * Test the RUM expansion for a 2 model group. This should result in two * charge packets, each populated according to the RUM map. * * @throws java.lang.Exception */ @Test public void testRUMMapTwoModel() throws Exception { TestRatingRecord ratingRecord; System.out.println("testRUMMapTwoModel"); ConversionUtils conv = ConversionUtils.getConversionUtilsObject(); conv.setInputDateFormat("yyyy-MM-dd hh:mm:ss"); long CDRDate = conv.convertInputDateToUTC("2010-01-23 00:00:00"); ratingRecord = getNewRatingRecordDUR(CDRDate, "TestModel2", 0); instance.evaluateRUMPriceGroup(ratingRecord); assertEquals(2, ratingRecord.getChargePacketCount()); assertEquals(1, ratingRecord.getChargePacket(0).getTimeZones().size()); assertEquals(1, ratingRecord.getChargePacket(1).getTimeZones().size()); ChargePacket tmpCP1 = ratingRecord.getChargePacket(0); TimePacket tmpTZ1 = ratingRecord.getChargePacket(0).getTimeZones().get(0); assertEquals("TestModel2", tmpTZ1.priceGroup); assertEquals("TestModel2a", tmpTZ1.priceModel); assertEquals("DUR", tmpCP1.rumName); assertEquals("EUR", tmpCP1.resource); assertEquals(2, tmpCP1.ratingType); assertEquals("TIERED", tmpCP1.ratingTypeDesc); ChargePacket tmpCP2 = ratingRecord.getChargePacket(1); TimePacket tmpTZ2 = ratingRecord.getChargePacket(1).getTimeZones().get(0); assertEquals("TestModel2", tmpTZ2.priceGroup); assertEquals("TestModel2b", tmpTZ2.priceModel); assertEquals("DUR", tmpCP2.rumName); assertEquals("EUR", tmpCP2.resource); assertEquals(2, tmpCP2.ratingType); assertEquals("TIERED", tmpCP2.ratingTypeDesc); } /** * Test the RUM expansion for a record which has undergone time splitting. In * this case we get multiple charge packets in, and we treat each in turn. * * @throws java.lang.Exception */ @Test public void testRUMMapTwoCPIn() throws Exception { TestRatingRecord ratingRecord; System.out.println("testRUMMapTwoCPIn"); ConversionUtils conv = ConversionUtils.getConversionUtilsObject(); conv.setInputDateFormat("yyyy-MM-dd hh:mm:ss"); long CDRDate = conv.convertInputDateToUTC("2010-01-23 00:00:00"); ratingRecord = getNewRatingRecordDURTimeSplit(CDRDate, "TestModel5a", "TestModel5b", 0); instance.evaluateRUMPriceGroup(ratingRecord); assertEquals(3, ratingRecord.getChargePacketCount()); assertEquals(1, ratingRecord.getChargePacket(0).getTimeZones().size()); assertEquals(1, ratingRecord.getChargePacket(1).getTimeZones().size()); assertEquals(1, ratingRecord.getChargePacket(2).getTimeZones().size()); ChargePacket tmpCP1 = ratingRecord.getChargePacket(0); TimePacket tmpTZ1 = ratingRecord.getChargePacket(0).getTimeZones().get(0); assertEquals("TestModel5a", tmpTZ1.priceGroup); assertEquals("TestModel5a1", tmpTZ1.priceModel); assertEquals("DUR", tmpCP1.rumName); assertEquals("EUR", tmpCP1.resource); assertEquals(2, tmpCP1.ratingType); assertEquals("TIERED", tmpCP1.ratingTypeDesc); ChargePacket tmpCP2 = ratingRecord.getChargePacket(1); TimePacket tmpTZ2 = ratingRecord.getChargePacket(1).getTimeZones().get(0); assertEquals("TestModel5b", tmpTZ2.priceGroup); assertEquals("TestModel5b1", tmpTZ2.priceModel); assertEquals("DUR", tmpCP2.rumName); assertEquals("EUR", tmpCP2.resource); assertEquals(2, tmpCP2.ratingType); assertEquals("TIERED", tmpCP2.ratingTypeDesc); ChargePacket tmpCP3 = ratingRecord.getChargePacket(2); TimePacket tmpTZ3 = ratingRecord.getChargePacket(2).getTimeZones().get(0); assertEquals("TestModel5b", tmpTZ3.priceGroup); assertEquals("TestModel5b2", tmpTZ3.priceModel); assertEquals("DUR", tmpCP3.rumName); assertEquals("EUR", tmpCP3.resource); assertEquals(2, tmpCP3.ratingType); assertEquals("TIERED", tmpCP3.ratingTypeDesc); } public class AbstractRUMMapImpl extends AbstractRUMMap { /** * Override the unused event handling routines. * * @param r input record * @return return record * @throws ProcessingException */ @Override public IRecord procValidRecord(IRecord r) throws ProcessingException { return r; } /** * Override the unused event handling routines. * * @param r input record * @return return record * @throws ProcessingException */ @Override public IRecord procErrorRecord(IRecord r) throws ProcessingException { return r; } } /** * Method to get an instance of the implementation. Done this way to allow * tests to be executed individually. * * @throws InitializationException */ private void getInstance() { if (instance == null) { // Get an initialise the cache instance = new AbstractRUMMapTest.AbstractRUMMapImpl(); try { // Get the instance instance.init("DBTestPipe", "AbstractRUMMapTest"); } catch (InitializationException ex) { org.junit.Assert.fail(); } } else { org.junit.Assert.fail("Instance already allocated"); } } /** * Method to release an instance of the implementation. */ private void releaseInstance() { instance = null; } /** * Create a rating record initialised with the information necessary for * performing a rating. * * @param CDRDate Date of the CDR * @param newPriceGroup The price group to use * @param durationValue The duration value to use * @return The record, ready to go */ private TestRatingRecord getNewRatingRecordDUR(long CDRDate, String newPriceGroup, double durationValue) { TestRatingRecord ratingRecord = new TestRatingRecord(); ratingRecord.utcEventDate = CDRDate; ChargePacket tmpCP = new ChargePacket(); TimePacket tmpTZ = new TimePacket(); tmpTZ.priceGroup = newPriceGroup; tmpCP.addTimeZone(tmpTZ); ratingRecord.addChargePacket(tmpCP); ratingRecord.setRUMValue("DUR", durationValue); return ratingRecord; } /** * Create a rating record initialised with the information necessary for * performing a rating. * * @param CDRDate Date of the CDR * @param newPriceGroup The price group to use * @param durationValue The duration value to use * @return The record, ready to go */ private TestRatingRecord getNewRatingRecordEVT(long CDRDate, String newPriceGroup, double durationValue) { TestRatingRecord ratingRecord = new TestRatingRecord(); ratingRecord.utcEventDate = CDRDate; ChargePacket tmpCP = new ChargePacket(); TimePacket tmpTZ = new TimePacket(); tmpTZ.priceGroup = newPriceGroup; tmpCP.addTimeZone(tmpTZ); ratingRecord.addChargePacket(tmpCP); ratingRecord.setRUMValue("EVT", durationValue); return ratingRecord; } /** * Create a rating record initialised with the information necessary for * performing a rating. This simulates a record that has undergone time * splitting. * * @param CDRDate Date of the CDR * @param newPriceGroup1 The price group to use * @param durationValue The duration value to use * @return The record, ready to go */ private TestRatingRecord getNewRatingRecordDURTimeSplit(long CDRDate, String newPriceGroup1, String newPriceGroup2, double durationValue) { TestRatingRecord ratingRecord = new TestRatingRecord(); ratingRecord.utcEventDate = CDRDate; ChargePacket tmpCP = new ChargePacket(); TimePacket tmpTZ1 = new TimePacket(); tmpTZ1.priceGroup = newPriceGroup1; tmpCP.addTimeZone(tmpTZ1); TimePacket tmpTZ2 = new TimePacket(); tmpTZ2.priceGroup = newPriceGroup2; tmpCP.addTimeZone(tmpTZ2); ratingRecord.addChargePacket(tmpCP); ratingRecord.setRUMValue("DUR", durationValue); return ratingRecord; } /** * Create a rating record initialised with the information necessary for * performing a rating. This simulates a record that has undergone time * splitting. * * @param CDRDate Date of the CDR * @param newPriceGroup1 The price group to use * @param durationValue The duration value to use * @return The record, ready to go */ private TestRatingRecord getNewRatingRecordDURTimeSplitBeatRounding(long CDRDate, String newPriceGroup1, String newPriceGroup2, int durationValue1, int durationValue2) { TestRatingRecord ratingRecord = new TestRatingRecord(); ratingRecord.utcEventDate = CDRDate; ChargePacket tmpCP = new ChargePacket(); tmpCP.timeSplitting = AbstractRUMTimeMatch.TIME_SPLITTING_CHECK_SPLITTING_BEAT_ROUNDING; TimePacket tmpTZ1 = new TimePacket(); tmpTZ1.priceGroup = newPriceGroup1; tmpTZ1.duration = durationValue1; tmpTZ1.totalDuration = durationValue1 + durationValue2; tmpCP.addTimeZone(tmpTZ1); TimePacket tmpTZ2 = new TimePacket(); tmpTZ2.priceGroup = newPriceGroup2; tmpTZ2.duration = durationValue2; tmpTZ2.totalDuration = durationValue1 + durationValue2; tmpCP.addTimeZone(tmpTZ2); ratingRecord.addChargePacket(tmpCP); ratingRecord.setRUMValue("DUR", durationValue1 + durationValue2); return ratingRecord; } /** * Create a rating record initialised with the information necessary for * performing a rating. This simulates a record that has undergone time * splitting. * * @param CDRDate Date of the CDR * @param newPriceGroup1 The price group to use * @param durationValue The duration value to use * @return The record, ready to go */ private TestRatingRecord getNewRatingRecordDURTimeSplitNoBeatRounding(long CDRDate, String newPriceGroup1, String newPriceGroup2, int durationValue1, int durationValue2) { TestRatingRecord ratingRecord = new TestRatingRecord(); ratingRecord.utcEventDate = CDRDate; ChargePacket tmpCP = new ChargePacket(); tmpCP.timeSplitting = AbstractRUMTimeMatch.TIME_SPLITTING_CHECK_SPLITTING; TimePacket tmpTZ1 = new TimePacket(); tmpTZ1.priceGroup = newPriceGroup1; tmpTZ1.duration = durationValue1; tmpTZ1.totalDuration = durationValue1 + durationValue2; tmpCP.addTimeZone(tmpTZ1); TimePacket tmpTZ2 = new TimePacket(); tmpTZ2.priceGroup = newPriceGroup2; tmpTZ2.duration = durationValue2; tmpTZ2.totalDuration = durationValue1 + durationValue2; tmpCP.addTimeZone(tmpTZ2); ratingRecord.addChargePacket(tmpCP); ratingRecord.setRUMValue("DUR", durationValue1 + durationValue2); return ratingRecord; } }