github.com/NVIDIA/aistore@v1.3.23-0.20240517131212-7df6609be51d/cmn/tests/sync_test.go (about)

     1  // Package test provides tests for common low-level types and utilities for all aistore projects
     2  /*
     3   * Copyright (c) 2018-2023, NVIDIA CORPORATION. All rights reserved.
     4   */
     5  package tests_test
     6  
     7  import (
     8  	"sync"
     9  	"testing"
    10  	"time"
    11  
    12  	"github.com/NVIDIA/aistore/cmn/atomic"
    13  	"github.com/NVIDIA/aistore/cmn/cos"
    14  	"github.com/NVIDIA/aistore/tools"
    15  )
    16  
    17  func TestTimeoutGroupSmoke(t *testing.T) {
    18  	tools.CheckSkip(t, &tools.SkipTestArgs{Long: true})
    19  	wg := cos.NewTimeoutGroup()
    20  	wg.Add(1)
    21  	wg.Done()
    22  	if wg.WaitTimeout(time.Second) {
    23  		t.Error("wait timed out")
    24  	}
    25  }
    26  
    27  func TestTimeoutGroupWait(t *testing.T) {
    28  	tools.CheckSkip(t, &tools.SkipTestArgs{Long: true})
    29  	wg := cos.NewTimeoutGroup()
    30  	wg.Add(2)
    31  	wg.Done()
    32  	wg.Done()
    33  	wg.Wait()
    34  }
    35  
    36  func TestTimeoutGroupGoroutines(t *testing.T) {
    37  	tools.CheckSkip(t, &tools.SkipTestArgs{Long: true})
    38  	wg := cos.NewTimeoutGroup()
    39  
    40  	for range 100000 {
    41  		wg.Add(1)
    42  		go func() {
    43  			time.Sleep(time.Second * 2)
    44  			wg.Done()
    45  		}()
    46  	}
    47  
    48  	if wg.WaitTimeout(time.Second * 5) {
    49  		t.Error("wait timed out")
    50  	}
    51  }
    52  
    53  func TestTimeoutGroupTimeout(t *testing.T) {
    54  	tools.CheckSkip(t, &tools.SkipTestArgs{Long: true})
    55  	wg := cos.NewTimeoutGroup()
    56  	wg.Add(1)
    57  
    58  	go func() {
    59  		time.Sleep(time.Second * 3)
    60  		wg.Done()
    61  	}()
    62  
    63  	if !wg.WaitTimeout(time.Second) {
    64  		t.Error("group did not time out")
    65  	}
    66  
    67  	if wg.WaitTimeout(time.Second * 3) { // now wait for actual end of the job
    68  		t.Error("group timed out")
    69  	}
    70  }
    71  
    72  func TestTimeoutGroupStop(t *testing.T) {
    73  	tools.CheckSkip(t, &tools.SkipTestArgs{Long: true})
    74  	wg := cos.NewTimeoutGroup()
    75  	wg.Add(1)
    76  
    77  	go func() {
    78  		time.Sleep(time.Second * 3)
    79  		wg.Done()
    80  	}()
    81  
    82  	if !wg.WaitTimeout(time.Second) {
    83  		t.Error("group did not time out")
    84  	}
    85  
    86  	stopCh := make(chan struct{}, 1)
    87  	stopCh <- struct{}{}
    88  
    89  	timed, stopped := wg.WaitTimeoutWithStop(time.Second, stopCh)
    90  	if timed {
    91  		t.Error("group should not time out")
    92  	}
    93  
    94  	if !stopped {
    95  		t.Error("group should be stopped")
    96  	}
    97  
    98  	if timed, stopped = wg.WaitTimeoutWithStop(time.Second*3, stopCh); timed || stopped {
    99  		t.Error("group timed out or was stopped on finish")
   100  	}
   101  }
   102  
   103  func TestTimeoutGroupStopAndTimeout(t *testing.T) {
   104  	tools.CheckSkip(t, &tools.SkipTestArgs{Long: true})
   105  	wg := cos.NewTimeoutGroup()
   106  	wg.Add(1)
   107  
   108  	go func() {
   109  		time.Sleep(time.Second * 3)
   110  		wg.Done()
   111  	}()
   112  
   113  	stopCh := make(chan struct{}, 1)
   114  	timed, stopped := wg.WaitTimeoutWithStop(time.Second, stopCh)
   115  	if !timed {
   116  		t.Error("group should time out")
   117  	}
   118  
   119  	if stopped {
   120  		t.Error("group should not be stopped")
   121  	}
   122  
   123  	if timed, stopped = wg.WaitTimeoutWithStop(time.Second*3, stopCh); timed || stopped {
   124  		t.Error("group timed out or was stopped on finish")
   125  	}
   126  }
   127  
   128  func TestSemaphore(t *testing.T) {
   129  	tools.CheckSkip(t, &tools.SkipTestArgs{Long: true})
   130  	sema := cos.NewSemaphore(2)
   131  	sema.Acquire()
   132  	sema.Acquire()
   133  
   134  	select {
   135  	case <-sema.TryAcquire():
   136  		t.Error("unexpected acquire")
   137  	default:
   138  		break
   139  	}
   140  
   141  	sema.Release()
   142  
   143  	select {
   144  	case <-sema.TryAcquire():
   145  	default:
   146  		t.Error("expected acquire to happen")
   147  	}
   148  }
   149  
   150  func TestDynSemaphore(t *testing.T) {
   151  	tools.CheckSkip(t, &tools.SkipTestArgs{Long: true})
   152  	limit := 10
   153  
   154  	sema := cos.NewDynSemaphore(limit)
   155  
   156  	var i atomic.Int32
   157  	wg := &sync.WaitGroup{}
   158  	ch := make(chan int32, 10*limit)
   159  
   160  	for range 10 * limit {
   161  		sema.Acquire()
   162  		wg.Add(1)
   163  		go func() {
   164  			ch <- i.Inc()
   165  			time.Sleep(time.Millisecond)
   166  			i.Dec()
   167  			sema.Release()
   168  			wg.Done()
   169  		}()
   170  	}
   171  
   172  	wg.Wait()
   173  	close(ch)
   174  
   175  	res := int32(0)
   176  	for c := range ch {
   177  		res = max(res, c)
   178  	}
   179  
   180  	if int(res) != limit {
   181  		t.Fatalf("acutal limit %d was different than expected %d", res, limit)
   182  	}
   183  }