mirror of
https://github.com/pgsty/minio.git
synced 2026-10-28 19:47:23 +03:00
dcc2f20ba8
Signed-off-by: Feng Ruohang <rh@vonng.com>
140 lines
3.8 KiB
Go
140 lines
3.8 KiB
Go
// Copyright (c) 2026 Feng Ruohang
|
|
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
|
|
package cmd
|
|
|
|
import (
|
|
"context"
|
|
"sync"
|
|
"testing"
|
|
"testing/synctest"
|
|
|
|
"github.com/minio/minio/internal/grid"
|
|
)
|
|
|
|
type cancelableRenameDisk struct {
|
|
StorageAPI
|
|
entered chan<- struct{}
|
|
release <-chan struct{}
|
|
}
|
|
|
|
func (d cancelableRenameDisk) RenameData(ctx context.Context, _, _ string, _ FileInfo, _, _ string, _ RenameOptions) (RenameDataResp, error) {
|
|
d.entered <- struct{}{}
|
|
select {
|
|
case <-ctx.Done():
|
|
return RenameDataResp{}, ctx.Err()
|
|
case <-d.release:
|
|
return RenameDataResp{}, errDiskNotFound
|
|
}
|
|
}
|
|
|
|
func TestStorageTimeoutCoordinatorCancellation(t *testing.T) {
|
|
synctest.Test(t, func(t *testing.T) {
|
|
ctx, cancel := context.WithCancel(t.Context())
|
|
defer cancel()
|
|
entered, release := make(chan struct{}, 4), make(chan struct{})
|
|
defer close(release)
|
|
disks := make([]StorageAPI, 4)
|
|
metadata := make([]FileInfo, 4)
|
|
for i := range disks {
|
|
disks[i] = cancelableRenameDisk{entered: entered, release: release}
|
|
metadata[i] = FileInfo{Deleted: true}
|
|
}
|
|
done := make(chan error, 1)
|
|
go func() {
|
|
_, _, _, err := renameData(ctx, disks, minioMetaTmpBucket, "staged", metadata, "bucket", "object", 3)
|
|
done <- err
|
|
}()
|
|
for range disks {
|
|
<-entered
|
|
}
|
|
cancel()
|
|
synctest.Wait()
|
|
select {
|
|
case err := <-done:
|
|
if err == nil {
|
|
t.Fatal("canceled commit unexpectedly succeeded")
|
|
}
|
|
default:
|
|
t.Fatal("coordinator did not propagate cancellation to disk calls")
|
|
}
|
|
})
|
|
}
|
|
|
|
type rollbackOptionsDisk struct {
|
|
StorageAPI
|
|
mu sync.Mutex
|
|
opts DeleteOptions
|
|
}
|
|
|
|
func (d *rollbackOptionsDisk) DeleteVersion(_ context.Context, _, _ string, _ FileInfo, _ bool, opts DeleteOptions) error {
|
|
d.mu.Lock()
|
|
defer d.mu.Unlock()
|
|
d.opts = opts
|
|
return nil
|
|
}
|
|
|
|
func TestStorageRollbackRPCOptions(t *testing.T) {
|
|
endpoint, err := NewEndpoint(t.TempDir())
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
disk := &rollbackOptionsDisk{}
|
|
globalLocalDrivesMu.Lock()
|
|
oldDrives, oldSets := globalLocalDrivesMap, globalLocalSetDrives
|
|
globalLocalDrivesMap = map[string]StorageAPI{endpoint.String(): disk}
|
|
globalLocalSetDrives = nil
|
|
globalLocalDrivesMu.Unlock()
|
|
defer func() {
|
|
globalLocalDrivesMu.Lock()
|
|
globalLocalDrivesMap, globalLocalSetDrives = oldDrives, oldSets
|
|
globalLocalDrivesMu.Unlock()
|
|
}()
|
|
tg, err := grid.SetupTestGrid(2)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer tg.Cleanup()
|
|
server := storageRESTServer{endpoint: endpoint}
|
|
const route = "/rollback-options"
|
|
if err := storageDeleteVersionRPC.Register(tg.Managers[1], server.DeleteVersionHandler, route); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
client := &storageRESTClient{gridConn: tg.Managers[0].Connection(tg.Hosts[1]).Subroute(route)}
|
|
client.diskID.Store(new(string))
|
|
want := DeleteOptions{UndoWrite: true, OldDataDir: mustGetUUID()}
|
|
if err := client.DeleteVersion(t.Context(), "bucket", "object", FileInfo{}, false, want); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
disk.mu.Lock()
|
|
defer disk.mu.Unlock()
|
|
if disk.opts != want {
|
|
t.Fatalf("remote handler lost rollback options: got %+v, want %+v", disk.opts, want)
|
|
}
|
|
}
|
|
|
|
func TestStoragePrereleaseMetadataHidden(t *testing.T) {
|
|
disk, _, err := newXLStorageTestSetup(t)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer disk.Close()
|
|
if err := disk.MakeVol(t.Context(), "bucket"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
fi := newFileInfo("object", 2, 2)
|
|
fi.DataDir, fi.ModTime, fi.Erasure.Index = mustGetUUID(), UTCNow(), 1
|
|
fi.Metadata = map[string]string{rollbackIDKey: mustGetUUID(), "user-key": "value"}
|
|
if err := disk.WriteMetadata(t.Context(), "", "bucket", "object", fi); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
got, err := disk.ReadVersion(t.Context(), "", "bucket", "object", "", ReadOptions{})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
public := cleanMetadata(got.Metadata)
|
|
if _, ok := public[rollbackIDKey]; ok || public["user-key"] != "value" {
|
|
t.Fatalf("pre-release metadata exposed or user metadata lost: %+v", public)
|
|
}
|
|
}
|