storj.io/minio@v0.0.0-20230509071714-0cbc90f649b1/cmd/naughty-disk_test.go (about)

     1  /*
     2   * MinIO Cloud Storage, (C) 2016 MinIO, Inc.
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *     http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  package cmd
    18  
    19  import (
    20  	"context"
    21  	"io"
    22  	"sync"
    23  )
    24  
    25  // naughtyDisk wraps a POSIX disk and returns programmed errors
    26  // specified by the developer. The purpose is to simulate errors
    27  // that are hard to simulate in practice like DiskNotFound.
    28  // Programmed errors are stored in errors field.
    29  type naughtyDisk struct {
    30  	// The real disk
    31  	disk StorageAPI
    32  	// Programmed errors: API call number => error to return
    33  	errors map[int]error
    34  	// The error to return when no error value is programmed
    35  	defaultErr error
    36  	// The current API call number
    37  	callNR int
    38  	// Data protection
    39  	mu sync.Mutex
    40  }
    41  
    42  func newNaughtyDisk(d StorageAPI, errs map[int]error, defaultErr error) *naughtyDisk {
    43  	return &naughtyDisk{disk: d, errors: errs, defaultErr: defaultErr}
    44  }
    45  
    46  func (d *naughtyDisk) String() string {
    47  	return d.disk.String()
    48  }
    49  
    50  func (d *naughtyDisk) IsOnline() bool {
    51  	if err := d.calcError(); err != nil {
    52  		return err == errDiskNotFound
    53  	}
    54  	return d.disk.IsOnline()
    55  }
    56  
    57  func (d *naughtyDisk) IsLocal() bool {
    58  	return d.disk.IsLocal()
    59  }
    60  
    61  func (d *naughtyDisk) Endpoint() Endpoint {
    62  	return d.disk.Endpoint()
    63  }
    64  
    65  func (d *naughtyDisk) Hostname() string {
    66  	return d.disk.Hostname()
    67  }
    68  
    69  func (d *naughtyDisk) Healing() *healingTracker {
    70  	return d.disk.Healing()
    71  }
    72  
    73  func (d *naughtyDisk) Close() (err error) {
    74  	if err = d.calcError(); err != nil {
    75  		return err
    76  	}
    77  	return d.disk.Close()
    78  }
    79  
    80  func (d *naughtyDisk) calcError() (err error) {
    81  	d.mu.Lock()
    82  	defer d.mu.Unlock()
    83  	d.callNR++
    84  	if err, ok := d.errors[d.callNR]; ok {
    85  		return err
    86  	}
    87  	if d.defaultErr != nil {
    88  		return d.defaultErr
    89  	}
    90  	return nil
    91  }
    92  
    93  func (d *naughtyDisk) GetDiskLoc() (poolIdx, setIdx, diskIdx int) {
    94  	return -1, -1, -1
    95  }
    96  
    97  func (d *naughtyDisk) SetDiskLoc(poolIdx, setIdx, diskIdx int) {}
    98  
    99  func (d *naughtyDisk) GetDiskID() (string, error) {
   100  	return d.disk.GetDiskID()
   101  }
   102  
   103  func (d *naughtyDisk) SetDiskID(id string) {
   104  	d.disk.SetDiskID(id)
   105  }
   106  
   107  func (d *naughtyDisk) NSScanner(ctx context.Context, cache dataUsageCache) (info dataUsageCache, err error) {
   108  	return d.disk.NSScanner(ctx, cache)
   109  }
   110  
   111  func (d *naughtyDisk) DiskInfo(ctx context.Context) (info DiskInfo, err error) {
   112  	if err := d.calcError(); err != nil {
   113  		return info, err
   114  	}
   115  	return d.disk.DiskInfo(ctx)
   116  }
   117  
   118  func (d *naughtyDisk) MakeVolBulk(ctx context.Context, volumes ...string) (err error) {
   119  	if err := d.calcError(); err != nil {
   120  		return err
   121  	}
   122  	return d.disk.MakeVolBulk(ctx, volumes...)
   123  }
   124  
   125  func (d *naughtyDisk) MakeVol(ctx context.Context, volume string) (err error) {
   126  	if err := d.calcError(); err != nil {
   127  		return err
   128  	}
   129  	return d.disk.MakeVol(ctx, volume)
   130  }
   131  
   132  func (d *naughtyDisk) ListVols(ctx context.Context) (vols []VolInfo, err error) {
   133  	if err := d.calcError(); err != nil {
   134  		return nil, err
   135  	}
   136  	return d.disk.ListVols(ctx)
   137  }
   138  
   139  func (d *naughtyDisk) StatVol(ctx context.Context, volume string) (vol VolInfo, err error) {
   140  	if err := d.calcError(); err != nil {
   141  		return VolInfo{}, err
   142  	}
   143  	return d.disk.StatVol(ctx, volume)
   144  }
   145  func (d *naughtyDisk) DeleteVol(ctx context.Context, volume string, forceDelete bool) (err error) {
   146  	if err := d.calcError(); err != nil {
   147  		return err
   148  	}
   149  	return d.disk.DeleteVol(ctx, volume, forceDelete)
   150  }
   151  
   152  func (d *naughtyDisk) WalkDir(ctx context.Context, opts WalkDirOptions, wr io.Writer) error {
   153  	if err := d.calcError(); err != nil {
   154  		return err
   155  	}
   156  	return d.disk.WalkDir(ctx, opts, wr)
   157  }
   158  
   159  func (d *naughtyDisk) ListDir(ctx context.Context, volume, dirPath string, count int) (entries []string, err error) {
   160  	if err := d.calcError(); err != nil {
   161  		return []string{}, err
   162  	}
   163  	return d.disk.ListDir(ctx, volume, dirPath, count)
   164  }
   165  
   166  func (d *naughtyDisk) ReadFile(ctx context.Context, volume string, path string, offset int64, buf []byte, verifier *BitrotVerifier) (n int64, err error) {
   167  	if err := d.calcError(); err != nil {
   168  		return 0, err
   169  	}
   170  	return d.disk.ReadFile(ctx, volume, path, offset, buf, verifier)
   171  }
   172  
   173  func (d *naughtyDisk) ReadFileStream(ctx context.Context, volume, path string, offset, length int64) (io.ReadCloser, error) {
   174  	if err := d.calcError(); err != nil {
   175  		return nil, err
   176  	}
   177  	return d.disk.ReadFileStream(ctx, volume, path, offset, length)
   178  }
   179  
   180  func (d *naughtyDisk) CreateFile(ctx context.Context, volume, path string, size int64, reader io.Reader) error {
   181  	if err := d.calcError(); err != nil {
   182  		return err
   183  	}
   184  	return d.disk.CreateFile(ctx, volume, path, size, reader)
   185  }
   186  
   187  func (d *naughtyDisk) AppendFile(ctx context.Context, volume string, path string, buf []byte) error {
   188  	if err := d.calcError(); err != nil {
   189  		return err
   190  	}
   191  	return d.disk.AppendFile(ctx, volume, path, buf)
   192  }
   193  
   194  func (d *naughtyDisk) RenameData(ctx context.Context, srcVolume, srcPath string, fi FileInfo, dstVolume, dstPath string) error {
   195  	if err := d.calcError(); err != nil {
   196  		return err
   197  	}
   198  	return d.disk.RenameData(ctx, srcVolume, srcPath, fi, dstVolume, dstPath)
   199  }
   200  
   201  func (d *naughtyDisk) RenameFile(ctx context.Context, srcVolume, srcPath, dstVolume, dstPath string) error {
   202  	if err := d.calcError(); err != nil {
   203  		return err
   204  	}
   205  	return d.disk.RenameFile(ctx, srcVolume, srcPath, dstVolume, dstPath)
   206  }
   207  
   208  func (d *naughtyDisk) CheckParts(ctx context.Context, volume string, path string, fi FileInfo) (err error) {
   209  	if err := d.calcError(); err != nil {
   210  		return err
   211  	}
   212  	return d.disk.CheckParts(ctx, volume, path, fi)
   213  }
   214  
   215  func (d *naughtyDisk) CheckFile(ctx context.Context, volume string, path string) (err error) {
   216  	if err := d.calcError(); err != nil {
   217  		return err
   218  	}
   219  	return d.disk.CheckFile(ctx, volume, path)
   220  }
   221  
   222  func (d *naughtyDisk) Delete(ctx context.Context, volume string, path string, recursive bool) (err error) {
   223  	if err := d.calcError(); err != nil {
   224  		return err
   225  	}
   226  	return d.disk.Delete(ctx, volume, path, recursive)
   227  }
   228  
   229  func (d *naughtyDisk) DeleteVersions(ctx context.Context, volume string, versions []FileInfo) []error {
   230  	if err := d.calcError(); err != nil {
   231  		errs := make([]error, len(versions))
   232  		for i := range errs {
   233  			errs[i] = err
   234  		}
   235  		return errs
   236  	}
   237  	return d.disk.DeleteVersions(ctx, volume, versions)
   238  }
   239  
   240  func (d *naughtyDisk) WriteMetadata(ctx context.Context, volume, path string, fi FileInfo) (err error) {
   241  	if err := d.calcError(); err != nil {
   242  		return err
   243  	}
   244  	return d.disk.WriteMetadata(ctx, volume, path, fi)
   245  }
   246  
   247  func (d *naughtyDisk) UpdateMetadata(ctx context.Context, volume, path string, fi FileInfo) (err error) {
   248  	if err := d.calcError(); err != nil {
   249  		return err
   250  	}
   251  	return d.disk.UpdateMetadata(ctx, volume, path, fi)
   252  }
   253  
   254  func (d *naughtyDisk) DeleteVersion(ctx context.Context, volume, path string, fi FileInfo, forceDelMarker bool) (err error) {
   255  	if err := d.calcError(); err != nil {
   256  		return err
   257  	}
   258  	return d.disk.DeleteVersion(ctx, volume, path, fi, forceDelMarker)
   259  }
   260  
   261  func (d *naughtyDisk) ReadVersion(ctx context.Context, volume, path, versionID string, readData bool) (fi FileInfo, err error) {
   262  	if err := d.calcError(); err != nil {
   263  		return FileInfo{}, err
   264  	}
   265  	return d.disk.ReadVersion(ctx, volume, path, versionID, readData)
   266  }
   267  
   268  func (d *naughtyDisk) WriteAll(ctx context.Context, volume string, path string, b []byte) (err error) {
   269  	if err := d.calcError(); err != nil {
   270  		return err
   271  	}
   272  	return d.disk.WriteAll(ctx, volume, path, b)
   273  }
   274  
   275  func (d *naughtyDisk) ReadAll(ctx context.Context, volume string, path string) (buf []byte, err error) {
   276  	if err := d.calcError(); err != nil {
   277  		return nil, err
   278  	}
   279  	return d.disk.ReadAll(ctx, volume, path)
   280  }
   281  
   282  func (d *naughtyDisk) VerifyFile(ctx context.Context, volume, path string, fi FileInfo) error {
   283  	if err := d.calcError(); err != nil {
   284  		return err
   285  	}
   286  	return d.disk.VerifyFile(ctx, volume, path, fi)
   287  }