From 533afcc689d8f127c096fe846825bfe7eb80f8b9 Mon Sep 17 00:00:00 2001 From: ErickSkrauch Date: Thu, 25 Apr 2019 00:45:04 +0300 Subject: [PATCH] #1: Add logging mechanic and remove awaiting of finishing of all textures requests in usernames queue --- api/mojang/queue/queue.go | 48 +++++++++--- api/mojang/queue/queue_test.go | 135 ++++++++++++++++++++++++++++++--- tests/wd_mock.go | 61 +++++++++++++++ 3 files changed, 221 insertions(+), 23 deletions(-) create mode 100644 tests/wd_mock.go diff --git a/api/mojang/queue/queue.go b/api/mojang/queue/queue.go index 2f8e159..ec3107e 100644 --- a/api/mojang/queue/queue.go +++ b/api/mojang/queue/queue.go @@ -8,6 +8,8 @@ import ( "syscall" "time" + "github.com/mono83/slf/wd" + "github.com/elyby/chrly/api/mojang" ) @@ -23,6 +25,7 @@ var allowedUsernamesRegex = regexp.MustCompile(`^[\w_]{3,16}$`) type JobsQueue struct { Storage Storage + Logger wd.Watchdog onFirstCall sync.Once queue jobsQueue @@ -38,6 +41,7 @@ func (ctx *JobsQueue) GetTexturesForUsername(username string) chan *mojang.Signe responseChan := make(chan *mojang.SignedTexturesResponse) if !allowedUsernamesRegex.MatchString(username) { + ctx.Logger.IncCounter("mojang_textures.invalid_username", 1) go func() { responseChan <- nil close(responseChan) @@ -46,8 +50,12 @@ func (ctx *JobsQueue) GetTexturesForUsername(username string) chan *mojang.Signe return responseChan } + ctx.Logger.IncCounter("mojang_textures.request", 1) + uuid, err := ctx.Storage.GetUuid(username) if err == nil && uuid == "" { + ctx.Logger.IncCounter("mojang_textures.usernames.cache_hit_nil", 1) + go func() { responseChan <- nil close(responseChan) @@ -58,12 +66,15 @@ func (ctx *JobsQueue) GetTexturesForUsername(username string) chan *mojang.Signe isFirstListener := ctx.broadcast.AddListener(username, responseChan) if isFirstListener { + start := time.Now() // TODO: respond nil if processing takes more than 5 seconds resultChan := make(chan *mojang.SignedTexturesResponse) if uuid == "" { + ctx.Logger.IncCounter("mojang_textures.usernames.queued", 1) ctx.queue.Enqueue(&jobItem{username, resultChan}) } else { + ctx.Logger.IncCounter("mojang_textures.usernames.cache_hit", 1) go func() { resultChan <- ctx.getTextures(uuid) }() @@ -73,7 +84,10 @@ func (ctx *JobsQueue) GetTexturesForUsername(username string) chan *mojang.Signe result := <-resultChan close(resultChan) ctx.broadcast.BroadcastAndRemove(username, result) + ctx.Logger.RecordTimer("mojang_textures.result_time", time.Since(start)) }() + } else { + ctx.Logger.IncCounter("mojang_textures.already_in_queue", 1) } return responseChan @@ -85,7 +99,9 @@ func (ctx *JobsQueue) startQueue() { for forever() { start := time.Now() ctx.queueRound() - time.Sleep(uuidsQueuePeriod - time.Since(start)) + elapsed := time.Since(start) + ctx.Logger.RecordTimer("mojang_textures.usernames.round_time", elapsed) + time.Sleep(uuidsQueuePeriod - elapsed) } }() } @@ -95,7 +111,10 @@ func (ctx *JobsQueue) queueRound() { return } + queueSize := ctx.queue.Size() jobs := ctx.queue.Dequeue(100) + ctx.Logger.UpdateGauge("mojang_textures.usernames.iteration_size", int64(len(jobs))) + ctx.Logger.UpdateGauge("mojang_textures.usernames.queue_size", int64(queueSize-len(jobs))) var usernames []string for _, job := range jobs { usernames = append(usernames, job.Username) @@ -108,14 +127,12 @@ func (ctx *JobsQueue) queueRound() { job.RespondTo <- nil } }() - maybeShouldPanic(err) + ctx.maybeShouldPanic(err) return } - var wg sync.WaitGroup for _, job := range jobs { - wg.Add(1) go func(job *jobItem) { var uuid string // Profiles in response not ordered, so we must search each username over full array @@ -129,27 +146,30 @@ func (ctx *JobsQueue) queueRound() { ctx.Storage.StoreUuid(job.Username, uuid) if uuid == "" { job.RespondTo <- nil + ctx.Logger.IncCounter("mojang_textures.usernames.uuid_miss", 1) } else { job.RespondTo <- ctx.getTextures(uuid) + ctx.Logger.IncCounter("mojang_textures.usernames.uuid_hit", 1) } - - wg.Done() }(job) } - - wg.Wait() } func (ctx *JobsQueue) getTextures(uuid string) *mojang.SignedTexturesResponse { existsTextures, err := ctx.Storage.GetTextures(uuid) if err == nil { + ctx.Logger.IncCounter("mojang_textures.textures.cache_hit", 1) return existsTextures } - shouldCache := true + ctx.Logger.IncCounter("mojang_textures.textures.request", 1) + + start := time.Now() result, err := uuidToTextures(uuid, true) + ctx.Logger.RecordTimer("mojang_textures.textures.request_time", time.Since(start)) + shouldCache := true if err != nil { - maybeShouldPanic(err) + ctx.maybeShouldPanic(err) shouldCache = false } @@ -161,9 +181,15 @@ func (ctx *JobsQueue) getTextures(uuid string) *mojang.SignedTexturesResponse { } // Starts to panic if there's an unexpected error -func maybeShouldPanic(err error) { +func (ctx *JobsQueue) maybeShouldPanic(err error) { + ctx.Logger.Debug("Got response error :err", wd.ErrParam(err)) + switch err.(type) { case mojang.ResponseError: + if _, ok := err.(*mojang.TooManyRequestsError); ok { + ctx.Logger.Warning("Got 429 Too Many Requests :err", wd.ErrParam(err)) + } + return case net.Error: if err.(net.Error).Timeout() { diff --git a/api/mojang/queue/queue_test.go b/api/mojang/queue/queue_test.go index f968ce3..bcc5895 100644 --- a/api/mojang/queue/queue_test.go +++ b/api/mojang/queue/queue_test.go @@ -3,14 +3,17 @@ package queue import ( "crypto/rand" "encoding/base64" - "github.com/elyby/chrly/api/mojang" - "github.com/stretchr/testify/mock" - "github.com/stretchr/testify/suite" "net" "strings" "syscall" - "testing" "time" + + "github.com/elyby/chrly/api/mojang" + + mocks "github.com/elyby/chrly/tests" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/suite" + "testing" ) type mojangApiMocks struct { @@ -69,6 +72,7 @@ type queueTestSuite struct { Queue *JobsQueue Storage *mockStorage MojangApi *mojangApiMocks + Logger *mocks.WdMock Iterate func() iterateChan chan bool @@ -81,8 +85,9 @@ func (suite *queueTestSuite) SetupSuite() { func (suite *queueTestSuite) SetupTest() { suite.Storage = &mockStorage{} + suite.Logger = &mocks.WdMock{} - suite.Queue = &JobsQueue{Storage: suite.Storage} + suite.Queue = &JobsQueue{Storage: suite.Storage, Logger: suite.Logger} suite.iterateChan = make(chan bool) forever = func() bool { @@ -106,15 +111,27 @@ func (suite *queueTestSuite) TearDownTest() { suite.done() suite.MojangApi.AssertExpectations(suite.T()) suite.Storage.AssertExpectations(suite.T()) + suite.Logger.AssertExpectations(suite.T()) } func (suite *queueTestSuite) TestReceiveTexturesForOneUsernameWithoutAnyCache() { expectedResult := &mojang.SignedTexturesResponse{Id: "0d252b7218b648bfb86c2ae476954d32", Name: "maksimkurb"} + suite.Logger.On("IncCounter", "mojang_textures.request", int64(1)).Once() + suite.Logger.On("IncCounter", "mojang_textures.usernames.queued", int64(1)).Once() + suite.Logger.On("UpdateGauge", "mojang_textures.usernames.iteration_size", int64(1)).Once() + suite.Logger.On("UpdateGauge", "mojang_textures.usernames.queue_size", int64(0)).Once() + suite.Logger.On("RecordTimer", "mojang_textures.usernames.round_time", mock.Anything) + suite.Logger.On("IncCounter", "mojang_textures.textures.request", int64(1)).Once() + suite.Logger.On("RecordTimer", "mojang_textures.textures.request_time", mock.Anything).Once() + suite.Logger.On("IncCounter", "mojang_textures.usernames.uuid_hit", int64(1)).Once() + suite.Logger.On("RecordTimer", "mojang_textures.result_time", mock.Anything).Once() + suite.Storage.On("GetUuid", "maksimkurb").Once().Return("", &ValueNotFound{}) suite.Storage.On("StoreUuid", "maksimkurb", "0d252b7218b648bfb86c2ae476954d32").Once() suite.Storage.On("GetTextures", "0d252b7218b648bfb86c2ae476954d32").Once().Return(nil, &ValueNotFound{}) suite.Storage.On("StoreTextures", expectedResult).Once() + suite.MojangApi.On("UsernamesToUuids", []string{"maksimkurb"}).Once().Return([]*mojang.ProfileInfo{ {Id: "0d252b7218b648bfb86c2ae476954d32", Name: "maksimkurb"}, }, nil) @@ -132,6 +149,16 @@ func (suite *queueTestSuite) TestReceiveTexturesForFewUsernamesWithoutAnyCache() expectedResult1 := &mojang.SignedTexturesResponse{Id: "0d252b7218b648bfb86c2ae476954d32", Name: "maksimkurb"} expectedResult2 := &mojang.SignedTexturesResponse{Id: "4566e69fc90748ee8d71d7ba5aa00d20", Name: "Thinkofdeath"} + suite.Logger.On("IncCounter", "mojang_textures.request", int64(1)).Twice() + suite.Logger.On("IncCounter", "mojang_textures.usernames.queued", int64(1)).Twice() + suite.Logger.On("UpdateGauge", "mojang_textures.usernames.iteration_size", int64(2)).Once() + suite.Logger.On("UpdateGauge", "mojang_textures.usernames.queue_size", int64(0)).Once() + suite.Logger.On("RecordTimer", "mojang_textures.usernames.round_time", mock.Anything) + suite.Logger.On("IncCounter", "mojang_textures.textures.request", int64(1)).Twice() + suite.Logger.On("RecordTimer", "mojang_textures.textures.request_time", mock.Anything).Twice() + suite.Logger.On("IncCounter", "mojang_textures.usernames.uuid_hit", int64(1)).Twice() + suite.Logger.On("RecordTimer", "mojang_textures.result_time", mock.Anything).Twice() + suite.Storage.On("GetUuid", "maksimkurb").Once().Return("", &ValueNotFound{}) suite.Storage.On("GetUuid", "Thinkofdeath").Once().Return("", &ValueNotFound{}) suite.Storage.On("StoreUuid", "maksimkurb", "0d252b7218b648bfb86c2ae476954d32").Once() @@ -140,6 +167,7 @@ func (suite *queueTestSuite) TestReceiveTexturesForFewUsernamesWithoutAnyCache() suite.Storage.On("GetTextures", "4566e69fc90748ee8d71d7ba5aa00d20").Once().Return(nil, &ValueNotFound{}) suite.Storage.On("StoreTextures", expectedResult1).Once() suite.Storage.On("StoreTextures", expectedResult2).Once() + suite.MojangApi.On("UsernamesToUuids", []string{"maksimkurb", "Thinkofdeath"}).Once().Return([]*mojang.ProfileInfo{ {Id: "0d252b7218b648bfb86c2ae476954d32", Name: "maksimkurb"}, {Id: "4566e69fc90748ee8d71d7ba5aa00d20", Name: "Thinkofdeath"}, @@ -159,10 +187,17 @@ func (suite *queueTestSuite) TestReceiveTexturesForFewUsernamesWithoutAnyCache() func (suite *queueTestSuite) TestReceiveTexturesForUsernameWithCachedUuid() { expectedResult := &mojang.SignedTexturesResponse{Id: "0d252b7218b648bfb86c2ae476954d32", Name: "maksimkurb"} + suite.Logger.On("IncCounter", "mojang_textures.request", int64(1)).Once() + suite.Logger.On("IncCounter", "mojang_textures.usernames.cache_hit", int64(1)).Once() + suite.Logger.On("IncCounter", "mojang_textures.textures.request", int64(1)).Once() + suite.Logger.On("RecordTimer", "mojang_textures.textures.request_time", mock.Anything).Once() + suite.Logger.On("RecordTimer", "mojang_textures.result_time", mock.Anything).Once() + suite.Storage.On("GetUuid", "maksimkurb").Once().Return("0d252b7218b648bfb86c2ae476954d32", nil) // Storage.StoreUuid shouldn't be called suite.Storage.On("GetTextures", "0d252b7218b648bfb86c2ae476954d32").Once().Return(nil, &ValueNotFound{}) suite.Storage.On("StoreTextures", expectedResult).Once() + // MojangApi.UsernamesToUuids shouldn't be called suite.MojangApi.On("UuidToTextures", "0d252b7218b648bfb86c2ae476954d32", true).Once().Return(expectedResult, nil) @@ -177,10 +212,16 @@ func (suite *queueTestSuite) TestReceiveTexturesForUsernameWithCachedUuid() { func (suite *queueTestSuite) TestReceiveTexturesForUsernameWithFullyCachedResult() { expectedResult := &mojang.SignedTexturesResponse{Id: "0d252b7218b648bfb86c2ae476954d32", Name: "maksimkurb"} + suite.Logger.On("IncCounter", "mojang_textures.request", int64(1)).Once() + suite.Logger.On("IncCounter", "mojang_textures.usernames.cache_hit", int64(1)).Once() + suite.Logger.On("IncCounter", "mojang_textures.textures.cache_hit", int64(1)).Once() + suite.Logger.On("RecordTimer", "mojang_textures.result_time", mock.Anything).Once() + suite.Storage.On("GetUuid", "maksimkurb").Once().Return("0d252b7218b648bfb86c2ae476954d32", nil) // Storage.StoreUuid shouldn't be called suite.Storage.On("GetTextures", "0d252b7218b648bfb86c2ae476954d32").Once().Return(expectedResult, nil) // Storage.StoreTextures shouldn't be called + // MojangApi.UsernamesToUuids shouldn't be called // MojangApi.UuidToTextures shouldn't be called @@ -193,10 +234,14 @@ func (suite *queueTestSuite) TestReceiveTexturesForUsernameWithFullyCachedResult } func (suite *queueTestSuite) TestReceiveTexturesForUsernameWithCachedUnknownUuid() { + suite.Logger.On("IncCounter", "mojang_textures.request", int64(1)).Once() + suite.Logger.On("IncCounter", "mojang_textures.usernames.cache_hit_nil", int64(1)).Once() + suite.Storage.On("GetUuid", "maksimkurb").Once().Return("", nil) // Storage.StoreUuid shouldn't be called // Storage.GetTextures shouldn't be called // Storage.StoreTextures shouldn't be called + // MojangApi.UsernamesToUuids shouldn't be called // MojangApi.UuidToTextures shouldn't be called @@ -213,23 +258,50 @@ func (suite *queueTestSuite) TestReceiveTexturesForMoreThan100Usernames() { usernames[i] = randStr(8) } + suite.Logger.On("IncCounter", "mojang_textures.request", int64(1)).Times(120) + suite.Logger.On("IncCounter", "mojang_textures.usernames.queued", int64(1)).Times(120) + suite.Logger.On("UpdateGauge", "mojang_textures.usernames.iteration_size", int64(100)).Once() + suite.Logger.On("UpdateGauge", "mojang_textures.usernames.iteration_size", int64(20)).Once() + suite.Logger.On("UpdateGauge", "mojang_textures.usernames.queue_size", int64(20)).Once() + suite.Logger.On("UpdateGauge", "mojang_textures.usernames.queue_size", int64(0)).Once() + suite.Logger.On("RecordTimer", "mojang_textures.usernames.round_time", mock.Anything).Twice() + suite.Logger.On("IncCounter", "mojang_textures.usernames.uuid_miss", int64(1)).Times(120) + suite.Logger.On("RecordTimer", "mojang_textures.result_time", mock.Anything).Times(120) + suite.Storage.On("GetUuid", mock.Anything).Times(120).Return("", &ValueNotFound{}) suite.Storage.On("StoreUuid", mock.Anything, "").Times(120) // if username is not compared to uuid, then receive "" // Storage.GetTextures and Storage.SetTextures shouldn't be called + suite.MojangApi.On("UsernamesToUuids", usernames[0:100]).Once().Return([]*mojang.ProfileInfo{}, nil) suite.MojangApi.On("UsernamesToUuids", usernames[100:120]).Once().Return([]*mojang.ProfileInfo{}, nil) - for _, username := range usernames { - suite.Queue.GetTexturesForUsername(username) + channels := make([]chan *mojang.SignedTexturesResponse, 120) + for i, username := range usernames { + channels[i] = suite.Queue.GetTexturesForUsername(username) } suite.Iterate() suite.Iterate() + + for _, channel := range channels { + <-channel + } } func (suite *queueTestSuite) TestReceiveTexturesForTheSameUsernames() { expectedResult := &mojang.SignedTexturesResponse{Id: "0d252b7218b648bfb86c2ae476954d32", Name: "maksimkurb"} + suite.Logger.On("IncCounter", "mojang_textures.request", int64(1)).Twice() + suite.Logger.On("IncCounter", "mojang_textures.usernames.queued", int64(1)).Once() + suite.Logger.On("IncCounter", "mojang_textures.already_in_queue", int64(1)).Once() + suite.Logger.On("UpdateGauge", "mojang_textures.usernames.iteration_size", int64(1)).Once() + suite.Logger.On("UpdateGauge", "mojang_textures.usernames.queue_size", int64(0)).Once() + suite.Logger.On("RecordTimer", "mojang_textures.usernames.round_time", mock.Anything) + suite.Logger.On("IncCounter", "mojang_textures.textures.request", int64(1)).Once() + suite.Logger.On("RecordTimer", "mojang_textures.textures.request_time", mock.Anything).Once() + suite.Logger.On("IncCounter", "mojang_textures.usernames.uuid_hit", int64(1)).Once() + suite.Logger.On("RecordTimer", "mojang_textures.result_time", mock.Anything).Once() + suite.Storage.On("GetUuid", "maksimkurb").Twice().Return("", &ValueNotFound{}) suite.Storage.On("StoreUuid", "maksimkurb", "0d252b7218b648bfb86c2ae476954d32").Once() suite.Storage.On("GetTextures", "0d252b7218b648bfb86c2ae476954d32").Once().Return(nil, &ValueNotFound{}) @@ -251,10 +323,22 @@ func (suite *queueTestSuite) TestReceiveTexturesForTheSameUsernames() { func (suite *queueTestSuite) TestReceiveTexturesForUsernameThatAlreadyProcessing() { expectedResult := &mojang.SignedTexturesResponse{Id: "0d252b7218b648bfb86c2ae476954d32", Name: "maksimkurb"} + suite.Logger.On("IncCounter", "mojang_textures.request", int64(1)).Twice() + suite.Logger.On("IncCounter", "mojang_textures.usernames.queued", int64(1)).Once() + suite.Logger.On("IncCounter", "mojang_textures.already_in_queue", int64(1)).Once() + suite.Logger.On("UpdateGauge", "mojang_textures.usernames.iteration_size", int64(1)).Once() + suite.Logger.On("UpdateGauge", "mojang_textures.usernames.queue_size", int64(0)).Once() + suite.Logger.On("RecordTimer", "mojang_textures.usernames.round_time", mock.Anything) + suite.Logger.On("IncCounter", "mojang_textures.textures.request", int64(1)).Once() + suite.Logger.On("RecordTimer", "mojang_textures.textures.request_time", mock.Anything).Once() + suite.Logger.On("IncCounter", "mojang_textures.usernames.uuid_hit", int64(1)).Once() + suite.Logger.On("RecordTimer", "mojang_textures.result_time", mock.Anything).Once() + suite.Storage.On("GetUuid", "maksimkurb").Twice().Return("", &ValueNotFound{}) suite.Storage.On("StoreUuid", "maksimkurb", "0d252b7218b648bfb86c2ae476954d32").Once() suite.Storage.On("GetTextures", "0d252b7218b648bfb86c2ae476954d32").Once().Return(nil, &ValueNotFound{}) suite.Storage.On("StoreTextures", expectedResult).Once() + suite.MojangApi.On("UsernamesToUuids", []string{"maksimkurb"}).Once().Return([]*mojang.ProfileInfo{ {Id: "0d252b7218b648bfb86c2ae476954d32", Name: "maksimkurb"}, }, nil) @@ -278,9 +362,18 @@ func (suite *queueTestSuite) TestReceiveTexturesForUsernameThatAlreadyProcessing } func (suite *queueTestSuite) TestDoNothingWhenNoTasks() { + suite.Logger.On("IncCounter", "mojang_textures.request", int64(1)).Once() + suite.Logger.On("IncCounter", "mojang_textures.usernames.queued", int64(1)).Once() + suite.Logger.On("UpdateGauge", "mojang_textures.usernames.iteration_size", int64(1)).Once() + suite.Logger.On("UpdateGauge", "mojang_textures.usernames.queue_size", int64(0)).Once() + suite.Logger.On("RecordTimer", "mojang_textures.usernames.round_time", mock.Anything) + suite.Logger.On("IncCounter", "mojang_textures.usernames.uuid_miss", int64(1)).Once() + suite.Logger.On("RecordTimer", "mojang_textures.result_time", mock.Anything).Once() + suite.Storage.On("GetUuid", "maksimkurb").Once().Return("", &ValueNotFound{}) suite.Storage.On("StoreUuid", "maksimkurb", "").Once() // Storage.GetTextures and Storage.StoreTextures shouldn't be called + suite.MojangApi.On("UsernamesToUuids", []string{"maksimkurb"}).Once().Return([]*mojang.ProfileInfo{}, nil) // Perform first iteration and await it finish @@ -313,9 +406,17 @@ var expectedErrors = []error{ } func (suite *queueTestSuite) TestShouldNotPanicWhenExpectedErrorReturnedFromUsernameToUuidRequest() { + suite.Logger.On("IncCounter", mock.Anything, mock.Anything) + suite.Logger.On("UpdateGauge", mock.Anything, mock.Anything) + suite.Logger.On("RecordTimer", mock.Anything, mock.Anything) + suite.Logger.On("Debug", "Got response error :err", mock.Anything).Times(len(expectedErrors)) + suite.Logger.On("Warning", "Got 429 Too Many Requests :err", mock.Anything).Once() + + suite.Storage.On("GetUuid", "maksimkurb").Return("", &ValueNotFound{}) + for _, err := range expectedErrors { - suite.Storage.On("GetUuid", "maksimkurb").Once().Return("", &ValueNotFound{}) suite.MojangApi.On("UsernamesToUuids", []string{"maksimkurb"}).Once().Return(nil, err) + resultChan := suite.Queue.GetTexturesForUsername("maksimkurb") suite.Iterate() suite.Assert().Nil(<-resultChan) @@ -325,15 +426,23 @@ func (suite *queueTestSuite) TestShouldNotPanicWhenExpectedErrorReturnedFromUser } func (suite *queueTestSuite) TestShouldNotPanicWhenExpectedErrorReturnedFromUuidToTexturesRequest() { + suite.Logger.On("IncCounter", mock.Anything, mock.Anything) + suite.Logger.On("UpdateGauge", mock.Anything, mock.Anything) + suite.Logger.On("RecordTimer", mock.Anything, mock.Anything) + suite.Logger.On("Debug", "Got response error :err", mock.Anything).Times(len(expectedErrors)) + suite.Logger.On("Warning", "Got 429 Too Many Requests :err", mock.Anything).Once() + + suite.Storage.On("GetUuid", "maksimkurb").Return("", &ValueNotFound{}) + suite.Storage.On("StoreUuid", "maksimkurb", "0d252b7218b648bfb86c2ae476954d32") + suite.Storage.On("GetTextures", "0d252b7218b648bfb86c2ae476954d32").Return(nil, &ValueNotFound{}) + // Storage.StoreTextures shouldn't be called + for _, err := range expectedErrors { - suite.Storage.On("GetUuid", "maksimkurb").Once().Return("", &ValueNotFound{}) - suite.Storage.On("StoreUuid", "maksimkurb", "0d252b7218b648bfb86c2ae476954d32").Once() - suite.Storage.On("GetTextures", "0d252b7218b648bfb86c2ae476954d32").Once().Return(nil, &ValueNotFound{}) - // Storage.StoreTextures shouldn't be called suite.MojangApi.On("UsernamesToUuids", []string{"maksimkurb"}).Once().Return([]*mojang.ProfileInfo{ {Id: "0d252b7218b648bfb86c2ae476954d32", Name: "maksimkurb"}, }, nil) suite.MojangApi.On("UuidToTextures", "0d252b7218b648bfb86c2ae476954d32", true).Once().Return(nil, err) + resultChan := suite.Queue.GetTexturesForUsername("maksimkurb") suite.Iterate() suite.Assert().Nil(<-resultChan) @@ -343,6 +452,8 @@ func (suite *queueTestSuite) TestShouldNotPanicWhenExpectedErrorReturnedFromUuid } func (suite *queueTestSuite) TestReceiveTexturesForNotAllowedMojangUsername() { + suite.Logger.On("IncCounter", "mojang_textures.invalid_username", int64(1)).Once() + resultChan := suite.Queue.GetTexturesForUsername("Not allowed") suite.Assert().Nil(<-resultChan) } diff --git a/tests/wd_mock.go b/tests/wd_mock.go new file mode 100644 index 0000000..1d30a60 --- /dev/null +++ b/tests/wd_mock.go @@ -0,0 +1,61 @@ +package tests + +import ( + "time" + + "github.com/mono83/slf" + "github.com/mono83/slf/wd" + "github.com/stretchr/testify/mock" +) + +type WdMock struct { + mock.Mock +} + +func (m *WdMock) Trace(message string, p ...slf.Param) { + m.Called(message) +} + +func (m *WdMock) Debug(message string, p ...slf.Param) { + m.Called(message) +} + +func (m *WdMock) Info(message string, p ...slf.Param) { + m.Called(message) +} + +func (m *WdMock) Warning(message string, p ...slf.Param) { + m.Called(message) +} + +func (m *WdMock) Error(message string, p ...slf.Param) { + m.Called(message) +} + +func (m *WdMock) Alert(message string, p ...slf.Param) { + m.Called(message) +} + +func (m *WdMock) Emergency(message string, p ...slf.Param) { + m.Called(message) +} + +func (m *WdMock) IncCounter(name string, value int64, p ...slf.Param) { + m.Called(name, value) +} + +func (m *WdMock) UpdateGauge(name string, value int64, p ...slf.Param) { + m.Called(name, value) +} + +func (m *WdMock) RecordTimer(name string, d time.Duration, p ...slf.Param) { + m.Called(name, d) +} + +func (m *WdMock) Timer(name string, p ...slf.Param) slf.Timer { + return slf.NewTimer(name, p, m) +} + +func (m *WdMock) WithParams(p ...slf.Param) wd.Watchdog { + panic("this method shouldn't be used") +}