1 package dst.ass3.elastic;
3 import dst.ass3.elastic.impl.ElasticityFactory;
4 import dst.ass3.messaging.IWorkloadMonitor;
5 import dst.ass3.messaging.RequestType;
6 import org.junit.After;
7 import org.junit.Before;
9 import org.junit.runner.RunWith;
10 import org.mockito.Mock;
11 import org.mockito.junit.MockitoJUnitRunner;
13 import java.util.ArrayList;
14 import java.util.HashMap;
15 import java.util.List;
17 import java.util.stream.Collectors;
19 import static org.mockito.ArgumentMatchers.any;
20 import static org.mockito.Mockito.*;
22 @RunWith(MockitoJUnitRunner.class)
23 public class ElasticityControllerTest {
24 private static final String WORKER_IMAGE = "dst/ass3-worker";
26 IElasticityFactory factory;
29 IContainerService containerService;
31 IWorkloadMonitor workloadMonitor;
33 IElasticityController elasticityController;
34 Map<RequestType, Double> processingTimes = new HashMap<>();
35 Map<RequestType, Long> workerCount = new HashMap<>();
36 Map<RequestType, Long> requestCount = new HashMap<>();
37 List<ContainerInfo> containers = new ArrayList<>();
40 public void setUp() throws Exception {
41 factory = new ElasticityFactory();
42 elasticityController = factory.createElasticityController(containerService, workloadMonitor);
44 processingTimes.clear();
45 processingTimes.put(RequestType.DOCUMENT, 5000.0);
46 processingTimes.put(RequestType.VIDEO, 10000.0);
47 processingTimes.put(RequestType.QUIZ, 2000.0);
48 when(workloadMonitor.getAverageProcessingTime()).thenReturn(processingTimes);
51 workerCount.put(RequestType.DOCUMENT, 95L);
52 workerCount.put(RequestType.VIDEO, 87L);
53 workerCount.put(RequestType.QUIZ, 61L);
54 when(workloadMonitor.getWorkerCount()).thenReturn(workerCount);
57 requestCount.put(RequestType.DOCUMENT, 600L);
58 requestCount.put(RequestType.VIDEO, 1000L);
59 requestCount.put(RequestType.QUIZ, 1005L);
60 when(workloadMonitor.getRequestCount()).thenReturn(requestCount);
63 for (int i = 0; i < 95; i++) {
64 containers.add(containerInfo("documentId" + i, WORKER_IMAGE, RequestType.DOCUMENT, true));
66 for (int i = 0; i < 87; i++) {
67 containers.add(containerInfo("video" + i, WORKER_IMAGE, RequestType.VIDEO, true));
69 for (int i = 0; i < 61; i++) {
70 containers.add(containerInfo("quiz" + i, WORKER_IMAGE, RequestType.QUIZ, true));
72 when(containerService.listContainers()).thenReturn(containers);
76 public void tearDown() {
77 verify(workloadMonitor, atLeast(1)).getWorkerCount();
78 verify(workloadMonitor, atLeast(1)).getRequestCount();
79 verify(workloadMonitor, atLeast(1)).getAverageProcessingTime();
83 public void notEnoughWorkers_scaleUp() throws Exception {
84 // remove 10 document workers and 10 quiz workers
85 List<ContainerInfo> containersToRemove = containers.stream()
86 .filter(c -> c.getContainerId().startsWith("documentId7") || c.getContainerId().startsWith("quiz1"))
87 .collect(Collectors.toList());
88 containers.removeAll(containersToRemove);
89 workerCount.put(RequestType.DOCUMENT, 85L);
90 workerCount.put(RequestType.QUIZ, 51L);
92 elasticityController.adjustWorkers();
94 verify(containerService, never()).stopContainer((String) any(String.class));
95 verify(containerService, times(15)).startWorker(RequestType.DOCUMENT);
96 verify(containerService, times(16)).startWorker(RequestType.QUIZ);
97 verify(containerService, never()).startWorker(RequestType.VIDEO);
98 verify(containerService, never()).listContainers();
102 public void tooManyWorkers_scaleDown() throws Exception {
103 // add 20 more, some should be stopped
104 for (int i = 0; i < 20; i++) {
105 containers.add(containerInfo("quiz1" + i, WORKER_IMAGE, RequestType.QUIZ, true));
107 workerCount.put(RequestType.QUIZ, 81L);
109 elasticityController.adjustWorkers();
111 verify(containerService, times(14)).stopContainer(contains("quiz"));
112 verify(containerService, never()).stopContainer(contains("video"));
113 verify(containerService, never()).stopContainer(contains("document"));
114 verify(containerService, never()).startWorker((RequestType) any(RequestType.class));
115 verify(containerService, times(1)).listContainers();
119 public void justEnoughWorkers_doNotScale() throws Exception {
120 elasticityController.adjustWorkers();
121 verify(containerService, never()).startWorker((RequestType) any(RequestType.class));
122 verify(containerService, never()).stopContainer((String) any());
123 verify(containerService, never()).listContainers();
126 private ContainerInfo containerInfo(String id, String image, RequestType workerType, boolean running) {
127 ContainerInfo info = new ContainerInfo();
128 info.setContainerId(id);
129 info.setImage(image);
130 info.setWorkerType(workerType);
131 info.setRunning(running);