Add tests for job store, Len and Sample method of pool

This commit is contained in:
Jan-Eric Hellenberg
2021-05-19 12:30:43 +02:00
parent 17c9839fac
commit 5bb3c6745e
5 changed files with 193 additions and 41 deletions

16
runner/constants_test.go Normal file
View File

@ -0,0 +1,16 @@
package runner
const (
defaultRunnerId = "s0m3-r4nd0m-1d"
anotherRunnerId = "4n0th3r-runn3r-1d"
defaultEnvironmentId = EnvironmentId(0)
anotherEnvironmentId = EnvironmentId(42)
defaultJobId = "s0m3-j0b-1d"
anotherJobId = "4n0th3r-j0b-1d"
)
type DummyEntity struct{}
func (DummyEntity) Id() string {
return ""
}

101
runner/job_store_test.go Normal file
View File

@ -0,0 +1,101 @@
package runner
import (
"github.com/sirupsen/logrus"
"github.com/sirupsen/logrus/hooks/test"
"github.com/stretchr/testify/suite"
"testing"
)
func TestJobStoreTestSuite(t *testing.T) {
suite.Run(t, new(JobStoreTestSuite))
}
type JobStoreTestSuite struct {
suite.Suite
jobStore *nomadJobStore
job *NomadJob
}
func (suite *JobStoreTestSuite) SetupTest() {
suite.jobStore = NewNomadJobStore()
suite.job = &NomadJob{environmentId: defaultEnvironmentId, jobId: defaultJobId}
}
func (suite *JobStoreTestSuite) TestAddInvalidEntityTypeThrowsFatal() {
var hook *test.Hook
logger, hook := test.NewNullLogger()
// don't terminate program on fatal log entry
logger.ExitFunc = func(int) {}
log = logger.WithField("pkg", "environment")
dummyEntity := DummyEntity{}
suite.jobStore.Add(dummyEntity)
suite.Equal(logrus.FatalLevel, hook.LastEntry().Level)
suite.Equal(dummyEntity, hook.LastEntry().Data["entity"])
}
func (suite *JobStoreTestSuite) TestAddValidEntityDoesNotThrowFatal() {
var hook *test.Hook
logger, hook := test.NewNullLogger()
log = logger.WithField("pkg", "environment")
suite.jobStore.Add(suite.job)
// currently, the Add method does not log anything else. adjust if necessary
suite.Nil(hook.LastEntry())
}
func (suite *JobStoreTestSuite) TestAddedJobCanBeRetrieved() {
suite.jobStore.Add(suite.job)
retrievedJob, ok := suite.jobStore.Get(suite.job.Id())
suite.True(ok, "A saved runner should be retrievable")
suite.Equal(suite.job, retrievedJob)
}
func (suite *JobStoreTestSuite) TestJobWithSameIdOverwritesOldOne() {
otherJobWithSameId := &NomadJob{environmentId: defaultEnvironmentId}
// assure runner is actually different
otherJobWithSameId.jobId = anotherJobId
suite.NotEqual(suite.job, otherJobWithSameId)
suite.jobStore.Add(suite.job)
suite.jobStore.Add(otherJobWithSameId)
retrievedJob, _ := suite.jobStore.Get(suite.job.Id())
suite.NotEqual(suite.job, retrievedJob)
suite.Equal(otherJobWithSameId, retrievedJob)
}
func (suite *JobStoreTestSuite) TestDeletedJobIsNotAccessible() {
suite.jobStore.Add(suite.job)
suite.jobStore.Delete(suite.job.Id())
retrievedRunner, ok := suite.jobStore.Get(suite.job.Id())
suite.Nil(retrievedRunner)
suite.False(ok, "A deleted runner should not be accessible")
}
func (suite *JobStoreTestSuite) TestLenOfEmptyPoolIsZero() {
suite.Equal(0, suite.jobStore.Len())
}
func (suite *JobStoreTestSuite) TestLenChangesOnStoreContentChange() {
suite.Run("len increases when job is added", func() {
suite.jobStore.Add(suite.job)
suite.Equal(1, suite.jobStore.Len())
})
suite.Run("len does not increase when job with same id is added", func() {
suite.jobStore.Add(suite.job)
suite.Equal(1, suite.jobStore.Len())
})
suite.Run("len increases again when different job is added", func() {
anotherJob := &NomadJob{environmentId: anotherEnvironmentId}
suite.jobStore.Add(anotherJob)
suite.Equal(2, suite.jobStore.Len())
})
suite.Run("len decreases when job is deleted", func() {
suite.jobStore.Delete(suite.job.Id())
suite.Equal(1, suite.jobStore.Len())
})
}

View File

@ -10,12 +10,7 @@ import (
) )
const ( const (
anotherRunnerId = "4n0th3r-runn3r-1d"
defaultEnvironmentId = EnvironmentId(0)
otherEnvironmentId = EnvironmentId(42)
defaultDesiredRunnersCount = 5 defaultDesiredRunnersCount = 5
jobId = "4n0th3r-j0b-1d"
waitTime = 100 * time.Millisecond
) )
func TestGetNextRunnerTestSuite(t *testing.T) { func TestGetNextRunnerTestSuite(t *testing.T) {
@ -32,7 +27,7 @@ type ManagerTestSuite struct {
func (suite *ManagerTestSuite) SetupTest() { func (suite *ManagerTestSuite) SetupTest() {
suite.apiMock = &nomad.ExecutorApiMock{} suite.apiMock = &nomad.ExecutorApiMock{}
suite.nomadRunnerManager = NewNomadRunnerManager(suite.apiMock) suite.nomadRunnerManager = NewNomadRunnerManager(suite.apiMock)
suite.exerciseRunner = CreateTestRunner() suite.exerciseRunner = NewRunner(defaultRunnerId)
suite.mockRunnerQueries([]string{}) suite.mockRunnerQueries([]string{})
suite.registerDefaultEnvironment() suite.registerDefaultEnvironment()
} }
@ -40,13 +35,13 @@ func (suite *ManagerTestSuite) SetupTest() {
func (suite *ManagerTestSuite) mockRunnerQueries(returnedRunnerIds []string) { func (suite *ManagerTestSuite) mockRunnerQueries(returnedRunnerIds []string) {
// reset expected calls to allow new mocked return values // reset expected calls to allow new mocked return values
suite.apiMock.ExpectedCalls = []*mock.Call{} suite.apiMock.ExpectedCalls = []*mock.Call{}
suite.apiMock.On("LoadRunners", jobId).Return(returnedRunnerIds, nil) suite.apiMock.On("LoadRunners", defaultJobId).Return(returnedRunnerIds, nil)
suite.apiMock.On("JobScale", jobId).Return(len(returnedRunnerIds), nil) suite.apiMock.On("JobScale", defaultJobId).Return(len(returnedRunnerIds), nil)
suite.apiMock.On("SetJobScale", jobId, mock.AnythingOfType("int"), "Runner Requested").Return(nil) suite.apiMock.On("SetJobScale", defaultJobId, mock.AnythingOfType("int"), "Runner Requested").Return(nil)
} }
func (suite *ManagerTestSuite) registerDefaultEnvironment() { func (suite *ManagerTestSuite) registerDefaultEnvironment() {
suite.nomadRunnerManager.RegisterEnvironment(defaultEnvironmentId, jobId, defaultDesiredRunnersCount) suite.nomadRunnerManager.RegisterEnvironment(defaultEnvironmentId, defaultJobId, defaultDesiredRunnersCount)
} }
func (suite *ManagerTestSuite) AddIdleRunnerForDefaultEnvironment(r Runner) { func (suite *ManagerTestSuite) AddIdleRunnerForDefaultEnvironment(r Runner) {
@ -55,11 +50,11 @@ func (suite *ManagerTestSuite) AddIdleRunnerForDefaultEnvironment(r Runner) {
} }
func (suite *ManagerTestSuite) waitForRunnerRefresh() { func (suite *ManagerTestSuite) waitForRunnerRefresh() {
time.Sleep(waitTime) time.Sleep(100 * time.Millisecond)
} }
func (suite *ManagerTestSuite) TestRegisterEnvironmentAddsNewJob() { func (suite *ManagerTestSuite) TestRegisterEnvironmentAddsNewJob() {
suite.nomadRunnerManager.RegisterEnvironment(otherEnvironmentId, jobId, defaultDesiredRunnersCount) suite.nomadRunnerManager.RegisterEnvironment(anotherEnvironmentId, defaultJobId, defaultDesiredRunnersCount)
jobEntity, ok := suite.nomadRunnerManager.jobs.Get(defaultEnvironmentId.toString()) jobEntity, ok := suite.nomadRunnerManager.jobs.Get(defaultEnvironmentId.toString())
suite.True(ok) suite.True(ok)
suite.NotNil(jobEntity) suite.NotNil(jobEntity)
@ -87,7 +82,7 @@ func (suite *ManagerTestSuite) TestClaimReturnsErrorIfNoRunnerAvailable() {
func (suite *ManagerTestSuite) TestClaimReturnsNoRunnerOfDifferentEnvironment() { func (suite *ManagerTestSuite) TestClaimReturnsNoRunnerOfDifferentEnvironment() {
suite.AddIdleRunnerForDefaultEnvironment(suite.exerciseRunner) suite.AddIdleRunnerForDefaultEnvironment(suite.exerciseRunner)
receivedRunner, err := suite.nomadRunnerManager.Claim(otherEnvironmentId) receivedRunner, err := suite.nomadRunnerManager.Claim(anotherEnvironmentId)
suite.Nil(receivedRunner) suite.Nil(receivedRunner)
suite.Error(err) suite.Error(err)
} }
@ -108,7 +103,7 @@ func (suite *ManagerTestSuite) TestClaimThrowsAnErrorIfNoRunnersAvailable() {
} }
func (suite *ManagerTestSuite) TestClaimAddsRunnerToUsedRunners() { func (suite *ManagerTestSuite) TestClaimAddsRunnerToUsedRunners() {
suite.mockRunnerQueries([]string{RunnerId}) suite.mockRunnerQueries([]string{defaultRunnerId})
suite.waitForRunnerRefresh() suite.waitForRunnerRefresh()
receivedRunner, _ := suite.nomadRunnerManager.Claim(defaultEnvironmentId) receivedRunner, _ := suite.nomadRunnerManager.Claim(defaultEnvironmentId)
savedRunner, ok := suite.nomadRunnerManager.usedRunners.Get(receivedRunner.Id()) savedRunner, ok := suite.nomadRunnerManager.usedRunners.Get(receivedRunner.Id())
@ -124,7 +119,7 @@ func (suite *ManagerTestSuite) TestGetReturnsRunnerIfRunnerIsUsed() {
} }
func (suite *ManagerTestSuite) TestGetReturnsErrorIfRunnerNotFound() { func (suite *ManagerTestSuite) TestGetReturnsErrorIfRunnerNotFound() {
savedRunner, err := suite.nomadRunnerManager.Get(RunnerId) savedRunner, err := suite.nomadRunnerManager.Get(defaultRunnerId)
suite.Nil(savedRunner) suite.Nil(savedRunner)
suite.Error(err) suite.Error(err)
} }
@ -152,32 +147,33 @@ func (suite *ManagerTestSuite) TestReturnReturnsErrorWhenApiCallFailed() {
} }
func (suite *ManagerTestSuite) TestRefreshFetchesRunners() { func (suite *ManagerTestSuite) TestRefreshFetchesRunners() {
suite.mockRunnerQueries([]string{RunnerId}) suite.mockRunnerQueries([]string{defaultRunnerId})
suite.waitForRunnerRefresh() suite.waitForRunnerRefresh()
suite.apiMock.AssertCalled(suite.T(), "LoadRunners", jobId) suite.apiMock.AssertCalled(suite.T(), "LoadRunners", defaultJobId)
} }
func (suite *ManagerTestSuite) TestNewRunnersFoundInRefreshAreAddedToUnusedRunners() { func (suite *ManagerTestSuite) TestNewRunnersFoundInRefreshAreAddedToIdleRunners() {
suite.mockRunnerQueries([]string{RunnerId}) suite.mockRunnerQueries([]string{defaultRunnerId})
suite.waitForRunnerRefresh() suite.waitForRunnerRefresh()
availableRunner, _ := suite.nomadRunnerManager.Claim(defaultEnvironmentId) jobEntity, _ := suite.nomadRunnerManager.jobs.Get(defaultEnvironmentId.toString())
suite.Equal(availableRunner.Id(), RunnerId) _, ok := jobEntity.(*NomadJob).idleRunners.Get(defaultRunnerId)
suite.True(ok)
} }
func (suite *ManagerTestSuite) TestRefreshScalesJob() { func (suite *ManagerTestSuite) TestRefreshScalesJob() {
suite.mockRunnerQueries([]string{RunnerId}) suite.mockRunnerQueries([]string{defaultRunnerId})
suite.waitForRunnerRefresh() suite.waitForRunnerRefresh()
// use one runner to necessitate rescaling // use one runner to necessitate rescaling
_, _ = suite.nomadRunnerManager.Claim(defaultEnvironmentId) _, _ = suite.nomadRunnerManager.Claim(defaultEnvironmentId)
suite.waitForRunnerRefresh() suite.waitForRunnerRefresh()
suite.apiMock.AssertCalled(suite.T(), "SetJobScale", jobId, defaultDesiredRunnersCount+1, "Runner Requested") suite.apiMock.AssertCalled(suite.T(), "SetJobScale", defaultJobId, defaultDesiredRunnersCount+1, "Runner Requested")
} }
func (suite *ManagerTestSuite) TestRefreshAddsRunnerToPool() { func (suite *ManagerTestSuite) TestRefreshAddsRunnerToPool() {
suite.mockRunnerQueries([]string{RunnerId}) suite.mockRunnerQueries([]string{defaultRunnerId})
suite.waitForRunnerRefresh() suite.waitForRunnerRefresh()
jobEntity, _ := suite.nomadRunnerManager.jobs.Get(defaultEnvironmentId.toString()) jobEntity, _ := suite.nomadRunnerManager.jobs.Get(defaultEnvironmentId.toString())
poolRunner, ok := jobEntity.(*NomadJob).idleRunners.Get(RunnerId) poolRunner, ok := jobEntity.(*NomadJob).idleRunners.Get(defaultRunnerId)
suite.True(ok) suite.True(ok)
suite.Equal(RunnerId, poolRunner.Id()) suite.Equal(defaultRunnerId, poolRunner.Id())
} }

View File

@ -7,12 +7,6 @@ import (
"testing" "testing"
) )
type DummyEntity struct{}
func (DummyEntity) Id() string {
return ""
}
func TestRunnerPoolTestSuite(t *testing.T) { func TestRunnerPoolTestSuite(t *testing.T) {
suite.Run(t, new(RunnerPoolTestSuite)) suite.Run(t, new(RunnerPoolTestSuite))
} }
@ -25,7 +19,7 @@ type RunnerPoolTestSuite struct {
func (suite *RunnerPoolTestSuite) SetupTest() { func (suite *RunnerPoolTestSuite) SetupTest() {
suite.runnerPool = NewLocalRunnerPool() suite.runnerPool = NewLocalRunnerPool()
suite.runner = CreateTestRunner() suite.runner = NewRunner(defaultRunnerId)
} }
func (suite *RunnerPoolTestSuite) TestAddInvalidEntityTypeThrowsFatal() { func (suite *RunnerPoolTestSuite) TestAddInvalidEntityTypeThrowsFatal() {
@ -41,7 +35,7 @@ func (suite *RunnerPoolTestSuite) TestAddInvalidEntityTypeThrowsFatal() {
suite.Equal(dummyEntity, hook.LastEntry().Data["entity"]) suite.Equal(dummyEntity, hook.LastEntry().Data["entity"])
} }
func (suite *RunnerPoolTestSuite) TestAddValidEntityThrowsFatal() { func (suite *RunnerPoolTestSuite) TestAddValidEntityDoesNotThrowFatal() {
var hook *test.Hook var hook *test.Hook
logger, hook := test.NewNullLogger() logger, hook := test.NewNullLogger()
log = logger.WithField("pkg", "environment") log = logger.WithField("pkg", "environment")
@ -77,3 +71,55 @@ func (suite *RunnerPoolTestSuite) TestDeletedRunnersAreNotAccessible() {
suite.Nil(retrievedRunner) suite.Nil(retrievedRunner)
suite.False(ok, "A deleted runner should not be accessible") suite.False(ok, "A deleted runner should not be accessible")
} }
func (suite *RunnerPoolTestSuite) TestSampleReturnsRunnerWhenOneIsAvailable() {
suite.runnerPool.Add(suite.runner)
sampledRunner, ok := suite.runnerPool.Sample()
suite.NotNil(sampledRunner)
suite.True(ok)
}
func (suite *RunnerPoolTestSuite) TestSampleReturnsFalseWhenNoneIsAvailable() {
sampledRunner, ok := suite.runnerPool.Sample()
suite.Nil(sampledRunner)
suite.False(ok)
}
func (suite *RunnerPoolTestSuite) TestSampleRemovesRunnerFromPool() {
suite.runnerPool.Add(suite.runner)
sampledRunner, _ := suite.runnerPool.Sample()
_, ok := suite.runnerPool.Get(sampledRunner.Id())
suite.False(ok)
}
func (suite *RunnerPoolTestSuite) TestLenOfEmptyPoolIsZero() {
suite.Equal(0, suite.runnerPool.Len())
}
func (suite *RunnerPoolTestSuite) TestLenChangesOnStoreContentChange() {
suite.Run("len increases when runner is added", func() {
suite.runnerPool.Add(suite.runner)
suite.Equal(1, suite.runnerPool.Len())
})
suite.Run("len does not increase when runner with same id is added", func() {
suite.runnerPool.Add(suite.runner)
suite.Equal(1, suite.runnerPool.Len())
})
suite.Run("len increases again when different runner is added", func() {
anotherRunner := NewRunner(anotherRunnerId)
suite.runnerPool.Add(anotherRunner)
suite.Equal(2, suite.runnerPool.Len())
})
suite.Run("len decreases when runner is deleted", func() {
suite.runnerPool.Delete(suite.runner.Id())
suite.Equal(1, suite.runnerPool.Len())
})
suite.Run("len decreases when runner is sampled", func() {
_, _ = suite.runnerPool.Sample()
suite.Equal(0, suite.runnerPool.Len())
})
}

View File

@ -1,7 +0,0 @@
package runner
const RunnerId = "s0m3-r4nd0m-1d"
func CreateTestRunner() Runner {
return NewRunner(RunnerId)
}