This repository has been archived on 2024-04-06. You can view files and clone it, but cannot push or open issues or pull requests.
core-old/internal/tw/client_test.go
Dawid Wysokiński 742a9046e0
All checks were successful
continuous-integration/drone/push Build is passing
feat: add ServerConsumer (#16)
Reviewed-on: twhelp/core#16
2022-08-04 05:09:12 +00:00

1302 lines
55 KiB
Go

package tw_test
import (
"context"
"encoding/csv"
"errors"
"fmt"
"net/http"
"net/http/httptest"
"strconv"
"testing"
"gitea.dwysokinski.me/twhelp/core/internal/domain"
"gitea.dwysokinski.me/twhelp/core/internal/tw"
"github.com/stretchr/testify/assert"
)
const (
testUserAgent = "tribalwarshelp.com/test"
)
func TestClient_GetOpenServers(t *testing.T) {
t.Parallel()
t.Run("OK", func(t *testing.T) {
t.Parallel()
//nolint:lll
resp := `a:16:{s:5:"pl159";s:25:"https://pl159.plemiona.pl";s:5:"pl161";s:25:"https://pl161.plemiona.pl";s:5:"pl164";s:25:"https://pl164.plemiona.pl";s:4:"plc1";s:24:"https://plc1.plemiona.pl";s:4:"pls1";s:24:"https://pls1.plemiona.pl";s:4:"plp7";s:24:"https://plp7.plemiona.pl";s:5:"pl165";s:25:"https://pl165.plemiona.pl";s:5:"pl167";s:25:"https://pl167.plemiona.pl";s:5:"pl168";s:25:"https://pl168.plemiona.pl";s:4:"plp8";s:24:"https://plp8.plemiona.pl";s:5:"pl169";s:25:"https://pl169.plemiona.pl";s:5:"pl170";s:25:"https://pl170.plemiona.pl";s:5:"pl171";s:25:"https://pl171.plemiona.pl";s:5:"pl172";s:25:"https://pl172.plemiona.pl";s:5:"pl173";s:25:"https://pl173.plemiona.pl";s:5:"pl174";s:25:"https://pl174.plemiona.pl";}`
mux := http.NewServeMux()
mux.HandleFunc("/backend/get_servers.php", createHandler(resp))
srv := httptest.NewTLSServer(mux)
defer srv.Close()
expectedServerKeys := []string{
"plp8",
"pl170",
"pl171",
"pl172",
"pl173",
"plc1",
"plp7",
"pl168",
"pl174",
"pl159",
"pl167",
"pl165",
"pl169",
"pls1",
"pl161",
"pl164",
}
servers, err := newTestClient(srv.Client()).GetOpenServers(context.Background(), srv.URL)
assert.NoError(t, err)
assert.Len(t, servers, len(expectedServerKeys))
for _, key := range expectedServerKeys {
found := false
for _, server := range servers {
if server.Key == key && server.URL == fmt.Sprintf("https://%s.plemiona.pl", key) {
found = true
break
}
}
assert.True(t, found, "key '%s' not found", key)
}
})
}
func TestClient_GetServerConfig(t *testing.T) {
t.Parallel()
t.Run("OK", func(t *testing.T) {
t.Parallel()
//nolint:lll
resp := `<?xml version="1.0" encoding="UTF-8" standalone="yes" ?><config><speed>4.5</speed><unit_speed>0.5</unit_speed><moral>1</moral><build><destroy>1</destroy></build><misc><kill_ranking>2</kill_ranking><tutorial>0</tutorial><trade_cancel_time>300</trade_cancel_time></misc><commands><millis_arrival>0</millis_arrival><command_cancel_time>600</command_cancel_time></commands><newbie><days>3</days><ratio_days>15</ratio_days><ratio>10</ratio><removeNewbieVillages>1</removeNewbieVillages></newbie><game><buildtime_formula>2</buildtime_formula><knight>0</knight><knight_new_items>0</knight_new_items><archer>1</archer><tech>2</tech><farm_limit>0</farm_limit><church>0</church><watchtower>0</watchtower><stronghold>0</stronghold><fake_limit>0.5</fake_limit><barbarian_rise>0.001</barbarian_rise><barbarian_shrink>1</barbarian_shrink><barbarian_max_points>800</barbarian_max_points><hauls>2</hauls><hauls_base>5000</hauls_base><hauls_max>1000000</hauls_max><base_production>75</base_production><event>0</event><suppress_events>1</suppress_events></game><buildings><custom_main>-1</custom_main><custom_farm>-1</custom_farm><custom_storage>-1</custom_storage><custom_place>-1</custom_place><custom_barracks>-1</custom_barracks><custom_church>-1</custom_church><custom_smith>-1</custom_smith><custom_wood>-1</custom_wood><custom_stone>-1</custom_stone><custom_iron>-1</custom_iron><custom_market>-1</custom_market><custom_stable>-1</custom_stable><custom_wall>-1</custom_wall><custom_garage>-1</custom_garage><custom_hide>-1</custom_hide><custom_snob>-1</custom_snob><custom_statue>-1</custom_statue><custom_watchtower>-1</custom_watchtower></buildings><snob><gold>1</gold><cheap_rebuild>0</cheap_rebuild><rise>2</rise><max_dist>50</max_dist><factor>1</factor><coin_wood>28000</coin_wood><coin_stone>30000</coin_stone><coin_iron>25000</coin_iron><no_barb_conquer>0</no_barb_conquer></snob><ally><no_harm>0</no_harm><no_other_support>0</no_other_support><no_other_support_type>0</no_other_support_type><allytime_support>0</allytime_support><no_leave></no_leave><no_join></no_join><limit>15</limit><fixed_allies>0</fixed_allies><wars_member_requirement>5</wars_member_requirement><wars_points_requirement>15000</wars_points_requirement><wars_autoaccept_days>7</wars_autoaccept_days><levels>1</levels><xp_requirements>v1</xp_requirements></ally><coord><map_size>1000</map_size><func>4</func><empty_villages>11</empty_villages><bonus_villages>1</bonus_villages><inner>550</inner><select_start>0</select_start><village_move_wait>336</village_move_wait><noble_restart>1</noble_restart><start_villages>1</start_villages></coord><sitter><allow>1</allow></sitter><sleep><active>0</active><delay>60</delay><min>6</min><max>10</max><min_awake>12</min_awake><max_awake>36</max_awake><warn_time>10</warn_time></sleep><night><active>2</active><start_hour>23</start_hour><end_hour>7</end_hour><def_factor>3.5</def_factor><duration>14</duration></night><win><check>3</check></win></config>`
mux := http.NewServeMux()
mux.HandleFunc("/interface.php", createConfigHandler("get_config", resp))
srv := httptest.NewTLSServer(mux)
defer srv.Close()
cfg, err := newTestClient(srv.Client()).GetServerConfig(context.Background(), srv.URL)
assert.NoError(t, err)
assert.Equal(t, 4.5, cfg.Speed)
assert.Equal(t, 0.5, cfg.UnitSpeed)
assert.EqualValues(t, 1, cfg.Moral)
assert.Equal(t, true, cfg.Build.Destroy)
assert.EqualValues(t, 2, cfg.Misc.KillRanking)
assert.EqualValues(t, 0, cfg.Misc.Tutorial)
assert.EqualValues(t, 300, cfg.Misc.TradeCancelTime)
assert.EqualValues(t, 0, cfg.Commands.MillisArrival)
assert.EqualValues(t, 600, cfg.Commands.CommandCancelTime)
assert.EqualValues(t, 3, cfg.Newbie.Days)
assert.EqualValues(t, 15, cfg.Newbie.RatioDays)
assert.EqualValues(t, 10, cfg.Newbie.Ratio)
assert.Equal(t, true, cfg.Newbie.RemoveNewbieVillages)
assert.EqualValues(t, 2, cfg.Game.BuildtimeFormula)
assert.EqualValues(t, false, cfg.Game.Knight)
assert.EqualValues(t, false, cfg.Game.KnightNewItems)
assert.Equal(t, true, cfg.Game.Archer)
assert.EqualValues(t, 2, cfg.Game.Tech)
assert.EqualValues(t, 0, cfg.Game.FarmLimit)
assert.Equal(t, false, cfg.Game.Church)
assert.Equal(t, false, cfg.Game.Watchtower)
assert.Equal(t, false, cfg.Game.Stronghold)
assert.EqualValues(t, 0.5, cfg.Game.FakeLimit)
assert.EqualValues(t, 0.001, cfg.Game.BarbarianRise)
assert.Equal(t, true, cfg.Game.BarbarianShrink)
assert.EqualValues(t, 800, cfg.Game.BarbarianMaxPoints)
assert.EqualValues(t, 2, cfg.Game.Hauls)
assert.EqualValues(t, 5000, cfg.Game.HaulsBase)
assert.EqualValues(t, 1000000, cfg.Game.HaulsMax)
assert.EqualValues(t, 0, cfg.Game.Event)
assert.Equal(t, true, cfg.Game.SuppressEvents)
assert.EqualValues(t, -1, cfg.Buildings.CustomMain)
assert.EqualValues(t, -1, cfg.Buildings.CustomFarm)
assert.EqualValues(t, -1, cfg.Buildings.CustomStorage)
assert.EqualValues(t, -1, cfg.Buildings.CustomPlace)
assert.EqualValues(t, -1, cfg.Buildings.CustomBarracks)
assert.EqualValues(t, -1, cfg.Buildings.CustomChurch)
assert.EqualValues(t, -1, cfg.Buildings.CustomSmith)
assert.EqualValues(t, -1, cfg.Buildings.CustomWood)
assert.EqualValues(t, -1, cfg.Buildings.CustomStone)
assert.EqualValues(t, -1, cfg.Buildings.CustomIron)
assert.EqualValues(t, -1, cfg.Buildings.CustomMarket)
assert.EqualValues(t, -1, cfg.Buildings.CustomStable)
assert.EqualValues(t, -1, cfg.Buildings.CustomWall)
assert.EqualValues(t, -1, cfg.Buildings.CustomGarage)
assert.EqualValues(t, -1, cfg.Buildings.CustomHide)
assert.EqualValues(t, -1, cfg.Buildings.CustomSnob)
assert.EqualValues(t, -1, cfg.Buildings.CustomStatue)
assert.EqualValues(t, -1, cfg.Buildings.CustomWatchtower)
assert.Equal(t, true, cfg.Snob.Gold)
assert.Equal(t, false, cfg.Snob.CheapRebuild)
assert.EqualValues(t, 2, cfg.Snob.Rise)
assert.EqualValues(t, 50, cfg.Snob.MaxDist)
assert.Equal(t, float64(1), cfg.Snob.Factor)
assert.EqualValues(t, 28000, cfg.Snob.CoinWood)
assert.EqualValues(t, 30000, cfg.Snob.CoinStone)
assert.EqualValues(t, 25000, cfg.Snob.CoinIron)
assert.Equal(t, false, cfg.Snob.NoBarbConquer)
assert.Equal(t, false, cfg.Ally.NoHarm)
assert.Equal(t, false, cfg.Ally.NoOtherSupport)
assert.EqualValues(t, 0, cfg.Ally.NoOtherSupportType)
assert.EqualValues(t, 0, cfg.Ally.AllytimeSupport)
assert.Equal(t, false, cfg.Ally.NoLeave)
assert.Equal(t, false, cfg.Ally.NoJoin)
assert.EqualValues(t, 15, cfg.Ally.Limit)
assert.Equal(t, false, cfg.Ally.FixedAllies)
assert.EqualValues(t, 5, cfg.Ally.WarsMemberRequirement)
assert.EqualValues(t, 15000, cfg.Ally.WarsPointsRequirement)
assert.EqualValues(t, 7, cfg.Ally.WarsAutoacceptDays)
assert.Equal(t, true, cfg.Ally.Levels)
assert.Equal(t, "v1", cfg.Ally.XpRequirements)
assert.EqualValues(t, 1000, cfg.Coord.MapSize)
assert.EqualValues(t, 4, cfg.Coord.Func)
assert.EqualValues(t, 11, cfg.Coord.EmptyVillages)
assert.EqualValues(t, 1, cfg.Coord.BonusVillages)
assert.EqualValues(t, 550, cfg.Coord.Inner)
assert.Equal(t, false, cfg.Coord.SelectStart)
assert.EqualValues(t, 336, cfg.Coord.VillageMoveWait)
assert.Equal(t, true, cfg.Coord.NobleRestart)
assert.Equal(t, true, cfg.Coord.StartVillages)
assert.Equal(t, true, cfg.Sitter.Allow)
assert.Equal(t, false, cfg.Sleep.Active)
assert.EqualValues(t, 60, cfg.Sleep.Delay)
assert.EqualValues(t, 6, cfg.Sleep.Min)
assert.EqualValues(t, 10, cfg.Sleep.Max)
assert.EqualValues(t, 12, cfg.Sleep.MinAwake)
assert.EqualValues(t, 36, cfg.Sleep.MaxAwake)
assert.EqualValues(t, 10, cfg.Sleep.WarnTime)
assert.EqualValues(t, 2, cfg.Night.Active)
assert.EqualValues(t, 23, cfg.Night.StartHour)
assert.EqualValues(t, 7, cfg.Night.EndHour)
assert.Equal(t, 3.5, cfg.Night.DefFactor)
assert.EqualValues(t, 14, cfg.Night.Duration)
assert.EqualValues(t, 3, cfg.Win.Check)
})
}
func TestClient_GetUnitInfo(t *testing.T) {
t.Parallel()
t.Run("OK", func(t *testing.T) {
t.Parallel()
//nolint:lll
resp := `<?xml version="1.0" encoding="UTF-8" standalone="yes" ?><config><spear><build_time>226.66666666667</build_time><pop>1</pop><speed>8</speed><attack>10</attack><defense>15</defense><defense_cavalry>45</defense_cavalry><defense_archer>20</defense_archer><carry>25</carry></spear><sword><build_time>333.33333333333</build_time><pop>1</pop><speed>9.7777777777778</speed><attack>25</attack><defense>50</defense><defense_cavalry>15</defense_cavalry><defense_archer>40</defense_archer><carry>15</carry></sword><axe><build_time>293.33333333333</build_time><pop>1</pop><speed>8</speed><attack>40</attack><defense>10</defense><defense_cavalry>5</defense_cavalry><defense_archer>10</defense_archer><carry>10</carry></axe><archer><build_time>400</build_time><pop>1</pop><speed>8</speed><attack>15</attack><defense>50</defense><defense_cavalry>40</defense_cavalry><defense_archer>5</defense_archer><carry>10</carry></archer><spy><build_time>200</build_time><pop>2</pop><speed>4</speed><attack>0</attack><defense>2</defense><defense_cavalry>1</defense_cavalry><defense_archer>2</defense_archer><carry>0</carry></spy><light><build_time>400</build_time><pop>4</pop><speed>4.4444444444444</speed><attack>130</attack><defense>30</defense><defense_cavalry>40</defense_cavalry><defense_archer>30</defense_archer><carry>80</carry></light><marcher><build_time>600</build_time><pop>5</pop><speed>4.4444444444444</speed><attack>120</attack><defense>40</defense><defense_cavalry>30</defense_cavalry><defense_archer>50</defense_archer><carry>50</carry></marcher><heavy><build_time>800</build_time><pop>6</pop><speed>4.8888888888889</speed><attack>150</attack><defense>200</defense><defense_cavalry>80</defense_cavalry><defense_archer>180</defense_archer><carry>50</carry></heavy><ram><build_time>1066.6666666667</build_time><pop>5</pop><speed>13.333333333333</speed><attack>2</attack><defense>20</defense><defense_cavalry>50</defense_cavalry><defense_archer>20</defense_archer><carry>0</carry></ram><catapult><build_time>1600</build_time><pop>8</pop><speed>13.333333333333</speed><attack>100</attack><defense>100</defense><defense_cavalry>50</defense_cavalry><defense_archer>100</defense_archer><carry>0</carry></catapult><snob><build_time>4000</build_time><pop>100</pop><speed>15.555555555556</speed><attack>30</attack><defense>100</defense><defense_cavalry>50</defense_cavalry><defense_archer>100</defense_archer><carry>0</carry></snob><militia><build_time>1</build_time><pop>0</pop><speed>0.016666666666667</speed><attack>0</attack><defense>15</defense><defense_cavalry>45</defense_cavalry><defense_archer>25</defense_archer><carry>0</carry></militia></config>`
mux := http.NewServeMux()
mux.HandleFunc("/interface.php", createConfigHandler("get_unit_info", resp))
srv := httptest.NewTLSServer(mux)
defer srv.Close()
unitInfo, err := newTestClient(srv.Client()).GetUnitInfo(context.Background(), srv.URL)
assert.NoError(t, err)
assert.Equal(t, 226.66666666667, unitInfo.Spear.BuildTime)
assert.EqualValues(t, 1, unitInfo.Spear.Pop)
assert.Equal(t, 8.0, unitInfo.Spear.Speed)
assert.EqualValues(t, 10, unitInfo.Spear.Attack)
assert.EqualValues(t, 15, unitInfo.Spear.Defense)
assert.EqualValues(t, 45, unitInfo.Spear.DefenseCavalry)
assert.EqualValues(t, 20, unitInfo.Spear.DefenseArcher)
assert.EqualValues(t, 25, unitInfo.Spear.Carry)
assert.Equal(t, 333.33333333333, unitInfo.Sword.BuildTime)
assert.EqualValues(t, 1, unitInfo.Sword.Pop)
assert.Equal(t, 9.7777777777778, unitInfo.Sword.Speed)
assert.EqualValues(t, 25, unitInfo.Sword.Attack)
assert.EqualValues(t, 50, unitInfo.Sword.Defense)
assert.EqualValues(t, 15, unitInfo.Sword.DefenseCavalry)
assert.EqualValues(t, 40, unitInfo.Sword.DefenseArcher)
assert.EqualValues(t, 15, unitInfo.Sword.Carry)
assert.Equal(t, 293.33333333333, unitInfo.Axe.BuildTime)
assert.EqualValues(t, 1, unitInfo.Axe.Pop)
assert.Equal(t, 8.0, unitInfo.Axe.Speed)
assert.EqualValues(t, 40, unitInfo.Axe.Attack)
assert.EqualValues(t, 10, unitInfo.Axe.Defense)
assert.EqualValues(t, 5, unitInfo.Axe.DefenseCavalry)
assert.EqualValues(t, 10, unitInfo.Axe.DefenseArcher)
assert.EqualValues(t, 10, unitInfo.Axe.Carry)
assert.Equal(t, 200.0, unitInfo.Spy.BuildTime)
assert.EqualValues(t, 2, unitInfo.Spy.Pop)
assert.Equal(t, 4.0, unitInfo.Spy.Speed)
assert.EqualValues(t, 0, unitInfo.Spy.Attack)
assert.EqualValues(t, 2, unitInfo.Spy.Defense)
assert.EqualValues(t, 1, unitInfo.Spy.DefenseCavalry)
assert.EqualValues(t, 2, unitInfo.Spy.DefenseArcher)
assert.EqualValues(t, 0, unitInfo.Spy.Carry)
assert.Equal(t, 400.0, unitInfo.Light.BuildTime)
assert.EqualValues(t, 4, unitInfo.Light.Pop)
assert.Equal(t, 4.4444444444444, unitInfo.Light.Speed)
assert.EqualValues(t, 130, unitInfo.Light.Attack)
assert.EqualValues(t, 30, unitInfo.Light.Defense)
assert.EqualValues(t, 40, unitInfo.Light.DefenseCavalry)
assert.EqualValues(t, 30, unitInfo.Light.DefenseArcher)
assert.EqualValues(t, 80, unitInfo.Light.Carry)
assert.Equal(t, 600.0, unitInfo.Marcher.BuildTime)
assert.EqualValues(t, 5, unitInfo.Marcher.Pop)
assert.Equal(t, 4.4444444444444, unitInfo.Marcher.Speed)
assert.EqualValues(t, 120, unitInfo.Marcher.Attack)
assert.EqualValues(t, 40, unitInfo.Marcher.Defense)
assert.EqualValues(t, 30, unitInfo.Marcher.DefenseCavalry)
assert.EqualValues(t, 50, unitInfo.Marcher.DefenseArcher)
assert.EqualValues(t, 50, unitInfo.Marcher.Carry)
assert.Equal(t, 800.0, unitInfo.Heavy.BuildTime)
assert.EqualValues(t, 6, unitInfo.Heavy.Pop)
assert.Equal(t, 4.8888888888889, unitInfo.Heavy.Speed)
assert.EqualValues(t, 150, unitInfo.Heavy.Attack)
assert.EqualValues(t, 200, unitInfo.Heavy.Defense)
assert.EqualValues(t, 80, unitInfo.Heavy.DefenseCavalry)
assert.EqualValues(t, 180, unitInfo.Heavy.DefenseArcher)
assert.EqualValues(t, 50, unitInfo.Heavy.Carry)
assert.Equal(t, 1066.6666666667, unitInfo.Ram.BuildTime)
assert.EqualValues(t, 5, unitInfo.Ram.Pop)
assert.Equal(t, 13.333333333333, unitInfo.Ram.Speed)
assert.EqualValues(t, 2, unitInfo.Ram.Attack)
assert.EqualValues(t, 20, unitInfo.Ram.Defense)
assert.EqualValues(t, 50, unitInfo.Ram.DefenseCavalry)
assert.EqualValues(t, 20, unitInfo.Ram.DefenseArcher)
assert.EqualValues(t, 0, unitInfo.Ram.Carry)
assert.Equal(t, 1600.0, unitInfo.Catapult.BuildTime)
assert.EqualValues(t, 8, unitInfo.Catapult.Pop)
assert.Equal(t, 13.333333333333, unitInfo.Catapult.Speed)
assert.EqualValues(t, 100, unitInfo.Catapult.Attack)
assert.EqualValues(t, 100, unitInfo.Catapult.Defense)
assert.EqualValues(t, 50, unitInfo.Catapult.DefenseCavalry)
assert.EqualValues(t, 100, unitInfo.Catapult.DefenseArcher)
assert.EqualValues(t, 0, unitInfo.Catapult.Carry)
assert.Equal(t, 4000.0, unitInfo.Snob.BuildTime)
assert.EqualValues(t, 100, unitInfo.Snob.Pop)
assert.Equal(t, 15.555555555556, unitInfo.Snob.Speed)
assert.EqualValues(t, 30, unitInfo.Snob.Attack)
assert.EqualValues(t, 100, unitInfo.Snob.Defense)
assert.EqualValues(t, 50, unitInfo.Snob.DefenseCavalry)
assert.EqualValues(t, 100, unitInfo.Snob.DefenseArcher)
assert.EqualValues(t, 0, unitInfo.Snob.Carry)
assert.Equal(t, 1.0, unitInfo.Militia.BuildTime)
assert.EqualValues(t, 0, unitInfo.Militia.Pop)
assert.Equal(t, 0.016666666666667, unitInfo.Militia.Speed)
assert.EqualValues(t, 0, unitInfo.Militia.Attack)
assert.EqualValues(t, 15, unitInfo.Militia.Defense)
assert.EqualValues(t, 45, unitInfo.Militia.DefenseCavalry)
assert.EqualValues(t, 25, unitInfo.Militia.DefenseArcher)
assert.EqualValues(t, 0, unitInfo.Militia.Carry)
})
}
func TestClient_GetBuildingInfo(t *testing.T) {
t.Parallel()
t.Run("OK", func(t *testing.T) {
t.Parallel()
//nolint:lll
resp := `<?xml version="1.0" encoding="UTF-8" standalone="yes" ?><config><main><max_level>30</max_level><min_level>1</min_level><wood>90</wood><stone>80</stone><iron>70</iron><pop>5</pop><wood_factor>1.26</wood_factor><stone_factor>1.275</stone_factor><iron_factor>1.26</iron_factor><pop_factor>1.17</pop_factor><build_time>900</build_time><build_time_factor>1.2</build_time_factor></main><barracks><max_level>25</max_level><min_level>0</min_level><wood>200</wood><stone>170</stone><iron>90</iron><pop>7</pop><wood_factor>1.26</wood_factor><stone_factor>1.28</stone_factor><iron_factor>1.26</iron_factor><pop_factor>1.17</pop_factor><build_time>1800</build_time><build_time_factor>1.2</build_time_factor></barracks><stable><max_level>20</max_level><min_level>0</min_level><wood>270</wood><stone>240</stone><iron>260</iron><pop>8</pop><wood_factor>1.26</wood_factor><stone_factor>1.28</stone_factor><iron_factor>1.26</iron_factor><pop_factor>1.17</pop_factor><build_time>6000</build_time><build_time_factor>1.2</build_time_factor></stable><garage><max_level>15</max_level><min_level>0</min_level><wood>300</wood><stone>240</stone><iron>260</iron><pop>8</pop><wood_factor>1.26</wood_factor><stone_factor>1.28</stone_factor><iron_factor>1.26</iron_factor><pop_factor>1.17</pop_factor><build_time>6000</build_time><build_time_factor>1.2</build_time_factor></garage><watchtower><max_level>20</max_level><min_level>0</min_level><wood>12000</wood><stone>14000</stone><iron>10000</iron><pop>500</pop><wood_factor>1.17</wood_factor><stone_factor>1.17</stone_factor><iron_factor>1.18</iron_factor><pop_factor>1.18</pop_factor><build_time>13200</build_time><build_time_factor>1.2</build_time_factor></watchtower><snob><max_level>1</max_level><min_level>0</min_level><wood>15000</wood><stone>25000</stone><iron>10000</iron><pop>80</pop><wood_factor>2</wood_factor><stone_factor>2</stone_factor><iron_factor>2</iron_factor><pop_factor>1.17</pop_factor><build_time>586800</build_time><build_time_factor>1.2</build_time_factor></snob><smith><max_level>20</max_level><min_level>0</min_level><wood>220</wood><stone>180</stone><iron>240</iron><pop>20</pop><wood_factor>1.26</wood_factor><stone_factor>1.275</stone_factor><iron_factor>1.26</iron_factor><pop_factor>1.17</pop_factor><build_time>6000</build_time><build_time_factor>1.2</build_time_factor></smith><place><max_level>1</max_level><min_level>0</min_level><wood>10</wood><stone>40</stone><iron>30</iron><pop>0</pop><wood_factor>1.26</wood_factor><stone_factor>1.275</stone_factor><iron_factor>1.26</iron_factor><pop_factor>1.17</pop_factor><build_time>10860</build_time><build_time_factor>1.2</build_time_factor></place><statue><max_level>1</max_level><min_level>0</min_level><wood>220</wood><stone>220</stone><iron>220</iron><pop>10</pop><wood_factor>1.26</wood_factor><stone_factor>1.275</stone_factor><iron_factor>1.26</iron_factor><pop_factor>1.17</pop_factor><build_time>1500</build_time><build_time_factor>1.2</build_time_factor></statue><market><max_level>25</max_level><min_level>0</min_level><wood>100</wood><stone>100</stone><iron>100</iron><pop>20</pop><wood_factor>1.26</wood_factor><stone_factor>1.275</stone_factor><iron_factor>1.26</iron_factor><pop_factor>1.17</pop_factor><build_time>2700</build_time><build_time_factor>1.2</build_time_factor></market><wood><max_level>30</max_level><min_level>0</min_level><wood>50</wood><stone>60</stone><iron>40</iron><pop>5</pop><wood_factor>1.25</wood_factor><stone_factor>1.275</stone_factor><iron_factor>1.245</iron_factor><pop_factor>1.155</pop_factor><build_time>900</build_time><build_time_factor>1.2</build_time_factor></wood><stone><max_level>30</max_level><min_level>0</min_level><wood>65</wood><stone>50</stone><iron>40</iron><pop>10</pop><wood_factor>1.27</wood_factor><stone_factor>1.265</stone_factor><iron_factor>1.24</iron_factor><pop_factor>1.14</pop_factor><build_time>900</build_time><build_time_factor>1.2</build_time_factor></stone><iron><max_level>30</max_level><min_level>0</min_level><wood>75</wood><stone>65</stone><iron>70</iron><pop>10</pop><wood_factor>1.252</wood_factor><stone_factor>1.275</stone_factor><iron_factor>1.24</iron_factor><pop_factor>1.17</pop_factor><build_time>1080</build_time><build_time_factor>1.2</build_time_factor></iron><farm><max_level>30</max_level><min_level>1</min_level><wood>45</wood><stone>40</stone><iron>30</iron><pop>0</pop><wood_factor>1.3</wood_factor><stone_factor>1.32</stone_factor><iron_factor>1.29</iron_factor><pop_factor>1</pop_factor><build_time>1200</build_time><build_time_factor>1.2</build_time_factor></farm><storage><max_level>30</max_level><min_level>1</min_level><wood>60</wood><stone>50</stone><iron>40</iron><pop>0</pop><wood_factor>1.265</wood_factor><stone_factor>1.27</stone_factor><iron_factor>1.245</iron_factor><pop_factor>1.15</pop_factor><build_time>1020</build_time><build_time_factor>1.2</build_time_factor></storage><hide><max_level>10</max_level><min_level>0</min_level><wood>50</wood><stone>60</stone><iron>50</iron><pop>2</pop><wood_factor>1.25</wood_factor><stone_factor>1.25</stone_factor><iron_factor>1.25</iron_factor><pop_factor>1.17</pop_factor><build_time>1800</build_time><build_time_factor>1.2</build_time_factor></hide><wall><max_level>20</max_level><min_level>0</min_level><wood>50</wood><stone>100</stone><iron>20</iron><pop>5</pop><wood_factor>1.26</wood_factor><stone_factor>1.275</stone_factor><iron_factor>1.26</iron_factor><pop_factor>1.17</pop_factor><build_time>3600</build_time><build_time_factor>1.2</build_time_factor></wall></config>`
mux := http.NewServeMux()
mux.HandleFunc("/interface.php", createConfigHandler("get_building_info", resp))
srv := httptest.NewTLSServer(mux)
defer srv.Close()
buildingInfo, err := newTestClient(srv.Client()).GetBuildingInfo(context.Background(), srv.URL)
assert.NoError(t, err)
assert.EqualValues(t, 30, buildingInfo.Main.MaxLevel)
assert.EqualValues(t, 1, buildingInfo.Main.MinLevel)
assert.EqualValues(t, 90, buildingInfo.Main.Wood)
assert.EqualValues(t, 80, buildingInfo.Main.Stone)
assert.EqualValues(t, 70, buildingInfo.Main.Iron)
assert.EqualValues(t, 5, buildingInfo.Main.Pop)
assert.Equal(t, 1.26, buildingInfo.Main.WoodFactor)
assert.Equal(t, 1.275, buildingInfo.Main.StoneFactor)
assert.Equal(t, 1.26, buildingInfo.Main.IronFactor)
assert.Equal(t, 1.17, buildingInfo.Main.PopFactor)
assert.Equal(t, 900.0, buildingInfo.Main.BuildTime)
assert.Equal(t, 1.2, buildingInfo.Main.BuildTimeFactor)
assert.EqualValues(t, 25, buildingInfo.Barracks.MaxLevel)
assert.EqualValues(t, 0, buildingInfo.Barracks.MinLevel)
assert.EqualValues(t, 200, buildingInfo.Barracks.Wood)
assert.EqualValues(t, 170, buildingInfo.Barracks.Stone)
assert.EqualValues(t, 90, buildingInfo.Barracks.Iron)
assert.EqualValues(t, 7, buildingInfo.Barracks.Pop)
assert.Equal(t, 1.26, buildingInfo.Barracks.WoodFactor)
assert.Equal(t, 1.28, buildingInfo.Barracks.StoneFactor)
assert.Equal(t, 1.26, buildingInfo.Barracks.IronFactor)
assert.Equal(t, 1.17, buildingInfo.Barracks.PopFactor)
assert.Equal(t, 1800.0, buildingInfo.Barracks.BuildTime)
assert.Equal(t, 1.2, buildingInfo.Barracks.BuildTimeFactor)
assert.EqualValues(t, 20, buildingInfo.Stable.MaxLevel)
assert.EqualValues(t, 0, buildingInfo.Stable.MinLevel)
assert.EqualValues(t, 270, buildingInfo.Stable.Wood)
assert.EqualValues(t, 240, buildingInfo.Stable.Stone)
assert.EqualValues(t, 260, buildingInfo.Stable.Iron)
assert.EqualValues(t, 8, buildingInfo.Stable.Pop)
assert.Equal(t, 1.26, buildingInfo.Stable.WoodFactor)
assert.Equal(t, 1.28, buildingInfo.Stable.StoneFactor)
assert.Equal(t, 1.26, buildingInfo.Stable.IronFactor)
assert.Equal(t, 1.17, buildingInfo.Stable.PopFactor)
assert.Equal(t, 6000.0, buildingInfo.Stable.BuildTime)
assert.Equal(t, 1.2, buildingInfo.Stable.BuildTimeFactor)
assert.EqualValues(t, 15, buildingInfo.Garage.MaxLevel)
assert.EqualValues(t, 0, buildingInfo.Garage.MinLevel)
assert.EqualValues(t, 300, buildingInfo.Garage.Wood)
assert.EqualValues(t, 240, buildingInfo.Garage.Stone)
assert.EqualValues(t, 260, buildingInfo.Garage.Iron)
assert.EqualValues(t, 8, buildingInfo.Garage.Pop)
assert.Equal(t, 1.26, buildingInfo.Garage.WoodFactor)
assert.Equal(t, 1.28, buildingInfo.Garage.StoneFactor)
assert.Equal(t, 1.26, buildingInfo.Garage.IronFactor)
assert.Equal(t, 1.17, buildingInfo.Garage.PopFactor)
assert.Equal(t, 6000.0, buildingInfo.Garage.BuildTime)
assert.Equal(t, 1.2, buildingInfo.Garage.BuildTimeFactor)
assert.EqualValues(t, 20, buildingInfo.Watchtower.MaxLevel)
assert.EqualValues(t, 0, buildingInfo.Watchtower.MinLevel)
assert.EqualValues(t, 12000, buildingInfo.Watchtower.Wood)
assert.EqualValues(t, 14000, buildingInfo.Watchtower.Stone)
assert.EqualValues(t, 10000, buildingInfo.Watchtower.Iron)
assert.EqualValues(t, 500, buildingInfo.Watchtower.Pop)
assert.Equal(t, 1.17, buildingInfo.Watchtower.WoodFactor)
assert.Equal(t, 1.17, buildingInfo.Watchtower.StoneFactor)
assert.Equal(t, 1.18, buildingInfo.Watchtower.IronFactor)
assert.Equal(t, 1.18, buildingInfo.Watchtower.PopFactor)
assert.Equal(t, 13200.0, buildingInfo.Watchtower.BuildTime)
assert.Equal(t, 1.2, buildingInfo.Watchtower.BuildTimeFactor)
assert.EqualValues(t, 1, buildingInfo.Snob.MaxLevel)
assert.EqualValues(t, 0, buildingInfo.Snob.MinLevel)
assert.EqualValues(t, 15000, buildingInfo.Snob.Wood)
assert.EqualValues(t, 25000, buildingInfo.Snob.Stone)
assert.EqualValues(t, 10000, buildingInfo.Snob.Iron)
assert.EqualValues(t, 80, buildingInfo.Snob.Pop)
assert.Equal(t, 2.0, buildingInfo.Snob.WoodFactor)
assert.Equal(t, 2.0, buildingInfo.Snob.StoneFactor)
assert.Equal(t, 2.0, buildingInfo.Snob.IronFactor)
assert.Equal(t, 1.17, buildingInfo.Snob.PopFactor)
assert.Equal(t, 586800.0, buildingInfo.Snob.BuildTime)
assert.Equal(t, 1.2, buildingInfo.Snob.BuildTimeFactor)
assert.EqualValues(t, 20, buildingInfo.Smith.MaxLevel)
assert.EqualValues(t, 0, buildingInfo.Smith.MinLevel)
assert.EqualValues(t, 220, buildingInfo.Smith.Wood)
assert.EqualValues(t, 180, buildingInfo.Smith.Stone)
assert.EqualValues(t, 240, buildingInfo.Smith.Iron)
assert.EqualValues(t, 20, buildingInfo.Smith.Pop)
assert.Equal(t, 1.26, buildingInfo.Smith.WoodFactor)
assert.Equal(t, 1.275, buildingInfo.Smith.StoneFactor)
assert.Equal(t, 1.26, buildingInfo.Smith.IronFactor)
assert.Equal(t, 1.17, buildingInfo.Smith.PopFactor)
assert.Equal(t, 6000.0, buildingInfo.Smith.BuildTime)
assert.Equal(t, 1.2, buildingInfo.Smith.BuildTimeFactor)
assert.EqualValues(t, 1, buildingInfo.Place.MaxLevel)
assert.EqualValues(t, 0, buildingInfo.Place.MinLevel)
assert.EqualValues(t, 10, buildingInfo.Place.Wood)
assert.EqualValues(t, 40, buildingInfo.Place.Stone)
assert.EqualValues(t, 30, buildingInfo.Place.Iron)
assert.EqualValues(t, 0, buildingInfo.Place.Pop)
assert.Equal(t, 1.26, buildingInfo.Place.WoodFactor)
assert.Equal(t, 1.275, buildingInfo.Place.StoneFactor)
assert.Equal(t, 1.26, buildingInfo.Place.IronFactor)
assert.Equal(t, 1.17, buildingInfo.Place.PopFactor)
assert.Equal(t, 10860.0, buildingInfo.Place.BuildTime)
assert.Equal(t, 1.2, buildingInfo.Place.BuildTimeFactor)
assert.EqualValues(t, 1, buildingInfo.Statue.MaxLevel)
assert.EqualValues(t, 0, buildingInfo.Statue.MinLevel)
assert.EqualValues(t, 220, buildingInfo.Statue.Wood)
assert.EqualValues(t, 220, buildingInfo.Statue.Stone)
assert.EqualValues(t, 220, buildingInfo.Statue.Iron)
assert.EqualValues(t, 10, buildingInfo.Statue.Pop)
assert.Equal(t, 1.26, buildingInfo.Statue.WoodFactor)
assert.Equal(t, 1.275, buildingInfo.Statue.StoneFactor)
assert.Equal(t, 1.26, buildingInfo.Statue.IronFactor)
assert.Equal(t, 1.17, buildingInfo.Statue.PopFactor)
assert.Equal(t, 1500.0, buildingInfo.Statue.BuildTime)
assert.Equal(t, 1.2, buildingInfo.Statue.BuildTimeFactor)
assert.EqualValues(t, 25, buildingInfo.Market.MaxLevel)
assert.EqualValues(t, 0, buildingInfo.Market.MinLevel)
assert.EqualValues(t, 100, buildingInfo.Market.Wood)
assert.EqualValues(t, 100, buildingInfo.Market.Stone)
assert.EqualValues(t, 100, buildingInfo.Market.Iron)
assert.EqualValues(t, 20, buildingInfo.Market.Pop)
assert.Equal(t, 1.26, buildingInfo.Market.WoodFactor)
assert.Equal(t, 1.275, buildingInfo.Market.StoneFactor)
assert.Equal(t, 1.26, buildingInfo.Market.IronFactor)
assert.Equal(t, 1.17, buildingInfo.Market.PopFactor)
assert.Equal(t, 2700.0, buildingInfo.Market.BuildTime)
assert.Equal(t, 1.2, buildingInfo.Market.BuildTimeFactor)
assert.EqualValues(t, 30, buildingInfo.Wood.MaxLevel)
assert.EqualValues(t, 0, buildingInfo.Wood.MinLevel)
assert.EqualValues(t, 50, buildingInfo.Wood.Wood)
assert.EqualValues(t, 60, buildingInfo.Wood.Stone)
assert.EqualValues(t, 40, buildingInfo.Wood.Iron)
assert.EqualValues(t, 5, buildingInfo.Wood.Pop)
assert.Equal(t, 1.25, buildingInfo.Wood.WoodFactor)
assert.Equal(t, 1.275, buildingInfo.Wood.StoneFactor)
assert.Equal(t, 1.245, buildingInfo.Wood.IronFactor)
assert.Equal(t, 1.155, buildingInfo.Wood.PopFactor)
assert.Equal(t, 900.0, buildingInfo.Wood.BuildTime)
assert.Equal(t, 1.2, buildingInfo.Wood.BuildTimeFactor)
assert.EqualValues(t, 30, buildingInfo.Stone.MaxLevel)
assert.EqualValues(t, 0, buildingInfo.Stone.MinLevel)
assert.EqualValues(t, 65, buildingInfo.Stone.Wood)
assert.EqualValues(t, 50, buildingInfo.Stone.Stone)
assert.EqualValues(t, 40, buildingInfo.Stone.Iron)
assert.EqualValues(t, 10, buildingInfo.Stone.Pop)
assert.Equal(t, 1.27, buildingInfo.Stone.WoodFactor)
assert.Equal(t, 1.265, buildingInfo.Stone.StoneFactor)
assert.Equal(t, 1.24, buildingInfo.Stone.IronFactor)
assert.Equal(t, 1.14, buildingInfo.Stone.PopFactor)
assert.Equal(t, 900.0, buildingInfo.Stone.BuildTime)
assert.Equal(t, 1.2, buildingInfo.Stone.BuildTimeFactor)
assert.EqualValues(t, 30, buildingInfo.Iron.MaxLevel)
assert.EqualValues(t, 0, buildingInfo.Iron.MinLevel)
assert.EqualValues(t, 75, buildingInfo.Iron.Wood)
assert.EqualValues(t, 65, buildingInfo.Iron.Stone)
assert.EqualValues(t, 70, buildingInfo.Iron.Iron)
assert.EqualValues(t, 10, buildingInfo.Iron.Pop)
assert.Equal(t, 1.252, buildingInfo.Iron.WoodFactor)
assert.Equal(t, 1.275, buildingInfo.Iron.StoneFactor)
assert.Equal(t, 1.24, buildingInfo.Iron.IronFactor)
assert.Equal(t, 1.17, buildingInfo.Iron.PopFactor)
assert.Equal(t, 1080.0, buildingInfo.Iron.BuildTime)
assert.Equal(t, 1.2, buildingInfo.Iron.BuildTimeFactor)
assert.EqualValues(t, 30, buildingInfo.Farm.MaxLevel)
assert.EqualValues(t, 1, buildingInfo.Farm.MinLevel)
assert.EqualValues(t, 45, buildingInfo.Farm.Wood)
assert.EqualValues(t, 40, buildingInfo.Farm.Stone)
assert.EqualValues(t, 30, buildingInfo.Farm.Iron)
assert.EqualValues(t, 0, buildingInfo.Farm.Pop)
assert.Equal(t, 1.3, buildingInfo.Farm.WoodFactor)
assert.Equal(t, 1.32, buildingInfo.Farm.StoneFactor)
assert.Equal(t, 1.29, buildingInfo.Farm.IronFactor)
assert.Equal(t, 1.0, buildingInfo.Farm.PopFactor)
assert.Equal(t, 1200.0, buildingInfo.Farm.BuildTime)
assert.Equal(t, 1.2, buildingInfo.Farm.BuildTimeFactor)
assert.EqualValues(t, 30, buildingInfo.Storage.MaxLevel)
assert.EqualValues(t, 1, buildingInfo.Storage.MinLevel)
assert.EqualValues(t, 60, buildingInfo.Storage.Wood)
assert.EqualValues(t, 50, buildingInfo.Storage.Stone)
assert.EqualValues(t, 40, buildingInfo.Storage.Iron)
assert.EqualValues(t, 0, buildingInfo.Storage.Pop)
assert.Equal(t, 1.265, buildingInfo.Storage.WoodFactor)
assert.Equal(t, 1.27, buildingInfo.Storage.StoneFactor)
assert.Equal(t, 1.245, buildingInfo.Storage.IronFactor)
assert.Equal(t, 1.15, buildingInfo.Storage.PopFactor)
assert.Equal(t, 1020.0, buildingInfo.Storage.BuildTime)
assert.Equal(t, 1.2, buildingInfo.Storage.BuildTimeFactor)
assert.EqualValues(t, 10, buildingInfo.Hide.MaxLevel)
assert.EqualValues(t, 0, buildingInfo.Hide.MinLevel)
assert.EqualValues(t, 50, buildingInfo.Hide.Wood)
assert.EqualValues(t, 60, buildingInfo.Hide.Stone)
assert.EqualValues(t, 50, buildingInfo.Hide.Iron)
assert.EqualValues(t, 2, buildingInfo.Hide.Pop)
assert.Equal(t, 1.25, buildingInfo.Hide.WoodFactor)
assert.Equal(t, 1.25, buildingInfo.Hide.StoneFactor)
assert.Equal(t, 1.25, buildingInfo.Hide.IronFactor)
assert.Equal(t, 1.17, buildingInfo.Hide.PopFactor)
assert.Equal(t, 1800.0, buildingInfo.Hide.BuildTime)
assert.Equal(t, 1.2, buildingInfo.Hide.BuildTimeFactor)
assert.EqualValues(t, 20, buildingInfo.Wall.MaxLevel)
assert.EqualValues(t, 0, buildingInfo.Wall.MinLevel)
assert.EqualValues(t, 50, buildingInfo.Wall.Wood)
assert.EqualValues(t, 100, buildingInfo.Wall.Stone)
assert.EqualValues(t, 20, buildingInfo.Wall.Iron)
assert.EqualValues(t, 5, buildingInfo.Wall.Pop)
assert.Equal(t, 1.26, buildingInfo.Wall.WoodFactor)
assert.Equal(t, 1.275, buildingInfo.Wall.StoneFactor)
assert.Equal(t, 1.26, buildingInfo.Wall.IronFactor)
assert.Equal(t, 1.17, buildingInfo.Wall.PopFactor)
assert.Equal(t, 3600.0, buildingInfo.Wall.BuildTime)
assert.Equal(t, 1.2, buildingInfo.Wall.BuildTimeFactor)
})
}
func TestClient_GetTribes(t *testing.T) {
t.Parallel()
tests := []struct {
name string
respTribe string
respOD string
respODA string
respODD string
checkErr func(err error) bool
expectedTribes []domain.BaseTribe
}{
{
name: "OK",
respTribe: "1,name%201,tag%201,100,101,102,103,104\n2,name2,tag2,200,202,202,203,204\n3,name3,tag3,300,303,302,303,304\n4,name4,tag4,400,404,402,403,404", //nolint:lll
respOD: "1,1,1\n2,2,2\n3,3,3",
respODA: "1,1,1\n2,2,2\n3,3,3",
respODD: "1,1,1\n2,2,2\n3,3,3",
expectedTribes: []domain.BaseTribe{
{
ID: 1,
Name: "name 1",
Tag: "tag 1",
NumMembers: 100,
NumVillages: 101,
Points: 102,
AllPoints: 103,
Rank: 104,
OpponentsDefeated: domain.OpponentsDefeated{
RankAtt: 1,
ScoreAtt: 1,
RankDef: 1,
ScoreDef: 1,
RankSup: 0,
ScoreSup: 0,
RankTotal: 1,
ScoreTotal: 1,
},
},
{
ID: 2,
Name: "name2",
Tag: "tag2",
NumMembers: 200,
NumVillages: 202,
Points: 202,
AllPoints: 203,
Rank: 204,
OpponentsDefeated: domain.OpponentsDefeated{
RankAtt: 2,
ScoreAtt: 2,
RankDef: 2,
ScoreDef: 2,
RankSup: 0,
ScoreSup: 0,
RankTotal: 2,
ScoreTotal: 2,
},
},
{
ID: 3,
Name: "name3",
Tag: "tag3",
NumMembers: 300,
NumVillages: 303,
Points: 302,
AllPoints: 303,
Rank: 304,
OpponentsDefeated: domain.OpponentsDefeated{
RankAtt: 3,
ScoreAtt: 3,
RankDef: 3,
ScoreDef: 3,
RankSup: 0,
ScoreSup: 0,
RankTotal: 3,
ScoreTotal: 3,
},
},
{
ID: 4,
Name: "name4",
Tag: "tag4",
NumMembers: 400,
NumVillages: 404,
Points: 402,
AllPoints: 403,
Rank: 404,
OpponentsDefeated: domain.OpponentsDefeated{},
},
},
},
{
name: "ERR: invalid value - OD.Rank",
respOD: "test,1,1001",
checkErr: func(err error) bool {
var parseErr tw.ParseError
return errors.As(err, &parseErr) && parseErr.Field() == "odRecord.Rank" && errors.Is(parseErr, strconv.ErrSyntax)
},
},
{
name: "ERR: invalid value - OD.ID",
respOD: "1,test,1001",
checkErr: func(err error) bool {
var parseErr tw.ParseError
return errors.As(err, &parseErr) && parseErr.Field() == "odRecord.ID" && errors.Is(parseErr, strconv.ErrSyntax)
},
},
{
name: "ERR: invalid value - OD.Score",
respOD: "1,1,test",
checkErr: func(err error) bool {
var parseErr tw.ParseError
return errors.As(err, &parseErr) && parseErr.Field() == "odRecord.Score" && errors.Is(parseErr, strconv.ErrSyntax)
},
},
{
name: "ERR: invalid value - ODA.Rank",
respODA: "test,1,1001",
checkErr: func(err error) bool {
var parseErr tw.ParseError
return errors.As(err, &parseErr) && parseErr.Field() == "odRecord.Rank" && errors.Is(parseErr, strconv.ErrSyntax)
},
},
{
name: "ERR: invalid value - ODA.ID",
respODA: "1,test,1001",
checkErr: func(err error) bool {
var parseErr tw.ParseError
return errors.As(err, &parseErr) && parseErr.Field() == "odRecord.ID" && errors.Is(parseErr, strconv.ErrSyntax)
},
},
{
name: "ERR: invalid value - ODA.Score",
respODA: "1,1,test",
checkErr: func(err error) bool {
var parseErr tw.ParseError
return errors.As(err, &parseErr) && parseErr.Field() == "odRecord.Score" && errors.Is(parseErr, strconv.ErrSyntax)
},
},
{
name: "ERR: invalid value - ODD.Rank",
respODD: "test,1,1001",
checkErr: func(err error) bool {
var parseErr tw.ParseError
return errors.As(err, &parseErr) && parseErr.Field() == "odRecord.Rank" && errors.Is(parseErr, strconv.ErrSyntax)
},
},
{
name: "ERR: invalid value - ODD.ID",
respODD: "1,test,1001",
checkErr: func(err error) bool {
var parseErr tw.ParseError
return errors.As(err, &parseErr) && parseErr.Field() == "odRecord.ID" && errors.Is(parseErr, strconv.ErrSyntax)
},
},
{
name: "ERR: invalid value - ODD.Score",
respODD: "1,1,test",
checkErr: func(err error) bool {
var parseErr tw.ParseError
return errors.As(err, &parseErr) && parseErr.Field() == "odRecord.Score" && errors.Is(parseErr, strconv.ErrSyntax)
},
},
{
name: "ERR: wrong number of fields 1",
respTribe: "1,name%201,tag%201,100,101,102,103",
checkErr: func(err error) bool {
return errors.Is(err, csv.ErrFieldCount)
},
},
{
name: "ERR: wrong number of fields 2",
respTribe: "1,name%201,tag%201,100,101,102,103,104,105",
checkErr: func(err error) bool {
return errors.Is(err, csv.ErrFieldCount)
},
},
{
name: "ERR: invalid value - Tribe.ID",
respTribe: "1.23,name1,tag1,100,101,102,103,104",
checkErr: func(err error) bool {
var parseErr tw.ParseError
return errors.As(err, &parseErr) && parseErr.Field() == "tribe.ID" && errors.Is(parseErr, strconv.ErrSyntax)
},
},
{
name: "ERR: invalid value - Tribe.NumMembers",
respTribe: "1,name1,tag1,100.23,101,102,103,104",
checkErr: func(err error) bool {
var parseErr tw.ParseError
return errors.As(err, &parseErr) && parseErr.Field() == "tribe.NumMembers" && errors.Is(parseErr, strconv.ErrSyntax)
},
},
{
name: "ERR: invalid value - Tribe.NumVillages",
respTribe: "1,name1,tag1,100,101.23,102,103,104",
checkErr: func(err error) bool {
var parseErr tw.ParseError
return errors.As(err, &parseErr) && parseErr.Field() == "tribe.NumVillages" && errors.Is(parseErr, strconv.ErrSyntax)
},
},
{
name: "ERR: invalid value - Tribe.Points",
respTribe: "1,name1,tag1,100,101,102.23,103,104",
checkErr: func(err error) bool {
var parseErr tw.ParseError
return errors.As(err, &parseErr) && parseErr.Field() == "tribe.Points" && errors.Is(parseErr, strconv.ErrSyntax)
},
},
{
name: "ERR: invalid value - Tribe.AllPoints",
respTribe: "1,name1,tag1,100,101,102,103.23,104",
checkErr: func(err error) bool {
var parseErr tw.ParseError
return errors.As(err, &parseErr) && parseErr.Field() == "tribe.AllPoints" && errors.Is(parseErr, strconv.ErrSyntax)
},
},
{
name: "ERR: invalid value - Tribe.Rank",
respTribe: "1,name1,tag1,100,101,102,103,104.23",
checkErr: func(err error) bool {
var parseErr tw.ParseError
return errors.As(err, &parseErr) && parseErr.Field() == "tribe.Rank" && errors.Is(parseErr, strconv.ErrSyntax)
},
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
mux := http.NewServeMux()
mux.HandleFunc("/map/kill_all_tribe.txt", createHandler(tt.respOD))
mux.HandleFunc("/map/kill_att_tribe.txt", createHandler(tt.respODA))
mux.HandleFunc("/map/kill_def_tribe.txt", createHandler(tt.respODD))
mux.HandleFunc("/map/ally.txt", createHandler(tt.respTribe))
srv := httptest.NewTLSServer(mux)
defer srv.Close()
tribes, err := newTestClient(srv.Client()).GetTribes(context.Background(), srv.URL)
checkErr := func(err error) bool {
return err == nil
}
if tt.checkErr != nil {
checkErr = tt.checkErr
}
assert.True(t, checkErr(err))
assert.Len(t, tribes, len(tt.expectedTribes))
for _, tribe := range tt.expectedTribes {
var expectedTribe domain.BaseTribe
for _, tribe2 := range tribes {
if tribe.ID == tribe2.ID {
expectedTribe = tribe2
break
}
}
assert.Equal(t, expectedTribe, tribe)
}
})
}
}
func TestClient_GetPlayers(t *testing.T) {
t.Parallel()
tests := []struct {
name string
respPlayer string
respOD string
respODA string
respODD string
respODS string
checkErr func(err error) bool
expectedPlayers []domain.BasePlayer
}{
{
name: "OK",
respPlayer: "1,name%201,123,124,125,126\n2,name2,256,257,258,259\n3,name3,356,357,358,359\n4,name4,456,457,458,459",
respOD: "1,1,1001\n2,2,252\n3,3,125",
respODA: "1,1,1000\n2,2,253\n3,3,100",
respODD: "1,1,1002\n2,2,251\n3,3,155",
respODS: "1,1,1003\n2,2,250\n3,3,166",
expectedPlayers: []domain.BasePlayer{
{
ID: 1,
Name: "name 1",
TribeID: 123,
NumVillages: 124,
Points: 125,
Rank: 126,
OpponentsDefeated: domain.OpponentsDefeated{
RankAtt: 1,
ScoreAtt: 1000,
RankDef: 1,
ScoreDef: 1002,
RankSup: 1,
ScoreSup: 1003,
RankTotal: 1,
ScoreTotal: 1001,
},
},
{
ID: 2,
Name: "name2",
TribeID: 256,
NumVillages: 257,
Points: 258,
Rank: 259,
OpponentsDefeated: domain.OpponentsDefeated{
RankAtt: 2,
ScoreAtt: 253,
RankDef: 2,
ScoreDef: 251,
RankSup: 2,
ScoreSup: 250,
RankTotal: 2,
ScoreTotal: 252,
},
},
{
ID: 3,
Name: "name3",
TribeID: 356,
NumVillages: 357,
Points: 358,
Rank: 359,
OpponentsDefeated: domain.OpponentsDefeated{
RankAtt: 3,
ScoreAtt: 100,
RankDef: 3,
ScoreDef: 155,
RankSup: 3,
ScoreSup: 166,
RankTotal: 3,
ScoreTotal: 125,
},
},
{
ID: 4,
Name: "name4",
TribeID: 456,
NumVillages: 457,
Points: 458,
Rank: 459,
OpponentsDefeated: domain.OpponentsDefeated{},
},
},
},
{
name: "ERR: invalid value - OD.Rank",
respOD: "test,1,1001",
checkErr: func(err error) bool {
var parseErr tw.ParseError
return errors.As(err, &parseErr) && parseErr.Field() == "odRecord.Rank" && errors.Is(parseErr, strconv.ErrSyntax)
},
},
{
name: "ERR: invalid value - OD.ID",
respOD: "1,test,1001",
checkErr: func(err error) bool {
var parseErr tw.ParseError
return errors.As(err, &parseErr) && parseErr.Field() == "odRecord.ID" && errors.Is(parseErr, strconv.ErrSyntax)
},
},
{
name: "ERR: invalid value - OD.Score",
respOD: "1,1,test",
checkErr: func(err error) bool {
var parseErr tw.ParseError
return errors.As(err, &parseErr) && parseErr.Field() == "odRecord.Score" && errors.Is(parseErr, strconv.ErrSyntax)
},
},
{
name: "ERR: invalid value - ODA.Rank",
respODA: "test,1,1001",
checkErr: func(err error) bool {
var parseErr tw.ParseError
return errors.As(err, &parseErr) && parseErr.Field() == "odRecord.Rank" && errors.Is(parseErr, strconv.ErrSyntax)
},
},
{
name: "ERR: invalid value - ODA.ID",
respODA: "1,test,1001",
checkErr: func(err error) bool {
var parseErr tw.ParseError
return errors.As(err, &parseErr) && parseErr.Field() == "odRecord.ID" && errors.Is(parseErr, strconv.ErrSyntax)
},
},
{
name: "ERR: invalid value - ODA.Score",
respODA: "1,1,test",
checkErr: func(err error) bool {
var parseErr tw.ParseError
return errors.As(err, &parseErr) && parseErr.Field() == "odRecord.Score" && errors.Is(parseErr, strconv.ErrSyntax)
},
},
{
name: "ERR: invalid value - ODD.Rank",
respODD: "test,1,1001",
checkErr: func(err error) bool {
var parseErr tw.ParseError
return errors.As(err, &parseErr) && parseErr.Field() == "odRecord.Rank" && errors.Is(parseErr, strconv.ErrSyntax)
},
},
{
name: "ERR: invalid value - ODD.ID",
respODD: "1,test,1001",
checkErr: func(err error) bool {
var parseErr tw.ParseError
return errors.As(err, &parseErr) && parseErr.Field() == "odRecord.ID" && errors.Is(parseErr, strconv.ErrSyntax)
},
},
{
name: "ERR: invalid value - ODD.Score",
respODD: "1,1,test",
checkErr: func(err error) bool {
var parseErr tw.ParseError
return errors.As(err, &parseErr) && parseErr.Field() == "odRecord.Score" && errors.Is(parseErr, strconv.ErrSyntax)
},
},
{
name: "ERR: invalid value - ODS.Rank",
respODS: "test,1,1001",
checkErr: func(err error) bool {
var parseErr tw.ParseError
return errors.As(err, &parseErr) && parseErr.Field() == "odRecord.Rank" && errors.Is(parseErr, strconv.ErrSyntax)
},
},
{
name: "ERR: invalid value - ODS.ID",
respODS: "1,test,1001",
checkErr: func(err error) bool {
var parseErr tw.ParseError
return errors.As(err, &parseErr) && parseErr.Field() == "odRecord.ID" && errors.Is(parseErr, strconv.ErrSyntax)
},
},
{
name: "ERR: invalid value - ODS.Score",
respODS: "1,1,test",
checkErr: func(err error) bool {
var parseErr tw.ParseError
return errors.As(err, &parseErr) && parseErr.Field() == "odRecord.Score" && errors.Is(parseErr, strconv.ErrSyntax)
},
},
{
name: "ERR: wrong number of fields 1",
respPlayer: "1,name%201,123,124,125",
checkErr: func(err error) bool {
return errors.Is(err, csv.ErrFieldCount)
},
},
{
name: "ERR: wrong number of fields 2",
respPlayer: "1,name%201,123,124,125,126,127",
checkErr: func(err error) bool {
return errors.Is(err, csv.ErrFieldCount)
},
},
{
name: "ERR: invalid value - Player.ID",
respPlayer: "1.25,name,123,124,125,126",
checkErr: func(err error) bool {
var parseErr tw.ParseError
return errors.As(err, &parseErr) && parseErr.Field() == "player.ID" && errors.Is(parseErr, strconv.ErrSyntax)
},
},
{
name: "ERR: invalid value - Player.TribeID",
respPlayer: "1,name,1.23,124,125,126",
checkErr: func(err error) bool {
var parseErr tw.ParseError
return errors.As(err, &parseErr) && parseErr.Field() == "player.TribeID" && errors.Is(parseErr, strconv.ErrSyntax)
},
},
{
name: "ERR: invalid value - Player.NumVillages",
respPlayer: "1,name,123,1.24,125,126",
checkErr: func(err error) bool {
var parseErr tw.ParseError
return errors.As(err, &parseErr) && parseErr.Field() == "player.NumVillages" && errors.Is(parseErr, strconv.ErrSyntax)
},
},
{
name: "ERR: invalid value - Player.Points",
respPlayer: "1,name,123,124,1.25,126",
checkErr: func(err error) bool {
var parseErr tw.ParseError
return errors.As(err, &parseErr) && parseErr.Field() == "player.Points" && errors.Is(parseErr, strconv.ErrSyntax)
},
},
{
name: "ERR: invalid value - Player.Rank",
respPlayer: "1,name,123,124,125,1.26",
checkErr: func(err error) bool {
var parseErr tw.ParseError
return errors.As(err, &parseErr) && parseErr.Field() == "player.Rank" && errors.Is(parseErr, strconv.ErrSyntax)
},
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
mux := http.NewServeMux()
mux.HandleFunc("/map/kill_all.txt", createHandler(tt.respOD))
mux.HandleFunc("/map/kill_att.txt", createHandler(tt.respODA))
mux.HandleFunc("/map/kill_def.txt", createHandler(tt.respODD))
mux.HandleFunc("/map/kill_sup.txt", createHandler(tt.respODS))
mux.HandleFunc("/map/player.txt", createHandler(tt.respPlayer))
srv := httptest.NewTLSServer(mux)
defer srv.Close()
players, err := newTestClient(srv.Client()).GetPlayers(context.Background(), srv.URL)
checkErr := func(err error) bool {
return err == nil
}
if tt.checkErr != nil {
checkErr = tt.checkErr
}
assert.True(t, checkErr(err))
assert.Len(t, players, len(tt.expectedPlayers))
for _, player1 := range tt.expectedPlayers {
var expectedPlayer domain.BasePlayer
for _, player2 := range players {
if player1.ID == player2.ID {
expectedPlayer = player2
break
}
}
assert.Equal(t, expectedPlayer, player1)
}
})
}
}
func TestClient_GetVillages(t *testing.T) {
t.Parallel()
tests := []struct {
name string
resp string
checkErr func(err error) bool
expectedVillages []domain.BaseVillage
}{
{
name: "OK",
resp: "123,village%201,500,501,502,503,504\n124,village 2,100,201,102,103,104",
expectedVillages: []domain.BaseVillage{
{
ID: 123,
Name: "village 1",
X: 500,
Y: 501,
Continent: "K55",
PlayerID: 502,
Points: 503,
Bonus: 504,
},
{
ID: 124,
Name: "village 2",
X: 100,
Y: 201,
Continent: "K21",
PlayerID: 102,
Points: 103,
Bonus: 104,
},
},
},
{
name: "ERR: wrong number of fields 1",
resp: "123,village 1,500,501,502,503",
checkErr: func(err error) bool {
return errors.Is(err, csv.ErrFieldCount)
},
},
{
name: "ERR: wrong number of fields 2",
resp: "123,village 1,500,501,502,503,504,505",
checkErr: func(err error) bool {
return errors.Is(err, csv.ErrFieldCount)
},
},
{
name: "ERR: invalid value - Village.ID",
resp: "123.23,village 1,500,501,502,503,504",
checkErr: func(err error) bool {
var parseErr tw.ParseError
return errors.As(err, &parseErr) && parseErr.Field() == "village.ID" && errors.Is(parseErr, strconv.ErrSyntax)
},
},
{
name: "ERR: invalid value - Village.X",
resp: "123,village 1,123.23,501,502,503,504",
checkErr: func(err error) bool {
var parseErr tw.ParseError
return errors.As(err, &parseErr) && parseErr.Field() == "village.X" && errors.Is(parseErr, strconv.ErrSyntax)
},
},
{
name: "ERR: invalid value - Village.Y",
resp: "123,village 1,500,123.23,502,503,504",
checkErr: func(err error) bool {
var parseErr tw.ParseError
return errors.As(err, &parseErr) && parseErr.Field() == "village.Y" && errors.Is(parseErr, strconv.ErrSyntax)
},
},
{
name: "ERR: invalid value - Village.PlayerID",
resp: "123,village 1,500,501,123.23,503,504",
checkErr: func(err error) bool {
var parseErr tw.ParseError
return errors.As(err, &parseErr) && parseErr.Field() == "village.PlayerID" && errors.Is(parseErr, strconv.ErrSyntax)
},
},
{
name: "ERR: invalid value - Village.Points",
resp: "123,village 1,500,501,502,123.23,504",
checkErr: func(err error) bool {
var parseErr tw.ParseError
return errors.As(err, &parseErr) && parseErr.Field() == "village.Points" && errors.Is(parseErr, strconv.ErrSyntax)
},
},
{
name: "ERR: invalid value - Village.Bonus",
resp: "123,village 1,500,501,502,503,123.23",
checkErr: func(err error) bool {
var parseErr tw.ParseError
return errors.As(err, &parseErr) && parseErr.Field() == "village.Bonus" && errors.Is(parseErr, strconv.ErrSyntax)
},
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
mux := http.NewServeMux()
mux.HandleFunc("/map/village.txt", createHandler(tt.resp))
srv := httptest.NewTLSServer(mux)
defer srv.Close()
villages, err := newTestClient(srv.Client()).GetVillages(context.Background(), srv.URL)
checkErr := func(err error) bool {
return err == nil
}
if tt.checkErr != nil {
checkErr = tt.checkErr
}
assert.True(t, checkErr(err))
assert.Len(t, villages, len(tt.expectedVillages))
for _, village := range tt.expectedVillages {
var expectedVillage domain.BaseVillage
for _, village2 := range villages {
if village.ID == village2.ID {
expectedVillage = village2
break
}
}
assert.Equal(t, expectedVillage, village)
}
})
}
}
func newTestClient(hc *http.Client) *tw.Client {
return tw.NewClient(tw.WithHTTPClient(hc), tw.WithUserAgent(testUserAgent))
}
func createHandler(result string) func(w http.ResponseWriter, r *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodGet {
w.WriteHeader(http.StatusMethodNotAllowed)
return
}
if r.Header.Get("User-Agent") != testUserAgent {
w.WriteHeader(http.StatusBadRequest)
return
}
if _, err := w.Write([]byte(result)); err != nil {
w.WriteHeader(http.StatusInternalServerError)
}
}
}
func createConfigHandler(funcName, result string) func(w http.ResponseWriter, r *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodGet {
w.WriteHeader(http.StatusMethodNotAllowed)
return
}
if r.Header.Get("User-Agent") != testUserAgent {
w.WriteHeader(http.StatusBadRequest)
return
}
if r.URL.Query().Get("func") != funcName {
w.WriteHeader(http.StatusNotFound)
return
}
w.Header().Set("Content-Type", "text/xml;charset=utf-8")
_, err := w.Write([]byte(result))
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
}
}
}