github.com/mutagen-io/mutagen@v0.18.0-rc1/pkg/state/tracker_test.go (about)

     1  package state
     2  
     3  import (
     4  	"context"
     5  	"testing"
     6  	"time"
     7  )
     8  
     9  // trackerTestTimeout prevents tracker tests from timing out. It also sets an
    10  // indirect performance boundary on update detection time.
    11  const trackerTestTimeout = 1 * time.Second
    12  
    13  // TestTracker tests Tracker.
    14  func TestTracker(t *testing.T) {
    15  	// Create a tracker.
    16  	tracker := NewTracker()
    17  
    18  	// Create a channel for Goroutine communication.
    19  	handoff := make(chan bool)
    20  
    21  	// Create a cancellable context that we can use to tracking testing. Ensure
    22  	// that it's cancelled by the time we return, just in case it isn't
    23  	// cancelled during testing.
    24  	ctx, cancel := context.WithCancel(context.Background())
    25  	defer cancel()
    26  
    27  	// Start a Goroutine with which we'll coordinate.
    28  	go func() {
    29  		// Wait indefinitely for a successful change from the initial tracker
    30  		// state (1).
    31  		firstState, err := tracker.WaitForChange(context.Background(), 1)
    32  		if err != nil || firstState != 2 {
    33  			handoff <- false
    34  			return
    35  		}
    36  		handoff <- true
    37  
    38  		// Perform a preempted wait and ensure that the state doesn't change.
    39  		secondState, err := tracker.WaitForChange(ctx, firstState)
    40  		if err != context.Canceled || secondState != firstState {
    41  			handoff <- false
    42  			return
    43  		}
    44  		handoff <- true
    45  
    46  		// Wait for termination and ensure that the state doesn't change.
    47  		finalState, err := tracker.WaitForChange(context.Background(), secondState)
    48  		handoff <- (finalState == firstState && err == ErrTrackingTerminated)
    49  	}()
    50  
    51  	// Notify of a change and wait for a response.
    52  	tracker.NotifyOfChange()
    53  	select {
    54  	case value := <-handoff:
    55  		if !value {
    56  			t.Fatal("received failure on state tracking")
    57  		}
    58  	case <-time.After(trackerTestTimeout):
    59  		t.Fatal("timeout failure on state tracking")
    60  	}
    61  
    62  	// Cancel the polling context and wait for a response.
    63  	cancel()
    64  	select {
    65  	case value := <-handoff:
    66  		if !value {
    67  			t.Fatal("received failure on state tracking with cancellation")
    68  		}
    69  	case <-time.After(trackerTestTimeout):
    70  		t.Fatal("timeout failure on state tracking with cancellation")
    71  	}
    72  
    73  	// Terminate tracking and wait for a response.
    74  	tracker.Terminate()
    75  	select {
    76  	case value := <-handoff:
    77  		if !value {
    78  			t.Fatal("received failure on tracking termination")
    79  		}
    80  	case <-time.After(trackerTestTimeout):
    81  		t.Fatal("timeout failure on tracking termination")
    82  	}
    83  }