diff --git a/mojangtextures/batch_uuids_provider.go b/mojangtextures/batch_uuids_provider.go index d8de3fb..bfd2227 100644 --- a/mojangtextures/batch_uuids_provider.go +++ b/mojangtextures/batch_uuids_provider.go @@ -130,7 +130,7 @@ func NewFullBusStrategy(delay time.Duration, batch int) *FullBusStrategy { func (ctx *FullBusStrategy) Queue(job *job) { n := ctx.queue.Enqueue(job) - if n % ctx.Batch == 0 { + if n%ctx.Batch == 0 { ctx.busIsFull <- true } } @@ -194,8 +194,12 @@ func (ctx *BatchUuidsProvider) GetUuid(username string) (*mojang.ProfileInfo, er } func (ctx *BatchUuidsProvider) startQueue() { + // This synchronization chan is used to ensure that strategy's jobs provider + // will be initialized before any job will be scheduled + d := make(chan struct{}) go func() { jobsChan := ctx.strategy.GetJobs(ctx.context) + close(d) for { select { case <-ctx.context.Done(): @@ -208,6 +212,8 @@ func (ctx *BatchUuidsProvider) startQueue() { } } }() + + <-d } func (ctx *BatchUuidsProvider) performRequest(iteration *JobsIteration) { diff --git a/mojangtextures/batch_uuids_provider_test.go b/mojangtextures/batch_uuids_provider_test.go index c237df6..4f13fd8 100644 --- a/mojangtextures/batch_uuids_provider_test.go +++ b/mojangtextures/batch_uuids_provider_test.go @@ -105,8 +105,33 @@ type batchUuidsProviderTestSuite struct { Strategy *manualStrategy MojangApi *mojangUsernamesToUuidsRequestMock - GetUuidAsync func(username string) <-chan *batchUuidsProviderGetUuidResult - stop context.CancelFunc + stop context.CancelFunc +} + +func (suite *batchUuidsProviderTestSuite) GetUuidAsync(username string) <-chan *batchUuidsProviderGetUuidResult { + s := make(chan struct{}) + // This dirty hack ensures, that the username will be queued before we return control to the caller. + // It's needed to keep expected calls order and prevent cases when iteration happens before + // all usernames will be queued. + suite.Emitter.On("Emit", + "mojang_textures:batch_uuids_provider:queued", + username, + ).Once().Run(func(args mock.Arguments) { + close(s) + }) + + c := make(chan *batchUuidsProviderGetUuidResult) + go func() { + profile, err := suite.Provider.GetUuid(username) + c <- &batchUuidsProviderGetUuidResult{ + Result: profile, + Error: err, + } + }() + + <-s + + return c } func (suite *batchUuidsProviderTestSuite) SetupTest() { @@ -118,32 +143,6 @@ func (suite *batchUuidsProviderTestSuite) SetupTest() { usernamesToUuids = suite.MojangApi.UsernamesToUuids suite.Provider = NewBatchUuidsProvider(ctx, suite.Strategy, suite.Emitter) - - suite.GetUuidAsync = func(username string) <-chan *batchUuidsProviderGetUuidResult { - s := make(chan struct{}) - // This dirty hack ensures, that the username will be queued before we return control to the caller. - // It's needed to keep expected calls order and prevent cases when iteration happens before - // all usernames will be queued. - suite.Emitter.On("Emit", - "mojang_textures:batch_uuids_provider:queued", - username, - ).Once().Run(func(args mock.Arguments) { - close(s) - }) - - c := make(chan *batchUuidsProviderGetUuidResult) - go func() { - profile, err := suite.Provider.GetUuid(username) - c <- &batchUuidsProviderGetUuidResult{ - Result: profile, - Error: err, - } - }() - - <-s - - return c - } } func (suite *batchUuidsProviderTestSuite) TearDownTest() { @@ -196,15 +195,11 @@ func (suite *batchUuidsProviderTestSuite) TestShouldNotSendRequestWhenNoJobsAreR close(done) }) - r := suite.GetUuidAsync("username") // Schedule one username to run the queue + suite.GetUuidAsync("username") // Schedule one username to run the queue suite.Strategy.Iterate(0, 1) // Return no jobs and indicate that there is one job in queue - select { - case <-r: - // fail - case <-done: - return - } + + <-done } // Test written for multiple usernames to ensure that the error