2 * ============LICENSE_START=======================================================
3 * Copyright (C) 2020 Nordix Foundation
4 * ================================================================================
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 * SPDX-License-Identifier: Apache-2.0
17 * ============LICENSE_END=========================================================
20 package org.openecomp.sdc.be.components.impl;
22 import static org.hamcrest.MatcherAssert.assertThat;
23 import static org.hamcrest.Matchers.aMapWithSize;
24 import static org.hamcrest.Matchers.containsInAnyOrder;
25 import static org.hamcrest.Matchers.equalTo;
26 import static org.hamcrest.Matchers.hasItems;
27 import static org.hamcrest.Matchers.hasSize;
28 import static org.junit.jupiter.api.Assertions.assertEquals;
29 import static org.junit.jupiter.api.Assertions.assertTrue;
30 import static org.junit.jupiter.api.Assertions.fail;
31 import static org.mockito.Mockito.when;
32 import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.DEFAULT;
33 import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.DESCRIPTION;
34 import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.REQUIRED;
35 import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.STATUS;
36 import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.TYPE;
38 import com.google.gson.Gson;
39 import fj.data.Either;
40 import java.io.FileInputStream;
41 import java.io.FileNotFoundException;
42 import java.nio.file.Path;
43 import java.nio.file.Paths;
44 import java.util.Collections;
45 import java.util.HashMap;
46 import java.util.LinkedHashMap;
47 import java.util.List;
49 import java.util.Map.Entry;
50 import java.util.Optional;
51 import java.util.stream.Collectors;
52 import org.apache.commons.collections.MapUtils;
53 import org.apache.commons.lang3.StringUtils;
54 import org.junit.jupiter.api.BeforeEach;
55 import org.junit.jupiter.api.Test;
56 import org.junit.jupiter.api.extension.ExtendWith;
57 import org.mockito.Mock;
58 import org.mockito.junit.jupiter.MockitoExtension;
59 import org.openecomp.sdc.be.datatypes.elements.ArtifactDataDefinition;
60 import org.openecomp.sdc.be.datatypes.elements.InputDataDefinition;
61 import org.openecomp.sdc.be.datatypes.elements.ListDataDefinition;
62 import org.openecomp.sdc.be.datatypes.elements.OperationDataDefinition;
63 import org.openecomp.sdc.be.datatypes.elements.OperationInputDefinition;
64 import org.openecomp.sdc.be.model.InterfaceDefinition;
65 import org.yaml.snakeyaml.Yaml;
67 @ExtendWith(MockitoExtension.class)
68 class InterfaceDefinitionHandlerTest {
71 private InterfaceOperationBusinessLogic interfaceOperationBusinessLogic;
72 private InterfaceDefinitionHandler interfaceDefinitionHandler;
73 private InterfaceDefinition interfaceLifecyleStandard;
74 private static final Path TEST_RESOURCE_PATH = Paths.get("src/test/resources/interfaceDefinition");
75 private static final String CREATE_OPERATION = "create";
76 private static final String DELETE_OPERATION = "delete";
77 private static final String START_OPERATION = "start";
78 private static final String STOP_OPERATION = "stop";
79 private static final String INTERFACE_TYPE = "tosca.interfaces.node.lifecycle.Standard";
83 interfaceDefinitionHandler = new InterfaceDefinitionHandler(interfaceOperationBusinessLogic);
84 mockAllInterfacesLifecycle();
87 private void mockAllInterfacesLifecycle() {
88 final Map<String, InterfaceDefinition> interfaceTypes = new HashMap<>();
89 interfaceLifecyleStandard = new InterfaceDefinition();
90 interfaceLifecyleStandard.setType(INTERFACE_TYPE);
91 final Map<String, OperationDataDefinition> operations = new HashMap<>();
92 operations.put(CREATE_OPERATION, new OperationDataDefinition());
93 operations.put(START_OPERATION, new OperationDataDefinition());
94 operations.put(STOP_OPERATION, new OperationDataDefinition());
95 operations.put(DELETE_OPERATION, new OperationDataDefinition());
96 interfaceLifecyleStandard.setOperations(operations);
97 interfaceTypes.put(INTERFACE_TYPE, interfaceLifecyleStandard);
98 when(interfaceOperationBusinessLogic.getAllInterfaceLifecycleTypes(StringUtils.EMPTY)).thenReturn(Either.left(interfaceTypes));
102 void testCreateWithLegacyOperationDeclarationSuccess() throws FileNotFoundException {
103 final Map<String, Object> load = loadYaml(Paths.get("interfaceDefinition-legacy.yaml"));
104 final InterfaceDefinition actualInterfaceDefinition = interfaceDefinitionHandler.create(load, StringUtils.EMPTY);
105 assertInterfaceDefinition(actualInterfaceDefinition);
109 void testCreateWithOperationSuccess() throws FileNotFoundException {
110 final Map<String, Object> load = loadYaml(Paths.get("interfaceDefinition-tosca1.3.yaml"));
111 final InterfaceDefinition actualInterfaceDefinition = interfaceDefinitionHandler.create(load, StringUtils.EMPTY);
112 assertInterfaceDefinition(actualInterfaceDefinition);
115 private void assertInterfaceDefinition(final InterfaceDefinition actualInterfaceDefinition) {
116 interfaceLifecyleStandard.getOperations().keySet().forEach(operation ->
117 assertTrue(actualInterfaceDefinition.hasOperation(operation)));
118 assertThat("Interface type should be as expected", actualInterfaceDefinition.getType(),
119 equalTo(actualInterfaceDefinition.getType()));
120 assertThat("Interface should contain 2 inputs", actualInterfaceDefinition.getInputs(), aMapWithSize(2));
121 assertThat("Interface inputs should be as expected", actualInterfaceDefinition.getInputs().keySet(),
122 containsInAnyOrder("stringInput", "actionInput"));
124 final InputDataDefinition stringInput = actualInterfaceDefinition.getInputs().get("stringInput");
125 assertInput("string", "stringInput description", true, "defaultValue", "aStatus", stringInput);
126 final InputDataDefinition actionInput = actualInterfaceDefinition.getInputs().get("actionInput");
127 assertInput("org.openecomp.resource.datatypes.Action", null, false, null, null, actionInput);
129 final OperationDataDefinition createOperation = actualInterfaceDefinition.getOperations().get(CREATE_OPERATION);
130 assertOperation("'camunda/serviceSelect'", createOperation);
132 final OperationDataDefinition deleteOperation = actualInterfaceDefinition.getOperations().get(DELETE_OPERATION);
133 assertOperation("'camunda/serviceDeselect'", deleteOperation);
135 final Map<String, Map<String, Object>> startOperationExpectedInputMap = createStartOperationInputMap();
136 final OperationDataDefinition startOperation = actualInterfaceDefinition.getOperations().get(START_OPERATION);
137 assertOperation("'camunda/executeAction'", startOperationExpectedInputMap, startOperation);
138 final Map<String, Map<String, Object>> stopOperationExpectedInputMap = createStopOperationInputMap();
139 final OperationDataDefinition stopOperation = actualInterfaceDefinition.getOperations().get(STOP_OPERATION);
140 assertOperation("'camunda/executeAction'", stopOperationExpectedInputMap, stopOperation);
143 private Map<String, Map<String, Object>> createStopOperationInputMap() {
144 final Map<String, Map<String, Object>> stopOperationExpectedInputMap = new HashMap<>();
145 final Map<String, Object> actionInput = Map.of(
146 "type", "org.openecomp.resource.datatypes.Action"
148 stopOperationExpectedInputMap.put("action", actionInput);
149 return stopOperationExpectedInputMap;
152 private Map<String, Map<String, Object>> createStartOperationInputMap() {
153 final Map<String, Map<String, Object>> startOperationExpectedInputMap = new HashMap<>();
154 final Map<String, Object> actionInput = Map.of(
155 "type", "org.openecomp.resource.datatypes.Action"
157 startOperationExpectedInputMap.put("action", actionInput);
158 final Map<String, Object> stringInput = Map.of(
160 "default", "this is a string"
162 startOperationExpectedInputMap.put("stringInput", stringInput);
163 final Map<String, Object> booleanInput = Map.of(
167 startOperationExpectedInputMap.put("booleanInput", booleanInput);
168 final Map<String, Object> integerInput = Map.of(
170 "description", "an integer",
171 "status", "supported",
175 startOperationExpectedInputMap.put("integerInput", integerInput);
176 final Map<String, Object> floatInput = Map.of(
181 startOperationExpectedInputMap.put("floatInput", floatInput);
183 final LinkedHashMap<String, Object> complexInputDefault = new LinkedHashMap<>();
184 complexInputDefault.put("dsl_stability_profile", "dsl_stability_profile_value");
185 complexInputDefault.put("central_splitter", false);
186 complexInputDefault.put("service_restoration_sla", "service_restoration_sla_value");
187 complexInputDefault.put("battery_backup", true);
188 complexInputDefault.put("partner_priorty_assist", false);
189 final Map<String, Object> complexInput = Map.of(
190 "type", "onap.datatypes.partner.access_details",
191 "status", "experimental",
192 "default", complexInputDefault
194 startOperationExpectedInputMap.put("complexInput", complexInput);
195 return startOperationExpectedInputMap;
198 private void assertOperation(final String implementation, final OperationDataDefinition actualOperation) {
199 assertOperation(implementation, Collections.emptyMap(), actualOperation);
202 private void assertOperation(final String implementation, final Map<String, Map<String, Object>> inputNameTypeMap,
203 final OperationDataDefinition actualOperation) {
204 final ArtifactDataDefinition artifactDefinition = actualOperation.getImplementation();
205 assertThat("Implementation should be as expected", artifactDefinition.getArtifactName(), equalTo(implementation));
206 final ListDataDefinition<OperationInputDefinition> inputListDataDef = actualOperation.getInputs();
207 if (inputListDataDef == null) {
208 if (MapUtils.isNotEmpty(inputNameTypeMap)) {
209 final String expectedInputNames = String.join(",", inputNameTypeMap.keySet());
210 fail(String.format("No inputs were found, but some inputs are expected: %s", expectedInputNames));
215 final String msgFormat = "Operation should have %s";
216 final List<OperationInputDefinition> inputList = inputListDataDef.getListToscaDataDefinition();
217 assertThat(String.format(msgFormat, "the expected quantity of inputs"), inputList, hasSize(inputNameTypeMap.size()));
219 final List<String> inputNames = inputList.stream()
220 .map(OperationInputDefinition::getName).collect(Collectors.toList());
222 assertThat(String.format(msgFormat, "the expected inputs"), inputNames,
223 hasItems(inputNameTypeMap.keySet().toArray(new String[0])));
225 for (final Entry<String, Map<String, Object>> inputEntry : inputNameTypeMap.entrySet()) {
226 final String expectedInputName = inputEntry.getKey();
227 final Optional<OperationInputDefinition> inputDefinitionOptional = inputList.stream()
228 .filter(operationInputDefinition -> operationInputDefinition.getName().equals(expectedInputName)).findFirst();
229 assertTrue(inputDefinitionOptional.isPresent(), String.format("Input '%s' should be present", expectedInputName));
230 final OperationInputDefinition actualInputDefinition = inputDefinitionOptional.get();
231 final Map<String, Object> expectedInput = inputEntry.getValue();
233 assertEquals(expectedInput.get(STATUS.getElementName()), actualInputDefinition.getStatus(),
234 String.format("%s attribute of input %s should be as expected", STATUS.getElementName(), expectedInputName)
236 assertEquals(expectedInput.get(TYPE.getElementName()), actualInputDefinition.getType(),
237 String.format("%s attribute of input %s should be as expected", TYPE.getElementName(), expectedInputName)
239 assertEquals(expectedInput.get(DESCRIPTION.getElementName()), actualInputDefinition.getDescription(),
240 String.format("%s attribute of input %s should be as expected", DESCRIPTION.getElementName(), expectedInputName)
242 final Object expectedRequired =
243 expectedInput.get(REQUIRED.getElementName()) == null ? false : expectedInput.get(REQUIRED.getElementName());
244 assertEquals(expectedRequired, actualInputDefinition.getRequired(),
245 String.format("%s attribute of input %s should be as expected", REQUIRED.getElementName(), expectedInputName)
248 String expectedJson = null;
249 if (expectedInput.get(DEFAULT.getElementName()) != null) {
250 expectedJson = new Gson().toJson(expectedInput.get(DEFAULT.getElementName()));
252 assertEquals(expectedJson, actualInputDefinition.getToscaDefaultValue(),
253 String.format("%s of input %s should be as expected", DEFAULT.getElementName(), expectedInputName)
258 private void assertInput(final String type, final String description, final Boolean required,
259 final String defaultValue, final String status, final InputDataDefinition actualInput) {
260 assertThat("Input type should be as expected", type, equalTo(actualInput.getType()));
261 assertThat("Input description should be as expected", description, equalTo(actualInput.getDescription()));
262 assertThat("Input required should be as expected", required, equalTo(required != null && required));
263 assertThat("Input default should be as expected", defaultValue, equalTo(actualInput.getDefaultValue()));
264 assertThat("Input status should be as expected", status, equalTo(actualInput.getStatus()));
267 private Map<String, Object> loadYaml(final Path filePathFromResource) throws FileNotFoundException {
268 final Path filePath = Paths.get(TEST_RESOURCE_PATH.toString(), filePathFromResource.toString());
269 final FileInputStream fileInputStream = new FileInputStream(filePath.toString());
270 return new Yaml().load(fileInputStream);