/*
* Copyright 2012 NGDATA nv
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.lilyproject.process.test;
import java.io.File;
import java.util.IdentityHashMap;
import org.apache.commons.io.FileUtils;
import org.junit.Test;
import org.lilyproject.client.LilyClient;
import org.lilyproject.lilyservertestfw.LilyProxy;
import org.lilyproject.process.decorator.TestRepositoryDecoratorFactory;
import org.lilyproject.repository.api.FieldType;
import org.lilyproject.repository.api.LRepository;
import org.lilyproject.repository.api.LTable;
import org.lilyproject.repository.api.QName;
import org.lilyproject.repository.api.Record;
import org.lilyproject.repository.api.RecordType;
import org.lilyproject.repository.api.Scope;
import org.lilyproject.repository.api.TypeManager;
import org.lilyproject.repository.model.impl.RepositoryModelImpl;
import org.lilyproject.server.modules.repository.DecoratingRepositoryManager;
import org.lilyproject.server.modules.repository.RepositoryDecoratorChain;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.lilyproject.repository.model.api.RepositoryDefinition.RepositoryLifecycleState;
/**
* Tests the repository decorator feature.
*
* <p>This test relies on test-decorator being installed in the local maven repository, hence
* requires that the build is done with "mvn install".</p>
*/
public class DecoratorTest {
@Test
public void test() throws Exception {
LilyProxy lilyProxy = createLilyProxy();
LilyClient client = lilyProxy.getLilyServerProxy().getClient();
RepositoryModelImpl repositoryModel = new RepositoryModelImpl(lilyProxy.getLilyServerProxy().getZooKeeper());
repositoryModel.create("repo1");
assertTrue(repositoryModel.waitUntilRepositoryInState("repo1", RepositoryLifecycleState.ACTIVE, 60000L));
repositoryModel.create("repo2");
assertTrue(repositoryModel.waitUntilRepositoryInState("repo2", RepositoryLifecycleState.ACTIVE, 60000L));
repositoryModel.close();
// Make a schema
TypeManager typeMgr = client.getDefaultRepository().getTypeManager();
QName field1 = new QName("ns", "f1");
FieldType fieldType1 = typeMgr.newFieldType(typeMgr.getValueType("STRING"), field1, Scope.NON_VERSIONED);
fieldType1 = typeMgr.createFieldType(fieldType1);
QName field2 = new QName("ns", "f2");
FieldType fieldType2 = typeMgr.newFieldType(typeMgr.getValueType("STRING"), field2, Scope.NON_VERSIONED);
fieldType2 = typeMgr.createFieldType(fieldType2);
QName typeName = new QName("ns", "rt1");
RecordType recordType = typeMgr.newRecordType(typeName);
recordType.addFieldTypeEntry(fieldType1.getId(), false);
recordType.addFieldTypeEntry(fieldType2.getId(), false);
recordType = typeMgr.createRecordType(recordType);
DecoratingRepositoryManager repositoryMgr = (DecoratingRepositoryManager)lilyProxy.getLilyServerProxy()
.getLilyServerTestingUtility().getRuntime().getModuleById("repository")
.getApplicationContext().getBean("repositoryManager");
IdentityHashMap<Object, Object> chains = new IdentityHashMap<Object, Object>();
// Test the decorator is applied for each repository and each table
for (String repositoryName : new String[] {"default", "repo1", "repo2"}) {
LRepository repository = client.getRepository(repositoryName);
repository.getTableManager().createTable("table1");
repository.getTableManager().createTable("table2");
for (String tableName : new String[] {"record", "table1", "table2"}) {
LTable table = repository.getTable(tableName);
Record record = table.newRecord();
record.setRecordType(typeName);
record.setField(field1, "foobar");
record = table.create(record);
assertEquals("foo", record.getField(field2));
assertEquals("foo", table.read(record.getId()).getField(field2));
// Test we can get access to our test decorator: this is something that is occasionally useful
// in test cases to check certain conditions, e.g. if the decorator would have async side effects.
RepositoryDecoratorChain chain = repositoryMgr.getRepositoryDecoratorChain(repositoryName, tableName);
assertNotNull(chain);
assertNotNull(chain.getDecorator(TestRepositoryDecoratorFactory.NAME));
chains.put(chain.getDecorator(TestRepositoryDecoratorFactory.NAME), null);
assertEquals(2, chain.getEntries().size());
}
}
// There should be one instance of the decorator created for each repository-table combination (that
// was accessed)
assertEquals(3 * 3, chains.size());
// Check that if we ask the same table twice, we get the same instance (verifies cache works)
assertTrue(client.getRepository("repo1").getTable("table1") == client.getRepository("repo1").getTable("table1"));
lilyProxy.stop();
// Check each of the decorators was properly closed
assertEquals(9, TestRepositoryDecoratorFactory.CLOSE_COUNT.get());
}
private static LilyProxy createLilyProxy() throws Exception {
String basedir = System.getProperty("basedir");
if (basedir == null) {
basedir = System.getProperty("java.io.tmpdir");
}
// Temp dir where we will create plugin & conf stuff
File tmpDir = new File(basedir + "/target/lily-test");
String pluginDir = setupPluginsDirectory(tmpDir);
System.setProperty("lily.plugin.dir", pluginDir);
File customConfDir = setupConfDirectory(tmpDir);
System.setProperty("lily.conf.dir", basedir + "/../server/conf");
System.setProperty("lily.conf.customdir", customConfDir.getAbsolutePath());
try {
LilyProxy lilyProxy = new LilyProxy();
lilyProxy.start();
return lilyProxy;
} finally {
// Make sure it's properties won't be used by later-running tests
System.getProperties().remove("lily.plugin.dir");
System.getProperties().remove("lily.conf.dir");
System.getProperties().remove("lily.conf.customdir");
}
}
private static String setupPluginsDirectory(File tmpDir) throws Exception {
File pluginDir = new File(tmpDir + "/plugins");
// Delete it if it would already exist
FileUtils.deleteDirectory(pluginDir);
FileUtils.forceMkdir(pluginDir);
File beforeRepoDir = new File(pluginDir, "load-before-repository");
FileUtils.forceMkdir(beforeRepoDir);
String projectVersion = System.getProperty("project.version");
if (projectVersion == null) {
throw new Exception("This test relies on a system property project.version being set. Probably you " +
"are running this test outside of Maven? Try adding -Dproject.version=...");
}
String wiringXml = "<wiring>\n" +
" <modules>\n" +
" <artifact id=\"test-decorator\" groupId=\"org.lilyproject\" artifactId=\"lily-test-decorator\" version=\"" + projectVersion + "\">\n" +
" </artifact>\n" +
" </modules>\n" +
"</wiring>";
FileUtils.writeStringToFile(new File(beforeRepoDir, "testdecorator.xml"), wiringXml, "UTF-8");
return pluginDir.getAbsolutePath();
}
private static File setupConfDirectory(File tmpDir) throws Exception {
File confDir = new File(tmpDir + "/conf");
File repoConfDir = new File(confDir, "repository");
FileUtils.forceMkdir(repoConfDir);
// Write configuration to activate the decorator
String repositoryXml = "<repository xmlns:conf=\"http://lilyproject.org/configuration\" conf:inherit=\"shallow\">" +
"<decorators><decorator>test-decorator</decorator></decorators>" +
"</repository>";
FileUtils.writeStringToFile(new File(repoConfDir, "repository.xml"), repositoryXml, "UTF-8");
return confDir;
}
}