Files
poseidon/runner/manager_test.go
sirkrypt0 630a006258 Use more uints
Previously we accepted int values although only uint values made sense.
We adjusted this to accept uints where appropriate.
2021-06-03 13:21:49 +00:00

198 lines
6.7 KiB
Go

package runner
import (
"errors"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite"
"gitlab.hpi.de/codeocean/codemoon/poseidon/nomad"
"gitlab.hpi.de/codeocean/codemoon/poseidon/tests"
"testing"
"time"
)
const (
defaultDesiredRunnersCount uint = 5
)
func TestGetNextRunnerTestSuite(t *testing.T) {
suite.Run(t, new(ManagerTestSuite))
}
type ManagerTestSuite struct {
suite.Suite
apiMock *nomad.ExecutorApiMock
nomadRunnerManager *NomadRunnerManager
exerciseRunner Runner
}
func (s *ManagerTestSuite) SetupTest() {
s.apiMock = &nomad.ExecutorApiMock{}
s.nomadRunnerManager = NewNomadRunnerManager(s.apiMock)
s.exerciseRunner = NewRunner(tests.DefaultRunnerId)
s.mockRunnerQueries([]string{})
s.registerDefaultEnvironment()
}
func (s *ManagerTestSuite) mockRunnerQueries(returnedRunnerIds []string) {
// reset expected calls to allow new mocked return values
s.apiMock.ExpectedCalls = []*mock.Call{}
s.apiMock.On("LoadRunners", tests.DefaultJobId).Return(returnedRunnerIds, nil)
s.apiMock.On("JobScale", tests.DefaultJobId).Return(uint(len(returnedRunnerIds)), nil)
s.apiMock.On("SetJobScale", tests.DefaultJobId, mock.AnythingOfType("uint"), "Runner Requested").Return(nil)
}
func (s *ManagerTestSuite) registerDefaultEnvironment() {
s.nomadRunnerManager.RegisterEnvironment(defaultEnvironmentId, tests.DefaultJobId, defaultDesiredRunnersCount)
}
func (s *ManagerTestSuite) AddIdleRunnerForDefaultEnvironment(r Runner) {
job, _ := s.nomadRunnerManager.jobs.Get(defaultEnvironmentId)
job.idleRunners.Add(r)
}
func (s *ManagerTestSuite) waitForRunnerRefresh() {
time.Sleep(100 * time.Millisecond)
}
func (s *ManagerTestSuite) TestRegisterEnvironmentAddsNewJob() {
s.nomadRunnerManager.RegisterEnvironment(anotherEnvironmentId, tests.DefaultJobId, defaultDesiredRunnersCount)
job, ok := s.nomadRunnerManager.jobs.Get(defaultEnvironmentId)
s.True(ok)
s.NotNil(job)
}
func (s *ManagerTestSuite) TestClaimReturnsNotFoundErrorIfEnvironmentNotFound() {
runner, err := s.nomadRunnerManager.Claim(EnvironmentId(42))
s.Nil(runner)
s.Equal(ErrUnknownExecutionEnvironment, err)
}
func (s *ManagerTestSuite) TestClaimReturnsRunnerIfAvailable() {
s.AddIdleRunnerForDefaultEnvironment(s.exerciseRunner)
receivedRunner, err := s.nomadRunnerManager.Claim(defaultEnvironmentId)
s.NoError(err)
s.Equal(s.exerciseRunner, receivedRunner)
}
func (s *ManagerTestSuite) TestClaimReturnsErrorIfNoRunnerAvailable() {
s.waitForRunnerRefresh()
runner, err := s.nomadRunnerManager.Claim(defaultEnvironmentId)
s.Nil(runner)
s.Equal(ErrNoRunnersAvailable, err)
}
func (s *ManagerTestSuite) TestClaimReturnsNoRunnerOfDifferentEnvironment() {
s.AddIdleRunnerForDefaultEnvironment(s.exerciseRunner)
receivedRunner, err := s.nomadRunnerManager.Claim(anotherEnvironmentId)
s.Nil(receivedRunner)
s.Error(err)
}
func (s *ManagerTestSuite) TestClaimDoesNotReturnTheSameRunnerTwice() {
s.AddIdleRunnerForDefaultEnvironment(s.exerciseRunner)
s.AddIdleRunnerForDefaultEnvironment(NewRunner(tests.AnotherRunnerId))
firstReceivedRunner, _ := s.nomadRunnerManager.Claim(defaultEnvironmentId)
secondReceivedRunner, _ := s.nomadRunnerManager.Claim(defaultEnvironmentId)
s.NotEqual(firstReceivedRunner, secondReceivedRunner)
}
func (s *ManagerTestSuite) TestClaimThrowsAnErrorIfNoRunnersAvailable() {
receivedRunner, err := s.nomadRunnerManager.Claim(defaultEnvironmentId)
s.Nil(receivedRunner)
s.Error(err)
}
func (s *ManagerTestSuite) TestClaimAddsRunnerToUsedRunners() {
s.mockRunnerQueries([]string{tests.DefaultRunnerId})
s.waitForRunnerRefresh()
receivedRunner, _ := s.nomadRunnerManager.Claim(defaultEnvironmentId)
savedRunner, ok := s.nomadRunnerManager.usedRunners.Get(receivedRunner.Id())
s.True(ok)
s.Equal(savedRunner, receivedRunner)
}
func (s *ManagerTestSuite) TestGetReturnsRunnerIfRunnerIsUsed() {
s.nomadRunnerManager.usedRunners.Add(s.exerciseRunner)
savedRunner, err := s.nomadRunnerManager.Get(s.exerciseRunner.Id())
s.NoError(err)
s.Equal(savedRunner, s.exerciseRunner)
}
func (s *ManagerTestSuite) TestGetReturnsErrorIfRunnerNotFound() {
savedRunner, err := s.nomadRunnerManager.Get(tests.DefaultRunnerId)
s.Nil(savedRunner)
s.Error(err)
}
func (s *ManagerTestSuite) TestReturnRemovesRunnerFromUsedRunners() {
s.apiMock.On("DeleteRunner", mock.AnythingOfType("string")).Return(nil)
s.nomadRunnerManager.usedRunners.Add(s.exerciseRunner)
err := s.nomadRunnerManager.Return(s.exerciseRunner)
s.Nil(err)
_, ok := s.nomadRunnerManager.usedRunners.Get(s.exerciseRunner.Id())
s.False(ok)
}
func (s *ManagerTestSuite) TestReturnCallsDeleteRunnerApiMethod() {
s.apiMock.On("DeleteRunner", mock.AnythingOfType("string")).Return(nil)
err := s.nomadRunnerManager.Return(s.exerciseRunner)
s.Nil(err)
s.apiMock.AssertCalled(s.T(), "DeleteRunner", s.exerciseRunner.Id())
}
func (s *ManagerTestSuite) TestReturnReturnsErrorWhenApiCallFailed() {
s.apiMock.On("DeleteRunner", mock.AnythingOfType("string")).Return(errors.New("return failed"))
err := s.nomadRunnerManager.Return(s.exerciseRunner)
s.Error(err)
}
func (s *ManagerTestSuite) TestRefreshFetchesRunners() {
s.mockRunnerQueries([]string{tests.DefaultRunnerId})
s.waitForRunnerRefresh()
s.apiMock.AssertCalled(s.T(), "LoadRunners", tests.DefaultJobId)
}
func (s *ManagerTestSuite) TestNewRunnersFoundInRefreshAreAddedToIdleRunners() {
s.mockRunnerQueries([]string{tests.DefaultRunnerId})
s.waitForRunnerRefresh()
job, _ := s.nomadRunnerManager.jobs.Get(defaultEnvironmentId)
_, ok := job.idleRunners.Get(tests.DefaultRunnerId)
s.True(ok)
}
func (s *ManagerTestSuite) TestRefreshScalesJob() {
s.mockRunnerQueries([]string{tests.DefaultRunnerId})
s.waitForRunnerRefresh()
// use one runner to necessitate rescaling
_, _ = s.nomadRunnerManager.Claim(defaultEnvironmentId)
s.waitForRunnerRefresh()
s.apiMock.AssertCalled(s.T(), "SetJobScale", tests.DefaultJobId, defaultDesiredRunnersCount+1, "Runner Requested")
}
func (s *ManagerTestSuite) TestRefreshAddsRunnerToPool() {
s.mockRunnerQueries([]string{tests.DefaultRunnerId})
s.waitForRunnerRefresh()
job, _ := s.nomadRunnerManager.jobs.Get(defaultEnvironmentId)
poolRunner, ok := job.idleRunners.Get(tests.DefaultRunnerId)
s.True(ok)
s.Equal(tests.DefaultRunnerId, poolRunner.Id())
}
func (s *ManagerTestSuite) TestWhenEnvironmentDoesNotExistEnvironmentExistsReturnsFalse() {
id := anotherEnvironmentId
_, ok := s.nomadRunnerManager.jobs.Get(id)
require.False(s.T(), ok)
s.False(s.nomadRunnerManager.EnvironmentExists(id))
}
func (s *ManagerTestSuite) TestWhenEnvironmentExistsEnvironmentExistsReturnsTrue() {
id := anotherEnvironmentId
s.nomadRunnerManager.jobs.Add(&NomadJob{environmentId: id})
exists := s.nomadRunnerManager.EnvironmentExists(id)
s.True(exists)
}