github.com/hyperledger/aries-framework-go@v0.3.2/pkg/ld/service_test.go (about)

     1  /*
     2  Copyright SecureKey Technologies Inc. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package ld_test
     8  
     9  import (
    10  	"bytes"
    11  	"encoding/json"
    12  	"errors"
    13  	"io/ioutil"
    14  	"net/http"
    15  	"testing"
    16  
    17  	jsonld "github.com/piprate/json-gold/ld"
    18  	"github.com/stretchr/testify/require"
    19  
    20  	"github.com/hyperledger/aries-framework-go/pkg/doc/ldcontext/remote"
    21  	"github.com/hyperledger/aries-framework-go/pkg/internal/ldtestutil"
    22  	"github.com/hyperledger/aries-framework-go/pkg/ld"
    23  	mockldstore "github.com/hyperledger/aries-framework-go/pkg/mock/ld"
    24  	mockprovider "github.com/hyperledger/aries-framework-go/pkg/mock/provider"
    25  	mockstorage "github.com/hyperledger/aries-framework-go/pkg/mock/storage"
    26  	ldstore "github.com/hyperledger/aries-framework-go/pkg/store/ld"
    27  	"github.com/hyperledger/aries-framework-go/spi/storage"
    28  )
    29  
    30  const sampleContextsResponse = `{
    31    "documents": [
    32      {
    33        "url": "https://example.com/context.jsonld",
    34        "content": {
    35          "@context": "remote"
    36        }
    37      }
    38    ]
    39  }`
    40  
    41  func TestDefaultService_AddContexts(t *testing.T) {
    42  	t.Run("Success", func(t *testing.T) {
    43  		store := mockldstore.NewMockContextStore()
    44  
    45  		svc := ld.New(createMockProvider(withContextStore(store)))
    46  
    47  		err := svc.AddContexts(ldtestutil.Contexts())
    48  
    49  		require.NoError(t, err)
    50  		require.Len(t, store.Store.Store, len(ldtestutil.Contexts()))
    51  	})
    52  
    53  	t.Run("Fail to add contexts", func(t *testing.T) {
    54  		store := mockldstore.NewMockContextStore()
    55  		store.ErrImport = errors.New("import error")
    56  
    57  		svc := ld.New(createMockProvider(withContextStore(store)))
    58  
    59  		err := svc.AddContexts(ldtestutil.Contexts())
    60  
    61  		require.Error(t, err)
    62  		require.Contains(t, err.Error(), "add contexts")
    63  	})
    64  }
    65  
    66  func TestDefaultService_AddRemoteProvider(t *testing.T) {
    67  	t.Run("Success", func(t *testing.T) {
    68  		httpClient := &mockHTTPClient{
    69  			DoFunc: func(req *http.Request) (*http.Response, error) {
    70  				return &http.Response{
    71  					StatusCode: http.StatusOK,
    72  					Body:       ioutil.NopCloser(bytes.NewReader([]byte(sampleContextsResponse))),
    73  				}, nil
    74  			},
    75  		}
    76  
    77  		contextStore := mockldstore.NewMockContextStore()
    78  		providerStore := mockldstore.NewMockRemoteProviderStore()
    79  
    80  		svc := ld.New(createMockProvider(
    81  			withContextStore(contextStore),
    82  			withRemoteProviderStore(providerStore),
    83  		))
    84  
    85  		providerID, err := svc.AddRemoteProvider("endpoint", remote.WithHTTPClient(httpClient))
    86  
    87  		require.NotEmpty(t, providerID)
    88  		require.NoError(t, err)
    89  		require.Equal(t, 1, len(providerStore.Store.Store))
    90  		require.Equal(t, 1, len(contextStore.Store.Store))
    91  	})
    92  
    93  	t.Run("Fail to get contexts from remote provider", func(t *testing.T) {
    94  		httpClient := &mockHTTPClient{
    95  			DoFunc: func(req *http.Request) (*http.Response, error) {
    96  				return &http.Response{
    97  					StatusCode: http.StatusNotFound,
    98  					Body:       ioutil.NopCloser(bytes.NewReader(nil)),
    99  				}, nil
   100  			},
   101  		}
   102  
   103  		svc := ld.New(createMockProvider())
   104  
   105  		providerID, err := svc.AddRemoteProvider("endpoint", remote.WithHTTPClient(httpClient))
   106  
   107  		require.Empty(t, providerID)
   108  		require.Error(t, err)
   109  		require.Contains(t, err.Error(), "get contexts from remote provider")
   110  	})
   111  
   112  	t.Run("Fail to save remote provider", func(t *testing.T) {
   113  		httpClient := &mockHTTPClient{
   114  			DoFunc: func(req *http.Request) (*http.Response, error) {
   115  				return &http.Response{
   116  					StatusCode: http.StatusOK,
   117  					Body:       ioutil.NopCloser(bytes.NewReader([]byte(sampleContextsResponse))),
   118  				}, nil
   119  			},
   120  		}
   121  
   122  		providerStore := mockldstore.NewMockRemoteProviderStore()
   123  		providerStore.ErrSave = errors.New("save error")
   124  
   125  		svc := ld.New(createMockProvider(withRemoteProviderStore(providerStore)))
   126  
   127  		providerID, err := svc.AddRemoteProvider("endpoint", remote.WithHTTPClient(httpClient))
   128  
   129  		require.Empty(t, providerID)
   130  		require.Error(t, err)
   131  		require.Contains(t, err.Error(), "save remote provider")
   132  	})
   133  
   134  	t.Run("Fail to import contexts", func(t *testing.T) {
   135  		httpClient := &mockHTTPClient{
   136  			DoFunc: func(req *http.Request) (*http.Response, error) {
   137  				return &http.Response{
   138  					StatusCode: http.StatusOK,
   139  					Body:       ioutil.NopCloser(bytes.NewReader([]byte(sampleContextsResponse))),
   140  				}, nil
   141  			},
   142  		}
   143  
   144  		contextStore := mockldstore.NewMockContextStore()
   145  		contextStore.ErrImport = errors.New("import error")
   146  
   147  		svc := ld.New(createMockProvider(withContextStore(contextStore)))
   148  
   149  		providerID, err := svc.AddRemoteProvider("endpoint", remote.WithHTTPClient(httpClient))
   150  
   151  		require.Empty(t, providerID)
   152  		require.Error(t, err)
   153  		require.Contains(t, err.Error(), "import contexts")
   154  	})
   155  }
   156  
   157  func TestDefaultService_RefreshAllRemoteProviders(t *testing.T) {
   158  	t.Run("Success", func(t *testing.T) {
   159  		httpClient := &mockHTTPClient{
   160  			DoFunc: func(req *http.Request) (*http.Response, error) {
   161  				return &http.Response{
   162  					StatusCode: http.StatusOK,
   163  					Body:       ioutil.NopCloser(bytes.NewReader([]byte(sampleContextsResponse))),
   164  				}, nil
   165  			},
   166  		}
   167  
   168  		contextStore := mockldstore.NewMockContextStore()
   169  
   170  		providerStore := mockldstore.NewMockRemoteProviderStore()
   171  		providerStore.Store.Store["id"] = mockstorage.DBEntry{
   172  			Value: []byte("endpoint"),
   173  			Tags:  []storage.Tag{{Name: ldstore.RemoteProviderRecordTag}},
   174  		}
   175  
   176  		svc := ld.New(createMockProvider(
   177  			withContextStore(contextStore),
   178  			withRemoteProviderStore(providerStore),
   179  		))
   180  
   181  		err := svc.RefreshRemoteProvider("id", remote.WithHTTPClient(httpClient))
   182  
   183  		require.NoError(t, err)
   184  		require.Equal(t, 1, len(providerStore.Store.Store))
   185  		require.Equal(t, 1, len(contextStore.Store.Store))
   186  	})
   187  
   188  	t.Run("Fail to get remote provider from store", func(t *testing.T) {
   189  		store := mockldstore.NewMockRemoteProviderStore()
   190  		store.ErrGet = errors.New("get error")
   191  
   192  		svc := ld.New(createMockProvider(withRemoteProviderStore(store)))
   193  
   194  		err := svc.RefreshRemoteProvider("id", remote.WithHTTPClient(&mockHTTPClient{}))
   195  
   196  		require.Error(t, err)
   197  		require.Contains(t, err.Error(), "get remote provider from store")
   198  	})
   199  
   200  	t.Run("Fail to get contexts from remote provider", func(t *testing.T) {
   201  		httpClient := &mockHTTPClient{
   202  			DoFunc: func(req *http.Request) (*http.Response, error) {
   203  				return &http.Response{
   204  					StatusCode: http.StatusNotFound,
   205  					Body:       ioutil.NopCloser(bytes.NewReader(nil)),
   206  				}, nil
   207  			},
   208  		}
   209  
   210  		providerStore := mockldstore.NewMockRemoteProviderStore()
   211  		providerStore.Store.Store["id"] = mockstorage.DBEntry{
   212  			Value: []byte("endpoint"),
   213  			Tags:  []storage.Tag{{Name: ldstore.RemoteProviderRecordTag}},
   214  		}
   215  
   216  		svc := ld.New(createMockProvider(withRemoteProviderStore(providerStore)))
   217  
   218  		err := svc.RefreshRemoteProvider("id", remote.WithHTTPClient(httpClient))
   219  
   220  		require.Error(t, err)
   221  		require.Contains(t, err.Error(), "get contexts from remote provider")
   222  	})
   223  
   224  	t.Run("Fail to import contexts", func(t *testing.T) {
   225  		httpClient := &mockHTTPClient{
   226  			DoFunc: func(req *http.Request) (*http.Response, error) {
   227  				return &http.Response{
   228  					StatusCode: http.StatusOK,
   229  					Body:       ioutil.NopCloser(bytes.NewReader([]byte(sampleContextsResponse))),
   230  				}, nil
   231  			},
   232  		}
   233  
   234  		contextStore := mockldstore.NewMockContextStore()
   235  		contextStore.ErrImport = errors.New("import error")
   236  
   237  		providerStore := mockldstore.NewMockRemoteProviderStore()
   238  		providerStore.Store.Store["id"] = mockstorage.DBEntry{
   239  			Value: []byte("endpoint"),
   240  			Tags:  []storage.Tag{{Name: ldstore.RemoteProviderRecordTag}},
   241  		}
   242  
   243  		svc := ld.New(createMockProvider(
   244  			withContextStore(contextStore),
   245  			withRemoteProviderStore(providerStore),
   246  		))
   247  
   248  		err := svc.RefreshRemoteProvider("id", remote.WithHTTPClient(httpClient))
   249  
   250  		require.Error(t, err)
   251  		require.Contains(t, err.Error(), "import contexts")
   252  	})
   253  }
   254  
   255  func TestDefaultService_DeleteRemoteProvider(t *testing.T) {
   256  	t.Run("Success", func(t *testing.T) {
   257  		httpClient := &mockHTTPClient{
   258  			DoFunc: func(req *http.Request) (*http.Response, error) {
   259  				return &http.Response{
   260  					StatusCode: http.StatusOK,
   261  					Body:       ioutil.NopCloser(bytes.NewReader([]byte(sampleContextsResponse))),
   262  				}, nil
   263  			},
   264  		}
   265  
   266  		document, err := jsonld.DocumentFromReader(bytes.NewReader([]byte(`{"@context": "remote"}`)))
   267  		require.NoError(t, err)
   268  
   269  		rd := jsonld.RemoteDocument{
   270  			DocumentURL: "https://example.com/context.jsonld",
   271  			Document:    document,
   272  		}
   273  
   274  		b, err := json.Marshal(rd)
   275  		require.NoError(t, err)
   276  
   277  		contextStore := mockldstore.NewMockContextStore()
   278  		contextStore.Store.Store[rd.DocumentURL] = mockstorage.DBEntry{
   279  			Value: b,
   280  			Tags:  []storage.Tag{{Name: ldstore.ContextRecordTag}},
   281  		}
   282  
   283  		providerStore := mockldstore.NewMockRemoteProviderStore()
   284  		providerStore.Store.Store["id"] = mockstorage.DBEntry{
   285  			Value: []byte("endpoint"),
   286  			Tags:  []storage.Tag{{Name: ldstore.RemoteProviderRecordTag}},
   287  		}
   288  
   289  		svc := ld.New(createMockProvider(
   290  			withContextStore(contextStore),
   291  			withRemoteProviderStore(providerStore),
   292  		))
   293  
   294  		err = svc.DeleteRemoteProvider("id", remote.WithHTTPClient(httpClient))
   295  
   296  		require.NoError(t, err)
   297  		require.Equal(t, 0, len(providerStore.Store.Store))
   298  		require.Equal(t, 0, len(contextStore.Store.Store))
   299  	})
   300  
   301  	t.Run("Fail to get remote provider from store", func(t *testing.T) {
   302  		store := mockldstore.NewMockRemoteProviderStore()
   303  		store.ErrGet = errors.New("get error")
   304  
   305  		svc := ld.New(createMockProvider(withRemoteProviderStore(store)))
   306  
   307  		err := svc.DeleteRemoteProvider("id", remote.WithHTTPClient(&mockHTTPClient{}))
   308  
   309  		require.Error(t, err)
   310  		require.Contains(t, err.Error(), "get remote provider from store")
   311  	})
   312  
   313  	t.Run("Fail to get contexts from remote provider", func(t *testing.T) {
   314  		httpClient := &mockHTTPClient{
   315  			DoFunc: func(req *http.Request) (*http.Response, error) {
   316  				return &http.Response{
   317  					StatusCode: http.StatusNotFound,
   318  					Body:       ioutil.NopCloser(bytes.NewReader(nil)),
   319  				}, nil
   320  			},
   321  		}
   322  
   323  		providerStore := mockldstore.NewMockRemoteProviderStore()
   324  		providerStore.Store.Store["id"] = mockstorage.DBEntry{
   325  			Value: []byte("endpoint"),
   326  			Tags:  []storage.Tag{{Name: ldstore.RemoteProviderRecordTag}},
   327  		}
   328  
   329  		svc := ld.New(createMockProvider(withRemoteProviderStore(providerStore)))
   330  
   331  		err := svc.DeleteRemoteProvider("id", remote.WithHTTPClient(httpClient))
   332  
   333  		require.Error(t, err)
   334  		require.Contains(t, err.Error(), "get contexts from remote provider")
   335  	})
   336  
   337  	t.Run("Fail to delete contexts", func(t *testing.T) {
   338  		httpClient := &mockHTTPClient{
   339  			DoFunc: func(req *http.Request) (*http.Response, error) {
   340  				return &http.Response{
   341  					StatusCode: http.StatusOK,
   342  					Body:       ioutil.NopCloser(bytes.NewReader([]byte(sampleContextsResponse))),
   343  				}, nil
   344  			},
   345  		}
   346  
   347  		contextStore := mockldstore.NewMockContextStore()
   348  		contextStore.ErrDelete = errors.New("delete error")
   349  
   350  		providerStore := mockldstore.NewMockRemoteProviderStore()
   351  		providerStore.Store.Store["id"] = mockstorage.DBEntry{
   352  			Value: []byte("endpoint"),
   353  			Tags:  []storage.Tag{{Name: ldstore.RemoteProviderRecordTag}},
   354  		}
   355  
   356  		svc := ld.New(createMockProvider(
   357  			withContextStore(contextStore),
   358  			withRemoteProviderStore(providerStore),
   359  		))
   360  
   361  		err := svc.DeleteRemoteProvider("id", remote.WithHTTPClient(httpClient))
   362  
   363  		require.Error(t, err)
   364  		require.Contains(t, err.Error(), "delete contexts")
   365  	})
   366  
   367  	t.Run("Fail to delete remote provider record", func(t *testing.T) {
   368  		httpClient := &mockHTTPClient{
   369  			DoFunc: func(req *http.Request) (*http.Response, error) {
   370  				return &http.Response{
   371  					StatusCode: http.StatusOK,
   372  					Body:       ioutil.NopCloser(bytes.NewReader([]byte(sampleContextsResponse))),
   373  				}, nil
   374  			},
   375  		}
   376  
   377  		store := mockldstore.NewMockRemoteProviderStore()
   378  		store.Store.Store["id"] = mockstorage.DBEntry{
   379  			Value: []byte("endpoint"),
   380  			Tags:  []storage.Tag{{Name: ldstore.RemoteProviderRecordTag}},
   381  		}
   382  		store.ErrDelete = errors.New("delete error")
   383  
   384  		svc := ld.New(createMockProvider(withRemoteProviderStore(store)))
   385  
   386  		err := svc.DeleteRemoteProvider("id", remote.WithHTTPClient(httpClient))
   387  
   388  		require.Error(t, err)
   389  		require.Contains(t, err.Error(), "delete remote provider record:")
   390  	})
   391  }
   392  
   393  func TestDefaultService_GetAllRemoteProviders(t *testing.T) {
   394  	t.Run("Success", func(t *testing.T) {
   395  		store := mockldstore.NewMockRemoteProviderStore()
   396  		store.Store.Store["id"] = mockstorage.DBEntry{
   397  			Value: []byte("endpoint"),
   398  			Tags:  []storage.Tag{{Name: ldstore.RemoteProviderRecordTag}},
   399  		}
   400  
   401  		cmd := ld.New(createMockProvider(withRemoteProviderStore(store)))
   402  
   403  		providers, err := cmd.GetAllRemoteProviders()
   404  
   405  		require.NoError(t, err)
   406  		require.Equal(t, 1, len(providers))
   407  	})
   408  
   409  	t.Run("Fail to get remote provider records", func(t *testing.T) {
   410  		store := mockldstore.NewMockRemoteProviderStore()
   411  		store.ErrGetAll = errors.New("get all error")
   412  
   413  		cmd := ld.New(createMockProvider(withRemoteProviderStore(store)))
   414  
   415  		providers, err := cmd.GetAllRemoteProviders()
   416  
   417  		require.Nil(t, providers)
   418  		require.Error(t, err)
   419  		require.Contains(t, err.Error(), "get remote provider records")
   420  	})
   421  }
   422  
   423  func TestDefaultService_RefreshRemoteProvider(t *testing.T) {
   424  	t.Run("Success", func(t *testing.T) {
   425  		httpClient := &mockHTTPClient{
   426  			DoFunc: func(req *http.Request) (*http.Response, error) {
   427  				return &http.Response{
   428  					StatusCode: http.StatusOK,
   429  					Body:       ioutil.NopCloser(bytes.NewReader([]byte(sampleContextsResponse))),
   430  				}, nil
   431  			},
   432  		}
   433  
   434  		contextStore := mockldstore.NewMockContextStore()
   435  
   436  		providerStore := mockldstore.NewMockRemoteProviderStore()
   437  		providerStore.Store.Store["id"] = mockstorage.DBEntry{
   438  			Value: []byte("endpoint"),
   439  			Tags:  []storage.Tag{{Name: ldstore.RemoteProviderRecordTag}},
   440  		}
   441  
   442  		svc := ld.New(createMockProvider(
   443  			withContextStore(contextStore),
   444  			withRemoteProviderStore(providerStore),
   445  		))
   446  
   447  		err := svc.RefreshAllRemoteProviders(remote.WithHTTPClient(httpClient))
   448  
   449  		require.NoError(t, err)
   450  		require.Equal(t, 1, len(providerStore.Store.Store))
   451  		require.Equal(t, 1, len(contextStore.Store.Store))
   452  	})
   453  
   454  	t.Run("Fail to get remote provider records", func(t *testing.T) {
   455  		store := mockldstore.NewMockRemoteProviderStore()
   456  		store.ErrGetAll = errors.New("get all error")
   457  
   458  		svc := ld.New(createMockProvider(withRemoteProviderStore(store)))
   459  
   460  		err := svc.RefreshAllRemoteProviders(remote.WithHTTPClient(&mockHTTPClient{}))
   461  
   462  		require.Error(t, err)
   463  		require.Contains(t, err.Error(), "get remote provider records")
   464  	})
   465  
   466  	t.Run("Fail to get contexts from remote provider", func(t *testing.T) {
   467  		httpClient := &mockHTTPClient{
   468  			DoFunc: func(req *http.Request) (*http.Response, error) {
   469  				return &http.Response{
   470  					StatusCode: http.StatusNotFound,
   471  					Body:       ioutil.NopCloser(bytes.NewReader(nil)),
   472  				}, nil
   473  			},
   474  		}
   475  
   476  		store := mockldstore.NewMockRemoteProviderStore()
   477  		store.Store.Store["id"] = mockstorage.DBEntry{
   478  			Value: []byte("endpoint"),
   479  			Tags:  []storage.Tag{{Name: ldstore.RemoteProviderRecordTag}},
   480  		}
   481  
   482  		svc := ld.New(createMockProvider(withRemoteProviderStore(store)))
   483  
   484  		err := svc.RefreshAllRemoteProviders(remote.WithHTTPClient(httpClient))
   485  
   486  		require.Error(t, err)
   487  		require.Contains(t, err.Error(), "get contexts from remote provider")
   488  	})
   489  
   490  	t.Run("Fail to import contexts", func(t *testing.T) {
   491  		httpClient := &mockHTTPClient{
   492  			DoFunc: func(req *http.Request) (*http.Response, error) {
   493  				return &http.Response{
   494  					StatusCode: http.StatusOK,
   495  					Body:       ioutil.NopCloser(bytes.NewReader([]byte(sampleContextsResponse))),
   496  				}, nil
   497  			},
   498  		}
   499  
   500  		store := mockldstore.NewMockContextStore()
   501  		store.ErrImport = errors.New("import error")
   502  
   503  		providerStore := mockldstore.NewMockRemoteProviderStore()
   504  		providerStore.Store.Store["id"] = mockstorage.DBEntry{
   505  			Value: []byte("endpoint"),
   506  			Tags:  []storage.Tag{{Name: ldstore.RemoteProviderRecordTag}},
   507  		}
   508  
   509  		svc := ld.New(createMockProvider(
   510  			withContextStore(store),
   511  			withRemoteProviderStore(providerStore),
   512  		))
   513  
   514  		err := svc.RefreshAllRemoteProviders(remote.WithHTTPClient(httpClient))
   515  
   516  		require.Error(t, err)
   517  		require.Contains(t, err.Error(), "import contexts")
   518  	})
   519  }
   520  
   521  type mockHTTPClient struct {
   522  	DoFunc func(req *http.Request) (*http.Response, error)
   523  }
   524  
   525  func (m *mockHTTPClient) Do(req *http.Request) (*http.Response, error) {
   526  	return m.DoFunc(req)
   527  }
   528  
   529  func createMockProvider(opts ...providerOptionFn) *mockprovider.Provider {
   530  	p := &mockprovider.Provider{
   531  		ContextStoreValue:        mockldstore.NewMockContextStore(),
   532  		RemoteProviderStoreValue: mockldstore.NewMockRemoteProviderStore(),
   533  	}
   534  
   535  	for i := range opts {
   536  		opts[i](p)
   537  	}
   538  
   539  	return p
   540  }
   541  
   542  type providerOptionFn func(opts *mockprovider.Provider)
   543  
   544  func withContextStore(store ldstore.ContextStore) providerOptionFn {
   545  	return func(p *mockprovider.Provider) {
   546  		p.ContextStoreValue = store
   547  	}
   548  }
   549  
   550  func withRemoteProviderStore(store ldstore.RemoteProviderStore) providerOptionFn {
   551  	return func(p *mockprovider.Provider) {
   552  		p.RemoteProviderStoreValue = store
   553  	}
   554  }