github.com/zuoyebang/bitalosdb@v1.1.1-0.20240516111551-79a8c4d8ce20/internal/vfs/disk_health_fs_test.go (about)

     1  // Copyright 2021 The Bitalosdb author(hustxrb@163.com) and other contributors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package vfs
    16  
    17  import (
    18  	"io"
    19  	"os"
    20  	"testing"
    21  	"time"
    22  )
    23  
    24  type mockFile struct {
    25  	syncDuration time.Duration
    26  }
    27  
    28  func (m mockFile) Close() error {
    29  	return nil
    30  }
    31  
    32  func (m mockFile) Read(p []byte) (n int, err error) {
    33  	panic("unimplemented")
    34  }
    35  
    36  func (m mockFile) ReadAt(p []byte, off int64) (n int, err error) {
    37  	panic("unimplemented")
    38  }
    39  
    40  func (m mockFile) Write(p []byte) (n int, err error) {
    41  	time.Sleep(m.syncDuration)
    42  	return len(p), nil
    43  }
    44  
    45  func (m mockFile) Seek(offset int64, whence int) (int64, error) {
    46  	panic("implement me")
    47  }
    48  
    49  func (m mockFile) Stat() (os.FileInfo, error) {
    50  	panic("unimplemented")
    51  }
    52  
    53  func (m mockFile) Sync() error {
    54  	time.Sleep(m.syncDuration)
    55  	return nil
    56  }
    57  
    58  var _ File = &mockFile{}
    59  
    60  type mockFS struct {
    61  	syncDuration time.Duration
    62  }
    63  
    64  func (m mockFS) Create(name string) (File, error) {
    65  	return mockFile(m), nil
    66  }
    67  
    68  func (m mockFS) Link(oldname, newname string) error {
    69  	panic("unimplemented")
    70  }
    71  
    72  func (m mockFS) Open(name string, opts ...OpenOption) (File, error) {
    73  	panic("unimplemented")
    74  }
    75  
    76  func (m mockFS) OpenDir(name string) (File, error) {
    77  	panic("unimplemented")
    78  }
    79  
    80  func (m mockFS) Remove(name string) error {
    81  	panic("unimplemented")
    82  }
    83  
    84  func (m mockFS) RemoveAll(name string) error {
    85  	panic("unimplemented")
    86  }
    87  
    88  func (m mockFS) Rename(oldname, newname string) error {
    89  	panic("unimplemented")
    90  }
    91  
    92  func (m mockFS) ReuseForWrite(oldname, newname string) (File, error) {
    93  	return mockFile(m), nil
    94  }
    95  
    96  func (m mockFS) MkdirAll(dir string, perm os.FileMode) error {
    97  	panic("unimplemented")
    98  }
    99  
   100  func (m mockFS) Lock(name string) (io.Closer, error) {
   101  	panic("unimplemented")
   102  }
   103  
   104  func (m mockFS) List(dir string) ([]string, error) {
   105  	panic("unimplemented")
   106  }
   107  
   108  func (m mockFS) Stat(name string) (os.FileInfo, error) {
   109  	panic("unimplemented")
   110  }
   111  
   112  func (m mockFS) PathBase(path string) string {
   113  	panic("unimplemented")
   114  }
   115  
   116  func (m mockFS) PathJoin(elem ...string) string {
   117  	panic("unimplemented")
   118  }
   119  
   120  func (m mockFS) PathDir(path string) string {
   121  	panic("unimplemented")
   122  }
   123  
   124  func (m mockFS) GetDiskUsage(path string) (DiskUsage, error) {
   125  	panic("unimplemented")
   126  }
   127  
   128  func (m mockFS) OpenForWrite(path string) (File, error) {
   129  	panic("unimplemented")
   130  }
   131  
   132  func (m mockFS) OpenWR(path string) (File, error) {
   133  	panic("unimplemented")
   134  }
   135  
   136  var _ FS = &mockFS{}
   137  
   138  func TestDiskHealthChecking(t *testing.T) {
   139  	diskSlow := make(chan time.Duration, 100)
   140  	slowThreshold := 1 * time.Second
   141  	mockFS := &mockFS{syncDuration: 3 * time.Second}
   142  	fs := WithDiskHealthChecks(mockFS, slowThreshold, func(s string, duration time.Duration) {
   143  		diskSlow <- duration
   144  	})
   145  	dhFile, _ := fs.Create("test")
   146  	defer dhFile.Close()
   147  
   148  	dhFile.Sync()
   149  
   150  	select {
   151  	case d := <-diskSlow:
   152  		if d.Seconds() < slowThreshold.Seconds() {
   153  			t.Fatalf("expected %0.1f to be greater than threshold %0.1f", d.Seconds(), slowThreshold.Seconds())
   154  		}
   155  	case <-time.After(5 * time.Second):
   156  		t.Fatal("disk stall detector did not detect slow disk operation")
   157  	}
   158  }