github.com/haraldrudell/parl@v0.4.176/win-or-waiter-core_test.go (about)

     1  /*
     2  © 2022–present Harald Rudell <harald.rudell@gmail.com> (https://haraldrudell.github.io/haraldrudell/)
     3  ISC License
     4  */
     5  
     6  package parl
     7  
     8  import (
     9  	"testing"
    10  	"time"
    11  )
    12  
    13  func TestNewWinOrWaiterCore(t *testing.T) {
    14  	var winOrWaiterStrategy = WinOrWaiterAnyValue
    15  	var shortTime = time.Millisecond
    16  
    17  	var calculatorInvoked = NewMutexWait()
    18  	var completeCalculation = NewMutexWait()
    19  	var calculator = func() (err error) {
    20  		calculatorInvoked.Unlock()
    21  		completeCalculation.Wait()
    22  		return
    23  	}
    24  	var calculationReference *Future[time.Time]
    25  	var result time.Time
    26  	var isValid bool
    27  
    28  	var winOrWaiter *WinOrWaiterCore = NewWinOrWaiterCore(winOrWaiterStrategy, calculator)
    29  
    30  	if winOrWaiter.strategy != winOrWaiterStrategy {
    31  		t.Errorf("bad startegy: %d exp %d", winOrWaiter.strategy, winOrWaiterStrategy)
    32  	}
    33  	if winOrWaiter.isCalculationPut.Load() {
    34  		t.Error("winOrWaiter.isCalculationPut true")
    35  	}
    36  	if winOrWaiter.calculation.Load() != nil {
    37  		t.Error("winOrWaiter.calculation not nil")
    38  	}
    39  	if winOrWaiter.winnerPicker.Load() {
    40  		t.Error("winOrWaiter.winnerPicker true")
    41  	}
    42  
    43  	// first thread gets stuck in calculator func
    44  	var calculatorThread = NewMutexWait()
    45  	go func() {
    46  		defer calculatorThread.Unlock()
    47  
    48  		winOrWaiter.WinOrWait()
    49  	}()
    50  	t.Log("waiting for calculator invocation…")
    51  	calculatorInvoked.Wait()
    52  
    53  	if !winOrWaiter.isCalculationPut.Load() {
    54  		t.Error("2 winOrWaiter.isCalculationPut false")
    55  	}
    56  	if winOrWaiter.calculation.Load() == nil {
    57  		t.Error("2 winOrWaiter.calculation nil")
    58  	}
    59  	if !winOrWaiter.winnerPicker.Load() {
    60  		t.Error("2 winOrWaiter.winnerPicker false")
    61  	}
    62  
    63  	// second thread gets stuck in at ww.calculator.RWMutex
    64  	var loserThread = NewMutexWait()
    65  	var loserThreadUp = NewMutexWait()
    66  	go func() {
    67  		defer loserThread.Unlock()
    68  
    69  		loserThreadUp.Unlock()
    70  		winOrWaiter.WinOrWait()
    71  	}()
    72  	t.Log("waiting for loser thread…")
    73  	loserThreadUp.Wait()
    74  
    75  	time.Sleep(shortTime)
    76  
    77  	if calculatorThread.IsUnlocked() {
    78  		t.Error("calculatorThread exited too soon")
    79  	}
    80  	if loserThread.IsUnlocked() {
    81  		t.Error("loserThread exited too soon")
    82  	}
    83  
    84  	completeCalculation.Unlock()
    85  
    86  	calculatorThread.Wait()
    87  	loserThread.Wait()
    88  
    89  	calculationReference = winOrWaiter.calculation.Load()
    90  	if calculationReference == nil {
    91  		t.Error("3 winOrWaiter.calculation.Get nil")
    92  		t.FailNow()
    93  	}
    94  	if !calculationReference.IsCompleted() {
    95  		t.Error("3 calculationReference.IsCompleted false")
    96  	}
    97  	result, isValid = calculationReference.Result()
    98  	if !isValid {
    99  		t.Error("3 isValid false")
   100  	}
   101  	if result.IsZero() {
   102  		t.Error("3 result IsZero")
   103  	}
   104  	if winOrWaiter.winnerPicker.Load() {
   105  		t.Error("3 winOrWaiter.winnerPicker true")
   106  	}
   107  }