diff options
author | Håkon Hallingstad <hakon@verizonmedia.com> | 2020-03-04 17:59:09 +0100 |
---|---|---|
committer | Håkon Hallingstad <hakon@verizonmedia.com> | 2020-03-04 17:59:09 +0100 |
commit | d6cd032311964e3ac914054a48a7c3a5784eb688 (patch) | |
tree | e4cfc36773d20587d8cd2c3b083709b915d8914d /service-monitor/src/test/java | |
parent | 42aa1c7de6b01a5f7d643c948b0dcf9e7c152c80 (diff) |
Listening to host changes to the service model
Diffstat (limited to 'service-monitor/src/test/java')
3 files changed, 156 insertions, 13 deletions
diff --git a/service-monitor/src/test/java/com/yahoo/vespa/service/model/ServiceHostListenerAdapterTest.java b/service-monitor/src/test/java/com/yahoo/vespa/service/model/ServiceHostListenerAdapterTest.java new file mode 100644 index 00000000000..6b1f0dfd5b6 --- /dev/null +++ b/service-monitor/src/test/java/com/yahoo/vespa/service/model/ServiceHostListenerAdapterTest.java @@ -0,0 +1,148 @@ +// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.service.model; + +import com.yahoo.config.model.api.ApplicationInfo; +import com.yahoo.config.model.api.HostInfo; +import com.yahoo.config.model.api.Model; +import com.yahoo.config.provision.ApplicationId; +import com.yahoo.config.provision.CloudName; +import com.yahoo.config.provision.Environment; +import com.yahoo.config.provision.RegionName; +import com.yahoo.config.provision.SystemName; +import com.yahoo.config.provision.Zone; +import com.yahoo.vespa.applicationmodel.ApplicationInstanceReference; +import com.yahoo.vespa.applicationmodel.HostName; +import com.yahoo.vespa.service.duper.DuperModel; +import com.yahoo.vespa.service.monitor.ServiceHostListener; +import org.junit.Before; +import org.junit.Test; + +import java.util.List; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.when; + +public class ServiceHostListenerAdapterTest { + private final Zone zone = new Zone(CloudName.from("AWS"), SystemName.cd, Environment.dev, RegionName.from("us-east-1")); + private final ModelGenerator generator = new ModelGenerator(zone); + private final ServiceHostListener listener = mock(ServiceHostListener.class); + private final ServiceHostListenerAdapter adapter = new ServiceHostListenerAdapter(listener, generator); + private final DuperModel duperModel = new DuperModel(); + + @Before + public void setUp() { + duperModel.registerListener(adapter); + } + + @Test + public void test() { + var applicationId1 = ApplicationId.from("tnt", "app", "default"); + var applicationId2 = ApplicationId.from("tnt2", "app2", "default2"); + + verifyNoMoreInteractions(listener); + + activate(applicationId1, "host1", "host2"); + verifyActivate(applicationId1, "host1", "host2"); + + activate(applicationId1, "host1", "host3"); + verifyActivate(applicationId1, "host1", "host3"); + + activate(applicationId1, "host1", "host3"); + verifyNoActivate(); + + activate(applicationId2, "host4"); + verifyActivate(applicationId2, "host4"); + + activate(applicationId1, "host1", "host3"); + verifyNoActivate(); + + removeAndVerify(applicationId1, true); + + activate(applicationId1, "host1", "host5"); + verifyActivate(applicationId1, "host1", "host5"); + } + + @Test + public void documentDuplicateHostnameStrangeness() { + var applicationId1 = ApplicationId.from("tnt", "app", "default"); + var applicationInfo1 = makeApplicationInfo(applicationId1, "host1", "host2"); + duperModel.add(applicationInfo1); + verifyActivate(applicationId1, "host1", "host2"); + + var applicationId2 = ApplicationId.from("tnt2", "app2", "default2"); + var applicationInfo2 = makeApplicationInfo(applicationId2, "host2", "host3"); + duperModel.add(applicationInfo2); + verifyActivate(applicationId2, "host2", "host3"); + + // Duplicate hosts doesn't affect the ServiceHostListener. + + duperModel.add(applicationInfo1); + verifyNoMoreInteractions(listener); + + duperModel.add(applicationInfo2); + verifyNoMoreInteractions(listener); + + // But do affect host lookup in duper model. + + assertEquals(Optional.of(applicationInfo1), getDuperModelApplicationInfo("host1")); + assertEquals(Optional.of(applicationInfo2), getDuperModelApplicationInfo("host2")); // <-- + assertEquals(Optional.of(applicationInfo2), getDuperModelApplicationInfo("host3")); + } + + private Optional<ApplicationInfo> getDuperModelApplicationInfo(String hostname) { + return duperModel.getApplicationInfo(com.yahoo.config.provision.HostName.from(hostname)); + } + + private void removeAndVerify(ApplicationId id, boolean listenerInvoked) { + duperModel.remove(id); + + if (listenerInvoked) { + ApplicationInstanceReference reference = generator.toApplicationInstanceReference(id); + verify(listener, times(1)).onApplicationRemove(reference); + } + + verifyNoMoreInteractions(listener); + } + + private void verifyActivate(ApplicationId id, String... hostnames) { + Set<HostName> hostnameSet = Stream.of(hostnames) + .map(HostName::new) + .collect(Collectors.toSet()); + + ApplicationInstanceReference reference = generator.toApplicationInstanceReference(id); + + verify(listener, times(1)).onApplicationActivate(reference, hostnameSet); + verifyNoMoreInteractions(listener); + } + + private void verifyNoActivate() { + verifyNoMoreInteractions(listener); + } + + private void activate(ApplicationId id, String... hostnames) { + duperModel.add(makeApplicationInfo(id, hostnames)); + } + + private ApplicationInfo makeApplicationInfo(ApplicationId applicationId, String... hostnames) { + var applicationInfo = mock(ApplicationInfo.class); + when(applicationInfo.getApplicationId()).thenReturn(applicationId); + + var model = mock(Model.class); + when(applicationInfo.getModel()).thenReturn(model); + + List<HostInfo> hostnameList = Stream.of(hostnames) + .map(hostname -> new HostInfo(hostname, List.of())) + .collect(Collectors.toList()); + when(model.getHosts()).thenReturn(hostnameList); + + return applicationInfo; + } +}
\ No newline at end of file diff --git a/service-monitor/src/test/java/com/yahoo/vespa/service/model/ServiceModelCacheTest.java b/service-monitor/src/test/java/com/yahoo/vespa/service/model/ServiceModelCacheTest.java index 21c6a49cc18..8649fec8e7e 100644 --- a/service-monitor/src/test/java/com/yahoo/vespa/service/model/ServiceModelCacheTest.java +++ b/service-monitor/src/test/java/com/yahoo/vespa/service/model/ServiceModelCacheTest.java @@ -4,10 +4,9 @@ package com.yahoo.vespa.service.model; import com.yahoo.jdisc.Timer; import com.yahoo.vespa.service.monitor.ServiceModel; +import com.yahoo.vespa.service.monitor.ServiceMonitor; import org.junit.Test; -import java.util.function.Supplier; - import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; @@ -15,15 +14,14 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; public class ServiceModelCacheTest { - @SuppressWarnings("unchecked") - private final Supplier<ServiceModel> expensiveServiceMonitor = mock(Supplier.class); + private final ServiceMonitor expensiveServiceMonitor = mock(ServiceMonitor.class); private final Timer timer = mock(Timer.class); private final ServiceModelCache cache = new ServiceModelCache(expensiveServiceMonitor, timer); @Test public void sanityCheck() { ServiceModel serviceModel = mock(ServiceModel.class); - when(expensiveServiceMonitor.get()).thenReturn(serviceModel); + when(expensiveServiceMonitor.getServiceModelSnapshot()).thenReturn(serviceModel); long timeMillis = 0; when(timer.currentTimeMillis()).thenReturn(timeMillis); @@ -31,7 +29,7 @@ public class ServiceModelCacheTest { // Will always populate cache the first time ServiceModel actualServiceModel = cache.getServiceModelSnapshot(); assertTrue(actualServiceModel == serviceModel); - verify(expensiveServiceMonitor, times(1)).get(); + verify(expensiveServiceMonitor, times(1)).getServiceModelSnapshot(); // Cache hit timeMillis += ServiceModelCache.EXPIRY_MILLIS / 2; @@ -44,12 +42,12 @@ public class ServiceModelCacheTest { when(timer.currentTimeMillis()).thenReturn(timeMillis); ServiceModel serviceModel2 = mock(ServiceModel.class); - when(expensiveServiceMonitor.get()).thenReturn(serviceModel2); + when(expensiveServiceMonitor.getServiceModelSnapshot()).thenReturn(serviceModel2); actualServiceModel = cache.getServiceModelSnapshot(); assertTrue(actualServiceModel == serviceModel2); // '2' because it's cumulative with '1' from the first times(1). - verify(expensiveServiceMonitor, times(2)).get(); + verify(expensiveServiceMonitor, times(2)).getServiceModelSnapshot(); // Cache hit #2 timeMillis += 1; diff --git a/service-monitor/src/test/java/com/yahoo/vespa/service/model/ServiceModelProviderTest.java b/service-monitor/src/test/java/com/yahoo/vespa/service/model/ServiceModelProviderTest.java index f34d61970ef..3b98e50bf9a 100644 --- a/service-monitor/src/test/java/com/yahoo/vespa/service/model/ServiceModelProviderTest.java +++ b/service-monitor/src/test/java/com/yahoo/vespa/service/model/ServiceModelProviderTest.java @@ -2,9 +2,8 @@ package com.yahoo.vespa.service.model; import com.yahoo.config.model.api.ApplicationInfo; -import com.yahoo.config.provision.Zone; -import com.yahoo.vespa.service.monitor.ServiceModel; import com.yahoo.vespa.service.duper.DuperModelManager; +import com.yahoo.vespa.service.monitor.ServiceModel; import com.yahoo.vespa.service.slobrok.SlobrokMonitorManagerImpl; import org.junit.Test; @@ -23,13 +22,11 @@ public class ServiceModelProviderTest { SlobrokMonitorManagerImpl slobrokMonitorManager = mock(SlobrokMonitorManagerImpl.class); DuperModelManager duperModelManager = mock(DuperModelManager.class); ModelGenerator modelGenerator = mock(ModelGenerator.class); - Zone zone = mock(Zone.class); ServiceModelProvider provider = new ServiceModelProvider( slobrokMonitorManager, mock(ServiceMonitorMetrics.class), duperModelManager, - modelGenerator, - zone); + modelGenerator); ApplicationInfo application1 = mock(ApplicationInfo.class); ApplicationInfo application2 = mock(ApplicationInfo.class); |