github.com/matrixorigin/matrixone@v1.2.0/pkg/fileservice/local_fs_test.go (about) 1 // Copyright 2022 Matrix Origin 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 fileservice 16 17 import ( 18 "context" 19 "crypto/rand" 20 "fmt" 21 "io" 22 "testing" 23 24 "github.com/matrixorigin/matrixone/pkg/fileservice/memorycache" 25 "github.com/matrixorigin/matrixone/pkg/perfcounter" 26 "github.com/matrixorigin/matrixone/pkg/util/toml" 27 "github.com/stretchr/testify/assert" 28 ) 29 30 func TestLocalFS(t *testing.T) { 31 32 t.Run("file service", func(t *testing.T) { 33 testFileService(t, 0, func(name string) FileService { 34 ctx := context.Background() 35 dir := t.TempDir() 36 fs, err := NewLocalFS(ctx, name, dir, DisabledCacheConfig, nil) 37 assert.Nil(t, err) 38 return fs 39 }) 40 }) 41 42 t.Run("with memory cache", func(t *testing.T) { 43 testFileService(t, 0, func(name string) FileService { 44 ctx := context.Background() 45 dir := t.TempDir() 46 fs, err := NewLocalFS(ctx, name, dir, CacheConfig{ 47 MemoryCapacity: ptrTo[toml.ByteSize](128 * 1024), 48 }, nil) 49 assert.Nil(t, err) 50 return fs 51 }) 52 }) 53 54 t.Run("mutable file service", func(t *testing.T) { 55 testMutableFileService(t, func() MutableFileService { 56 ctx := context.Background() 57 dir := t.TempDir() 58 fs, err := NewLocalFS(ctx, "local", dir, DisabledCacheConfig, nil) 59 assert.Nil(t, err) 60 return fs 61 }) 62 }) 63 64 t.Run("replaceable file service", func(t *testing.T) { 65 testReplaceableFileService(t, func() ReplaceableFileService { 66 ctx := context.Background() 67 dir := t.TempDir() 68 fs, err := NewLocalFS(ctx, "local", dir, DisabledCacheConfig, nil) 69 assert.Nil(t, err) 70 return fs 71 }) 72 }) 73 74 t.Run("caching file service", func(t *testing.T) { 75 testCachingFileService(t, func() CachingFileService { 76 ctx := context.Background() 77 dir := t.TempDir() 78 fs, err := NewLocalFS(ctx, "local", dir, CacheConfig{ 79 MemoryCapacity: ptrTo[toml.ByteSize](128 * 1024), 80 }, nil) 81 assert.Nil(t, err) 82 return fs 83 }) 84 }) 85 86 } 87 88 func BenchmarkLocalFS(b *testing.B) { 89 ctx := context.Background() 90 benchmarkFileService(ctx, b, func() FileService { 91 dir := b.TempDir() 92 fs, err := NewLocalFS(ctx, "local", dir, DisabledCacheConfig, nil) 93 assert.Nil(b, err) 94 return fs 95 }) 96 } 97 98 func TestLocalFSWithDiskCache(t *testing.T) { 99 ctx := context.Background() 100 var counter perfcounter.CounterSet 101 ctx = perfcounter.WithCounterSet(ctx, &counter) 102 const ( 103 n = 128 104 dataLen = 128 105 ) 106 107 // new fs 108 fs, err := NewLocalFS( 109 ctx, 110 "foo", 111 t.TempDir(), 112 CacheConfig{ 113 DiskPath: ptrTo(t.TempDir()), 114 DiskCapacity: ptrTo[toml.ByteSize](dataLen * n / 32), 115 enableDiskCacheForLocalFS: true, 116 }, 117 nil, 118 ) 119 assert.Nil(t, err) 120 121 // prepare data 122 datas := make([][]byte, 0, n) 123 for i := 0; i < n; i++ { 124 data := make([]byte, dataLen) 125 _, err := rand.Read(data) 126 assert.Nil(t, err) 127 datas = append(datas, data) 128 } 129 130 // write 131 for i := 0; i < n; i++ { 132 data := datas[i] 133 vec := IOVector{ 134 FilePath: fmt.Sprintf("%d", i), 135 Entries: []IOEntry{ 136 { 137 Data: data, 138 Size: int64(len(data)), 139 }, 140 }, 141 } 142 err := fs.Write(ctx, vec) 143 assert.Nil(t, err) 144 } 145 146 // read 147 for i := 0; i < n*10; i++ { 148 idx := i % n 149 expected := datas[idx] 150 length := 8 151 for j := 0; j < dataLen/length; j++ { 152 offset := j * length 153 vec := IOVector{ 154 FilePath: fmt.Sprintf("%d", idx), 155 Entries: []IOEntry{ 156 { 157 Offset: int64(offset), 158 Size: int64(length), 159 }, 160 }, 161 } 162 err := fs.Read(ctx, &vec) 163 assert.Nil(t, err) 164 assert.Equal(t, expected[offset:offset+length], vec.Entries[0].Data) 165 } 166 } 167 168 } 169 170 // default allocator must use with no memcache 171 // only memory obtained through memcache.Alloc can be set to memcache 172 func TestLocalFSWithIOVectorCache(t *testing.T) { 173 memCache1 := NewMemCache( 174 NewMemoryCache(1<<20, false, nil), 175 nil, 176 ) 177 memCache2 := NewMemCache( 178 NewMemoryCache(1<<20, false, nil), 179 nil, 180 ) 181 caches := []IOVectorCache{memCache1, memCache2} 182 183 ctx := context.Background() 184 dir := t.TempDir() 185 fs, err := NewLocalFS(ctx, "test", dir, CacheConfig{ 186 MemoryCapacity: ptrTo[toml.ByteSize](128 * 1024), 187 }, nil) 188 assert.Nil(t, err) 189 190 err = fs.Write(ctx, IOVector{ 191 Caches: caches, 192 FilePath: "foo", 193 Entries: []IOEntry{ 194 { 195 Size: 8, 196 Data: []byte("12345678"), 197 }, 198 }, 199 }) 200 assert.Nil(t, err) 201 202 vec := IOVector{ 203 Caches: caches, 204 FilePath: "foo", 205 Entries: []IOEntry{ 206 { 207 Size: 8, 208 ToCacheData: func(r io.Reader, _ []byte, allocator CacheDataAllocator) (memorycache.CacheData, error) { 209 cacheData := allocator.Alloc(8) 210 _, err := io.ReadFull(r, cacheData.Bytes()) 211 if err != nil { 212 return nil, err 213 } 214 return cacheData, nil 215 }, 216 }, 217 }, 218 } 219 err = fs.Read(ctx, &vec) 220 assert.Nil(t, err) 221 vec.Release() 222 223 assert.Equal(t, int64(8), memCache1.cache.Used()) 224 assert.Equal(t, int64(8), memCache2.cache.Used()) 225 memCache1.cache.Flush() 226 memCache2.cache.Flush() 227 fs.FlushCache() 228 } 229 230 func TestLocalFSEmptyRootPath(t *testing.T) { 231 fs, err := NewLocalFS( 232 context.Background(), 233 "test", 234 "", 235 CacheConfig{}, 236 nil, 237 ) 238 assert.Nil(t, err) 239 assert.NotNil(t, fs) 240 }