/* * Copyright (c) 2013 EMC Corporation * All Rights Reserved */ package com.emc.storageos.db.common; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.StringWriter; import javax.xml.bind.JAXBContext; import javax.xml.bind.Marshaller; import javax.xml.bind.Unmarshaller; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElements; import javax.xml.bind.annotation.XmlRootElement; import org.apache.commons.io.FileUtils; import org.junit.Assert; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.emc.storageos.db.common.diff.DbSchemasDiff; import com.emc.storageos.db.common.schema.DataObjectSchema; import com.emc.storageos.db.common.schema.DataPointSchema; import com.emc.storageos.db.common.schema.DbSchema; import com.emc.storageos.db.common.schema.DbSchemas; import com.emc.storageos.db.common.schema.TimeSeriesSchema; import com.emc.storageos.services.util.LoggingUtils; public class DbSchemaCheckerTest extends BaseDbSchemaCheckerTest { static { LoggingUtils.configureIfNecessary("dbchecker-log4j.properties"); } private static final Logger log = LoggerFactory.getLogger(DbSchemaCheckerTest.class); @XmlRootElement(name = "dbschemas") private static class SchemaUT { @XmlElements({ @XmlElement(name = "data_object_schema", type = DataObjectSchema.class), @XmlElement(name = "time_series_schema", type = TimeSeriesSchema.class), @XmlElement(name = "data_point_schema", type = DataPointSchema.class) }) public DbSchema schema; public SchemaUT() { } public SchemaUT(DbSchema schema) { this.schema = schema; } } @Test public void testSchemaConsistent() { StringWriter sw1 = new StringWriter(); StringWriter sw2 = new StringWriter(); SchemaUT schemaUT = new SchemaUT(srcSchema); try { JAXBContext jc = JAXBContext.newInstance(SchemaUT.class); Marshaller m = jc.createMarshaller(); m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, new Boolean(true)); m.marshal(schemaUT, sw1); m.marshal(schemaUT, sw2); Assert.assertEquals(sw1.getBuffer().toString(), sw2.getBuffer().toString()); } catch (Exception e) { log.error("testSchemaConsistent failed:", e); Assert.fail(); } finally { try { sw1.close(); sw2.close(); } catch (IOException e) { log.warn("IO close exception:{}", e); } } } @Test public void testSchemaCheckRoundTrip() { BufferedWriter writer = null; String schemaFile = FileUtils.getTempDirectoryPath() + "/.schema"; SchemaUT schemaUT = new SchemaUT(srcSchema); JAXBContext jc; try { File output = new File(schemaFile); writer = new BufferedWriter(new FileWriter(output)); jc = JAXBContext.newInstance(SchemaUT.class); Marshaller m = jc.createMarshaller(); m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); StringWriter sw = new StringWriter(); m.marshal(schemaUT, sw); writer.write(sw.toString()); } catch (Exception e) { log.error("testSchemaCheckRoundTrip failed:{}", e); Assert.fail(); } finally { try { if (writer != null) { writer.close(); } } catch (IOException e) { log.warn("IO close exception:{}", e); } } try { File input = new File(schemaFile); jc = JAXBContext.newInstance(DbSchemas.class); Unmarshaller um = jc.createUnmarshaller(); DbSchemas schemas = (DbSchemas) um.unmarshal(input); Assert.assertEquals(srcSchema, schemas.getSchemas().get(0)); } catch (Exception e) { log.error("testSchemaCheckRoundTrip failed:{}", e); Assert.fail(); } } @Test public void testNewClassAnnotation() { tgtSchema = new DataObjectSchema(NewClassAnnotation.class); // a little bit of hack tgtSchema.setType(srcSchema.getType()); tgtSchemas.addSchema(tgtSchema); DbSchemasDiff diff = new DbSchemasDiff(srcSchemas, tgtSchemas); // No new class annotation is allowed Assert.assertFalse(diff.isUpgradable()); Assert.assertTrue(diff.isChanged()); Assert.assertTrue(diff.getNewClasses().isEmpty()); Assert.assertTrue(diff.getNewFields().isEmpty()); Assert.assertFalse(diff.getNewClassAnnotations().isEmpty()); Assert.assertEquals(diff.getNewClassAnnotations().size(), 1); Assert.assertTrue(diff.getNewFieldAnnotations().isEmpty()); Assert.assertTrue(diff.getNewAnnotationValues().isEmpty()); } @Test public void testRemovedClassAnnotation() { tgtSchema = new DataObjectSchema(RemovedClassAnnotation.class); tgtSchema.setType(srcSchema.getType()); tgtSchemas.addSchema(tgtSchema); DbSchemasDiff diff = new DbSchemasDiff(srcSchemas, tgtSchemas); Assert.assertFalse(diff.isUpgradable()); Assert.assertTrue(diff.isChanged()); } @Test public void testRemovedFieldIndexAnnotation() { srcSchema = new DataObjectSchema(WithIndexAnnotation.class); srcSchema.setType(srcSchema.getType()); srcSchemas.addSchema(srcSchema); tgtSchema = new DataObjectSchema(WithRemovedIndexAnnotation.class); tgtSchema.setType(srcSchema.getType()); tgtSchemas.addSchema(tgtSchema); DbSchemasDiff diff = new DbSchemasDiff(srcSchemas, tgtSchemas); Assert.assertFalse(diff.isUpgradable()); Assert.assertTrue(diff.isChanged()); } @Test public void testNewClassAnnotationValue() { tgtSchema = new DataObjectSchema(NewClassAnnotationValue.class); tgtSchema.setType(srcSchema.getType()); tgtSchemas.addSchema(tgtSchema); DbSchemasDiff diff = new DbSchemasDiff(srcSchemas, tgtSchemas); Assert.assertFalse(diff.isUpgradable()); Assert.assertTrue(diff.isChanged()); } @Test public void testNewField() { tgtSchema = new DataObjectSchema(NewField.class); tgtSchema.setType(srcSchema.getType()); tgtSchemas.addSchema(tgtSchema); DbSchemasDiff diff = new DbSchemasDiff(srcSchemas, tgtSchemas); Assert.assertTrue(diff.isUpgradable()); Assert.assertTrue(diff.isChanged()); Assert.assertTrue(diff.getNewClasses().isEmpty()); Assert.assertFalse(diff.getNewFields().isEmpty()); Assert.assertEquals(diff.getNewFields().size(), 1); Assert.assertTrue(diff.getNewClassAnnotations().isEmpty()); Assert.assertTrue(diff.getNewFieldAnnotations().isEmpty()); Assert.assertTrue(diff.getNewAnnotationValues().isEmpty()); } @Test public void testRemovedField() { tgtSchema = new DataObjectSchema(RemovedField.class); tgtSchema.setType(srcSchema.getType()); tgtSchemas.addSchema(tgtSchema); DbSchemasDiff diff = new DbSchemasDiff(srcSchemas, tgtSchemas); Assert.assertFalse(diff.isUpgradable()); Assert.assertTrue(diff.isChanged()); } @Test public void testNewFieldType() { tgtSchema = new DataObjectSchema(NewFieldType.class); tgtSchema.setType(srcSchema.getType()); tgtSchemas.addSchema(tgtSchema); DbSchemasDiff diff = new DbSchemasDiff(srcSchemas, tgtSchemas); Assert.assertFalse(diff.isUpgradable()); Assert.assertTrue(diff.isChanged()); } @Test public void testNewFieldAnnotation() { tgtSchema = new DataObjectSchema(NewFieldAnnotation.class); tgtSchema.setType(srcSchema.getType()); tgtSchemas.addSchema(tgtSchema); DbSchemasDiff diff = new DbSchemasDiff(srcSchemas, tgtSchemas); Assert.assertTrue(diff.isUpgradable()); Assert.assertTrue(diff.isChanged()); Assert.assertTrue(diff.getNewClasses().isEmpty()); Assert.assertTrue(diff.getNewFields().isEmpty()); Assert.assertTrue(diff.getNewClassAnnotations().isEmpty()); Assert.assertFalse(diff.getNewFieldAnnotations().isEmpty()); Assert.assertEquals(diff.getNewFieldAnnotations().size(), 1); Assert.assertTrue(diff.getNewAnnotationValues().isEmpty()); } @Test public void testRemovedFieldAnnotation() { tgtSchema = new DataObjectSchema(RemovedFieldAnnotation.class); tgtSchema.setType(srcSchema.getType()); tgtSchemas.addSchema(tgtSchema); DbSchemasDiff diff = new DbSchemasDiff(srcSchemas, tgtSchemas); Assert.assertFalse(diff.isUpgradable()); Assert.assertTrue(diff.isChanged()); } @Test public void testNewFieldAnnotationValue() { tgtSchema = new DataObjectSchema(WithChangedAnnotationValue.class); tgtSchema.setType(srcSchema.getType()); tgtSchemas.addSchema(tgtSchema); DbSchemasDiff diff = new DbSchemasDiff(srcSchemas, tgtSchemas); Assert.assertFalse(diff.isUpgradable()); Assert.assertTrue(diff.isChanged()); } @Test public void testNewPermittedFieldAnnotation() { tgtSchema = new DataObjectSchema(NewPermittedFieldAnnotation.class); tgtSchema.setType(srcSchema.getType()); tgtSchemas.addSchema(tgtSchema); DbSchemasDiff diff = new DbSchemasDiff(srcSchemas, tgtSchemas); Assert.assertTrue(diff.isUpgradable()); Assert.assertTrue(diff.isChanged()); Assert.assertTrue(diff.getNewClasses().isEmpty()); Assert.assertTrue(diff.getNewFields().isEmpty()); Assert.assertTrue(diff.getNewClassAnnotations().isEmpty()); Assert.assertFalse(diff.getNewFieldAnnotations().isEmpty()); Assert.assertEquals(diff.getNewFieldAnnotations().size(), 1); Assert.assertTrue(diff.getNewAnnotationValues().isEmpty()); } @Test public void testNewNotPermittedFieldAnnotation() { tgtSchema = new DataObjectSchema(NewNotPermittedFieldAnnotation.class); tgtSchema.setType(srcSchema.getType()); tgtSchemas.addSchema(tgtSchema); DbSchemasDiff diff = new DbSchemasDiff(srcSchemas, tgtSchemas); Assert.assertFalse(diff.isUpgradable()); Assert.assertTrue(diff.isChanged()); } @Test public void testDuplicateCF() { tgtSchema = new DataObjectSchema(DuplicateCF1.class); tgtSchema.setType(srcSchema.getType()); tgtSchemas.addSchema(tgtSchema); srcSchema = new DataObjectSchema(classUT2.class); srcSchemas.addSchema(srcSchema); tgtSchema = new DataObjectSchema(DuplicateCF2.class); tgtSchema.setType(srcSchema.getType()); tgtSchemas.addSchema(tgtSchema); tgtSchemas.addSchema(srcSchema); DbSchemasDiff diff = new DbSchemasDiff(srcSchemas, tgtSchemas); Assert.assertFalse(diff.isUpgradable()); Assert.assertTrue(diff.isChanged()); Assert.assertFalse(diff.getSchemaCT().getDuplicateList().isEmpty()); } @Test public void testMultipleIllegalUpgradeChanges() { srcSchema = new DataObjectSchema(WithIndexAnnotation.class); srcSchema.setType(srcSchema.getType()); srcSchemas.addSchema(srcSchema); srcSchema = new DataObjectSchema(ClassUT7.class); srcSchema.setType(srcSchema.getType()); srcSchemas.addSchema(srcSchema); srcSchema = new DataObjectSchema(ClassUT4.class); srcSchema.setType(srcSchema.getType()); srcSchemas.addSchema(srcSchema); srcSchema = new DataObjectSchema(ClassUT5.class); srcSchema.setType(srcSchema.getType()); srcSchemas.addSchema(srcSchema); tgtSchema = new DataObjectSchema(WithRemovedIndexAnnotation.class); tgtSchema.setType(srcSchema.getType()); tgtSchemas.addSchema(tgtSchema); tgtSchema = new DataObjectSchema(ClassUT3.class); tgtSchema.setType(srcSchema.getType()); tgtSchemas.addSchema(tgtSchema); tgtSchema = new DataObjectSchema(ClassUT6.class); tgtSchema.setType(srcSchema.getType()); tgtSchemas.addSchema(tgtSchema); DbSchemasDiff diff = new DbSchemasDiff(srcSchemas, tgtSchemas); Assert.assertFalse(diff.isUpgradable()); Assert.assertTrue(diff.isChanged()); } @Test public void testRemoveNamedRelationIndex() { srcSchema = new DataObjectSchema(WithNamedRelationIndex.class); srcSchema.setType(srcSchema.getType()); srcSchemas.addSchema(srcSchema); tgtSchema = new DataObjectSchema(WithRemovedIndexAnnotation.class); tgtSchema.setType(srcSchema.getType()); tgtSchemas.addSchema(tgtSchema); DbSchemasDiff diff = new DbSchemasDiff(srcSchemas, tgtSchemas); Assert.assertFalse(diff.isUpgradable()); Assert.assertTrue(diff.isChanged()); } @Test public void testDataObjectWithInvalidDependencyCheck() { log.info("testDataObjectWithInvalidDependencyCheck() started..."); DataObjectScanner scanner = new DataObjectScanner(); String[] packages = new String[] { "com.emc.storageos.db.common.model" }; scanner.setPackages(packages); boolean pass = true; try { scanner.init(); log.info("testDataObjectWithInvalidDependencyCheck() passed."); } catch (Exception ex) { // do something log.info("testDataObjectWithInvalidDependencyCheck(), dependency check failed -> " + ex.getMessage()); pass = false; } Assert.assertFalse(pass); } @Test public void testDataObjectWithValidDependencyCheck() { log.info("testDataObjectWithValidDependencyCheck() started..."); DataObjectScanner scanner = new DataObjectScanner(); String[] packages = new String[] { "com.emc.storageos.db.common.model2" }; scanner.setPackages(packages); boolean pass = true; try { scanner.init(); log.info("testDataObjectWithValidDependencyCheck() passed."); } catch (Exception ex) { // do something log.info("testDataObjectWithValidDependencyCheck(), dependency check failed -> " + ex.getMessage()); pass = false; } Assert.assertTrue(pass); } @Test public void testGeoNewAnnotationOnExistingField() { DbSchema srcGeoSchema = new DataObjectSchema(GeoClassUT.class); srcSchemas.addSchema(srcGeoSchema); tgtSchema = new DataObjectSchema(GeoNewAnnotationOnExistingField.class); tgtSchema.setType(srcSchema.getType()); tgtSchemas.addSchema(tgtSchema); tgtSchemas.addSchema(srcSchema); DbSchemasDiff diff = new DbSchemasDiff(srcSchemas, tgtSchemas); // Adding index on existing field of Geo object is not allowed Assert.assertFalse(diff.isUpgradable()); Assert.assertTrue(diff.isChanged()); } @Test public void testGeoNewAnnotationOnNewField() { DbSchema srcGeoSchema = new DataObjectSchema(GeoClassUT.class); srcSchemas.addSchema(srcGeoSchema); tgtSchema = new DataObjectSchema(GeoNewField.class); tgtSchema.setType(srcSchema.getType()); tgtSchemas.addSchema(tgtSchema); tgtSchemas.addSchema(srcSchema); DbSchemasDiff diff = new DbSchemasDiff(srcSchemas, tgtSchemas); // Adding index on new field of Geo object is allowed Assert.assertTrue(diff.isUpgradable()); Assert.assertTrue(diff.isChanged()); } @Test public void testGeoNewAnnotationOnNewCF() { DbSchema srcGeoSchema = new DataObjectSchema(GeoClassUT.class); srcSchemas.addSchema(srcGeoSchema); tgtSchemas.addSchema(srcGeoSchema); tgtSchema = new DataObjectSchema(GeoNewCF.class); tgtSchema.setType(srcSchema.getType()); tgtSchemas.addSchema(tgtSchema); tgtSchemas.addSchema(srcSchema); DbSchemasDiff diff = new DbSchemasDiff(srcSchemas, tgtSchemas); // Adding index of new Geo object is allowed Assert.assertTrue(diff.isUpgradable()); Assert.assertTrue(diff.isChanged()); } }