Commit 9c8492cb by Ashutosh Mestry Committed by Madhan Neethiraj

ATLAS-2378: Fix repository unit tests to address random failures

parent 77dd50c6
......@@ -22,6 +22,7 @@ import org.apache.atlas.AtlasException;
import org.apache.commons.configuration.Configuration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testng.SkipException;
import java.io.File;
import java.util.UUID;
......@@ -33,33 +34,28 @@ public class GraphSandboxUtil {
Configuration configuration;
try {
configuration = ApplicationProperties.get();
configuration.setProperty("atlas.graph.storage.directory", getStorageDir(sandboxName, "storage"));
configuration.setProperty("atlas.graph.index.search.directory", getStorageDir(sandboxName, "index"));
String newStorageDir = System.getProperty("atlas.data") +
File.separatorChar + "storage" +
File.separatorChar + sandboxName;
configuration.setProperty("atlas.graph.storage.directory", newStorageDir);
String newIndexerDir = System.getProperty("atlas.data") +
File.separatorChar + "index" +
File.separatorChar + sandboxName;
configuration.setProperty("atlas.graph.index.search.directory", newIndexerDir);
LOG.debug("New Storage dir : {}", configuration.getProperty("atlas.graph.storage.directory"));
LOG.debug("New Indexer dir : {}", configuration.getProperty("atlas.graph.index.search.directory"));
} catch (AtlasException ignored) {
throw new SkipException("Failure to setup Sandbox: " + sandboxName);
}
}
LOG.debug("New Storage dir : {}", newStorageDir);
LOG.debug("New Indexer dir : {}", newIndexerDir);
} catch (AtlasException ignored) {}
private static String getStorageDir(String sandboxName, String directory) {
return System.getProperty("atlas.data") +
File.separatorChar + sandboxName +
File.separatorChar + directory;
}
public static void create() {
// Append a suffix to isolate the database for each instance
UUID uuid = UUID.randomUUID();
create(uuid.toString());
}
// Need to start local Solr Cloud for JanusGraph 0.2.0
public static boolean useLocalSolr() {
boolean ret = false;
......@@ -70,7 +66,9 @@ public class GraphSandboxUtil {
if (property != null && property instanceof String) {
ret = Boolean.valueOf((String) property);
}
} catch (AtlasException ignored) {}
} catch (AtlasException ignored) {
throw new SkipException("useLocalSolr: failed! ", ignored);
}
return ret;
}
......
......@@ -155,15 +155,20 @@ public class AtlasJanusGraphDatabase implements GraphDatabase<AtlasJanusVertex,
@Override
public void cleanup() {
JanusGraph g = getGraphInstance();
try {
getGraphInstance().close();
if(g != null) {
g.close();
}
} catch (Throwable t) {
LOG.warn("Could not close test JanusGraph", t);
t.printStackTrace();
}
try {
JanusGraphFactory.drop(getGraphInstance());
if(g != null) {
JanusGraphFactory.drop(g);
}
} catch (Throwable t) {
LOG.warn("Could not clear test JanusGraph", t);
t.printStackTrace();
......
......@@ -594,7 +594,7 @@
<entity.repository.impl>org.apache.atlas.repository.audit.InMemoryEntityAuditRepository</entity.repository.impl>
<surefire.version>2.18.1</surefire.version>
<surefire.forkCount>1C</surefire.forkCount>
<surefire.forkCount>2C</surefire.forkCount>
<failsafe.version>2.18.1</failsafe.version>
<atlas.surefire.options></atlas.surefire.options>
......
......@@ -243,12 +243,6 @@
<artifactId>maven-surefire-plugin</artifactId>
<version>${surefire.version}</version>
<configuration combine.children="override">
<properties>
<property>
<name>listener</name>
<value>org.apache.atlas.DBSandboxer</value>
</property>
</properties>
</configuration>
</plugin>
......
/**
* 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
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* 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.atlas;
import org.apache.atlas.graph.GraphSandboxUtil;
import org.apache.atlas.repository.graph.AtlasGraphProvider;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.testng.ITestContext;
import org.testng.TestListenerAdapter;
import org.testng.xml.XmlClass;
import java.util.List;
public class DBSandboxer extends TestListenerAdapter {
@Override
public void onStart(ITestContext context) {
// This will only work if each test is run individually (test suite has only one running test)
// If there are multiple tests the the sandbox folder name is not provided and the GraphSandboxUtil provisions
// a unique name
List<XmlClass> testClassesToRun = context.getCurrentXmlTest().getClasses();
if (CollectionUtils.isNotEmpty(testClassesToRun) && 1 == testClassesToRun.size()) {
XmlClass currentTestClass = testClassesToRun.get(0);
if (null != currentTestClass && StringUtils.isNotEmpty(currentTestClass.getName())) {
GraphSandboxUtil.create(currentTestClass.getName());
} else {
GraphSandboxUtil.create();
}
} else {
GraphSandboxUtil.create();
}
}
@Override
public void onFinish(ITestContext context) {
AtlasGraphProvider.cleanup();
}
}
......@@ -58,9 +58,11 @@ import org.apache.commons.configuration.Configuration;
import org.mockito.Mockito;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testng.annotations.Test;
import static org.apache.atlas.graph.GraphSandboxUtil.useLocalSolr;
@Test(enabled = false)
public class TestModules {
static class MockNotifier implements Provider<AtlasEntityChangeNotifier> {
......
......@@ -21,8 +21,12 @@ import org.apache.atlas.TestModules;
import org.apache.atlas.discovery.EntityDiscoveryService;
import org.apache.atlas.exception.AtlasBaseException;
import org.apache.atlas.model.discovery.AtlasSearchResult;
import org.apache.atlas.repository.graph.AtlasGraphProvider;
import org.apache.atlas.runner.LocalSolrRunner;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testng.SkipException;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.DataProvider;
......@@ -35,6 +39,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.apache.atlas.graph.GraphSandboxUtil.useLocalSolr;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertNull;
......@@ -42,6 +47,8 @@ import static org.testng.Assert.assertTrue;
@Guice(modules = TestModules.TestOnlyModule.class)
public class DSLQueriesTest extends BasicTestSetup {
private static final Logger LOG = LoggerFactory.getLogger(DSLQueriesTest.class);
private final int DEFAULT_LIMIT = 25;
@Inject
private EntityDiscoveryService discoveryService;
......@@ -50,12 +57,78 @@ public class DSLQueriesTest extends BasicTestSetup {
public void setup() throws Exception {
LocalSolrRunner.start();
setupTestData();
pollForData();
}
private void pollForData() throws InterruptedException {
Object[][] basicVerificationQueries = new Object[][] {
{"hive_db", 3},
{"hive_process", 7},
{"hive_table", 10},
{"hive_column", 17},
{"hive_storagedesc", 1},
{"Manager", 2},
{"Employee", 4},
};
int pollingAttempts = 5;
int pollingBackoff = 0; // in msecs
boolean success;
for (int attempt = 0; attempt < pollingAttempts; attempt++, pollingBackoff += attempt * 5000) {
LOG.debug("Polling -- Attempt {}, Backoff {}", attempt, pollingBackoff);
success = false;
for (Object[] verificationQuery : basicVerificationQueries) {
String query = (String) verificationQuery[0];
int expected = (int) verificationQuery[1];
try {
AtlasSearchResult result = discoveryService.searchUsingDslQuery(query, 25, 0);
if (result.getEntities() == null || result.getEntities().isEmpty()) {
LOG.warn("DSL {} returned no entities", query);
success = false;
} else if (result.getEntities().size() != expected) {
LOG.warn("DSL {} returned unexpected number of entities. Expected {} Actual {}", query, expected, result.getEntities().size());
success = false;
} else {
success = true;
}
} catch (AtlasBaseException e) {
LOG.error("Got exception for DSL {}, errorCode: {}", query, e.getAtlasErrorCode());
waitOrBailout(pollingAttempts, pollingBackoff, attempt);
}
}
// DSL queries were successful
if (success) {
LOG.info("Polling was success");
break;
} else {
waitOrBailout(pollingAttempts, pollingBackoff, attempt);
}
}
}
private void waitOrBailout(final int pollingAttempts, final int pollingBackoff, final int attempt) throws InterruptedException {
if (attempt == pollingAttempts - 1) {
LOG.error("Polling failed after {} attempts", pollingAttempts);
throw new SkipException("Polling for test data was unsuccessful");
} else {
LOG.warn("Waiting for {} before polling again", pollingBackoff);
Thread.sleep(pollingBackoff);
}
}
@AfterClass
public void teardown() throws Exception {
AtlasGraphProvider.cleanup();
if (useLocalSolr()) {
LocalSolrRunner.stop();
}
}
@DataProvider(name = "comparisonQueriesProvider")
private Object[][] comparisonQueriesProvider() {
......@@ -108,6 +181,7 @@ public class DSLQueriesTest extends BasicTestSetup {
@Test(dataProvider = "comparisonQueriesProvider")
public void comparison(String query, int expected) throws AtlasBaseException {
LOG.debug(query);
AtlasSearchResult searchResult = discoveryService.searchUsingDslQuery(query, DEFAULT_LIMIT, 0);
assertSearchResult(searchResult, expected, query);
......@@ -286,6 +360,7 @@ public class DSLQueriesTest extends BasicTestSetup {
@Test(dataProvider = "syntaxProvider")
public void syntax(String query, int expected) throws AtlasBaseException {
LOG.debug(query);
queryAssert(query, expected, DEFAULT_LIMIT, 0);
queryAssert(query.replace("where", " "), expected, DEFAULT_LIMIT, 0);
}
......@@ -366,6 +441,7 @@ public class DSLQueriesTest extends BasicTestSetup {
@Test(dataProvider = "orderByProvider")
public void orderBy(String query, int expected, String orderBy, boolean ascending) throws AtlasBaseException {
LOG.debug(query);
queryAssert(query, expected, DEFAULT_LIMIT, 0);
queryAssert(query.replace("where", " "), expected, DEFAULT_LIMIT, 0);
}
......@@ -385,6 +461,7 @@ public class DSLQueriesTest extends BasicTestSetup {
@Test(dataProvider = "likeQueriesProvider")
public void likeQueries(String query, int expected) throws AtlasBaseException {
LOG.debug(query);
queryAssert(query, expected, DEFAULT_LIMIT, 0);
queryAssert(query.replace("where", " "), expected, DEFAULT_LIMIT, 0);
}
......@@ -503,6 +580,7 @@ public class DSLQueriesTest extends BasicTestSetup {
@Test(dataProvider = "minMaxCountProvider")
public void minMaxCount(String query, FieldValueValidator fv) throws AtlasBaseException {
LOG.debug(query);
queryAssert(query, fv);
queryAssert(query.replace("where", " "), fv);
}
......@@ -531,6 +609,7 @@ public class DSLQueriesTest extends BasicTestSetup {
@Test(dataProvider = "errorQueriesProvider", expectedExceptions = { AtlasBaseException.class })
public void errorQueries(String query) throws AtlasBaseException {
LOG.debug(query);
discoveryService.searchUsingDslQuery(query, DEFAULT_LIMIT, 0);
}
......
/**
* 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.atlas.repository.impexp;
import com.google.common.collect.Sets;
import org.apache.atlas.exception.AtlasBaseException;
import org.apache.atlas.model.impexp.AtlasExportResult;
import org.apache.atlas.model.impexp.AtlasImportRequest;
import org.apache.atlas.model.impexp.AtlasImportResult;
import org.apache.atlas.model.typedef.AtlasTypesDef;
import org.apache.atlas.repository.store.bootstrap.AtlasTypeDefStoreInitializer;
import org.apache.atlas.store.AtlasTypeDefStore;
import org.apache.atlas.type.AtlasType;
import org.apache.atlas.type.AtlasTypeRegistry;
import org.testng.Assert;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class ImportServiceTestUtils {
public static void verifyImportedEntities(List<String> creationOrder, List<String> processedEntities) {
Set<String> lhs = com.google.common.collect.Sets.newHashSet(creationOrder);
Set<String> rhs = com.google.common.collect.Sets.newHashSet(processedEntities);
Set<String> difference = Sets.difference(lhs, rhs);
Assert.assertNotNull(difference);
Assert.assertEquals(difference.size(), 0);
}
public static void verifyImportedMetrics(AtlasExportResult exportResult, AtlasImportResult importResult) {
Map<String, Integer> metricsForCompare = getImportMetricsForCompare(importResult);
for (Map.Entry<String, Integer> entry : exportResult.getMetrics().entrySet()) {
if(entry.getKey().startsWith("entity") == false ||
entry.getKey().contains("withExtInfo") ||
entry.getKey().contains("Column") ||
entry.getKey().contains("StorageDesc")) continue;
Assert.assertTrue(metricsForCompare.containsKey(entry.getKey()));
Assert.assertEquals(entry.getValue(), metricsForCompare.get(entry.getKey()));
}
}
private static Map<String,Integer> getImportMetricsForCompare(AtlasImportResult result) {
Map<String, Integer> r = new HashMap<>();
for (Map.Entry<String, Integer> entry : result.getMetrics().entrySet()) {
r.put(entry.getKey().replace(":updated", "").replace(":created", ""), entry.getValue());
}
return r;
}
public static void loadModelFromJson(String fileName, AtlasTypeDefStore typeDefStore, AtlasTypeRegistry typeRegistry) throws IOException, AtlasBaseException {
AtlasTypesDef typesFromJson = getAtlasTypesDefFromFile(fileName);
createTypesAsNeeded(typesFromJson, typeDefStore, typeRegistry);
}
private static void createTypesAsNeeded(AtlasTypesDef typesFromJson, AtlasTypeDefStore typeDefStore, AtlasTypeRegistry typeRegistry) throws AtlasBaseException {
AtlasTypesDef typesToCreate = AtlasTypeDefStoreInitializer.getTypesToCreate(typesFromJson, typeRegistry);
if (!typesToCreate.isEmpty()) {
typeDefStore.createTypesDef(typesToCreate);
}
}
private static AtlasTypesDef getAtlasTypesDefFromFile(String fileName) throws IOException {
String sampleTypes = ZipFileResourceTestUtils.getModelJson(fileName);
return AtlasType.fromJson(sampleTypes, AtlasTypesDef.class);
}
public static AtlasImportRequest getDefaultImportRequest() {
return new AtlasImportRequest();
}
public static AtlasImportResult runImportWithParameters(ImportService importService, AtlasImportRequest request, ZipSource source) throws AtlasBaseException, IOException {
final String requestingIP = "1.0.0.0";
final String hostName = "localhost";
final String userName = "admin";
AtlasImportResult result = importService.run(source, request, userName, hostName, requestingIP);
Assert.assertEquals(result.getOperationStatus(), AtlasImportResult.OperationStatus.SUCCESS);
return result;
}
public static void runAndVerifyQuickStart_v1_Import(ImportService importService, ZipSource zipSource) throws AtlasBaseException, IOException {
AtlasExportResult exportResult = zipSource.getExportResult();
List<String> creationOrder = zipSource.getCreationOrder();
AtlasImportRequest request = getDefaultImportRequest();
AtlasImportResult result = runImportWithParameters(importService, request, zipSource);
Assert.assertNotNull(result);
verifyImportedMetrics(exportResult, result);
verifyImportedEntities(creationOrder, result.getProcessedEntities());
}
}
......@@ -17,6 +17,7 @@
*/
package org.apache.atlas.services;
import org.apache.atlas.TestModules;
import org.apache.atlas.exception.AtlasBaseException;
import org.apache.atlas.model.metrics.AtlasMetrics;
import org.apache.atlas.repository.graphdb.AtlasGraph;
......@@ -25,8 +26,10 @@ import org.apache.atlas.type.AtlasTypeRegistry;
import org.apache.commons.configuration.Configuration;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.testng.SkipException;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Guice;
import org.testng.annotations.Test;
import java.util.ArrayList;
......@@ -42,6 +45,7 @@ import static org.mockito.Mockito.*;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
@Guice(modules = TestModules.TestOnlyModule.class)
public class MetricsServiceTest {
private Configuration mockConfig = mock(Configuration.class);
private AtlasTypeRegistry mockTypeRegistry = mock(AtlasTypeRegistry.class);
......@@ -53,10 +57,7 @@ public class MetricsServiceTest {
@BeforeClass
public void init() throws Exception {
if (useLocalSolr()) {
LocalSolrRunner.start();
}
try {
Map<String, Object> mockMap = new HashMap<>();
mockMap.put("a", 1);
mockMap.put("b", 2);
......@@ -68,10 +69,15 @@ public class MetricsServiceTest {
when(mockConfig.getString(anyString(), anyString()))
.thenReturn("count()", "count()", "count()", "count()", "count()", "toList()", "count()", "toList()");
when(mockTypeRegistry.getAllEntityDefNames()).thenReturn(Arrays.asList("a", "b", "c"));
when(mockTypeRegistry.getAllEntityDefNames()).thenReturn(Arrays.asList("a", "b", "c"));
setupMockGraph();
metricsService = new MetricsService(mockConfig, mockGraph);
}
catch(Exception e) {
throw new SkipException("MetricsServicesTest: init failed!", e);
}
}
@AfterClass
public void cleanup() throws Exception {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment