/*
* Copyright 2016 ThoughtWorks, Inc.
*
* 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 com.thoughtworks.go.server.messaging.scheduling;
import com.thoughtworks.go.domain.AgentRuntimeStatus;
import com.thoughtworks.go.helper.AgentMother;
import com.thoughtworks.go.remote.AgentIdentifier;
import com.thoughtworks.go.remote.work.NoWork;
import com.thoughtworks.go.server.perf.WorkAssignmentPerformanceLogger;
import com.thoughtworks.go.server.service.AgentRuntimeInfo;
import com.thoughtworks.go.server.service.BuildAssignmentService;
import com.thoughtworks.go.util.ClassMockery;
import com.thoughtworks.go.work.FakeWork;
import org.jmock.Expectations;
import org.jmock.Mockery;
import org.jmock.integration.junit4.JMock;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import static com.thoughtworks.go.util.SystemUtil.currentWorkingDirectory;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.*;
@RunWith(JMock.class)
public class WorkFinderTest {
private Mockery context;
private BuildAssignmentService workAssigner;
private static final AgentIdentifier AGENT_1 = new AgentIdentifier("localhost", "127.0.0.1", "uuid");
private static final FakeWork SOME_WORK = new FakeWork();
private static final NoWork NO_WORK = new NoWork();
private WorkAssignedTopic assignedWorkTopic;
private WorkFinder finder;
private IdleAgentTopic idleAgentTopic;
private WorkAssignmentPerformanceLogger workAssignmentPerformanceLogger;
@Before
public void before() {
context = new ClassMockery();
workAssigner = context.mock(BuildAssignmentService.class);
assignedWorkTopic = context.mock(WorkAssignedTopic.class, "assignedWork");
idleAgentTopic = context.mock(IdleAgentTopic.class, "idleAgent");
workAssignmentPerformanceLogger = mock(WorkAssignmentPerformanceLogger.class);
context.checking(new Expectations() {{
one(idleAgentTopic).addListener(with(any(WorkFinder.class)));
}});
finder = new WorkFinder(workAssigner, idleAgentTopic, assignedWorkTopic, workAssignmentPerformanceLogger);
}
@Test
public void shouldDoNothingIfNoWorkIsAvailable() {
context.checking(new Expectations() {{
one(workAssigner).assignWorkToAgent(AGENT_1);
will(returnValue(NO_WORK));
one(assignedWorkTopic).post(new WorkAssignedMessage(AGENT_1, NO_WORK));
}});
finder.onMessage(new IdleAgentMessage(new AgentRuntimeInfo(AGENT_1, AgentRuntimeStatus.Idle, currentWorkingDirectory(), "cookie", false)));
}
@Test
public void shouldAssignWorkIfItIsAvailable() {
context.checking(new Expectations() {{
one(workAssigner).assignWorkToAgent(AGENT_1);
will(returnValue(SOME_WORK));
one(assignedWorkTopic).post(new WorkAssignedMessage(AGENT_1, SOME_WORK));
}});
finder.onMessage(new IdleAgentMessage(new AgentRuntimeInfo(AGENT_1, AgentRuntimeStatus.Idle, currentWorkingDirectory(), "cookie", false)));
}
@Test
public void shouldPostNoWorkOnException() {
final RuntimeException exception = new RuntimeException("foo");
context.checking(new Expectations() {{
one(workAssigner).assignWorkToAgent(AGENT_1);
will(throwException(exception));
one(assignedWorkTopic).post(new WorkAssignedMessage(AGENT_1, NO_WORK));
}});
try {
finder.onMessage(new IdleAgentMessage(new AgentRuntimeInfo(AGENT_1, AgentRuntimeStatus.Idle, currentWorkingDirectory(), "cookie", false)));
} catch (Exception e) {
assertSame(exception, e);
}
}
@Test
public void shouldReturnNoWorkInCaseOfAnErrorIsThrown() {
BuildAssignmentService assigner = mock(BuildAssignmentService.class);
IdleAgentTopic idleTopic = mock(IdleAgentTopic.class);
WorkAssignedTopic assignedTopic = mock(WorkAssignedTopic.class);
WorkFinder finder = new WorkFinder(assigner, idleTopic, assignedTopic, workAssignmentPerformanceLogger);
AgentRuntimeInfo runtimeInfo = AgentRuntimeInfo.initialState(AgentMother.approvedAgent());
when(assigner.assignWorkToAgent(runtimeInfo.getIdentifier())).thenThrow(new OutOfMemoryError("test error for martians"));
try {
finder.onMessage(new IdleAgentMessage(runtimeInfo));
fail("should have propagated error");
} catch (OutOfMemoryError e) {
String message = e.getMessage();
if (message != null && message.equals("test error for martians")) {
//expected
} else {
throw e;
}
}
verify(assignedTopic).post(new WorkAssignedMessage(runtimeInfo.getIdentifier(), new NoWork()));
}
}