/* * Copyright (c) 2006-2013 Nuxeo SA (http://nuxeo.com/) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Stephane Lacoin * Florent Guillaume */ package org.nuxeo.ecm.core; import static org.junit.Assert.assertEquals; import java.util.concurrent.CountDownLatch; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.junit.Before; import org.junit.Test; import org.nuxeo.ecm.core.api.ClientException; import org.nuxeo.ecm.core.api.DocumentModel; import org.nuxeo.ecm.core.api.DocumentModelList; import org.nuxeo.ecm.core.api.DocumentRef; import org.nuxeo.ecm.core.api.IdRef; import org.nuxeo.ecm.core.api.blobholder.BlobHolder; import org.nuxeo.ecm.core.api.impl.blob.StringBlob; import org.nuxeo.ecm.core.event.EventService; import org.nuxeo.ecm.core.storage.sql.TXSQLRepositoryTestCase; import org.nuxeo.ecm.core.work.AbstractWork; import org.nuxeo.ecm.core.work.api.WorkManager; import org.nuxeo.runtime.api.Framework; import org.nuxeo.runtime.transaction.TransactionHelper; public class TestSQLBinariesIndexing extends TXSQLRepositoryTestCase { protected static final Log log = LogFactory.getLog(TestSQLBinariesIndexing.class); protected String docId; protected DocumentRef docRef; protected BlockingWork blockingWork; @Override @Before public void setUp() throws Exception { super.setUp(); waitForFulltextIndexing(); } @Override protected void deployRepositoryContrib() throws Exception { super.deployRepositoryContrib(); deployBundle("org.nuxeo.ecm.core.convert"); deployBundle("org.nuxeo.ecm.core.convert.plugins"); } /** Creates doc, doesn't do a session save. */ protected void createDocument() throws ClientException { DocumentModel doc = session.createDocumentModel("/", "source", "File"); BlobHolder holder = doc.getAdapter(BlobHolder.class); holder.setBlob(new StringBlob("test")); doc = session.createDocument(doc); docId = doc.getId(); docRef = new IdRef(docId); } /** * Work that waits in the fulltext updater queue, blocking other indexing * work, until the main thread tells it to go ahead. */ public static class BlockingWork extends AbstractWork { protected CountDownLatch readyLatch = new CountDownLatch(1); protected CountDownLatch startLatch = new CountDownLatch(1); @Override public String getCategory() { return "fulltextUpdater"; } @Override public String getTitle() { return "Blocking Work"; } @Override public void work() throws Exception { setStatus("Blocking"); readyLatch.countDown(); startLatch.await(); setStatus("Released"); } } protected void blockFulltextUpdating() throws InterruptedException { blockingWork = new BlockingWork(); Framework.getLocalService(WorkManager.class).schedule(blockingWork); blockingWork.readyLatch.await(); } protected void allowFulltextUpdating() throws ClientException { blockingWork.startLatch.countDown(); blockingWork = null; waitForFulltextIndexing(); } protected void flush() throws ClientException { session.save(); closeSession(); TransactionHelper.commitOrRollbackTransaction(); TransactionHelper.startTransaction(); openSession(); } protected int indexedDocs() throws ClientException { DocumentModelList res = session.query("SELECT * FROM Document WHERE ecm:fulltext = 'test'"); return res.size(); } protected int jobDocs() throws ClientException { String request = String.format( "SELECT * from Document where ecm:fulltextJobId = '%s'", docId); return session.query(request).size(); } @Override public void waitForFulltextIndexing() { try { flush(); // also starts a new tx, which will allow progress } catch (ClientException e) { throw new RuntimeException(e); } super.waitForFulltextIndexing(); } @Test public void testBinariesAreIndexed() throws Exception { createDocument(); blockFulltextUpdating(); try { flush(); assertEquals(1, jobDocs()); assertEquals(0, indexedDocs()); } finally { allowFulltextUpdating(); } flush(); assertEquals(0, jobDocs()); assertEquals(1, indexedDocs()); } @Test public void testCopiesAreIndexed() throws Exception { createDocument(); blockFulltextUpdating(); try { flush(); assertEquals(1, jobDocs()); assertEquals(0, indexedDocs()); session.copy(docRef, session.getRootDocument().getRef(), "copy").getRef(); // check copy is part of requested flush(); assertEquals(2, jobDocs()); } finally { allowFulltextUpdating(); } // check copy is indexed also flush(); assertEquals(0, jobDocs()); assertEquals(2, indexedDocs()); // check copy doesn't stay linked to doc DocumentModel doc = session.getDocument(docRef); doc.getAdapter(BlobHolder.class).setBlob(new StringBlob("other")); session.saveDocument(doc); waitForFulltextIndexing(); assertEquals(1, indexedDocs()); } @Test public void testVersionsAreIndexed() throws Exception { createDocument(); blockFulltextUpdating(); try { flush(); assertEquals(1, jobDocs()); assertEquals(0, indexedDocs()); session.checkIn(docRef, null, null); flush(); } finally { allowFulltextUpdating(); } assertEquals(2, indexedDocs()); } }