Merge pull request #8 from tribalwarshelp/feat/add-tests
feat: add tests - twdataloader
This commit is contained in:
commit
2875c56885
5
go.mod
5
go.mod
|
@ -7,7 +7,6 @@ require (
|
|||
github.com/Kichiyaki/gopgutil/v10 v10.0.0-20210521204542-cc672e361b3d
|
||||
github.com/go-pg/pg/v10 v10.10.2
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/vmihailenco/msgpack/v5 v5.3.1 // indirect
|
||||
go.opentelemetry.io/otel v0.20.0 // indirect
|
||||
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b // indirect
|
||||
github.com/stretchr/testify v1.7.0
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
|
||||
)
|
||||
|
|
17
go.sum
17
go.sum
|
@ -16,10 +16,7 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7
|
|||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
|
||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||
github.com/go-pg/pg/v10 v10.9.1 h1:kU4t84zWGGaU0Qsu49FbNtToUVrlSTkNOngW8aQmwvk=
|
||||
github.com/go-pg/pg/v10 v10.9.1/go.mod h1:rgmTPgHgl5EN2CNKKoMwC7QT62t8BqsdpEkUQuiZMQs=
|
||||
github.com/go-pg/pg/v10 v10.10.1 h1:82lLX4KGs2wOFOvVVIICoU0Si1fLu6Aitniu73HaDuM=
|
||||
github.com/go-pg/pg/v10 v10.10.1/go.mod h1:EmoJGYErc+stNN/1Jf+o4csXuprjxcRztBnn6cHe38E=
|
||||
github.com/go-pg/pg/v10 v10.10.2 h1:8G2DdKrB3/0nRIlpur0HySEWBJnHYUByiC0ko4XzE8w=
|
||||
github.com/go-pg/pg/v10 v10.10.2/go.mod h1:EmoJGYErc+stNN/1Jf+o4csXuprjxcRztBnn6cHe38E=
|
||||
github.com/go-pg/zerochecker v0.2.0 h1:pp7f72c3DobMWOb2ErtZsnrPaSvHd2W4o9//8HtF4mU=
|
||||
|
@ -41,7 +38,6 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw
|
|||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
||||
|
@ -84,17 +80,9 @@ github.com/vmihailenco/tagparser v0.1.2/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgq
|
|||
github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g=
|
||||
github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds=
|
||||
go.opentelemetry.io/otel v0.19.0/go.mod h1:j9bF567N9EfomkSidSfmMwIwIBuP37AMAIzVW85OxSg=
|
||||
go.opentelemetry.io/otel v0.20.0 h1:eaP0Fqu7SXHwvjiqDq83zImeehOHX8doTvU9AwXON8g=
|
||||
go.opentelemetry.io/otel v0.20.0/go.mod h1:Y3ugLH2oa81t5QO+Lty+zXf8zC9L26ax4Nzoxm/dooo=
|
||||
go.opentelemetry.io/otel/metric v0.19.0/go.mod h1:8f9fglJPRnXuskQmKpnad31lcLJ2VmNNqIsx/uIwBSc=
|
||||
go.opentelemetry.io/otel/metric v0.20.0 h1:4kzhXFP+btKm4jwxpjIqjs41A7MakRFUS86bqLHTIw8=
|
||||
go.opentelemetry.io/otel/metric v0.20.0/go.mod h1:598I5tYlH1vzBjn+BTuhzTCSb/9debfNp6R3s7Pr1eU=
|
||||
go.opentelemetry.io/otel/oteltest v0.19.0/go.mod h1:tI4yxwh8U21v7JD6R3BcA/2+RBoTKFexE/PJ/nSO7IA=
|
||||
go.opentelemetry.io/otel/oteltest v0.20.0 h1:HiITxCawalo5vQzdHfKeZurV8x7ljcqAgiWzF6Vaeaw=
|
||||
go.opentelemetry.io/otel/oteltest v0.20.0/go.mod h1:L7bgKf9ZB7qCwT9Up7i9/pn0PWIa9FqQ2IQ8LoxiGnw=
|
||||
go.opentelemetry.io/otel/trace v0.19.0/go.mod h1:4IXiNextNOpPnRlI4ryK69mn5iC84bjBWZQA5DXz/qg=
|
||||
go.opentelemetry.io/otel/trace v0.20.0 h1:1DL6EXUdcg95gukhuRRvLDO/4X5THh/5dIV52lqtnbw=
|
||||
go.opentelemetry.io/otel/trace v0.20.0/go.mod h1:6GjCW8zgDjwGHGa6GkyeB8+/5vjT16gUEi0Nf1iBdgw=
|
||||
golang.org/x/crypto v0.0.0-20180910181607-0e37d006457b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
|
@ -131,8 +119,6 @@ golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da h1:b3NXsE2LusjYGGjL5bxEVZZORm/YEFFrWFjR8eFrw/c=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7 h1:iGu644GcxtEcrInvDsQRCwJjtCIOlT2V7IRt6ah2Whw=
|
||||
golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
|
@ -175,8 +161,9 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
|||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
mellium.im/sasl v0.2.1 h1:nspKSRg7/SyO0cRGY71OkfHab8tf9kCts6a6oTDut0w=
|
||||
|
|
|
@ -26,6 +26,7 @@ const (
|
|||
EndpointKillAllTribeNotGzipped = "/map/kill_all_tribe.txt"
|
||||
EndpointConquer = "/map/conquer.txt.gz"
|
||||
EndpointConquerNotGzipped = "/map/conquer.txt"
|
||||
EndpointGetConquer = "/interface.php?func=get_conquer&since=%d"
|
||||
endpointInterface = "/interface.php"
|
||||
EndpointGetConquer = endpointInterface + "?func=get_conquer&since=%d"
|
||||
EndpointGetServers = "/backend/get_servers.php"
|
||||
)
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"encoding/csv"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"time"
|
||||
)
|
||||
|
||||
|
@ -22,3 +23,144 @@ func uncompressAndReadCsvLines(r io.Reader) ([][]string, error) {
|
|||
defer uncompressedStream.Close()
|
||||
return csv.NewReader(uncompressedStream).ReadAll()
|
||||
}
|
||||
|
||||
type handlers struct {
|
||||
getServers http.HandlerFunc
|
||||
killAll http.HandlerFunc
|
||||
killAtt http.HandlerFunc
|
||||
killDef http.HandlerFunc
|
||||
killSup http.HandlerFunc
|
||||
killAllTribe http.HandlerFunc
|
||||
killAttTribe http.HandlerFunc
|
||||
killDefTribe http.HandlerFunc
|
||||
player http.HandlerFunc
|
||||
tribe http.HandlerFunc
|
||||
village http.HandlerFunc
|
||||
conquer http.HandlerFunc
|
||||
getConquer http.HandlerFunc
|
||||
}
|
||||
|
||||
func (h *handlers) init() {
|
||||
noop := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
})
|
||||
if h.getServers == nil {
|
||||
h.getServers = noop
|
||||
}
|
||||
if h.killAll == nil {
|
||||
h.killAll = noop
|
||||
}
|
||||
if h.killAtt == nil {
|
||||
h.killAtt = noop
|
||||
}
|
||||
if h.killDef == nil {
|
||||
h.killDef = noop
|
||||
}
|
||||
if h.killSup == nil {
|
||||
h.killSup = noop
|
||||
}
|
||||
if h.killAllTribe == nil {
|
||||
h.killAllTribe = noop
|
||||
}
|
||||
if h.killAttTribe == nil {
|
||||
h.killAttTribe = noop
|
||||
}
|
||||
if h.killDefTribe == nil {
|
||||
h.killDefTribe = noop
|
||||
}
|
||||
if h.player == nil {
|
||||
h.player = noop
|
||||
}
|
||||
if h.tribe == nil {
|
||||
h.tribe = noop
|
||||
}
|
||||
if h.village == nil {
|
||||
h.village = noop
|
||||
}
|
||||
if h.conquer == nil {
|
||||
h.conquer = noop
|
||||
}
|
||||
if h.getConquer == nil {
|
||||
h.getConquer = noop
|
||||
}
|
||||
}
|
||||
|
||||
func prepareTestServer(h *handlers) *httptest.Server {
|
||||
if h == nil {
|
||||
h = &handlers{}
|
||||
}
|
||||
h.init()
|
||||
|
||||
return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != "GET" {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
switch r.URL.Path {
|
||||
case EndpointGetServers:
|
||||
h.getServers(w, r)
|
||||
return
|
||||
case EndpointKillAll:
|
||||
h.killAll(w, r)
|
||||
return
|
||||
case EndpointKillAtt:
|
||||
h.killAtt(w, r)
|
||||
return
|
||||
case EndpointKillDef:
|
||||
h.killDef(w, r)
|
||||
return
|
||||
case EndpointKillSup:
|
||||
h.killSup(w, r)
|
||||
return
|
||||
case EndpointKillAllTribe:
|
||||
h.killAllTribe(w, r)
|
||||
return
|
||||
case EndpointKillAttTribe:
|
||||
h.killAttTribe(w, r)
|
||||
return
|
||||
case EndpointKillDefTribe:
|
||||
h.killDefTribe(w, r)
|
||||
return
|
||||
case EndpointPlayer:
|
||||
h.player(w, r)
|
||||
return
|
||||
case EndpointTribe:
|
||||
h.tribe(w, r)
|
||||
return
|
||||
case EndpointVillage:
|
||||
h.village(w, r)
|
||||
return
|
||||
case EndpointConquer:
|
||||
h.conquer(w, r)
|
||||
return
|
||||
case endpointInterface:
|
||||
h.getConquer(w, r)
|
||||
return
|
||||
default:
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
||||
func createWriteStringHandler(resp string) http.HandlerFunc {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
_, err := w.Write([]byte(resp))
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func createWriteCompressedStringHandler(resp string) http.HandlerFunc {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
gzipWriter := gzip.NewWriter(w)
|
||||
defer gzipWriter.Close()
|
||||
_, err := gzipWriter.Write([]byte(resp))
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
}
|
||||
if err := gzipWriter.Flush(); err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -49,7 +49,7 @@ type parsedODLine struct {
|
|||
Score int
|
||||
}
|
||||
|
||||
func (d *ServerDataLoader) parseODLine(line []string) (*parsedODLine, error) {
|
||||
func (dl *ServerDataLoader) parseODLine(line []string) (*parsedODLine, error) {
|
||||
if len(line) != 3 {
|
||||
return nil, errors.New("invalid line format (should be rank,id,score)")
|
||||
}
|
||||
|
@ -70,19 +70,19 @@ func (d *ServerDataLoader) parseODLine(line []string) (*parsedODLine, error) {
|
|||
return p, nil
|
||||
}
|
||||
|
||||
func (d *ServerDataLoader) LoadOD(tribe bool) (map[int]*twmodel.OpponentsDefeated, error) {
|
||||
func (dl *ServerDataLoader) LoadOD(tribe bool) (map[int]*twmodel.OpponentsDefeated, error) {
|
||||
m := make(map[int]*twmodel.OpponentsDefeated)
|
||||
formattedURLs := []string{
|
||||
fmt.Sprintf("%s%s", d.baseURL, EndpointKillAll),
|
||||
fmt.Sprintf("%s%s", d.baseURL, EndpointKillAtt),
|
||||
fmt.Sprintf("%s%s", d.baseURL, EndpointKillDef),
|
||||
fmt.Sprintf("%s%s", d.baseURL, EndpointKillSup),
|
||||
fmt.Sprintf("%s%s", dl.baseURL, EndpointKillAll),
|
||||
fmt.Sprintf("%s%s", dl.baseURL, EndpointKillAtt),
|
||||
fmt.Sprintf("%s%s", dl.baseURL, EndpointKillDef),
|
||||
fmt.Sprintf("%s%s", dl.baseURL, EndpointKillSup),
|
||||
}
|
||||
if tribe {
|
||||
formattedURLs = []string{
|
||||
fmt.Sprintf("%s%s", d.baseURL, EndpointKillAllTribe),
|
||||
fmt.Sprintf("%s%s", d.baseURL, EndpointKillAttTribe),
|
||||
fmt.Sprintf("%s%s", d.baseURL, EndpointKillDefTribe),
|
||||
fmt.Sprintf("%s%s", dl.baseURL, EndpointKillAllTribe),
|
||||
fmt.Sprintf("%s%s", dl.baseURL, EndpointKillAttTribe),
|
||||
fmt.Sprintf("%s%s", dl.baseURL, EndpointKillDefTribe),
|
||||
"",
|
||||
}
|
||||
}
|
||||
|
@ -90,12 +90,12 @@ func (d *ServerDataLoader) LoadOD(tribe bool) (map[int]*twmodel.OpponentsDefeate
|
|||
if formattedURL == "" {
|
||||
continue
|
||||
}
|
||||
lines, err := d.getCSVData(formattedURL, true)
|
||||
lines, err := dl.getCSVData(formattedURL, true)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "couldn't load data, formattedURL %s", formattedURL)
|
||||
}
|
||||
for _, line := range lines {
|
||||
parsed, err := d.parseODLine(line)
|
||||
parsed, err := dl.parseODLine(line)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "couldn't parse the line, url %s, line %s", formattedURL, strings.Join(line, ","))
|
||||
}
|
||||
|
@ -121,7 +121,7 @@ func (d *ServerDataLoader) LoadOD(tribe bool) (map[int]*twmodel.OpponentsDefeate
|
|||
return m, nil
|
||||
}
|
||||
|
||||
func (d *ServerDataLoader) parsePlayerLine(line []string) (*twmodel.Player, error) {
|
||||
func (dl *ServerDataLoader) parsePlayerLine(line []string) (*twmodel.Player, error) {
|
||||
if len(line) != 6 {
|
||||
return nil, errors.New("invalid line format (should be id,name,tribeid,villages,points,rank)")
|
||||
}
|
||||
|
@ -159,16 +159,16 @@ func (d *ServerDataLoader) parsePlayerLine(line []string) (*twmodel.Player, erro
|
|||
return player, nil
|
||||
}
|
||||
|
||||
func (d *ServerDataLoader) LoadPlayers() ([]*twmodel.Player, error) {
|
||||
formattedURL := d.baseURL + EndpointPlayer
|
||||
lines, err := d.getCSVData(formattedURL, true)
|
||||
func (dl *ServerDataLoader) LoadPlayers() ([]*twmodel.Player, error) {
|
||||
formattedURL := dl.baseURL + EndpointPlayer
|
||||
lines, err := dl.getCSVData(formattedURL, true)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "couldn't load data, url %s", formattedURL)
|
||||
}
|
||||
|
||||
var players []*twmodel.Player
|
||||
for _, line := range lines {
|
||||
player, err := d.parsePlayerLine(line)
|
||||
player, err := dl.parsePlayerLine(line)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "couldn't parse the line, url %s, line %s", formattedURL, strings.Join(line, ","))
|
||||
}
|
||||
|
@ -178,7 +178,7 @@ func (d *ServerDataLoader) LoadPlayers() ([]*twmodel.Player, error) {
|
|||
return players, nil
|
||||
}
|
||||
|
||||
func (d *ServerDataLoader) parseTribeLine(line []string) (*twmodel.Tribe, error) {
|
||||
func (dl *ServerDataLoader) parseTribeLine(line []string) (*twmodel.Tribe, error) {
|
||||
if len(line) != 8 {
|
||||
return nil, errors.New("invalid line format (should be id,name,tag,members,villages,points,allpoints,rank)")
|
||||
}
|
||||
|
@ -224,15 +224,15 @@ func (d *ServerDataLoader) parseTribeLine(line []string) (*twmodel.Tribe, error)
|
|||
return tribe, nil
|
||||
}
|
||||
|
||||
func (d *ServerDataLoader) LoadTribes() ([]*twmodel.Tribe, error) {
|
||||
formattedURL := d.baseURL + EndpointTribe
|
||||
lines, err := d.getCSVData(formattedURL, true)
|
||||
func (dl *ServerDataLoader) LoadTribes() ([]*twmodel.Tribe, error) {
|
||||
formattedURL := dl.baseURL + EndpointTribe
|
||||
lines, err := dl.getCSVData(formattedURL, true)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "couldn't load data, url %s", formattedURL)
|
||||
}
|
||||
var tribes []*twmodel.Tribe
|
||||
for _, line := range lines {
|
||||
tribe, err := d.parseTribeLine(line)
|
||||
tribe, err := dl.parseTribeLine(line)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "couldn't parse the line, url %s, line %s", formattedURL, strings.Join(line, ","))
|
||||
}
|
||||
|
@ -241,7 +241,7 @@ func (d *ServerDataLoader) LoadTribes() ([]*twmodel.Tribe, error) {
|
|||
return tribes, nil
|
||||
}
|
||||
|
||||
func (d *ServerDataLoader) parseVillageLine(line []string) (*twmodel.Village, error) {
|
||||
func (dl *ServerDataLoader) parseVillageLine(line []string) (*twmodel.Village, error) {
|
||||
if len(line) != 7 {
|
||||
return nil, errors.New("invalid line format (should be id,name,x,y,playerID,points,bonus)")
|
||||
}
|
||||
|
@ -278,15 +278,15 @@ func (d *ServerDataLoader) parseVillageLine(line []string) (*twmodel.Village, er
|
|||
return village, nil
|
||||
}
|
||||
|
||||
func (d *ServerDataLoader) LoadVillages() ([]*twmodel.Village, error) {
|
||||
formattedURL := d.baseURL + EndpointVillage
|
||||
lines, err := d.getCSVData(formattedURL, true)
|
||||
func (dl *ServerDataLoader) LoadVillages() ([]*twmodel.Village, error) {
|
||||
formattedURL := dl.baseURL + EndpointVillage
|
||||
lines, err := dl.getCSVData(formattedURL, true)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "couldn't load data, formattedURL %s", formattedURL)
|
||||
}
|
||||
var villages []*twmodel.Village
|
||||
for _, line := range lines {
|
||||
village, err := d.parseVillageLine(line)
|
||||
village, err := dl.parseVillageLine(line)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "couldn't parse the line, formattedURL %s, line %s", formattedURL, strings.Join(line, ","))
|
||||
}
|
||||
|
@ -295,7 +295,7 @@ func (d *ServerDataLoader) LoadVillages() ([]*twmodel.Village, error) {
|
|||
return villages, nil
|
||||
}
|
||||
|
||||
func (d *ServerDataLoader) parseEnnoblementLine(line []string) (*twmodel.Ennoblement, error) {
|
||||
func (dl *ServerDataLoader) parseEnnoblementLine(line []string) (*twmodel.Ennoblement, error) {
|
||||
if len(line) != 4 {
|
||||
return nil, errors.New("invalid line format (should be village_id,timestamp,new_owner_id,old_owner_id)")
|
||||
}
|
||||
|
@ -326,25 +326,25 @@ type LoadEnnoblementsConfig struct {
|
|||
EnnobledAtGT time.Time
|
||||
}
|
||||
|
||||
func (d *ServerDataLoader) LoadEnnoblements(cfg *LoadEnnoblementsConfig) ([]*twmodel.Ennoblement, error) {
|
||||
func (dl *ServerDataLoader) LoadEnnoblements(cfg *LoadEnnoblementsConfig) ([]*twmodel.Ennoblement, error) {
|
||||
if cfg == nil {
|
||||
cfg = &LoadEnnoblementsConfig{}
|
||||
}
|
||||
yesterdaysDate := time.Now().Add(-23 * time.Hour)
|
||||
formattedURL := d.baseURL + EndpointConquer
|
||||
formattedURL := dl.baseURL + EndpointConquer
|
||||
compressed := true
|
||||
if cfg.EnnobledAtGT.After(yesterdaysDate) || cfg.EnnobledAtGT.Equal(yesterdaysDate) {
|
||||
formattedURL = d.baseURL + fmt.Sprintf(EndpointGetConquer, cfg.EnnobledAtGT.Unix())
|
||||
formattedURL = dl.baseURL + fmt.Sprintf(EndpointGetConquer, cfg.EnnobledAtGT.Unix())
|
||||
compressed = false
|
||||
}
|
||||
lines, err := d.getCSVData(formattedURL, compressed)
|
||||
lines, err := dl.getCSVData(formattedURL, compressed)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "couldn't load data, formattedURL %s", formattedURL)
|
||||
}
|
||||
|
||||
var ennoblements []*twmodel.Ennoblement
|
||||
for _, line := range lines {
|
||||
ennoblement, err := d.parseEnnoblementLine(line)
|
||||
ennoblement, err := dl.parseEnnoblementLine(line)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "couldn't parse the line, formattedURL %s, line %s", formattedURL, strings.Join(line, ","))
|
||||
}
|
||||
|
@ -355,38 +355,38 @@ func (d *ServerDataLoader) LoadEnnoblements(cfg *LoadEnnoblementsConfig) ([]*twm
|
|||
return ennoblements, nil
|
||||
}
|
||||
|
||||
func (d *ServerDataLoader) GetConfig() (*twmodel.ServerConfig, error) {
|
||||
formattedURL := d.baseURL + EndpointConfig
|
||||
func (dl *ServerDataLoader) GetConfig() (*twmodel.ServerConfig, error) {
|
||||
formattedURL := dl.baseURL + EndpointConfig
|
||||
cfg := &twmodel.ServerConfig{}
|
||||
err := d.getXML(formattedURL, cfg)
|
||||
err := dl.getXML(formattedURL, cfg)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "getConfig")
|
||||
}
|
||||
return cfg, nil
|
||||
}
|
||||
|
||||
func (d *ServerDataLoader) GetBuildingConfig() (*twmodel.BuildingConfig, error) {
|
||||
formattedURL := d.baseURL + EndpointBuildingConfig
|
||||
func (dl *ServerDataLoader) GetBuildingConfig() (*twmodel.BuildingConfig, error) {
|
||||
formattedURL := dl.baseURL + EndpointBuildingConfig
|
||||
cfg := &twmodel.BuildingConfig{}
|
||||
err := d.getXML(formattedURL, cfg)
|
||||
err := dl.getXML(formattedURL, cfg)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "getBuildingConfig")
|
||||
}
|
||||
return cfg, nil
|
||||
}
|
||||
|
||||
func (d *ServerDataLoader) GetUnitConfig() (*twmodel.UnitConfig, error) {
|
||||
formattedURL := d.baseURL + EndpointUnitConfig
|
||||
func (dl *ServerDataLoader) GetUnitConfig() (*twmodel.UnitConfig, error) {
|
||||
formattedURL := dl.baseURL + EndpointUnitConfig
|
||||
cfg := &twmodel.UnitConfig{}
|
||||
err := d.getXML(formattedURL, cfg)
|
||||
err := dl.getXML(formattedURL, cfg)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "getUnitConfig")
|
||||
}
|
||||
return cfg, nil
|
||||
}
|
||||
|
||||
func (d *ServerDataLoader) getCSVData(url string, compressed bool) ([][]string, error) {
|
||||
resp, err := d.client.Get(url)
|
||||
func (dl *ServerDataLoader) getCSVData(url string, compressed bool) ([][]string, error) {
|
||||
resp, err := dl.client.Get(url)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -397,8 +397,8 @@ func (d *ServerDataLoader) getCSVData(url string, compressed bool) ([][]string,
|
|||
return uncompressAndReadCsvLines(resp.Body)
|
||||
}
|
||||
|
||||
func (d *ServerDataLoader) getXML(url string, decode interface{}) error {
|
||||
resp, err := d.client.Get(url)
|
||||
func (dl *ServerDataLoader) getXML(url string, decode interface{}) error {
|
||||
resp, err := dl.client.Get(url)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -0,0 +1,626 @@
|
|||
package twdataloader
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/tribalwarshelp/shared/tw/twmodel"
|
||||
)
|
||||
|
||||
func TestLoadOD(t *testing.T) {
|
||||
type scenario struct {
|
||||
respKillAll string
|
||||
respKillAtt string
|
||||
respKillDef string
|
||||
respKillSup string
|
||||
respKillAllTribe string
|
||||
respKillAttTribe string
|
||||
respKillDefTribe string
|
||||
tribe bool
|
||||
expectedResult map[int]*twmodel.OpponentsDefeated
|
||||
expectedErrMsg string
|
||||
}
|
||||
|
||||
scenarios := []scenario{
|
||||
{
|
||||
respKillAll: "1,1",
|
||||
expectedErrMsg: "invalid line format (should be rank,id,score)",
|
||||
},
|
||||
{
|
||||
respKillAllTribe: "1,1",
|
||||
expectedErrMsg: "invalid line format (should be rank,id,score)",
|
||||
tribe: true,
|
||||
},
|
||||
{
|
||||
respKillAll: "1,1,1",
|
||||
respKillAtt: "1,1,1",
|
||||
respKillDef: "1,1,1",
|
||||
respKillSup: "1,1",
|
||||
expectedErrMsg: "invalid line format (should be rank,id,score)",
|
||||
},
|
||||
{
|
||||
respKillAllTribe: "1,1,1",
|
||||
respKillAttTribe: "1,1,1",
|
||||
respKillDefTribe: "1,1",
|
||||
expectedErrMsg: "invalid line format (should be rank,id,score)",
|
||||
tribe: true,
|
||||
},
|
||||
{
|
||||
respKillAll: "1,1,asd",
|
||||
expectedErrMsg: "parsedODLine.Score: strconv.Atoi: parsing \"asd\"",
|
||||
},
|
||||
{
|
||||
respKillAll: "1,asd,1",
|
||||
expectedErrMsg: "parsedODLine.ID: strconv.Atoi: parsing \"asd\":",
|
||||
},
|
||||
{
|
||||
respKillAll: "asd,1,1",
|
||||
expectedErrMsg: "parsedODLine.Rank: strconv.Atoi: parsing \"asd\":",
|
||||
},
|
||||
{
|
||||
respKillAllTribe: "1,1,asd",
|
||||
expectedErrMsg: "parsedODLine.Score: strconv.Atoi: parsing \"asd\"",
|
||||
tribe: true,
|
||||
},
|
||||
{
|
||||
respKillAllTribe: "1,asd,1",
|
||||
expectedErrMsg: "parsedODLine.ID: strconv.Atoi: parsing \"asd\":",
|
||||
tribe: true,
|
||||
},
|
||||
{
|
||||
respKillAllTribe: "asd,1,1",
|
||||
expectedErrMsg: "parsedODLine.Rank: strconv.Atoi: parsing \"asd\":",
|
||||
tribe: true,
|
||||
},
|
||||
{
|
||||
respKillAll: "1,1,1\n4,2,4\n2,3,2",
|
||||
respKillAtt: "2,1,2\n3,2,3\n1,3,1",
|
||||
respKillDef: "3,1,3\n2,2,2\n4,3,4",
|
||||
respKillSup: "4,1,4\n1,2,1\n3,3,3",
|
||||
expectedResult: map[int]*twmodel.OpponentsDefeated{
|
||||
1: {
|
||||
RankAtt: 2,
|
||||
ScoreAtt: 2,
|
||||
RankDef: 3,
|
||||
ScoreDef: 3,
|
||||
RankSup: 4,
|
||||
ScoreSup: 4,
|
||||
RankTotal: 1,
|
||||
ScoreTotal: 1,
|
||||
},
|
||||
2: {
|
||||
RankAtt: 3,
|
||||
ScoreAtt: 3,
|
||||
RankDef: 2,
|
||||
ScoreDef: 2,
|
||||
RankSup: 1,
|
||||
ScoreSup: 1,
|
||||
ScoreTotal: 4,
|
||||
RankTotal: 4,
|
||||
},
|
||||
3: {
|
||||
RankAtt: 1,
|
||||
ScoreAtt: 1,
|
||||
RankDef: 4,
|
||||
ScoreDef: 4,
|
||||
RankSup: 3,
|
||||
ScoreSup: 3,
|
||||
ScoreTotal: 2,
|
||||
RankTotal: 2,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
respKillAllTribe: "1,1,1\n2,2,2\n3,3,3",
|
||||
respKillAttTribe: "1,1,1\n2,2,2\n3,3,3",
|
||||
respKillDefTribe: "1,1,1\n2,2,2\n3,3,3",
|
||||
expectedResult: map[int]*twmodel.OpponentsDefeated{
|
||||
1: {
|
||||
RankAtt: 1,
|
||||
ScoreAtt: 1,
|
||||
RankDef: 1,
|
||||
ScoreDef: 1,
|
||||
ScoreTotal: 1,
|
||||
RankTotal: 1,
|
||||
},
|
||||
2: {
|
||||
RankAtt: 2,
|
||||
ScoreAtt: 2,
|
||||
RankDef: 2,
|
||||
ScoreDef: 2,
|
||||
ScoreTotal: 2,
|
||||
RankTotal: 2,
|
||||
},
|
||||
3: {
|
||||
RankAtt: 3,
|
||||
ScoreAtt: 3,
|
||||
RankDef: 3,
|
||||
ScoreDef: 3,
|
||||
ScoreTotal: 3,
|
||||
RankTotal: 3,
|
||||
},
|
||||
},
|
||||
tribe: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, scenario := range scenarios {
|
||||
ts := prepareTestServer(&handlers{
|
||||
killAll: createWriteCompressedStringHandler(scenario.respKillAll),
|
||||
killAtt: createWriteCompressedStringHandler(scenario.respKillAtt),
|
||||
killDef: createWriteCompressedStringHandler(scenario.respKillDef),
|
||||
killSup: createWriteCompressedStringHandler(scenario.respKillSup),
|
||||
killAllTribe: createWriteCompressedStringHandler(scenario.respKillAllTribe),
|
||||
killAttTribe: createWriteCompressedStringHandler(scenario.respKillAttTribe),
|
||||
killDefTribe: createWriteCompressedStringHandler(scenario.respKillDefTribe),
|
||||
})
|
||||
|
||||
dl := NewServerDataLoader(&ServerDataLoaderConfig{
|
||||
BaseURL: ts.URL,
|
||||
Client: ts.Client(),
|
||||
})
|
||||
|
||||
res, err := dl.LoadOD(scenario.tribe)
|
||||
if scenario.expectedErrMsg != "" {
|
||||
assert.NotNil(t, err)
|
||||
assert.Contains(t, err.Error(), scenario.expectedErrMsg)
|
||||
} else {
|
||||
assert.Nil(t, err)
|
||||
}
|
||||
|
||||
if scenario.expectedResult != nil {
|
||||
assert.Len(t, res, len(scenario.expectedResult))
|
||||
for id, singleResult := range res {
|
||||
expected, ok := scenario.expectedResult[id]
|
||||
assert.True(t, ok)
|
||||
assert.NotNil(t, expected)
|
||||
assert.EqualValues(t, expected, singleResult)
|
||||
}
|
||||
}
|
||||
|
||||
ts.Close()
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadPlayers(t *testing.T) {
|
||||
type scenario struct {
|
||||
resp string
|
||||
expectedResult []*twmodel.Player
|
||||
expectedErrMsg string
|
||||
}
|
||||
|
||||
exists := true
|
||||
scenarios := []scenario{
|
||||
{
|
||||
resp: "1,1,1,1",
|
||||
expectedErrMsg: "invalid line format (should be id,name,tribeid,villages,points,rank)",
|
||||
},
|
||||
{
|
||||
resp: "1,name,1,500,500",
|
||||
expectedErrMsg: "invalid line format (should be id,name,tribeid,villages,points,rank)",
|
||||
},
|
||||
{
|
||||
resp: "asd,name,1,500,500,500",
|
||||
expectedErrMsg: "player.ID: strconv.Atoi: parsing \"asd\"",
|
||||
},
|
||||
{
|
||||
resp: "1,name,asd,500,500,500",
|
||||
expectedErrMsg: "player.TribeID: strconv.Atoi: parsing \"asd\"",
|
||||
},
|
||||
{
|
||||
resp: "1,name,123,asd,500,500",
|
||||
expectedErrMsg: "player.TotalVillages: strconv.Atoi: parsing \"asd\"",
|
||||
},
|
||||
{
|
||||
resp: "1,name,123,500,asd,500",
|
||||
expectedErrMsg: "player.Points: strconv.Atoi: parsing \"asd\"",
|
||||
},
|
||||
{
|
||||
resp: "1,name,123,500,123,asd",
|
||||
expectedErrMsg: "player.Rank: strconv.Atoi: parsing \"asd\"",
|
||||
},
|
||||
{
|
||||
resp: "1,name,123,500,500,asd",
|
||||
expectedErrMsg: "player.Rank: strconv.Atoi: parsing \"asd\"",
|
||||
},
|
||||
{
|
||||
resp: "1,name,123,124,125,126\n2,name2,256,257,258,259",
|
||||
expectedResult: []*twmodel.Player{
|
||||
{
|
||||
ID: 1,
|
||||
Name: "name",
|
||||
TribeID: 123,
|
||||
TotalVillages: 124,
|
||||
Points: 125,
|
||||
Rank: 126,
|
||||
Exists: &exists,
|
||||
},
|
||||
{
|
||||
ID: 2,
|
||||
Name: "name2",
|
||||
TribeID: 256,
|
||||
TotalVillages: 257,
|
||||
Points: 258,
|
||||
Rank: 259,
|
||||
Exists: &exists,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, scenario := range scenarios {
|
||||
ts := prepareTestServer(&handlers{
|
||||
player: createWriteCompressedStringHandler(scenario.resp),
|
||||
})
|
||||
|
||||
dl := NewServerDataLoader(&ServerDataLoaderConfig{
|
||||
BaseURL: ts.URL,
|
||||
Client: ts.Client(),
|
||||
})
|
||||
|
||||
res, err := dl.LoadPlayers()
|
||||
if scenario.expectedErrMsg != "" {
|
||||
assert.NotNil(t, err)
|
||||
assert.Contains(t, err.Error(), scenario.expectedErrMsg)
|
||||
} else {
|
||||
assert.Nil(t, err)
|
||||
}
|
||||
|
||||
if scenario.expectedResult != nil {
|
||||
assert.Len(t, res, len(scenario.expectedResult))
|
||||
for _, singleResult := range res {
|
||||
found := false
|
||||
var player *twmodel.Player
|
||||
for _, expected := range scenario.expectedResult {
|
||||
if expected.ID == singleResult.ID {
|
||||
found = true
|
||||
player = expected
|
||||
break
|
||||
}
|
||||
}
|
||||
assert.True(t, found)
|
||||
assert.NotNil(t, player)
|
||||
assert.EqualValues(t, player, singleResult)
|
||||
}
|
||||
}
|
||||
|
||||
ts.Close()
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadTribes(t *testing.T) {
|
||||
type scenario struct {
|
||||
resp string
|
||||
expectedResult []*twmodel.Tribe
|
||||
expectedErrMsg string
|
||||
}
|
||||
|
||||
ex := true
|
||||
scenarios := []scenario{
|
||||
{
|
||||
resp: "1,1,1,1",
|
||||
expectedErrMsg: "invalid line format (should be id,name,tag,members,villages,points,allpoints,rank)",
|
||||
},
|
||||
{
|
||||
resp: "1,name,1,500,500",
|
||||
expectedErrMsg: "invalid line format (should be id,name,tag,members,villages,points,allpoints,rank)",
|
||||
},
|
||||
{
|
||||
resp: "asd,name,tag,500,500,500,500,500",
|
||||
expectedErrMsg: "tribe.ID: strconv.Atoi: parsing \"asd\"",
|
||||
},
|
||||
{
|
||||
resp: "123,name,tag,asd,500,500,500,500",
|
||||
expectedErrMsg: "tribe.TotalMembers: strconv.Atoi: parsing \"asd\"",
|
||||
},
|
||||
{
|
||||
resp: "123,name,tag,500,asd,500,500,500",
|
||||
expectedErrMsg: "tribe.TotalVillages: strconv.Atoi: parsing \"asd\"",
|
||||
},
|
||||
{
|
||||
resp: "123,name,tag,500,500,asd,500,500",
|
||||
expectedErrMsg: "tribe.Points: strconv.Atoi: parsing \"asd\"",
|
||||
},
|
||||
{
|
||||
resp: "123,name,tag,500,500,500,asd,500",
|
||||
expectedErrMsg: "tribe.AllPoints: strconv.Atoi: parsing \"asd\"",
|
||||
},
|
||||
{
|
||||
resp: "123,name,tag,500,500,500,500,asd",
|
||||
expectedErrMsg: "tribe.Rank: strconv.Atoi: parsing \"asd\"",
|
||||
},
|
||||
{
|
||||
resp: "123,name,tag,500,501,502,503,504\n1234,name2,tag2,5000,5001,5002,5003,5004",
|
||||
expectedResult: []*twmodel.Tribe{
|
||||
{
|
||||
ID: 123,
|
||||
Name: "name",
|
||||
Tag: "tag",
|
||||
TotalMembers: 500,
|
||||
TotalVillages: 501,
|
||||
Points: 502,
|
||||
AllPoints: 503,
|
||||
Rank: 504,
|
||||
Exists: &ex,
|
||||
},
|
||||
{
|
||||
ID: 1234,
|
||||
Name: "name2",
|
||||
Tag: "tag2",
|
||||
TotalMembers: 5000,
|
||||
TotalVillages: 5001,
|
||||
Points: 5002,
|
||||
AllPoints: 5003,
|
||||
Rank: 5004,
|
||||
Exists: &ex,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, scenario := range scenarios {
|
||||
ts := prepareTestServer(&handlers{
|
||||
tribe: createWriteCompressedStringHandler(scenario.resp),
|
||||
})
|
||||
|
||||
dl := NewServerDataLoader(&ServerDataLoaderConfig{
|
||||
BaseURL: ts.URL,
|
||||
Client: ts.Client(),
|
||||
})
|
||||
|
||||
res, err := dl.LoadTribes()
|
||||
if scenario.expectedErrMsg != "" {
|
||||
assert.NotNil(t, err)
|
||||
assert.Contains(t, err.Error(), scenario.expectedErrMsg)
|
||||
} else {
|
||||
assert.Nil(t, err)
|
||||
}
|
||||
|
||||
if scenario.expectedResult != nil {
|
||||
assert.Len(t, res, len(scenario.expectedResult))
|
||||
for _, singleResult := range res {
|
||||
found := false
|
||||
var tribe *twmodel.Tribe
|
||||
for _, expected := range scenario.expectedResult {
|
||||
if expected.ID == singleResult.ID {
|
||||
found = true
|
||||
tribe = expected
|
||||
break
|
||||
}
|
||||
}
|
||||
assert.True(t, found)
|
||||
assert.NotNil(t, tribe)
|
||||
assert.EqualValues(t, tribe, singleResult)
|
||||
}
|
||||
}
|
||||
|
||||
ts.Close()
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadVillages(t *testing.T) {
|
||||
type scenario struct {
|
||||
resp string
|
||||
expectedResult []*twmodel.Village
|
||||
expectedErrMsg string
|
||||
}
|
||||
|
||||
scenarios := []scenario{
|
||||
{
|
||||
resp: "1,1,1,1",
|
||||
expectedErrMsg: "invalid line format (should be id,name,x,y,playerID,points,bonus)",
|
||||
},
|
||||
{
|
||||
resp: "1,name,1,500,500",
|
||||
expectedErrMsg: "invalid line format (should be id,name,x,y,playerID,points,bonus)",
|
||||
},
|
||||
{
|
||||
resp: "asd,name,500,500,500,500,0",
|
||||
expectedErrMsg: "village.ID: strconv.Atoi: parsing \"asd\"",
|
||||
},
|
||||
{
|
||||
resp: "123,name,asd,500,500,500,0",
|
||||
expectedErrMsg: "village.X: strconv.Atoi: parsing \"asd\"",
|
||||
},
|
||||
{
|
||||
resp: "123,name,500,asd,500,500,0",
|
||||
expectedErrMsg: "village.Y: strconv.Atoi: parsing \"asd\"",
|
||||
},
|
||||
{
|
||||
resp: "123,name,500,500,asd,500,0",
|
||||
expectedErrMsg: "village.PlayerID: strconv.Atoi: parsing \"asd\"",
|
||||
},
|
||||
{
|
||||
resp: "123,name,500,500,500,asd,0",
|
||||
expectedErrMsg: "village.Points: strconv.Atoi: parsing \"asd\"",
|
||||
},
|
||||
{
|
||||
resp: "123,name,500,500,500,500,asd",
|
||||
expectedErrMsg: "village.Bonus: strconv.Atoi: parsing \"asd\"",
|
||||
},
|
||||
{
|
||||
resp: "123,village 1,500,501,502,503,504\n124,village 2,100,101,102,103,104",
|
||||
expectedResult: []*twmodel.Village{
|
||||
{
|
||||
ID: 123,
|
||||
Name: "village 1",
|
||||
X: 500,
|
||||
Y: 501,
|
||||
PlayerID: 502,
|
||||
Points: 503,
|
||||
Bonus: 504,
|
||||
},
|
||||
{
|
||||
ID: 124,
|
||||
Name: "village 2",
|
||||
X: 100,
|
||||
Y: 101,
|
||||
PlayerID: 102,
|
||||
Points: 103,
|
||||
Bonus: 104,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, scenario := range scenarios {
|
||||
ts := prepareTestServer(&handlers{
|
||||
village: createWriteCompressedStringHandler(scenario.resp),
|
||||
})
|
||||
|
||||
dl := NewServerDataLoader(&ServerDataLoaderConfig{
|
||||
BaseURL: ts.URL,
|
||||
Client: ts.Client(),
|
||||
})
|
||||
|
||||
res, err := dl.LoadVillages()
|
||||
if scenario.expectedErrMsg != "" {
|
||||
assert.NotNil(t, err)
|
||||
assert.Contains(t, err.Error(), scenario.expectedErrMsg)
|
||||
} else {
|
||||
assert.Nil(t, err)
|
||||
}
|
||||
|
||||
if scenario.expectedResult != nil {
|
||||
assert.Len(t, res, len(scenario.expectedResult))
|
||||
for _, singleResult := range res {
|
||||
found := false
|
||||
var village *twmodel.Village
|
||||
for _, expected := range scenario.expectedResult {
|
||||
if expected.ID == singleResult.ID {
|
||||
found = true
|
||||
village = expected
|
||||
break
|
||||
}
|
||||
}
|
||||
assert.True(t, found)
|
||||
assert.NotNil(t, village)
|
||||
assert.EqualValues(t, village, singleResult)
|
||||
}
|
||||
}
|
||||
|
||||
ts.Close()
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadEnnoblements(t *testing.T) {
|
||||
type scenario struct {
|
||||
respConquer string
|
||||
respGetConquer string
|
||||
cfg *LoadEnnoblementsConfig
|
||||
expectedResult []*twmodel.Ennoblement
|
||||
expectedErrMsg string
|
||||
}
|
||||
|
||||
nowMinus5h := time.Now().Add(-5 * time.Hour).Unix()
|
||||
nowMinus6h := time.Now().Add(-6 * time.Hour).Unix()
|
||||
scenarios := []scenario{
|
||||
{
|
||||
respConquer: "1,1,1",
|
||||
expectedErrMsg: "invalid line format (should be village_id,timestamp,new_owner_id,old_owner_id)",
|
||||
},
|
||||
{
|
||||
respConquer: "1,name,1,500,500",
|
||||
expectedErrMsg: "invalid line format (should be village_id,timestamp,new_owner_id,old_owner_id)",
|
||||
},
|
||||
{
|
||||
respConquer: "asd,123,123,123",
|
||||
expectedErrMsg: "ennoblement.VillageID: strconv.Atoi: parsing \"asd\"",
|
||||
},
|
||||
{
|
||||
respConquer: "123,asd,123,123",
|
||||
expectedErrMsg: "timestamp: strconv.Atoi: parsing \"asd\"",
|
||||
},
|
||||
{
|
||||
respConquer: "123,123,asd,123",
|
||||
expectedErrMsg: "ennoblement.NewOwnerID: strconv.Atoi: parsing \"asd\"",
|
||||
},
|
||||
{
|
||||
respConquer: "123,123,123,asd",
|
||||
expectedErrMsg: "ennoblement.OldOwnerID: strconv.Atoi: parsing \"asd\"",
|
||||
},
|
||||
{
|
||||
respConquer: "123,124,125,126\n127,128,129,130",
|
||||
expectedResult: []*twmodel.Ennoblement{
|
||||
{
|
||||
VillageID: 123,
|
||||
EnnobledAt: time.Unix(124, 0),
|
||||
NewOwnerID: 125,
|
||||
OldOwnerID: 126,
|
||||
},
|
||||
{
|
||||
VillageID: 127,
|
||||
EnnobledAt: time.Unix(128, 0),
|
||||
NewOwnerID: 129,
|
||||
OldOwnerID: 130,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
respGetConquer: "123,124,125,126\n127,128,129,130",
|
||||
cfg: &LoadEnnoblementsConfig{
|
||||
EnnobledAtGT: time.Now().Add(5 * time.Hour),
|
||||
},
|
||||
expectedResult: []*twmodel.Ennoblement{},
|
||||
},
|
||||
{
|
||||
respConquer: fmt.Sprintf("123,%d,125,126\n127,%d,129,130", nowMinus5h, nowMinus6h),
|
||||
expectedResult: []*twmodel.Ennoblement{
|
||||
{
|
||||
VillageID: 123,
|
||||
EnnobledAt: time.Unix(nowMinus5h, 0),
|
||||
NewOwnerID: 125,
|
||||
OldOwnerID: 126,
|
||||
},
|
||||
{
|
||||
VillageID: 127,
|
||||
EnnobledAt: time.Unix(nowMinus6h, 0),
|
||||
NewOwnerID: 129,
|
||||
OldOwnerID: 130,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, scenario := range scenarios {
|
||||
ts := prepareTestServer(&handlers{
|
||||
conquer: createWriteCompressedStringHandler(scenario.respConquer),
|
||||
getConquer: createWriteStringHandler(scenario.respGetConquer),
|
||||
})
|
||||
|
||||
dl := NewServerDataLoader(&ServerDataLoaderConfig{
|
||||
BaseURL: ts.URL,
|
||||
Client: ts.Client(),
|
||||
})
|
||||
|
||||
res, err := dl.LoadEnnoblements(scenario.cfg)
|
||||
if scenario.expectedErrMsg != "" {
|
||||
assert.NotNil(t, err)
|
||||
assert.Contains(t, err.Error(), scenario.expectedErrMsg)
|
||||
} else {
|
||||
assert.Nil(t, err)
|
||||
}
|
||||
|
||||
if scenario.expectedResult != nil {
|
||||
assert.Len(t, res, len(scenario.expectedResult))
|
||||
for _, singleResult := range res {
|
||||
found := false
|
||||
var ennoblement *twmodel.Ennoblement
|
||||
for _, expected := range scenario.expectedResult {
|
||||
if expected.VillageID == singleResult.VillageID {
|
||||
found = true
|
||||
ennoblement = expected
|
||||
break
|
||||
}
|
||||
}
|
||||
assert.True(t, found)
|
||||
assert.NotNil(t, ennoblement)
|
||||
assert.EqualValues(t, ennoblement, singleResult)
|
||||
}
|
||||
}
|
||||
|
||||
ts.Close()
|
||||
}
|
||||
}
|
|
@ -1,7 +1,6 @@
|
|||
package twdataloader
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
phpserialize "github.com/Kichiyaki/go-php-serialize"
|
||||
"github.com/pkg/errors"
|
||||
"io/ioutil"
|
||||
|
@ -40,8 +39,8 @@ func NewVersionDataLoader(cfg *VersionDataLoaderConfig) *VersionDataLoader {
|
|||
}
|
||||
}
|
||||
|
||||
func (d *VersionDataLoader) LoadServers() ([]*Server, error) {
|
||||
resp, err := d.client.Get(fmt.Sprintf("https://%s%s", d.host, EndpointGetServers))
|
||||
func (dl *VersionDataLoader) LoadServers() ([]*Server, error) {
|
||||
resp, err := dl.client.Get(dl.host + EndpointGetServers)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "couldn't load servers")
|
||||
}
|
||||
|
@ -52,14 +51,28 @@ func (d *VersionDataLoader) LoadServers() ([]*Server, error) {
|
|||
return nil, errors.Wrap(err, "couldn't read the response body")
|
||||
}
|
||||
body, err := phpserialize.Decode(string(bodyBytes))
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "couldn't decode the response body into the go value")
|
||||
if err != nil || body == nil {
|
||||
fmtedErr := errors.New("couldn't decode the response body into a go value")
|
||||
if err != nil {
|
||||
fmtedErr = errors.Wrap(err, fmtedErr.Error())
|
||||
}
|
||||
return nil, fmtedErr
|
||||
}
|
||||
bodyMap, ok := body.(map[interface{}]interface{})
|
||||
if !ok {
|
||||
return nil, errors.Errorf("expected map, got %T", body)
|
||||
}
|
||||
|
||||
var servers []*Server
|
||||
for serverKey, url := range body.(map[interface{}]interface{}) {
|
||||
serverKeyStr := serverKey.(string)
|
||||
urlStr := url.(string)
|
||||
for serverKey, url := range bodyMap {
|
||||
serverKeyStr, ok := serverKey.(string)
|
||||
if !ok {
|
||||
return nil, errors.Errorf("expected string as the key of the map, got %T", serverKey)
|
||||
}
|
||||
urlStr, ok := url.(string)
|
||||
if !ok {
|
||||
return nil, errors.Errorf("expected string as the value of the map, got %T", url)
|
||||
}
|
||||
if serverKeyStr != "" && urlStr != "" {
|
||||
servers = append(servers, &Server{
|
||||
Key: serverKeyStr,
|
||||
|
|
|
@ -0,0 +1,83 @@
|
|||
package twdataloader
|
||||
|
||||
import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestLoadServers(t *testing.T) {
|
||||
t.Run("invalid response", func(t *testing.T) {
|
||||
type scenario struct {
|
||||
resp string
|
||||
expectedErrMsg string
|
||||
}
|
||||
|
||||
scenarios := []scenario{
|
||||
{
|
||||
resp: `:"https://pl165.plemiona.pl";s:5:"pl166";s:25:"https://pl166.plemiona.pl";s:5:"pl167";s:25:"https://pl167.plemiona.pl";}`,
|
||||
expectedErrMsg: "couldn't decode the response body into a go value",
|
||||
},
|
||||
{
|
||||
resp: `a:19:{s:5:"pl150"s:25"https://pl150.plemiona.pl";}`,
|
||||
expectedErrMsg: "expected string as the value of the map, got <nil>",
|
||||
},
|
||||
{
|
||||
resp: "a:3:{i:0;i:1;i:1;i:2;i:2;i:3;}",
|
||||
expectedErrMsg: "expected string as the key of the map, got int64",
|
||||
},
|
||||
{
|
||||
resp: `O:8:"stdClass":0:{}`,
|
||||
expectedErrMsg: "expected map, got *phpserialize.PhpObject",
|
||||
},
|
||||
{
|
||||
resp: `a:2:{s:3:"asd";i:123;s:4:"asd2";i:123;}`,
|
||||
expectedErrMsg: "expected string as the value of the map, got int64",
|
||||
},
|
||||
}
|
||||
|
||||
for _, scenario := range scenarios {
|
||||
ts := prepareTestServer(&handlers{
|
||||
getServers: createWriteStringHandler(scenario.resp),
|
||||
})
|
||||
|
||||
dl := NewVersionDataLoader(&VersionDataLoaderConfig{
|
||||
Host: ts.URL,
|
||||
Client: ts.Client(),
|
||||
})
|
||||
|
||||
_, err := dl.LoadServers()
|
||||
assert.NotNil(t, err)
|
||||
assert.Contains(t, err.Error(), scenario.expectedErrMsg)
|
||||
|
||||
ts.Close()
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("success", func(t *testing.T) {
|
||||
resp := `a:19:{s:5:"pl150";s:25:"https://pl150.plemiona.pl";s:5:"pl151";s:25:"https://pl151.plemiona.pl";s:5:"pl152";s:25:"https://pl152.plemiona.pl";s:5:"pl153";s:25:"https://pl153.plemiona.pl";s:5:"pl154";s:25:"https://pl154.plemiona.pl";s:5:"pl155";s:25:"https://pl155.plemiona.pl";s:5:"pl156";s:25:"https://pl156.plemiona.pl";s:5:"pl157";s:25:"https://pl157.plemiona.pl";s:5:"pl158";s:25:"https://pl158.plemiona.pl";s:5:"pl159";s:25:"https://pl159.plemiona.pl";s:5:"pl160";s:25:"https://pl160.plemiona.pl";s:5:"pl161";s:25:"https://pl161.plemiona.pl";s:5:"pl162";s:25:"https://pl162.plemiona.pl";s:5:"pl163";s:25:"https://pl163.plemiona.pl";s:5:"pl164";s:25:"https://pl164.plemiona.pl";s:4:"plp7";s:24:"https://plp7.plemiona.pl";s:5:"pl165";s:25:"https://pl165.plemiona.pl";s:5:"pl166";s:25:"https://pl166.plemiona.pl";s:5:"pl167";s:25:"https://pl167.plemiona.pl";}`
|
||||
ts := prepareTestServer(&handlers{
|
||||
getServers: createWriteStringHandler(resp),
|
||||
})
|
||||
defer ts.Close()
|
||||
|
||||
expectedLength, err := strconv.Atoi(strings.Split(resp, ":")[1])
|
||||
assert.Nil(t, err)
|
||||
|
||||
dl := NewVersionDataLoader(&VersionDataLoaderConfig{
|
||||
Host: ts.URL,
|
||||
Client: ts.Client(),
|
||||
})
|
||||
|
||||
servers, err := dl.LoadServers()
|
||||
assert.Nil(t, err)
|
||||
cnt := 0
|
||||
for _, server := range servers {
|
||||
if strings.Contains(resp, server.URL) && strings.Contains(resp, server.Key) {
|
||||
cnt++
|
||||
}
|
||||
}
|
||||
assert.Equal(t, expectedLength, cnt)
|
||||
})
|
||||
}
|
Reference in New Issue