storj.io/minio@v0.0.0-20230509071714-0cbc90f649b1/cmd/fs-tree-walk-pool_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 "testing" 21 "time" 22 ) 23 24 // Test if tree walker go-routine is removed from the pool after timeout 25 // and that is available in the pool before the timeout. 26 func TestTreeWalkPoolBasic(t *testing.T) { 27 // Create a treeWalkPool 28 tw := NewTreeWalkPool(1 * time.Second) 29 30 // Create sample params 31 params := listParams{ 32 bucket: "test-bucket", 33 } 34 35 // Add a treeWalk to the pool 36 resultCh := make(chan TreeWalkResult) 37 endWalkCh := make(chan struct{}) 38 tw.Set(params, resultCh, endWalkCh) 39 40 // Wait for treeWalkPool timeout to happen 41 <-time.After(2 * time.Second) 42 if c1, _ := tw.Release(params); c1 != nil { 43 t.Error("treeWalk go-routine must have been freed") 44 } 45 46 // Add the treeWalk back to the pool 47 tw.Set(params, resultCh, endWalkCh) 48 49 // Release the treeWalk before timeout 50 select { 51 case <-time.After(1 * time.Second): 52 break 53 default: 54 if c1, _ := tw.Release(params); c1 == nil { 55 t.Error("treeWalk go-routine got freed before timeout") 56 } 57 } 58 } 59 60 // Test if multiple tree walkers for the same listParams are managed as expected by the pool. 61 func TestManyWalksSameParam(t *testing.T) { 62 // Create a treeWalkPool. 63 tw := NewTreeWalkPool(5 * time.Second) 64 65 // Create sample params. 66 params := listParams{ 67 bucket: "test-bucket", 68 } 69 70 select { 71 // This timeout is an upper-bound. This is started 72 // before the first treeWalk go-routine's timeout period starts. 73 case <-time.After(5 * time.Second): 74 break 75 default: 76 // Create many treeWalk go-routines for the same params. 77 for i := 0; i < treeWalkSameEntryLimit; i++ { 78 resultCh := make(chan TreeWalkResult) 79 endWalkCh := make(chan struct{}) 80 tw.Set(params, resultCh, endWalkCh) 81 } 82 83 tw.mu.Lock() 84 if walks, ok := tw.pool[params]; ok { 85 if len(walks) != treeWalkSameEntryLimit { 86 t.Error("There aren't as many walks as were Set") 87 } 88 } 89 tw.mu.Unlock() 90 for i := 0; i < treeWalkSameEntryLimit; i++ { 91 tw.mu.Lock() 92 if walks, ok := tw.pool[params]; ok { 93 // Before ith Release we should have n-i treeWalk go-routines. 94 if treeWalkSameEntryLimit-i != len(walks) { 95 t.Error("There aren't as many walks as were Set") 96 } 97 } 98 tw.mu.Unlock() 99 tw.Release(params) 100 } 101 } 102 } 103 104 // Test if multiple tree walkers for the same listParams are managed as expected by the pool 105 // but that treeWalkSameEntryLimit is respected. 106 func TestManyWalksSameParamPrune(t *testing.T) { 107 // Create a treeWalkPool. 108 tw := NewTreeWalkPool(5 * time.Second) 109 110 // Create sample params. 111 params := listParams{ 112 bucket: "test-bucket", 113 } 114 115 select { 116 // This timeout is an upper-bound. This is started 117 // before the first treeWalk go-routine's timeout period starts. 118 case <-time.After(5 * time.Second): 119 break 120 default: 121 // Create many treeWalk go-routines for the same params. 122 for i := 0; i < treeWalkSameEntryLimit*4; i++ { 123 resultCh := make(chan TreeWalkResult) 124 endWalkCh := make(chan struct{}) 125 tw.Set(params, resultCh, endWalkCh) 126 } 127 128 tw.mu.Lock() 129 if walks, ok := tw.pool[params]; ok { 130 if len(walks) != treeWalkSameEntryLimit { 131 t.Error("There aren't as many walks as were Set") 132 } 133 } 134 tw.mu.Unlock() 135 for i := 0; i < treeWalkSameEntryLimit; i++ { 136 tw.mu.Lock() 137 if walks, ok := tw.pool[params]; ok { 138 // Before ith Release we should have n-i treeWalk go-routines. 139 if treeWalkSameEntryLimit-i != len(walks) { 140 t.Error("There aren't as many walks as were Set") 141 } 142 } 143 tw.mu.Unlock() 144 tw.Release(params) 145 } 146 } 147 }