github.com/verrazzano/verrazzano@v1.7.0/platform-operator/internal/monitor/monitor_test.go (about)

     1  // Copyright (c) 2022, 2023, Oracle and/or its affiliates.
     2  // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.
     3  
     4  package monitor
     5  
     6  import (
     7  	"fmt"
     8  	"testing"
     9  	"time"
    10  
    11  	"github.com/stretchr/testify/assert"
    12  	ctrlerrors "github.com/verrazzano/verrazzano/pkg/controller/errors"
    13  )
    14  
    15  var fakeCompName = "fake-component-name"
    16  
    17  func TestMonitorTypeIsRunning(t *testing.T) {
    18  	a := assert.New(t)
    19  
    20  	m := &BackgroundProcessMonitorType{ComponentName: fakeCompName}
    21  	blocker := make(chan int)
    22  	finished := make(chan int)
    23  	operation := func() error {
    24  		defer func() { finished <- 0 }()
    25  		<-blocker
    26  		return nil
    27  	}
    28  
    29  	a.False(m.IsRunning())
    30  
    31  	m.Run(operation)
    32  	a.True(m.IsRunning())
    33  
    34  	// send to the channel to unblock operation
    35  	blocker <- 0
    36  
    37  	// block until the operation says it's finished
    38  	<-finished
    39  
    40  	// even after the operation is finished, the monitor should still be "running" unless reset
    41  	a.True(m.IsRunning())
    42  }
    43  
    44  func TestMonitorTypeCheckResultWhileRunning(t *testing.T) {
    45  	a := assert.New(t)
    46  
    47  	m := &BackgroundProcessMonitorType{ComponentName: fakeCompName}
    48  	blocker := make(chan int)
    49  	operation := func() error {
    50  		<-blocker
    51  		return nil
    52  	}
    53  
    54  	m.Run(operation)
    55  	res, err := m.CheckResult()
    56  	a.Equal(false, res)
    57  	a.Equal(ctrlerrors.RetryableError{Source: fakeCompName}, err)
    58  	blocker <- 0
    59  }
    60  
    61  func TestMonitorTypeCheckResult(t *testing.T) {
    62  	a := assert.New(t)
    63  
    64  	errMsg := "an error from the background operation"
    65  	tests := []struct {
    66  		success        bool
    67  		expectedResult bool
    68  		expectedError  error
    69  	}{
    70  		{
    71  			success:        true,
    72  			expectedResult: true,
    73  		},
    74  		{
    75  			success:        false,
    76  			expectedResult: false,
    77  		},
    78  	}
    79  
    80  	for _, tt := range tests {
    81  		m := &BackgroundProcessMonitorType{ComponentName: fakeCompName}
    82  		operation := func() error {
    83  			if tt.success {
    84  				return nil
    85  			}
    86  			return fmt.Errorf(errMsg)
    87  		}
    88  
    89  		// Run the background goroutine
    90  		m.Run(operation)
    91  
    92  		// CheckResult returns an error if the operation has not yet completed, so keep checking until complete
    93  		if res, ok := waitForResult(t, m); ok {
    94  			a.Equal(tt.expectedResult, res)
    95  		} else {
    96  			a.Fail("Expected a result from CheckResult but never received one")
    97  		}
    98  	}
    99  }
   100  
   101  // waitForResult waits for the background process result to be available. Returns the value of
   102  // the result and true if a result was received, or false if we timed out waiting.
   103  func waitForResult(t *testing.T, monitor *BackgroundProcessMonitorType) (bool, bool) {
   104  	var res, gotResult bool
   105  	for i := 0; i < 100; i++ {
   106  		var err error
   107  		// CheckResult returns an error if the operation is still running
   108  		res, err = monitor.CheckResult()
   109  		if err != nil {
   110  			t.Log("Waiting for result...")
   111  			time.Sleep(100 * time.Millisecond)
   112  			continue
   113  		}
   114  		gotResult = true
   115  		break
   116  	}
   117  	return res, gotResult
   118  }
   119  
   120  func TestMonitorTypeReset(t *testing.T) {
   121  	a := assert.New(t)
   122  
   123  	m := &BackgroundProcessMonitorType{ComponentName: fakeCompName}
   124  	operation := func() error {
   125  		return nil
   126  	}
   127  
   128  	// Run the background goroutine
   129  	m.Run(operation)
   130  
   131  	// Wait for the operation result to be available
   132  	if res, ok := waitForResult(t, m); ok {
   133  		a.True(res)
   134  	} else {
   135  		a.Fail("Expected a result from CheckResult but never received one")
   136  	}
   137  
   138  	a.True(m.IsRunning())
   139  
   140  	m.Reset()
   141  	res, _ := m.CheckResult()
   142  	a.False(res)
   143  	a.False(m.IsRunning())
   144  }
   145  
   146  func TestMonitorTypeIsCompleted(t *testing.T) {
   147  	a := assert.New(t)
   148  
   149  	m := &BackgroundProcessMonitorType{ComponentName: fakeCompName}
   150  	blocker := make(chan int)
   151  	finished := make(chan int)
   152  	operation := func() error {
   153  		defer func() { finished <- 0 }()
   154  		<-blocker
   155  		return nil
   156  	}
   157  
   158  	m.Run(operation)
   159  	a.True(m.IsRunning())
   160  	m.SetCompleted()
   161  	a.True(m.IsCompleted())
   162  	a.False(m.IsRunning())
   163  
   164  	// send to the channel to unblock operation
   165  	blocker <- 0
   166  
   167  	// block until the operation says it's finished
   168  	<-finished
   169  }