/* * Copyright © 2017 the original authors (http://cereebro.io) * * 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. */ package io.cereebro.core; import java.net.URI; import java.util.Arrays; import java.util.HashSet; import org.assertj.core.api.Assertions; import org.junit.Before; import org.junit.Test; import org.mockito.Mockito; /** * {@link SimpleSystemResolver} unit tests. * * @author michaeltecourt */ public class SimpleSystemResolverTest { private static final Component CABLE = Component.of("cable", "future"); private static final Component SABRETOOTH = Component.of("sabretooth", "villain"); private static final Component CYCLOP = Component.of("cyclop", "superhero"); private static final Component XAVIER = Component.of("xavier", "superhero"); private static final Component WOLVERINE = Component.of("wolverine", "superhero"); private static final Component PHOENIX = Component.of("phoenix", "superhero"); private static final String SYSTEM_NAME = "xmen"; private SimpleSystemResolver resolver; @Before public void setUp() { resolver = new SimpleSystemResolver(); } @Test public void resolvingEmptySnitchRegistryShouldReturnEmptySystem() { System actual = resolver.resolve(SYSTEM_NAME, StaticSnitchRegistry.of()); Assertions.assertThat(actual).isEqualTo(System.empty(SYSTEM_NAME)); } /** * This fat test name means that : * <ul> * <li>if B is a dependency of A, then A should be resolved as a consumer of * B.</li> * <li>Corollary : if C is a consumer of D, then D should be resolved as a * dependency of C</li> * </ul> */ @Test public void resolvingComponentRelationshipsShouldCreateInvertedRelationshipOnRelatedComponents() { // Initial relationships // @formatter:off ComponentRelationships wolverineRels = ComponentRelationships.builder() .component(WOLVERINE) .addDependency(Dependency.on(PHOENIX)) .addConsumer(Consumer.by(SABRETOOTH)) .build(); // @formatter:on Snitch snitch1 = StaticSnitch.of(URI.create("fake://1"), SystemFragment.of(wolverineRels)); System actual = resolver.resolve(SYSTEM_NAME, StaticSnitchRegistry.of(snitch1)); // Resolved relationships (expected) // @formatter:off ComponentRelationships wolverineResolved = ComponentRelationships.builder() .component(WOLVERINE) .addDependency(Dependency.on(PHOENIX)) .addConsumer(Consumer.by(SABRETOOTH)) .build(); ComponentRelationships phoenixResolved = ComponentRelationships.builder() .component(PHOENIX) .addConsumer(Consumer.by(WOLVERINE)) .build(); ComponentRelationships sabretoothResolved = ComponentRelationships.builder() .component(SABRETOOTH) .addDependency(Dependency.on(WOLVERINE)) .build(); // @formatter:on System expected = System.of(SYSTEM_NAME, wolverineResolved, phoenixResolved, sabretoothResolved); Assertions.assertThat(actual).isEqualTo(expected); } @Test public void resolveBidirectionalRelationship() { // Initial relationships // @formatter:off ComponentRelationships cyclopRels = ComponentRelationships.builder() .component(CYCLOP) .addDependency(Dependency.on(PHOENIX)) .addDependency(Dependency.on(XAVIER)) .build(); ComponentRelationships phoenixRels = ComponentRelationships.builder() .component(PHOENIX) .addDependency(Dependency.on(CYCLOP)) .addDependency(Dependency.on(XAVIER)) .build(); // @formatter:on Snitch snitch1 = StaticSnitch.of(URI.create("fake://1"), SystemFragment.of(cyclopRels)); Snitch snitch2 = StaticSnitch.of(URI.create("fake://2"), SystemFragment.of(phoenixRels)); SnitchRegistry registry = StaticSnitchRegistry.of(snitch1, snitch2); System actual = resolver.resolve(SYSTEM_NAME, registry); // Resolved relationships (expected) // @formatter:off ComponentRelationships cyclopResolved = ComponentRelationships.builder() .component(CYCLOP) .addDependency(Dependency.on(PHOENIX)) .addDependency(Dependency.on(XAVIER)) .addConsumer(Consumer.by(PHOENIX)) .build(); ComponentRelationships phoenixResolved = ComponentRelationships.builder() .component(PHOENIX) .addDependency(Dependency.on(CYCLOP)) .addDependency(Dependency.on(XAVIER)) .addConsumer(Consumer.by(CYCLOP)) .build(); ComponentRelationships xavierResolved = ComponentRelationships.builder() .component(XAVIER) .addConsumer(Consumer.by(CYCLOP)) .addConsumer(Consumer.by(PHOENIX)) .build(); // @formatter:on System expected = System.of(SYSTEM_NAME, cyclopResolved, phoenixResolved, xavierResolved); Assertions.assertThat(actual).isEqualTo(expected); } /** * A component consuming itself should be resolved as both a dependency and * a consumer. */ @Test public void resolveSelfRelationship() { // @formatter:off // Initial relationships ComponentRelationships cable = ComponentRelationships.builder() .component(CABLE) .addConsumer(Consumer.by(CABLE)) .build(); // Resolved relationships (expected) ComponentRelationships cableResolved = ComponentRelationships.builder() .component(CABLE) .addConsumer(Consumer.by(CABLE)) .addDependency(Dependency.on(CABLE)) .build(); // @formatter:on Snitch snitch1 = StaticSnitch.of(URI.create("fake://1"), SystemFragment.of(cable)); System actual = resolver.resolve(SYSTEM_NAME, StaticSnitchRegistry.of(snitch1)); System expected = System.of(SYSTEM_NAME, cableResolved); Assertions.assertThat(actual).isEqualTo(expected); } @Test public void snitchingExceptionShouldBeTranslatedToError() { Snitch snitchMock = Mockito.mock(Snitch.class); URI uri = URI.create("http://nope"); String message = "nope"; Mockito.when(snitchMock.getUri()).thenReturn(uri); SnitchingException snitchingExceptionMock = Mockito.mock(SnitchingException.class); Mockito.when(snitchingExceptionMock.getMessage()).thenReturn(message); Mockito.when(snitchingExceptionMock.getSnitchUri()).thenReturn(uri); Mockito.when(snitchMock.snitch()).thenThrow(snitchingExceptionMock); System actual = resolver.resolve(SYSTEM_NAME, StaticSnitchRegistry.of(snitchMock)); ResolutionError error = ResolutionError.of(uri, message); System expected = System.of(SYSTEM_NAME, new HashSet<>(), new HashSet<>(Arrays.asList(error))); Assertions.assertThat(actual).isEqualTo(expected); } @Test public void runtimeExceptionShouldBeTranslatedToError() { Snitch snitchMock = Mockito.mock(Snitch.class); URI uri = URI.create("http://nope"); String message = "nope"; Mockito.when(snitchMock.getUri()).thenReturn(uri); RuntimeException exceptionMock = Mockito.mock(RuntimeException.class); Mockito.when(exceptionMock.getMessage()).thenReturn(message); Mockito.when(snitchMock.snitch()).thenThrow(exceptionMock); System actual = resolver.resolve(SYSTEM_NAME, StaticSnitchRegistry.of(snitchMock)); ResolutionError error = ResolutionError.of(uri, "Could not access or process Snitch"); System expected = System.of(SYSTEM_NAME, new HashSet<>(), new HashSet<>(Arrays.asList(error))); Assertions.assertThat(actual).isEqualTo(expected); } @Test public void resolutionUsingFragmentsShouldNotReturnErrors() { System system = resolver.resolve(SYSTEM_NAME, new HashSet<>()); Assertions.assertThat(system).isEqualTo(System.empty(SYSTEM_NAME)); } }