/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.apache.stanbol.entityhub.indexing.destination.solryard;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Properties;
import java.util.ServiceLoader;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import org.apache.commons.io.FilenameUtils;
import org.apache.stanbol.commons.solr.managed.ManagedSolrServer;
import org.apache.stanbol.commons.solr.managed.standalone.StandaloneManagedSolrServer;
import org.apache.stanbol.entityhub.indexing.core.IndexingDestination;
import org.apache.stanbol.entityhub.indexing.core.config.IndexingConfig;
import org.apache.stanbol.entityhub.indexing.core.destination.OsgiConfigurationUtil;
import org.apache.stanbol.entityhub.servicesapi.defaults.NamespaceEnum;
import org.apache.stanbol.entityhub.servicesapi.model.Representation;
import org.apache.stanbol.entityhub.servicesapi.model.rdf.RdfResourceEnum;
import org.apache.stanbol.entityhub.servicesapi.yard.Yard;
import org.apache.stanbol.entityhub.servicesapi.yard.YardException;
import org.apache.stanbol.entityhub.yard.solr.impl.SolrYard;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* What to test:
* - correct initialisation
* - special schema initialisation
* - default schema initialisation
* - finalisation
* - writing of the IndexFieldConfiguration
* - creating of the {name}.solrindex.zip
* - creating of the {name}.solrindex.ref
*
* Indexing needs not to be tested, because this is the responsibility of the
* Unit Tests for the used Yard implementation.
*
* @author Rupert Westenthaler
*
*/
public class SolrYardIndexingDestinationTest {
public static final Collection<String> EXPECTED_INDEX_ARCHIVE_FILE_NAMES =
Arrays.asList(
"schema.xml",
"solrconfig.xml",
"segments.gen");
private static final Logger log = LoggerFactory.getLogger(SolrYardIndexingDestinationTest.class);
private static final String CONFIG_ROOT =
FilenameUtils.separatorsToSystem("testConfigs/");
/**
* mvn copies the resources in "src/test/resources" to target/test-classes.
* This folder is than used as classpath.<p>
* "/target/test-files/" does not exist, but is created by the
* {@link IndexingConfig}.
*/
private static final String TEST_ROOT =
FilenameUtils.separatorsToSystem("/target/test-files");
private static String userDir;
private static String testRoot;
/**
* The methods resets the "user.dir" system property
*/
@BeforeClass
public static void initTestRootFolder(){
String baseDir = System.getProperty("basedir");
if(baseDir == null){
baseDir = System.getProperty("user.dir");
}
//store the current user.dir
userDir = System.getProperty("user.dir");
testRoot = baseDir+TEST_ROOT;
log.info("ConfigTest Root : "+testRoot);
//set the user.dir to the testRoot (needed to test loading of missing
//configurations via classpath
//store the current user.dir and reset it after the tests
System.setProperty("user.dir", testRoot);
}
/**
* resets the "user.dir" system property the the original value
*/
@AfterClass
public static void cleanup(){
System.setProperty("user.dir", userDir);
}
@After
public void close(){
//after each test we need ensure to shutdown the default ManagedSolrServer
//because different tests use different Directories and therefore a new
//instance needs to be created
StandaloneManagedSolrServer.shutdownManagedServer();
}
@Test(expected=IllegalArgumentException.class)
public void testMissingBoostConfig(){
IndexingConfig config = new IndexingConfig(CONFIG_ROOT+"missingBoostConfig",CONFIG_ROOT+"missingBoostConfig"){};
config.getIndexingDestination();
}
@Test(expected=IllegalArgumentException.class)
public void testInvalidBoostConfig(){
IndexingConfig config = new IndexingConfig(CONFIG_ROOT+"invalidBoostConfig",CONFIG_ROOT+"invalidBoostConfig"){};
config.getIndexingDestination();
}
/**
* Tests that the Solr configuration is required, but the name of the config
* file is the default. The referenced directory is missing
*/
@Test(expected=IllegalArgumentException.class)
public void testMissingDefaultSolrSchemaConfig(){
IndexingConfig config = new IndexingConfig(CONFIG_ROOT+"missingDefaultSolrConf",CONFIG_ROOT+"missingDefaultSolrConf"){};
config.getIndexingDestination();
}
/**
* Tests that the Solr configuration is required and the name of the config
* file is specified. The referenced directory is missing
*/
@Test(expected=IllegalArgumentException.class)
public void testMissingSolrSchemaConfig(){
IndexingConfig config = new IndexingConfig(CONFIG_ROOT+"missingSolrConf",CONFIG_ROOT+"missingSolrConf"){};
config.getIndexingDestination();
}
@Test
public void testSimple() throws YardException, IOException {
IndexingConfig config = new IndexingConfig(CONFIG_ROOT+"simple",CONFIG_ROOT+"simple"){};
validateSolrDestination(config);
}
@Test
public void testWithSolrConf() throws YardException, IOException {
IndexingConfig config = new IndexingConfig(CONFIG_ROOT+"withSolrConf",CONFIG_ROOT+"withSolrConf"){};
validateSolrDestination(config);
}
/**
* Checks if the SolrYardIndexingDestination returned by the
* {@link IndexingConfig} is valid and functional
* @param config the configuration
* @throws YardException indicates problems while working with the {@link SolrYard}
* returned by {@link IndexingDestination#getYard()}
* @throws IOException indicates problems while validating the SolrArchives
* created by the {@link IndexingDestination#finalise()} method
*/
private void validateSolrDestination(IndexingConfig config) throws YardException,
IOException {
//get the destination
IndexingDestination destination = config.getIndexingDestination();
assertNotNull(destination);
assertEquals(destination.getClass(), SolrYardIndexingDestination.class);
//initialise
assertTrue(destination.needsInitialisation());
destination.initialise();
//test that the returned Yard instance is functional
Yard yard = destination.getYard();
assertNotNull(yard);
assertEquals(yard.getClass(), SolrYard.class);
Representation rep = yard.getValueFactory().createRepresentation("http://www.example.com/entity#123");
rep.add(NamespaceEnum.rdfs+"label", "test");
rep.add(NamespaceEnum.rdfs+"description", "Representation to test storage while indexing");
rep.add(RdfResourceEnum.entityRank.getUri(), Float.valueOf(0.8f));
yard.store(rep);
//finalise
destination.finalise();
//test the archives
File expectedSolrArchiveFile =
new File(config.getDistributionFolder(),config.getName()+".solrindex.zip");
assertTrue(expectedSolrArchiveFile.isFile());
// validate the archive
ZipFile archive = new ZipFile(expectedSolrArchiveFile);
Set<String> expected = new HashSet<String>(EXPECTED_INDEX_ARCHIVE_FILE_NAMES);
for(Enumeration<? extends ZipEntry> entries = archive.entries();entries.hasMoreElements();){
ZipEntry entry = entries.nextElement();
log.info("Validate Entry : "+entry.getName());
//the name of the index MUST be the root folder within the Archive!
assertTrue(entry.getName().startsWith(config.getName()));
expected.remove(FilenameUtils.getName(entry.getName()));
}
assertTrue("missing Files in index archive: "+expected,expected.isEmpty());
//TODO: reimplement to validate the created bundle!
// //check for the solrArchive reference file and validate required properties
// File expectedSolrArchiveReferenceFile =
// new File(,config.getName()+".solrindex.ref");
// assertTrue(expectedSolrArchiveReferenceFile.isFile());
// Properties solrRefProperties = new Properties();
// solrRefProperties.load(new FileInputStream(expectedSolrArchiveReferenceFile));
// assertTrue(solrRefProperties.getProperty("Index-Archive").equals(expectedSolrArchiveFile.getName()));
// assertTrue(solrRefProperties.getProperty("Name") != null);
}
}