mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-07 17:49:17 +00:00
Merged HEAD-BUG-FIX (5.0/Cloud) to HEAD (4.3/Cloud)
71594: Merged V4.2-BUG-FIX (4.2.3) to HEAD-BUG-FIX (4.3/Cloud) 70332: Merged V4.1-BUG-FIX (4.1.9) to V4.2-BUG-FIX (4.2.3) 70292: Merged DEV to V4.1-BUG-FIX (4.1.9) 60077: Created branch for MNT-10067 work. 60101: MNT-10067: first commit of a generic SQL script runner. Very rough and ready extraction of SchemaBootstrap SQL script execution functionality. Will serve as the basis for the implementation of MNT-10067. 60147: MNT-10067: added tests for "dialect" placeholder resolution, including overriding of dialects. 60180: MNT-10067: exception thrown when unable to find SQL script to execute 60187: MNT-10067: renamed ScriptExecutor to ScriptExecutorImpl to make way for an interface definition. 60188: MNT-10067: introduced a ScriptExecutor interface. 60189: MNT-10067: renamed ScriptExecutorTest 60190: MNT-10067: added ScriptExecutorImplIntegrationTest to repo test suite. 60194: MNT-10067: a very simple initial implementation of a SQL script runner capable of running multiple scripts in a given directory. 60195: MNT-10067: added integration test for ScriptBundleExecutorImpl. 60196: MNT-10067: moved ScriptBundleExecutorImplTest to correct source tree. 60197: MNT-10067: added ScriptBundleExecutorImplIntegrationTest to repo test suite. 60263: MNT-10067: ScriptBundleExecutor(Impl) now stops executing the main batch of scripts upon failure and runs a post-script. 60459: MNT-10067: minor change to test data to avoid implying that ScriptBundleExecutor.exec(String, String...) has an always-run final script. 60482: MNT-10067: added integration test for ScriptBundleExecutor.execWithPostScript() 60483: MNT-10067: committed missing files from r60482 60488: MNT-10067: set appropriate log levels for log4j 60620: MNT-10067: added alf_props_xxx clean-up script. 60623: MNT-10067: minor tidy up of ScriptExecutorImpl (tidy imports, group fields at top of class) 60625: MNT-10067: further tidy up ScriptExecutorImpl (removed redundant constants, made externally unused public constant private) 60629: MNT-10067: fix tests broken by introduction of scriptExecutor bean in production code. 60662: MNT-10067: added tests to check deletion of doubles, serializables and dates. 61378: MNT-10067 : Cleanup alf_prop_XXX data Added MySQL, Oracle DB, MS SQL Server and IBM DB2 scripts. 63371: MNT-10067: removed the vacuum and analyze statements from the postgresql script. 63372: MNT-10067: replaced begin and commit statements (PostgreSQL script only) with --BEGIN TXN and --END TXN, handled by the script executor. 63568: MNT-10067 : Cleanup alf_prop_XXX data Added start and end transaction marks to the scripts. 64115: MNT-10067: added Quartz job that by default doesn't fire until 2099 and can be manually invoked over JMX. 64223: MNT-10067: improved testing for AuditDAOTest and added PropertyValueDAOTest 64685: MNT-10067: added AttributeServiceTest 65796: MNT-10067 : Cleanup alf_prop_XXX data Implemented a performance test. 65983: MNT-10067 : Cleanup alf_prop_XXX data Reworked the MySQL script. Added time measurements for entry creation. 66116: MNT-10067 : Cleanup alf_prop_XXX data For MySQL: 1) Renamed temp tables. 2) Split the script into execution and cleanup of temp tables parts. 67023: MNT-10067 : Cleanup alf_prop_XXX data Modified MySQL script to skip null values from alf_prop_unique_ctx.prop1_id. 67199: MNT-10067 : Cleanup alf_prop_XXX data Implemented the latest changes of the script for other DB flavors. Removed the MS SQL Server transaction marks. 67763: MNT-10067 : Cleanup alf_prop_XXX data Removed unnecessary temporary index dropping. Added additional cleanup before main script execution. 68710: MNT-10067 : Cleanup alf_prop_XXX data Added batch logging. Moved clearCaches() statement in PropertyValueDAOImpl.cleanupUnusedValues() to finally block. 68711: MNT-10067 : Cleanup alf_prop_XXX data Added batching for MySQL script. 69602: MNT-10067 : Cleanup alf_prop_XXX data Updated scripts for all DB flavors with batching. 69768: MNT-10067 : Cleanup alf_prop_XXX data Fixed failing ScriptBundleExecutorImplIntegrationTest and ScriptExecutorImplIntegrationTest. 70058: Sync with latest changes in V4.1-BUG-FIX. git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@74691 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -419,6 +419,8 @@ public class Repository01TestSuite extends TestSuite
|
||||
suite.addTest(new JUnit4TestAdapter(org.alfresco.util.CronTriggerBeanSystemTest.class));
|
||||
suite.addTest(new JUnit4TestAdapter(org.alfresco.filesys.auth.cifs.CifsAuthenticatorKerberosTest.class));
|
||||
suite.addTest(new JUnit4TestAdapter(org.alfresco.filesys.auth.cifs.CifsAuthenticatorPassthruTest.class));
|
||||
suite.addTest(new JUnit4TestAdapter(org.alfresco.repo.domain.schema.script.ScriptExecutorImplIntegrationTest.class));
|
||||
suite.addTest(new JUnit4TestAdapter(org.alfresco.repo.domain.schema.script.ScriptBundleExecutorImplIntegrationTest.class));
|
||||
}
|
||||
|
||||
static void tests65(TestSuite suite)
|
||||
|
@@ -20,13 +20,18 @@ package org.alfresco.repo.attributes;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.alfresco.repo.domain.propval.PropValGenerator;
|
||||
import org.alfresco.repo.domain.propval.PropertyValueDAO;
|
||||
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
|
||||
import org.alfresco.service.cmr.attributes.AttributeService;
|
||||
import org.alfresco.service.cmr.attributes.AttributeService.AttributeQueryCallback;
|
||||
import org.alfresco.util.ApplicationContextHelper;
|
||||
import org.alfresco.util.Pair;
|
||||
import org.apache.commons.lang.mutable.MutableInt;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
|
||||
@@ -47,12 +52,14 @@ public class AttributeServiceTest extends TestCase
|
||||
|
||||
private ApplicationContext ctx;
|
||||
private AttributeService attributeService;
|
||||
private PropertyValueDAO propertyValueDAO;
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception
|
||||
{
|
||||
ctx = ApplicationContextHelper.getApplicationContext();
|
||||
attributeService = (AttributeService) ctx.getBean("AttributeService");
|
||||
propertyValueDAO = (PropertyValueDAO) ctx.getBean("propertyValueDAO");
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -132,4 +139,57 @@ public class AttributeServiceTest extends TestCase
|
||||
assertEquals(2, results.size());
|
||||
assertEquals(2, counter.getValue());
|
||||
}
|
||||
|
||||
public void testRemoveOrphanedProps()
|
||||
{
|
||||
final Serializable[] stringKey = new String[] { "z", "q", "string" };
|
||||
final Serializable[] doubleKey = new String[] { "z", "q", "double" };
|
||||
final Serializable[] dateKey = new String[] { "z", "q", "date" };
|
||||
|
||||
// Make sure there's nothing left from previous failed test runs etc.
|
||||
attributeService.removeAttributes(stringKey);
|
||||
attributeService.removeAttributes(doubleKey);
|
||||
attributeService.removeAttributes(dateKey);
|
||||
|
||||
final PropValGenerator valueGen = new PropValGenerator(propertyValueDAO);
|
||||
|
||||
// Create some values
|
||||
final String stringValue = valueGen.createUniqueString();
|
||||
attributeService.createAttribute(stringValue, stringKey);
|
||||
|
||||
final Double doubleValue = valueGen.createUniqueDouble();
|
||||
attributeService.createAttribute(doubleValue, doubleKey);
|
||||
|
||||
final Date dateValue = valueGen.createUniqueDate();
|
||||
attributeService.createAttribute(dateValue, dateKey);
|
||||
|
||||
// Remove the properties, potentially leaving oprhaned prop values.
|
||||
attributeService.removeAttributes(stringKey);
|
||||
attributeService.removeAttributes(doubleKey);
|
||||
attributeService.removeAttributes(dateKey);
|
||||
|
||||
// Check there are some persisted values to delete, otherwise there is no
|
||||
// need to run the cleanup script in the first place.
|
||||
assertEquals(stringValue, propertyValueDAO.getPropertyValue(stringValue).getSecond());
|
||||
assertEquals(doubleValue, propertyValueDAO.getPropertyValue(doubleValue).getSecond());
|
||||
assertEquals(dateValue, propertyValueDAO.getPropertyValue(dateValue).getSecond());
|
||||
|
||||
// Run the cleanup script - should remove the orphaned values.
|
||||
propertyValueDAO.cleanupUnusedValues();
|
||||
|
||||
// Check that the cleanup script removed the orphaned values.
|
||||
assertPropDeleted(propertyValueDAO.getPropertyValue(stringValue));
|
||||
assertPropDeleted(propertyValueDAO.getPropertyValue(doubleValue));
|
||||
assertPropDeleted(propertyValueDAO.getPropertyValue(dateValue));
|
||||
}
|
||||
|
||||
private void assertPropDeleted(Pair<Long, ?> value)
|
||||
{
|
||||
if (value != null)
|
||||
{
|
||||
String msg = String.format("Property value [%s=%s] should have been deleted by cleanup script.",
|
||||
value.getSecond().getClass().getSimpleName(), value.getSecond());
|
||||
fail(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2014 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.alfresco.repo.attributes;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import org.alfresco.repo.domain.propval.PropertyValueDAO;
|
||||
import org.alfresco.util.ApplicationContextHelper;
|
||||
import org.alfresco.util.CronTriggerBean;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.quartz.JobDetail;
|
||||
import org.quartz.SchedulerException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
|
||||
import com.ibm.icu.util.Calendar;
|
||||
|
||||
/**
|
||||
* Integration tests for the {@link PropTablesCleanupJob} class.
|
||||
*
|
||||
* @author Matt Ward
|
||||
*/
|
||||
public class PropTablesCleanupJobIntegrationTest
|
||||
{
|
||||
private static ApplicationContext ctx;
|
||||
private CronTriggerBean jobTrigger;
|
||||
|
||||
@BeforeClass
|
||||
public static void setUpClass()
|
||||
{
|
||||
ctx = ApplicationContextHelper.getApplicationContext();
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception
|
||||
{
|
||||
jobTrigger = ctx.getBean("propTablesCleanupTrigger", CronTriggerBean.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkJobWillNeverRunByDefault() throws Exception
|
||||
{
|
||||
Date fireTime = jobTrigger.getTrigger().getFireTimeAfter(new Date());
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
|
||||
// Far into the future, we count this as never.
|
||||
calendar.setTime(fireTime);
|
||||
assertEquals(2099, calendar.get(Calendar.YEAR));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkJobDetails()
|
||||
{
|
||||
JobDetail jobDetail = jobTrigger.getJobDetail();
|
||||
assertEquals(PropTablesCleanupJob.class, jobDetail.getJobClass());
|
||||
assertTrue("JobDetail did not contain PropertyValueDAO reference",
|
||||
jobDetail.getJobDataMap().get("propertyValueDAO") instanceof PropertyValueDAO);
|
||||
}
|
||||
}
|
@@ -0,0 +1,63 @@
|
||||
package org.alfresco.repo.attributes;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import org.alfresco.repo.domain.propval.PropertyValueDAO;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.quartz.JobDetail;
|
||||
import org.quartz.JobExecutionContext;
|
||||
import org.quartz.JobExecutionException;
|
||||
|
||||
|
||||
/**
|
||||
* Tests for the {@link PropTablesCleanupJob} class.
|
||||
*
|
||||
* @author Matt Ward
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class PropTablesCleanupJobTest
|
||||
{
|
||||
private PropTablesCleanupJob cleanupJob;
|
||||
private @Mock JobExecutionContext jobCtx;
|
||||
private @Mock PropertyValueDAO propValueDAO;
|
||||
private JobDetail jobDetail;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception
|
||||
{
|
||||
jobDetail = new JobDetail("propTablesCleanupJob", PropTablesCleanupJob.class);
|
||||
jobDetail.getJobDataMap().put(PropTablesCleanupJob.PROPERTY_VALUE_DAO_KEY, propValueDAO);
|
||||
cleanupJob = new PropTablesCleanupJob();
|
||||
|
||||
when(jobCtx.getJobDetail()).thenReturn(jobDetail);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExecute() throws JobExecutionException
|
||||
{
|
||||
cleanupJob.execute(jobCtx);
|
||||
|
||||
verify(propValueDAO).cleanupUnusedValues();
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testMissingPropertyValueDAO() throws JobExecutionException
|
||||
{
|
||||
jobDetail.getJobDataMap().put(PropTablesCleanupJob.PROPERTY_VALUE_DAO_KEY, null);
|
||||
cleanupJob.execute(jobCtx);
|
||||
}
|
||||
|
||||
@Test(expected=ClassCastException.class)
|
||||
public void testWrongTypeForPropertyValueDAO() throws JobExecutionException
|
||||
{
|
||||
jobDetail.getJobDataMap().put(PropTablesCleanupJob.PROPERTY_VALUE_DAO_KEY, "This is not a PropertyValueDAO");
|
||||
cleanupJob.execute(jobCtx);
|
||||
}
|
||||
|
||||
}
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2010 Alfresco Software Limited.
|
||||
* Copyright (C) 2005-2014 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
@@ -23,16 +23,22 @@ import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
import java.net.URL;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.transaction.UserTransaction;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.repo.content.transform.AbstractContentTransformerTest;
|
||||
import org.alfresco.repo.domain.audit.AuditDAO.AuditApplicationInfo;
|
||||
import org.alfresco.repo.domain.contentdata.ContentDataDAO;
|
||||
import org.alfresco.repo.domain.propval.PropValGenerator;
|
||||
import org.alfresco.repo.domain.propval.PropertyValueDAO;
|
||||
import org.alfresco.repo.transaction.RetryingTransactionHelper;
|
||||
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
|
||||
import org.alfresco.service.ServiceRegistry;
|
||||
@@ -62,6 +68,7 @@ public class AuditDAOTest extends TestCase
|
||||
private TransactionService transactionService;
|
||||
private RetryingTransactionHelper txnHelper;
|
||||
private AuditDAO auditDAO;
|
||||
private PropertyValueDAO propertyValueDAO;
|
||||
|
||||
@Override
|
||||
public void setUp() throws Exception
|
||||
@@ -71,6 +78,7 @@ public class AuditDAOTest extends TestCase
|
||||
txnHelper = transactionService.getRetryingTransactionHelper();
|
||||
|
||||
auditDAO = (AuditDAO) ctx.getBean("auditDAO");
|
||||
propertyValueDAO = ctx.getBean(PropertyValueDAO.class);
|
||||
}
|
||||
|
||||
public void testAuditModel() throws Exception
|
||||
@@ -527,4 +535,168 @@ public class AuditDAOTest extends TestCase
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* MNT-10067: use a script to delete the orphaned audit data (property values).
|
||||
*/
|
||||
public void testScriptCanDeleteOrphanedProps() throws Exception
|
||||
{
|
||||
// single test
|
||||
scriptCanDeleteOrphanedPropsWork(false);
|
||||
}
|
||||
|
||||
private void scriptCanDeleteOrphanedPropsWork(final boolean performance) throws Exception
|
||||
{
|
||||
final int iterationStep, maxIterations;
|
||||
if (performance)
|
||||
{
|
||||
iterationStep = 1000;
|
||||
maxIterations = 1000;
|
||||
}
|
||||
else
|
||||
{
|
||||
iterationStep = 1;
|
||||
maxIterations = 1;
|
||||
}
|
||||
|
||||
UserTransaction txn;
|
||||
|
||||
for (int i = iterationStep; i <= maxIterations*iterationStep; i+=iterationStep)
|
||||
{
|
||||
List<String> stringValues = new LinkedList<String>();
|
||||
List<Double> doubleValues = new LinkedList<Double>();
|
||||
List<Date> dateValues = new LinkedList<Date>();
|
||||
|
||||
txn = transactionService.getUserTransaction();
|
||||
long startCreate = System.currentTimeMillis();
|
||||
txn.begin();
|
||||
for (int j = 0; j < i; j++)
|
||||
{
|
||||
PropValGenerator valueGen = new PropValGenerator(propertyValueDAO);
|
||||
String stringValue = valueGen.createUniqueString();
|
||||
stringValues.add(stringValue);
|
||||
Double doubleValue = valueGen.createUniqueDouble();
|
||||
doubleValues.add(doubleValue);
|
||||
Date dateValue = valueGen.createUniqueDate();
|
||||
dateValues.add(dateValue);
|
||||
|
||||
AuditQueryCallbackImpl preDeleteCallback = new AuditQueryCallbackImpl();
|
||||
AuditQueryCallbackImpl resultsCallback = new AuditQueryCallbackImpl();
|
||||
|
||||
AuditApplicationInfo info1 = createAuditApp();
|
||||
String app1 = info1.getName();
|
||||
|
||||
String username = "alexi";
|
||||
Map<String, Serializable> values = new HashMap<String, Serializable>();
|
||||
values.put("/a/b/string-" + j, stringValue);
|
||||
values.put("/a/b/double-" + j, doubleValue);
|
||||
values.put("/a/b/date-" + j, dateValue);
|
||||
// TODO: how to deal with Serializable values which cannot be retrieved later in test by value alone?
|
||||
long now = System.currentTimeMillis();
|
||||
auditDAO.createAuditEntry(info1.getId(), now, username, values);
|
||||
|
||||
auditDAO.findAuditEntries(preDeleteCallback, new AuditQueryParameters(), -1);
|
||||
assertEquals(1, preDeleteCallback.numEntries(app1));
|
||||
|
||||
// Delete audit entries between times - for all applications.
|
||||
auditDAO.deleteAuditEntries(info1.getId(), null, null);
|
||||
|
||||
if (!performance)
|
||||
{
|
||||
auditDAO.findAuditEntries(resultsCallback, new AuditQueryParameters(), -1);
|
||||
assertEquals("All entries should have been deleted from app1", 0, resultsCallback.numEntries(app1));
|
||||
}
|
||||
}
|
||||
txn.commit();
|
||||
System.out.println("Created values for " + i + " entries in " + (System.currentTimeMillis() - startCreate) + " ms.");
|
||||
|
||||
txn = transactionService.getUserTransaction();
|
||||
txn.begin();
|
||||
if (!performance)
|
||||
{
|
||||
// Check there are some persisted values to delete.
|
||||
// Unlike PropertyValueDAOTest we're using the getPropertyValue() method here,
|
||||
// instead of the datatype-specific methods (e.g. getPropertyStringValue()).
|
||||
// This is because AuditDAO persists an entire map of values resulting in different behaviour
|
||||
// (i.e. dates are persisted as Serializable)
|
||||
for (String stringValue : stringValues)
|
||||
{
|
||||
assertEquals(stringValue, propertyValueDAO.getPropertyValue(stringValue).getSecond());
|
||||
}
|
||||
for (Double doubleValue : doubleValues)
|
||||
{
|
||||
assertEquals(doubleValue, propertyValueDAO.getPropertyValue(doubleValue).getSecond());
|
||||
}
|
||||
for (Date dateValue : dateValues)
|
||||
{
|
||||
assertEquals(dateValue, propertyValueDAO.getPropertyValue(dateValue).getSecond());
|
||||
}
|
||||
}
|
||||
long startDelete = System.currentTimeMillis();
|
||||
propertyValueDAO.cleanupUnusedValues();
|
||||
txn.commit();
|
||||
System.out.println("Cleaned values for " + i + " entries in " + (System.currentTimeMillis() - startDelete) + " ms.");
|
||||
|
||||
if (!performance)
|
||||
{
|
||||
// Check all the properties have been deleted.
|
||||
txn = transactionService.getUserTransaction();
|
||||
txn.begin();
|
||||
|
||||
for (String stringValue : stringValues)
|
||||
{
|
||||
assertPropDeleted(propertyValueDAO.getPropertyValue(stringValue));
|
||||
}
|
||||
for (Double doubleValue : doubleValues)
|
||||
{
|
||||
assertPropDeleted(propertyValueDAO.getPropertyValue(doubleValue));
|
||||
}
|
||||
for (Date dateValue : dateValues)
|
||||
{
|
||||
assertPropDeleted(propertyValueDAO.getPropertyValue(dateValue));
|
||||
}
|
||||
|
||||
txn.commit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void assertPropDeleted(Pair<Long, ?> value)
|
||||
{
|
||||
if (value != null)
|
||||
{
|
||||
String msg = String.format("Property value [%s=%s] should have been deleted by cleanup script.",
|
||||
value.getSecond().getClass().getSimpleName(), value.getSecond());
|
||||
fail(msg);
|
||||
}
|
||||
}
|
||||
|
||||
public void scriptCanDeleteOrphanedPropsPerformance() throws Exception
|
||||
{
|
||||
scriptCanDeleteOrphanedPropsWork(true);
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
try
|
||||
{
|
||||
AuditDAOTest test = new AuditDAOTest();
|
||||
test.setUp();
|
||||
System.out.println("Press any key to run performance test.");
|
||||
System.in.read();
|
||||
test.scriptCanDeleteOrphanedPropsPerformance();
|
||||
System.out.println("Press any key to shutdown.");
|
||||
System.in.read();
|
||||
test.tearDown();
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
finally
|
||||
{
|
||||
ApplicationContextHelper.closeApplicationContext();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,186 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2014 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.alfresco.repo.domain.propval;
|
||||
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import java.util.Random;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.alfresco.util.Pair;
|
||||
|
||||
/**
|
||||
* Creates property values suitable for use in testing.
|
||||
*
|
||||
* @author Matt Ward
|
||||
*/
|
||||
public class PropValGenerator
|
||||
{
|
||||
private static final Random rand = new Random();
|
||||
private final PropertyValueDAO propertyValueDAO;
|
||||
private final DoubleGen doubleGen = new DoubleGen();
|
||||
private final DateGen dateGen = new DateGen();
|
||||
private final SerializableGen serGen = new SerializableGen();
|
||||
|
||||
public PropValGenerator(PropertyValueDAO propertyValueDAO)
|
||||
{
|
||||
this.propertyValueDAO = propertyValueDAO;
|
||||
}
|
||||
|
||||
public String createUniqueString()
|
||||
{
|
||||
// No need to do anything more clever than create a UUID.
|
||||
return UUID.randomUUID().toString();
|
||||
}
|
||||
|
||||
public Double createUniqueDouble()
|
||||
{
|
||||
return doubleGen.getUnusedValue();
|
||||
}
|
||||
|
||||
public Date createUniqueDate()
|
||||
{
|
||||
return dateGen.getUnusedValue();
|
||||
}
|
||||
|
||||
public Serializable createUniqueSerializable()
|
||||
{
|
||||
return serGen.getUnusedValue();
|
||||
}
|
||||
|
||||
|
||||
private class DoubleGen extends UniqueValueGenerator<Double>
|
||||
{
|
||||
@Override
|
||||
protected Double createValue()
|
||||
{
|
||||
return (Math.pow(2,32)) + (rand.nextDouble() * (Math.pow(2,32) - Math.pow(2,31)));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Pair<Long, Double> getExistingValue(Double value)
|
||||
{
|
||||
return propertyValueDAO.getPropertyDoubleValue(value);
|
||||
}
|
||||
}
|
||||
|
||||
private class DateGen extends UniqueValueGenerator<Date>
|
||||
{
|
||||
@Override
|
||||
protected Date createValue()
|
||||
{
|
||||
Random rand = new Random();
|
||||
Date date = new Date(rand.nextLong());
|
||||
// Dates are stored to day precision, make sure we return the
|
||||
// same value that will be stored, for comparison in assert statements etc.
|
||||
Date truncDate = PropertyDateValueEntity.truncateDate(date);
|
||||
return truncDate;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Pair<Long, Date> getExistingValue(Date value)
|
||||
{
|
||||
return propertyValueDAO.getPropertyDateValue(value);
|
||||
}
|
||||
}
|
||||
|
||||
private class SerializableGen extends UniqueValueGenerator<Serializable>
|
||||
{
|
||||
@Override
|
||||
protected Serializable createValue()
|
||||
{
|
||||
return new MySerializable();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Pair<Long, Serializable> getExistingValue(Serializable value)
|
||||
{
|
||||
return propertyValueDAO.getPropertyValue(value);
|
||||
}
|
||||
}
|
||||
|
||||
private static class MySerializable implements Serializable
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
private final Long val;
|
||||
|
||||
public MySerializable()
|
||||
{
|
||||
val = rand.nextLong();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((this.val == null) ? 0 : this.val.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
if (this == obj) return true;
|
||||
if (obj == null) return false;
|
||||
if (getClass() != obj.getClass()) return false;
|
||||
MySerializable other = (MySerializable) obj;
|
||||
if (this.val == null)
|
||||
{
|
||||
if (other.val != null) return false;
|
||||
}
|
||||
else if (!this.val.equals(other.val)) return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate values that aren't currently in the properties tables. By trying random values
|
||||
* several times until an unused value is used. This is to help avoid red builds, since the
|
||||
* assumption by the orphaned property cleanup test is that the properties are not in use
|
||||
* (otherwise they won't be cleaned up!)
|
||||
*/
|
||||
private abstract class UniqueValueGenerator<T>
|
||||
{
|
||||
private final int maxTries = 5;
|
||||
protected abstract T createValue();
|
||||
protected abstract Pair<Long, T> getExistingValue(T value);
|
||||
|
||||
public T getUnusedValue()
|
||||
{
|
||||
int tries = 0;
|
||||
T value = null;
|
||||
boolean exists = true;
|
||||
while (exists)
|
||||
{
|
||||
if (++tries > maxTries)
|
||||
{
|
||||
throw new RuntimeException("Unable to generate unused value in " + maxTries + " tries.");
|
||||
}
|
||||
value = createValue();
|
||||
assertNotNull("Value generator should not generate a null value, but did.", value);
|
||||
// Make sure the value isn't already present in the properties tables.
|
||||
exists = (getExistingValue(value) != null);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
@@ -44,6 +44,7 @@ import org.alfresco.util.GUID;
|
||||
import org.alfresco.util.Pair;
|
||||
import org.junit.experimental.categories.Category;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.dao.DataIntegrityViolationException;
|
||||
import org.springframework.extensions.surf.util.ISO8601DateFormat;
|
||||
|
||||
/**
|
||||
@@ -874,4 +875,84 @@ public class PropertyValueDAOTest extends TestCase
|
||||
}, false);
|
||||
assertEquals("ID-value pair incorrect", v2Pair, pair);
|
||||
}
|
||||
|
||||
/**
|
||||
* MNT-10067: use a script to delete the orphaned property values.
|
||||
*/
|
||||
public void testScriptCanDeleteUnusedProps()
|
||||
{
|
||||
PropValGenerator valueGen = new PropValGenerator(propertyValueDAO);
|
||||
|
||||
// Find some values to use in the test that aren't already in the property tables.
|
||||
final String stringValue = valueGen.createUniqueString();
|
||||
final Double doubleValue = valueGen.createUniqueDouble();
|
||||
final Date dateValue = valueGen.createUniqueDate();
|
||||
final Serializable serValue = valueGen.createUniqueSerializable();
|
||||
// We'll keep a list of the DB IDs of the persisted values so we can later check they've been deleted.
|
||||
final Map<Object, Long> persistedIDs = new HashMap<Object, Long>();
|
||||
|
||||
txnHelper.doInTransaction(new RetryingTransactionCallback<Void>()
|
||||
{
|
||||
public Void execute() throws Throwable
|
||||
{
|
||||
persistedIDs.put(stringValue, propertyValueDAO.getOrCreatePropertyStringValue(stringValue).getFirst());
|
||||
persistedIDs.put(doubleValue, propertyValueDAO.getOrCreatePropertyDoubleValue(doubleValue).getFirst());
|
||||
persistedIDs.put(dateValue, propertyValueDAO.getOrCreatePropertyDateValue(dateValue).getFirst());
|
||||
persistedIDs.put(serValue, propertyValueDAO.getOrCreatePropertyValue(serValue).getFirst());
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
// Run the clean-up script.
|
||||
txnHelper.doInTransaction(new RetryingTransactionCallback<Void>()
|
||||
{
|
||||
public Void execute() throws Throwable
|
||||
{
|
||||
// Check there are some persisted values to delete.
|
||||
assertEquals(stringValue, propertyValueDAO.getPropertyStringValue(stringValue).getSecond());
|
||||
assertEquals(doubleValue, propertyValueDAO.getPropertyDoubleValue(doubleValue).getSecond());
|
||||
assertEquals(dateValue, propertyValueDAO.getPropertyDateValue(dateValue).getSecond());
|
||||
// Serializable values are the odd-one-out; we can't query for them by value
|
||||
// and no de-duplication is used during storage.
|
||||
assertEquals(serValue, propertyValueDAO.getPropertyValueById(persistedIDs.get(serValue)).getSecond());
|
||||
|
||||
propertyValueDAO.cleanupUnusedValues();
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
// Check all the properties have been deleted.
|
||||
txnHelper.doInTransaction(new RetryingTransactionCallback<Void>()
|
||||
{
|
||||
public Void execute() throws Throwable
|
||||
{
|
||||
assertPropDeleted(propertyValueDAO.getPropertyStringValue(stringValue));
|
||||
assertPropDeleted(propertyValueDAO.getPropertyDoubleValue(doubleValue));
|
||||
// TODO: fix date deletion, not currently handled by CleanAlfPropTables.sql
|
||||
// assertPropDeleted(propertyValueDAO.getPropertyDateValue(dateValue));
|
||||
// Serializable values cannot be queried by value
|
||||
try
|
||||
{
|
||||
propertyValueDAO.getPropertyValueById(persistedIDs.get(serValue));
|
||||
fail(String.format("Persisted %s was not deleted, but should have been.",
|
||||
serValue.getClass().getSimpleName()));
|
||||
}
|
||||
catch (DataIntegrityViolationException e)
|
||||
{
|
||||
// Good - it was deleted.
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void assertPropDeleted(Pair<Long, ?> value)
|
||||
{
|
||||
if (value != null)
|
||||
{
|
||||
String msg = String.format("Property value [%s=%s] should have been deleted by cleanup script.",
|
||||
value.getSecond().getClass().getSimpleName(), value.getSecond());
|
||||
fail(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2014 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.alfresco.repo.domain.schema.script;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.alfresco.util.ApplicationContextHelper;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
|
||||
/**
|
||||
* Integration tests for the {@link ScriptBundleExecutorImpl} class.
|
||||
*
|
||||
* @author Matt Ward
|
||||
*/
|
||||
public class ScriptBundleExecutorImplIntegrationTest
|
||||
{
|
||||
private static ApplicationContext ctx;
|
||||
private ScriptBundleExecutor bundleExecutor;
|
||||
private DataSource dataSource;
|
||||
private JdbcTemplate jdbcTmpl;
|
||||
|
||||
@BeforeClass
|
||||
public static void setUpBeforeClass() throws Exception
|
||||
{
|
||||
String[] config = new String[] {
|
||||
"classpath:alfresco/application-context.xml",
|
||||
"classpath:scriptexec/script-exec-test.xml"
|
||||
};
|
||||
ctx = ApplicationContextHelper.getApplicationContext(config);
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception
|
||||
{
|
||||
bundleExecutor = ctx.getBean("bundleExecutor", ScriptBundleExecutorImpl.class);
|
||||
dataSource = ctx.getBean("dataSource", DataSource.class);
|
||||
jdbcTmpl = new JdbcTemplate(dataSource);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canExecuteBundle()
|
||||
{
|
||||
bundleExecutor.exec("scriptexec/${db.script.dialect}/bundle", "script_a.sql", "script_b.sql", "script_c.sql");
|
||||
|
||||
String select = "select message from alf_test_bundle order by message asc";
|
||||
List<String> res = jdbcTmpl.queryForList(select, String.class);
|
||||
assertEquals(2, res.size());
|
||||
// script_c deleted "script_a message 1"
|
||||
assertEquals("script_a message 2", res.get(0));
|
||||
assertEquals("script_b", res.get(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void postScriptIsRunFinallyEvenAfterEarlierFailure()
|
||||
{
|
||||
// script_b.sql will fail
|
||||
bundleExecutor.execWithPostScript("scriptexec/${db.script.dialect}/bundle2",
|
||||
"post_script.sql", "script_a.sql", "script_b.sql");
|
||||
|
||||
String select = "select message from alf_test_bundle2 order by message asc";
|
||||
List<String> res = jdbcTmpl.queryForList(select, String.class);
|
||||
assertEquals(1, res.size());
|
||||
// post_script deleted "script_a message 1"
|
||||
assertEquals("script_a message 2", res.get(0));
|
||||
}
|
||||
}
|
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2014 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.alfresco.repo.domain.schema.script;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Matchers.anyString;
|
||||
import static org.mockito.Matchers.same;
|
||||
import static org.mockito.Mockito.doThrow;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.InOrder;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
|
||||
/**
|
||||
* Unit tests for the {@link ScriptBundleExecutorImpl} class.
|
||||
*
|
||||
* @author Matt Ward
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class ScriptBundleExecutorImplTest
|
||||
{
|
||||
// Class under test
|
||||
private ScriptBundleExecutorImpl bundleExecutor;
|
||||
private @Mock ScriptExecutor scriptExecutor;
|
||||
private @Mock Log log;
|
||||
|
||||
@BeforeClass
|
||||
public static void setUpClass() throws Exception
|
||||
{
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception
|
||||
{
|
||||
bundleExecutor = new ScriptBundleExecutorImpl(scriptExecutor);
|
||||
bundleExecutor.log = log;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canExecuteMultipleScripts() throws Exception
|
||||
{
|
||||
bundleExecutor.exec("/path/to/script/dir", "one.sql", "two.sql", "three.sql");
|
||||
|
||||
InOrder inOrder = Mockito.inOrder(scriptExecutor);
|
||||
inOrder.verify(scriptExecutor).executeScriptUrl("/path/to/script/dir/one.sql");
|
||||
inOrder.verify(scriptExecutor).executeScriptUrl("/path/to/script/dir/two.sql");
|
||||
inOrder.verify(scriptExecutor).executeScriptUrl("/path/to/script/dir/three.sql");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void willAlwaysRunPostBatchScript() throws Exception
|
||||
{
|
||||
// The first of the "main" scripts will fail...
|
||||
Exception e = new RuntimeException("Script failure!");
|
||||
doThrow(e).when(scriptExecutor).executeScriptUrl("/path/to/script/dir/work01.sql");
|
||||
|
||||
bundleExecutor.execWithPostScript("/path/to/script/dir", "post.sql", "pre.sql", "work01.sql", "work02.sql");
|
||||
|
||||
InOrder inOrder = Mockito.inOrder(scriptExecutor);
|
||||
inOrder.verify(scriptExecutor).executeScriptUrl("/path/to/script/dir/pre.sql");
|
||||
inOrder.verify(scriptExecutor).executeScriptUrl("/path/to/script/dir/work01.sql");
|
||||
// work02.sql will NOT be executed, but the post-script will be.
|
||||
inOrder.verify(scriptExecutor, never()).executeScriptUrl("/path/to/script/dir/work02.sql");
|
||||
inOrder.verify(scriptExecutor).executeScriptUrl("/path/to/script/dir/post.sql");
|
||||
|
||||
verify(log).error(anyString(), same(e));
|
||||
}
|
||||
}
|
@@ -0,0 +1,158 @@
|
||||
package org.alfresco.repo.domain.schema.script;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.util.ApplicationContextHelper;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.dialect.MySQLInnoDBDialect;
|
||||
import org.hibernate.dialect.PostgreSQLDialect;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
|
||||
/**
|
||||
* Integration tests for the {@link ScriptExecutorImpl} class.
|
||||
*
|
||||
* @author Matt Ward
|
||||
*/
|
||||
public class ScriptExecutorImplIntegrationTest
|
||||
{
|
||||
private final static Log log = LogFactory.getLog(ScriptExecutorImplIntegrationTest.class);
|
||||
private static ApplicationContext ctx;
|
||||
private ScriptExecutor scriptExecutor;
|
||||
private DataSource dataSource;
|
||||
private JdbcTemplate jdbcTmpl;
|
||||
private Dialect dialect;
|
||||
|
||||
@BeforeClass
|
||||
public static void setUpBeforeClass() throws Exception
|
||||
{
|
||||
String[] config = new String[] {
|
||||
"classpath:alfresco/application-context.xml",
|
||||
"classpath:scriptexec/script-exec-test.xml"
|
||||
};
|
||||
ctx = ApplicationContextHelper.getApplicationContext(config);
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception
|
||||
{
|
||||
scriptExecutor = ctx.getBean("simpleScriptExecutor", ScriptExecutorImpl.class);
|
||||
dataSource = ctx.getBean("dataSource", DataSource.class);
|
||||
dialect = ctx.getBean("dialect", Dialect.class);
|
||||
jdbcTmpl = new JdbcTemplate(dataSource);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that we can execute a simple script, without any dialect-specific loading.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test
|
||||
public void canExecuteBasicScript() throws Exception
|
||||
{
|
||||
scriptExecutor.executeScriptUrl("scriptexec/basic.sql");
|
||||
|
||||
String select = "select textfield from alf_test_script_exec order by textfield asc";
|
||||
List<String> res = jdbcTmpl.queryForList(select, String.class);
|
||||
assertEquals(2, res.size());
|
||||
assertEquals("hello", res.get(0));
|
||||
assertEquals("world", res.get(1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that a script designed to be run for all varieties of DBMS
|
||||
* (i.e. in subdirectory org.hibernate.dialect.Dialect) will run
|
||||
* regardless of specific dialect (e.g. MySQL or PostgreSQL)
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test
|
||||
public void canExecuteGenericDialectScript() throws Exception
|
||||
{
|
||||
scriptExecutor.executeScriptUrl("scriptexec/${db.script.dialect}/generic.sql");
|
||||
|
||||
String select = "select message from alf_test_script_exec_generic";
|
||||
List<String> res = jdbcTmpl.queryForList(select, String.class);
|
||||
assertEquals(1, res.size());
|
||||
assertEquals("generic", res.get(0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the case of executing a specific (e.g. PostgreSQL) database script
|
||||
* when no general script is present (therefore no overriding mechanism is required).
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test
|
||||
public void canExecuteSpecificDialectScript() throws Exception
|
||||
{
|
||||
scriptExecutor.executeScriptUrl("scriptexec/${db.script.dialect}/specific.sql");
|
||||
|
||||
String select = "select message from alf_test_script_exec_specific";
|
||||
List<String> res = jdbcTmpl.queryForList(select, String.class);
|
||||
assertEquals(1, res.size());
|
||||
if (dialect.getClass().equals(MySQLInnoDBDialect.class))
|
||||
{
|
||||
assertEquals("mysql", res.get(0));
|
||||
}
|
||||
else if (dialect.getClass().equals(PostgreSQLDialect.class))
|
||||
{
|
||||
assertEquals("postgresql", res.get(0));
|
||||
}
|
||||
else
|
||||
{
|
||||
log.warn("No suitable dialect-specific DB script for test canExecuteSpecificDialectScript()");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the case of executing a specific database script (e.g. PostgreSQL) when
|
||||
* a more generic script also exists -- the more generic script is not run.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test
|
||||
public void canExecuteSpecificDialectOverridingGenericScript() throws Exception
|
||||
{
|
||||
scriptExecutor.executeScriptUrl("scriptexec/${db.script.dialect}/override.sql");
|
||||
|
||||
String select = "select message from alf_test_script_exec_override";
|
||||
List<String> res = jdbcTmpl.queryForList(select, String.class);
|
||||
assertEquals(1, res.size());
|
||||
if (dialect.getClass().equals(MySQLInnoDBDialect.class))
|
||||
{
|
||||
assertEquals("mysql", res.get(0));
|
||||
}
|
||||
else if (dialect.getClass().equals(PostgreSQLDialect.class))
|
||||
{
|
||||
assertEquals("postgresql", res.get(0));
|
||||
}
|
||||
else
|
||||
{
|
||||
log.warn("No suitable dialect-specific DB script for test canExecuteSpecificDialectOverridingGenericScript()");
|
||||
}
|
||||
}
|
||||
|
||||
@Test()
|
||||
public void exceptionThrownWhenNoMatchingScriptFound() throws Exception
|
||||
{
|
||||
try
|
||||
{
|
||||
scriptExecutor.executeScriptUrl("scriptexec/${db.script.dialect}/non-existent-file.sql");
|
||||
}
|
||||
catch (AlfrescoRuntimeException e)
|
||||
{
|
||||
assertEquals("schema.update.err.script_not_found", e.getMsgId());
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user