github.com/kaleido-io/firefly@v0.0.0-20210622132723-8b4b6aacb971/internal/data/data_manager_test.go (about)

     1  // Copyright © 2021 Kaleido, Inc.
     2  //
     3  // SPDX-License-Identifier: Apache-2.0
     4  //
     5  // Licensed under the Apache License, Version 2.0 (the "License");
     6  // you may not use this file except in compliance with the License.
     7  // You may obtain a copy of the License at
     8  //
     9  //     http://www.apache.org/licenses/LICENSE-2.0
    10  //
    11  // Unless required by applicable law or agreed to in writing, software
    12  // distributed under the License is distributed on an "AS IS" BASIS,
    13  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14  // See the License for the specific language governing permissions and
    15  // limitations under the License.
    16  
    17  package data
    18  
    19  import (
    20  	"context"
    21  	"fmt"
    22  	"testing"
    23  
    24  	"github.com/kaleido-io/firefly/internal/config"
    25  	"github.com/kaleido-io/firefly/mocks/databasemocks"
    26  	"github.com/kaleido-io/firefly/mocks/dataexchangemocks"
    27  	"github.com/kaleido-io/firefly/pkg/fftypes"
    28  	"github.com/stretchr/testify/assert"
    29  	"github.com/stretchr/testify/mock"
    30  )
    31  
    32  func newTestDataManager(t *testing.T) (*dataManager, context.Context, func()) {
    33  	ctx, cancel := context.WithCancel(context.Background())
    34  	mdi := &databasemocks.Plugin{}
    35  	mdx := &dataexchangemocks.Plugin{}
    36  	dm, err := NewDataManager(ctx, mdi, mdx)
    37  	assert.NoError(t, err)
    38  	return dm.(*dataManager), ctx, cancel
    39  }
    40  
    41  func TestValidateE2E(t *testing.T) {
    42  
    43  	config.Reset()
    44  	dm, ctx, cancel := newTestDataManager(t)
    45  	defer cancel()
    46  	mdi := dm.database.(*databasemocks.Plugin)
    47  	data := &fftypes.Data{
    48  		Namespace: "ns1",
    49  		Validator: fftypes.ValidatorTypeJSON,
    50  		Datatype: &fftypes.DatatypeRef{
    51  			Name:    "customer",
    52  			Version: "0.0.1",
    53  		},
    54  		Value: fftypes.Byteable(`{"some":"json"}`),
    55  	}
    56  	data.Seal(ctx)
    57  	dt := &fftypes.Datatype{
    58  		ID:        fftypes.NewUUID(),
    59  		Validator: fftypes.ValidatorTypeJSON,
    60  		Value: fftypes.Byteable(`{
    61  			"properties": {
    62  				"field1": {
    63  					"type": "string"
    64  				}
    65  			},
    66  			"additionalProperties": false
    67  		}`),
    68  		Namespace: "ns1",
    69  		Name:      "customer",
    70  		Version:   "0.0.1",
    71  	}
    72  	mdi.On("GetDatatypeByName", mock.Anything, "ns1", "customer", "0.0.1").Return(dt, nil)
    73  	isValid, err := dm.ValidateAll(ctx, []*fftypes.Data{data})
    74  	assert.Regexp(t, "FF10198", err)
    75  	assert.False(t, isValid)
    76  
    77  	v, err := dm.getValidatorForDatatype(ctx, data.Namespace, data.Validator, data.Datatype)
    78  	err = v.Validate(ctx, data)
    79  	assert.Regexp(t, "FF10198", err)
    80  
    81  	data.Value = fftypes.Byteable(`{"field1":"value1"}`)
    82  	data.Seal(context.Background())
    83  	err = v.Validate(ctx, data)
    84  	assert.NoError(t, err)
    85  
    86  	isValid, err = dm.ValidateAll(ctx, []*fftypes.Data{data})
    87  	assert.NoError(t, err)
    88  	assert.True(t, isValid)
    89  
    90  }
    91  
    92  func TestInitBadDeps(t *testing.T) {
    93  	_, err := NewDataManager(context.Background(), nil, nil)
    94  	assert.Regexp(t, "FF10128", err)
    95  }
    96  
    97  func TestValidatorLookupCached(t *testing.T) {
    98  
    99  	config.Reset()
   100  	dm, ctx, cancel := newTestDataManager(t)
   101  	defer cancel()
   102  	mdi := dm.database.(*databasemocks.Plugin)
   103  	ref := &fftypes.DatatypeRef{
   104  		Name:    "customer",
   105  		Version: "0.0.1",
   106  	}
   107  	dt := &fftypes.Datatype{
   108  		ID:        fftypes.NewUUID(),
   109  		Validator: fftypes.ValidatorTypeJSON,
   110  		Value:     fftypes.Byteable(`{}`),
   111  		Name:      "customer",
   112  		Namespace: "0.0.1",
   113  	}
   114  	mdi.On("GetDatatypeByName", mock.Anything, "ns1", "customer", "0.0.1").Return(dt, nil).Once()
   115  	lookup1, err := dm.getValidatorForDatatype(ctx, "ns1", fftypes.ValidatorTypeJSON, ref)
   116  	assert.NoError(t, err)
   117  	assert.Equal(t, "customer", lookup1.(*jsonValidator).datatype.Name)
   118  
   119  	lookup2, err := dm.getValidatorForDatatype(ctx, "ns1", fftypes.ValidatorTypeJSON, ref)
   120  	assert.NoError(t, err)
   121  	assert.Equal(t, lookup1, lookup2)
   122  
   123  }
   124  
   125  func TestValidateBadHash(t *testing.T) {
   126  
   127  	config.Reset()
   128  	dm, ctx, cancel := newTestDataManager(t)
   129  	defer cancel()
   130  	mdi := dm.database.(*databasemocks.Plugin)
   131  	data := &fftypes.Data{
   132  		Namespace: "ns1",
   133  		Validator: fftypes.ValidatorTypeJSON,
   134  		Datatype: &fftypes.DatatypeRef{
   135  			Name:    "customer",
   136  			Version: "0.0.1",
   137  		},
   138  		Value: fftypes.Byteable(`{}`),
   139  		Hash:  fftypes.NewRandB32(),
   140  	}
   141  	dt := &fftypes.Datatype{
   142  		ID:        fftypes.NewUUID(),
   143  		Validator: fftypes.ValidatorTypeJSON,
   144  		Value:     fftypes.Byteable(`{}`),
   145  		Name:      "customer",
   146  		Namespace: "0.0.1",
   147  	}
   148  	mdi.On("GetDatatypeByName", mock.Anything, "ns1", "customer", "0.0.1").Return(dt, nil).Once()
   149  	_, err := dm.ValidateAll(ctx, []*fftypes.Data{data})
   150  	assert.Regexp(t, "FF10201", err)
   151  
   152  }
   153  
   154  func TestGetMessageDataDBError(t *testing.T) {
   155  
   156  	dm, ctx, cancel := newTestDataManager(t)
   157  	defer cancel()
   158  	mdi := dm.database.(*databasemocks.Plugin)
   159  	mdi.On("GetDataByID", mock.Anything, mock.Anything, true).Return(nil, fmt.Errorf("pop"))
   160  	data, foundAll, err := dm.GetMessageData(ctx, &fftypes.Message{
   161  		Header: fftypes.MessageHeader{ID: fftypes.NewUUID()},
   162  		Data:   fftypes.DataRefs{{ID: fftypes.NewUUID(), Hash: fftypes.NewRandB32()}},
   163  	}, true)
   164  	assert.Nil(t, data)
   165  	assert.False(t, foundAll)
   166  	assert.EqualError(t, err, "pop")
   167  
   168  }
   169  
   170  func TestGetMessageDataNilEntry(t *testing.T) {
   171  
   172  	dm, ctx, cancel := newTestDataManager(t)
   173  	defer cancel()
   174  	mdi := dm.database.(*databasemocks.Plugin)
   175  	mdi.On("GetDataByID", mock.Anything, mock.Anything, true).Return(nil, nil)
   176  	data, foundAll, err := dm.GetMessageData(ctx, &fftypes.Message{
   177  		Header: fftypes.MessageHeader{ID: fftypes.NewUUID()},
   178  		Data:   fftypes.DataRefs{nil},
   179  	}, true)
   180  	assert.Empty(t, data)
   181  	assert.False(t, foundAll)
   182  	assert.NoError(t, err)
   183  
   184  }
   185  
   186  func TestGetMessageDataNotFound(t *testing.T) {
   187  
   188  	dm, ctx, cancel := newTestDataManager(t)
   189  	defer cancel()
   190  	mdi := dm.database.(*databasemocks.Plugin)
   191  	mdi.On("GetDataByID", mock.Anything, mock.Anything, true).Return(nil, nil)
   192  	data, foundAll, err := dm.GetMessageData(ctx, &fftypes.Message{
   193  		Header: fftypes.MessageHeader{ID: fftypes.NewUUID()},
   194  		Data:   fftypes.DataRefs{{ID: fftypes.NewUUID(), Hash: fftypes.NewRandB32()}},
   195  	}, true)
   196  	assert.Empty(t, data)
   197  	assert.False(t, foundAll)
   198  	assert.NoError(t, err)
   199  
   200  }
   201  
   202  func TestGetMessageDataHashMismatch(t *testing.T) {
   203  
   204  	dm, ctx, cancel := newTestDataManager(t)
   205  	defer cancel()
   206  	mdi := dm.database.(*databasemocks.Plugin)
   207  	dataID := fftypes.NewUUID()
   208  	mdi.On("GetDataByID", mock.Anything, mock.Anything, true).Return(&fftypes.Data{
   209  		ID:   dataID,
   210  		Hash: fftypes.NewRandB32(),
   211  	}, nil)
   212  	data, foundAll, err := dm.GetMessageData(ctx, &fftypes.Message{
   213  		Header: fftypes.MessageHeader{ID: fftypes.NewUUID()},
   214  		Data:   fftypes.DataRefs{{ID: dataID, Hash: fftypes.NewRandB32()}},
   215  	}, true)
   216  	assert.Empty(t, data)
   217  	assert.False(t, foundAll)
   218  	assert.NoError(t, err)
   219  
   220  }
   221  
   222  func TestGetMessageDataOk(t *testing.T) {
   223  
   224  	dm, ctx, cancel := newTestDataManager(t)
   225  	defer cancel()
   226  	mdi := dm.database.(*databasemocks.Plugin)
   227  	dataID := fftypes.NewUUID()
   228  	hash := fftypes.NewRandB32()
   229  	mdi.On("GetDataByID", mock.Anything, mock.Anything, true).Return(&fftypes.Data{
   230  		ID:   dataID,
   231  		Hash: hash,
   232  	}, nil)
   233  	data, foundAll, err := dm.GetMessageData(ctx, &fftypes.Message{
   234  		Header: fftypes.MessageHeader{ID: fftypes.NewUUID()},
   235  		Data:   fftypes.DataRefs{{ID: dataID, Hash: hash}},
   236  	}, true)
   237  	assert.NotEmpty(t, data)
   238  	assert.Equal(t, *dataID, *data[0].ID)
   239  	assert.True(t, foundAll)
   240  	assert.NoError(t, err)
   241  
   242  }
   243  
   244  func TestCheckDatatypeVerifiesTheSchema(t *testing.T) {
   245  
   246  	dm, ctx, cancel := newTestDataManager(t)
   247  	defer cancel()
   248  	err := dm.CheckDatatype(ctx, "ns1", &fftypes.Datatype{})
   249  	assert.Regexp(t, "FF10196", err)
   250  }
   251  
   252  func TestResolveInputDataEmpty(t *testing.T) {
   253  
   254  	dm, ctx, cancel := newTestDataManager(t)
   255  	defer cancel()
   256  	refs, err := dm.ResolveInputData(ctx, "ns1", fftypes.InputData{})
   257  	assert.NoError(t, err)
   258  	assert.Empty(t, refs)
   259  
   260  }
   261  
   262  func TestResolveInputDataRefIDOnlyOK(t *testing.T) {
   263  	dm, ctx, cancel := newTestDataManager(t)
   264  	defer cancel()
   265  	mdi := dm.database.(*databasemocks.Plugin)
   266  
   267  	dataID := fftypes.NewUUID()
   268  	dataHash := fftypes.NewRandB32()
   269  
   270  	mdi.On("GetDataByID", ctx, dataID, false).Return(&fftypes.Data{
   271  		ID:        dataID,
   272  		Namespace: "ns1",
   273  		Hash:      dataHash,
   274  	}, nil)
   275  
   276  	refs, err := dm.ResolveInputData(ctx, "ns1", fftypes.InputData{
   277  		{DataRef: fftypes.DataRef{ID: dataID}},
   278  	})
   279  	assert.NoError(t, err)
   280  	assert.Len(t, refs, 1)
   281  	assert.Equal(t, dataID, refs[0].ID)
   282  	assert.Equal(t, dataHash, refs[0].Hash)
   283  }
   284  
   285  func TestResolveInputDataRefBadNamespace(t *testing.T) {
   286  	dm, ctx, cancel := newTestDataManager(t)
   287  	defer cancel()
   288  	mdi := dm.database.(*databasemocks.Plugin)
   289  
   290  	dataID := fftypes.NewUUID()
   291  	dataHash := fftypes.NewRandB32()
   292  
   293  	mdi.On("GetDataByID", ctx, dataID, false).Return(&fftypes.Data{
   294  		ID:        dataID,
   295  		Namespace: "ns2",
   296  		Hash:      dataHash,
   297  	}, nil)
   298  
   299  	refs, err := dm.ResolveInputData(ctx, "ns1", fftypes.InputData{
   300  		{DataRef: fftypes.DataRef{ID: dataID, Hash: dataHash}},
   301  	})
   302  	assert.Regexp(t, "FF10204", err)
   303  	assert.Empty(t, refs)
   304  }
   305  
   306  func TestResolveInputDataRefBadHash(t *testing.T) {
   307  	dm, ctx, cancel := newTestDataManager(t)
   308  	defer cancel()
   309  	mdi := dm.database.(*databasemocks.Plugin)
   310  
   311  	dataID := fftypes.NewUUID()
   312  	dataHash := fftypes.NewRandB32()
   313  
   314  	mdi.On("GetDataByID", ctx, dataID, false).Return(&fftypes.Data{
   315  		ID:        dataID,
   316  		Namespace: "ns2",
   317  		Hash:      dataHash,
   318  	}, nil)
   319  
   320  	refs, err := dm.ResolveInputData(ctx, "ns1", fftypes.InputData{
   321  		{DataRef: fftypes.DataRef{ID: dataID, Hash: fftypes.NewRandB32()}},
   322  	})
   323  	assert.Regexp(t, "FF10204", err)
   324  	assert.Empty(t, refs)
   325  }
   326  
   327  func TestResolveInputDataRefLookkupFail(t *testing.T) {
   328  	dm, ctx, cancel := newTestDataManager(t)
   329  	defer cancel()
   330  	mdi := dm.database.(*databasemocks.Plugin)
   331  
   332  	dataID := fftypes.NewUUID()
   333  
   334  	mdi.On("GetDataByID", ctx, dataID, false).Return(nil, fmt.Errorf("pop"))
   335  
   336  	_, err := dm.ResolveInputData(ctx, "ns1", fftypes.InputData{
   337  		{DataRef: fftypes.DataRef{ID: dataID, Hash: fftypes.NewRandB32()}},
   338  	})
   339  	assert.EqualError(t, err, "pop")
   340  }
   341  
   342  func TestResolveInputDataValueNoValidatorOK(t *testing.T) {
   343  	dm, ctx, cancel := newTestDataManager(t)
   344  	defer cancel()
   345  	mdi := dm.database.(*databasemocks.Plugin)
   346  
   347  	mdi.On("UpsertData", ctx, mock.Anything, false, false).Return(nil)
   348  
   349  	refs, err := dm.ResolveInputData(ctx, "ns1", fftypes.InputData{
   350  		{Value: fftypes.Byteable(`{"some":"json"}`)},
   351  	})
   352  	assert.NoError(t, err)
   353  	assert.Len(t, refs, 1)
   354  	assert.NotNil(t, refs[0].ID)
   355  	assert.NotNil(t, refs[0].Hash)
   356  }
   357  
   358  func TestResolveInputDataValueNoValidatorStoreFail(t *testing.T) {
   359  	dm, ctx, cancel := newTestDataManager(t)
   360  	defer cancel()
   361  	mdi := dm.database.(*databasemocks.Plugin)
   362  
   363  	mdi.On("UpsertData", ctx, mock.Anything, false, false).Return(fmt.Errorf("pop"))
   364  
   365  	_, err := dm.ResolveInputData(ctx, "ns1", fftypes.InputData{
   366  		{Value: fftypes.Byteable(`{"some":"json"}`)},
   367  	})
   368  	assert.EqualError(t, err, "pop")
   369  }
   370  
   371  func TestResolveInputDataValueWithValidation(t *testing.T) {
   372  	dm, ctx, cancel := newTestDataManager(t)
   373  	defer cancel()
   374  	mdi := dm.database.(*databasemocks.Plugin)
   375  
   376  	mdi.On("UpsertData", ctx, mock.Anything, false, false).Return(nil)
   377  	mdi.On("GetDatatypeByName", ctx, "ns1", "customer", "0.0.1").Return(&fftypes.Datatype{
   378  		ID:        fftypes.NewUUID(),
   379  		Validator: fftypes.ValidatorTypeJSON,
   380  		Namespace: "ns1",
   381  		Name:      "customer",
   382  		Version:   "0.0.1",
   383  		Value: fftypes.Byteable(`{
   384  			"properties": {
   385  				"field1": {
   386  					"type": "string"
   387  				}
   388  			},
   389  			"additionalProperties": false
   390  		}`),
   391  	}, nil)
   392  
   393  	refs, err := dm.ResolveInputData(ctx, "ns1", fftypes.InputData{
   394  		{
   395  			Datatype: &fftypes.DatatypeRef{
   396  				Name:    "customer",
   397  				Version: "0.0.1",
   398  			},
   399  			Value: fftypes.Byteable(`{"field1":"value1"}`),
   400  		},
   401  	})
   402  	assert.NoError(t, err)
   403  	assert.Len(t, refs, 1)
   404  	assert.NotNil(t, refs[0].ID)
   405  	assert.NotNil(t, refs[0].Hash)
   406  
   407  	_, err = dm.ResolveInputData(ctx, "ns1", fftypes.InputData{
   408  		{
   409  			Datatype: &fftypes.DatatypeRef{
   410  				Name:    "customer",
   411  				Version: "0.0.1",
   412  			},
   413  			Value: fftypes.Byteable(`{"not_allowed":"value"}`),
   414  		},
   415  	})
   416  	assert.Regexp(t, "FF10198", err)
   417  }
   418  
   419  func TestResolveInputDataNoRefOrValue(t *testing.T) {
   420  	dm, ctx, cancel := newTestDataManager(t)
   421  	defer cancel()
   422  
   423  	_, err := dm.ResolveInputData(ctx, "ns1", fftypes.InputData{
   424  		{ /* missing */ },
   425  	})
   426  	assert.Regexp(t, "FF10205", err)
   427  }
   428  
   429  func TestUploadJSONLoadDatatypeFail(t *testing.T) {
   430  	dm, ctx, cancel := newTestDataManager(t)
   431  	defer cancel()
   432  	mdi := dm.database.(*databasemocks.Plugin)
   433  
   434  	mdi.On("GetDatatypeByName", ctx, "ns1", "customer", "0.0.1").Return(nil, fmt.Errorf("pop"))
   435  	_, err := dm.UploadJSON(ctx, "ns1", &fftypes.Data{
   436  		Datatype: &fftypes.DatatypeRef{
   437  			Name:    "customer",
   438  			Version: "0.0.1",
   439  		},
   440  	})
   441  	assert.EqualError(t, err, "pop")
   442  }
   443  
   444  func TestValidateAndStoreLoadNilRef(t *testing.T) {
   445  	dm, ctx, cancel := newTestDataManager(t)
   446  	defer cancel()
   447  
   448  	_, err := dm.validateAndStoreInlined(ctx, "ns1", &fftypes.DataRefOrValue{
   449  		Validator: fftypes.ValidatorTypeJSON,
   450  		Datatype:  nil,
   451  	})
   452  	assert.Regexp(t, "FF10199", err)
   453  }
   454  
   455  func TestValidateAndStoreLoadValidatorUnknown(t *testing.T) {
   456  
   457  	dm, ctx, cancel := newTestDataManager(t)
   458  	defer cancel()
   459  	mdi := dm.database.(*databasemocks.Plugin)
   460  	mdi.On("GetDatatypeByName", mock.Anything, "ns1", "customer", "0.0.1").Return(nil, nil)
   461  	_, err := dm.validateAndStoreInlined(ctx, "ns1", &fftypes.DataRefOrValue{
   462  		Validator: "wrong!",
   463  		Datatype: &fftypes.DatatypeRef{
   464  			Name:    "customer",
   465  			Version: "0.0.1",
   466  		},
   467  	})
   468  	assert.Regexp(t, "FF10200.*wrong", err)
   469  
   470  }
   471  
   472  func TestValidateAndStoreLoadBadRef(t *testing.T) {
   473  
   474  	dm, ctx, cancel := newTestDataManager(t)
   475  	defer cancel()
   476  	mdi := dm.database.(*databasemocks.Plugin)
   477  	mdi.On("GetDatatypeByName", mock.Anything, "ns1", "customer", "0.0.1").Return(nil, nil)
   478  	_, err := dm.validateAndStoreInlined(ctx, "ns1", &fftypes.DataRefOrValue{
   479  		Datatype: &fftypes.DatatypeRef{
   480  			// Missing name
   481  		},
   482  	})
   483  	assert.Regexp(t, "FF10195", err)
   484  }
   485  
   486  func TestValidateAndStoreNotFound(t *testing.T) {
   487  
   488  	dm, ctx, cancel := newTestDataManager(t)
   489  	defer cancel()
   490  	mdi := dm.database.(*databasemocks.Plugin)
   491  	mdi.On("GetDatatypeByName", mock.Anything, "ns1", "customer", "0.0.1").Return(nil, nil)
   492  	_, err := dm.validateAndStoreInlined(ctx, "ns1", &fftypes.DataRefOrValue{
   493  		Datatype: &fftypes.DatatypeRef{
   494  			Name:    "customer",
   495  			Version: "0.0.1",
   496  		},
   497  	})
   498  	assert.Regexp(t, "FF10195", err)
   499  }
   500  
   501  func TestValidateAllLookupError(t *testing.T) {
   502  
   503  	dm, ctx, cancel := newTestDataManager(t)
   504  	defer cancel()
   505  	mdi := dm.database.(*databasemocks.Plugin)
   506  	mdi.On("GetDatatypeByName", mock.Anything, "ns1", "customer", "0.0.1").Return(nil, fmt.Errorf("pop"))
   507  	data := &fftypes.Data{
   508  		Namespace: "ns1",
   509  		Validator: fftypes.ValidatorTypeJSON,
   510  		Datatype: &fftypes.DatatypeRef{
   511  			Name:    "customer",
   512  			Version: "0.0.1",
   513  		},
   514  		Value: fftypes.Byteable(`anything`),
   515  	}
   516  	data.Seal(ctx)
   517  	_, err := dm.ValidateAll(ctx, []*fftypes.Data{data})
   518  	assert.Regexp(t, "pop", err)
   519  
   520  }
   521  
   522  func TestGetValidatorForDatatypeNilRef(t *testing.T) {
   523  
   524  	dm, ctx, cancel := newTestDataManager(t)
   525  	defer cancel()
   526  	v, err := dm.getValidatorForDatatype(ctx, "", "", nil)
   527  	assert.Nil(t, v)
   528  	assert.NoError(t, err)
   529  
   530  }
   531  
   532  func TestValidateAllStoredValidatorInvalid(t *testing.T) {
   533  
   534  	dm, ctx, cancel := newTestDataManager(t)
   535  	defer cancel()
   536  	mdi := dm.database.(*databasemocks.Plugin)
   537  	mdi.On("GetDatatypeByName", mock.Anything, "ns1", "customer", "0.0.1").Return(&fftypes.Datatype{
   538  		Value: fftypes.Byteable(`{"not": "a", "schema": true}`),
   539  	}, nil)
   540  	data := &fftypes.Data{
   541  		Namespace: "ns1",
   542  		Datatype: &fftypes.DatatypeRef{
   543  			Name:    "customer",
   544  			Version: "0.0.1",
   545  		},
   546  	}
   547  	isValid, err := dm.ValidateAll(ctx, []*fftypes.Data{data})
   548  	assert.False(t, isValid)
   549  	assert.NoError(t, err)
   550  	mdi.AssertExpectations(t)
   551  }
   552  
   553  func TestVerifyNamespaceExistsInvalidFFName(t *testing.T) {
   554  	dm, ctx, cancel := newTestDataManager(t)
   555  	defer cancel()
   556  	err := dm.VerifyNamespaceExists(ctx, "!wrong")
   557  	assert.Regexp(t, "FF10131", err)
   558  }
   559  
   560  func TestVerifyNamespaceExistsLookupErr(t *testing.T) {
   561  	dm, ctx, cancel := newTestDataManager(t)
   562  	defer cancel()
   563  	mdi := dm.database.(*databasemocks.Plugin)
   564  	mdi.On("GetNamespace", mock.Anything, "ns1").Return(nil, fmt.Errorf("pop"))
   565  	err := dm.VerifyNamespaceExists(ctx, "ns1")
   566  	assert.Regexp(t, "pop", err)
   567  }
   568  
   569  func TestVerifyNamespaceExistsNotFound(t *testing.T) {
   570  	dm, ctx, cancel := newTestDataManager(t)
   571  	defer cancel()
   572  	mdi := dm.database.(*databasemocks.Plugin)
   573  	mdi.On("GetNamespace", mock.Anything, "ns1").Return(nil, nil)
   574  	err := dm.VerifyNamespaceExists(ctx, "ns1")
   575  	assert.Regexp(t, "FF10187", err)
   576  }
   577  
   578  func TestVerifyNamespaceExistsOk(t *testing.T) {
   579  	dm, ctx, cancel := newTestDataManager(t)
   580  	defer cancel()
   581  	mdi := dm.database.(*databasemocks.Plugin)
   582  	mdi.On("GetNamespace", mock.Anything, "ns1").Return(&fftypes.Namespace{}, nil)
   583  	err := dm.VerifyNamespaceExists(ctx, "ns1")
   584  	assert.NoError(t, err)
   585  }