github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/worker/remoterelations/mock_test.go (about)

     1  // Copyright 2016 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package remoterelations_test
     5  
     6  import (
     7  	"sync"
     8  
     9  	"github.com/juju/errors"
    10  	"github.com/juju/names/v5"
    11  	"github.com/juju/testing"
    12  	"gopkg.in/macaroon.v2"
    13  	"gopkg.in/tomb.v2"
    14  
    15  	"github.com/juju/juju/api"
    16  	apitesting "github.com/juju/juju/api/testing"
    17  	apiwatcher "github.com/juju/juju/api/watcher"
    18  	apiservererrors "github.com/juju/juju/apiserver/errors"
    19  	"github.com/juju/juju/core/crossmodel"
    20  	"github.com/juju/juju/core/life"
    21  	"github.com/juju/juju/core/status"
    22  	"github.com/juju/juju/core/watcher"
    23  	"github.com/juju/juju/rpc/params"
    24  )
    25  
    26  type mockRelationsFacade struct {
    27  	mu                                 sync.Mutex
    28  	stub                               *testing.Stub
    29  	remoteApplicationsWatcher          *mockStringsWatcher
    30  	remoteApplicationRelationsWatchers map[string]*mockStringsWatcher
    31  	remoteApplications                 map[string]*mockRemoteApplication
    32  	relations                          map[string]*mockRelation
    33  	relationsEndpoints                 map[string]*relationEndpointInfo
    34  	remoteRelationWatchers             map[string]*mockRemoteRelationWatcher
    35  	controllerInfo                     map[string]*api.Info
    36  }
    37  
    38  func newMockRelationsFacade(stub *testing.Stub) *mockRelationsFacade {
    39  	return &mockRelationsFacade{
    40  		stub:                               stub,
    41  		remoteApplications:                 make(map[string]*mockRemoteApplication),
    42  		relations:                          make(map[string]*mockRelation),
    43  		relationsEndpoints:                 make(map[string]*relationEndpointInfo),
    44  		remoteApplicationsWatcher:          newMockStringsWatcher(),
    45  		remoteApplicationRelationsWatchers: make(map[string]*mockStringsWatcher),
    46  		remoteRelationWatchers:             make(map[string]*mockRemoteRelationWatcher),
    47  		controllerInfo:                     make(map[string]*api.Info),
    48  	}
    49  }
    50  
    51  func (m *mockRelationsFacade) WatchRemoteApplications() (watcher.StringsWatcher, error) {
    52  	m.mu.Lock()
    53  	defer m.mu.Unlock()
    54  	m.stub.MethodCall(m, "WatchRemoteApplications")
    55  	if err := m.stub.NextErr(); err != nil {
    56  		return nil, err
    57  	}
    58  	return m.remoteApplicationsWatcher, nil
    59  }
    60  
    61  func (m *mockRelationsFacade) remoteApplicationRelationsWatcher(name string) (*mockStringsWatcher, bool) {
    62  	m.mu.Lock()
    63  	defer m.mu.Unlock()
    64  	w, ok := m.remoteApplicationRelationsWatchers[name]
    65  	return w, ok
    66  }
    67  
    68  func (m *mockRelationsFacade) removeApplication(name string) (*mockStringsWatcher, bool) {
    69  	m.mu.Lock()
    70  	defer m.mu.Unlock()
    71  	w, ok := m.remoteApplicationRelationsWatchers[name]
    72  	delete(m.remoteApplications, name)
    73  	return w, ok
    74  }
    75  
    76  func (m *mockRelationsFacade) removeRelation(key string) (*mockRemoteRelationWatcher, bool) {
    77  	m.mu.Lock()
    78  	defer m.mu.Unlock()
    79  	w, ok := m.remoteRelationWatchers[key]
    80  	delete(m.relations, key)
    81  	return w, ok
    82  }
    83  
    84  func (m *mockRelationsFacade) updateRelationLife(key string, life life.Value) (*mockRemoteRelationWatcher, bool) {
    85  	m.mu.Lock()
    86  	defer m.mu.Unlock()
    87  	w, ok := m.remoteRelationWatchers[key]
    88  	m.relations[key].life = life
    89  	return w, ok
    90  }
    91  
    92  func (m *mockRelationsFacade) WatchRemoteApplicationRelations(application string) (watcher.StringsWatcher, error) {
    93  	m.mu.Lock()
    94  	defer m.mu.Unlock()
    95  	m.stub.MethodCall(m, "WatchRemoteApplicationRelations", application)
    96  	if err := m.stub.NextErr(); err != nil {
    97  		return nil, err
    98  	}
    99  	m.remoteApplicationRelationsWatchers[application] = newMockStringsWatcher()
   100  	return m.remoteApplicationRelationsWatchers[application], nil
   101  }
   102  
   103  func (m *mockRelationsFacade) ExportEntities(entities []names.Tag) ([]params.TokenResult, error) {
   104  	m.stub.MethodCall(m, "ExportEntities", entities)
   105  	if err := m.stub.NextErr(); err != nil {
   106  		return nil, err
   107  	}
   108  	result := make([]params.TokenResult, len(entities))
   109  	for i, e := range entities {
   110  		result[i] = params.TokenResult{
   111  			Token: "token-" + e.Id(),
   112  		}
   113  	}
   114  	return result, nil
   115  }
   116  
   117  func (m *mockRelationsFacade) ImportRemoteEntity(entity names.Tag, token string) error {
   118  	m.stub.MethodCall(m, "ImportRemoteEntity", entity, token)
   119  	return m.stub.NextErr()
   120  }
   121  
   122  func (m *mockRelationsFacade) SaveMacaroon(entity names.Tag, mac *macaroon.Macaroon) error {
   123  	m.stub.MethodCall(m, "SaveMacaroon", entity, mac)
   124  	return m.stub.NextErr()
   125  }
   126  
   127  func (m *mockRelationsFacade) GetToken(entity names.Tag) (string, error) {
   128  	m.stub.MethodCall(m, "GetToken", entity)
   129  	if err := m.stub.NextErr(); err != nil {
   130  		return "", err
   131  	}
   132  	return "token-" + entity.Id(), nil
   133  }
   134  
   135  func (m *mockRelationsFacade) RemoteApplications(names []string) ([]params.RemoteApplicationResult, error) {
   136  	m.mu.Lock()
   137  	defer m.mu.Unlock()
   138  	m.stub.MethodCall(m, "RemoteApplications", names)
   139  	if err := m.stub.NextErr(); err != nil {
   140  		return nil, err
   141  	}
   142  	mac, err := apitesting.NewMacaroon("test")
   143  	if err != nil {
   144  		return nil, err
   145  	}
   146  	result := make([]params.RemoteApplicationResult, len(names))
   147  	for i, name := range names {
   148  		if app, ok := m.remoteApplications[name]; ok {
   149  			result[i] = params.RemoteApplicationResult{
   150  				Result: &params.RemoteApplication{
   151  					Name:            app.name,
   152  					OfferUUID:       app.offeruuid,
   153  					Life:            app.life,
   154  					ModelUUID:       app.modelUUID,
   155  					IsConsumerProxy: app.registered,
   156  					Status:          string(app.status),
   157  					ConsumeVersion:  app.consumeVersion,
   158  					Macaroon:        mac,
   159  				},
   160  			}
   161  		} else {
   162  			result[i] = params.RemoteApplicationResult{
   163  				Error: apiservererrors.ServerError(errors.NotFoundf(name))}
   164  		}
   165  	}
   166  	return result, nil
   167  }
   168  
   169  func (m *mockRelationsFacade) ConsumeRemoteSecretChanges(changes []watcher.SecretRevisionChange) error {
   170  	m.mu.Lock()
   171  	defer m.mu.Unlock()
   172  	m.stub.MethodCall(m, "ConsumeRemoteSecretChanges", changes)
   173  	return nil
   174  }
   175  
   176  type relationEndpointInfo struct {
   177  	localApplicationName string
   178  	localEndpoint        params.RemoteEndpoint
   179  	remoteEndpointName   string
   180  }
   181  
   182  func (m *mockRelationsFacade) Relations(keys []string) ([]params.RemoteRelationResult, error) {
   183  	m.mu.Lock()
   184  	defer m.mu.Unlock()
   185  	m.stub.MethodCall(m, "Relations", keys)
   186  	if err := m.stub.NextErr(); err != nil {
   187  		return nil, err
   188  	}
   189  	result := make([]params.RemoteRelationResult, len(keys))
   190  	for i, key := range keys {
   191  		if rel, ok := m.relations[key]; ok {
   192  			result[i].Result = &params.RemoteRelation{
   193  				Id:        rel.id,
   194  				Life:      rel.life,
   195  				Suspended: rel.Suspended(),
   196  				Key:       keys[i],
   197  			}
   198  			if epInfo, ok := m.relationsEndpoints[key]; ok {
   199  				result[i].Result.RemoteEndpointName = epInfo.remoteEndpointName
   200  				result[i].Result.Endpoint = epInfo.localEndpoint
   201  				result[i].Result.ApplicationName = epInfo.localApplicationName
   202  			}
   203  		} else {
   204  			result[i].Error = apiservererrors.ServerError(errors.NotFoundf(key))
   205  		}
   206  	}
   207  	return result, nil
   208  }
   209  
   210  func (m *mockRelationsFacade) remoteRelationWatcher(key string) (*mockRemoteRelationWatcher, bool) {
   211  	m.mu.Lock()
   212  	defer m.mu.Unlock()
   213  	w, ok := m.remoteRelationWatchers[key]
   214  	return w, ok
   215  }
   216  
   217  func (m *mockRelationsFacade) WatchLocalRelationChanges(relationKey string) (apiwatcher.RemoteRelationWatcher, error) {
   218  	m.mu.Lock()
   219  	defer m.mu.Unlock()
   220  	m.stub.MethodCall(m, "WatchLocalRelationChanges", relationKey)
   221  	if err := m.stub.NextErr(); err != nil {
   222  		return nil, err
   223  	}
   224  	m.remoteRelationWatchers[relationKey] = newMockRemoteRelationWatcher()
   225  	return m.remoteRelationWatchers[relationKey], nil
   226  }
   227  
   228  func (m *mockRelationsFacade) ConsumeRemoteRelationChange(change params.RemoteRelationChangeEvent) error {
   229  	m.stub.MethodCall(m, "ConsumeRemoteRelationChange", change)
   230  	if err := m.stub.NextErr(); err != nil {
   231  		return err
   232  	}
   233  	return nil
   234  }
   235  
   236  func (m *mockRelationsFacade) ControllerAPIInfoForModel(modelUUID string) (*api.Info, error) {
   237  	m.stub.MethodCall(m, "ControllerAPIInfoForModel", modelUUID)
   238  	if err := m.stub.NextErr(); err != nil {
   239  		return nil, err
   240  	}
   241  	return m.controllerInfo[modelUUID], nil
   242  }
   243  
   244  func (m *mockRelationsFacade) SetRemoteApplicationStatus(applicationName string, status status.Status, message string) error {
   245  	m.stub.MethodCall(m, "SetRemoteApplicationStatus", applicationName, status.String(), message)
   246  	return nil
   247  }
   248  
   249  func (m *mockRelationsFacade) UpdateControllerForModel(controller crossmodel.ControllerInfo, modelUUID string) error {
   250  	m.stub.MethodCall(m, "UpdateControllerForModel", controller, modelUUID)
   251  	if err := m.stub.NextErr(); err != nil {
   252  		return err
   253  	}
   254  	return nil
   255  }
   256  
   257  type mockRemoteRelationsFacade struct {
   258  	mu                      sync.Mutex
   259  	stub                    *testing.Stub
   260  	remoteRelationWatchers  map[string]*mockRemoteRelationWatcher
   261  	relationsStatusWatchers map[string]*mockRelationStatusWatcher
   262  	offersStatusWatchers    map[string]*mockOfferStatusWatcher
   263  	secretsRevisionWatchers map[string]*mockSecretsRevisionWatcher
   264  }
   265  
   266  func newMockRemoteRelationsFacade(stub *testing.Stub) *mockRemoteRelationsFacade {
   267  	return &mockRemoteRelationsFacade{
   268  		stub:                    stub,
   269  		remoteRelationWatchers:  make(map[string]*mockRemoteRelationWatcher),
   270  		relationsStatusWatchers: make(map[string]*mockRelationStatusWatcher),
   271  		offersStatusWatchers:    make(map[string]*mockOfferStatusWatcher),
   272  		secretsRevisionWatchers: make(map[string]*mockSecretsRevisionWatcher),
   273  	}
   274  }
   275  
   276  func (m *mockRemoteRelationsFacade) Close() error {
   277  	m.stub.MethodCall(m, "Close")
   278  	return nil
   279  }
   280  
   281  func (m *mockRemoteRelationsFacade) PublishRelationChange(change params.RemoteRelationChangeEvent) error {
   282  	m.stub.MethodCall(m, "PublishRelationChange", change)
   283  	if err := m.stub.NextErr(); err != nil {
   284  		return err
   285  	}
   286  	return nil
   287  }
   288  
   289  func (m *mockRemoteRelationsFacade) RegisterRemoteRelations(relations ...params.RegisterRemoteRelationArg) ([]params.RegisterRemoteRelationResult, error) {
   290  	m.stub.MethodCall(m, "RegisterRemoteRelations", relations)
   291  	if err := m.stub.NextErr(); err != nil {
   292  		return nil, err
   293  	}
   294  	result := make([]params.RegisterRemoteRelationResult, len(relations))
   295  	mac, err := apitesting.NewMacaroon("apimac")
   296  	if err != nil {
   297  		return nil, err
   298  	}
   299  	for i, rel := range relations {
   300  		result[i].Result = &params.RemoteRelationDetails{
   301  			Token:    "token-" + rel.OfferUUID,
   302  			Macaroon: mac,
   303  		}
   304  	}
   305  	return result, nil
   306  }
   307  
   308  func (m *mockRemoteRelationsFacade) remoteRelationWatcher(key string) (*mockRemoteRelationWatcher, bool) {
   309  	m.mu.Lock()
   310  	defer m.mu.Unlock()
   311  	w, ok := m.remoteRelationWatchers[key]
   312  	return w, ok
   313  }
   314  
   315  func (m *mockRemoteRelationsFacade) WatchRelationChanges(relationToken string, appToken string, mac macaroon.Slice) (apiwatcher.RemoteRelationWatcher, error) {
   316  	m.mu.Lock()
   317  	defer m.mu.Unlock()
   318  	m.stub.MethodCall(m, "WatchRelationChanges", relationToken, appToken, mac)
   319  	if err := m.stub.NextErr(); err != nil {
   320  		return nil, err
   321  	}
   322  	m.remoteRelationWatchers[relationToken] = newMockRemoteRelationWatcher()
   323  	return m.remoteRelationWatchers[relationToken], nil
   324  }
   325  
   326  func (m *mockRemoteRelationsFacade) relationsStatusWatcher(key string) (*mockRelationStatusWatcher, bool) {
   327  	m.mu.Lock()
   328  	defer m.mu.Unlock()
   329  	w, ok := m.relationsStatusWatchers[key]
   330  	return w, ok
   331  }
   332  
   333  func (m *mockRemoteRelationsFacade) secretsRevisionWatcher(key string) (*mockSecretsRevisionWatcher, bool) {
   334  	m.mu.Lock()
   335  	defer m.mu.Unlock()
   336  	w, ok := m.secretsRevisionWatchers[key]
   337  	return w, ok
   338  }
   339  
   340  func (m *mockRemoteRelationsFacade) WatchRelationSuspendedStatus(arg params.RemoteEntityArg) (watcher.RelationStatusWatcher, error) {
   341  	m.mu.Lock()
   342  	defer m.mu.Unlock()
   343  	m.stub.MethodCall(m, "WatchRelationSuspendedStatus", arg.Token, arg.Macaroons)
   344  	if err := m.stub.NextErr(); err != nil {
   345  		return nil, err
   346  	}
   347  	m.relationsStatusWatchers[arg.Token] = newMockRelationStatusWatcher()
   348  	return m.relationsStatusWatchers[arg.Token], nil
   349  }
   350  
   351  func (m *mockRemoteRelationsFacade) WatchOfferStatus(arg params.OfferArg) (watcher.OfferStatusWatcher, error) {
   352  	m.mu.Lock()
   353  	defer m.mu.Unlock()
   354  	m.stub.MethodCall(m, "WatchOfferStatus", arg.OfferUUID, arg.Macaroons)
   355  	if err := m.stub.NextErr(); err != nil {
   356  		return nil, err
   357  	}
   358  	m.offersStatusWatchers[arg.OfferUUID] = newMockOfferStatusWatcher()
   359  	return m.offersStatusWatchers[arg.OfferUUID], nil
   360  }
   361  
   362  // RelationUnitSettings returns the relation unit settings for the given relation units in the remote model.
   363  func (m *mockRemoteRelationsFacade) RelationUnitSettings(relationUnits []params.RemoteRelationUnit) ([]params.SettingsResult, error) {
   364  	m.mu.Lock()
   365  	defer m.mu.Unlock()
   366  	m.stub.MethodCall(m, "RelationUnitSettings", relationUnits)
   367  	if err := m.stub.NextErr(); err != nil {
   368  		return nil, err
   369  	}
   370  	result := make([]params.SettingsResult, len(relationUnits))
   371  	for i := range relationUnits {
   372  		result[i].Settings = map[string]string{
   373  			"foo": "bar",
   374  		}
   375  	}
   376  	return result, nil
   377  }
   378  
   379  func (m *mockRemoteRelationsFacade) WatchConsumedSecretsChanges(appToken, relToken string, mac *macaroon.Macaroon) (watcher.SecretsRevisionWatcher, error) {
   380  	m.mu.Lock()
   381  	defer m.mu.Unlock()
   382  	m.stub.MethodCall(m, "WatchConsumedSecretsChanges", appToken, relToken, mac)
   383  	if err := m.stub.NextErr(); err != nil {
   384  		return nil, err
   385  	}
   386  	m.secretsRevisionWatchers[appToken] = newMockSecretsRevisionWatcher()
   387  	return m.secretsRevisionWatchers[appToken], nil
   388  }
   389  
   390  type mockWatcher struct {
   391  	testing.Stub
   392  	tomb.Tomb
   393  	mu         sync.Mutex
   394  	terminated bool
   395  }
   396  
   397  func (w *mockWatcher) killed() bool {
   398  	w.mu.Lock()
   399  	defer w.mu.Unlock()
   400  	return w.terminated
   401  }
   402  
   403  func (w *mockWatcher) Kill() {
   404  	w.MethodCall(w, "Kill")
   405  	w.Tomb.Kill(nil)
   406  	w.mu.Lock()
   407  	defer w.mu.Unlock()
   408  	w.terminated = true
   409  }
   410  
   411  func (w *mockWatcher) Stop() error {
   412  	w.MethodCall(w, "Stop")
   413  	if err := w.NextErr(); err != nil {
   414  		return err
   415  	}
   416  	w.Tomb.Kill(nil)
   417  	return w.Tomb.Wait()
   418  }
   419  
   420  type mockStringsWatcher struct {
   421  	mockWatcher
   422  	changes chan []string
   423  }
   424  
   425  func newMockStringsWatcher() *mockStringsWatcher {
   426  	w := &mockStringsWatcher{changes: make(chan []string, 5)}
   427  	w.Tomb.Go(func() error {
   428  		<-w.Tomb.Dying()
   429  		return nil
   430  	})
   431  	return w
   432  }
   433  
   434  func (w *mockStringsWatcher) Changes() watcher.StringsChannel {
   435  	w.MethodCall(w, "Changes")
   436  	return w.changes
   437  }
   438  
   439  type mockSecretsRevisionWatcher struct {
   440  	mockWatcher
   441  	changes chan []watcher.SecretRevisionChange
   442  }
   443  
   444  func newMockSecretsRevisionWatcher() *mockSecretsRevisionWatcher {
   445  	w := &mockSecretsRevisionWatcher{
   446  		changes: make(chan []watcher.SecretRevisionChange, 1),
   447  	}
   448  	w.Tomb.Go(func() error {
   449  		<-w.Tomb.Dying()
   450  		return nil
   451  	})
   452  	return w
   453  }
   454  
   455  func (w *mockSecretsRevisionWatcher) Changes() watcher.SecretRevisionChannel {
   456  	w.MethodCall(w, "Changes")
   457  	return w.changes
   458  }
   459  
   460  type mockRemoteApplication struct {
   461  	testing.Stub
   462  	name           string
   463  	offeruuid      string
   464  	url            string
   465  	life           life.Value
   466  	modelUUID      string
   467  	registered     bool
   468  	status         status.Status
   469  	consumeVersion int
   470  }
   471  
   472  type mockRemoteRelationWatcher struct {
   473  	mockWatcher
   474  	changes chan params.RemoteRelationChangeEvent
   475  }
   476  
   477  func newMockRemoteRelationWatcher() *mockRemoteRelationWatcher {
   478  	w := &mockRemoteRelationWatcher{
   479  		changes: make(chan params.RemoteRelationChangeEvent, 1),
   480  	}
   481  	w.Tomb.Go(func() error {
   482  		<-w.Tomb.Dying()
   483  		return nil
   484  	})
   485  	return w
   486  }
   487  
   488  func (w *mockRemoteRelationWatcher) kill(err error) {
   489  	w.Tomb.Kill(err)
   490  }
   491  
   492  func (w *mockRemoteRelationWatcher) Changes() <-chan params.RemoteRelationChangeEvent {
   493  	w.MethodCall(w, "Changes")
   494  	return w.changes
   495  }
   496  
   497  type mockRelationStatusWatcher struct {
   498  	mockWatcher
   499  	changes chan []watcher.RelationStatusChange
   500  }
   501  
   502  func newMockRelationStatusWatcher() *mockRelationStatusWatcher {
   503  	w := &mockRelationStatusWatcher{
   504  		changes: make(chan []watcher.RelationStatusChange, 1),
   505  	}
   506  	w.Tomb.Go(func() error {
   507  		<-w.Tomb.Dying()
   508  		return nil
   509  	})
   510  	return w
   511  }
   512  
   513  func (w *mockRelationStatusWatcher) Changes() watcher.RelationStatusChannel {
   514  	w.MethodCall(w, "Changes")
   515  	return w.changes
   516  }
   517  
   518  type mockOfferStatusWatcher struct {
   519  	mockWatcher
   520  	changes chan []watcher.OfferStatusChange
   521  }
   522  
   523  func newMockOfferStatusWatcher() *mockOfferStatusWatcher {
   524  	w := &mockOfferStatusWatcher{
   525  		changes: make(chan []watcher.OfferStatusChange, 1),
   526  	}
   527  	w.Tomb.Go(func() error {
   528  		<-w.Tomb.Dying()
   529  		return nil
   530  	})
   531  	return w
   532  }
   533  
   534  func (w *mockOfferStatusWatcher) Changes() watcher.OfferStatusChannel {
   535  	w.MethodCall(w, "Changes")
   536  	return w.changes
   537  }
   538  
   539  func newMockRemoteApplication(name, url string) *mockRemoteApplication {
   540  	return &mockRemoteApplication{
   541  		name: name, url: url, life: life.Alive, offeruuid: "offer-" + name + "-uuid",
   542  		modelUUID:      "remote-model-uuid",
   543  		consumeVersion: 666,
   544  	}
   545  }
   546  
   547  func (r *mockRemoteApplication) Name() string {
   548  	r.MethodCall(r, "Name")
   549  	return r.name
   550  }
   551  
   552  func (r *mockRemoteApplication) SourceModel() names.ModelTag {
   553  	r.MethodCall(r, "SourceModel")
   554  	return names.NewModelTag(r.modelUUID)
   555  }
   556  
   557  func (r *mockRemoteApplication) Life() life.Value {
   558  	r.MethodCall(r, "Life")
   559  	return r.life
   560  }
   561  
   562  type mockRelation struct {
   563  	testing.Stub
   564  	sync.Mutex
   565  	id        int
   566  	life      life.Value
   567  	suspended bool
   568  }
   569  
   570  func newMockRelation(id int) *mockRelation {
   571  	return &mockRelation{
   572  		id:   id,
   573  		life: life.Alive,
   574  	}
   575  }
   576  
   577  func (r *mockRelation) Id() int {
   578  	r.MethodCall(r, "Id")
   579  	return r.id
   580  }
   581  
   582  func (r *mockRelation) Life() life.Value {
   583  	r.MethodCall(r, "Life")
   584  	return r.life
   585  }
   586  
   587  func (r *mockRelation) Suspended() bool {
   588  	r.Lock()
   589  	defer r.Unlock()
   590  	r.MethodCall(r, "Suspended")
   591  	return r.suspended
   592  }
   593  
   594  func (r *mockRelation) SetSuspended(suspended bool) {
   595  	r.Lock()
   596  	defer r.Unlock()
   597  	r.suspended = suspended
   598  }