github.com/NVIDIA/aistore@v1.3.23-0.20240517131212-7df6609be51d/xact/xs/xaction_test.go (about) 1 // Package xs_test contains xs unit test. 2 /* 3 * Copyright (c) 2018-2024, NVIDIA CORPORATION. All rights reserved. 4 */ 5 package xs_test 6 7 import ( 8 "errors" 9 "fmt" 10 "os" 11 "sync" 12 "testing" 13 "time" 14 15 "github.com/NVIDIA/aistore/api/apc" 16 "github.com/NVIDIA/aistore/cmn" 17 "github.com/NVIDIA/aistore/cmn/cos" 18 "github.com/NVIDIA/aistore/core" 19 "github.com/NVIDIA/aistore/core/meta" 20 "github.com/NVIDIA/aistore/core/mock" 21 "github.com/NVIDIA/aistore/fs" 22 "github.com/NVIDIA/aistore/space" 23 "github.com/NVIDIA/aistore/tools/tassert" 24 "github.com/NVIDIA/aistore/xact" 25 "github.com/NVIDIA/aistore/xact/xreg" 26 "github.com/NVIDIA/aistore/xact/xs" 27 ) 28 29 func init() { 30 config := cmn.GCO.BeginUpdate() 31 config.Log.Level = "3" 32 config.ConfigDir = "/tmp/ais-tests" 33 config.Timeout.CplaneOperation = cos.Duration(2 * time.Second) 34 config.Timeout.MaxKeepalive = cos.Duration(4 * time.Second) 35 config.Timeout.MaxHostBusy = cos.Duration(20 * time.Second) 36 config.TestFSP.Count = 1 37 cmn.GCO.CommitUpdate(config) 38 39 xreg.Init() 40 xs.Xreg(false) 41 fs.TestNew(nil) 42 } 43 44 // Smoke tests for xactions 45 func TestXactionRenewLRU(t *testing.T) { 46 var ( 47 num = 10 48 xactCh = make(chan xreg.RenewRes, num) 49 wg = &sync.WaitGroup{} 50 ) 51 xreg.TestReset() 52 53 xreg.RegNonBckXact(&space.TestFactory{}) 54 defer xreg.AbortAll(nil) 55 cos.InitShortID(0) 56 57 wg.Add(num) 58 for range num { 59 go func() { 60 xactCh <- xreg.RenewLRU(cos.GenUUID()) 61 wg.Done() 62 }() 63 } 64 wg.Wait() 65 close(xactCh) 66 67 newCnt := 0 68 for rns := range xactCh { 69 if !rns.IsRunning() { 70 newCnt++ 71 } 72 } 73 tassert.Errorf(t, newCnt == 1, "expected just one LRU xaction to be created, got %d", newCnt) 74 } 75 76 func TestXactionRenewPrefetch(t *testing.T) { 77 var ( 78 msg = &apc.PrefetchMsg{} 79 bmd = mock.NewBaseBownerMock() 80 bck = meta.NewBck( 81 "test", apc.GCP, cmn.NsGlobal, 82 &cmn.Bprops{Cksum: cmn.CksumConf{Type: cos.ChecksumXXHash}}, 83 ) 84 tMock = mock.NewTarget(bmd) 85 ) 86 core.T = tMock 87 xreg.TestReset() 88 bmd.Add(bck) 89 90 _ = cos.CreateDir("/tmp/prefetch") 91 _, err := fs.Add("/tmp/prefetch", tMock.SID()) 92 if err != nil { 93 fmt.Fprintln(os.Stderr, "ignoring:", err) 94 } 95 xreg.RegBckXact(&xs.TestXFactory{}) 96 defer xreg.AbortAll(nil) 97 cos.InitShortID(0) 98 99 ch := make(chan xreg.RenewRes, 10) 100 wg := &sync.WaitGroup{} 101 wg.Add(10) 102 for range 10 { 103 go func() { 104 defer wg.Done() 105 ch <- xreg.RenewPrefetch(cos.GenUUID(), bck, msg) 106 }() 107 } 108 109 wg.Wait() 110 close(ch) 111 112 res := make(map[core.Xact]struct{}, 10) 113 for rns := range ch { 114 if xctn := rns.Entry.Get(); xctn != nil { 115 res[xctn] = struct{}{} 116 } 117 } 118 119 tassert.Errorf(t, len(res) > 0, "expected xactions to be created") 120 } 121 122 func TestXactionAbortAll(t *testing.T) { 123 var ( 124 bmd = mock.NewBaseBownerMock() 125 bckFrom = meta.NewBck("test", apc.AIS, cmn.NsGlobal) 126 bckTo = meta.NewBck("test", apc.AIS, cmn.NsGlobal) 127 tMock = mock.NewTarget(bmd) 128 ) 129 core.T = tMock 130 xreg.TestReset() 131 bmd.Add(bckFrom) 132 bmd.Add(bckTo) 133 134 xreg.RegNonBckXact(&space.TestFactory{}) 135 xreg.RegBckXact(&xs.TestBmvFactory{}) 136 cos.InitShortID(0) 137 138 rnsLRU := xreg.RenewLRU(cos.GenUUID()) 139 tassert.Errorf(t, !rnsLRU.IsRunning(), "new LRU must be created") 140 rnsRen := xreg.RenewBckRename(bckFrom, bckTo, cos.GenUUID(), 123, "phase") 141 xactBck := rnsRen.Entry.Get() 142 tassert.Errorf(t, rnsRen.Err == nil && xactBck != nil, "Xaction must be created") 143 144 xreg.AbortAll(errors.New("test-abort-all")) 145 146 tassert.Errorf(t, rnsLRU.Entry.Get().IsAborted(), "AbortAllGlobal: expected global xaction to be aborted") 147 tassert.Errorf(t, xactBck.IsAborted(), "AbortAllGlobal: expected bucket xaction to be aborted") 148 } 149 150 func TestXactionAbortAllGlobal(t *testing.T) { 151 var ( 152 bmd = mock.NewBaseBownerMock() 153 bckFrom = meta.NewBck("test", apc.AIS, cmn.NsGlobal) 154 bckTo = meta.NewBck("test", apc.AIS, cmn.NsGlobal) 155 tMock = mock.NewTarget(bmd) 156 ) 157 core.T = tMock 158 xreg.TestReset() 159 160 defer xreg.AbortAll(errors.New("test-abort-global")) 161 162 bmd.Add(bckFrom) 163 bmd.Add(bckTo) 164 165 xreg.RegNonBckXact(&space.TestFactory{}) 166 xreg.RegBckXact(&xs.TestBmvFactory{}) 167 cos.InitShortID(0) 168 169 rnsLRU := xreg.RenewLRU(cos.GenUUID()) 170 tassert.Errorf(t, !rnsLRU.IsRunning(), "new LRU must be created") 171 rnsRen := xreg.RenewBckRename(bckFrom, bckTo, cos.GenUUID(), 123, "phase") 172 xactBck := rnsRen.Entry.Get() 173 tassert.Errorf(t, rnsRen.Err == nil && xactBck != nil, "Xaction must be created") 174 175 xreg.AbortAll(errors.New("test-abort-g"), xact.ScopeG, xact.ScopeGB) 176 177 tassert.Errorf(t, rnsLRU.Entry.Get().IsAborted(), "AbortAllGlobal: expected global xaction to be aborted") 178 tassert.Errorf(t, !xactBck.IsAborted(), "AbortAllGlobal: expected bucket xaction to be running: %s", xactBck) 179 } 180 181 func TestXactionAbortBuckets(t *testing.T) { 182 var ( 183 bmd = mock.NewBaseBownerMock() 184 bckFrom = meta.NewBck("test", apc.AIS, cmn.NsGlobal) 185 bckTo = meta.NewBck("test", apc.AIS, cmn.NsGlobal) 186 tMock = mock.NewTarget(bmd) 187 ) 188 core.T = tMock 189 xreg.TestReset() 190 191 defer xreg.AbortAll(errors.New("abort-buckets")) 192 193 bmd.Add(bckFrom) 194 bmd.Add(bckTo) 195 196 xreg.RegNonBckXact(&space.TestFactory{}) 197 xreg.RegBckXact(&xs.TestBmvFactory{}) 198 cos.InitShortID(0) 199 200 rnsLRU := xreg.RenewLRU(cos.GenUUID()) 201 tassert.Errorf(t, !rnsLRU.IsRunning(), "new LRU must be created") 202 rns := xreg.RenewBckRename(bckFrom, bckTo, cos.GenUUID(), 123, "phase") 203 xactBck := rns.Entry.Get() 204 tassert.Errorf(t, rns.Err == nil && xactBck != nil, "Xaction must be created") 205 206 xreg.AbortAllBuckets(nil, bckFrom) 207 208 tassert.Errorf(t, !rnsLRU.Entry.Get().IsAborted(), "AbortAllGlobal: expected global xaction to keep running") 209 tassert.Errorf(t, xactBck.IsAborted(), "AbortAllGlobal: expected bucket xaction to be aborted") 210 } 211 212 // TODO: extend this to include all cases of the Query 213 func TestXactionQueryFinished(t *testing.T) { 214 type testConfig struct { 215 bckNil bool 216 kindNil bool 217 showActive bool 218 expectedStatsLen int 219 } 220 var ( 221 bmd = mock.NewBaseBownerMock() 222 bck1 = meta.NewBck("test1", apc.AIS, cmn.NsGlobal) 223 bck2 = meta.NewBck("test2", apc.AIS, cmn.NsGlobal) 224 bck3 = meta.NewBck("test3", apc.GCP, cmn.NsGlobal) 225 tMock = mock.NewTarget(bmd) 226 ) 227 core.T = tMock 228 xreg.TestReset() 229 230 defer xreg.AbortAll(nil) 231 232 bmd.Add(bck1) 233 bmd.Add(bck2) 234 bmd.Add(bck3) 235 236 xreg.RegBckXact(&xs.TestXFactory{}) 237 xreg.RegBckXact(&xs.TestBmvFactory{}) 238 cos.InitShortID(0) 239 240 rns1 := xreg.RenewBckRename(bck1, bck1, cos.GenUUID(), 123, "phase") 241 tassert.Errorf(t, rns1.Err == nil && rns1.Entry.Get() != nil, "Xaction must be created") 242 rns2 := xreg.RenewBckRename(bck2, bck2, cos.GenUUID(), 123, "phase") 243 tassert.Errorf(t, rns2.Err == nil && rns2.Entry.Get() != nil, "Xaction must be created %v", rns2.Err) 244 rns1.Entry.Get().Finish() 245 246 rns1 = xreg.RenewBckRename(bck1, bck1, cos.GenUUID(), 123, "phase") 247 tassert.Errorf(t, rns1.Err == nil && rns1.Entry.Get() != nil, "Xaction must be created") 248 249 rns3 := xreg.RenewPrefetch(cos.GenUUID(), bck3, &apc.PrefetchMsg{}) 250 tassert.Fatalf(t, cmn.IsErrRemoteBckNotFound(rns3.Err), "x-prefetch: expected 'cloud bucket does not exist' error") 251 252 xactBck1 := rns1.Entry.Get() 253 254 scenarioName := func(tc testConfig) string { 255 name := "" 256 if tc.bckNil { 257 name += "bck:empty" 258 } else { 259 name += "bck:set" 260 } 261 if tc.kindNil { 262 name += "/kind:empty" 263 } else { 264 name += "/kind:set" 265 } 266 if tc.showActive { 267 name += "/state:running" 268 } else { 269 name += "/state:finished" 270 } 271 return name 272 } 273 274 f := func(t *testing.T, tc testConfig) { 275 t.Run(scenarioName(tc), func(t *testing.T) { 276 query := xreg.Flt{} 277 if !tc.bckNil { 278 query.Bck = bck1 279 } 280 if !tc.kindNil { 281 query.Kind = xactBck1.Kind() 282 } 283 query.OnlyRunning = &tc.showActive 284 stats, err := xreg.GetSnap(query) 285 tassert.Errorf(t, err == nil, "Error fetching Xact Stats %v for query %v", err, query) 286 tassert.Errorf(t, len(stats) == tc.expectedStatsLen, "Length of result: %d != %d", len(stats), tc.expectedStatsLen) 287 }) 288 } 289 tests := []testConfig{ 290 {bckNil: true, kindNil: true, showActive: false, expectedStatsLen: 1}, 291 {bckNil: true, kindNil: false, showActive: false, expectedStatsLen: 1}, 292 {bckNil: false, kindNil: true, showActive: false, expectedStatsLen: 1}, 293 {bckNil: false, kindNil: false, showActive: false, expectedStatsLen: 1}, 294 } 295 for _, test := range tests { 296 f(t, test) 297 } 298 } 299 300 func TestBeid(t *testing.T) { 301 const div = uint64(100 * time.Millisecond) 302 num := 100 303 if testing.Short() { 304 num = 10 305 } 306 now := time.Now() 307 xreg.PrimeTime.Store(now.UnixNano()) 308 xreg.MyTime.Store(now.Add(time.Second).UnixNano()) 309 310 var ( 311 ids = make(map[string]struct{}, num) 312 tags = []string{"tag1", "tag2"} 313 cnt int 314 ) 315 for i := range num { 316 beid, _, _ := xreg.GenBEID(div, tags[i%2]) 317 if _, ok := ids[beid]; ok { 318 t.Fatalf("%d: %s duplicated", i, beid) 319 } 320 ids[beid] = struct{}{} 321 322 time.Sleep(time.Millisecond) 323 id, _, _ := xreg.GenBEID(div, tags[i%2]) 324 if beid != id { 325 cnt++ 326 } 327 328 time.Sleep(time.Duration(div)) 329 } 330 if cnt > 0 { 331 fmt.Printf("Warning: failed to reproduce %d time%s out of %d\n", cnt, cos.Plural(cnt), num) 332 } 333 }