use of co.cask.cdap.app.verification.VerifyResult in project cdap by caskdata.
the class ApplicationVerificationTest method testGoodApplication.
/**
* Good test
*/
@Test
public void testGoodApplication() throws Exception {
ApplicationSpecification appSpec = Specifications.from(new WebCrawlApp());
ApplicationSpecificationAdapter adapter = ApplicationSpecificationAdapter.create(new ReflectionSchemaGenerator());
ApplicationSpecification newSpec = adapter.fromJson(adapter.toJson(appSpec));
ApplicationVerification app = new ApplicationVerification();
VerifyResult result = app.verify(new ApplicationId("test", newSpec.getName()), newSpec);
Assert.assertTrue(result.getMessage(), result.getStatus() == VerifyResult.Status.SUCCESS);
}
use of co.cask.cdap.app.verification.VerifyResult in project cdap by caskdata.
the class FlowVerificationTest method testFlowMissingConnection.
/**
* This test that verification of flow connections
*/
@Test
public void testFlowMissingConnection() throws Exception {
ApplicationSpecification appSpec = Specifications.from(new NoConsumerApp());
ApplicationSpecificationAdapter adapter = ApplicationSpecificationAdapter.create(new ReflectionSchemaGenerator());
ApplicationSpecification newSpec = adapter.fromJson(adapter.toJson(appSpec));
FlowVerification flowVerifier = new FlowVerification();
for (FlowSpecification flowSpec : appSpec.getFlows().values()) {
VerifyResult result = flowVerifier.verify(new ApplicationId("test", newSpec.getName()), flowSpec);
Assert.assertTrue(result.getStatus() == VerifyResult.Status.FAILED);
}
}
use of co.cask.cdap.app.verification.VerifyResult in project cdap by caskdata.
the class FlowVerificationTest method testFlowWithMoreOutputThanWhatInputCanHandle.
@Test
public void testFlowWithMoreOutputThanWhatInputCanHandle() throws Exception {
ApplicationSpecification appSpec = Specifications.from(new WebCrawlApp());
ApplicationSpecificationAdapter adapter = ApplicationSpecificationAdapter.create(new ReflectionSchemaGenerator());
ApplicationSpecification newSpec = adapter.fromJson(adapter.toJson(appSpec));
FlowVerification flowSpec = new FlowVerification();
for (Map.Entry<String, FlowSpecification> entry : newSpec.getFlows().entrySet()) {
VerifyResult result = flowSpec.verify(new ApplicationId("test", newSpec.getName()), entry.getValue());
// that is not connected to any input to flowlet CountByField.
if (entry.getValue().getName().equals("WordCountFlow")) {
Assert.assertTrue(result.getStatus() == VerifyResult.Status.FAILED);
} else {
Assert.assertTrue(result.getStatus() == VerifyResult.Status.SUCCESS);
}
}
}
use of co.cask.cdap.app.verification.VerifyResult in project cdap by caskdata.
the class FlowVerification method verify.
/**
* Verifies a single {@link FlowSpecification} for a {@link co.cask.cdap.api.flow.Flow}.
*
* @param input to be verified
* @return An instance of {@link VerifyResult} depending of status of verification.
*/
@Override
public VerifyResult verify(ApplicationId appId, final FlowSpecification input) {
VerifyResult verifyResult = super.verify(appId, input);
if (!verifyResult.isSuccess()) {
return verifyResult;
}
String flowName = input.getName();
// Check if there are no flowlets.
if (input.getFlowlets().isEmpty()) {
return VerifyResult.failure(Err.Flow.ATLEAST_ONE_FLOWLET, flowName);
}
// Check if there no connections.
if (input.getConnections().isEmpty()) {
return VerifyResult.failure(Err.Flow.ATLEAST_ONE_CONNECTION, flowName);
}
// We go through each Flowlet and verify the flowlets.
// First collect all source flowlet names
Set<String> sourceFlowletNames = Sets.newHashSet();
for (FlowletConnection connection : input.getConnections()) {
if (connection.getSourceType() == FlowletConnection.Type.FLOWLET) {
sourceFlowletNames.add(connection.getSourceName());
}
}
for (Map.Entry<String, FlowletDefinition> entry : input.getFlowlets().entrySet()) {
FlowletDefinition defn = entry.getValue();
String flowletName = defn.getFlowletSpec().getName();
// Check if the Flowlet Name is an ID.
if (!EntityId.isValidId(defn.getFlowletSpec().getName())) {
return VerifyResult.failure(Err.NOT_AN_ID, flowName + ":" + flowletName);
}
// We check if all the dataset names used are ids
for (String dataSet : defn.getDatasets()) {
if (!EntityId.isValidDatasetId(dataSet)) {
return VerifyResult.failure(Err.NOT_AN_ID, flowName + ":" + flowletName + ":" + dataSet);
}
}
// Check if the flowlet has output, it must be appear as source flowlet in at least one connection
if (entry.getValue().getOutputs().size() > 0 && !sourceFlowletNames.contains(flowletName)) {
return VerifyResult.failure(Err.Flow.OUTPUT_NOT_CONNECTED, flowName, flowletName);
}
}
// NOTE: We should unify the logic here and the queue spec generation, as they are doing the same thing.
Table<QueueSpecificationGenerator.Node, String, Set<QueueSpecification>> queueSpecTable = new SimpleQueueSpecificationGenerator(appId).create(input);
// For all connections, there should be an entry in the table.
for (FlowletConnection connection : input.getConnections()) {
QueueSpecificationGenerator.Node node;
if (connection.getSourceType() == FlowletConnection.Type.FLOWLET) {
node = new QueueSpecificationGenerator.Node(connection.getSourceType(), connection.getSourceName());
} else {
String sourceNamespace = connection.getSourceNamespace() == null ? appId.getNamespace() : connection.getSourceNamespace();
node = new QueueSpecificationGenerator.Node(connection.getSourceType(), sourceNamespace, connection.getSourceName());
}
if (!queueSpecTable.contains(node, connection.getTargetName())) {
return VerifyResult.failure(Err.Flow.NO_INPUT_FOR_OUTPUT, flowName, connection.getTargetName(), connection.getSourceType(), connection.getSourceName());
}
}
// For each output entity, check for any unconnected output
for (QueueSpecificationGenerator.Node node : queueSpecTable.rowKeySet()) {
// For stream output, no need to check
if (node.getType() == FlowletConnection.Type.STREAM) {
continue;
}
// For all outputs of a flowlet, remove all the matched connected schema, if there is anything left,
// then it's a incomplete flow connection (has output not connect to any input).
Multimap<String, Schema> outputs = toMultimap(input.getFlowlets().get(node.getName()).getOutputs());
for (Map.Entry<String, Set<QueueSpecification>> entry : queueSpecTable.row(node).entrySet()) {
for (QueueSpecification queueSpec : entry.getValue()) {
outputs.remove(queueSpec.getQueueName().getSimpleName(), queueSpec.getOutputSchema());
}
}
if (!outputs.isEmpty()) {
return VerifyResult.failure(Err.Flow.MORE_OUTPUT_NOT_ALLOWED, flowName, node.getType().toString().toLowerCase(), node.getName(), outputs);
}
}
return VerifyResult.success();
}
use of co.cask.cdap.app.verification.VerifyResult in project cdap by caskdata.
the class ApplicationVerificationStage method verifyPrograms.
protected void verifyPrograms(ApplicationId appId, ApplicationSpecification specification) {
Iterable<ProgramSpecification> programSpecs = Iterables.concat(specification.getFlows().values(), specification.getMapReduce().values(), specification.getWorkflows().values());
VerifyResult result;
for (ProgramSpecification programSpec : programSpecs) {
result = getVerifier(programSpec.getClass()).verify(appId, programSpec);
if (!result.isSuccess()) {
throw new RuntimeException(result.getMessage());
}
}
for (Map.Entry<String, WorkflowSpecification> entry : specification.getWorkflows().entrySet()) {
verifyWorkflowSpecifications(specification, entry.getValue());
}
for (Map.Entry<String, ScheduleCreationSpec> entry : specification.getProgramSchedules().entrySet()) {
String programName = entry.getValue().getProgramName();
if (!specification.getWorkflows().containsKey(programName)) {
throw new RuntimeException(String.format("Schedule '%s' is invalid: Workflow '%s' is not configured " + "in application '%s'", entry.getValue().getName(), programName, specification.getName()));
}
}
}
Aggregations