diff options
Diffstat (limited to 'src/test')
17 files changed, 607 insertions, 319 deletions
diff --git a/src/test/java/org/onap/aai/modelloader/DistributionClientTestConfiguration.java b/src/test/java/org/onap/aai/modelloader/DistributionClientTestConfiguration.java new file mode 100644 index 0000000..1eed62f --- /dev/null +++ b/src/test/java/org/onap/aai/modelloader/DistributionClientTestConfiguration.java @@ -0,0 +1,81 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2024 Deutsche Telekom AG Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed 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. + * ============LICENSE_END========================================================= + */ +package org.onap.aai.modelloader; + +import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; +import static com.github.tomakehurst.wiremock.client.WireMock.equalTo; +import static com.github.tomakehurst.wiremock.client.WireMock.get; +import static com.github.tomakehurst.wiremock.client.WireMock.matching; +import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; +import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.Properties; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.context.event.ApplicationStartedEvent; +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Primary; +import org.springframework.context.event.EventListener; + +@TestConfiguration +public class DistributionClientTestConfiguration { + + @Value("${CONFIG_HOME}") + private String configDir; + + @Value("${wiremock.server.port}") + private int wiremockPort; + + @Primary + @Bean(name = "testProperties") + public Properties configProperties() throws IOException { + // Load model loader system configuration + InputStream configInputStream = Files.newInputStream(Paths.get(configDir, "model-loader.properties")); + Properties configProperties = new Properties(); + configProperties.load(configInputStream); + + setOverrides(configProperties); + + return configProperties; + } + + private void setOverrides(Properties configProperties) { + configProperties.setProperty("ml.distribution.ASDC_ADDRESS", "localhost:" + wiremockPort); + configProperties.setProperty("ml.babel.BASE_URL", "http://localhost:" + wiremockPort); + } + + @EventListener(ApplicationStartedEvent.class) + public void mockSdcInit() { + stubFor(get(urlEqualTo("/sdc/v1/artifactTypes")) + .withHeader("X-ECOMP-RequestID", matching(".+")) + .withHeader("X-ECOMP-InstanceID", equalTo("aai-ml-id-test")) + .willReturn(aResponse().withHeader("Content-Type", "application/json").withBodyFile("artifactTypes.json"))); + + stubFor(get(urlEqualTo("/sdc/v1/distributionKafkaData")) + .withHeader("X-ECOMP-RequestID", matching(".+")) + .withHeader("X-ECOMP-InstanceID", equalTo("aai-ml-id-test")) + .willReturn(aResponse().withHeader("Content-Type", "application/json").withBodyFile("kafkaBootstrap.json"))); + } +}
\ No newline at end of file diff --git a/src/test/java/org/onap/aai/modelloader/TestModelLoaderApplication.java b/src/test/java/org/onap/aai/modelloader/TestModelLoaderApplication.java deleted file mode 100644 index cd39066..0000000 --- a/src/test/java/org/onap/aai/modelloader/TestModelLoaderApplication.java +++ /dev/null @@ -1,44 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 European Software Marketing Ltd. - * ================================================================================ - * Licensed 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. - * ============LICENSE_END========================================================= - */ -package org.onap.aai.modelloader; - -import static org.junit.jupiter.api.Assertions.assertTrue; - -import org.junit.jupiter.api.Test; - -/** - * Tests for ModelLoaderApplication class. - * - */ -public class TestModelLoaderApplication { - - static { - System.setProperty("CONFIG_HOME", "src/test/resources"); - } - - @Test - public void testServiceStarts() { - // The SDC Distribution Client is disabled. - ModelLoaderApplication.main(new String[0]); - assertTrue(true); - } - -} diff --git a/src/test/java/org/onap/aai/modelloader/distribution/NotificationIntegrationTest.java b/src/test/java/org/onap/aai/modelloader/distribution/NotificationIntegrationTest.java index 2645871..abdefd4 100644 --- a/src/test/java/org/onap/aai/modelloader/distribution/NotificationIntegrationTest.java +++ b/src/test/java/org/onap/aai/modelloader/distribution/NotificationIntegrationTest.java @@ -26,6 +26,7 @@ import java.util.concurrent.TimeUnit; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; +import org.onap.aai.modelloader.notification.NotificationDataImpl; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.test.context.SpringBootTest; @@ -35,25 +36,26 @@ import org.springframework.test.annotation.DirtiesContext; @DirtiesContext @SpringBootTest(properties = { "model-loader.sdc.connection.enabled=true"}) -@EmbeddedKafka(partitions = 1, brokerProperties = { "listeners=PLAINTEXT://localhost:9092", "port=9092" }) +@EmbeddedKafka(partitions = 1, ports = 9092, topics = {"${topics.distribution.notification}"}) public class NotificationIntegrationTest { @Autowired EventCallbackAspect eventCallbackAspect; @Autowired - private KafkaTemplate<String, String> kafkaTemplate; + private KafkaTemplate<String, NotificationDataImpl> kafkaTemplate; - @Value("${test.topic}") + @Value("${topics.distribution.notification}") private String topic; @Test @Disabled("This test is not yet implemented") public void thatActivateCallbackIsCalled() throws Exception { - String data = "Smth"; - + NotificationDataImpl notificationData = new NotificationDataImpl(); + notificationData.setDistributionID("distributionID"); + // TODO: send distribution event here - kafkaTemplate.send(topic, data); + kafkaTemplate.send(topic, notificationData); // TODO: mock distribution client requests to /sdc/v1/artifactTypes // TODO: mock distribution client requests to /sdc/v1/distributionKafkaData diff --git a/src/test/java/org/onap/aai/modelloader/notification/ArtifactDownloadManagerTest.java b/src/test/java/org/onap/aai/modelloader/notification/ArtifactDownloadManagerTest.java new file mode 100644 index 0000000..0985790 --- /dev/null +++ b/src/test/java/org/onap/aai/modelloader/notification/ArtifactDownloadManagerTest.java @@ -0,0 +1,107 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2024 Deutsche Telekom AG Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed 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. + * ============LICENSE_END========================================================= + */ +package org.onap.aai.modelloader.notification; + +import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; +import static com.github.tomakehurst.wiremock.client.WireMock.equalTo; +import static com.github.tomakehurst.wiremock.client.WireMock.get; +import static com.github.tomakehurst.wiremock.client.WireMock.matching; +import static com.github.tomakehurst.wiremock.client.WireMock.matchingJsonPath; +import static com.github.tomakehurst.wiremock.client.WireMock.post; +import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; +import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.http.entity.ContentType; +import org.junit.jupiter.api.Test; +import org.onap.aai.modelloader.DistributionClientTestConfiguration; +import org.onap.aai.modelloader.entity.Artifact; +import org.onap.aai.modelloader.entity.ArtifactType; +import org.onap.aai.modelloader.service.ArtifactInfoImpl; +import org.onap.sdc.api.notification.IArtifactInfo; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.cloud.contract.wiremock.AutoConfigureWireMock; +import org.springframework.context.annotation.Import; +import org.springframework.http.MediaType; +import org.springframework.kafka.test.context.EmbeddedKafka; +import org.springframework.test.annotation.DirtiesContext; + +import com.fasterxml.jackson.core.JsonProcessingException; + +@DirtiesContext +@AutoConfigureWireMock(port = 0) +@EmbeddedKafka(partitions = 1, ports = 9092, topics = {"${topics.distribution.notification}"}) +@SpringBootTest(properties = { "ml.distribution.connection.enabled=true" }) +@Import(DistributionClientTestConfiguration.class) +public class ArtifactDownloadManagerTest { + + @Autowired ArtifactDownloadManager artifactDownloadManager; + + @Test + public void downloadArtifacts() throws JsonProcessingException { + NotificationDataImpl notificationData = new NotificationDataImpl(); + notificationData.setDistributionID("distributionID"); + notificationData.setServiceVersion("2.0"); + + stubFor(get(urlEqualTo("/sdc/v1/catalog/services/DemovlbCds/1.0/artifacts/service-TestSvc-csar.csar")) + .withHeader("Accept", equalTo(ContentType.APPLICATION_OCTET_STREAM.toString())) + .withHeader("X-ECOMP-RequestID", matching(".+")) + .withHeader("X-ECOMP-InstanceID", equalTo("aai-ml-id-test")) + .willReturn(aResponse() + .withHeader("Content-Type", MediaType.APPLICATION_OCTET_STREAM.toString()) + .withBodyFile("service-TestSvc-csar.csar"))); + + stubFor( + post(urlEqualTo("/services/babel-service/v1/app/generateArtifacts")) + .withHeader("X-TransactionId", equalTo("distributionID")) + .withHeader("X-FromAppId", equalTo("ModelLoader")) + .withHeader("Content-Type", equalTo(MediaType.APPLICATION_JSON_VALUE)) + .withRequestBody(matchingJsonPath("$.artifactName", equalTo("service-TestSvc-csar.csar"))) + .withRequestBody(matchingJsonPath("$.artifactVersion", equalTo("2.0"))) + .withRequestBody(matchingJsonPath("$.csar", matching(".*"))) + .willReturn( + aResponse() + .withHeader("Content-Type", "application/json") + .withBodyFile("service-TestSvc-csar-babel-response.json"))); + + ArtifactInfoImpl artifactInfo = new ArtifactInfoImpl(); + artifactInfo.setArtifactName("service-TestSvc-csar.csar"); + artifactInfo.setArtifactVersion("1.0"); + artifactInfo.setArtifactURL("/sdc/v1/catalog/services/DemovlbCds/1.0/artifacts/service-TestSvc-csar.csar"); + artifactInfo.setArtifactType("TOSCA_CSAR"); + artifactInfo.setArtifactChecksum("ZmI5NzQ1MWViZGFkMjRjZWEwNTQzY2U0OWQwYjlmYjQ="); + artifactInfo.setArtifactUUID("f6f907f1-3f45-4fb4-8cbe-15a4c6ee16db"); + List<IArtifactInfo> artifacts = new ArrayList<>(); + artifacts.add(artifactInfo); + List<Artifact> modelArtifacts = new ArrayList<>(); // processed artifacts will be written to this list + List<Artifact> catalogArtifacts = new ArrayList<>(); // processed artifacts will be written to this list + boolean result = artifactDownloadManager.downloadArtifacts(notificationData, artifacts, modelArtifacts, catalogArtifacts); + + assertEquals(1, modelArtifacts.size()); + assertEquals(ArtifactType.MODEL, modelArtifacts.get(0).getType()); + assertTrue(result); + } + +} diff --git a/src/test/java/org/onap/aai/modelloader/notification/ModelArtifactHandlerTest.java b/src/test/java/org/onap/aai/modelloader/notification/ModelArtifactHandlerTest.java new file mode 100644 index 0000000..b1269ee --- /dev/null +++ b/src/test/java/org/onap/aai/modelloader/notification/ModelArtifactHandlerTest.java @@ -0,0 +1,226 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2024 Deutsche Telekom AG Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed 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. + * ============LICENSE_END========================================================= + */ +package org.onap.aai.modelloader.notification; + +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.when; +import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; +import static com.github.tomakehurst.wiremock.client.WireMock.verify; +import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo; +import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; +import static com.github.tomakehurst.wiremock.client.WireMock.deleteRequestedFor; +import static com.github.tomakehurst.wiremock.client.WireMock.equalTo; +import static com.github.tomakehurst.wiremock.client.WireMock.ok; + +import java.util.List; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.onap.aai.modelloader.config.ModelLoaderConfig; +import org.onap.aai.modelloader.entity.Artifact; +import org.onap.aai.modelloader.entity.model.ModelArtifact; +import org.onap.aai.modelloader.entity.model.ModelArtifactHandler; +import org.onap.aai.modelloader.restclient.AaiRestClient; +import org.onap.aai.restclient.client.OperationResult; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.cloud.contract.wiremock.AutoConfigureWireMock; +import org.springframework.http.HttpStatus; +import org.springframework.web.client.RestTemplate; +import org.w3c.dom.Node; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.github.tomakehurst.wiremock.client.WireMock; + +import java.util.ArrayList; + +@SpringBootTest +@AutoConfigureWireMock(port = 0) +public class ModelArtifactHandlerTest { + + @Value("${wiremock.server.port}") + private int wiremockPort; + + final ObjectMapper objectMapper = new ObjectMapper(); + @Mock + ModelLoaderConfig config; + @InjectMocks + ModelArtifactHandler modelArtifactHandler; + + @Autowired + AaiRestClient restClient; + + @BeforeEach + public void setUp() { + when(config.getAaiBaseUrl()).thenReturn("http://localhost:" + wiremockPort); + when(config.getAaiModelUrl(any())).thenReturn("/aai/v28/service-design-and-creation/models/model/"); + } + + @Test + public void thatArtifactsCanBeCreated() { + WireMock.stubFor( + WireMock.get(urlEqualTo("/aai/v28/service-design-and-creation/models/model/modelInvariantId")) + .withHeader("Accept", equalTo("application/xml")) + .withHeader("X-TransactionId", equalTo("someId")) + .withHeader("X-FromAppId", equalTo("ModelLoader")) + .willReturn( + WireMock.aResponse() + .withStatus(HttpStatus.NOT_FOUND.value()))); + + WireMock.stubFor( + WireMock.put(urlEqualTo("/aai/v28/service-design-and-creation/models/model/modelInvariantId")) + .withHeader("Content-Type", equalTo("application/xml")) + .withHeader("X-TransactionId", equalTo("someId")) + .withHeader("X-FromAppId", equalTo("ModelLoader")) + .willReturn( + WireMock.aResponse() + .withStatus(HttpStatus.CREATED.value()))); + + ModelArtifact modelArtifact = new ModelArtifact(); + modelArtifact.setModelInvariantId("modelInvariantId"); + List<Artifact> artifacts = List.of(modelArtifact); + List<Artifact> completedArtifacts = new ArrayList<>(); + + boolean result = modelArtifactHandler.pushArtifacts(artifacts, + "someId", completedArtifacts, restClient); + assertTrue(result); + WireMock.verify( + WireMock.putRequestedFor(urlEqualTo("/aai/v28/service-design-and-creation/models/model/modelInvariantId"))); + } + + @Test + public void thatArtifactsCanBeUpdated() { + // Checks if model exists in resources service + WireMock.stubFor( + WireMock.get(urlEqualTo("/aai/v28/service-design-and-creation/models/model/modelInvariantId")) + .withHeader("Accept", equalTo("application/xml")) + .withHeader("X-TransactionId", equalTo("distributionId")) + .withHeader("X-FromAppId", equalTo("ModelLoader")) + .willReturn( + WireMock.aResponse() + .withStatus(HttpStatus.OK.value()))); + + // Checks if specific version of model exists in aai-resources + WireMock.stubFor( + WireMock.get(urlEqualTo( + "/aai/v28/service-design-and-creation/models/model/modelInvariantId/model-vers/model-ver/modelVersionId")) + .withHeader("Accept", equalTo("application/xml")) + .withHeader("X-TransactionId", equalTo("distributionId")) + .withHeader("X-FromAppId", equalTo("ModelLoader")) + .willReturn( + WireMock.aResponse() + .withStatus(HttpStatus.NOT_FOUND.value()))); + + WireMock.stubFor( + WireMock.put(urlEqualTo( + "/aai/v28/service-design-and-creation/models/model/modelInvariantId/model-vers/model-ver/modelVersionId")) + .withHeader("Content-Type", equalTo("application/xml")) + .withHeader("X-TransactionId", equalTo("distributionId")) + .withHeader("X-FromAppId", equalTo("ModelLoader")) + .willReturn( + WireMock.aResponse() + .withStatus(HttpStatus.CREATED.value()))); + + ModelArtifact modelArtifact = new ModelArtifact(); + modelArtifact.setModelInvariantId("modelInvariantId"); + modelArtifact.setModelVerId("modelVersionId"); + Node node = Mockito.mock(Node.class); + modelArtifact.setModelVer(node); + List<Artifact> artifacts = List.of(modelArtifact); + List<Artifact> completedArtifacts = new ArrayList<>(); + + boolean result = modelArtifactHandler.pushArtifacts(artifacts, + "distributionId", completedArtifacts, restClient); + verify(WireMock.putRequestedFor(urlEqualTo( + "/aai/v28/service-design-and-creation/models/model/modelInvariantId/model-vers/model-ver/modelVersionId"))); + assertTrue(result); + } + + @Test + public void thatModelCanBeRolledBack() { + stubFor(WireMock.get(urlEqualTo("/aai/v28/service-design-and-creation/models/model/3a40ab73-6694-4e75-bb6d-9a4a86ce35b3")) + .withHeader("X-FromAppId", equalTo("ModelLoader")) + .withHeader("X-TransactionId", equalTo("distributionId")) + .willReturn(aResponse() + .withBodyFile("modelResponse.xml"))); + + stubFor(WireMock.delete(urlEqualTo("/aai/v28/service-design-and-creation/models/model/3a40ab73-6694-4e75-bb6d-9a4a86ce35b3?resource-version=1710523260974")) + .withHeader("X-FromAppId", equalTo("ModelLoader")) + .withHeader("X-TransactionId", equalTo("distributionId")) + .willReturn(aResponse().withStatus(HttpStatus.OK.value()))); + + ModelArtifact modelArtifact = new ModelArtifact(); + modelArtifact.setModelInvariantId("3a40ab73-6694-4e75-bb6d-9a4a86ce35b3"); + modelArtifact.setModelVerId("modelVersionId"); + Node node = Mockito.mock(Node.class); + modelArtifact.setModelVer(node); + List<Artifact> completedArtifacts = new ArrayList<>(); + completedArtifacts.add(modelArtifact); + + mockModelCreation(modelArtifact); + + modelArtifactHandler.rollback(completedArtifacts, "distributionId", restClient); + + verify( + deleteRequestedFor( + urlEqualTo("/aai/v28/service-design-and-creation/models/model/3a40ab73-6694-4e75-bb6d-9a4a86ce35b3?resource-version=1710523260974"))); + } + + /** + * To test the rollback of the full model, the ModelArtifact must have the + * firstVersionOfModel = true state. + * This flag is set during the model creation and thus needs to run before + * testing this particular aspect. + * + * @param modelArtifact + */ + private void mockModelCreation(ModelArtifact modelArtifact) { + OperationResult createdResult = Mockito.mock(OperationResult.class); + when(createdResult.getResultCode()).thenReturn(HttpStatus.CREATED.value()); + OperationResult notFoundResult = Mockito.mock(OperationResult.class); + when(notFoundResult.getResultCode()).thenReturn(HttpStatus.NOT_FOUND.value()); + AaiRestClient aaiClient = Mockito.mock(AaiRestClient.class); + when(aaiClient.putResource(any(), any(), any(), any())).thenReturn(createdResult); + when(aaiClient.getResource(any(), any(), any())).thenReturn(notFoundResult); + modelArtifact.push(aaiClient, config, null, new ArrayList<>()); + } + + @Test + public void thatModelVersionCanBeRolledBack() { + + // "http://localhost:10594/aai/v28/service-design-and-creation/models/model/modelInvariantId/model-vers/model-ver/modelVersionId" + + ModelArtifact modelArtifact = new ModelArtifact(); + modelArtifact.setModelInvariantId("modelInvariantId"); + modelArtifact.setModelVerId("modelVersionId"); + Node node = Mockito.mock(Node.class); + modelArtifact.setModelVer(node); + List<Artifact> completedArtifacts = new ArrayList<>(); + completedArtifacts.add(modelArtifact); + + modelArtifactHandler.rollback(completedArtifacts, "distributionId", restClient); + + } +}
\ No newline at end of file diff --git a/src/test/java/org/onap/aai/modelloader/notification/TestNotificationDataImpl.java b/src/test/java/org/onap/aai/modelloader/notification/TestNotificationDataImpl.java deleted file mode 100644 index 4d6858a..0000000 --- a/src/test/java/org/onap/aai/modelloader/notification/TestNotificationDataImpl.java +++ /dev/null @@ -1,83 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 European Software Marketing Ltd. - * ================================================================================ - * Licensed 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. - * ============LICENSE_END========================================================= - */ -package org.onap.aai.modelloader.notification; - -import static org.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.CoreMatchers.not; -import static org.hamcrest.MatcherAssert.assertThat; - -import org.junit.jupiter.api.Test; - -/** - * Tests for NotificationDataImpl class - * - */ -public class TestNotificationDataImpl { - - @Test - public void testGettersAndSetters() { - NotificationDataImpl data = new NotificationDataImpl(); - String distributionId = "testid"; - - data.setDistributionID(distributionId); - assertThat(data.getDistributionID(), is(equalTo(distributionId))); - - // Getters return empty data - assertThat(data.getArtifactMetadataByUUID(null), is(equalTo(null))); - assertThat(data.getServiceDescription(), is(equalTo(null))); - assertThat(data.getServiceInvariantUUID(), is(equalTo(null))); - assertThat(data.getServiceName(), is(equalTo(null))); - assertThat(data.getServiceUUID(), is(equalTo(null))); - assertThat(data.getServiceVersion(), is(equalTo(null))); - assertThat(data.getResources().size(), is(0)); - assertThat(data.getServiceArtifacts().size(), is(0)); - - // Unsupported method! - String context = "testcontext"; - data.setWorkloadContext(context); - assertThat(data.getWorkloadContext(), is(equalTo(null))); - } - - - @Test - public void testEquality() { - NotificationDataImpl data = new NotificationDataImpl(); - assertThat(data, is(not(equalTo(null)))); - assertThat(data, is(not(equalTo("")))); // NOSONAR - assertThat(data, is(equalTo(data))); - - NotificationDataImpl other = new NotificationDataImpl(); - assertThat(data, is(equalTo(other))); - assertThat(data.hashCode(), is(equalTo(other.hashCode()))); - - other.setDistributionID(""); - assertThat(data, is(not(equalTo(other)))); - - data.setDistributionID("1234"); - assertThat(data, is(not(equalTo(other)))); - - other.setDistributionID("1234"); - assertThat(data, is(equalTo(other))); - assertThat(data.hashCode(), is(equalTo(other.hashCode()))); - } - -} diff --git a/src/test/java/org/onap/aai/modelloader/restclient/TestBabelServiceClient.java b/src/test/java/org/onap/aai/modelloader/restclient/TestBabelServiceClient.java index 77e1594..169943c 100644 --- a/src/test/java/org/onap/aai/modelloader/restclient/TestBabelServiceClient.java +++ b/src/test/java/org/onap/aai/modelloader/restclient/TestBabelServiceClient.java @@ -20,68 +20,65 @@ */ package org.onap.aai.modelloader.restclient; -import static javax.servlet.http.HttpServletResponse.SC_OK; -import static org.apache.commons.io.IOUtils.write; import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.MatcherAssert.assertThat; import java.io.IOException; import java.net.URISyntaxException; -import java.nio.charset.Charset; import java.nio.file.Files; import java.nio.file.Paths; -import java.util.ArrayList; import java.util.List; import java.util.Properties; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.eclipse.jetty.server.Handler; -import org.eclipse.jetty.server.Request; -import org.eclipse.jetty.server.Server; -import org.eclipse.jetty.server.handler.AbstractHandler; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.onap.aai.babel.service.data.BabelArtifact; import org.onap.aai.modelloader.config.ModelLoaderConfig; import org.onap.aai.modelloader.service.HttpsBabelServiceClientFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.cloud.contract.wiremock.AutoConfigureWireMock; -import com.google.gson.Gson; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.github.tomakehurst.wiremock.client.WireMock; +import com.github.tomakehurst.wiremock.matching.EqualToPattern; /** * Local testing of the Babel service client. * */ +@SpringBootTest +@AutoConfigureWireMock(port = 0) public class TestBabelServiceClient { - private Server server; - private String responseBody; - - @BeforeEach - public void startJetty() throws Exception { - List<BabelArtifact> response = new ArrayList<>(); - response.add(new BabelArtifact("", null, "")); - response.add(new BabelArtifact("", null, "")); - response.add(new BabelArtifact("", null, "")); - responseBody = new Gson().toJson(response); - - server = new Server(0); - server.setHandler(getMockHandler()); - server.start(); - } + @Value("${wiremock.server.port}") + private int wiremockPort; - @AfterEach - public void stopJetty() throws Exception { - server.stop(); + @BeforeAll + public static void setup() throws JsonProcessingException { + ObjectMapper objectMapper = new ObjectMapper(); + List<BabelArtifact> artifacts = List.of( + new BabelArtifact("art1", null, ""), + new BabelArtifact("art2", null, ""), + new BabelArtifact("art3", null, "")); + WireMock.stubFor( + WireMock.post(WireMock.urlEqualTo("/generate")) + .withHeader("X-TransactionId", WireMock.equalTo("Test-Transaction-ID-BabelClient")) + .withHeader("X-FromAppId", WireMock.equalTo("ModelLoader")) + .withRequestBody(WireMock.matchingJsonPath("$.artifactName", WireMock.equalTo("service-Vscpass-Test"))) + .withRequestBody(WireMock.matchingJsonPath("$.artifactVersion", WireMock.equalTo("1.0"))) + .withRequestBody(WireMock.matchingJsonPath("$.csar", WireMock.matching(".*"))) + .willReturn( + WireMock.aResponse() + .withHeader("Content-Type", "application/json") + .withBody(objectMapper.writeValueAsString(artifacts)))); } @Test public void testRestClient() throws BabelServiceClientException, IOException, URISyntaxException { - String url = server.getURI().toString(); + String url = "http://localhost:" + wiremockPort; Properties configProperties = new Properties(); configProperties.put("ml.babel.KEYSTORE_PASSWORD", "OBF:1vn21ugu1saj1v9i1v941sar1ugw1vo0"); configProperties.put("ml.babel.KEYSTORE_FILE", "src/test/resources/auth/aai-client-dummy.p12"); @@ -89,7 +86,7 @@ public class TestBabelServiceClient { // In a real deployment this would be a different file (to the client keystore) configProperties.put("ml.babel.TRUSTSTORE_FILE", "src/test/resources/auth/aai-client-dummy.p12"); configProperties.put("ml.babel.BASE_URL", url); - configProperties.put("ml.babel.GENERATE_ARTIFACTS_URL", "generate"); + configProperties.put("ml.babel.GENERATE_ARTIFACTS_URL", "/generate"); configProperties.put("ml.aai.RESTCLIENT_CONNECT_TIMEOUT", "12000"); configProperties.put("ml.aai.RESTCLIENT_READ_TIMEOUT", "12000"); BabelServiceClient client = @@ -102,11 +99,11 @@ public class TestBabelServiceClient { @Test public void testRestClientHttp() throws BabelServiceClientException, IOException, URISyntaxException { - String url = server.getURI().toString(); + String url = "http://localhost:" + wiremockPort; Properties configProperties = new Properties(); configProperties.put("ml.babel.USE_HTTPS", "false"); configProperties.put("ml.babel.BASE_URL", url); - configProperties.put("ml.babel.GENERATE_ARTIFACTS_URL", "generate"); + configProperties.put("ml.babel.GENERATE_ARTIFACTS_URL", "/generate"); configProperties.put("ml.aai.RESTCLIENT_CONNECT_TIMEOUT", "3000"); configProperties.put("ml.aai.RESTCLIENT_READ_TIMEOUT", "3000"); BabelServiceClient client = @@ -121,23 +118,4 @@ public class TestBabelServiceClient { private byte[] readBytesFromFile(String resourceFile) throws IOException, URISyntaxException { return Files.readAllBytes(Paths.get(ClassLoader.getSystemResource(resourceFile).toURI())); } - - /** - * Creates an {@link AbstractHandler handler} returning an arbitrary String as a response. - * - * @return never <code>null</code>. - */ - private Handler getMockHandler() { - Handler handler = new AbstractHandler() { - @Override - public void handle(String target, Request request, HttpServletRequest servletRequest, - HttpServletResponse response) throws IOException, ServletException { - response.setStatus(SC_OK); - response.setContentType("text/xml;charset=utf-8"); - write(responseBody, response.getOutputStream(), Charset.defaultCharset()); - request.setHandled(true); - } - }; - return handler; - } } diff --git a/src/test/java/org/onap/aai/modelloader/restclient/TracingTest.java b/src/test/java/org/onap/aai/modelloader/restclient/TracingTest.java new file mode 100644 index 0000000..3bfceb5 --- /dev/null +++ b/src/test/java/org/onap/aai/modelloader/restclient/TracingTest.java @@ -0,0 +1,63 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2024 Deutsche Telekom AG Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed 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. + * ============LICENSE_END========================================================= + */ +package org.onap.aai.modelloader.restclient; + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.cloud.contract.wiremock.AutoConfigureWireMock; +import org.springframework.http.HttpStatus; +import org.springframework.web.client.RestTemplate; + +import com.github.tomakehurst.wiremock.client.WireMock; + +@SpringBootTest(properties = { + "spring.sleuth.enabled=true", + "spring.zipkin.baseUrl=http://localhost:${wiremock.server.port}" +}) +@AutoConfigureWireMock(port = 0) +public class TracingTest { + + @Value("${wiremock.server.port}") + private int wiremockPort; + + @Autowired RestTemplate restTemplate; + + @Test + public void thatArtifactsCanBePushed() { + WireMock.stubFor( + WireMock.post(WireMock.urlEqualTo("/api/v2/spans")) + .willReturn( + WireMock.aResponse() + .withStatus(HttpStatus.OK.value()))); + + WireMock.stubFor( + WireMock.get(WireMock.urlEqualTo("/")) + .withHeader("X-B3-TraceId", WireMock.matching(".*")) + .willReturn( + WireMock.aResponse() + .withStatus(HttpStatus.OK.value()))); + + + String response = restTemplate.getForObject("http://localhost:" + wiremockPort + "/", String.class); + } + +} diff --git a/src/test/java/org/onap/aai/modelloader/service/TestArtifactInfoImpl.java b/src/test/java/org/onap/aai/modelloader/service/TestArtifactInfoImpl.java deleted file mode 100644 index d1d46f0..0000000 --- a/src/test/java/org/onap/aai/modelloader/service/TestArtifactInfoImpl.java +++ /dev/null @@ -1,123 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 European Software Marketing Ltd. - * ================================================================================ - * Licensed 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. - * ============LICENSE_END========================================================= - */ -package org.onap.aai.modelloader.service; - -import static org.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.CoreMatchers.not; -import static org.hamcrest.CoreMatchers.nullValue; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.empty; - -import org.junit.jupiter.api.Test; - -/** - * Tests for NotificationDataImpl class - * - */ -public class TestArtifactInfoImpl { - - @Test - public void testGettersAndSetters() { - ArtifactInfoImpl info = new ArtifactInfoImpl(); - String artifactName = "testname"; - - info.setArtifactName(artifactName); - assertThat(info.getArtifactName(), is(equalTo(artifactName))); - - String artifactType = "test-type"; - info.setArtifactType(artifactType); - assertThat(info.getArtifactType(), is(equalTo(artifactType))); - - String artifactVersion = "v1"; - info.setArtifactVersion(artifactVersion); - assertThat(info.getArtifactVersion(), is(equalTo(artifactVersion))); - - String artifactDescription = "test description"; - info.setArtifactDescription(artifactDescription); - assertThat(info.getArtifactDescription(), is(equalTo(artifactDescription))); - - assertThat(info.getArtifactChecksum(), is(nullValue())); - assertThat(info.getArtifactTimeout(), is(nullValue())); - assertThat(info.getArtifactURL(), is(nullValue())); - assertThat(info.getArtifactUUID(), is(nullValue())); - assertThat(info.getGeneratedArtifact(), is(nullValue())); - assertThat(info.getRelatedArtifacts(), is(empty())); - } - - - @Test - public void testEquality() { - ArtifactInfoImpl info = new ArtifactInfoImpl(); - assertThat(info, is(not(equalTo(null)))); - assertThat(info, is(not(equalTo("")))); // NOSONAR - assertThat(info, is(equalTo(info))); - - ArtifactInfoImpl other = new ArtifactInfoImpl(); - assertThat(info, is(equalTo(other))); - assertThat(info.hashCode(), is(equalTo(other.hashCode()))); - - // Artifact Name - other.setArtifactName(""); - assertThat(info, is(not(equalTo(other)))); - - info.setArtifactName("1234"); - assertThat(info, is(not(equalTo(other)))); - - other.setArtifactName("1234"); - assertThat(info, is(equalTo(other))); - assertThat(info.hashCode(), is(equalTo(other.hashCode()))); - - // Artifact Type - other.setArtifactType(""); - assertThat(info, is(not(equalTo(other)))); - - info.setArtifactType("type"); - assertThat(info, is(not(equalTo(other)))); - - other.setArtifactType("type"); - assertThat(info, is(equalTo(other))); - assertThat(info.hashCode(), is(equalTo(other.hashCode()))); - - // Artifact Description - other.setArtifactDescription(""); - assertThat(info, is(not(equalTo(other)))); - - info.setArtifactDescription("type"); - assertThat(info, is(not(equalTo(other)))); - - other.setArtifactDescription("type"); - assertThat(info, is(equalTo(other))); - assertThat(info.hashCode(), is(equalTo(other.hashCode()))); - - // Artifact Version - other.setArtifactVersion(""); - assertThat(info, is(not(equalTo(other)))); - - info.setArtifactVersion("v1"); - assertThat(info, is(not(equalTo(other)))); - - other.setArtifactVersion("v1"); - assertThat(info, is(equalTo(other))); - assertThat(info.hashCode(), is(equalTo(other.hashCode()))); - } - -} diff --git a/src/test/resources/__files/artifactTypes.json b/src/test/resources/__files/artifactTypes.json new file mode 100644 index 0000000..de3cfce --- /dev/null +++ b/src/test/resources/__files/artifactTypes.json @@ -0,0 +1,63 @@ +[ + "AAI_SERVICE_MODEL", + "AAI_VF_INSTANCE_MODEL", + "AAI_VF_MODEL", + "AAI_VF_MODULE_MODEL", + "ANSIBLE_PLAYBOOK", + "APPC_CONFIG", + "BPEL", + "CHEF", + "CLOUD_TECHNOLOGY_SPECIFIC_ARTIFACT", + "CONTROLLER_BLUEPRINT_ARCHIVE", + "DCAE_DOC", + "DCAE_EVENT", + "DCAE_INVENTORY_BLUEPRINT", + "DCAE_INVENTORY_DOC", + "DCAE_INVENTORY_EVENT", + "DCAE_INVENTORY_JSON", + "DCAE_INVENTORY_POLICY", + "DCAE_INVENTORY_TOSCA", + "DCAE_JSON", + "DCAE_POLICY", + "DCAE_TOSCA", + "DG_XML", + "ETSI_PACKAGE", + "ASD_PACKAGE", + "GUIDE", + "HEAT_ARTIFACT", + "HEAT_ENV", + "HEAT", + "HEAT_NESTED", + "HEAT_NET", + "HEAT_VOL", + "HELM", + "ICON", + "LIFECYCLE_OPERATIONS", + "MODEL_INVENTORY_PROFILE", + "MODEL_QUERY_SPEC", + "MURANO_PKG", + "NETWORK_CALL_FLOW", + "ONBOARDED_PACKAGE", + "OTHER", + "PERFORMANCE_COUNTER", + "PLAN", + "PM_DICTIONARY", + "PNF_SW_INFORMATION", + "PUPPET", + "SHELL_SCRIPT", + "SHELL", + "SNMP_POLL", + "SNMP_TRAP", + "TOSCA_CSAR", + "TOSCA_TEMPLATE", + "UCPE_LAYER_2_CONFIGURATION", + "VENDOR_LICENSE", + "VES_EVENTS", + "VF_LICENSE", + "VF_MODULES_METADATA", + "VNF_CATALOG", + "WORKFLOW", + "YANG_MODULE", + "YANG_XML", + "YANG" +]
\ No newline at end of file diff --git a/src/test/resources/__files/kafkaBootstrap.json b/src/test/resources/__files/kafkaBootstrap.json new file mode 100644 index 0000000..1820ade --- /dev/null +++ b/src/test/resources/__files/kafkaBootstrap.json @@ -0,0 +1,5 @@ +{ + "kafkaBootStrapServer": "localhost:9092", + "distrNotificationTopicName": "SDC-DISTR-NOTIF-TOPIC-AUTO", + "distrStatusTopicName": "SDC-DISTR-STATUS-TOPIC-AUTO" +}
\ No newline at end of file diff --git a/src/test/resources/__files/modelResponse.xml b/src/test/resources/__files/modelResponse.xml new file mode 100644 index 0000000..36d07d8 --- /dev/null +++ b/src/test/resources/__files/modelResponse.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="UTF-8"?> +<model xmlns="http://org.onap.aai.inventory/v28"> + <model-invariant-id>3a40ab73-6694-4e75-bb6d-9a4a86ce35b3</model-invariant-id> + <model-type>service</model-type> + <model-role>Network Service</model-role> + <resource-version>1710523260974</resource-version> +</model>
\ No newline at end of file diff --git a/src/test/resources/__files/service-TestSvc-csar-babel-response.json b/src/test/resources/__files/service-TestSvc-csar-babel-response.json new file mode 100644 index 0000000..7103156 --- /dev/null +++ b/src/test/resources/__files/service-TestSvc-csar-babel-response.json @@ -0,0 +1 @@ +[{"name":"AAI-test-svc-service-2.0.xml","type":"MODEL","payload":"<model xmlns=\"http://org.onap.aai.inventory/v28\">\n <model-invariant-id>3c8bc8e7-e387-46ed-8616-70e99e2206dc</model-invariant-id>\n <model-type>service</model-type>\n <model-role>Network L1-3</model-role>\n <model-vers>\n <model-ver>\n <model-version-id>71f47717-b100-4eac-940b-7d4e86a4cbb7</model-version-id>\n <model-name>test-svc</model-name>\n <model-version>2.0</model-version>\n <model-description>test-svc</model-description>\n <model-elements>\n <model-element>\n <new-data-del-flag>T</new-data-del-flag>\n <cardinality>unbounded</cardinality>\n <model-elements/>\n <relationship-list>\n <relationship>\n <related-to>model-ver</related-to>\n <relationship-data>\n <relationship-key>model-ver.model-version-id</relationship-key>\n <relationship-value>46b92144-923a-4d20-b85a-3cbd847668a9</relationship-value>\n </relationship-data>\n <relationship-data>\n <relationship-key>model.model-invariant-id</relationship-key>\n <relationship-value>82194af1-3c2c-485a-8f44-420e22a9eaa4</relationship-value>\n </relationship-data>\n </relationship>\n </relationship-list>\n </model-element>\n </model-elements>\n </model-ver>\n </model-vers>\n</model>"}]
\ No newline at end of file diff --git a/src/test/resources/__files/service-TestSvc-csar.csar b/src/test/resources/__files/service-TestSvc-csar.csar Binary files differnew file mode 100644 index 0000000..711f068 --- /dev/null +++ b/src/test/resources/__files/service-TestSvc-csar.csar diff --git a/src/test/resources/application.properties b/src/test/resources/application.properties index 96816ce..69f4ff7 100644 --- a/src/test/resources/application.properties +++ b/src/test/resources/application.properties @@ -1,10 +1,11 @@ CONFIG_HOME=src/test/resources spring.kafka.consumer.auto-offset-reset=earliest spring.kafka.consumer.group-id=aai -spring.kafka.consumer.client-id=aai-model-loader - -test.topic=SDC-DISTR-NOTIF-TOPIC +spring.kafka.consumer.client-id=aai-model-loader +topics.distribution.notification=SDC-DISTR-NOTIF-TOPIC-AUTO spring.sleuth.enabled=false -ml.distribution.connection.enabled=false # avoid having the distribution client running in the background (requires active kafka)
\ No newline at end of file +ml.distribution.connection.enabled=false # avoid having the distribution client running in the background (requires active kafka) + +spring.main.allow-bean-definition-overriding=true
\ No newline at end of file diff --git a/src/test/resources/logback-test.xml b/src/test/resources/logback-test.xml index aef38e6..4bf73da 100644 --- a/src/test/resources/logback-test.xml +++ b/src/test/resources/logback-test.xml @@ -11,7 +11,7 @@ <appender-ref ref="STDOUT" /> </logger> - <root level="debug"> + <root level="INFO"> <appender-ref ref="STDOUT" /> </root> </configuration> diff --git a/src/test/resources/model-loader.properties b/src/test/resources/model-loader.properties index 4c24679..2db7c09 100644 --- a/src/test/resources/model-loader.properties +++ b/src/test/resources/model-loader.properties @@ -1,16 +1,20 @@ # Model Loader Distribution Client Configuration ml.distribution.ACTIVE_SERVER_TLS_AUTH=false ml.distribution.ASDC_ADDRESS=localhost:8443 +ml.distribution.ASDC_USE_HTTPS=false ml.distribution.CONSUMER_GROUP=aai-ml-group-test ml.distribution.CONSUMER_ID=aai-ml-id-test -ml.distribution.ENVIRONMENT_NAME=env +ml.distribution.ENVIRONMENT_NAME=AUTO ml.distribution.KEYSTORE_PASSWORD= ml.distribution.KEYSTORE_FILE= ml.distribution.PASSWORD=Aa123456 -ml.distribution.POLLING_INTERVAL=5 +ml.distribution.POLLING_INTERVAL=15 ml.distribution.POLLING_TIMEOUT=3 ml.distribution.USER=ci ml.distribution.ARTIFACT_TYPES=MODEL_QUERY_SPEC,TOSCA_CSAR +ml.distribution.SASL_JAAS_CONFIG=org.apache.kafka.common.security.scram.ScramLoginModule required username="aai-modelloader-ku" password="somePassword"; +ml.distribution.SECURITY_PROTOCOL=PLAINTEXT +ml.distribution.SASL_MECHANISM=PLAIN # Disable ASDC polling & enable REST interface ml.distribution.ASDC_CONNECTION_DISABLE=true |