Refactor Docker and Makefile configurations for improved build processes
- Updated docker-compose.tools.yml to mount source code at /src and set working directory for backend tools, ensuring proper Go module caching. - Modified Dockerfile.tools to install the latest golangci-lint version compatible with Go 1.24 and adjusted working directory for build-time operations. - Enhanced Makefile to build backend tools before running tests and linting, ensuring dependencies are up-to-date and improving overall workflow efficiency. - Refactored test and handler files to include error handling for database operations, enhancing reliability and debugging capabilities.
This commit is contained in:
@@ -66,7 +66,7 @@ func (h *Handlers) clientLocate(rw http.ResponseWriter, req *http.Request) {
|
||||
}
|
||||
rw.Header().Set("Content-Type", "text/plain")
|
||||
rw.WriteHeader(http.StatusOK)
|
||||
rw.Write([]byte(result))
|
||||
_, _ = rw.Write([]byte(result))
|
||||
}
|
||||
|
||||
func (h *Handlers) clientGridUpdate(rw http.ResponseWriter, req *http.Request) {
|
||||
@@ -85,7 +85,7 @@ func (h *Handlers) clientGridUpdate(rw http.ResponseWriter, req *http.Request) {
|
||||
}
|
||||
rw.Header().Set("Content-Type", "application/json")
|
||||
rw.WriteHeader(http.StatusOK)
|
||||
json.NewEncoder(rw).Encode(result.Response)
|
||||
_ = json.NewEncoder(rw).Encode(result.Response)
|
||||
}
|
||||
|
||||
func (h *Handlers) clientGridUpload(rw http.ResponseWriter, req *http.Request) {
|
||||
|
||||
@@ -64,9 +64,11 @@ func (env *testEnv) createUser(t *testing.T, username, password string, auths ap
|
||||
hash, _ := bcrypt.GenerateFromPassword([]byte(password), bcrypt.MinCost)
|
||||
u := app.User{Pass: hash, Auths: auths}
|
||||
raw, _ := json.Marshal(u)
|
||||
env.st.Update(context.Background(), func(tx *bbolt.Tx) error {
|
||||
if err := env.st.Update(context.Background(), func(tx *bbolt.Tx) error {
|
||||
return env.st.PutUser(tx, username, raw)
|
||||
})
|
||||
}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func (env *testEnv) loginSession(t *testing.T, username string) string {
|
||||
@@ -90,7 +92,7 @@ func TestAPISetup_NoUsers(t *testing.T) {
|
||||
}
|
||||
|
||||
var resp struct{ SetupRequired bool }
|
||||
json.NewDecoder(rr.Body).Decode(&resp)
|
||||
_ = json.NewDecoder(rr.Body).Decode(&resp)
|
||||
if !resp.SetupRequired {
|
||||
t.Fatal("expected setupRequired=true")
|
||||
}
|
||||
@@ -105,7 +107,7 @@ func TestAPISetup_WithUsers(t *testing.T) {
|
||||
env.h.APISetup(rr, req)
|
||||
|
||||
var resp struct{ SetupRequired bool }
|
||||
json.NewDecoder(rr.Body).Decode(&resp)
|
||||
_ = json.NewDecoder(rr.Body).Decode(&resp)
|
||||
if resp.SetupRequired {
|
||||
t.Fatal("expected setupRequired=false with users")
|
||||
}
|
||||
@@ -196,7 +198,7 @@ func TestAPIMe_Authenticated(t *testing.T) {
|
||||
Username string `json:"username"`
|
||||
Auths []string `json:"auths"`
|
||||
}
|
||||
json.NewDecoder(rr.Body).Decode(&resp)
|
||||
_ = json.NewDecoder(rr.Body).Decode(&resp)
|
||||
if resp.Username != "alice" {
|
||||
t.Fatalf("expected alice, got %s", resp.Username)
|
||||
}
|
||||
@@ -245,7 +247,7 @@ func TestAPIMeTokens_Authenticated(t *testing.T) {
|
||||
t.Fatalf("expected 200, got %d: %s", rr.Code, rr.Body.String())
|
||||
}
|
||||
var resp struct{ Tokens []string }
|
||||
json.NewDecoder(rr.Body).Decode(&resp)
|
||||
_ = json.NewDecoder(rr.Body).Decode(&resp)
|
||||
if len(resp.Tokens) != 1 {
|
||||
t.Fatalf("expected 1 token, got %d", len(resp.Tokens))
|
||||
}
|
||||
@@ -396,7 +398,7 @@ func TestAdminSettings(t *testing.T) {
|
||||
DefaultHide bool `json:"defaultHide"`
|
||||
Title string `json:"title"`
|
||||
}
|
||||
json.NewDecoder(rr3.Body).Decode(&resp)
|
||||
_ = json.NewDecoder(rr3.Body).Decode(&resp)
|
||||
if resp.Prefix != "pfx" || !resp.DefaultHide || resp.Title != "New Title" {
|
||||
t.Fatalf("unexpected settings: %+v", resp)
|
||||
}
|
||||
@@ -493,7 +495,7 @@ func TestAPIGetChars_NoMarkersAuth(t *testing.T) {
|
||||
t.Fatalf("expected 200, got %d", rr.Code)
|
||||
}
|
||||
var chars []interface{}
|
||||
json.NewDecoder(rr.Body).Decode(&chars)
|
||||
_ = json.NewDecoder(rr.Body).Decode(&chars)
|
||||
if len(chars) != 0 {
|
||||
t.Fatal("expected empty array without markers auth")
|
||||
}
|
||||
@@ -511,7 +513,7 @@ func TestAPIGetMarkers_NoMarkersAuth(t *testing.T) {
|
||||
t.Fatalf("expected 200, got %d", rr.Code)
|
||||
}
|
||||
var markers []interface{}
|
||||
json.NewDecoder(rr.Body).Decode(&markers)
|
||||
_ = json.NewDecoder(rr.Body).Decode(&markers)
|
||||
if len(markers) != 0 {
|
||||
t.Fatal("expected empty array without markers auth")
|
||||
}
|
||||
@@ -583,7 +585,7 @@ func TestAdminUserByName(t *testing.T) {
|
||||
Username string `json:"username"`
|
||||
Auths []string `json:"auths"`
|
||||
}
|
||||
json.NewDecoder(rr.Body).Decode(&resp)
|
||||
_ = json.NewDecoder(rr.Body).Decode(&resp)
|
||||
if resp.Username != "bob" {
|
||||
t.Fatalf("expected bob, got %s", resp.Username)
|
||||
}
|
||||
@@ -613,9 +615,11 @@ func TestClientRouter_Locate(t *testing.T) {
|
||||
}
|
||||
gd := app.GridData{ID: "g1", Map: 1, Coord: app.Coord{X: 2, Y: 3}}
|
||||
raw, _ := json.Marshal(gd)
|
||||
env.st.Update(ctx, func(tx *bbolt.Tx) error {
|
||||
if err := env.st.Update(ctx, func(tx *bbolt.Tx) error {
|
||||
return env.st.PutGrid(tx, "g1", raw)
|
||||
})
|
||||
}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
req := httptest.NewRequest(http.MethodGet, "/client/"+tokens[0]+"/locate?gridID=g1", nil)
|
||||
rr := httptest.NewRecorder()
|
||||
|
||||
@@ -55,7 +55,7 @@ func (h *Handlers) WatchGridUpdates(rw http.ResponseWriter, req *http.Request) {
|
||||
tileCache := []services.TileCache{}
|
||||
raw, _ := json.Marshal(tileCache)
|
||||
fmt.Fprint(rw, "data: ")
|
||||
rw.Write(raw)
|
||||
_, _ = rw.Write(raw)
|
||||
fmt.Fprint(rw, "\n\n")
|
||||
flusher.Flush()
|
||||
|
||||
@@ -93,13 +93,13 @@ func (h *Handlers) WatchGridUpdates(rw http.ResponseWriter, req *http.Request) {
|
||||
}
|
||||
fmt.Fprint(rw, "event: merge\n")
|
||||
fmt.Fprint(rw, "data: ")
|
||||
rw.Write(raw)
|
||||
_, _ = rw.Write(raw)
|
||||
fmt.Fprint(rw, "\n\n")
|
||||
flusher.Flush()
|
||||
case <-ticker.C:
|
||||
raw, _ := json.Marshal(tileCache)
|
||||
fmt.Fprint(rw, "data: ")
|
||||
rw.Write(raw)
|
||||
_, _ = rw.Write(raw)
|
||||
fmt.Fprint(rw, "\n\n")
|
||||
tileCache = tileCache[:0]
|
||||
flusher.Flush()
|
||||
@@ -152,7 +152,7 @@ func (h *Handlers) GridTile(rw http.ResponseWriter, req *http.Request) {
|
||||
rw.Header().Set("Content-Type", "image/png")
|
||||
rw.Header().Set("Cache-Control", "private, max-age=3600")
|
||||
rw.WriteHeader(http.StatusOK)
|
||||
rw.Write(transparentPNG)
|
||||
_, _ = rw.Write(transparentPNG)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -172,7 +172,9 @@ var migrations = []func(tx *bbolt.Tx) error{
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
users.Put(k, raw)
|
||||
if err := users.Put(k, raw); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
@@ -26,7 +26,7 @@ func TestRunMigrations_FreshDB(t *testing.T) {
|
||||
t.Fatalf("migrations failed on fresh DB: %v", err)
|
||||
}
|
||||
|
||||
db.View(func(tx *bbolt.Tx) error {
|
||||
if err := db.View(func(tx *bbolt.Tx) error {
|
||||
b := tx.Bucket(store.BucketConfig)
|
||||
if b == nil {
|
||||
t.Fatal("expected config bucket after migrations")
|
||||
@@ -40,13 +40,15 @@ func TestRunMigrations_FreshDB(t *testing.T) {
|
||||
t.Fatalf("expected default title, got %s", title)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if tx, _ := db.Begin(false); tx != nil {
|
||||
if tx.Bucket(store.BucketOAuthStates) == nil {
|
||||
t.Fatal("expected oauth_states bucket after migrations")
|
||||
}
|
||||
tx.Rollback()
|
||||
_ = tx.Rollback()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,7 +63,7 @@ func TestRunMigrations_Idempotent(t *testing.T) {
|
||||
t.Fatalf("second run failed: %v", err)
|
||||
}
|
||||
|
||||
db.View(func(tx *bbolt.Tx) error {
|
||||
if err := db.View(func(tx *bbolt.Tx) error {
|
||||
b := tx.Bucket(store.BucketConfig)
|
||||
if b == nil {
|
||||
t.Fatal("expected config bucket")
|
||||
@@ -71,7 +73,9 @@ func TestRunMigrations_Idempotent(t *testing.T) {
|
||||
t.Fatal("expected version key")
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunMigrations_SetsVersion(t *testing.T) {
|
||||
@@ -81,11 +85,13 @@ func TestRunMigrations_SetsVersion(t *testing.T) {
|
||||
}
|
||||
|
||||
var version string
|
||||
db.View(func(tx *bbolt.Tx) error {
|
||||
if err := db.View(func(tx *bbolt.Tx) error {
|
||||
b := tx.Bucket(store.BucketConfig)
|
||||
version = string(b.Get([]byte("version")))
|
||||
return nil
|
||||
})
|
||||
}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if version == "" || version == "0" {
|
||||
t.Fatalf("expected non-zero version, got %q", version)
|
||||
|
||||
@@ -101,7 +101,9 @@ func (s *AdminService) DeleteUser(ctx context.Context, username string) error {
|
||||
return err
|
||||
}
|
||||
for _, tok := range u.Tokens {
|
||||
s.st.DeleteToken(tx, tok)
|
||||
if err := s.st.DeleteToken(tx, tok); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return s.st.DeleteUser(tx, username)
|
||||
@@ -129,17 +131,25 @@ func (s *AdminService) GetSettings(ctx context.Context) (prefix string, defaultH
|
||||
func (s *AdminService) UpdateSettings(ctx context.Context, prefix *string, defaultHide *bool, title *string) error {
|
||||
return s.st.Update(ctx, func(tx *bbolt.Tx) error {
|
||||
if prefix != nil {
|
||||
s.st.PutConfig(tx, "prefix", []byte(*prefix))
|
||||
if err := s.st.PutConfig(tx, "prefix", []byte(*prefix)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if defaultHide != nil {
|
||||
if *defaultHide {
|
||||
s.st.PutConfig(tx, "defaultHide", []byte("1"))
|
||||
if err := s.st.PutConfig(tx, "defaultHide", []byte("1")); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
s.st.DeleteConfig(tx, "defaultHide")
|
||||
if err := s.st.DeleteConfig(tx, "defaultHide"); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
if title != nil {
|
||||
s.st.PutConfig(tx, "title", []byte(*title))
|
||||
if err := s.st.PutConfig(tx, "title", []byte(*title)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
@@ -264,7 +274,9 @@ func (s *AdminService) WipeTile(ctx context.Context, mapid, x, y int) error {
|
||||
return err
|
||||
}
|
||||
for _, id := range ids {
|
||||
grids.Delete(id)
|
||||
if err := grids.Delete(id); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}); err != nil {
|
||||
@@ -310,7 +322,9 @@ func (s *AdminService) SetCoords(ctx context.Context, mapid, fx, fy, tx2, ty int
|
||||
g.Coord.X += diff.X
|
||||
g.Coord.Y += diff.Y
|
||||
raw, _ := json.Marshal(g)
|
||||
grids.Put(k, raw)
|
||||
if err := grids.Put(k, raw); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}); err != nil {
|
||||
@@ -367,7 +381,9 @@ func (s *AdminService) HideMarker(ctx context.Context, markerID string) error {
|
||||
}
|
||||
m.Hidden = true
|
||||
raw, _ = json.Marshal(m)
|
||||
grid.Put(key, raw)
|
||||
if err := grid.Put(key, raw); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
@@ -234,7 +234,7 @@ func TestToggleMapHidden(t *testing.T) {
|
||||
admin, _ := newTestAdmin(t)
|
||||
ctx := context.Background()
|
||||
|
||||
admin.UpdateMap(ctx, 1, "world", false, false)
|
||||
_ = admin.UpdateMap(ctx, 1, "world", false, false)
|
||||
|
||||
mi, err := admin.ToggleMapHidden(ctx, 1)
|
||||
if err != nil {
|
||||
@@ -257,19 +257,27 @@ func TestWipe(t *testing.T) {
|
||||
admin, st := newTestAdmin(t)
|
||||
ctx := context.Background()
|
||||
|
||||
st.Update(ctx, func(tx *bbolt.Tx) error {
|
||||
st.PutGrid(tx, "g1", []byte("data"))
|
||||
st.PutMap(tx, 1, []byte("data"))
|
||||
st.PutTile(tx, 1, 0, "0_0", []byte("data"))
|
||||
st.CreateMarkersBuckets(tx)
|
||||
return nil
|
||||
})
|
||||
if err := st.Update(ctx, func(tx *bbolt.Tx) error {
|
||||
if err := st.PutGrid(tx, "g1", []byte("data")); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := st.PutMap(tx, 1, []byte("data")); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := st.PutTile(tx, 1, 0, "0_0", []byte("data")); err != nil {
|
||||
return err
|
||||
}
|
||||
_, _, err := st.CreateMarkersBuckets(tx)
|
||||
return err
|
||||
}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err := admin.Wipe(ctx); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
st.View(ctx, func(tx *bbolt.Tx) error {
|
||||
if err := st.View(ctx, func(tx *bbolt.Tx) error {
|
||||
if st.GetGrid(tx, "g1") != nil {
|
||||
t.Fatal("expected grids wiped")
|
||||
}
|
||||
@@ -283,7 +291,9 @@ func TestWipe(t *testing.T) {
|
||||
t.Fatal("expected markers wiped")
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetMap_NotFound(t *testing.T) {
|
||||
|
||||
@@ -53,7 +53,7 @@ func (s *AuthService) GetSession(ctx context.Context, req *http.Request) *app.Se
|
||||
return nil
|
||||
}
|
||||
var sess *app.Session
|
||||
s.st.View(ctx, func(tx *bbolt.Tx) error {
|
||||
if err := s.st.View(ctx, func(tx *bbolt.Tx) error {
|
||||
raw := s.st.GetSession(tx, c.Value)
|
||||
if raw == nil {
|
||||
return nil
|
||||
@@ -77,7 +77,9 @@ func (s *AuthService) GetSession(ctx context.Context, req *http.Request) *app.Se
|
||||
}
|
||||
sess.Auths = u.Auths
|
||||
return nil
|
||||
})
|
||||
}); err != nil {
|
||||
return nil
|
||||
}
|
||||
return sess
|
||||
}
|
||||
|
||||
@@ -165,7 +167,7 @@ func (s *AuthService) GetUserByUsername(ctx context.Context, username string) *a
|
||||
// SetupRequired returns true if no users exist (first run).
|
||||
func (s *AuthService) SetupRequired(ctx context.Context) bool {
|
||||
var required bool
|
||||
s.st.View(ctx, func(tx *bbolt.Tx) error {
|
||||
_ = s.st.View(ctx, func(tx *bbolt.Tx) error {
|
||||
if s.st.UserCount(tx) == 0 {
|
||||
required = true
|
||||
}
|
||||
@@ -181,7 +183,7 @@ func (s *AuthService) BootstrapAdmin(ctx context.Context, username, pass, bootst
|
||||
}
|
||||
var created bool
|
||||
var u *app.User
|
||||
s.st.Update(ctx, func(tx *bbolt.Tx) error {
|
||||
if err := s.st.Update(ctx, func(tx *bbolt.Tx) error {
|
||||
if s.st.GetUser(tx, "admin") != nil {
|
||||
return nil
|
||||
}
|
||||
@@ -200,7 +202,9 @@ func (s *AuthService) BootstrapAdmin(ctx context.Context, username, pass, bootst
|
||||
created = true
|
||||
u = &user
|
||||
return nil
|
||||
})
|
||||
}); err != nil {
|
||||
return nil
|
||||
}
|
||||
if created {
|
||||
return u
|
||||
}
|
||||
@@ -239,7 +243,7 @@ func (s *AuthService) GenerateTokenForUser(ctx context.Context, username string)
|
||||
}
|
||||
token := hex.EncodeToString(tokenRaw)
|
||||
var tokens []string
|
||||
s.st.Update(ctx, func(tx *bbolt.Tx) error {
|
||||
_ = s.st.Update(ctx, func(tx *bbolt.Tx) error {
|
||||
uRaw := s.st.GetUser(tx, username)
|
||||
u := app.User{}
|
||||
if uRaw != nil {
|
||||
@@ -250,7 +254,9 @@ func (s *AuthService) GenerateTokenForUser(ctx context.Context, username string)
|
||||
u.Tokens = append(u.Tokens, token)
|
||||
tokens = u.Tokens
|
||||
buf, _ := json.Marshal(u)
|
||||
s.st.PutUser(tx, username, buf)
|
||||
if err := s.st.PutUser(tx, username, buf); err != nil {
|
||||
return err
|
||||
}
|
||||
return s.st.PutToken(tx, token, username)
|
||||
})
|
||||
return tokens
|
||||
@@ -522,7 +528,9 @@ func (s *AuthService) findOrCreateOAuthUser(ctx context.Context, provider, sub,
|
||||
user.Email = email
|
||||
}
|
||||
raw, _ = json.Marshal(user)
|
||||
s.st.PutUser(tx, username, raw)
|
||||
if err := s.st.PutUser(tx, username, raw); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -41,9 +41,11 @@ func createUser(t *testing.T, st *store.Store, username, password string, auths
|
||||
}
|
||||
u := app.User{Pass: hash, Auths: auths}
|
||||
raw, _ := json.Marshal(u)
|
||||
st.Update(context.Background(), func(tx *bbolt.Tx) error {
|
||||
if err := st.Update(context.Background(), func(tx *bbolt.Tx) error {
|
||||
return st.PutUser(tx, username, raw)
|
||||
})
|
||||
}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetupRequired_EmptyDB(t *testing.T) {
|
||||
@@ -246,9 +248,11 @@ func TestGetUserTokensAndPrefix(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
createUser(t, st, "alice", "pass", app.Auths{app.AUTH_UPLOAD})
|
||||
|
||||
st.Update(ctx, func(tx *bbolt.Tx) error {
|
||||
if err := st.Update(ctx, func(tx *bbolt.Tx) error {
|
||||
return st.PutConfig(tx, "prefix", []byte("myprefix"))
|
||||
})
|
||||
}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
auth.GenerateTokenForUser(ctx, "alice")
|
||||
tokens, prefix := auth.GetUserTokensAndPrefix(ctx, "alice")
|
||||
@@ -288,9 +292,11 @@ func TestValidateClientToken_NoUploadPerm(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
createUser(t, st, "alice", "pass", app.Auths{app.AUTH_MAP})
|
||||
|
||||
st.Update(ctx, func(tx *bbolt.Tx) error {
|
||||
if err := st.Update(ctx, func(tx *bbolt.Tx) error {
|
||||
return st.PutToken(tx, "tok123", "alice")
|
||||
})
|
||||
}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
_, err := auth.ValidateClientToken(ctx, "tok123")
|
||||
if err == nil {
|
||||
|
||||
@@ -141,7 +141,9 @@ func (s *ClientService) ProcessGridUpdate(ctx context.Context, grup GridUpdate)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
grids.Put([]byte(grid), raw)
|
||||
if err := grids.Put([]byte(grid), raw); err != nil {
|
||||
return err
|
||||
}
|
||||
greq.GridRequests = append(greq.GridRequests, grid)
|
||||
}
|
||||
}
|
||||
@@ -192,7 +194,9 @@ func (s *ClientService) ProcessGridUpdate(ctx context.Context, grup GridUpdate)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
grids.Put([]byte(grid), raw)
|
||||
if err := grids.Put([]byte(grid), raw); err != nil {
|
||||
return err
|
||||
}
|
||||
greq.GridRequests = append(greq.GridRequests, grid)
|
||||
}
|
||||
}
|
||||
@@ -207,7 +211,7 @@ func (s *ClientService) ProcessGridUpdate(ctx context.Context, grup GridUpdate)
|
||||
}
|
||||
}
|
||||
if len(maps) > 1 {
|
||||
grids.ForEach(func(k, v []byte) error {
|
||||
if err := grids.ForEach(func(k, v []byte) error {
|
||||
gd := app.GridData{}
|
||||
if err := json.Unmarshal(v, &gd); err != nil {
|
||||
return err
|
||||
@@ -244,16 +248,22 @@ func (s *ClientService) ProcessGridUpdate(ctx context.Context, grup GridUpdate)
|
||||
File: td.File,
|
||||
})
|
||||
}
|
||||
grids.Put(k, raw)
|
||||
if err := grids.Put(k, raw); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
for mergeid, merge := range maps {
|
||||
if mapid == mergeid {
|
||||
continue
|
||||
}
|
||||
mapB.Delete([]byte(strconv.Itoa(mergeid)))
|
||||
if err := mapB.Delete([]byte(strconv.Itoa(mergeid))); err != nil {
|
||||
return err
|
||||
}
|
||||
slog.Info("reporting merge", "from", mergeid, "to", mapid)
|
||||
s.mapSvc.ReportMerge(mergeid, mapid, app.Coord{X: offset.X - merge.X, Y: offset.Y - merge.Y})
|
||||
}
|
||||
@@ -271,10 +281,10 @@ func (s *ClientService) ProcessGridUpdate(ctx context.Context, grup GridUpdate)
|
||||
func (s *ClientService) ProcessGridUpload(ctx context.Context, id string, extraData string, fileReader io.Reader) error {
|
||||
if extraData != "" {
|
||||
ed := ExtraData{}
|
||||
json.Unmarshal([]byte(extraData), &ed)
|
||||
_ = json.Unmarshal([]byte(extraData), &ed)
|
||||
if ed.Season == 3 {
|
||||
needTile := false
|
||||
s.st.Update(ctx, func(tx *bbolt.Tx) error {
|
||||
if err := s.st.Update(ctx, func(tx *bbolt.Tx) error {
|
||||
raw := s.st.GetGrid(tx, id)
|
||||
if raw == nil {
|
||||
return fmt.Errorf("unknown grid id: %s", id)
|
||||
@@ -301,7 +311,9 @@ func (s *ClientService) ProcessGridUpload(ctx context.Context, id string, extraD
|
||||
}
|
||||
raw, _ = json.Marshal(cur)
|
||||
return s.st.PutGrid(tx, id, raw)
|
||||
})
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if !needTile {
|
||||
slog.Debug("ignoring tile upload: winter")
|
||||
return nil
|
||||
@@ -316,7 +328,7 @@ func (s *ClientService) ProcessGridUpload(ctx context.Context, id string, extraD
|
||||
cur := app.GridData{}
|
||||
mapid := 0
|
||||
|
||||
s.st.Update(ctx, func(tx *bbolt.Tx) error {
|
||||
if err := s.st.Update(ctx, func(tx *bbolt.Tx) error {
|
||||
raw := s.st.GetGrid(tx, id)
|
||||
if raw == nil {
|
||||
return fmt.Errorf("unknown grid id: %s", id)
|
||||
@@ -331,7 +343,9 @@ func (s *ClientService) ProcessGridUpload(ctx context.Context, id string, extraD
|
||||
}
|
||||
raw, _ = json.Marshal(cur)
|
||||
return s.st.PutGrid(tx, id, raw)
|
||||
})
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if updateTile {
|
||||
gridDir := fmt.Sprintf("%s/grids", s.mapSvc.GridStorage())
|
||||
@@ -374,7 +388,7 @@ func (s *ClientService) UpdatePositions(ctx context.Context, data []byte) error
|
||||
}
|
||||
|
||||
gridDataByID := make(map[string]app.GridData)
|
||||
s.st.View(ctx, func(tx *bbolt.Tx) error {
|
||||
if err := s.st.View(ctx, func(tx *bbolt.Tx) error {
|
||||
for _, craw := range craws {
|
||||
raw := s.st.GetGrid(tx, craw.GridID)
|
||||
if raw != nil {
|
||||
@@ -385,7 +399,9 @@ func (s *ClientService) UpdatePositions(ctx context.Context, data []byte) error
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
username, _ := ctx.Value(app.ClientUsernameKey).(string)
|
||||
|
||||
@@ -478,8 +494,12 @@ func (s *ClientService) UploadMarkers(ctx context.Context, data []byte) error {
|
||||
Image: img,
|
||||
}
|
||||
raw, _ := json.Marshal(m)
|
||||
grid.Put(key, raw)
|
||||
idB.Put(idKey, key)
|
||||
if err := grid.Put(key, raw); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := idB.Put(idKey, key); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
@@ -58,9 +58,11 @@ func TestClientLocate_Found(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
gd := app.GridData{ID: "g1", Map: 1, Coord: app.Coord{X: 2, Y: 3}}
|
||||
raw, _ := json.Marshal(gd)
|
||||
st.Update(ctx, func(tx *bbolt.Tx) error {
|
||||
if err := st.Update(ctx, func(tx *bbolt.Tx) error {
|
||||
return st.PutGrid(tx, "g1", raw)
|
||||
})
|
||||
}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
result, err := client.Locate(ctx, "g1")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
||||
@@ -111,7 +111,7 @@ func (s *ExportService) Export(ctx context.Context, w io.Writer) error {
|
||||
if markersb != nil {
|
||||
markersgrid := markersb.Bucket(store.BucketMarkersGrid)
|
||||
if markersgrid != nil {
|
||||
markersgrid.ForEach(func(k, v []byte) error {
|
||||
if err := markersgrid.ForEach(func(k, v []byte) error {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
@@ -125,7 +125,9 @@ func (s *ExportService) Export(ctx context.Context, w io.Writer) error {
|
||||
maps[gridMap[marker.GridID]].Markers[marker.GridID] = append(maps[gridMap[marker.GridID]].Markers[marker.GridID], marker)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
@@ -218,7 +220,11 @@ func (s *ExportService) Merge(ctx context.Context, zr *zip.Reader) error {
|
||||
f.Close()
|
||||
return err
|
||||
}
|
||||
io.Copy(f, r)
|
||||
if _, err := io.Copy(f, r); err != nil {
|
||||
r.Close()
|
||||
f.Close()
|
||||
return err
|
||||
}
|
||||
r.Close()
|
||||
f.Close()
|
||||
newTiles[strings.TrimSuffix(filepath.Base(fhdr.Name), ".png")] = struct{}{}
|
||||
@@ -290,8 +296,12 @@ func (s *ExportService) processMergeJSON(
|
||||
Image: img,
|
||||
}
|
||||
raw, _ := json.Marshal(m)
|
||||
mgrid.Put(key, raw)
|
||||
idB.Put(idKey, key)
|
||||
if err := mgrid.Put(key, raw); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := idB.Put(idKey, key); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -333,7 +343,9 @@ func (s *ExportService) processMergeJSON(
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
grids.Put([]byte(grid), raw)
|
||||
if err := grids.Put([]byte(grid), raw); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -372,11 +384,13 @@ func (s *ExportService) processMergeJSON(
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
grids.Put([]byte(grid), raw)
|
||||
if err := grids.Put([]byte(grid), raw); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if len(existingMaps) > 1 {
|
||||
grids.ForEach(func(k, v []byte) error {
|
||||
if err := grids.ForEach(func(k, v []byte) error {
|
||||
gd := app.GridData{}
|
||||
if err := json.Unmarshal(v, &gd); err != nil {
|
||||
return err
|
||||
@@ -413,16 +427,22 @@ func (s *ExportService) processMergeJSON(
|
||||
File: td.File,
|
||||
})
|
||||
}
|
||||
grids.Put(k, raw)
|
||||
if err := grids.Put(k, raw); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
for mergeid, merge := range existingMaps {
|
||||
if mapid == mergeid {
|
||||
continue
|
||||
}
|
||||
mapB.Delete([]byte(strconv.Itoa(mergeid)))
|
||||
if err := mapB.Delete([]byte(strconv.Itoa(mergeid))); err != nil {
|
||||
return err
|
||||
}
|
||||
slog.Info("reporting merge", "from", mergeid, "to", mapid)
|
||||
s.mapSvc.ReportMerge(mergeid, mapid, app.Coord{X: offset.X - merge.X, Y: offset.Y - merge.Y})
|
||||
}
|
||||
|
||||
@@ -47,12 +47,14 @@ func TestExport_WithGrid(t *testing.T) {
|
||||
gdRaw, _ := json.Marshal(gd)
|
||||
mi := app.MapInfo{ID: 1, Name: "test", Hidden: false}
|
||||
miRaw, _ := json.Marshal(mi)
|
||||
st.Update(ctx, func(tx *bbolt.Tx) error {
|
||||
if err := st.Update(ctx, func(tx *bbolt.Tx) error {
|
||||
if err := st.PutGrid(tx, "g1", gdRaw); err != nil {
|
||||
return err
|
||||
}
|
||||
return st.PutMap(tx, 1, miRaw)
|
||||
})
|
||||
}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
var buf bytes.Buffer
|
||||
err := export.Export(ctx, &buf)
|
||||
if err != nil {
|
||||
|
||||
@@ -218,7 +218,7 @@ func (s *MapService) getSubTiles(ctx context.Context, mapid int, c app.Coord, z
|
||||
|
||||
// SaveTile persists a tile and broadcasts the update.
|
||||
func (s *MapService) SaveTile(ctx context.Context, mapid int, c app.Coord, z int, f string, t int64) {
|
||||
s.st.Update(ctx, func(tx *bbolt.Tx) error {
|
||||
_ = s.st.Update(ctx, func(tx *bbolt.Tx) error {
|
||||
td := &app.TileData{
|
||||
MapID: mapid,
|
||||
Coord: c,
|
||||
@@ -293,7 +293,7 @@ func (s *MapService) RebuildZooms(ctx context.Context) error {
|
||||
if b == nil {
|
||||
return nil
|
||||
}
|
||||
b.ForEach(func(k, v []byte) error {
|
||||
if err := b.ForEach(func(k, v []byte) error {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
@@ -306,8 +306,12 @@ func (s *MapService) RebuildZooms(ctx context.Context) error {
|
||||
needProcess[zoomproc{grid.Coord.Parent(), grid.Map}] = struct{}{}
|
||||
saveGrid[zoomproc{grid.Coord, grid.Map}] = grid.ID
|
||||
return nil
|
||||
})
|
||||
tx.DeleteBucket(store.BucketTiles)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := tx.DeleteBucket(store.BucketTiles); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}); err != nil {
|
||||
slog.Error("RebuildZooms: failed to update store", "error", err)
|
||||
@@ -364,7 +368,7 @@ func (s *MapService) WatchMerges() chan *app.Merge {
|
||||
// GetAllTileCache returns all tiles for the initial SSE cache dump.
|
||||
func (s *MapService) GetAllTileCache(ctx context.Context) []TileCache {
|
||||
var cache []TileCache
|
||||
s.st.View(ctx, func(tx *bbolt.Tx) error {
|
||||
_ = s.st.View(ctx, func(tx *bbolt.Tx) error {
|
||||
return s.st.ForEachTile(tx, func(mapK, zoomK, coordK, v []byte) error {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
|
||||
@@ -57,9 +57,11 @@ func TestGetConfig(t *testing.T) {
|
||||
svc, st := newTestMapService(t)
|
||||
ctx := context.Background()
|
||||
|
||||
st.Update(ctx, func(tx *bbolt.Tx) error {
|
||||
if err := st.Update(ctx, func(tx *bbolt.Tx) error {
|
||||
return st.PutConfig(tx, "title", []byte("Test Map"))
|
||||
})
|
||||
}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
config, err := svc.GetConfig(ctx, app.Auths{app.AUTH_MAP})
|
||||
if err != nil {
|
||||
@@ -93,9 +95,11 @@ func TestGetConfig_Empty(t *testing.T) {
|
||||
func TestGetPage(t *testing.T) {
|
||||
svc, st := newTestMapService(t)
|
||||
ctx := context.Background()
|
||||
st.Update(ctx, func(tx *bbolt.Tx) error {
|
||||
if err := st.Update(ctx, func(tx *bbolt.Tx) error {
|
||||
return st.PutConfig(tx, "title", []byte("Map Page"))
|
||||
})
|
||||
}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
page, err := svc.GetPage(ctx)
|
||||
if err != nil {
|
||||
@@ -112,9 +116,11 @@ func TestGetGrid(t *testing.T) {
|
||||
|
||||
gd := app.GridData{ID: "g1", Map: 1, Coord: app.Coord{X: 5, Y: 10}}
|
||||
raw, _ := json.Marshal(gd)
|
||||
st.Update(ctx, func(tx *bbolt.Tx) error {
|
||||
if err := st.Update(ctx, func(tx *bbolt.Tx) error {
|
||||
return st.PutGrid(tx, "g1", raw)
|
||||
})
|
||||
}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
got, err := svc.GetGrid(ctx, "g1")
|
||||
if err != nil {
|
||||
@@ -158,11 +164,17 @@ func TestGetMaps_HiddenFilter(t *testing.T) {
|
||||
mi2 := app.MapInfo{ID: 2, Name: "hidden", Hidden: true}
|
||||
raw1, _ := json.Marshal(mi1)
|
||||
raw2, _ := json.Marshal(mi2)
|
||||
st.Update(ctx, func(tx *bbolt.Tx) error {
|
||||
st.PutMap(tx, 1, raw1)
|
||||
st.PutMap(tx, 2, raw2)
|
||||
if err := st.Update(ctx, func(tx *bbolt.Tx) error {
|
||||
if err := st.PutMap(tx, 1, raw1); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := st.PutMap(tx, 2, raw2); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
maps, err := svc.GetMaps(ctx, false)
|
||||
if err != nil {
|
||||
@@ -201,14 +213,18 @@ func TestGetMarkers_WithData(t *testing.T) {
|
||||
m := app.Marker{Name: "Tower", ID: 1, GridID: "g1", Position: app.Position{X: 10, Y: 20}, Image: "gfx/terobjs/mm/tower"}
|
||||
mRaw, _ := json.Marshal(m)
|
||||
|
||||
st.Update(ctx, func(tx *bbolt.Tx) error {
|
||||
st.PutGrid(tx, "g1", gdRaw)
|
||||
if err := st.Update(ctx, func(tx *bbolt.Tx) error {
|
||||
if err := st.PutGrid(tx, "g1", gdRaw); err != nil {
|
||||
return err
|
||||
}
|
||||
grid, _, err := st.CreateMarkersBuckets(tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return grid.Put([]byte("g1_10_20"), mRaw)
|
||||
})
|
||||
}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
markers, err := svc.GetMarkers(ctx)
|
||||
if err != nil {
|
||||
@@ -233,9 +249,11 @@ func TestGetTile(t *testing.T) {
|
||||
|
||||
td := app.TileData{MapID: 1, Coord: app.Coord{X: 0, Y: 0}, Zoom: 0, File: "grids/g1.png", Cache: 12345}
|
||||
raw, _ := json.Marshal(td)
|
||||
st.Update(ctx, func(tx *bbolt.Tx) error {
|
||||
if err := st.Update(ctx, func(tx *bbolt.Tx) error {
|
||||
return st.PutTile(tx, 1, 0, "0_0", raw)
|
||||
})
|
||||
}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
got := svc.GetTile(ctx, 1, app.Coord{X: 0, Y: 0}, 0)
|
||||
if got == nil {
|
||||
@@ -287,9 +305,11 @@ func TestGetAllTileCache_WithData(t *testing.T) {
|
||||
|
||||
td := app.TileData{MapID: 1, Coord: app.Coord{X: 1, Y: 2}, Zoom: 0, Cache: 999}
|
||||
raw, _ := json.Marshal(td)
|
||||
st.Update(ctx, func(tx *bbolt.Tx) error {
|
||||
if err := st.Update(ctx, func(tx *bbolt.Tx) error {
|
||||
return st.PutTile(tx, 1, 0, "1_2", raw)
|
||||
})
|
||||
}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
cache := svc.GetAllTileCache(ctx)
|
||||
if len(cache) != 1 {
|
||||
|
||||
@@ -25,12 +25,14 @@ func TestUserCRUD(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
// Verify user doesn't exist on empty DB.
|
||||
st.View(ctx, func(tx *bbolt.Tx) error {
|
||||
if err := st.View(ctx, func(tx *bbolt.Tx) error {
|
||||
if got := st.GetUser(tx, "alice"); got != nil {
|
||||
t.Fatal("expected nil user before creation")
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Create user.
|
||||
if err := st.Update(ctx, func(tx *bbolt.Tx) error {
|
||||
@@ -40,7 +42,7 @@ func TestUserCRUD(t *testing.T) {
|
||||
}
|
||||
|
||||
// Verify user exists and count is correct (separate transaction for accurate Stats).
|
||||
st.View(ctx, func(tx *bbolt.Tx) error {
|
||||
if err := st.View(ctx, func(tx *bbolt.Tx) error {
|
||||
got := st.GetUser(tx, "alice")
|
||||
if got == nil || string(got) != `{"pass":"hash"}` {
|
||||
t.Fatalf("expected user data, got %s", got)
|
||||
@@ -49,7 +51,9 @@ func TestUserCRUD(t *testing.T) {
|
||||
t.Fatalf("expected 1 user, got %d", c)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Delete user.
|
||||
if err := st.Update(ctx, func(tx *bbolt.Tx) error {
|
||||
@@ -58,31 +62,41 @@ func TestUserCRUD(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
st.View(ctx, func(tx *bbolt.Tx) error {
|
||||
if err := st.View(ctx, func(tx *bbolt.Tx) error {
|
||||
if got := st.GetUser(tx, "alice"); got != nil {
|
||||
t.Fatal("expected nil user after deletion")
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestForEachUser(t *testing.T) {
|
||||
st := newTestStore(t)
|
||||
ctx := context.Background()
|
||||
|
||||
st.Update(ctx, func(tx *bbolt.Tx) error {
|
||||
st.PutUser(tx, "alice", []byte("1"))
|
||||
st.PutUser(tx, "bob", []byte("2"))
|
||||
if err := st.Update(ctx, func(tx *bbolt.Tx) error {
|
||||
if err := st.PutUser(tx, "alice", []byte("1")); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := st.PutUser(tx, "bob", []byte("2")); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
var names []string
|
||||
st.View(ctx, func(tx *bbolt.Tx) error {
|
||||
if err := st.View(ctx, func(tx *bbolt.Tx) error {
|
||||
return st.ForEachUser(tx, func(k, _ []byte) error {
|
||||
names = append(names, string(k))
|
||||
return nil
|
||||
})
|
||||
})
|
||||
}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(names) != 2 {
|
||||
t.Fatalf("expected 2 users, got %d", len(names))
|
||||
}
|
||||
@@ -91,12 +105,14 @@ func TestForEachUser(t *testing.T) {
|
||||
func TestUserCountEmptyBucket(t *testing.T) {
|
||||
st := newTestStore(t)
|
||||
ctx := context.Background()
|
||||
st.View(ctx, func(tx *bbolt.Tx) error {
|
||||
if err := st.View(ctx, func(tx *bbolt.Tx) error {
|
||||
if c := st.UserCount(tx); c != 0 {
|
||||
t.Fatalf("expected 0 users on empty db, got %d", c)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSessionCRUD(t *testing.T) {
|
||||
@@ -211,19 +227,27 @@ func TestForEachMap(t *testing.T) {
|
||||
st := newTestStore(t)
|
||||
ctx := context.Background()
|
||||
|
||||
st.Update(ctx, func(tx *bbolt.Tx) error {
|
||||
st.PutMap(tx, 1, []byte("a"))
|
||||
st.PutMap(tx, 2, []byte("b"))
|
||||
if err := st.Update(ctx, func(tx *bbolt.Tx) error {
|
||||
if err := st.PutMap(tx, 1, []byte("a")); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := st.PutMap(tx, 2, []byte("b")); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
var count int
|
||||
st.View(ctx, func(tx *bbolt.Tx) error {
|
||||
if err := st.View(ctx, func(tx *bbolt.Tx) error {
|
||||
return st.ForEachMap(tx, func(_, _ []byte) error {
|
||||
count++
|
||||
return nil
|
||||
})
|
||||
})
|
||||
}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if count != 2 {
|
||||
t.Fatalf("expected 2 maps, got %d", count)
|
||||
}
|
||||
@@ -290,20 +314,30 @@ func TestForEachTile(t *testing.T) {
|
||||
st := newTestStore(t)
|
||||
ctx := context.Background()
|
||||
|
||||
st.Update(ctx, func(tx *bbolt.Tx) error {
|
||||
st.PutTile(tx, 1, 0, "0_0", []byte("a"))
|
||||
st.PutTile(tx, 1, 1, "0_0", []byte("b"))
|
||||
st.PutTile(tx, 2, 0, "1_1", []byte("c"))
|
||||
if err := st.Update(ctx, func(tx *bbolt.Tx) error {
|
||||
if err := st.PutTile(tx, 1, 0, "0_0", []byte("a")); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := st.PutTile(tx, 1, 1, "0_0", []byte("b")); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := st.PutTile(tx, 2, 0, "1_1", []byte("c")); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
var count int
|
||||
st.View(ctx, func(tx *bbolt.Tx) error {
|
||||
if err := st.View(ctx, func(tx *bbolt.Tx) error {
|
||||
return st.ForEachTile(tx, func(_, _, _, _ []byte) error {
|
||||
count++
|
||||
return nil
|
||||
})
|
||||
})
|
||||
}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if count != 3 {
|
||||
t.Fatalf("expected 3 tiles, got %d", count)
|
||||
}
|
||||
@@ -313,7 +347,7 @@ func TestTilesMapBucket(t *testing.T) {
|
||||
st := newTestStore(t)
|
||||
ctx := context.Background()
|
||||
|
||||
st.Update(ctx, func(tx *bbolt.Tx) error {
|
||||
if err := st.Update(ctx, func(tx *bbolt.Tx) error {
|
||||
if b := st.GetTilesMapBucket(tx, 1); b != nil {
|
||||
t.Fatal("expected nil bucket before creation")
|
||||
}
|
||||
@@ -328,31 +362,39 @@ func TestTilesMapBucket(t *testing.T) {
|
||||
t.Fatal("expected non-nil after create")
|
||||
}
|
||||
return st.DeleteTilesMapBucket(tx, 1)
|
||||
})
|
||||
}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDeleteTilesBucket(t *testing.T) {
|
||||
st := newTestStore(t)
|
||||
ctx := context.Background()
|
||||
|
||||
st.Update(ctx, func(tx *bbolt.Tx) error {
|
||||
st.PutTile(tx, 1, 0, "0_0", []byte("a"))
|
||||
if err := st.Update(ctx, func(tx *bbolt.Tx) error {
|
||||
if err := st.PutTile(tx, 1, 0, "0_0", []byte("a")); err != nil {
|
||||
return err
|
||||
}
|
||||
return st.DeleteTilesBucket(tx)
|
||||
})
|
||||
}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
st.View(ctx, func(tx *bbolt.Tx) error {
|
||||
if err := st.View(ctx, func(tx *bbolt.Tx) error {
|
||||
if got := st.GetTile(tx, 1, 0, "0_0"); got != nil {
|
||||
t.Fatal("expected nil after bucket deletion")
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMarkerBuckets(t *testing.T) {
|
||||
st := newTestStore(t)
|
||||
ctx := context.Background()
|
||||
|
||||
st.Update(ctx, func(tx *bbolt.Tx) error {
|
||||
if err := st.Update(ctx, func(tx *bbolt.Tx) error {
|
||||
if b := st.GetMarkersGridBucket(tx); b != nil {
|
||||
t.Fatal("expected nil grid bucket before creation")
|
||||
}
|
||||
@@ -376,7 +418,9 @@ func TestMarkerBuckets(t *testing.T) {
|
||||
t.Fatal("expected non-zero sequence")
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOAuthStateCRUD(t *testing.T) {
|
||||
@@ -408,23 +452,29 @@ func TestBucketExistsAndDelete(t *testing.T) {
|
||||
st := newTestStore(t)
|
||||
ctx := context.Background()
|
||||
|
||||
st.Update(ctx, func(tx *bbolt.Tx) error {
|
||||
if err := st.Update(ctx, func(tx *bbolt.Tx) error {
|
||||
if st.BucketExists(tx, store.BucketUsers) {
|
||||
t.Fatal("expected bucket to not exist")
|
||||
}
|
||||
st.PutUser(tx, "alice", []byte("x"))
|
||||
if err := st.PutUser(tx, "alice", []byte("x")); err != nil {
|
||||
return err
|
||||
}
|
||||
if !st.BucketExists(tx, store.BucketUsers) {
|
||||
t.Fatal("expected bucket to exist")
|
||||
}
|
||||
return st.DeleteBucket(tx, store.BucketUsers)
|
||||
})
|
||||
}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
st.View(ctx, func(tx *bbolt.Tx) error {
|
||||
if err := st.View(ctx, func(tx *bbolt.Tx) error {
|
||||
if st.BucketExists(tx, store.BucketUsers) {
|
||||
t.Fatal("expected bucket to be deleted")
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDeleteBucketNonExistent(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user