/* (c) 2017 Open Source Geospatial Foundation - all rights reserved * This code is licensed under the GPL 2.0 license, available at the root * application directory. */ package org.geoserver.h2; import org.apache.commons.io.output.ByteArrayOutputStream; import org.geoserver.catalog.DataStoreInfo; import org.geoserver.catalog.FeatureTypeInfo; import org.geoserver.catalog.LayerInfo; import org.geoserver.catalog.impl.NamespaceInfoImpl; import org.geoserver.catalog.impl.WorkspaceInfoImpl; import org.geoserver.data.test.SystemTestData; import org.geoserver.test.GeoServerSystemTestSupport; import org.geoserver.util.IOUtils; import org.geotools.data.DataAccess; import org.geotools.data.Query; import org.geotools.feature.NameImpl; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import org.opengis.feature.type.Name; import org.springframework.mock.web.MockHttpServletResponse; import java.io.File; import java.io.FileOutputStream; import java.io.InputStream; import java.util.List; import java.util.zip.ZipOutputStream; import static org.hamcrest.CoreMatchers.instanceOf; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.notNullValue; import static org.junit.Assert.assertThat; /** * Contains tests that invoke REST resources that will use H2 data store. */ public final class RestTest extends GeoServerSystemTestSupport { private static final String WORKSPACE_NAME = "h2-tests"; private static final String WORKSPACE_URI = "http://h2-tests.org"; private static File ROOT_DIRECTORY; private static File DATABASE_DIR; @Override protected void onSetUp(SystemTestData testData) throws Exception { // create a test workspace WorkspaceInfoImpl workspace = new WorkspaceInfoImpl(); workspace.setName(WORKSPACE_NAME); getCatalog().add(workspace); // create test workspace namespace NamespaceInfoImpl nameSpace = new NamespaceInfoImpl(); nameSpace.setPrefix(WORKSPACE_NAME); nameSpace.setURI(WORKSPACE_URI); getCatalog().add(nameSpace); } @BeforeClass public static void setUp() throws Throwable { // create root tests directory ROOT_DIRECTORY = IOUtils.createTempDirectory("h2-tests"); // create the test database DATABASE_DIR = new File(ROOT_DIRECTORY, "testdb"); DATABASE_DIR.mkdirs(); } @AfterClass public static void tearDown() throws Throwable { // check if the root directory was initiated (test may have been skipped) if (ROOT_DIRECTORY != null) { // remove root tests directory IOUtils.delete(ROOT_DIRECTORY); } } @Before public void login() { // make sure we perform all requests logged as admin login("admin", "geoserver", "ROLE_ADMINISTRATOR"); } @Test public void createDataStoreUsingRestSingleFile() throws Exception { String dataStoreName = "h2-test-db-single"; // send only the database file byte[] content = readSqLiteDatabaseFile(); genericCreateDataStoreUsingRestTest(dataStoreName, "application/octet-stream", content); } @Test public void createDataStoreUsingRestZipFile() throws Exception { String dataStoreName = "h2-test-db-zip"; // send the database directory byte[] content = readSqLiteDatabaseDir(); genericCreateDataStoreUsingRestTest(dataStoreName, "application/zip", content); } public void genericCreateDataStoreUsingRestTest(String dataStoreName, String mimeType, byte[] content) throws Exception { // perform a PUT request, a new H2 data store should be created // we also require that all available feature types should be created String path = String.format( "/rest/workspaces/%s/datastores/%s/file.h2?configure=all", WORKSPACE_NAME, dataStoreName); MockHttpServletResponse response = putAsServletResponse(path, content, mimeType); // we should get a HTTP 201 status code meaning that the data store was created assertThat(response.getStatus(), is(201)); // let's see if the data store was correctly created DataStoreInfo storeInfo = getCatalog().getDataStoreByName(dataStoreName); assertThat(storeInfo, notNullValue()); DataAccess store = storeInfo.getDataStore(null); assertThat(store, notNullValue()); List<Name> names = store.getNames(); assertThat(store, notNullValue()); // check that at least the table points is available Name found = names.stream() .filter(name -> name != null && name.getLocalPart().equals("points")) .findFirst().orElse(null); assertThat(found, notNullValue()); // check that the points layer was correctly created LayerInfo layerInfo = getCatalog().getLayerByName(new NameImpl(WORKSPACE_URI, "points")); assertThat(layerInfo, notNullValue()); assertThat(layerInfo.getResource(), notNullValue()); assertThat(layerInfo.getResource(), instanceOf(FeatureTypeInfo.class)); // check that we have the expected features FeatureTypeInfo featureTypeInfo = (FeatureTypeInfo) layerInfo.getResource(); int count = featureTypeInfo.getFeatureSource(null, null).getCount(Query.ALL); assertThat(count, is(4)); } /** * Helper method that just reads the test H2 database file * and stores it in a array of bytes. */ private static byte[] readSqLiteDatabaseFile() throws Exception { // open the database file InputStream input = RestTest.class.getResourceAsStream("/test-database.data.db"); ByteArrayOutputStream output = new ByteArrayOutputStream(); try { // copy the input stream to the output stream IOUtils.copy(input, output); } catch (Exception exception) { throw new RuntimeException("Error reading SQLite database file to byte array.", exception); } return output.toByteArray(); } /** * Helper method that zips the H2 data directory and returns it as * an array of bytes. */ private static byte[] readSqLiteDatabaseDir() throws Exception { // copy database file to database directory File outputFile = new File(DATABASE_DIR, "test-database.data.db"); InputStream input = RestTest.class.getResourceAsStream("/test-database.data.db"); IOUtils.copy(input, new FileOutputStream(outputFile)); // zip the database directory ByteArrayOutputStream output = new ByteArrayOutputStream(); ZipOutputStream zip = new ZipOutputStream(output); // ignore the lock files IOUtils.zipDirectory(DATABASE_DIR, zip, (dir, name) -> !name.toLowerCase().contains("lock")); zip.close(); // just return the output stream content return output.toByteArray(); } }