mirror of
https://github.com/elyby/chrly.git
synced 2024-12-22 21:19:55 +05:30
#1: Tests for http layer are restored
This commit is contained in:
parent
f7cdab243f
commit
2c7a1625f3
850
http/api_test.go
850
http/api_test.go
@ -17,474 +17,482 @@ import (
|
|||||||
testify "github.com/stretchr/testify/assert"
|
testify "github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestConfig_PostSkin_Valid(t *testing.T) {
|
func TestConfig_PostSkin(t *testing.T) {
|
||||||
assert := testify.New(t)
|
t.Run("Upload new identity with textures info", func(t *testing.T) {
|
||||||
|
assert := testify.New(t)
|
||||||
|
|
||||||
ctrl := gomock.NewController(t)
|
ctrl := gomock.NewController(t)
|
||||||
defer ctrl.Finish()
|
defer ctrl.Finish()
|
||||||
|
|
||||||
config, mocks := setupMocks(ctrl)
|
config, mocks := setupMocks(ctrl)
|
||||||
|
|
||||||
resultModel := createSkinModel("mock_user", false)
|
resultModel := createSkinModel("mock_user", false)
|
||||||
resultModel.SkinId = 5
|
resultModel.SkinId = 5
|
||||||
resultModel.Hash = "94a457d92a61460cb9cb5d6f29732d2a"
|
resultModel.Hash = "94a457d92a61460cb9cb5d6f29732d2a"
|
||||||
resultModel.Url = "http://ely.by/minecraft/skins/default.png"
|
resultModel.Url = "http://ely.by/minecraft/skins/default.png"
|
||||||
resultModel.MojangTextures = ""
|
resultModel.MojangTextures = ""
|
||||||
resultModel.MojangSignature = ""
|
resultModel.MojangSignature = ""
|
||||||
|
|
||||||
mocks.Auth.EXPECT().Check(gomock.Any()).Return(nil)
|
form := url.Values{
|
||||||
mocks.Skins.EXPECT().FindByUserId(1).Return(createSkinModel("mock_user", false), nil)
|
"identityId": {"1"},
|
||||||
mocks.Skins.EXPECT().Save(resultModel).Return(nil)
|
"username": {"mock_user"},
|
||||||
mocks.Log.EXPECT().IncCounter("authentication.challenge", int64(1))
|
"uuid": {"0f657aa8-bfbe-415d-b700-5750090d3af3"},
|
||||||
mocks.Log.EXPECT().IncCounter("authentication.success", int64(1))
|
"skinId": {"5"},
|
||||||
mocks.Log.EXPECT().IncCounter("api.skins.post.request", int64(1))
|
"hash": {"94a457d92a61460cb9cb5d6f29732d2a"},
|
||||||
mocks.Log.EXPECT().IncCounter("api.skins.post.success", int64(1))
|
"is1_8": {"0"},
|
||||||
|
"isSlim": {"0"},
|
||||||
form := url.Values{
|
"url": {"http://ely.by/minecraft/skins/default.png"},
|
||||||
"identityId": {"1"},
|
|
||||||
"username": {"mock_user"},
|
|
||||||
"uuid": {"0f657aa8-bfbe-415d-b700-5750090d3af3"},
|
|
||||||
"skinId": {"5"},
|
|
||||||
"hash": {"94a457d92a61460cb9cb5d6f29732d2a"},
|
|
||||||
"is1_8": {"0"},
|
|
||||||
"isSlim": {"0"},
|
|
||||||
"url": {"http://ely.by/minecraft/skins/default.png"},
|
|
||||||
}
|
|
||||||
|
|
||||||
req := httptest.NewRequest("POST", "http://skinsystem.ely.by/api/skins", bytes.NewBufferString(form.Encode()))
|
|
||||||
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
|
|
||||||
w := httptest.NewRecorder()
|
|
||||||
|
|
||||||
config.CreateHandler().ServeHTTP(w, req)
|
|
||||||
|
|
||||||
resp := w.Result()
|
|
||||||
defer resp.Body.Close()
|
|
||||||
assert.Equal(201, resp.StatusCode)
|
|
||||||
response, _ := ioutil.ReadAll(resp.Body)
|
|
||||||
assert.Empty(response)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestConfig_PostSkin_ChangedIdentityId(t *testing.T) {
|
|
||||||
assert := testify.New(t)
|
|
||||||
|
|
||||||
ctrl := gomock.NewController(t)
|
|
||||||
defer ctrl.Finish()
|
|
||||||
|
|
||||||
config, mocks := setupMocks(ctrl)
|
|
||||||
|
|
||||||
resultModel := createSkinModel("mock_user", false)
|
|
||||||
resultModel.UserId = 2
|
|
||||||
resultModel.SkinId = 5
|
|
||||||
resultModel.Hash = "94a457d92a61460cb9cb5d6f29732d2a"
|
|
||||||
resultModel.Url = "http://ely.by/minecraft/skins/default.png"
|
|
||||||
resultModel.MojangTextures = ""
|
|
||||||
resultModel.MojangSignature = ""
|
|
||||||
|
|
||||||
form := url.Values{
|
|
||||||
"identityId": {"2"},
|
|
||||||
"username": {"mock_user"},
|
|
||||||
"uuid": {"0f657aa8-bfbe-415d-b700-5750090d3af3"},
|
|
||||||
"skinId": {"5"},
|
|
||||||
"hash": {"94a457d92a61460cb9cb5d6f29732d2a"},
|
|
||||||
"is1_8": {"0"},
|
|
||||||
"isSlim": {"0"},
|
|
||||||
"url": {"http://ely.by/minecraft/skins/default.png"},
|
|
||||||
}
|
|
||||||
|
|
||||||
req := httptest.NewRequest("POST", "http://skinsystem.ely.by/api/skins", bytes.NewBufferString(form.Encode()))
|
|
||||||
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
|
|
||||||
w := httptest.NewRecorder()
|
|
||||||
|
|
||||||
mocks.Auth.EXPECT().Check(gomock.Any()).Return(nil)
|
|
||||||
mocks.Skins.EXPECT().FindByUserId(2).Return(nil, &db.SkinNotFoundError{"unknown"})
|
|
||||||
mocks.Skins.EXPECT().FindByUsername("mock_user").Return(createSkinModel("mock_user", false), nil)
|
|
||||||
mocks.Skins.EXPECT().RemoveByUsername("mock_user").Return(nil)
|
|
||||||
mocks.Skins.EXPECT().Save(resultModel).Return(nil)
|
|
||||||
mocks.Log.EXPECT().IncCounter("authentication.challenge", int64(1))
|
|
||||||
mocks.Log.EXPECT().IncCounter("authentication.success", int64(1))
|
|
||||||
mocks.Log.EXPECT().IncCounter("api.skins.post.request", int64(1))
|
|
||||||
mocks.Log.EXPECT().IncCounter("api.skins.post.success", int64(1))
|
|
||||||
|
|
||||||
config.CreateHandler().ServeHTTP(w, req)
|
|
||||||
|
|
||||||
resp := w.Result()
|
|
||||||
defer resp.Body.Close()
|
|
||||||
assert.Equal(201, resp.StatusCode)
|
|
||||||
response, _ := ioutil.ReadAll(resp.Body)
|
|
||||||
assert.Empty(response)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestConfig_PostSkin_ChangedUsername(t *testing.T) {
|
|
||||||
assert := testify.New(t)
|
|
||||||
|
|
||||||
ctrl := gomock.NewController(t)
|
|
||||||
defer ctrl.Finish()
|
|
||||||
|
|
||||||
config, mocks := setupMocks(ctrl)
|
|
||||||
|
|
||||||
resultModel := createSkinModel("changed_username", false)
|
|
||||||
resultModel.SkinId = 5
|
|
||||||
resultModel.Hash = "94a457d92a61460cb9cb5d6f29732d2a"
|
|
||||||
resultModel.Url = "http://ely.by/minecraft/skins/default.png"
|
|
||||||
resultModel.MojangTextures = ""
|
|
||||||
resultModel.MojangSignature = ""
|
|
||||||
|
|
||||||
form := url.Values{
|
|
||||||
"identityId": {"1"},
|
|
||||||
"username": {"changed_username"},
|
|
||||||
"uuid": {"0f657aa8-bfbe-415d-b700-5750090d3af3"},
|
|
||||||
"skinId": {"5"},
|
|
||||||
"hash": {"94a457d92a61460cb9cb5d6f29732d2a"},
|
|
||||||
"is1_8": {"0"},
|
|
||||||
"isSlim": {"0"},
|
|
||||||
"url": {"http://ely.by/minecraft/skins/default.png"},
|
|
||||||
}
|
|
||||||
|
|
||||||
req := httptest.NewRequest("POST", "http://skinsystem.ely.by/api/skins", bytes.NewBufferString(form.Encode()))
|
|
||||||
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
|
|
||||||
w := httptest.NewRecorder()
|
|
||||||
|
|
||||||
mocks.Auth.EXPECT().Check(gomock.Any()).Return(nil)
|
|
||||||
mocks.Skins.EXPECT().FindByUserId(1).Return(createSkinModel("mock_user", false), nil)
|
|
||||||
mocks.Skins.EXPECT().RemoveByUserId(1).Return(nil)
|
|
||||||
mocks.Skins.EXPECT().Save(resultModel).Return(nil)
|
|
||||||
mocks.Log.EXPECT().IncCounter("authentication.challenge", int64(1))
|
|
||||||
mocks.Log.EXPECT().IncCounter("authentication.success", int64(1))
|
|
||||||
mocks.Log.EXPECT().IncCounter("api.skins.post.request", int64(1))
|
|
||||||
mocks.Log.EXPECT().IncCounter("api.skins.post.success", int64(1))
|
|
||||||
|
|
||||||
config.CreateHandler().ServeHTTP(w, req)
|
|
||||||
|
|
||||||
resp := w.Result()
|
|
||||||
defer resp.Body.Close()
|
|
||||||
assert.Equal(201, resp.StatusCode)
|
|
||||||
response, _ := ioutil.ReadAll(resp.Body)
|
|
||||||
assert.Empty(response)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestConfig_PostSkin_CompletelyNewIdentity(t *testing.T) {
|
|
||||||
assert := testify.New(t)
|
|
||||||
|
|
||||||
ctrl := gomock.NewController(t)
|
|
||||||
defer ctrl.Finish()
|
|
||||||
|
|
||||||
config, mocks := setupMocks(ctrl)
|
|
||||||
|
|
||||||
resultModel := createSkinModel("mock_user", false)
|
|
||||||
resultModel.SkinId = 5
|
|
||||||
resultModel.Hash = "94a457d92a61460cb9cb5d6f29732d2a"
|
|
||||||
resultModel.Url = "http://ely.by/minecraft/skins/default.png"
|
|
||||||
resultModel.MojangTextures = ""
|
|
||||||
resultModel.MojangSignature = ""
|
|
||||||
|
|
||||||
form := url.Values{
|
|
||||||
"identityId": {"1"},
|
|
||||||
"username": {"mock_user"},
|
|
||||||
"uuid": {"0f657aa8-bfbe-415d-b700-5750090d3af3"},
|
|
||||||
"skinId": {"5"},
|
|
||||||
"hash": {"94a457d92a61460cb9cb5d6f29732d2a"},
|
|
||||||
"is1_8": {"0"},
|
|
||||||
"isSlim": {"0"},
|
|
||||||
"url": {"http://ely.by/minecraft/skins/default.png"},
|
|
||||||
}
|
|
||||||
|
|
||||||
req := httptest.NewRequest("POST", "http://skinsystem.ely.by/api/skins", bytes.NewBufferString(form.Encode()))
|
|
||||||
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
|
|
||||||
w := httptest.NewRecorder()
|
|
||||||
|
|
||||||
mocks.Auth.EXPECT().Check(gomock.Any()).Return(nil)
|
|
||||||
mocks.Skins.EXPECT().FindByUserId(1).Return(nil, &db.SkinNotFoundError{"unknown"})
|
|
||||||
mocks.Skins.EXPECT().FindByUsername("mock_user").Return(nil, &db.SkinNotFoundError{"mock_user"})
|
|
||||||
mocks.Skins.EXPECT().Save(resultModel).Return(nil)
|
|
||||||
mocks.Log.EXPECT().IncCounter("authentication.challenge", int64(1))
|
|
||||||
mocks.Log.EXPECT().IncCounter("authentication.success", int64(1))
|
|
||||||
mocks.Log.EXPECT().IncCounter("api.skins.post.request", int64(1))
|
|
||||||
mocks.Log.EXPECT().IncCounter("api.skins.post.success", int64(1))
|
|
||||||
|
|
||||||
config.CreateHandler().ServeHTTP(w, req)
|
|
||||||
|
|
||||||
resp := w.Result()
|
|
||||||
defer resp.Body.Close()
|
|
||||||
assert.Equal(201, resp.StatusCode)
|
|
||||||
response, _ := ioutil.ReadAll(resp.Body)
|
|
||||||
assert.Empty(response)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestConfig_PostSkin_UploadSkin(t *testing.T) {
|
|
||||||
assert := testify.New(t)
|
|
||||||
|
|
||||||
ctrl := gomock.NewController(t)
|
|
||||||
defer ctrl.Finish()
|
|
||||||
|
|
||||||
config, mocks := setupMocks(ctrl)
|
|
||||||
|
|
||||||
body := &bytes.Buffer{}
|
|
||||||
writer := multipart.NewWriter(body)
|
|
||||||
|
|
||||||
part, _ := writer.CreateFormFile("skin", "char.png")
|
|
||||||
part.Write(loadSkinFile())
|
|
||||||
|
|
||||||
_ = writer.WriteField("identityId", "1")
|
|
||||||
_ = writer.WriteField("username", "mock_user")
|
|
||||||
_ = writer.WriteField("uuid", "0f657aa8-bfbe-415d-b700-5750090d3af3")
|
|
||||||
_ = writer.WriteField("skinId", "5")
|
|
||||||
|
|
||||||
err := writer.Close()
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
req := httptest.NewRequest("POST", "http://skinsystem.ely.by/api/skins", body)
|
|
||||||
req.Header.Add("Content-Type", writer.FormDataContentType())
|
|
||||||
w := httptest.NewRecorder()
|
|
||||||
|
|
||||||
mocks.Auth.EXPECT().Check(gomock.Any()).Return(nil)
|
|
||||||
mocks.Log.EXPECT().IncCounter("authentication.challenge", int64(1))
|
|
||||||
mocks.Log.EXPECT().IncCounter("authentication.success", int64(1))
|
|
||||||
mocks.Log.EXPECT().IncCounter("api.skins.post.request", int64(1))
|
|
||||||
mocks.Log.EXPECT().IncCounter("api.skins.post.validation_failed", int64(1))
|
|
||||||
|
|
||||||
config.CreateHandler().ServeHTTP(w, req)
|
|
||||||
|
|
||||||
resp := w.Result()
|
|
||||||
defer resp.Body.Close()
|
|
||||||
assert.Equal(400, resp.StatusCode)
|
|
||||||
response, _ := ioutil.ReadAll(resp.Body)
|
|
||||||
assert.JSONEq(`{
|
|
||||||
"errors": {
|
|
||||||
"skin": [
|
|
||||||
"Skin uploading is temporary unavailable"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}`, string(response))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestConfig_PostSkin_RequiredFields(t *testing.T) {
|
req := httptest.NewRequest("POST", "http://skinsystem.ely.by/api/skins", bytes.NewBufferString(form.Encode()))
|
||||||
assert := testify.New(t)
|
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
|
||||||
ctrl := gomock.NewController(t)
|
mocks.Auth.EXPECT().Check(gomock.Any()).Return(nil)
|
||||||
defer ctrl.Finish()
|
mocks.Skins.EXPECT().FindByUserId(1).Return(nil, &db.SkinNotFoundError{Who: "unknown"})
|
||||||
|
mocks.Skins.EXPECT().FindByUsername("mock_user").Return(nil, &db.SkinNotFoundError{Who: "mock_user"})
|
||||||
|
mocks.Skins.EXPECT().Save(resultModel).Return(nil)
|
||||||
|
mocks.Log.EXPECT().IncCounter("authentication.challenge", int64(1))
|
||||||
|
mocks.Log.EXPECT().IncCounter("authentication.success", int64(1))
|
||||||
|
mocks.Log.EXPECT().IncCounter("api.skins.post.request", int64(1))
|
||||||
|
mocks.Log.EXPECT().IncCounter("api.skins.post.success", int64(1))
|
||||||
|
|
||||||
config, mocks := setupMocks(ctrl)
|
config.CreateHandler().ServeHTTP(w, req)
|
||||||
|
|
||||||
form := url.Values{
|
resp := w.Result()
|
||||||
"mojangTextures": {"someBase64EncodedString"},
|
defer resp.Body.Close()
|
||||||
}
|
assert.Equal(201, resp.StatusCode)
|
||||||
|
response, _ := ioutil.ReadAll(resp.Body)
|
||||||
|
assert.Empty(response)
|
||||||
|
})
|
||||||
|
|
||||||
req := httptest.NewRequest("POST", "http://skinsystem.ely.by/api/skins", bytes.NewBufferString(form.Encode()))
|
t.Run("Upload new identity with skin file", func(t *testing.T) {
|
||||||
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
|
assert := testify.New(t)
|
||||||
w := httptest.NewRecorder()
|
|
||||||
|
|
||||||
mocks.Auth.EXPECT().Check(gomock.Any()).Return(nil)
|
ctrl := gomock.NewController(t)
|
||||||
mocks.Log.EXPECT().IncCounter("authentication.challenge", int64(1))
|
defer ctrl.Finish()
|
||||||
mocks.Log.EXPECT().IncCounter("authentication.success", int64(1))
|
|
||||||
mocks.Log.EXPECT().IncCounter("api.skins.post.request", int64(1))
|
|
||||||
mocks.Log.EXPECT().IncCounter("api.skins.post.validation_failed", int64(1))
|
|
||||||
|
|
||||||
config.CreateHandler().ServeHTTP(w, req)
|
config, mocks := setupMocks(ctrl)
|
||||||
|
|
||||||
resp := w.Result()
|
body := &bytes.Buffer{}
|
||||||
defer resp.Body.Close()
|
writer := multipart.NewWriter(body)
|
||||||
assert.Equal(400, resp.StatusCode)
|
|
||||||
response, _ := ioutil.ReadAll(resp.Body)
|
part, _ := writer.CreateFormFile("skin", "char.png")
|
||||||
assert.JSONEq(`{
|
part.Write(loadSkinFile())
|
||||||
"errors": {
|
|
||||||
"identityId": [
|
_ = writer.WriteField("identityId", "1")
|
||||||
"The identityId field is required",
|
_ = writer.WriteField("username", "mock_user")
|
||||||
"The identityId field must be numeric",
|
_ = writer.WriteField("uuid", "0f657aa8-bfbe-415d-b700-5750090d3af3")
|
||||||
"The identityId field must be minimum 1 char"
|
_ = writer.WriteField("skinId", "5")
|
||||||
],
|
|
||||||
"skinId": [
|
err := writer.Close()
|
||||||
"The skinId field is required",
|
if err != nil {
|
||||||
"The skinId field must be numeric",
|
panic(err)
|
||||||
"The skinId field must be minimum 1 char"
|
|
||||||
],
|
|
||||||
"username": [
|
|
||||||
"The username field is required"
|
|
||||||
],
|
|
||||||
"uuid": [
|
|
||||||
"The uuid field is required",
|
|
||||||
"The uuid field must contain valid UUID"
|
|
||||||
],
|
|
||||||
"url": [
|
|
||||||
"One of url or skin should be provided, but not both"
|
|
||||||
],
|
|
||||||
"skin": [
|
|
||||||
"One of url or skin should be provided, but not both"
|
|
||||||
],
|
|
||||||
"mojangSignature": [
|
|
||||||
"The mojangSignature field is required"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}`, string(response))
|
|
||||||
|
req := httptest.NewRequest("POST", "http://skinsystem.ely.by/api/skins", body)
|
||||||
|
req.Header.Add("Content-Type", writer.FormDataContentType())
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
|
||||||
|
mocks.Auth.EXPECT().Check(gomock.Any()).Return(nil)
|
||||||
|
mocks.Log.EXPECT().IncCounter("authentication.challenge", int64(1))
|
||||||
|
mocks.Log.EXPECT().IncCounter("authentication.success", int64(1))
|
||||||
|
mocks.Log.EXPECT().IncCounter("api.skins.post.request", int64(1))
|
||||||
|
mocks.Log.EXPECT().IncCounter("api.skins.post.validation_failed", int64(1))
|
||||||
|
|
||||||
|
config.CreateHandler().ServeHTTP(w, req)
|
||||||
|
|
||||||
|
resp := w.Result()
|
||||||
|
defer resp.Body.Close()
|
||||||
|
assert.Equal(400, resp.StatusCode)
|
||||||
|
response, _ := ioutil.ReadAll(resp.Body)
|
||||||
|
assert.JSONEq(`{
|
||||||
|
"errors": {
|
||||||
|
"skin": [
|
||||||
|
"Skin uploading is temporary unavailable"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}`, string(response))
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("Keep the same identityId, uuid and username, but change textures information", func(t *testing.T) {
|
||||||
|
assert := testify.New(t)
|
||||||
|
|
||||||
|
ctrl := gomock.NewController(t)
|
||||||
|
defer ctrl.Finish()
|
||||||
|
|
||||||
|
config, mocks := setupMocks(ctrl)
|
||||||
|
|
||||||
|
resultModel := createSkinModel("mock_user", false)
|
||||||
|
resultModel.SkinId = 5
|
||||||
|
resultModel.Hash = "94a457d92a61460cb9cb5d6f29732d2a"
|
||||||
|
resultModel.Url = "http://textures-server.com/skin.png"
|
||||||
|
resultModel.MojangTextures = ""
|
||||||
|
resultModel.MojangSignature = ""
|
||||||
|
|
||||||
|
mocks.Auth.EXPECT().Check(gomock.Any()).Return(nil)
|
||||||
|
mocks.Skins.EXPECT().FindByUserId(1).Return(createSkinModel("mock_user", false), nil)
|
||||||
|
mocks.Skins.EXPECT().Save(resultModel).Return(nil)
|
||||||
|
mocks.Log.EXPECT().IncCounter("authentication.challenge", int64(1))
|
||||||
|
mocks.Log.EXPECT().IncCounter("authentication.success", int64(1))
|
||||||
|
mocks.Log.EXPECT().IncCounter("api.skins.post.request", int64(1))
|
||||||
|
mocks.Log.EXPECT().IncCounter("api.skins.post.success", int64(1))
|
||||||
|
|
||||||
|
form := url.Values{
|
||||||
|
"identityId": {"1"},
|
||||||
|
"username": {"mock_user"},
|
||||||
|
"uuid": {"0f657aa8-bfbe-415d-b700-5750090d3af3"},
|
||||||
|
"skinId": {"5"},
|
||||||
|
"hash": {"94a457d92a61460cb9cb5d6f29732d2a"},
|
||||||
|
"is1_8": {"0"},
|
||||||
|
"isSlim": {"0"},
|
||||||
|
"url": {"http://textures-server.com/skin.png"},
|
||||||
|
}
|
||||||
|
|
||||||
|
req := httptest.NewRequest("POST", "http://chrly/api/skins", bytes.NewBufferString(form.Encode()))
|
||||||
|
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
|
||||||
|
config.CreateHandler().ServeHTTP(w, req)
|
||||||
|
|
||||||
|
resp := w.Result()
|
||||||
|
defer resp.Body.Close()
|
||||||
|
assert.Equal(201, resp.StatusCode)
|
||||||
|
response, _ := ioutil.ReadAll(resp.Body)
|
||||||
|
assert.Empty(response)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("Keep the same uuid and username, but change identityId", func(t *testing.T) {
|
||||||
|
assert := testify.New(t)
|
||||||
|
|
||||||
|
ctrl := gomock.NewController(t)
|
||||||
|
defer ctrl.Finish()
|
||||||
|
|
||||||
|
config, mocks := setupMocks(ctrl)
|
||||||
|
|
||||||
|
resultModel := createSkinModel("mock_user", false)
|
||||||
|
resultModel.UserId = 2
|
||||||
|
resultModel.SkinId = 5
|
||||||
|
resultModel.Hash = "94a457d92a61460cb9cb5d6f29732d2a"
|
||||||
|
resultModel.Url = "http://ely.by/minecraft/skins/default.png"
|
||||||
|
resultModel.MojangTextures = ""
|
||||||
|
resultModel.MojangSignature = ""
|
||||||
|
|
||||||
|
form := url.Values{
|
||||||
|
"identityId": {"2"},
|
||||||
|
"username": {"mock_user"},
|
||||||
|
"uuid": {"0f657aa8-bfbe-415d-b700-5750090d3af3"},
|
||||||
|
"skinId": {"5"},
|
||||||
|
"hash": {"94a457d92a61460cb9cb5d6f29732d2a"},
|
||||||
|
"is1_8": {"0"},
|
||||||
|
"isSlim": {"0"},
|
||||||
|
"url": {"http://ely.by/minecraft/skins/default.png"},
|
||||||
|
}
|
||||||
|
|
||||||
|
req := httptest.NewRequest("POST", "http://skinsystem.ely.by/api/skins", bytes.NewBufferString(form.Encode()))
|
||||||
|
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
|
||||||
|
mocks.Auth.EXPECT().Check(gomock.Any()).Return(nil)
|
||||||
|
mocks.Skins.EXPECT().FindByUserId(2).Return(nil, &db.SkinNotFoundError{Who: "unknown"})
|
||||||
|
mocks.Skins.EXPECT().FindByUsername("mock_user").Return(createSkinModel("mock_user", false), nil)
|
||||||
|
mocks.Skins.EXPECT().RemoveByUsername("mock_user").Return(nil)
|
||||||
|
mocks.Skins.EXPECT().Save(resultModel).Return(nil)
|
||||||
|
mocks.Log.EXPECT().IncCounter("authentication.challenge", int64(1))
|
||||||
|
mocks.Log.EXPECT().IncCounter("authentication.success", int64(1))
|
||||||
|
mocks.Log.EXPECT().IncCounter("api.skins.post.request", int64(1))
|
||||||
|
mocks.Log.EXPECT().IncCounter("api.skins.post.success", int64(1))
|
||||||
|
|
||||||
|
config.CreateHandler().ServeHTTP(w, req)
|
||||||
|
|
||||||
|
resp := w.Result()
|
||||||
|
defer resp.Body.Close()
|
||||||
|
assert.Equal(201, resp.StatusCode)
|
||||||
|
response, _ := ioutil.ReadAll(resp.Body)
|
||||||
|
assert.Empty(response)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("Keep the same identityId and uuid, but change username", func(t *testing.T) {
|
||||||
|
assert := testify.New(t)
|
||||||
|
|
||||||
|
ctrl := gomock.NewController(t)
|
||||||
|
defer ctrl.Finish()
|
||||||
|
|
||||||
|
config, mocks := setupMocks(ctrl)
|
||||||
|
|
||||||
|
resultModel := createSkinModel("changed_username", false)
|
||||||
|
resultModel.SkinId = 5
|
||||||
|
resultModel.Hash = "94a457d92a61460cb9cb5d6f29732d2a"
|
||||||
|
resultModel.Url = "http://ely.by/minecraft/skins/default.png"
|
||||||
|
resultModel.MojangTextures = ""
|
||||||
|
resultModel.MojangSignature = ""
|
||||||
|
|
||||||
|
form := url.Values{
|
||||||
|
"identityId": {"1"},
|
||||||
|
"username": {"changed_username"},
|
||||||
|
"uuid": {"0f657aa8-bfbe-415d-b700-5750090d3af3"},
|
||||||
|
"skinId": {"5"},
|
||||||
|
"hash": {"94a457d92a61460cb9cb5d6f29732d2a"},
|
||||||
|
"is1_8": {"0"},
|
||||||
|
"isSlim": {"0"},
|
||||||
|
"url": {"http://ely.by/minecraft/skins/default.png"},
|
||||||
|
}
|
||||||
|
|
||||||
|
req := httptest.NewRequest("POST", "http://skinsystem.ely.by/api/skins", bytes.NewBufferString(form.Encode()))
|
||||||
|
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
|
||||||
|
mocks.Auth.EXPECT().Check(gomock.Any()).Return(nil)
|
||||||
|
mocks.Skins.EXPECT().FindByUserId(1).Return(createSkinModel("mock_user", false), nil)
|
||||||
|
mocks.Skins.EXPECT().RemoveByUserId(1).Return(nil)
|
||||||
|
mocks.Skins.EXPECT().Save(resultModel).Return(nil)
|
||||||
|
mocks.Log.EXPECT().IncCounter("authentication.challenge", int64(1))
|
||||||
|
mocks.Log.EXPECT().IncCounter("authentication.success", int64(1))
|
||||||
|
mocks.Log.EXPECT().IncCounter("api.skins.post.request", int64(1))
|
||||||
|
mocks.Log.EXPECT().IncCounter("api.skins.post.success", int64(1))
|
||||||
|
|
||||||
|
config.CreateHandler().ServeHTTP(w, req)
|
||||||
|
|
||||||
|
resp := w.Result()
|
||||||
|
defer resp.Body.Close()
|
||||||
|
assert.Equal(201, resp.StatusCode)
|
||||||
|
response, _ := ioutil.ReadAll(resp.Body)
|
||||||
|
assert.Empty(response)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("Get errors about required fields", func(t *testing.T) {
|
||||||
|
assert := testify.New(t)
|
||||||
|
|
||||||
|
ctrl := gomock.NewController(t)
|
||||||
|
defer ctrl.Finish()
|
||||||
|
|
||||||
|
config, mocks := setupMocks(ctrl)
|
||||||
|
|
||||||
|
form := url.Values{
|
||||||
|
"mojangTextures": {"someBase64EncodedString"},
|
||||||
|
}
|
||||||
|
|
||||||
|
req := httptest.NewRequest("POST", "http://skinsystem.ely.by/api/skins", bytes.NewBufferString(form.Encode()))
|
||||||
|
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
|
||||||
|
mocks.Auth.EXPECT().Check(gomock.Any()).Return(nil)
|
||||||
|
mocks.Log.EXPECT().IncCounter("authentication.challenge", int64(1))
|
||||||
|
mocks.Log.EXPECT().IncCounter("authentication.success", int64(1))
|
||||||
|
mocks.Log.EXPECT().IncCounter("api.skins.post.request", int64(1))
|
||||||
|
mocks.Log.EXPECT().IncCounter("api.skins.post.validation_failed", int64(1))
|
||||||
|
|
||||||
|
config.CreateHandler().ServeHTTP(w, req)
|
||||||
|
|
||||||
|
resp := w.Result()
|
||||||
|
defer resp.Body.Close()
|
||||||
|
assert.Equal(400, resp.StatusCode)
|
||||||
|
response, _ := ioutil.ReadAll(resp.Body)
|
||||||
|
assert.JSONEq(`{
|
||||||
|
"errors": {
|
||||||
|
"identityId": [
|
||||||
|
"The identityId field is required",
|
||||||
|
"The identityId field must be numeric",
|
||||||
|
"The identityId field must be minimum 1 char"
|
||||||
|
],
|
||||||
|
"skinId": [
|
||||||
|
"The skinId field is required",
|
||||||
|
"The skinId field must be numeric",
|
||||||
|
"The skinId field must be minimum 1 char"
|
||||||
|
],
|
||||||
|
"username": [
|
||||||
|
"The username field is required"
|
||||||
|
],
|
||||||
|
"uuid": [
|
||||||
|
"The uuid field is required",
|
||||||
|
"The uuid field must contain valid UUID"
|
||||||
|
],
|
||||||
|
"url": [
|
||||||
|
"One of url or skin should be provided, but not both"
|
||||||
|
],
|
||||||
|
"skin": [
|
||||||
|
"One of url or skin should be provided, but not both"
|
||||||
|
],
|
||||||
|
"mojangSignature": [
|
||||||
|
"The mojangSignature field is required"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}`, string(response))
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("Perform request without authorization", func(t *testing.T) {
|
||||||
|
assert := testify.New(t)
|
||||||
|
|
||||||
|
ctrl := gomock.NewController(t)
|
||||||
|
defer ctrl.Finish()
|
||||||
|
|
||||||
|
config, mocks := setupMocks(ctrl)
|
||||||
|
|
||||||
|
req := httptest.NewRequest("POST", "http://skinsystem.ely.by/api/skins", nil)
|
||||||
|
req.Header.Add("Authorization", "Bearer invalid.jwt.token")
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
|
||||||
|
mocks.Auth.EXPECT().Check(gomock.Any()).Return(&auth.Unauthorized{"Cannot parse passed JWT token"})
|
||||||
|
mocks.Log.EXPECT().IncCounter("authentication.challenge", int64(1))
|
||||||
|
mocks.Log.EXPECT().IncCounter("authentication.failed", int64(1))
|
||||||
|
|
||||||
|
config.CreateHandler().ServeHTTP(w, req)
|
||||||
|
|
||||||
|
resp := w.Result()
|
||||||
|
defer resp.Body.Close()
|
||||||
|
assert.Equal(403, resp.StatusCode)
|
||||||
|
response, _ := ioutil.ReadAll(resp.Body)
|
||||||
|
assert.JSONEq(`{
|
||||||
|
"error": "Cannot parse passed JWT token"
|
||||||
|
}`, string(response))
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestConfig_PostSkin_Unauthorized(t *testing.T) {
|
func TestConfig_DeleteSkinByUserId(t *testing.T) {
|
||||||
assert := testify.New(t)
|
t.Run("Delete skin by its identity id", func(t *testing.T) {
|
||||||
|
assert := testify.New(t)
|
||||||
|
|
||||||
ctrl := gomock.NewController(t)
|
ctrl := gomock.NewController(t)
|
||||||
defer ctrl.Finish()
|
defer ctrl.Finish()
|
||||||
|
|
||||||
config, mocks := setupMocks(ctrl)
|
config, mocks := setupMocks(ctrl)
|
||||||
|
|
||||||
req := httptest.NewRequest("POST", "http://skinsystem.ely.by/api/skins", nil)
|
req := httptest.NewRequest("DELETE", "http://skinsystem.ely.by/api/skins/id:1", nil)
|
||||||
req.Header.Add("Authorization", "Bearer invalid.jwt.token")
|
w := httptest.NewRecorder()
|
||||||
w := httptest.NewRecorder()
|
|
||||||
|
|
||||||
mocks.Auth.EXPECT().Check(gomock.Any()).Return(&auth.Unauthorized{"Cannot parse passed JWT token"})
|
mocks.Auth.EXPECT().Check(gomock.Any()).Return(nil)
|
||||||
mocks.Log.EXPECT().IncCounter("authentication.challenge", int64(1))
|
mocks.Skins.EXPECT().FindByUserId(1).Return(createSkinModel("mock_user", false), nil)
|
||||||
mocks.Log.EXPECT().IncCounter("authentication.failed", int64(1))
|
mocks.Skins.EXPECT().RemoveByUserId(1).Return(nil)
|
||||||
|
mocks.Log.EXPECT().IncCounter("authentication.challenge", int64(1))
|
||||||
|
mocks.Log.EXPECT().IncCounter("authentication.success", int64(1))
|
||||||
|
mocks.Log.EXPECT().IncCounter("api.skins.delete.request", int64(1))
|
||||||
|
mocks.Log.EXPECT().IncCounter("api.skins.delete.success", int64(1))
|
||||||
|
|
||||||
config.CreateHandler().ServeHTTP(w, req)
|
config.CreateHandler().ServeHTTP(w, req)
|
||||||
|
|
||||||
resp := w.Result()
|
resp := w.Result()
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
assert.Equal(403, resp.StatusCode)
|
assert.Equal(204, resp.StatusCode)
|
||||||
response, _ := ioutil.ReadAll(resp.Body)
|
response, _ := ioutil.ReadAll(resp.Body)
|
||||||
assert.JSONEq(`{
|
assert.Empty(response)
|
||||||
"error": "Cannot parse passed JWT token"
|
})
|
||||||
}`, string(response))
|
|
||||||
|
t.Run("Try to remove not exists identity id", func(t *testing.T) {
|
||||||
|
assert := testify.New(t)
|
||||||
|
|
||||||
|
ctrl := gomock.NewController(t)
|
||||||
|
defer ctrl.Finish()
|
||||||
|
|
||||||
|
config, mocks := setupMocks(ctrl)
|
||||||
|
|
||||||
|
req := httptest.NewRequest("DELETE", "http://skinsystem.ely.by/api/skins/id:2", nil)
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
|
||||||
|
mocks.Auth.EXPECT().Check(gomock.Any()).Return(nil)
|
||||||
|
mocks.Skins.EXPECT().FindByUserId(2).Return(nil, &db.SkinNotFoundError{"unknown"})
|
||||||
|
mocks.Log.EXPECT().IncCounter("authentication.challenge", int64(1))
|
||||||
|
mocks.Log.EXPECT().IncCounter("authentication.success", int64(1))
|
||||||
|
mocks.Log.EXPECT().IncCounter("api.skins.delete.request", int64(1))
|
||||||
|
mocks.Log.EXPECT().IncCounter("api.skins.delete.not_found", int64(1))
|
||||||
|
|
||||||
|
config.CreateHandler().ServeHTTP(w, req)
|
||||||
|
|
||||||
|
resp := w.Result()
|
||||||
|
defer resp.Body.Close()
|
||||||
|
assert.Equal(404, resp.StatusCode)
|
||||||
|
response, _ := ioutil.ReadAll(resp.Body)
|
||||||
|
assert.JSONEq(`[
|
||||||
|
"Cannot find record for requested user id"
|
||||||
|
]`, string(response))
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestConfig_DeleteSkinByUserId_Success(t *testing.T) {
|
func TestConfig_DeleteSkinByUsername(t *testing.T) {
|
||||||
assert := testify.New(t)
|
t.Run("Delete skin by its identity username", func(t *testing.T) {
|
||||||
|
assert := testify.New(t)
|
||||||
|
|
||||||
ctrl := gomock.NewController(t)
|
ctrl := gomock.NewController(t)
|
||||||
defer ctrl.Finish()
|
defer ctrl.Finish()
|
||||||
|
|
||||||
config, mocks := setupMocks(ctrl)
|
config, mocks := setupMocks(ctrl)
|
||||||
|
|
||||||
req := httptest.NewRequest("DELETE", "http://skinsystem.ely.by/api/skins/id:1", nil)
|
req := httptest.NewRequest("DELETE", "http://skinsystem.ely.by/api/skins/mock_user", nil)
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
|
|
||||||
mocks.Auth.EXPECT().Check(gomock.Any()).Return(nil)
|
mocks.Auth.EXPECT().Check(gomock.Any()).Return(nil)
|
||||||
mocks.Skins.EXPECT().FindByUserId(1).Return(createSkinModel("mock_user", false), nil)
|
mocks.Skins.EXPECT().FindByUsername("mock_user").Return(createSkinModel("mock_user", false), nil)
|
||||||
mocks.Skins.EXPECT().RemoveByUserId(1).Return(nil)
|
mocks.Skins.EXPECT().RemoveByUserId(1).Return(nil)
|
||||||
mocks.Log.EXPECT().IncCounter("authentication.challenge", int64(1))
|
mocks.Log.EXPECT().IncCounter("authentication.challenge", int64(1))
|
||||||
mocks.Log.EXPECT().IncCounter("authentication.success", int64(1))
|
mocks.Log.EXPECT().IncCounter("authentication.success", int64(1))
|
||||||
mocks.Log.EXPECT().IncCounter("api.skins.delete.request", int64(1))
|
mocks.Log.EXPECT().IncCounter("api.skins.delete.request", int64(1))
|
||||||
mocks.Log.EXPECT().IncCounter("api.skins.delete.success", int64(1))
|
mocks.Log.EXPECT().IncCounter("api.skins.delete.success", int64(1))
|
||||||
|
|
||||||
config.CreateHandler().ServeHTTP(w, req)
|
config.CreateHandler().ServeHTTP(w, req)
|
||||||
|
|
||||||
resp := w.Result()
|
resp := w.Result()
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
assert.Equal(204, resp.StatusCode)
|
assert.Equal(204, resp.StatusCode)
|
||||||
response, _ := ioutil.ReadAll(resp.Body)
|
response, _ := ioutil.ReadAll(resp.Body)
|
||||||
assert.Empty(response)
|
assert.Empty(response)
|
||||||
}
|
})
|
||||||
|
|
||||||
func TestConfig_DeleteSkinByUserId_NotFound(t *testing.T) {
|
t.Run("Try to remove not exists identity username", func(t *testing.T) {
|
||||||
assert := testify.New(t)
|
assert := testify.New(t)
|
||||||
|
|
||||||
ctrl := gomock.NewController(t)
|
ctrl := gomock.NewController(t)
|
||||||
defer ctrl.Finish()
|
defer ctrl.Finish()
|
||||||
|
|
||||||
config, mocks := setupMocks(ctrl)
|
config, mocks := setupMocks(ctrl)
|
||||||
|
|
||||||
req := httptest.NewRequest("DELETE", "http://skinsystem.ely.by/api/skins/id:2", nil)
|
req := httptest.NewRequest("DELETE", "http://skinsystem.ely.by/api/skins/mock_user_2", nil)
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
|
|
||||||
mocks.Auth.EXPECT().Check(gomock.Any()).Return(nil)
|
mocks.Auth.EXPECT().Check(gomock.Any()).Return(nil)
|
||||||
mocks.Skins.EXPECT().FindByUserId(2).Return(nil, &db.SkinNotFoundError{"unknown"})
|
mocks.Skins.EXPECT().FindByUsername("mock_user_2").Return(nil, &db.SkinNotFoundError{"mock_user_2"})
|
||||||
mocks.Log.EXPECT().IncCounter("authentication.challenge", int64(1))
|
mocks.Log.EXPECT().IncCounter("authentication.challenge", int64(1))
|
||||||
mocks.Log.EXPECT().IncCounter("authentication.success", int64(1))
|
mocks.Log.EXPECT().IncCounter("authentication.success", int64(1))
|
||||||
mocks.Log.EXPECT().IncCounter("api.skins.delete.request", int64(1))
|
mocks.Log.EXPECT().IncCounter("api.skins.delete.request", int64(1))
|
||||||
mocks.Log.EXPECT().IncCounter("api.skins.delete.not_found", int64(1))
|
mocks.Log.EXPECT().IncCounter("api.skins.delete.not_found", int64(1))
|
||||||
|
|
||||||
config.CreateHandler().ServeHTTP(w, req)
|
config.CreateHandler().ServeHTTP(w, req)
|
||||||
|
|
||||||
resp := w.Result()
|
resp := w.Result()
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
assert.Equal(404, resp.StatusCode)
|
assert.Equal(404, resp.StatusCode)
|
||||||
response, _ := ioutil.ReadAll(resp.Body)
|
response, _ := ioutil.ReadAll(resp.Body)
|
||||||
assert.JSONEq(`[
|
assert.JSONEq(`[
|
||||||
"Cannot find record for requested user id"
|
|
||||||
]`, string(response))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestConfig_DeleteSkinByUsername_Success(t *testing.T) {
|
|
||||||
assert := testify.New(t)
|
|
||||||
|
|
||||||
ctrl := gomock.NewController(t)
|
|
||||||
defer ctrl.Finish()
|
|
||||||
|
|
||||||
config, mocks := setupMocks(ctrl)
|
|
||||||
|
|
||||||
req := httptest.NewRequest("DELETE", "http://skinsystem.ely.by/api/skins/mock_user", nil)
|
|
||||||
w := httptest.NewRecorder()
|
|
||||||
|
|
||||||
mocks.Auth.EXPECT().Check(gomock.Any()).Return(nil)
|
|
||||||
mocks.Skins.EXPECT().FindByUsername("mock_user").Return(createSkinModel("mock_user", false), nil)
|
|
||||||
mocks.Skins.EXPECT().RemoveByUserId(1).Return(nil)
|
|
||||||
mocks.Log.EXPECT().IncCounter("authentication.challenge", int64(1))
|
|
||||||
mocks.Log.EXPECT().IncCounter("authentication.success", int64(1))
|
|
||||||
mocks.Log.EXPECT().IncCounter("api.skins.delete.request", int64(1))
|
|
||||||
mocks.Log.EXPECT().IncCounter("api.skins.delete.success", int64(1))
|
|
||||||
|
|
||||||
config.CreateHandler().ServeHTTP(w, req)
|
|
||||||
|
|
||||||
resp := w.Result()
|
|
||||||
defer resp.Body.Close()
|
|
||||||
assert.Equal(204, resp.StatusCode)
|
|
||||||
response, _ := ioutil.ReadAll(resp.Body)
|
|
||||||
assert.Empty(response)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestConfig_DeleteSkinByUsername_NotFound(t *testing.T) {
|
|
||||||
assert := testify.New(t)
|
|
||||||
|
|
||||||
ctrl := gomock.NewController(t)
|
|
||||||
defer ctrl.Finish()
|
|
||||||
|
|
||||||
config, mocks := setupMocks(ctrl)
|
|
||||||
|
|
||||||
req := httptest.NewRequest("DELETE", "http://skinsystem.ely.by/api/skins/mock_user_2", nil)
|
|
||||||
w := httptest.NewRecorder()
|
|
||||||
|
|
||||||
mocks.Auth.EXPECT().Check(gomock.Any()).Return(nil)
|
|
||||||
mocks.Skins.EXPECT().FindByUsername("mock_user_2").Return(nil, &db.SkinNotFoundError{"mock_user_2"})
|
|
||||||
mocks.Log.EXPECT().IncCounter("authentication.challenge", int64(1))
|
|
||||||
mocks.Log.EXPECT().IncCounter("authentication.success", int64(1))
|
|
||||||
mocks.Log.EXPECT().IncCounter("api.skins.delete.request", int64(1))
|
|
||||||
mocks.Log.EXPECT().IncCounter("api.skins.delete.not_found", int64(1))
|
|
||||||
|
|
||||||
config.CreateHandler().ServeHTTP(w, req)
|
|
||||||
|
|
||||||
resp := w.Result()
|
|
||||||
defer resp.Body.Close()
|
|
||||||
assert.Equal(404, resp.StatusCode)
|
|
||||||
response, _ := ioutil.ReadAll(resp.Body)
|
|
||||||
assert.JSONEq(`[
|
|
||||||
"Cannot find record for requested username"
|
"Cannot find record for requested username"
|
||||||
]`, string(response))
|
]`, string(response))
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestConfig_Authenticate_SignatureKeyNotSet(t *testing.T) {
|
func TestConfig_Authenticate(t *testing.T) {
|
||||||
assert := testify.New(t)
|
t.Run("Test behavior when signing key is not set", func(t *testing.T) {
|
||||||
|
assert := testify.New(t)
|
||||||
|
|
||||||
ctrl := gomock.NewController(t)
|
ctrl := gomock.NewController(t)
|
||||||
defer ctrl.Finish()
|
defer ctrl.Finish()
|
||||||
|
|
||||||
config, mocks := setupMocks(ctrl)
|
config, mocks := setupMocks(ctrl)
|
||||||
|
|
||||||
req := httptest.NewRequest("POST", "http://localhost", nil)
|
req := httptest.NewRequest("POST", "http://localhost", nil)
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
|
|
||||||
mocks.Auth.EXPECT().Check(gomock.Any()).Return(&auth.Unauthorized{"signing key not available"})
|
mocks.Auth.EXPECT().Check(gomock.Any()).Return(&auth.Unauthorized{Reason: "signing key not available"})
|
||||||
mocks.Log.EXPECT().IncCounter("authentication.challenge", int64(1))
|
mocks.Log.EXPECT().IncCounter("authentication.challenge", int64(1))
|
||||||
mocks.Log.EXPECT().IncCounter("authentication.failed", int64(1))
|
mocks.Log.EXPECT().IncCounter("authentication.failed", int64(1))
|
||||||
|
|
||||||
res := config.Authenticate(http.HandlerFunc(func (resp http.ResponseWriter, req *http.Request) {}))
|
res := config.Authenticate(http.HandlerFunc(func (resp http.ResponseWriter, req *http.Request) {}))
|
||||||
res.ServeHTTP(w, req)
|
res.ServeHTTP(w, req)
|
||||||
|
|
||||||
resp := w.Result()
|
resp := w.Result()
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
assert.Equal(403, resp.StatusCode)
|
assert.Equal(403, resp.StatusCode)
|
||||||
response, _ := ioutil.ReadAll(resp.Body)
|
response, _ := ioutil.ReadAll(resp.Body)
|
||||||
assert.JSONEq(`{
|
assert.JSONEq(`{
|
||||||
"error": "signing key not available"
|
"error": "signing key not available"
|
||||||
}`, string(response))
|
}`, string(response))
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// base64 https://github.com/mathiasbynens/small/blob/0ca3c51/png-transparent.png
|
// base64 https://github.com/mathiasbynens/small/blob/0ca3c51/png-transparent.png
|
||||||
|
@ -5,6 +5,7 @@ import (
|
|||||||
"image"
|
"image"
|
||||||
"image/png"
|
"image/png"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
@ -15,123 +16,147 @@ import (
|
|||||||
"github.com/elyby/chrly/model"
|
"github.com/elyby/chrly/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type capesTestCase struct {
|
||||||
|
Name string
|
||||||
|
RequestUrl string
|
||||||
|
ExpectedLogKey string
|
||||||
|
ExistsInLocalStorage bool
|
||||||
|
ExistsInMojang bool
|
||||||
|
HasCapeInMojangResp bool
|
||||||
|
AssertResponse func(assert *testify.Assertions, resp *http.Response)
|
||||||
|
}
|
||||||
|
|
||||||
|
var capesTestCases = []*capesTestCase{
|
||||||
|
{
|
||||||
|
Name: "Obtain cape for known username",
|
||||||
|
ExistsInLocalStorage: true,
|
||||||
|
AssertResponse: func(assert *testify.Assertions, resp *http.Response) {
|
||||||
|
assert.Equal(200, resp.StatusCode)
|
||||||
|
responseData, _ := ioutil.ReadAll(resp.Body)
|
||||||
|
assert.Equal(createCape(), responseData)
|
||||||
|
assert.Equal("image/png", resp.Header.Get("Content-Type"))
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "Obtain cape for unknown username that exists in Mojang and has a cape",
|
||||||
|
ExistsInLocalStorage: false,
|
||||||
|
ExistsInMojang: true,
|
||||||
|
HasCapeInMojangResp: true,
|
||||||
|
AssertResponse: func(assert *testify.Assertions, resp *http.Response) {
|
||||||
|
assert.Equal(301, resp.StatusCode)
|
||||||
|
assert.Equal("http://mojang/cape.png", resp.Header.Get("Location"))
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "Obtain cape for unknown username that exists in Mojang, but don't has a cape",
|
||||||
|
ExistsInLocalStorage: false,
|
||||||
|
ExistsInMojang: true,
|
||||||
|
HasCapeInMojangResp: false,
|
||||||
|
AssertResponse: func(assert *testify.Assertions, resp *http.Response) {
|
||||||
|
assert.Equal(404, resp.StatusCode)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "Obtain cape for unknown username that doesn't exists in Mojang",
|
||||||
|
ExistsInLocalStorage: false,
|
||||||
|
ExistsInMojang: false,
|
||||||
|
AssertResponse: func(assert *testify.Assertions, resp *http.Response) {
|
||||||
|
assert.Equal(404, resp.StatusCode)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
func TestConfig_Cape(t *testing.T) {
|
func TestConfig_Cape(t *testing.T) {
|
||||||
assert := testify.New(t)
|
performTest := func(t *testing.T, testCase *capesTestCase) {
|
||||||
|
assert := testify.New(t)
|
||||||
|
|
||||||
ctrl := gomock.NewController(t)
|
ctrl := gomock.NewController(t)
|
||||||
defer ctrl.Finish()
|
defer ctrl.Finish()
|
||||||
|
|
||||||
config, mocks := setupMocks(ctrl)
|
config, mocks := setupMocks(ctrl)
|
||||||
|
|
||||||
cape := createCape()
|
mocks.Log.EXPECT().IncCounter(testCase.ExpectedLogKey, int64(1))
|
||||||
|
if testCase.ExistsInLocalStorage {
|
||||||
|
mocks.Capes.EXPECT().FindByUsername("mock_username").Return(&model.Cape{
|
||||||
|
File: bytes.NewReader(createCape()),
|
||||||
|
}, nil)
|
||||||
|
} else {
|
||||||
|
mocks.Capes.EXPECT().FindByUsername("mock_username").Return(nil, &db.CapeNotFoundError{Who: "mock_username"})
|
||||||
|
}
|
||||||
|
|
||||||
mocks.Capes.EXPECT().FindByUsername("mocked_username").Return(&model.Cape{
|
if testCase.ExistsInMojang {
|
||||||
File: bytes.NewReader(cape),
|
textures := createTexturesResponse(false, testCase.HasCapeInMojangResp)
|
||||||
}, nil)
|
mocks.Queue.On("GetTexturesForUsername", "mock_username").Return(textures)
|
||||||
mocks.Log.EXPECT().IncCounter("capes.request", int64(1))
|
} else {
|
||||||
|
mocks.Queue.On("GetTexturesForUsername", "mock_username").Return(nil)
|
||||||
|
}
|
||||||
|
|
||||||
req := httptest.NewRequest("GET", "http://skinsystem.ely.by/cloaks/mocked_username", nil)
|
req := httptest.NewRequest("GET", testCase.RequestUrl, nil)
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
|
|
||||||
config.CreateHandler().ServeHTTP(w, req)
|
config.CreateHandler().ServeHTTP(w, req)
|
||||||
|
|
||||||
resp := w.Result()
|
resp := w.Result()
|
||||||
assert.Equal(200, resp.StatusCode)
|
testCase.AssertResponse(assert, resp)
|
||||||
responseData, _ := ioutil.ReadAll(resp.Body)
|
}
|
||||||
assert.Equal(cape, responseData)
|
|
||||||
assert.Equal("image/png", resp.Header.Get("Content-Type"))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestConfig_Cape2(t *testing.T) {
|
t.Run("Normal API", func(t *testing.T) {
|
||||||
assert := testify.New(t)
|
for _, testCase := range capesTestCases {
|
||||||
|
testCase.RequestUrl = "http://chrly/cloaks/mock_username"
|
||||||
|
testCase.ExpectedLogKey = "capes.request"
|
||||||
|
t.Run(testCase.Name, func(t *testing.T) {
|
||||||
|
performTest(t, testCase)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
ctrl := gomock.NewController(t)
|
t.Run("GET fallback API", func(t *testing.T) {
|
||||||
defer ctrl.Finish()
|
for _, testCase := range capesTestCases {
|
||||||
|
testCase.RequestUrl = "http://chrly/cloaks?name=mock_username"
|
||||||
|
testCase.ExpectedLogKey = "capes.get_request"
|
||||||
|
t.Run(testCase.Name, func(t *testing.T) {
|
||||||
|
performTest(t, testCase)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
config, mocks := setupMocks(ctrl)
|
t.Run("Should trim trailing slash", func(t *testing.T) {
|
||||||
|
assert := testify.New(t)
|
||||||
|
|
||||||
mocks.Capes.EXPECT().FindByUsername("notch").Return(nil, &db.CapeNotFoundError{"notch"})
|
req := httptest.NewRequest("GET", "http://chrly/cloaks/?name=notch", nil)
|
||||||
mocks.Log.EXPECT().IncCounter("capes.request", int64(1))
|
w := httptest.NewRecorder()
|
||||||
|
|
||||||
req := httptest.NewRequest("GET", "http://skinsystem.ely.by/cloaks/notch", nil)
|
(&Config{}).CreateHandler().ServeHTTP(w, req)
|
||||||
w := httptest.NewRecorder()
|
|
||||||
|
|
||||||
config.CreateHandler().ServeHTTP(w, req)
|
resp := w.Result()
|
||||||
|
assert.Equal(301, resp.StatusCode)
|
||||||
|
assert.Equal("http://chrly/cloaks?name=notch", resp.Header.Get("Location"))
|
||||||
|
})
|
||||||
|
|
||||||
resp := w.Result()
|
t.Run("Return error when name is not provided", func(t *testing.T) {
|
||||||
assert.Equal(301, resp.StatusCode)
|
assert := testify.New(t)
|
||||||
assert.Equal("http://skins.minecraft.net/MinecraftCloaks/notch.png", resp.Header.Get("Location"))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestConfig_CapeGET(t *testing.T) {
|
ctrl := gomock.NewController(t)
|
||||||
assert := testify.New(t)
|
defer ctrl.Finish()
|
||||||
|
|
||||||
ctrl := gomock.NewController(t)
|
config, mocks := setupMocks(ctrl)
|
||||||
defer ctrl.Finish()
|
mocks.Log.EXPECT().IncCounter("capes.get_request", int64(1))
|
||||||
|
|
||||||
config, mocks := setupMocks(ctrl)
|
req := httptest.NewRequest("GET", "http://chrly/cloaks", nil)
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
|
||||||
cape := createCape()
|
config.CreateHandler().ServeHTTP(w, req)
|
||||||
|
|
||||||
mocks.Capes.EXPECT().FindByUsername("mocked_username").Return(&model.Cape{
|
resp := w.Result()
|
||||||
File: bytes.NewReader(cape),
|
assert.Equal(400, resp.StatusCode)
|
||||||
}, nil)
|
})
|
||||||
mocks.Log.EXPECT().IncCounter("capes.request", int64(1)).Times(0)
|
})
|
||||||
mocks.Log.EXPECT().IncCounter("capes.get_request", int64(1))
|
|
||||||
|
|
||||||
req := httptest.NewRequest("GET", "http://skinsystem.ely.by/cloaks?name=mocked_username", nil)
|
|
||||||
w := httptest.NewRecorder()
|
|
||||||
|
|
||||||
config.CreateHandler().ServeHTTP(w, req)
|
|
||||||
|
|
||||||
resp := w.Result()
|
|
||||||
assert.Equal(200, resp.StatusCode)
|
|
||||||
responseData, _ := ioutil.ReadAll(resp.Body)
|
|
||||||
assert.Equal(cape, responseData)
|
|
||||||
assert.Equal("image/png", resp.Header.Get("Content-Type"))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestConfig_CapeGET2(t *testing.T) {
|
|
||||||
assert := testify.New(t)
|
|
||||||
|
|
||||||
ctrl := gomock.NewController(t)
|
|
||||||
defer ctrl.Finish()
|
|
||||||
|
|
||||||
config, mocks := setupMocks(ctrl)
|
|
||||||
|
|
||||||
mocks.Capes.EXPECT().FindByUsername("notch").Return(nil, &db.CapeNotFoundError{"notch"})
|
|
||||||
mocks.Log.EXPECT().IncCounter("capes.request", int64(1)).Times(0)
|
|
||||||
mocks.Log.EXPECT().IncCounter("capes.get_request", int64(1))
|
|
||||||
|
|
||||||
req := httptest.NewRequest("GET", "http://skinsystem.ely.by/cloaks?name=notch", nil)
|
|
||||||
w := httptest.NewRecorder()
|
|
||||||
|
|
||||||
config.CreateHandler().ServeHTTP(w, req)
|
|
||||||
|
|
||||||
resp := w.Result()
|
|
||||||
assert.Equal(301, resp.StatusCode)
|
|
||||||
assert.Equal("http://skins.minecraft.net/MinecraftCloaks/notch.png", resp.Header.Get("Location"))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestConfig_CapeGET3(t *testing.T) {
|
|
||||||
assert := testify.New(t)
|
|
||||||
|
|
||||||
req := httptest.NewRequest("GET", "http://skinsystem.ely.by/cloaks/?name=notch", nil)
|
|
||||||
w := httptest.NewRecorder()
|
|
||||||
|
|
||||||
(&Config{}).CreateHandler().ServeHTTP(w, req)
|
|
||||||
|
|
||||||
resp := w.Result()
|
|
||||||
assert.Equal(301, resp.StatusCode)
|
|
||||||
assert.Equal("http://skinsystem.ely.by/cloaks?name=notch", resp.Header.Get("Location"))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cape md5: 424ff79dce9940af89c28ad80de8aaad
|
// Cape md5: 424ff79dce9940af89c28ad80de8aaad
|
||||||
func createCape() []byte {
|
func createCape() []byte {
|
||||||
img := image.NewAlpha(image.Rect(0, 0, 64, 32))
|
img := image.NewAlpha(image.Rect(0, 0, 64, 32))
|
||||||
writer := &bytes.Buffer{}
|
writer := &bytes.Buffer{}
|
||||||
png.Encode(writer, img)
|
_ = png.Encode(writer, img)
|
||||||
|
|
||||||
pngBytes, _ := ioutil.ReadAll(writer)
|
pngBytes, _ := ioutil.ReadAll(writer)
|
||||||
|
|
||||||
return pngBytes
|
return pngBytes
|
||||||
|
@ -2,7 +2,11 @@ package http
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/elyby/chrly/api/mojang"
|
||||||
|
|
||||||
|
"github.com/elyby/chrly/tests"
|
||||||
"github.com/golang/mock/gomock"
|
"github.com/golang/mock/gomock"
|
||||||
testify "github.com/stretchr/testify/assert"
|
testify "github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
@ -19,6 +23,7 @@ func TestParseUsername(t *testing.T) {
|
|||||||
type mocks struct {
|
type mocks struct {
|
||||||
Skins *mock_interfaces.MockSkinsRepository
|
Skins *mock_interfaces.MockSkinsRepository
|
||||||
Capes *mock_interfaces.MockCapesRepository
|
Capes *mock_interfaces.MockCapesRepository
|
||||||
|
Queue *tests.MojangTexturesQueueMock
|
||||||
Auth *mock_interfaces.MockAuthChecker
|
Auth *mock_interfaces.MockAuthChecker
|
||||||
Log *mock_wd.MockWatchdog
|
Log *mock_wd.MockWatchdog
|
||||||
}
|
}
|
||||||
@ -31,16 +36,54 @@ func setupMocks(ctrl *gomock.Controller) (
|
|||||||
capesRepo := mock_interfaces.NewMockCapesRepository(ctrl)
|
capesRepo := mock_interfaces.NewMockCapesRepository(ctrl)
|
||||||
authChecker := mock_interfaces.NewMockAuthChecker(ctrl)
|
authChecker := mock_interfaces.NewMockAuthChecker(ctrl)
|
||||||
wd := mock_wd.NewMockWatchdog(ctrl)
|
wd := mock_wd.NewMockWatchdog(ctrl)
|
||||||
|
texturesQueue := &tests.MojangTexturesQueueMock{}
|
||||||
|
|
||||||
return &Config{
|
return &Config{
|
||||||
SkinsRepo: skinsRepo,
|
SkinsRepo: skinsRepo,
|
||||||
CapesRepo: capesRepo,
|
CapesRepo: capesRepo,
|
||||||
Auth: authChecker,
|
Auth: authChecker,
|
||||||
Logger: wd,
|
MojangTexturesQueue: texturesQueue,
|
||||||
|
Logger: wd,
|
||||||
}, &mocks{
|
}, &mocks{
|
||||||
Skins: skinsRepo,
|
Skins: skinsRepo,
|
||||||
Capes: capesRepo,
|
Capes: capesRepo,
|
||||||
Auth: authChecker,
|
Auth: authChecker,
|
||||||
|
Queue: texturesQueue,
|
||||||
Log: wd,
|
Log: wd,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func createTexturesResponse(includeSkin bool, includeCape bool) *mojang.SignedTexturesResponse {
|
||||||
|
timeZone, _ := time.LoadLocation("Europe/Minsk")
|
||||||
|
textures := &mojang.TexturesProp{
|
||||||
|
Timestamp: time.Date(2019, 4, 27, 23, 56, 12, 0, timeZone).Unix(),
|
||||||
|
ProfileID: "00000000000000000000000000000000",
|
||||||
|
ProfileName: "mock_user",
|
||||||
|
Textures: &mojang.TexturesResponse{},
|
||||||
|
}
|
||||||
|
|
||||||
|
if includeSkin {
|
||||||
|
textures.Textures.Skin = &mojang.SkinTexturesResponse{
|
||||||
|
Url: "http://mojang/skin.png",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if includeCape {
|
||||||
|
textures.Textures.Cape = &mojang.CapeTexturesResponse{
|
||||||
|
Url: "http://mojang/cape.png",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
response := &mojang.SignedTexturesResponse{
|
||||||
|
Id: "00000000000000000000000000000000",
|
||||||
|
Name: "mock_user",
|
||||||
|
Props: []*mojang.Property{
|
||||||
|
{
|
||||||
|
Name: "textures",
|
||||||
|
Value: mojang.EncodeTextures(textures),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
@ -27,10 +27,6 @@ func (cfg *Config) SignedTextures(response http.ResponseWriter, request *http.Re
|
|||||||
Signature: rec.MojangSignature,
|
Signature: rec.MojangSignature,
|
||||||
Value: rec.MojangTextures,
|
Value: rec.MojangTextures,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
Name: "chrly",
|
|
||||||
Value: "how do you tame a horse in Minecraft?",
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
} else if request.URL.Query().Get("proxy") != "" {
|
} else if request.URL.Query().Get("proxy") != "" {
|
||||||
@ -42,6 +38,11 @@ func (cfg *Config) SignedTextures(response http.ResponseWriter, request *http.Re
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
responseData.Props = append(responseData.Props, &mojang.Property{
|
||||||
|
Name: "chrly",
|
||||||
|
Value: "how do you tame a horse in Minecraft?",
|
||||||
|
})
|
||||||
|
|
||||||
responseJson, _ := json.Marshal(responseData)
|
responseJson, _ := json.Marshal(responseData)
|
||||||
response.Header().Set("Content-Type", "application/json")
|
response.Header().Set("Content-Type", "application/json")
|
||||||
response.Write(responseJson)
|
response.Write(responseJson)
|
||||||
|
@ -12,60 +12,130 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestConfig_SignedTextures(t *testing.T) {
|
func TestConfig_SignedTextures(t *testing.T) {
|
||||||
assert := testify.New(t)
|
t.Run("Obtain signed textures for exists user", func(t *testing.T) {
|
||||||
|
assert := testify.New(t)
|
||||||
|
|
||||||
ctrl := gomock.NewController(t)
|
ctrl := gomock.NewController(t)
|
||||||
defer ctrl.Finish()
|
defer ctrl.Finish()
|
||||||
|
|
||||||
config, mocks := setupMocks(ctrl)
|
config, mocks := setupMocks(ctrl)
|
||||||
|
|
||||||
mocks.Skins.EXPECT().FindByUsername("mock_user").Return(createSkinModel("mock_user", false), nil)
|
mocks.Log.EXPECT().IncCounter("signed_textures.request", int64(1))
|
||||||
mocks.Log.EXPECT().IncCounter("signed_textures.request", int64(1))
|
mocks.Skins.EXPECT().FindByUsername("mock_user").Return(createSkinModel("mock_user", false), nil)
|
||||||
|
|
||||||
req := httptest.NewRequest("GET", "http://skinsystem.ely.by/textures/signed/mock_user", nil)
|
req := httptest.NewRequest("GET", "http://chrly/textures/signed/mock_user", nil)
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
|
|
||||||
config.CreateHandler().ServeHTTP(w, req)
|
config.CreateHandler().ServeHTTP(w, req)
|
||||||
|
|
||||||
resp := w.Result()
|
resp := w.Result()
|
||||||
assert.Equal(200, resp.StatusCode)
|
assert.Equal(200, resp.StatusCode)
|
||||||
assert.Equal("application/json", resp.Header.Get("Content-Type"))
|
assert.Equal("application/json", resp.Header.Get("Content-Type"))
|
||||||
response, _ := ioutil.ReadAll(resp.Body)
|
response, _ := ioutil.ReadAll(resp.Body)
|
||||||
assert.JSONEq(`{
|
assert.JSONEq(`{
|
||||||
"id": "0f657aa8bfbe415db7005750090d3af3",
|
"id": "0f657aa8bfbe415db7005750090d3af3",
|
||||||
"name": "mock_user",
|
"name": "mock_user",
|
||||||
"properties": [
|
"properties": [
|
||||||
{
|
{
|
||||||
"name": "textures",
|
"name": "textures",
|
||||||
"signature": "mocked signature",
|
"signature": "mocked signature",
|
||||||
"value": "mocked textures base64"
|
"value": "mocked textures base64"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "chrly",
|
"name": "chrly",
|
||||||
"value": "how do you tame a horse in Minecraft?"
|
"value": "how do you tame a horse in Minecraft?"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}`, string(response))
|
}`, string(response))
|
||||||
}
|
})
|
||||||
|
|
||||||
func TestConfig_SignedTextures2(t *testing.T) {
|
t.Run("Obtain signed textures for not exists user", func(t *testing.T) {
|
||||||
assert := testify.New(t)
|
assert := testify.New(t)
|
||||||
|
|
||||||
ctrl := gomock.NewController(t)
|
ctrl := gomock.NewController(t)
|
||||||
defer ctrl.Finish()
|
defer ctrl.Finish()
|
||||||
|
|
||||||
config, mocks := setupMocks(ctrl)
|
config, mocks := setupMocks(ctrl)
|
||||||
|
|
||||||
mocks.Skins.EXPECT().FindByUsername("mock_user").Return(nil, &db.SkinNotFoundError{})
|
mocks.Log.EXPECT().IncCounter("signed_textures.request", int64(1))
|
||||||
mocks.Log.EXPECT().IncCounter("signed_textures.request", int64(1))
|
|
||||||
|
mocks.Skins.EXPECT().FindByUsername("mock_user").Return(nil, &db.SkinNotFoundError{})
|
||||||
req := httptest.NewRequest("GET", "http://skinsystem.ely.by/textures/signed/mock_user", nil)
|
|
||||||
w := httptest.NewRecorder()
|
req := httptest.NewRequest("GET", "http://chrly/textures/signed/mock_user", nil)
|
||||||
|
w := httptest.NewRecorder()
|
||||||
config.CreateHandler().ServeHTTP(w, req)
|
|
||||||
|
config.CreateHandler().ServeHTTP(w, req)
|
||||||
resp := w.Result()
|
|
||||||
assert.Equal(204, resp.StatusCode)
|
resp := w.Result()
|
||||||
response, _ := ioutil.ReadAll(resp.Body)
|
assert.Equal(204, resp.StatusCode)
|
||||||
assert.Equal("", string(response))
|
response, _ := ioutil.ReadAll(resp.Body)
|
||||||
|
assert.Equal("", string(response))
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("Obtain signed textures for exists user, but without signed textures", func(t *testing.T) {
|
||||||
|
assert := testify.New(t)
|
||||||
|
|
||||||
|
ctrl := gomock.NewController(t)
|
||||||
|
defer ctrl.Finish()
|
||||||
|
|
||||||
|
config, mocks := setupMocks(ctrl)
|
||||||
|
|
||||||
|
skinModel := createSkinModel("mock_user", false)
|
||||||
|
skinModel.MojangTextures = ""
|
||||||
|
skinModel.MojangSignature = ""
|
||||||
|
|
||||||
|
mocks.Log.EXPECT().IncCounter("signed_textures.request", int64(1))
|
||||||
|
mocks.Skins.EXPECT().FindByUsername("mock_user").Return(skinModel, nil)
|
||||||
|
|
||||||
|
req := httptest.NewRequest("GET", "http://chrly/textures/signed/mock_user", nil)
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
|
||||||
|
config.CreateHandler().ServeHTTP(w, req)
|
||||||
|
|
||||||
|
resp := w.Result()
|
||||||
|
assert.Equal(204, resp.StatusCode)
|
||||||
|
response, _ := ioutil.ReadAll(resp.Body)
|
||||||
|
assert.Equal("", string(response))
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("Obtain signed textures for exists user, but without signed textures", func(t *testing.T) {
|
||||||
|
assert := testify.New(t)
|
||||||
|
|
||||||
|
ctrl := gomock.NewController(t)
|
||||||
|
defer ctrl.Finish()
|
||||||
|
|
||||||
|
config, mocks := setupMocks(ctrl)
|
||||||
|
|
||||||
|
skinModel := createSkinModel("mock_user", false)
|
||||||
|
skinModel.MojangTextures = ""
|
||||||
|
skinModel.MojangSignature = ""
|
||||||
|
|
||||||
|
mocks.Log.EXPECT().IncCounter("signed_textures.request", int64(1))
|
||||||
|
mocks.Skins.EXPECT().FindByUsername("mock_user").Return(skinModel, nil)
|
||||||
|
mocks.Queue.On("GetTexturesForUsername", "mock_user").Once().Return(createTexturesResponse(true, false))
|
||||||
|
|
||||||
|
req := httptest.NewRequest("GET", "http://chrly/textures/signed/mock_user?proxy=true", nil)
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
|
||||||
|
config.CreateHandler().ServeHTTP(w, req)
|
||||||
|
|
||||||
|
resp := w.Result()
|
||||||
|
assert.Equal(200, resp.StatusCode)
|
||||||
|
assert.Equal("application/json", resp.Header.Get("Content-Type"))
|
||||||
|
response, _ := ioutil.ReadAll(resp.Body)
|
||||||
|
assert.JSONEq(`{
|
||||||
|
"id": "00000000000000000000000000000000",
|
||||||
|
"name": "mock_user",
|
||||||
|
"properties": [
|
||||||
|
{
|
||||||
|
"name": "textures",
|
||||||
|
"value": "eyJ0aW1lc3RhbXAiOjE1NTYzOTg1NzIsInByb2ZpbGVJZCI6IjAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwIiwicHJvZmlsZU5hbWUiOiJtb2NrX3VzZXIiLCJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly9tb2phbmcvc2tpbi5wbmcifX19"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "chrly",
|
||||||
|
"value": "how do you tame a horse in Minecraft?"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}`, string(response))
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package http
|
package http
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
@ -11,113 +12,146 @@ import (
|
|||||||
"github.com/elyby/chrly/model"
|
"github.com/elyby/chrly/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type skinsTestCase struct {
|
||||||
|
Name string
|
||||||
|
RequestUrl string
|
||||||
|
ExpectedLogKey string
|
||||||
|
ExistsInLocalStorage bool
|
||||||
|
ExistsInMojang bool
|
||||||
|
HasSkinInMojangResp bool
|
||||||
|
AssertResponse func(assert *testify.Assertions, resp *http.Response)
|
||||||
|
}
|
||||||
|
|
||||||
|
var skinsTestCases = []*skinsTestCase{
|
||||||
|
{
|
||||||
|
Name: "Obtain skin for known username",
|
||||||
|
ExistsInLocalStorage: true,
|
||||||
|
AssertResponse: func(assert *testify.Assertions, resp *http.Response) {
|
||||||
|
assert.Equal(301, resp.StatusCode)
|
||||||
|
assert.Equal("http://chrly/skin.png", resp.Header.Get("Location"))
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "Obtain skin for unknown username that exists in Mojang and has a cape",
|
||||||
|
ExistsInLocalStorage: false,
|
||||||
|
ExistsInMojang: true,
|
||||||
|
HasSkinInMojangResp: true,
|
||||||
|
AssertResponse: func(assert *testify.Assertions, resp *http.Response) {
|
||||||
|
assert.Equal(301, resp.StatusCode)
|
||||||
|
assert.Equal("http://mojang/skin.png", resp.Header.Get("Location"))
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "Obtain skin for unknown username that exists in Mojang, but don't has a cape",
|
||||||
|
ExistsInLocalStorage: false,
|
||||||
|
ExistsInMojang: true,
|
||||||
|
HasSkinInMojangResp: false,
|
||||||
|
AssertResponse: func(assert *testify.Assertions, resp *http.Response) {
|
||||||
|
assert.Equal(404, resp.StatusCode)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "Obtain skin for unknown username that doesn't exists in Mojang",
|
||||||
|
ExistsInLocalStorage: false,
|
||||||
|
ExistsInMojang: false,
|
||||||
|
AssertResponse: func(assert *testify.Assertions, resp *http.Response) {
|
||||||
|
assert.Equal(404, resp.StatusCode)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
func TestConfig_Skin(t *testing.T) {
|
func TestConfig_Skin(t *testing.T) {
|
||||||
assert := testify.New(t)
|
performTest := func(t *testing.T, testCase *skinsTestCase) {
|
||||||
|
assert := testify.New(t)
|
||||||
|
|
||||||
ctrl := gomock.NewController(t)
|
ctrl := gomock.NewController(t)
|
||||||
defer ctrl.Finish()
|
defer ctrl.Finish()
|
||||||
|
|
||||||
config, mocks := setupMocks(ctrl)
|
config, mocks := setupMocks(ctrl)
|
||||||
|
|
||||||
mocks.Skins.EXPECT().FindByUsername("mock_user").Return(createSkinModel("mock_user", false), nil)
|
mocks.Log.EXPECT().IncCounter(testCase.ExpectedLogKey, int64(1))
|
||||||
mocks.Log.EXPECT().IncCounter("skins.request", int64(1))
|
if testCase.ExistsInLocalStorage {
|
||||||
|
mocks.Skins.EXPECT().FindByUsername("mock_username").Return(createSkinModel("mock_username", false), nil)
|
||||||
|
} else {
|
||||||
|
mocks.Skins.EXPECT().FindByUsername("mock_username").Return(nil, &db.SkinNotFoundError{Who: "mock_username"})
|
||||||
|
}
|
||||||
|
|
||||||
req := httptest.NewRequest("GET", "http://skinsystem.ely.by/skins/mock_user", nil)
|
if testCase.ExistsInMojang {
|
||||||
w := httptest.NewRecorder()
|
textures := createTexturesResponse(testCase.HasSkinInMojangResp, true)
|
||||||
|
mocks.Queue.On("GetTexturesForUsername", "mock_username").Return(textures)
|
||||||
|
} else {
|
||||||
|
mocks.Queue.On("GetTexturesForUsername", "mock_username").Return(nil)
|
||||||
|
}
|
||||||
|
|
||||||
config.CreateHandler().ServeHTTP(w, req)
|
req := httptest.NewRequest("GET", testCase.RequestUrl, nil)
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
|
||||||
resp := w.Result()
|
config.CreateHandler().ServeHTTP(w, req)
|
||||||
assert.Equal(301, resp.StatusCode)
|
|
||||||
assert.Equal("http://ely.by/minecraft/skins/skin.png", resp.Header.Get("Location"))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestConfig_Skin2(t *testing.T) {
|
resp := w.Result()
|
||||||
assert := testify.New(t)
|
testCase.AssertResponse(assert, resp)
|
||||||
|
}
|
||||||
|
|
||||||
ctrl := gomock.NewController(t)
|
t.Run("Normal API", func(t *testing.T) {
|
||||||
defer ctrl.Finish()
|
for _, testCase := range skinsTestCases {
|
||||||
|
testCase.RequestUrl = "http://chrly/skins/mock_username"
|
||||||
|
testCase.ExpectedLogKey = "skins.request"
|
||||||
|
t.Run(testCase.Name, func(t *testing.T) {
|
||||||
|
performTest(t, testCase)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
config, mocks := setupMocks(ctrl)
|
t.Run("GET fallback API", func(t *testing.T) {
|
||||||
|
for _, testCase := range skinsTestCases {
|
||||||
|
testCase.RequestUrl = "http://chrly/skins?name=mock_username"
|
||||||
|
testCase.ExpectedLogKey = "skins.get_request"
|
||||||
|
t.Run(testCase.Name, func(t *testing.T) {
|
||||||
|
performTest(t, testCase)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
mocks.Skins.EXPECT().FindByUsername("notch").Return(nil, &db.SkinNotFoundError{"notch"})
|
t.Run("Should trim trailing slash", func(t *testing.T) {
|
||||||
mocks.Log.EXPECT().IncCounter("skins.request", int64(1))
|
assert := testify.New(t)
|
||||||
|
|
||||||
req := httptest.NewRequest("GET", "http://skinsystem.ely.by/skins/notch", nil)
|
req := httptest.NewRequest("GET", "http://chrly/skins/?name=notch", nil)
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
|
|
||||||
config.CreateHandler().ServeHTTP(w, req)
|
(&Config{}).CreateHandler().ServeHTTP(w, req)
|
||||||
|
|
||||||
resp := w.Result()
|
resp := w.Result()
|
||||||
assert.Equal(301, resp.StatusCode)
|
assert.Equal(301, resp.StatusCode)
|
||||||
assert.Equal("http://skins.minecraft.net/MinecraftSkins/notch.png", resp.Header.Get("Location"))
|
assert.Equal("http://chrly/skins?name=notch", resp.Header.Get("Location"))
|
||||||
}
|
})
|
||||||
|
|
||||||
func TestConfig_SkinGET(t *testing.T) {
|
t.Run("Return error when name is not provided", func(t *testing.T) {
|
||||||
assert := testify.New(t)
|
assert := testify.New(t)
|
||||||
|
|
||||||
ctrl := gomock.NewController(t)
|
ctrl := gomock.NewController(t)
|
||||||
defer ctrl.Finish()
|
defer ctrl.Finish()
|
||||||
|
|
||||||
config, mocks := setupMocks(ctrl)
|
config, mocks := setupMocks(ctrl)
|
||||||
|
mocks.Log.EXPECT().IncCounter("skins.get_request", int64(1))
|
||||||
|
|
||||||
mocks.Skins.EXPECT().FindByUsername("mock_user").Return(createSkinModel("mock_user", false), nil)
|
req := httptest.NewRequest("GET", "http://chrly/skins", nil)
|
||||||
mocks.Log.EXPECT().IncCounter("skins.get_request", int64(1))
|
w := httptest.NewRecorder()
|
||||||
mocks.Log.EXPECT().IncCounter("skins.request", int64(1)).Times(0)
|
|
||||||
|
|
||||||
req := httptest.NewRequest("GET", "http://skinsystem.ely.by/skins?name=mock_user", nil)
|
config.CreateHandler().ServeHTTP(w, req)
|
||||||
w := httptest.NewRecorder()
|
|
||||||
|
|
||||||
config.CreateHandler().ServeHTTP(w, req)
|
resp := w.Result()
|
||||||
|
assert.Equal(400, resp.StatusCode)
|
||||||
resp := w.Result()
|
})
|
||||||
assert.Equal(301, resp.StatusCode)
|
})
|
||||||
assert.Equal("http://ely.by/minecraft/skins/skin.png", resp.Header.Get("Location"))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestConfig_SkinGET2(t *testing.T) {
|
|
||||||
assert := testify.New(t)
|
|
||||||
|
|
||||||
ctrl := gomock.NewController(t)
|
|
||||||
defer ctrl.Finish()
|
|
||||||
|
|
||||||
config, mocks := setupMocks(ctrl)
|
|
||||||
|
|
||||||
mocks.Skins.EXPECT().FindByUsername("notch").Return(nil, &db.SkinNotFoundError{"notch"})
|
|
||||||
mocks.Log.EXPECT().IncCounter("skins.get_request", int64(1))
|
|
||||||
mocks.Log.EXPECT().IncCounter("skins.request", int64(1)).Times(0)
|
|
||||||
|
|
||||||
req := httptest.NewRequest("GET", "http://skinsystem.ely.by/skins?name=notch", nil)
|
|
||||||
w := httptest.NewRecorder()
|
|
||||||
|
|
||||||
config.CreateHandler().ServeHTTP(w, req)
|
|
||||||
|
|
||||||
resp := w.Result()
|
|
||||||
assert.Equal(301, resp.StatusCode)
|
|
||||||
assert.Equal("http://skins.minecraft.net/MinecraftSkins/notch.png", resp.Header.Get("Location"))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestConfig_SkinGET3(t *testing.T) {
|
|
||||||
assert := testify.New(t)
|
|
||||||
|
|
||||||
req := httptest.NewRequest("GET", "http://skinsystem.ely.by/skins/?name=notch", nil)
|
|
||||||
w := httptest.NewRecorder()
|
|
||||||
|
|
||||||
(&Config{}).CreateHandler().ServeHTTP(w, req)
|
|
||||||
|
|
||||||
resp := w.Result()
|
|
||||||
assert.Equal(301, resp.StatusCode)
|
|
||||||
assert.Equal("http://skinsystem.ely.by/skins?name=notch", resp.Header.Get("Location"))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func createSkinModel(username string, isSlim bool) *model.Skin {
|
func createSkinModel(username string, isSlim bool) *model.Skin {
|
||||||
return &model.Skin{
|
return &model.Skin{
|
||||||
UserId: 1,
|
UserId: 1,
|
||||||
Username: username,
|
Username: username,
|
||||||
Uuid: "0f657aa8-bfbe-415d-b700-5750090d3af3",
|
Uuid: "0f657aa8-bfbe-415d-b700-5750090d3af3", // Use non nil UUID to pass validation in api tests
|
||||||
SkinId: 1,
|
SkinId: 1,
|
||||||
Hash: "55d2a8848764f5ff04012cdb093458bd",
|
Hash: "00000000000000000000000000000000",
|
||||||
Url: "http://ely.by/minecraft/skins/skin.png",
|
Url: "http://chrly/skin.png",
|
||||||
MojangTextures: "mocked textures base64",
|
MojangTextures: "mocked textures base64",
|
||||||
MojangSignature: "mocked signature",
|
MojangSignature: "mocked signature",
|
||||||
IsSlim: isSlim,
|
IsSlim: isSlim,
|
||||||
|
@ -14,29 +14,28 @@ func (cfg *Config) Textures(response http.ResponseWriter, request *http.Request)
|
|||||||
username := parseUsername(mux.Vars(request)["username"])
|
username := parseUsername(mux.Vars(request)["username"])
|
||||||
|
|
||||||
var textures *mojang.TexturesResponse
|
var textures *mojang.TexturesResponse
|
||||||
skin, err := cfg.SkinsRepo.FindByUsername(username)
|
skin, skinErr := cfg.SkinsRepo.FindByUsername(username)
|
||||||
if err == nil && skin.SkinId != 0 {
|
_, capeErr := cfg.CapesRepo.FindByUsername(username)
|
||||||
textures = &mojang.TexturesResponse{
|
if (skinErr == nil && skin.SkinId != 0) || capeErr == nil {
|
||||||
Skin: &mojang.SkinTexturesResponse{
|
textures = &mojang.TexturesResponse{}
|
||||||
|
|
||||||
|
if skinErr == nil && skin.SkinId != 0 {
|
||||||
|
skinTextures := &mojang.SkinTexturesResponse{
|
||||||
Url: skin.Url,
|
Url: skin.Url,
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
if skin.IsSlim {
|
|
||||||
textures.Skin.Metadata = &mojang.SkinTexturesMetadata{
|
|
||||||
Model: "slim",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = cfg.CapesRepo.FindByUsername(username)
|
|
||||||
if err == nil {
|
|
||||||
var scheme = "http://"
|
|
||||||
if request.TLS != nil {
|
|
||||||
scheme = "https://"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if skin.IsSlim {
|
||||||
|
skinTextures.Metadata = &mojang.SkinTexturesMetadata{
|
||||||
|
Model: "slim",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
textures.Skin = skinTextures
|
||||||
|
}
|
||||||
|
|
||||||
|
if capeErr == nil {
|
||||||
textures.Cape = &mojang.CapeTexturesResponse{
|
textures.Cape = &mojang.CapeTexturesResponse{
|
||||||
Url: scheme + request.Host + "/cloaks/" + username,
|
Url: request.URL.Scheme + "://" + request.Host + "/cloaks/" + username,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -5,7 +5,6 @@ import (
|
|||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/golang/mock/gomock"
|
"github.com/golang/mock/gomock"
|
||||||
testify "github.com/stretchr/testify/assert"
|
testify "github.com/stretchr/testify/assert"
|
||||||
@ -15,152 +14,183 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestConfig_Textures(t *testing.T) {
|
func TestConfig_Textures(t *testing.T) {
|
||||||
assert := testify.New(t)
|
t.Run("Obtain textures for exists user with only default skin", func(t *testing.T) {
|
||||||
|
assert := testify.New(t)
|
||||||
|
|
||||||
ctrl := gomock.NewController(t)
|
ctrl := gomock.NewController(t)
|
||||||
defer ctrl.Finish()
|
defer ctrl.Finish()
|
||||||
|
|
||||||
config, mocks := setupMocks(ctrl)
|
config, mocks := setupMocks(ctrl)
|
||||||
|
|
||||||
mocks.Skins.EXPECT().FindByUsername("mock_user").Return(createSkinModel("mock_user", false), nil)
|
mocks.Log.EXPECT().IncCounter("textures.request", int64(1))
|
||||||
mocks.Capes.EXPECT().FindByUsername("mock_user").Return(nil, &db.CapeNotFoundError{"mock_user"})
|
|
||||||
mocks.Log.EXPECT().IncCounter("textures.request", int64(1))
|
|
||||||
|
|
||||||
req := httptest.NewRequest("GET", "http://skinsystem.ely.by/textures/mock_user", nil)
|
mocks.Skins.EXPECT().FindByUsername("mock_user").Return(createSkinModel("mock_user", false), nil)
|
||||||
w := httptest.NewRecorder()
|
mocks.Capes.EXPECT().FindByUsername("mock_user").Return(nil, &db.CapeNotFoundError{Who: "mock_user"})
|
||||||
|
|
||||||
config.CreateHandler().ServeHTTP(w, req)
|
req := httptest.NewRequest("GET", "http://chrly/textures/mock_user", nil)
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
|
||||||
resp := w.Result()
|
config.CreateHandler().ServeHTTP(w, req)
|
||||||
assert.Equal(200, resp.StatusCode)
|
|
||||||
assert.Equal("application/json", resp.Header.Get("Content-Type"))
|
|
||||||
response, _ := ioutil.ReadAll(resp.Body)
|
|
||||||
assert.JSONEq(`{
|
|
||||||
"SKIN": {
|
|
||||||
"url": "http://ely.by/minecraft/skins/skin.png",
|
|
||||||
"hash": "55d2a8848764f5ff04012cdb093458bd"
|
|
||||||
}
|
|
||||||
}`, string(response))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestConfig_Textures2(t *testing.T) {
|
resp := w.Result()
|
||||||
assert := testify.New(t)
|
assert.Equal(200, resp.StatusCode)
|
||||||
|
assert.Equal("application/json", resp.Header.Get("Content-Type"))
|
||||||
ctrl := gomock.NewController(t)
|
response, _ := ioutil.ReadAll(resp.Body)
|
||||||
defer ctrl.Finish()
|
assert.JSONEq(`{
|
||||||
|
"SKIN": {
|
||||||
config, mocks := setupMocks(ctrl)
|
"url": "http://chrly/skin.png"
|
||||||
|
|
||||||
mocks.Skins.EXPECT().FindByUsername("mock_user").Return(createSkinModel("mock_user", true), nil)
|
|
||||||
mocks.Capes.EXPECT().FindByUsername("mock_user").Return(nil, &db.CapeNotFoundError{"mock_user"})
|
|
||||||
mocks.Log.EXPECT().IncCounter("textures.request", int64(1))
|
|
||||||
|
|
||||||
req := httptest.NewRequest("GET", "http://skinsystem.ely.by/textures/mock_user", nil)
|
|
||||||
w := httptest.NewRecorder()
|
|
||||||
|
|
||||||
config.CreateHandler().ServeHTTP(w, req)
|
|
||||||
|
|
||||||
resp := w.Result()
|
|
||||||
assert.Equal(200, resp.StatusCode)
|
|
||||||
assert.Equal("application/json", resp.Header.Get("Content-Type"))
|
|
||||||
response, _ := ioutil.ReadAll(resp.Body)
|
|
||||||
assert.JSONEq(`{
|
|
||||||
"SKIN": {
|
|
||||||
"url": "http://ely.by/minecraft/skins/skin.png",
|
|
||||||
"hash": "55d2a8848764f5ff04012cdb093458bd",
|
|
||||||
"metadata": {
|
|
||||||
"model": "slim"
|
|
||||||
}
|
}
|
||||||
}
|
}`, string(response))
|
||||||
}`, string(response))
|
})
|
||||||
|
|
||||||
|
t.Run("Obtain textures for exists user with only slim skin", func(t *testing.T) {
|
||||||
|
assert := testify.New(t)
|
||||||
|
|
||||||
|
ctrl := gomock.NewController(t)
|
||||||
|
defer ctrl.Finish()
|
||||||
|
|
||||||
|
config, mocks := setupMocks(ctrl)
|
||||||
|
|
||||||
|
mocks.Log.EXPECT().IncCounter("textures.request", int64(1))
|
||||||
|
|
||||||
|
mocks.Skins.EXPECT().FindByUsername("mock_user").Return(createSkinModel("mock_user", true), nil)
|
||||||
|
mocks.Capes.EXPECT().FindByUsername("mock_user").Return(nil, &db.CapeNotFoundError{Who: "mock_user"})
|
||||||
|
|
||||||
|
req := httptest.NewRequest("GET", "http://chrly/textures/mock_user", nil)
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
|
||||||
|
config.CreateHandler().ServeHTTP(w, req)
|
||||||
|
|
||||||
|
resp := w.Result()
|
||||||
|
assert.Equal(200, resp.StatusCode)
|
||||||
|
assert.Equal("application/json", resp.Header.Get("Content-Type"))
|
||||||
|
response, _ := ioutil.ReadAll(resp.Body)
|
||||||
|
assert.JSONEq(`{
|
||||||
|
"SKIN": {
|
||||||
|
"url": "http://chrly/skin.png",
|
||||||
|
"metadata": {
|
||||||
|
"model": "slim"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}`, string(response))
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("Obtain textures for exists user with only cape", func(t *testing.T) {
|
||||||
|
assert := testify.New(t)
|
||||||
|
|
||||||
|
ctrl := gomock.NewController(t)
|
||||||
|
defer ctrl.Finish()
|
||||||
|
|
||||||
|
config, mocks := setupMocks(ctrl)
|
||||||
|
|
||||||
|
mocks.Log.EXPECT().IncCounter("textures.request", int64(1))
|
||||||
|
|
||||||
|
mocks.Skins.EXPECT().FindByUsername("mock_user").Return(nil, &db.SkinNotFoundError{Who: "mock_user"})
|
||||||
|
mocks.Capes.EXPECT().FindByUsername("mock_user").Return(&model.Cape{File: bytes.NewReader(createCape())}, nil)
|
||||||
|
|
||||||
|
req := httptest.NewRequest("GET", "http://chrly/textures/mock_user", nil)
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
|
||||||
|
config.CreateHandler().ServeHTTP(w, req)
|
||||||
|
|
||||||
|
resp := w.Result()
|
||||||
|
assert.Equal(200, resp.StatusCode)
|
||||||
|
assert.Equal("application/json", resp.Header.Get("Content-Type"))
|
||||||
|
response, _ := ioutil.ReadAll(resp.Body)
|
||||||
|
assert.JSONEq(`{
|
||||||
|
"CAPE": {
|
||||||
|
"url": "http://chrly/cloaks/mock_user"
|
||||||
|
}
|
||||||
|
}`, string(response))
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("Obtain textures for exists user with skin and cape", func(t *testing.T) {
|
||||||
|
assert := testify.New(t)
|
||||||
|
|
||||||
|
ctrl := gomock.NewController(t)
|
||||||
|
defer ctrl.Finish()
|
||||||
|
|
||||||
|
config, mocks := setupMocks(ctrl)
|
||||||
|
|
||||||
|
mocks.Log.EXPECT().IncCounter("textures.request", int64(1))
|
||||||
|
|
||||||
|
mocks.Skins.EXPECT().FindByUsername("mock_user").Return(createSkinModel("mock_user", false), nil)
|
||||||
|
mocks.Capes.EXPECT().FindByUsername("mock_user").Return(&model.Cape{File: bytes.NewReader(createCape())}, nil)
|
||||||
|
|
||||||
|
req := httptest.NewRequest("GET", "http://chrly/textures/mock_user", nil)
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
|
||||||
|
config.CreateHandler().ServeHTTP(w, req)
|
||||||
|
|
||||||
|
resp := w.Result()
|
||||||
|
assert.Equal(200, resp.StatusCode)
|
||||||
|
assert.Equal("application/json", resp.Header.Get("Content-Type"))
|
||||||
|
response, _ := ioutil.ReadAll(resp.Body)
|
||||||
|
assert.JSONEq(`{
|
||||||
|
"SKIN": {
|
||||||
|
"url": "http://chrly/skin.png"
|
||||||
|
},
|
||||||
|
"CAPE": {
|
||||||
|
"url": "http://chrly/cloaks/mock_user"
|
||||||
|
}
|
||||||
|
}`, string(response))
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("Obtain textures for not exists user that exists in Mojang", func(t *testing.T) {
|
||||||
|
assert := testify.New(t)
|
||||||
|
|
||||||
|
ctrl := gomock.NewController(t)
|
||||||
|
defer ctrl.Finish()
|
||||||
|
|
||||||
|
config, mocks := setupMocks(ctrl)
|
||||||
|
|
||||||
|
mocks.Log.EXPECT().IncCounter("textures.request", int64(1))
|
||||||
|
|
||||||
|
mocks.Skins.EXPECT().FindByUsername("mock_username").Return(nil, &db.SkinNotFoundError{})
|
||||||
|
mocks.Capes.EXPECT().FindByUsername("mock_username").Return(nil, &db.CapeNotFoundError{})
|
||||||
|
mocks.Queue.On("GetTexturesForUsername", "mock_username").Once().Return(createTexturesResponse(true, true))
|
||||||
|
|
||||||
|
req := httptest.NewRequest("GET", "http://chrly/textures/mock_username", nil)
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
|
||||||
|
config.CreateHandler().ServeHTTP(w, req)
|
||||||
|
|
||||||
|
resp := w.Result()
|
||||||
|
assert.Equal(200, resp.StatusCode)
|
||||||
|
assert.Equal("application/json", resp.Header.Get("Content-Type"))
|
||||||
|
response, _ := ioutil.ReadAll(resp.Body)
|
||||||
|
assert.JSONEq(`{
|
||||||
|
"SKIN": {
|
||||||
|
"url": "http://mojang/skin.png"
|
||||||
|
},
|
||||||
|
"CAPE": {
|
||||||
|
"url": "http://mojang/cape.png"
|
||||||
|
}
|
||||||
|
}`, string(response))
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("Obtain textures for not exists user that not exists in Mojang too", func(t *testing.T) {
|
||||||
|
assert := testify.New(t)
|
||||||
|
|
||||||
|
ctrl := gomock.NewController(t)
|
||||||
|
defer ctrl.Finish()
|
||||||
|
|
||||||
|
config, mocks := setupMocks(ctrl)
|
||||||
|
|
||||||
|
mocks.Log.EXPECT().IncCounter("textures.request", int64(1))
|
||||||
|
|
||||||
|
mocks.Skins.EXPECT().FindByUsername("mock_username").Return(nil, &db.SkinNotFoundError{})
|
||||||
|
mocks.Capes.EXPECT().FindByUsername("mock_username").Return(nil, &db.CapeNotFoundError{})
|
||||||
|
mocks.Queue.On("GetTexturesForUsername", "mock_username").Once().Return(nil)
|
||||||
|
|
||||||
|
req := httptest.NewRequest("GET", "http://chrly/textures/mock_username", nil)
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
|
||||||
|
config.CreateHandler().ServeHTTP(w, req)
|
||||||
|
|
||||||
|
resp := w.Result()
|
||||||
|
assert.Equal(204, resp.StatusCode) // TODO: this is not confirmed behavior
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestConfig_Textures3(t *testing.T) {
|
|
||||||
assert := testify.New(t)
|
|
||||||
|
|
||||||
ctrl := gomock.NewController(t)
|
|
||||||
defer ctrl.Finish()
|
|
||||||
|
|
||||||
config, mocks := setupMocks(ctrl)
|
|
||||||
|
|
||||||
mocks.Skins.EXPECT().FindByUsername("mock_user").Return(createSkinModel("mock_user", false), nil)
|
|
||||||
mocks.Capes.EXPECT().FindByUsername("mock_user").Return(&model.Cape{
|
|
||||||
File: bytes.NewReader(createCape()),
|
|
||||||
}, nil)
|
|
||||||
mocks.Log.EXPECT().IncCounter("textures.request", int64(1))
|
|
||||||
|
|
||||||
req := httptest.NewRequest("GET", "http://skinsystem.ely.by/textures/mock_user", nil)
|
|
||||||
w := httptest.NewRecorder()
|
|
||||||
|
|
||||||
config.CreateHandler().ServeHTTP(w, req)
|
|
||||||
|
|
||||||
resp := w.Result()
|
|
||||||
assert.Equal(200, resp.StatusCode)
|
|
||||||
assert.Equal("application/json", resp.Header.Get("Content-Type"))
|
|
||||||
response, _ := ioutil.ReadAll(resp.Body)
|
|
||||||
assert.JSONEq(`{
|
|
||||||
"SKIN": {
|
|
||||||
"url": "http://ely.by/minecraft/skins/skin.png",
|
|
||||||
"hash": "55d2a8848764f5ff04012cdb093458bd"
|
|
||||||
},
|
|
||||||
"CAPE": {
|
|
||||||
"url": "http://skinsystem.ely.by/cloaks/mock_user",
|
|
||||||
"hash": "424ff79dce9940af89c28ad80de8aaad"
|
|
||||||
}
|
|
||||||
}`, string(response))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestConfig_Textures4(t *testing.T) {
|
|
||||||
assert := testify.New(t)
|
|
||||||
|
|
||||||
ctrl := gomock.NewController(t)
|
|
||||||
defer ctrl.Finish()
|
|
||||||
|
|
||||||
config, mocks := setupMocks(ctrl)
|
|
||||||
|
|
||||||
mocks.Skins.EXPECT().FindByUsername("notch").Return(nil, &db.SkinNotFoundError{})
|
|
||||||
mocks.Capes.EXPECT().FindByUsername("notch").Return(nil, &db.CapeNotFoundError{})
|
|
||||||
mocks.Log.EXPECT().IncCounter("textures.request", int64(1))
|
|
||||||
timeNow = func() time.Time {
|
|
||||||
return time.Date(2017, time.August, 20, 0, 15, 54, 0, time.UTC)
|
|
||||||
}
|
|
||||||
|
|
||||||
req := httptest.NewRequest("GET", "http://skinsystem.ely.by/textures/notch", nil)
|
|
||||||
w := httptest.NewRecorder()
|
|
||||||
|
|
||||||
config.CreateHandler().ServeHTTP(w, req)
|
|
||||||
|
|
||||||
resp := w.Result()
|
|
||||||
assert.Equal(200, resp.StatusCode)
|
|
||||||
assert.Equal("application/json", resp.Header.Get("Content-Type"))
|
|
||||||
response, _ := ioutil.ReadAll(resp.Body)
|
|
||||||
assert.JSONEq(`{
|
|
||||||
"SKIN": {
|
|
||||||
"url": "http://skins.minecraft.net/MinecraftSkins/notch.png",
|
|
||||||
"hash": "5923cf3f7fa170a279e4d7a9483cfc52"
|
|
||||||
}
|
|
||||||
}`, string(response))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBuildNonElyTexturesHash(t *testing.T) {
|
|
||||||
assert := testify.New(t)
|
|
||||||
timeNow = func() time.Time {
|
|
||||||
return time.Date(2017, time.November, 30, 16, 15, 34, 0, time.UTC)
|
|
||||||
}
|
|
||||||
|
|
||||||
assert.Equal("686d788a5353cb636e8fdff727634d88", buildNonElyTexturesHash("username"), "Function should return fixed hash by username-time pair")
|
|
||||||
assert.Equal("fb876f761683a10accdb17d403cef64c", buildNonElyTexturesHash("another-username"), "Function should return fixed hash by username-time pair")
|
|
||||||
|
|
||||||
timeNow = func() time.Time {
|
|
||||||
return time.Date(2017, time.November, 30, 16, 20, 12, 0, time.UTC)
|
|
||||||
}
|
|
||||||
|
|
||||||
assert.Equal("686d788a5353cb636e8fdff727634d88", buildNonElyTexturesHash("username"), "Function should do not change it's value if hour the same")
|
|
||||||
assert.Equal("fb876f761683a10accdb17d403cef64c", buildNonElyTexturesHash("another-username"), "Function should return fixed hash by username-time pair")
|
|
||||||
|
|
||||||
timeNow = func() time.Time {
|
|
||||||
return time.Date(2017, time.November, 30, 17, 1, 3, 0, time.UTC)
|
|
||||||
}
|
|
||||||
|
|
||||||
assert.Equal("42277892fd24bc0ed86285b3bb8b8fad", buildNonElyTexturesHash("username"), "Function should change it's value if hour changed")
|
|
||||||
}
|
|
||||||
|
33
tests/mojang_textures_queue_mock.go
Normal file
33
tests/mojang_textures_queue_mock.go
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
package tests
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/elyby/chrly/api/mojang"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/mock"
|
||||||
|
)
|
||||||
|
|
||||||
|
type MojangTexturesQueueMock struct {
|
||||||
|
mock.Mock
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MojangTexturesQueueMock) GetTexturesForUsername(username string) chan *mojang.SignedTexturesResponse {
|
||||||
|
args := m.Called(username)
|
||||||
|
result := make(chan *mojang.SignedTexturesResponse)
|
||||||
|
arg := args.Get(0)
|
||||||
|
switch arg.(type) {
|
||||||
|
case *mojang.SignedTexturesResponse:
|
||||||
|
go func() {
|
||||||
|
result <- arg.(*mojang.SignedTexturesResponse)
|
||||||
|
}()
|
||||||
|
case chan *mojang.SignedTexturesResponse:
|
||||||
|
return arg.(chan *mojang.SignedTexturesResponse)
|
||||||
|
case nil:
|
||||||
|
go func() {
|
||||||
|
result <- nil
|
||||||
|
}()
|
||||||
|
default:
|
||||||
|
panic("unsupported return value")
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user