mirror of
https://github.com/elyby/chrly.git
synced 2024-11-27 01:01:59 +05:30
Оттестирован функционал пакета worker
This commit is contained in:
parent
04714543b8
commit
fecfa9c4e8
@ -6,8 +6,8 @@ import (
|
|||||||
"github.com/golang/mock/gomock"
|
"github.com/golang/mock/gomock"
|
||||||
testify "github.com/stretchr/testify/assert"
|
testify "github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
"elyby/minecraft-skinsystem/http/mock_wd"
|
|
||||||
"elyby/minecraft-skinsystem/interfaces/mock_interfaces"
|
"elyby/minecraft-skinsystem/interfaces/mock_interfaces"
|
||||||
|
"elyby/minecraft-skinsystem/interfaces/mock_wd"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestParseUsername(t *testing.T) {
|
func TestParseUsername(t *testing.T) {
|
||||||
|
46
interfaces/mock_interfaces/mock_api.go
Normal file
46
interfaces/mock_interfaces/mock_api.go
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
// Code generated by MockGen. DO NOT EDIT.
|
||||||
|
// Source: interfaces/api.go
|
||||||
|
|
||||||
|
package mock_interfaces
|
||||||
|
|
||||||
|
import (
|
||||||
|
accounts "elyby/minecraft-skinsystem/api/accounts"
|
||||||
|
gomock "github.com/golang/mock/gomock"
|
||||||
|
reflect "reflect"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MockAccountsAPI is a mock of AccountsAPI interface
|
||||||
|
type MockAccountsAPI struct {
|
||||||
|
ctrl *gomock.Controller
|
||||||
|
recorder *MockAccountsAPIMockRecorder
|
||||||
|
}
|
||||||
|
|
||||||
|
// MockAccountsAPIMockRecorder is the mock recorder for MockAccountsAPI
|
||||||
|
type MockAccountsAPIMockRecorder struct {
|
||||||
|
mock *MockAccountsAPI
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewMockAccountsAPI creates a new mock instance
|
||||||
|
func NewMockAccountsAPI(ctrl *gomock.Controller) *MockAccountsAPI {
|
||||||
|
mock := &MockAccountsAPI{ctrl: ctrl}
|
||||||
|
mock.recorder = &MockAccountsAPIMockRecorder{mock}
|
||||||
|
return mock
|
||||||
|
}
|
||||||
|
|
||||||
|
// EXPECT returns an object that allows the caller to indicate expected use
|
||||||
|
func (_m *MockAccountsAPI) EXPECT() *MockAccountsAPIMockRecorder {
|
||||||
|
return _m.recorder
|
||||||
|
}
|
||||||
|
|
||||||
|
// AccountInfo mocks base method
|
||||||
|
func (_m *MockAccountsAPI) AccountInfo(attribute string, value string) (*accounts.AccountInfoResponse, error) {
|
||||||
|
ret := _m.ctrl.Call(_m, "AccountInfo", attribute, value)
|
||||||
|
ret0, _ := ret[0].(*accounts.AccountInfoResponse)
|
||||||
|
ret1, _ := ret[1].(error)
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
|
// AccountInfo indicates an expected call of AccountInfo
|
||||||
|
func (_mr *MockAccountsAPIMockRecorder) AccountInfo(arg0, arg1 interface{}) *gomock.Call {
|
||||||
|
return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "AccountInfo", reflect.TypeOf((*MockAccountsAPI)(nil).AccountInfo), arg0, arg1)
|
||||||
|
}
|
159
worker/worder_test.go
Normal file
159
worker/worder_test.go
Normal file
@ -0,0 +1,159 @@
|
|||||||
|
package worker
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/golang/mock/gomock"
|
||||||
|
testify "github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
|
"elyby/minecraft-skinsystem/api/accounts"
|
||||||
|
"elyby/minecraft-skinsystem/db"
|
||||||
|
"elyby/minecraft-skinsystem/interfaces/mock_interfaces"
|
||||||
|
"elyby/minecraft-skinsystem/interfaces/mock_wd"
|
||||||
|
"elyby/minecraft-skinsystem/model"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestServices_HandleChangeUsername(t *testing.T) {
|
||||||
|
assert := testify.New(t)
|
||||||
|
|
||||||
|
ctrl := gomock.NewController(t)
|
||||||
|
defer ctrl.Finish()
|
||||||
|
|
||||||
|
services, skinRepo, _, wd := setupMocks(ctrl)
|
||||||
|
|
||||||
|
resultModel := createSourceModel()
|
||||||
|
resultModel.Username = "new_username"
|
||||||
|
|
||||||
|
// Запись о скине существует, никаких осложнений
|
||||||
|
skinRepo.EXPECT().FindByUserId(1).Return(createSourceModel(), nil)
|
||||||
|
skinRepo.EXPECT().Save(resultModel)
|
||||||
|
wd.EXPECT().IncCounter("worker.change_username", int64(1))
|
||||||
|
|
||||||
|
assert.True(services.HandleChangeUsername(&model.UsernameChanged{
|
||||||
|
AccountId: 1,
|
||||||
|
OldUsername: "mock_user",
|
||||||
|
NewUsername: "new_username",
|
||||||
|
}))
|
||||||
|
|
||||||
|
// Событие с пустым ником, т.е это регистрация, так что нужно создать запись о скине
|
||||||
|
skinRepo.EXPECT().FindByUserId(1).Times(0)
|
||||||
|
skinRepo.EXPECT().Save(&model.Skin{UserId: 1, Username: "new_mock"})
|
||||||
|
wd.EXPECT().IncCounter("worker.change_username", int64(1))
|
||||||
|
wd.EXPECT().IncCounter("worker.change_username_empty_old_username", int64(1))
|
||||||
|
|
||||||
|
assert.True(services.HandleChangeUsername(&model.UsernameChanged{
|
||||||
|
AccountId: 1,
|
||||||
|
OldUsername: "",
|
||||||
|
NewUsername: "new_mock",
|
||||||
|
}))
|
||||||
|
|
||||||
|
// В базе системы скинов нет записи об указанном пользователе, так что её нужно восстановить
|
||||||
|
skinRepo.EXPECT().FindByUserId(1).Return(nil, &db.SkinNotFoundError{})
|
||||||
|
skinRepo.EXPECT().Save(&model.Skin{UserId: 1, Username: "new_mock2"})
|
||||||
|
wd.EXPECT().IncCounter("worker.change_username", int64(1))
|
||||||
|
wd.EXPECT().IncCounter("worker.change_username_id_not_found", int64(1))
|
||||||
|
|
||||||
|
assert.True(services.HandleChangeUsername(&model.UsernameChanged{
|
||||||
|
AccountId: 1,
|
||||||
|
OldUsername: "mock_user",
|
||||||
|
NewUsername: "new_mock2",
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestServices_HandleSkinChanged(t *testing.T) {
|
||||||
|
assert := testify.New(t)
|
||||||
|
|
||||||
|
ctrl := gomock.NewController(t)
|
||||||
|
defer ctrl.Finish()
|
||||||
|
|
||||||
|
services, skinRepo, accountsAPI, wd := setupMocks(ctrl)
|
||||||
|
|
||||||
|
event := &model.SkinChanged{
|
||||||
|
AccountId: 1,
|
||||||
|
Uuid: "cdb907ce-84f4-4c38-801d-1e287dca2623",
|
||||||
|
SkinId: 2,
|
||||||
|
OldSkinId: 1,
|
||||||
|
Hash: "f76caa016e07267a05b7daf9ebc7419c",
|
||||||
|
Is1_8: true,
|
||||||
|
IsSlim: false,
|
||||||
|
Url: "http://ely.by/minecraft/skins/69c6740d2993e5d6f6a7fc92420efc29.png",
|
||||||
|
MojangTextures: "new mocked textures base64",
|
||||||
|
MojangSignature: "new mocked signature",
|
||||||
|
}
|
||||||
|
|
||||||
|
resultModel := createSourceModel()
|
||||||
|
resultModel.SkinId = event.SkinId
|
||||||
|
resultModel.Hash = event.Hash
|
||||||
|
resultModel.Is1_8 = event.Is1_8
|
||||||
|
resultModel.IsSlim = event.IsSlim
|
||||||
|
resultModel.Url = event.Url
|
||||||
|
resultModel.MojangTextures = event.MojangTextures
|
||||||
|
resultModel.MojangSignature = event.MojangSignature
|
||||||
|
|
||||||
|
// Запись о скине существует, никаких осложнений
|
||||||
|
skinRepo.EXPECT().FindByUserId(1).Return(createSourceModel(), nil)
|
||||||
|
skinRepo.EXPECT().Save(resultModel)
|
||||||
|
wd.EXPECT().IncCounter("worker.skin_changed", int64(1))
|
||||||
|
|
||||||
|
assert.True(services.HandleSkinChanged(event))
|
||||||
|
|
||||||
|
// Записи о скине не существует, она должна быть восстановлена
|
||||||
|
skinRepo.EXPECT().FindByUserId(1).Return(nil, &db.SkinNotFoundError{"mock_user"})
|
||||||
|
skinRepo.EXPECT().Save(resultModel)
|
||||||
|
accountsAPI.EXPECT().AccountInfo("id", "1").Return(&accounts.AccountInfoResponse{
|
||||||
|
Id: 1,
|
||||||
|
Username: "mock_user",
|
||||||
|
Uuid: "cdb907ce-84f4-4c38-801d-1e287dca2623",
|
||||||
|
Email: "mock-user@ely.by",
|
||||||
|
}, nil)
|
||||||
|
wd.EXPECT().IncCounter("worker.skin_changed", int64(1))
|
||||||
|
wd.EXPECT().IncCounter("worker.skin_changed_id_not_found", int64(1))
|
||||||
|
wd.EXPECT().IncCounter("worker.skin_changed_id_restored", int64(1))
|
||||||
|
wd.EXPECT().Warning(gomock.Any())
|
||||||
|
wd.EXPECT().Info(gomock.Any())
|
||||||
|
|
||||||
|
assert.True(services.HandleSkinChanged(event))
|
||||||
|
|
||||||
|
// Записи о скине не существует, и Ely.by Accounts internal API не знает о таком пользователе
|
||||||
|
skinRepo.EXPECT().FindByUserId(1).Return(nil, &db.SkinNotFoundError{"mock_user"})
|
||||||
|
accountsAPI.EXPECT().AccountInfo("id", "1").Return(nil, &accounts.NotFoundResponse{})
|
||||||
|
wd.EXPECT().IncCounter("worker.skin_changed", int64(1))
|
||||||
|
wd.EXPECT().IncCounter("worker.skin_changed_id_not_found", int64(1))
|
||||||
|
wd.EXPECT().IncCounter("worker.skin_changed_id_not_restored", int64(1))
|
||||||
|
wd.EXPECT().Warning(gomock.Any())
|
||||||
|
wd.EXPECT().Error(gomock.Any())
|
||||||
|
|
||||||
|
assert.True(services.HandleSkinChanged(event))
|
||||||
|
}
|
||||||
|
|
||||||
|
func createSourceModel() *model.Skin {
|
||||||
|
return &model.Skin{
|
||||||
|
UserId: 1,
|
||||||
|
Uuid: "cdb907ce-84f4-4c38-801d-1e287dca2623",
|
||||||
|
Username: "mock_user",
|
||||||
|
SkinId: 1,
|
||||||
|
Url: "http://ely.by/minecraft/skins/3a345c701f473ac08c8c5b8ecb58ecf3.png",
|
||||||
|
Is1_8: false,
|
||||||
|
IsSlim: false,
|
||||||
|
Hash: "3a345c701f473ac08c8c5b8ecb58ecf3",
|
||||||
|
MojangTextures: "mocked textures base64",
|
||||||
|
MojangSignature: "mocked signature",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func setupMocks(ctrl *gomock.Controller) (
|
||||||
|
*Services,
|
||||||
|
*mock_interfaces.MockSkinsRepository,
|
||||||
|
*mock_interfaces.MockAccountsAPI,
|
||||||
|
*mock_wd.MockWatchdog,
|
||||||
|
) {
|
||||||
|
skinsRepo := mock_interfaces.NewMockSkinsRepository(ctrl)
|
||||||
|
accountApi := mock_interfaces.NewMockAccountsAPI(ctrl)
|
||||||
|
wd := mock_wd.NewMockWatchdog(ctrl)
|
||||||
|
|
||||||
|
return &Services{
|
||||||
|
SkinsRepo: skinsRepo,
|
||||||
|
AccountsAPI: accountApi,
|
||||||
|
Logger: wd,
|
||||||
|
}, skinsRepo, accountApi, wd
|
||||||
|
}
|
@ -31,24 +31,7 @@ func (service *Services) Run() error {
|
|||||||
forever := make(chan bool)
|
forever := make(chan bool)
|
||||||
go func() {
|
go func() {
|
||||||
for d := range deliveryChannel {
|
for d := range deliveryChannel {
|
||||||
service.Logger.Debug("Incoming message with routing key " + d.RoutingKey)
|
service.HandleDelivery(&d)
|
||||||
var result bool = true
|
|
||||||
switch d.RoutingKey {
|
|
||||||
case "accounts.username-changed":
|
|
||||||
var event *model.UsernameChanged
|
|
||||||
json.Unmarshal(d.Body, &event)
|
|
||||||
result = service.HandleChangeUsername(event)
|
|
||||||
case "accounts.skin-changed":
|
|
||||||
var event *model.SkinChanged
|
|
||||||
json.Unmarshal(d.Body, &event)
|
|
||||||
result = service.HandleSkinChanged(event)
|
|
||||||
}
|
|
||||||
|
|
||||||
if result {
|
|
||||||
d.Ack(false)
|
|
||||||
} else {
|
|
||||||
d.Reject(true)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
<-forever
|
<-forever
|
||||||
@ -56,9 +39,35 @@ func (service *Services) Run() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (service *Services) HandleDelivery(delivery *amqp.Delivery) {
|
||||||
|
service.Logger.Debug("Incoming message with routing key " + delivery.RoutingKey)
|
||||||
|
var result bool = true
|
||||||
|
switch delivery.RoutingKey {
|
||||||
|
case "accounts.username-changed":
|
||||||
|
var event *model.UsernameChanged
|
||||||
|
json.Unmarshal(delivery.Body, &event)
|
||||||
|
result = service.HandleChangeUsername(event)
|
||||||
|
case "accounts.skin-changed":
|
||||||
|
var event *model.SkinChanged
|
||||||
|
json.Unmarshal(delivery.Body, &event)
|
||||||
|
result = service.HandleSkinChanged(event)
|
||||||
|
default:
|
||||||
|
service.Logger.Info("Unknown delivery with routing key " + delivery.RoutingKey)
|
||||||
|
delivery.Ack(false)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if result {
|
||||||
|
delivery.Ack(false)
|
||||||
|
} else {
|
||||||
|
delivery.Reject(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (service *Services) HandleChangeUsername(event *model.UsernameChanged) bool {
|
func (service *Services) HandleChangeUsername(event *model.UsernameChanged) bool {
|
||||||
|
service.Logger.IncCounter("worker.change_username", 1)
|
||||||
if event.OldUsername == "" {
|
if event.OldUsername == "" {
|
||||||
service.Logger.IncCounter("worker.change_username.empty_old_username", 1)
|
service.Logger.IncCounter("worker.change_username_empty_old_username", 1)
|
||||||
record := &model.Skin{
|
record := &model.Skin{
|
||||||
UserId: event.AccountId,
|
UserId: event.AccountId,
|
||||||
Username: event.NewUsername,
|
Username: event.NewUsername,
|
||||||
@ -71,49 +80,42 @@ func (service *Services) HandleChangeUsername(event *model.UsernameChanged) bool
|
|||||||
|
|
||||||
record, err := service.SkinsRepo.FindByUserId(event.AccountId)
|
record, err := service.SkinsRepo.FindByUserId(event.AccountId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
service.Logger.IncCounter("worker.change_username.id_not_found", 1)
|
// TODO: если это не SkinNotFound, то нужно логгировать в Sentry
|
||||||
service.Logger.Warning("Cannot find user id. Trying to search.")
|
service.Logger.IncCounter("worker.change_username_id_not_found", 1)
|
||||||
response, err := service.AccountsAPI.AccountInfo("id", strconv.Itoa(event.AccountId))
|
|
||||||
if err != nil {
|
|
||||||
service.Logger.IncCounter("worker.change_username.id_not_restored", 1)
|
|
||||||
service.Logger.Error(fmt.Sprintf("Cannot restore user info. %+v\n", err))
|
|
||||||
// TODO: логгировать в какой-нибудь Sentry, если там не 404
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
service.Logger.IncCounter("worker.change_username.id_restored", 1)
|
|
||||||
fmt.Println("User info successfully restored.")
|
|
||||||
record = &model.Skin{
|
record = &model.Skin{
|
||||||
UserId: response.Id,
|
UserId: event.AccountId,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
record.Username = event.NewUsername
|
record.Username = event.NewUsername
|
||||||
service.SkinsRepo.Save(record)
|
service.SkinsRepo.Save(record)
|
||||||
|
|
||||||
service.Logger.IncCounter("worker.change_username.processed", 1)
|
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: возможно стоит добавить проверку на совпадение id аккаунтов
|
||||||
func (service *Services) HandleSkinChanged(event *model.SkinChanged) bool {
|
func (service *Services) HandleSkinChanged(event *model.SkinChanged) bool {
|
||||||
|
service.Logger.IncCounter("worker.skin_changed", 1)
|
||||||
|
var record *model.Skin
|
||||||
record, err := service.SkinsRepo.FindByUserId(event.AccountId)
|
record, err := service.SkinsRepo.FindByUserId(event.AccountId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
service.Logger.IncCounter("worker.skin_changed.id_not_found", 1)
|
service.Logger.IncCounter("worker.skin_changed_id_not_found", 1)
|
||||||
service.Logger.Warning("Cannot find user id. Trying to search.")
|
service.Logger.Warning("Cannot find user id. Trying to search.")
|
||||||
response, err := service.AccountsAPI.AccountInfo("id", strconv.Itoa(event.AccountId))
|
response, err := service.AccountsAPI.AccountInfo("id", strconv.Itoa(event.AccountId))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
service.Logger.IncCounter("worker.skin_changed.id_not_restored", 1)
|
service.Logger.IncCounter("worker.skin_changed_id_not_restored", 1)
|
||||||
service.Logger.Error(fmt.Sprintf("Cannot restore user info. %+v\n", err))
|
service.Logger.Error(fmt.Sprintf("Cannot restore user info. %+v\n", err))
|
||||||
// TODO: логгировать в какой-нибудь Sentry, если там не 404
|
// TODO: логгировать в какой-нибудь Sentry, если там не 404
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
service.Logger.IncCounter("worker.skin_changed.id_restored", 1)
|
service.Logger.IncCounter("worker.skin_changed_id_restored", 1)
|
||||||
service.Logger.Info("User info successfully restored.")
|
service.Logger.Info("User info successfully restored.")
|
||||||
|
|
||||||
record.UserId = response.Id
|
record = &model.Skin{
|
||||||
record.Username = response.Username
|
UserId: response.Id,
|
||||||
|
Username: response.Username,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
record.Uuid = event.Uuid
|
record.Uuid = event.Uuid
|
||||||
@ -127,8 +129,6 @@ func (service *Services) HandleSkinChanged(event *model.SkinChanged) bool {
|
|||||||
|
|
||||||
service.SkinsRepo.Save(record)
|
service.SkinsRepo.Save(record)
|
||||||
|
|
||||||
service.Logger.IncCounter("worker.skin_changed.processed", 1)
|
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user