/******************************************************************************* * ALMA - Atacama Large Millimeter Array * Copyright (c) ESO - European Southern Observatory, 2011 * (in the framework of the ALMA collaboration). * All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *******************************************************************************/ package alma.acs.tmcdb; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; import java.sql.Connection; import java.sql.SQLException; import java.sql.Statement; import java.util.Date; import java.util.Iterator; import java.util.List; import java.util.logging.Logger; import junit.framework.TestCase; import org.hibernate.Criteria; import org.hibernate.Query; import org.hibernate.QueryException; import org.hibernate.criterion.Restrictions; import org.hibernate.jdbc.Work; import alma.acs.logging.ClientLogManager; import alma.acs.logging.level.AcsLogLevelDefinition; import com.cosylab.cdb.jdal.hibernate.HibernateUtil; import com.cosylab.cdb.jdal.hibernate.HibernateUtil.HibernateUtilException; import com.cosylab.cdb.jdal.logging.AcsLoggerHelper; public class TestPojosPersistence extends TestCase { private final String CREATE_TMCDB_SWCORE = System.getenv("ACSDATA") + "/config/DDL/hsqldb/TMCDB_swconfigcore/CreateHsqldbTables.sql"; private final String CREATE_TMCDB_SWEXT = System.getenv("ACSDATA") + "/config/DDL/hsqldb/TMCDB_swconfigext/CreateHsqldbTables.sql"; private final String DROP_TMCDB_SWCORE = System.getenv("ACSDATA") + "/config/DDL/hsqldb/TMCDB_swconfigcore/DropAllTables.sql"; private final String DROP_TMCDB_SWEXT = System.getenv("ACSDATA") + "/config/DDL/hsqldb/TMCDB_swconfigext/DropAllTables.sql"; private final static int DEFAULT_BUF_LEN = 64 * 1024; private final String COMPUTER_NAME = "eva"; private final String COMPUTER_NETNAME = "eva.eso.org"; private final String COMPUTER_LOCATION = "A033"; private final boolean COMPUTER_RT = true; private final boolean COMPUTER_DISKLESS = false; private Logger logger; private HibernateUtil hibernateUtil; // private SessionFactory _sessionFactory; protected void setUp() throws Exception { System.out.println("\n---------------- " + getName() + " ---------------\n"); String loggerName = getName(); // name of junit test AcsLoggerHelper acsLoggerHelper = AcsLoggerHelper.getInstance(); acsLoggerHelper.setLoggerName(loggerName); acsLoggerHelper.setDefaultLogLevels(AcsLogLevelDefinition.INFO, AcsLogLevelDefinition.INFO); logger = AcsLoggerHelper.getInstance().getSharedLogger(); logger.info("Example test log"); acsLoggerHelper.setHibernateLogLevels(AcsLogLevelDefinition.INFO, AcsLogLevelDefinition.TRACE); acsLoggerHelper.setHibernateSqlLogLevels(AcsLogLevelDefinition.TRACE, AcsLogLevelDefinition.TRACE); // ACSLoggerFactory hibernateLoggerFactory = ((ACSLoggerFactory)StaticLoggerBinder.getSingleton().getLoggerFactory()); // hibernateLoggerFactory.getLogger("blabla").info("Greetings from your hibernate logger"); hibernateUtil = HibernateUtil.getInstance(logger); hibernateUtil.setConfiguration(new org.hibernate.cfg.Configuration().configure("test-hibernate.cfg.xml")); hibernateUtil.getSessionFactory().openSession(); } protected void tearDown() throws Exception { // null the various static logger references; otherwise junit will not create new loggers in subsequent setUp HibernateUtil.clearInstance(); AcsLoggerHelper.getInstance().shutdown(); ClientLogManager.getAcsLogManager().shutdown(true); } public void testCreateDrop() throws Exception { createDB(); dropDB(); } public void testSimpleSave() throws Exception { createDB(); try { ComponentType componentType = new ComponentType(); componentType.setIDL("IDL:alma/samp/Samp.idl:1.0"); // The fact that this first simple save works // implies that ID generation for HSQLDB and Oracle // is working fine hibernateUtil.beginTransaction(); hibernateUtil.getSession().save(componentType); hibernateUtil.commitTransaction(); TMCDBVersion tmcdbVersion = new TMCDBVersion(); tmcdbVersion.setDBDate("12.01.10"); tmcdbVersion.setDBName("TMCDB"); tmcdbVersion.setDBVersion("1.2.3"); try{ hibernateUtil.beginTransaction(); hibernateUtil.getSession().save(tmcdbVersion); hibernateUtil.commitTransaction(); fail("Duplicated PK allowed!"); // Should fail, TMCDB already contains a "TMCDB" record } catch(HibernateUtilException e) { hibernateUtil.rollbackTransaction(); } Configuration config = new Configuration(); config.setActive(true); config.setConfigurationName("rtobarConfig"); config.setCreationTime(new Date()); config.setFullName("Testing configuration"); config.setDescription("Configuration used for testing purposes"); hibernateUtil.beginTransaction(); hibernateUtil.getSession().save(config); hibernateUtil.commitTransaction(); NetworkDevice networkDevice = new NetworkDevice(); networkDevice.setName(COMPUTER_NAME); networkDevice.setNetworkName(COMPUTER_NETNAME); networkDevice.setPhysicalLocation(COMPUTER_LOCATION); networkDevice.setConfiguration(null); try{ hibernateUtil.beginTransaction(); hibernateUtil.getSession().save(networkDevice); hibernateUtil.commitTransaction(); fail("networkDevice's configuration is null, FK is beign violated and shouldn't be saved"); } catch(Exception e) { hibernateUtil.closeSession(); } networkDevice = new NetworkDevice(); networkDevice.setName(COMPUTER_NAME); networkDevice.setNetworkName(COMPUTER_NETNAME); networkDevice.setPhysicalLocation(COMPUTER_LOCATION); networkDevice.setConfiguration(config); hibernateUtil.beginTransaction(); hibernateUtil.getSession().save(networkDevice); hibernateUtil.commitTransaction(); // Testing loggingConfig, which only states GENERATED in the model LoggingConfig loggingConfig = new LoggingConfig(); loggingConfig.setMinLogLevelDefault((byte)0x01); loggingConfig.setMinLogLevelLocalDefault((byte)0x01); loggingConfig.setCentralizedLogger(""); loggingConfig.setDispatchPacketSize((byte)0x01); loggingConfig.setImmediateDispatchLevel((byte)0x01); loggingConfig.setFlushPeriodSeconds((byte)0x01); loggingConfig.setMaxLogQueueSize(0); hibernateUtil.beginTransaction(); hibernateUtil.getSession().save(loggingConfig); hibernateUtil.commitTransaction(); } finally { dropDB(); } } @SuppressWarnings("unchecked") public void testXmlTypeSave() throws Exception { createDB(); try { ComponentType componentType = new ComponentType(); componentType.setIDL("IDL:alma/xmltype/XML.idl:1.0"); hibernateUtil.beginTransaction(); hibernateUtil.getSession().save(componentType); hibernateUtil.commitTransaction(); Configuration config = new Configuration(); config.setActive(true); config.setConfigurationName("rtobarConfig"); config.setCreationTime(new Date()); config.setFullName("Testing configuration"); config.setDescription("Configuration used for testing purposes"); hibernateUtil.beginTransaction(); hibernateUtil.getSession().save(config); hibernateUtil.commitTransaction(); Component comp; String url = hibernateUtil.getConfiguration().getProperty("hibernate.connection.url"); if( url.contains("oracle") ) { comp = createTrascientComponent(componentType, config); try { hibernateUtil.beginTransaction(); hibernateUtil.getSession().save(comp); hibernateUtil.commitTransaction(); fail("XMLDoc is not really XML, should fail with Oracle"); // No valid XML, should fail with Oracle } catch (Exception e) { hibernateUtil.closeSession(); } comp = createTrascientComponent(componentType, config); comp.setComponentName("component3"); comp.setXMLDoc(""); try { hibernateUtil.beginTransaction(); hibernateUtil.getSession().save(comp); hibernateUtil.commitTransaction(); fail("Emtpy string is not valid XML"); } catch(Exception e){ hibernateUtil.closeSession(); } } comp = createTrascientComponent(componentType, config); comp.setXMLDoc("<?xml version='1.0' encoding='ISO-8859-1'?>\n<CorrCanMngr xmlns=\"urn:schemas-cosylab-com:CorrCanMngr:1.0\" xmlns:baci=\"urn:schemas-cosylab-com:BACI:1.0\" xmlns:cdb=\"urn:schemas-cosylab-com:CDB:1.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" id=\"0\" resetWait=\"30\"></CorrCanMngr>"); hibernateUtil.beginTransaction(); try { hibernateUtil.getSession().save(comp); } catch(Exception e) { e.printStackTrace(); } hibernateUtil.commitTransaction(); comp = createTrascientComponent(componentType, config); comp.setComponentName("component2"); comp.setXMLDoc(null); hibernateUtil.beginTransaction(); hibernateUtil.getSession().save(comp); // Should not fail with null XMLDoc hibernateUtil.commitTransaction(); for(Component component: (List<Component>)hibernateUtil.getList(Component.class)) component.getXMLDoc(); } finally { dropDB(); } } @SuppressWarnings("unchecked") public void testSaveInheritance() throws Exception { createDB(); try { createConfigurationComputerAndTwoNetworkDevices(); // Now we get all NetworkDevice's from DB (we should get two) List<NetworkDevice> nDevices = hibernateUtil.getList(NetworkDevice.class); assertEquals(3, nDevices.size()); // Found the 2 objects :) boolean found = false; for (Iterator<NetworkDevice> iterator = nDevices.iterator(); iterator.hasNext();) { NetworkDevice nd = (NetworkDevice)iterator.next(); if( nd instanceof Computer ) { Computer comp = (Computer)nd; assertEquals( comp.getName(), COMPUTER_NAME); assertEquals( comp.getRealTime().booleanValue(), COMPUTER_RT); assertEquals( comp.getNetworkName(), COMPUTER_NETNAME); assertEquals( comp.getProcessorType(), ComputerProcessorType.SMP); assertEquals( comp.getPhysicalLocation(), COMPUTER_LOCATION); assertEquals( comp.getDiskless().booleanValue(), COMPUTER_DISKLESS); found = true; break; } } assertTrue(found); } finally { dropDB(); } } private void createConfigurationComputerAndTwoNetworkDevices() throws Exception { Configuration config = new Configuration(); config.setActive(true); config.setConfigurationName("rtobarConfig"); config.setCreationTime(new Date()); config.setFullName("Testing configuration"); config.setDescription("Configuration used for testing purposes"); Computer computer = new Computer(); computer.setName(COMPUTER_NAME); computer.setRealTime(COMPUTER_RT); computer.setNetworkName(COMPUTER_NETNAME); computer.setProcessorType(ComputerProcessorType.SMP); computer.setPhysicalLocation(COMPUTER_LOCATION); computer.setDiskless(COMPUTER_DISKLESS); computer.setConfiguration(config); hibernateUtil.beginTransaction(); hibernateUtil.getSession().save(config); hibernateUtil.getSession().save(computer); hibernateUtil.commitTransaction(); NetworkDevice networkDevice = new NetworkDevice(); networkDevice.setName("wall-e"); networkDevice.setNetworkName("wall-e.eso.org"); networkDevice.setPhysicalLocation("A033-2"); networkDevice.setConfiguration(config); hibernateUtil.beginTransaction(); hibernateUtil.getSession().save(networkDevice); hibernateUtil.commitTransaction(); networkDevice = new NetworkDevice(); networkDevice.setName("wall-e"); networkDevice.setNetworkName("wall-e.alma.cl"); networkDevice.setPhysicalLocation("A033-2"); networkDevice.setConfiguration(config); hibernateUtil.beginTransaction(); hibernateUtil.getSession().save(networkDevice); hibernateUtil.commitTransaction(); } public void testCriteriaAPI() throws Exception { createDB(); try { createConfigurationComputerAndTwoNetworkDevices(); Configuration config = (Configuration)hibernateUtil.getList(Configuration.class).iterator().next(); assertNotNull(config); // Now we test that using the criteria API we can find our objects Criteria c = hibernateUtil.getSession().createCriteria(NetworkDevice.class); c.add( Restrictions.eq("name", "wall-e") ); assertEquals(2, c.list().size()); c = hibernateUtil.getSession().createCriteria(NetworkDevice.class); c.add( Restrictions.eq("name", "wall-e") ); c.add( Restrictions.eq("networkName", "wall-e.eso.org") ); assertEquals(1, c.list().size()); c = hibernateUtil.getSession().createCriteria(NetworkDevice.class); c.add( Restrictions.eq("configuration", config) ); assertEquals(3, c.list().size()); c = hibernateUtil.getSession().createCriteria(Configuration.class); c.add( Restrictions.eq("configurationName", "rtobarConfig")); c.add( Restrictions.lt("creationTime", new Date())); assertEquals(1, c.list().size()); try { c = hibernateUtil.getSession().createCriteria(Configuration.class); c.add( Restrictions.eq("configuratioName", "rtobarConfig")); // typo: should be configurationName c.list(); fail("Should fail, property 'configuratioName' doesn't exist for Configuration objects"); } catch(QueryException e) { } } finally { dropDB(); } } public void testHQL() throws Exception { createDB(); try { createConfigurationComputerAndTwoNetworkDevices(); Configuration config = (Configuration)hibernateUtil.getList(Configuration.class).iterator().next(); assertNotNull(config); // Now we test that using HQL queries Query q = hibernateUtil.getSession().createQuery("from NetworkDevice as nd where nd.name = ?"); q.setParameter(0, "wall-e"); assertEquals(2, q.list().size()); q = hibernateUtil.getSession().createQuery("from NetworkDevice as nd where nd.name = ? and nd.networkName = ?"); q.setParameter( 0, "wall-e"); q.setParameter(1, "wall-e.eso.org" ); assertEquals(1, q.list().size()); q = hibernateUtil.getSession().createQuery("from NetworkDevice as nd where nd.configuration = ?"); q.setParameter( 0, config ); assertEquals(3, q.list().size()); q = hibernateUtil.getSession().createQuery("from Configuration as conf where conf.configurationName = ? and creationTime < ?"); q.setParameter(0, "rtobarConfig"); q.setParameter(1, new Date()); assertEquals(1, q.list().size()); try { // typo: should be configurationName q = hibernateUtil.getSession().createQuery("from Configuration as conf where conf.configuratioName = ?"); q.setParameter(0, "rtobarConfig"); q.list(); fail("Should fail, property 'configuratioName' doesn't exist for Configuration objects"); } catch(QueryException e) { } } finally { dropDB(); } } public void testShutdown() throws HibernateUtilException { String url = hibernateUtil.getConfiguration().getProperty("hibernate.connection.url"); if( url.contains("file") ) { hibernateUtil.beginTransaction(); hibernateUtil.getSession().doWork( new Work() { public void execute(Connection conn) throws SQLException { runScript("shutdown", conn); } }); hibernateUtil.commitTransaction(); } } private Component createTrascientComponent(ComponentType componentType, Configuration config) { Component comp = new Component(); comp.setCode("CodeImplClass"); comp.setConfiguration(config); comp.setXMLDoc("Something that is not XML"); comp.setRealTime(true); comp.setImplLang(ImplLangEnum.JAVA); comp.setIsAutostart(true); comp.setIsDefault(false); comp.setIsControl(true); comp.setPath("/path"); comp.setKeepAliveTime(0); comp.setComponentName("rtobarComponent"); comp.setComponentType(componentType); comp.setMinLogLevel((byte)-1); comp.setMinLogLevelLocal((byte)-1); return comp; } private void createDB() throws HibernateUtilException { String url = hibernateUtil.getConfiguration().getProperty("hibernate.connection.url"); if( url.contains("oracle") ) { return; } hibernateUtil.beginTransaction(); hibernateUtil.getSession().doWork( new Work() { public void execute(Connection conn) throws SQLException { conn.setAutoCommit(true); runScriptFile(CREATE_TMCDB_SWCORE, conn); runScriptFile(CREATE_TMCDB_SWEXT, conn); } }); hibernateUtil.commitTransaction(); } private void dropDB() throws HibernateUtilException { String url = hibernateUtil.getConfiguration().getProperty("hibernate.connection.url"); if( !url.contains("mem") ) { hibernateUtil.beginTransaction(); hibernateUtil.getSession().doWork( new Work() { public void execute(Connection conn) throws SQLException { conn.setAutoCommit(true); runScript("delete from event;" + "delete from eventchannel;" + "delete from baciproperty;" + "delete from snmptrapsink;" + "delete from powerstripsocket;" + "delete from networkpowerstrip;" + "delete from networkdevicesnmpconfig;" + "delete from component;" + "delete from componenttype;" + "delete from namedloggerconfig;" + "delete from loggingconfig;" + "delete from eventchannel;" + "delete from computer;" + "delete from networkdevice;" + "delete from configuration", conn); } }); hibernateUtil.commitTransaction(); return; } hibernateUtil.beginTransaction(); hibernateUtil.getSession().doWork( new Work() { public void execute(Connection conn) throws SQLException { conn.setAutoCommit(true); runScriptFile(DROP_TMCDB_SWEXT, conn); runScriptFile(DROP_TMCDB_SWCORE, conn); } }); hibernateUtil.commitTransaction(); } private void runScriptFile( String script, Connection conn ) throws SQLException { String sql = ""; try { // try to get hold of the script InputStream is = getResourceStream(script); sql = fileToString(new InputStreamReader(is)); } catch (IOException e) { // convert to runtime, as this is only used for testing throw new RuntimeException(e); } runScript(sql, conn); } private void runScript( String sql, Connection conn ) throws SQLException { Statement stmt = conn.createStatement(); String[] statements = sql.split( ";", -1 ); for( int i = 0; i < statements.length; i++ ) { String statement = statements[i].trim(); if( statement.length() == 0 ) { // skip empty lines continue; } stmt.execute( statement ); } } private InputStream getResourceStream(String pathname) throws IOException { InputStream s = null; // this is the stream we return // Look for the resource on the file system // ----------------------------------------- File f = new File( pathname ); s = new FileInputStream( f ); return s; } private String fileToString( Reader reader ) throws IOException { BufferedReader br = new BufferedReader( reader ); StringBuffer sb = new StringBuffer(); char[] buff = new char[DEFAULT_BUF_LEN]; while( br.ready() ) { int nread = br.read( buff, 0, buff.length ); if( nread <= 0 ) { break; } sb.append( buff, 0, nread ); } br.close(); return sb.toString(); } }