github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/core/watcher/watchertest/notify.go (about)

     1  // Copyright 2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package watchertest
     5  
     6  import (
     7  	"time"
     8  
     9  	jc "github.com/juju/testing/checkers"
    10  	gc "gopkg.in/check.v1"
    11  	tomb "gopkg.in/tomb.v2"
    12  
    13  	"github.com/juju/juju/core/watcher"
    14  	"github.com/juju/juju/testing"
    15  )
    16  
    17  type MockNotifyWatcher struct {
    18  	tomb tomb.Tomb
    19  	ch   <-chan struct{}
    20  }
    21  
    22  func NewMockNotifyWatcher(ch <-chan struct{}) *MockNotifyWatcher {
    23  	w := &MockNotifyWatcher{ch: ch}
    24  	w.tomb.Go(func() error {
    25  		<-w.tomb.Dying()
    26  		return tomb.ErrDying
    27  	})
    28  	return w
    29  }
    30  
    31  func (w *MockNotifyWatcher) Changes() watcher.NotifyChannel {
    32  	return watcher.NotifyChannel(w.ch)
    33  }
    34  
    35  func (w *MockNotifyWatcher) Stop() error {
    36  	w.Kill()
    37  	return w.Wait()
    38  }
    39  
    40  func (w *MockNotifyWatcher) Kill() {
    41  	w.tomb.Kill(nil)
    42  }
    43  
    44  // KillErr can be used to kill the worker with
    45  // an error, to simulate a failing watcher.
    46  func (w *MockNotifyWatcher) KillErr(err error) {
    47  	w.tomb.Kill(err)
    48  }
    49  
    50  func (w *MockNotifyWatcher) Err() error {
    51  	return w.tomb.Err()
    52  }
    53  
    54  func (w *MockNotifyWatcher) Wait() error {
    55  	return w.tomb.Wait()
    56  }
    57  
    58  func NewNotifyWatcherC(c *gc.C, watcher watcher.NotifyWatcher) NotifyWatcherC {
    59  	return NotifyWatcherC{
    60  		C:       c,
    61  		Watcher: watcher,
    62  	}
    63  }
    64  
    65  type NotifyWatcherC struct {
    66  	*gc.C
    67  	Watcher watcher.NotifyWatcher
    68  }
    69  
    70  // AssertOneChange fails if no change is sent before a long time has passed; or
    71  // if, subsequent to that, any further change is sent before a short time has
    72  // passed.
    73  func (c NotifyWatcherC) AssertOneChange() {
    74  	select {
    75  	case _, ok := <-c.Watcher.Changes():
    76  		c.Assert(ok, jc.IsTrue)
    77  	case <-time.After(testing.LongWait):
    78  		c.Fatalf("watcher did not send change")
    79  	}
    80  	c.AssertNoChange()
    81  }
    82  
    83  // AssertNoChange fails if it manages to read a value from Changes before a
    84  // short time has passed.
    85  func (c NotifyWatcherC) AssertNoChange() {
    86  	select {
    87  	case _, ok := <-c.Watcher.Changes():
    88  		c.Fatalf("watcher sent unexpected change: (_, %v)", ok)
    89  	case <-time.After(testing.ShortWait):
    90  	}
    91  }
    92  
    93  func (c NotifyWatcherC) assertStops(changesClosed bool) {
    94  	c.Watcher.Kill()
    95  	wait := make(chan error)
    96  	go func() {
    97  		wait <- c.Watcher.Wait()
    98  	}()
    99  	select {
   100  	case <-time.After(testing.LongWait):
   101  		c.Fatalf("watcher never stopped")
   102  	case err := <-wait:
   103  		c.Assert(err, jc.ErrorIsNil)
   104  	}
   105  
   106  	select {
   107  	case _, ok := <-c.Watcher.Changes():
   108  		if ok || !changesClosed {
   109  			c.Fatalf("watcher sent unexpected change: (_, %v)", ok)
   110  		}
   111  	default:
   112  	}
   113  }
   114  
   115  // AssertStops Kills the watcher and asserts (1) that Wait completes without
   116  // error before a long time has passed; and (2) that Changes remains open but
   117  // no values are being sent.
   118  func (c NotifyWatcherC) AssertStops() {
   119  	c.assertStops(false)
   120  }
   121  
   122  // AssertKilled Kills the watcher and asserts that Wait completes without
   123  // error before a long time has passed.
   124  func (c NotifyWatcherC) AssertKilled() {
   125  	c.assertStops(true)
   126  }