package jetbrains.buildServer.clouds.base; import java.util.*; import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Function; import java.util.stream.Collectors; import jetbrains.buildServer.BaseTestCase; import jetbrains.buildServer.clouds.CloudClientParameters; import jetbrains.buildServer.clouds.InstanceStatus; import jetbrains.buildServer.clouds.base.connector.CloudApiConnector; import jetbrains.buildServer.clouds.base.stubs.*; import jetbrains.buildServer.clouds.base.tasks.UpdateInstancesTask; import jetbrains.buildServer.serverSide.AgentDescription; import jetbrains.buildServer.util.WaitFor; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; /** * Created by Sergey.Pak on 3/4/2016. */ @Test public class UpdateInstancesTaskTest extends BaseTestCase { private UpdateInstancesTask myUpdateInstancesTask; private DummyApiConnector myApiConnector; private MyClient myClient; private Map<String, DummyRealInstance> myRealInstanceMap; @BeforeMethod @Override protected void setUp() throws Exception { super.setUp(); myRealInstanceMap = new HashMap<>(); myApiConnector = new DummyApiConnector(myRealInstanceMap); myClient = new MyClient(myApiConnector); myUpdateInstancesTask = new UpdateInstancesTask(myApiConnector, myClient, 2*1000, true); } public void no_instances(){ myClient.getImageMap().put("image1", new DummyCloudImage("image1")); myUpdateInstancesTask.run(); assertEquals(0, myClient.getInstances().size()); } public void catch_new_instances(){ final String imageName = "image1"; final String instanceName = "instance1"; myClient.getImageMap().put(imageName, new DummyCloudImage(imageName)); myRealInstanceMap.put(instanceName, new DummyRealInstance(instanceName, imageName, InstanceStatus.RUNNING)); myUpdateInstancesTask.run(); final DummyCloudInstance dummyCloudInstance = myClient.getInstances().get(instanceName); assertNotNull(dummyCloudInstance); assertEquals(imageName, dummyCloudInstance.getImageId()); assertEquals(instanceName, dummyCloudInstance.getName()); } public void detect_removed_instance(){ final String imageName = "image1"; final String instanceName = "instance1"; myClient.getImageMap().put(imageName, new DummyCloudImage(imageName)); myRealInstanceMap.put(instanceName, new DummyRealInstance(instanceName, imageName, InstanceStatus.RUNNING)); myUpdateInstancesTask.run(); assertEquals(1, myClient.getInstances().size()); myRealInstanceMap.clear(); myUpdateInstancesTask.run(); assertEquals(0, myClient.getInstances().size()); } public void handle_instances_started_after_list_image(){ final String imageName = "image1"; final String instanceName = "instance1"; myClient.getImageMap().put(imageName, new DummyCloudImage(imageName)); myRealInstanceMap.put(instanceName, new DummyRealInstance(instanceName, imageName, InstanceStatus.RUNNING)); myUpdateInstancesTask.run(); assertEquals(1, myClient.getInstances().size()); myRealInstanceMap.clear(); final CountDownLatch innerLatch = new CountDownLatch(1); myApiConnector.getLatchMap().put("listImageInstances", innerLatch); final AtomicBoolean complete = new AtomicBoolean(false); final Thread thread = new Thread(new Runnable() { @Override public void run() { myUpdateInstancesTask.run(); complete.set(true); } }); thread.start(); myRealInstanceMap.put(instanceName, new DummyRealInstance(instanceName, imageName, InstanceStatus.RUNNING)); innerLatch.countDown(); new WaitFor(300){ @Override protected boolean condition() { return complete.get(); } }; assertTrue(complete.get()); final DummyCloudInstance dummyCloudInstance = myClient.getInstances().get(instanceName); assertNotNull(dummyCloudInstance); assertEquals(imageName, dummyCloudInstance.getImageId()); assertEquals(instanceName, dummyCloudInstance.getName()); } @AfterMethod @Override protected void tearDown() throws Exception { super.tearDown(); } private class MyClient extends AbstractCloudClient<DummyCloudInstance, DummyCloudImage, DummyImageDetails>{ public MyClient(@NotNull final CloudApiConnector apiConnector) { super(new CloudClientParameters(), apiConnector); } @Override protected DummyCloudImage checkAndCreateImage(@NotNull final DummyImageDetails imageDetails) { return new DummyCloudImage(imageDetails.getSourceId()); } @NotNull @Override protected UpdateInstancesTask<DummyCloudInstance, DummyCloudImage, ?> createUpdateInstancesTask() { return null; } @Nullable @Override public DummyCloudInstance findInstanceByAgent(@NotNull final AgentDescription agent) { final String name = generateAgentName(agent); return getInstances().get(name); } @Nullable @Override public String generateAgentName(@NotNull final AgentDescription agent) { return agent.getAvailableParameters().get("name"); } public Map<String, DummyCloudImage> getImageMap(){ return myImageMap; } public Map<String, DummyCloudInstance> getInstances(){ final Map<String, DummyCloudInstance> retval = new HashMap<>(); myImageMap.forEach((n, i)->{ retval.putAll(i.getInstances().stream().collect(Collectors.toMap(DummyCloudInstance::getName, Function.identity()))); }); return retval; } } }