github.com/hyperledger/aries-framework-go@v0.3.2/pkg/store/verifiable/store_test.go (about)

     1  /*
     2  Copyright SecureKey Technologies Inc. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package verifiable_test
     8  
     9  import (
    10  	"encoding/json"
    11  	"fmt"
    12  	"strconv"
    13  	"testing"
    14  
    15  	"github.com/stretchr/testify/require"
    16  
    17  	"github.com/hyperledger/aries-framework-go/pkg/doc/verifiable"
    18  	"github.com/hyperledger/aries-framework-go/pkg/internal/ldtestutil"
    19  	mockprovider "github.com/hyperledger/aries-framework-go/pkg/mock/provider"
    20  	mockstore "github.com/hyperledger/aries-framework-go/pkg/mock/storage"
    21  	. "github.com/hyperledger/aries-framework-go/pkg/store/verifiable"
    22  	"github.com/hyperledger/aries-framework-go/pkg/store/verifiable/internal"
    23  )
    24  
    25  const (
    26  	sampleCredentialName   = "sampleVCName"
    27  	sampleCredentialID     = "sampleVCID"
    28  	samplePresentationName = "sampleVPName"
    29  	samplePresentationID   = "sampleVPID"
    30  )
    31  
    32  //nolint:gochecknoglobals
    33  var udCredential = `
    34  
    35  {
    36    "@context": [
    37      "https://www.w3.org/2018/credentials/v1",
    38      "https://www.w3.org/2018/credentials/examples/v1"
    39    ],
    40    "id": "http://example.edu/credentials/1872",
    41    "type": [
    42      "VerifiableCredential",
    43      "UniversityDegreeCredential"
    44    ],
    45    "credentialSubject": {
    46      "id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
    47      "degree": {
    48        "type": "BachelorDegree"
    49      },
    50      "name": "Jayden Doe",
    51      "spouse": "did:example:c276e12ec21ebfeb1f712ebc6f1"
    52    },
    53  
    54    "issuer": {
    55      "id": "did:example:76e12ec712ebc6f1c221ebfeb1f",
    56      "name": "Example University"
    57    },
    58  
    59    "issuanceDate": "2010-01-01T19:23:24Z",
    60  
    61    "expirationDate": "2020-01-01T19:23:24Z",
    62  
    63    "credentialStatus": {
    64      "id": "https://example.edu/status/24",
    65      "type": "CredentialStatusList2017"
    66    },
    67  
    68    "evidence": [{
    69      "id": "https://example.edu/evidence/f2aeec97-fc0d-42bf-8ca7-0548192d4231",
    70      "type": ["DocumentVerification"],
    71      "verifier": "https://example.edu/issuers/14",
    72      "evidenceDocument": "DriversLicense",
    73      "subjectPresence": "Physical",
    74      "documentPresence": "Physical"
    75    },{
    76      "id": "https://example.edu/evidence/f2aeec97-fc0d-42bf-8ca7-0548192dxyzab",
    77      "type": ["SupportingActivity"],
    78      "verifier": "https://example.edu/issuers/14",
    79      "evidenceDocument": "Fluid Dynamics Focus",
    80      "subjectPresence": "Digital",
    81      "documentPresence": "Digital"
    82    }],
    83  
    84    "termsOfUse": [
    85      {
    86        "type": "IssuerPolicy",
    87        "id": "http://example.com/policies/credential/4",
    88        "profile": "http://example.com/profiles/credential",
    89        "prohibition": [
    90          {
    91            "assigner": "https://example.edu/issuers/14",
    92            "assignee": "AllVerifiers",
    93            "target": "http://example.edu/credentials/3732",
    94            "action": [
    95              "Archival"
    96            ]
    97          }
    98        ]
    99      }
   100    ],
   101  
   102    "refreshService": {
   103      "id": "https://example.edu/refresh/3732",
   104      "type": "ManualRefreshService2018"
   105    }
   106  }
   107  `
   108  
   109  //nolint:gochecknoglobals
   110  var udCredentialWithoutID = `
   111  
   112  {
   113    "@context": [
   114      "https://www.w3.org/2018/credentials/v1",
   115      "https://www.w3.org/2018/credentials/examples/v1"
   116    ],
   117    "type": [
   118      "VerifiableCredential",
   119      "UniversityDegreeCredential"
   120    ],
   121    "credentialSubject": {
   122      "id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
   123      "degree": {
   124        "type": "BachelorDegree"
   125      },
   126      "name": "Jayden Doe",
   127      "spouse": "did:example:c276e12ec21ebfeb1f712ebc6f1"
   128    },
   129  
   130    "issuer": {
   131      "id": "did:example:76e12ec712ebc6f1c221ebfeb1f",
   132      "name": "Example University"
   133    },
   134  
   135    "issuanceDate": "2010-01-01T19:23:24Z",
   136  
   137    "expirationDate": "2020-01-01T19:23:24Z"
   138  }
   139  `
   140  
   141  //nolint:lll
   142  const udVerifiablePresentation = `{
   143          "@context": ["https://www.w3.org/2018/credentials/v1", "https://www.w3.org/2018/credentials/examples/v1"],
   144          "type": ["VerifiablePresentation"],
   145  		"holder": "did:example:ebfeb1f712ebc6f1c276e12ec21",
   146          "verifiableCredential": [{
   147              "@context": ["https://www.w3.org/2018/credentials/v1", "https://www.w3.org/2018/credentials/examples/v1"],
   148              "credentialSchema": [],
   149              "credentialStatus": {
   150                  "id": "http://issuer.vc.rest.example.com:8070/status/1",
   151                  "type": "CredentialStatusList2017"
   152              },
   153              "credentialSubject": {
   154                  "degree": {"degree": "MIT", "type": "BachelorDegree"},
   155                  "id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
   156                  "name": "Jayden Doe",
   157                  "spouse": "did:example:c276e12ec21ebfeb1f712ebc6f1"
   158              },
   159              "id": "https://example.com/credentials/9315d0fd-da93-436e-9e20-2121f2821df3",
   160              "issuanceDate": "2020-03-16T22:37:26.544Z",
   161              "issuer": {
   162                  "id": "did:elem:EiBJJPdo-ONF0jxqt8mZYEj9Z7FbdC87m2xvN0_HAbcoEg",
   163                  "name": "alice_ca31684e-6cbb-40f9-b7e6-87e1ab5661ae"
   164              },
   165              "proof": {
   166                  "created": "2020-04-08T21:19:02Z",
   167                  "jws": "eyJhbGciOiJFZERTQSIsImI2NCI6ZmFsc2UsImNyaXQiOlsiYjY0Il19..yGHHYmRp4mWd918SDSzmBDs8eq-SX7WPl8moGB8oJeSqEMmuEiI81D4s5-BPWGmKy3VlCsKJxYrTNqrEGJpNAQ",
   168                  "proofPurpose": "assertionMethod",
   169                  "type": "Ed25519Signature2018",
   170                  "verificationMethod": "did:elem:EiBJJPdo-ONF0jxqt8mZYEj9Z7FbdC87m2xvN0_HAbcoEg#xqc3gS1gz1vch7R3RvNebWMjLvBOY-n_14feCYRPsUo"
   171              },
   172              "type": ["VerifiableCredential", "UniversityDegreeCredential"]
   173          }],
   174          "proof": {
   175              "created": "2020-04-08T17:19:05-04:00",
   176              "jws": "eyJhbGciOiJFZERTQSIsImI2NCI6ZmFsc2UsImNyaXQiOlsiYjY0Il19..0CH8GwphcMoQ0JHCm1O8n9ctM-s8hTfTuOa-WeQFSmPipaO41pECe7pQ4zDM6sp08W59pkrTz_U1PrwLlUyoBw",
   177              "proofPurpose": "assertionMethod",
   178              "type": "Ed25519Signature2018",
   179              "verificationMethod": "did:elem:EiBJJPdo-ONF0jxqt8mZYEj9Z7FbdC87m2xvN0_HAbcoEg#xqc3gS1gz1vch7R3RvNebWMjLvBOY-n_14feCYRPsUo"
   180          }
   181      }
   182  `
   183  
   184  //nolint:lll
   185  const udPresentation = `{
   186          "@context": ["https://www.w3.org/2018/credentials/v1", "https://www.w3.org/2018/credentials/examples/v1"],
   187          "type": ["VerifiablePresentation"],
   188  		"holder": "did:example:ebfeb1f712ebc6f1c276e12ec21",
   189          "verifiableCredential": [{
   190              "@context": ["https://www.w3.org/2018/credentials/v1", "https://www.w3.org/2018/credentials/examples/v1"],
   191              "credentialSchema": [],
   192              "credentialStatus": {
   193                  "id": "http://issuer.vc.rest.example.com:8070/status/1",
   194                  "type": "CredentialStatusList2017"
   195              },
   196              "credentialSubject": {
   197                  "degree": {"degree": "MIT", "type": "BachelorDegree"},
   198                  "id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
   199                  "name": "Jayden Doe",
   200                  "spouse": "did:example:c276e12ec21ebfeb1f712ebc6f1"
   201              },
   202              "id": "https://example.com/credentials/9315d0fd-da93-436e-9e20-2121f2821df3",
   203              "issuanceDate": "2020-03-16T22:37:26.544Z",
   204              "issuer": {
   205                  "id": "did:elem:EiBJJPdo-ONF0jxqt8mZYEj9Z7FbdC87m2xvN0_HAbcoEg",
   206                  "name": "alice_ca31684e-6cbb-40f9-b7e6-87e1ab5661ae"
   207              },
   208              "proof": {
   209                  "created": "2020-04-08T21:19:02Z",
   210                  "jws": "eyJhbGciOiJFZERTQSIsImI2NCI6ZmFsc2UsImNyaXQiOlsiYjY0Il19..yGHHYmRp4mWd918SDSzmBDs8eq-SX7WPl8moGB8oJeSqEMmuEiI81D4s5-BPWGmKy3VlCsKJxYrTNqrEGJpNAQ",
   211                  "proofPurpose": "assertionMethod",
   212                  "type": "Ed25519Signature2018",
   213                  "verificationMethod": "did:elem:EiBJJPdo-ONF0jxqt8mZYEj9Z7FbdC87m2xvN0_HAbcoEg#xqc3gS1gz1vch7R3RvNebWMjLvBOY-n_14feCYRPsUo"
   214              },
   215              "type": ["VerifiableCredential", "UniversityDegreeCredential"]
   216          }]
   217      }
   218  `
   219  
   220  func TestNew(t *testing.T) {
   221  	t.Run("test new store", func(t *testing.T) {
   222  		s, err := New(&mockprovider.Provider{
   223  			StorageProviderValue: mockstore.NewMockStoreProvider(),
   224  		})
   225  		require.NoError(t, err)
   226  		require.NotNil(t, s)
   227  	})
   228  
   229  	t.Run("test error from open store", func(t *testing.T) {
   230  		s, err := New(&mockprovider.Provider{
   231  			StorageProviderValue: &mockstore.MockStoreProvider{
   232  				ErrOpenStoreHandle: fmt.Errorf("failed to open store"),
   233  			},
   234  		})
   235  		require.Error(t, err)
   236  		require.Contains(t, err.Error(), "failed to open store")
   237  		require.Nil(t, s)
   238  	})
   239  }
   240  
   241  func TestSaveVC(t *testing.T) {
   242  	t.Run("test save vc - success", func(t *testing.T) {
   243  		s, err := New(&mockprovider.Provider{
   244  			StorageProviderValue: mockstore.NewMockStoreProvider(),
   245  		})
   246  		require.NoError(t, err)
   247  		require.NoError(t, s.SaveCredential(sampleCredentialName, &verifiable.Credential{ID: "vc1"}))
   248  	})
   249  
   250  	t.Run("test save vc - error from store put", func(t *testing.T) {
   251  		s, err := New(&mockprovider.Provider{
   252  			StorageProviderValue: mockstore.NewCustomMockStoreProvider(&mockstore.MockStore{
   253  				Store:  make(map[string]mockstore.DBEntry),
   254  				ErrPut: fmt.Errorf("error put"),
   255  			}),
   256  		})
   257  		require.NoError(t, err)
   258  		err = s.SaveCredential(sampleCredentialName, &verifiable.Credential{ID: "vc1"})
   259  		require.Error(t, err)
   260  		require.Contains(t, err.Error(), "error put")
   261  	})
   262  
   263  	t.Run("test save vc - empty name", func(t *testing.T) {
   264  		s, err := New(&mockprovider.Provider{
   265  			StorageProviderValue: mockstore.NewCustomMockStoreProvider(&mockstore.MockStore{
   266  				Store:  make(map[string]mockstore.DBEntry),
   267  				ErrPut: fmt.Errorf("error put"),
   268  			}),
   269  		})
   270  		require.NoError(t, err)
   271  		err = s.SaveCredential("", &verifiable.Credential{ID: "vc1"})
   272  		require.Error(t, err)
   273  		require.Contains(t, err.Error(), "credential name is mandatory")
   274  	})
   275  
   276  	t.Run("test save vc - error getting existing mapping for name", func(t *testing.T) {
   277  		s, err := New(&mockprovider.Provider{
   278  			StorageProviderValue: mockstore.NewCustomMockStoreProvider(&mockstore.MockStore{
   279  				Store:  make(map[string]mockstore.DBEntry),
   280  				ErrGet: fmt.Errorf("error get"),
   281  			}),
   282  		})
   283  		require.NoError(t, err)
   284  		err = s.SaveCredential(sampleCredentialName, &verifiable.Credential{ID: "vc1"})
   285  		require.Error(t, err)
   286  		require.Contains(t, err.Error(), "get credential id using name")
   287  	})
   288  
   289  	t.Run("test save vc - name already exists", func(t *testing.T) {
   290  		s, err := New(&mockprovider.Provider{
   291  			StorageProviderValue: mockstore.NewMockStoreProvider(),
   292  		})
   293  		require.NoError(t, err)
   294  		require.NoError(t, s.SaveCredential(sampleCredentialName, &verifiable.Credential{ID: "vc1"}))
   295  
   296  		err = s.SaveCredential(sampleCredentialName, &verifiable.Credential{ID: "vc2"})
   297  		require.Error(t, err)
   298  		require.Contains(t, err.Error(), "credential name already exists")
   299  	})
   300  
   301  	t.Run("test save vc - with options", func(t *testing.T) {
   302  		const (
   303  			MyDID    = "MyDID"
   304  			TheirDID = "TheirDID"
   305  		)
   306  		s, err := New(&mockprovider.Provider{
   307  			StorageProviderValue: mockstore.NewMockStoreProvider(),
   308  		})
   309  		require.NoError(t, err)
   310  		require.NoError(t, s.SaveCredential(sampleCredentialName, &verifiable.Credential{ID: "vc1"},
   311  			WithMyDID(MyDID), WithTheirDID(TheirDID)))
   312  
   313  		records, err := s.GetCredentials()
   314  		require.NoError(t, err)
   315  		require.Equal(t, 1, len(records))
   316  
   317  		require.Equal(t, MyDID, records[0].MyDID)
   318  		require.Equal(t, TheirDID, records[0].TheirDID)
   319  	})
   320  }
   321  
   322  func TestGetVC(t *testing.T) {
   323  	loader, err := ldtestutil.DocumentLoader()
   324  	require.NoError(t, err)
   325  
   326  	t.Run("test success", func(t *testing.T) {
   327  		s, err := New(&mockprovider.Provider{
   328  			StorageProviderValue: mockstore.NewMockStoreProvider(),
   329  			DocumentLoaderValue:  loader,
   330  		})
   331  		require.NoError(t, err)
   332  		udVC, err := verifiable.ParseCredential([]byte(udCredential),
   333  			verifiable.WithJSONLDDocumentLoader(loader))
   334  		require.NoError(t, err)
   335  		require.NoError(t, s.SaveCredential(sampleCredentialName, udVC))
   336  		vc, err := s.GetCredential("http://example.edu/credentials/1872")
   337  		require.NoError(t, err)
   338  		require.Equal(t, vc.ID, "http://example.edu/credentials/1872")
   339  
   340  		records, err := s.GetCredentials()
   341  		require.NoError(t, err)
   342  		require.NotEmpty(t, records)
   343  
   344  		for _, r := range records {
   345  			require.Equal(t, "did:example:ebfeb1f712ebc6f1c276e12ec21", r.SubjectID)
   346  			require.Equal(t, "http://example.edu/credentials/1872", r.ID)
   347  			require.Equal(t, "sampleVCName", r.Name)
   348  		}
   349  	})
   350  
   351  	t.Run("test success - vc without ID", func(t *testing.T) {
   352  		s, err := New(&mockprovider.Provider{
   353  			StorageProviderValue: mockstore.NewMockStoreProvider(),
   354  			DocumentLoaderValue:  loader,
   355  		})
   356  		require.NoError(t, err)
   357  		udVC, err := verifiable.ParseCredential([]byte(udCredentialWithoutID),
   358  			verifiable.WithJSONLDDocumentLoader(loader))
   359  		require.NoError(t, err)
   360  		require.NoError(t, s.SaveCredential(sampleCredentialName, udVC))
   361  
   362  		id, err := s.GetCredentialIDByName(sampleCredentialName)
   363  		require.NoError(t, err)
   364  		require.NotEmpty(t, id)
   365  
   366  		vc, err := s.GetCredential(id)
   367  		require.NoError(t, err)
   368  		require.NotEmpty(t, vc)
   369  	})
   370  
   371  	t.Run("test error from store get", func(t *testing.T) {
   372  		s, err := New(&mockprovider.Provider{
   373  			StorageProviderValue: mockstore.NewCustomMockStoreProvider(&mockstore.MockStore{
   374  				Store:  make(map[string]mockstore.DBEntry),
   375  				ErrGet: fmt.Errorf("error get"),
   376  			}),
   377  			DocumentLoaderValue: loader,
   378  		})
   379  		require.NoError(t, err)
   380  		vc, err := s.GetCredential("vc1")
   381  		require.Error(t, err)
   382  		require.Contains(t, err.Error(), "error get")
   383  		require.Nil(t, vc)
   384  	})
   385  
   386  	t.Run("test error from new credential", func(t *testing.T) {
   387  		s, err := New(&mockprovider.Provider{
   388  			StorageProviderValue: mockstore.NewMockStoreProvider(),
   389  			DocumentLoaderValue:  loader,
   390  		})
   391  		require.NoError(t, err)
   392  		require.NoError(t, s.SaveCredential(sampleCredentialName, &verifiable.Credential{ID: "vc1"}))
   393  		require.NoError(t, err)
   394  		vc, err := s.GetCredential("vc1")
   395  		require.Error(t, err)
   396  		require.Contains(t, err.Error(), "credential type of unknown structure")
   397  		require.Nil(t, vc)
   398  	})
   399  }
   400  
   401  func TestGetCredentialIDBasedOnName(t *testing.T) {
   402  	t.Run("test get credential based on name - success", func(t *testing.T) {
   403  		rbytes, err := json.Marshal(&Record{
   404  			ID:        sampleCredentialID,
   405  			Name:      "",
   406  			Context:   nil,
   407  			Type:      nil,
   408  			SubjectID: "",
   409  		},
   410  		)
   411  		require.NoError(t, err)
   412  
   413  		store := make(map[string]mockstore.DBEntry)
   414  		store[internal.CredentialNameDataKey(sampleCredentialName)] = mockstore.DBEntry{Value: rbytes}
   415  
   416  		s, err := New(&mockprovider.Provider{
   417  			StorageProviderValue: &mockstore.MockStoreProvider{Store: &mockstore.MockStore{Store: store}},
   418  		})
   419  		require.NoError(t, err)
   420  
   421  		id, err := s.GetCredentialIDByName(sampleCredentialName)
   422  		require.NoError(t, err)
   423  		require.Equal(t, sampleCredentialID, id)
   424  
   425  		id, err = s.GetCredentialIDByName("some-random-id")
   426  		require.Error(t, err)
   427  		require.Empty(t, id)
   428  		require.Contains(t, err.Error(), "fetch credential id based on name : data not found")
   429  	})
   430  
   431  	t.Run("test get credential based on name - db error", func(t *testing.T) {
   432  		s, err := New(&mockprovider.Provider{
   433  			StorageProviderValue: mockstore.NewCustomMockStoreProvider(&mockstore.MockStore{
   434  				Store:  make(map[string]mockstore.DBEntry),
   435  				ErrGet: fmt.Errorf("error get"),
   436  			}),
   437  		})
   438  		require.NoError(t, err)
   439  
   440  		id, err := s.GetCredentialIDByName(sampleCredentialName)
   441  		require.Error(t, err)
   442  		require.Contains(t, err.Error(), "fetch credential id based on name")
   443  		require.Equal(t, "", id)
   444  	})
   445  }
   446  
   447  func TestGetCredentials(t *testing.T) {
   448  	t.Run("test get credentials", func(t *testing.T) {
   449  		store := make(map[string]mockstore.DBEntry)
   450  		s, err := New(&mockprovider.Provider{
   451  			StorageProviderValue: &mockstore.MockStoreProvider{Store: &mockstore.MockStore{Store: store}},
   452  		})
   453  		require.NoError(t, err)
   454  
   455  		records, err := s.GetCredentials()
   456  		require.NoError(t, err)
   457  		require.Equal(t, 0, len(records))
   458  
   459  		err = s.SaveCredential(sampleCredentialName, &verifiable.Credential{ID: sampleCredentialID})
   460  		require.NoError(t, err)
   461  
   462  		records, err = s.GetCredentials()
   463  		require.NoError(t, err)
   464  		require.Equal(t, 1, len(records))
   465  		require.Equal(t, records[0].Name, sampleCredentialName)
   466  		require.Equal(t, records[0].ID, sampleCredentialID)
   467  
   468  		// add some other values and make sure the GetCredential returns records as before
   469  		store["dummy-value"] = mockstore.DBEntry{Value: []byte("dummy-key")}
   470  
   471  		records, err = s.GetCredentials()
   472  		require.NoError(t, err)
   473  		require.Equal(t, 1, len(records))
   474  
   475  		n := 10
   476  		for i := 0; i < n; i++ {
   477  			err = s.SaveCredential(sampleCredentialName+strconv.Itoa(i),
   478  				&verifiable.Credential{ID: sampleCredentialID + strconv.Itoa(i)})
   479  			require.NoError(t, err)
   480  		}
   481  
   482  		records, err = s.GetCredentials()
   483  		require.Equal(t, 1+n, len(records))
   484  		require.NoError(t, err)
   485  	})
   486  }
   487  
   488  func TestSaveVP(t *testing.T) {
   489  	t.Run("test save vp - success", func(t *testing.T) {
   490  		s, err := New(&mockprovider.Provider{
   491  			StorageProviderValue: mockstore.NewMockStoreProvider(),
   492  		})
   493  		require.NoError(t, err)
   494  		require.NoError(t, s.SavePresentation(samplePresentationName, &verifiable.Presentation{ID: "vp1"}))
   495  	})
   496  
   497  	t.Run("test save vp - error from store put", func(t *testing.T) {
   498  		s, err := New(&mockprovider.Provider{
   499  			StorageProviderValue: mockstore.NewCustomMockStoreProvider(&mockstore.MockStore{
   500  				Store:  make(map[string]mockstore.DBEntry),
   501  				ErrPut: fmt.Errorf("error put"),
   502  			}),
   503  		})
   504  		require.NoError(t, err)
   505  		err = s.SavePresentation(samplePresentationName, &verifiable.Presentation{ID: "vp1"})
   506  		require.Error(t, err)
   507  		require.Contains(t, err.Error(), "error put")
   508  	})
   509  
   510  	t.Run("test save vp - empty name", func(t *testing.T) {
   511  		s, err := New(&mockprovider.Provider{
   512  			StorageProviderValue: mockstore.NewCustomMockStoreProvider(&mockstore.MockStore{
   513  				Store:  make(map[string]mockstore.DBEntry),
   514  				ErrPut: fmt.Errorf("error put"),
   515  			}),
   516  		})
   517  		require.NoError(t, err)
   518  		err = s.SavePresentation("", &verifiable.Presentation{ID: "vp1"})
   519  		require.Error(t, err)
   520  		require.Contains(t, err.Error(), "presentation name is mandatory")
   521  	})
   522  
   523  	t.Run("test save vp - error getting existing mapping for name", func(t *testing.T) {
   524  		s, err := New(&mockprovider.Provider{
   525  			StorageProviderValue: mockstore.NewCustomMockStoreProvider(&mockstore.MockStore{
   526  				Store:  make(map[string]mockstore.DBEntry),
   527  				ErrGet: fmt.Errorf("error get"),
   528  			}),
   529  		})
   530  		require.NoError(t, err)
   531  		err = s.SavePresentation(samplePresentationName, &verifiable.Presentation{ID: "vp1"})
   532  		require.Error(t, err)
   533  		require.Contains(t, err.Error(), "get presentation id using name")
   534  	})
   535  
   536  	t.Run("test save vp - name already exists", func(t *testing.T) {
   537  		s, err := New(&mockprovider.Provider{
   538  			StorageProviderValue: mockstore.NewMockStoreProvider(),
   539  		})
   540  		require.NoError(t, err)
   541  		require.NoError(t, s.SavePresentation(samplePresentationName, &verifiable.Presentation{ID: "vp1"}))
   542  
   543  		err = s.SavePresentation(samplePresentationName, &verifiable.Presentation{ID: "vp2"})
   544  		require.Error(t, err)
   545  		require.Contains(t, err.Error(), "presentation name already exists")
   546  	})
   547  
   548  	t.Run("test save vp - with options", func(t *testing.T) {
   549  		const (
   550  			MyDID    = "MyDID"
   551  			TheirDID = "TheirDID"
   552  		)
   553  		s, err := New(&mockprovider.Provider{
   554  			StorageProviderValue: mockstore.NewMockStoreProvider(),
   555  		})
   556  		require.NoError(t, err)
   557  		require.NoError(t, s.SavePresentation(samplePresentationName, &verifiable.Presentation{ID: "vp1"},
   558  			WithMyDID(MyDID), WithTheirDID(TheirDID)))
   559  
   560  		records, err := s.GetPresentations()
   561  		require.NoError(t, err)
   562  		require.Equal(t, 1, len(records))
   563  
   564  		require.Equal(t, MyDID, records[0].MyDID)
   565  		require.Equal(t, TheirDID, records[0].TheirDID)
   566  	})
   567  }
   568  
   569  func TestGetVP(t *testing.T) {
   570  	loader, err := ldtestutil.DocumentLoader()
   571  	require.NoError(t, err)
   572  
   573  	t.Run("test success - save presentation", func(t *testing.T) {
   574  		s, err := New(&mockprovider.Provider{
   575  			StorageProviderValue: mockstore.NewMockStoreProvider(),
   576  			DocumentLoaderValue:  loader,
   577  		})
   578  		require.NoError(t, err)
   579  		udVP, err := verifiable.ParsePresentation([]byte(udPresentation),
   580  			verifiable.WithPresDisabledProofCheck(),
   581  			verifiable.WithPresJSONLDDocumentLoader(loader))
   582  		require.NoError(t, err)
   583  		require.NoError(t, s.SavePresentation(samplePresentationName, udVP))
   584  
   585  		id, err := s.GetPresentationIDByName(samplePresentationName)
   586  		require.NoError(t, err)
   587  		require.NotEmpty(t, id)
   588  
   589  		vp, err := s.GetPresentation(id)
   590  		require.NoError(t, err)
   591  		require.Equal(t, vp.Type[0], "VerifiablePresentation")
   592  		require.NotEmpty(t, vp.Credentials())
   593  		require.EqualValues(t, vp.Credentials()[0].(map[string]interface{})["id"],
   594  			"https://example.com/credentials/9315d0fd-da93-436e-9e20-2121f2821df3")
   595  	})
   596  
   597  	t.Run("test success - save VP", func(t *testing.T) {
   598  		s, err := New(&mockprovider.Provider{
   599  			StorageProviderValue: mockstore.NewMockStoreProvider(),
   600  			DocumentLoaderValue:  loader,
   601  		})
   602  		require.NoError(t, err)
   603  		udVP, err := verifiable.ParsePresentation([]byte(udVerifiablePresentation),
   604  			verifiable.WithPresDisabledProofCheck(),
   605  			verifiable.WithPresJSONLDDocumentLoader(loader))
   606  		require.NoError(t, err)
   607  		require.NoError(t, s.SavePresentation(samplePresentationName, udVP))
   608  
   609  		id, err := s.GetPresentationIDByName(samplePresentationName)
   610  		require.NoError(t, err)
   611  		require.NotEmpty(t, id)
   612  
   613  		vp, err := s.GetPresentation(id)
   614  		require.NoError(t, err)
   615  		require.Equal(t, vp.Type[0], "VerifiablePresentation")
   616  		require.NotEmpty(t, vp.Credentials())
   617  		require.EqualValues(t, vp.Credentials()[0].(map[string]interface{})["id"],
   618  			"https://example.com/credentials/9315d0fd-da93-436e-9e20-2121f2821df3")
   619  	})
   620  
   621  	t.Run("test error from store get", func(t *testing.T) {
   622  		s, err := New(&mockprovider.Provider{
   623  			StorageProviderValue: mockstore.NewCustomMockStoreProvider(&mockstore.MockStore{
   624  				Store:  make(map[string]mockstore.DBEntry),
   625  				ErrGet: fmt.Errorf("error get"),
   626  			}),
   627  			DocumentLoaderValue: loader,
   628  		})
   629  		require.NoError(t, err)
   630  		vp, err := s.GetPresentation("vpxyz")
   631  		require.Error(t, err)
   632  		require.Contains(t, err.Error(), "error get")
   633  		require.Nil(t, vp)
   634  	})
   635  
   636  	t.Run("test error from new presentation", func(t *testing.T) {
   637  		s, err := New(&mockprovider.Provider{
   638  			StorageProviderValue: mockstore.NewMockStoreProvider(),
   639  			DocumentLoaderValue:  loader,
   640  		})
   641  		require.NoError(t, err)
   642  		require.NoError(t, s.SavePresentation(samplePresentationName, &verifiable.Presentation{ID: "vp1"}))
   643  		require.NoError(t, err)
   644  
   645  		vc, err := s.GetPresentation("vp1")
   646  		require.Error(t, err)
   647  		require.Contains(t, err.Error(), "verifiable presentation is not valid")
   648  		require.Nil(t, vc)
   649  	})
   650  }
   651  
   652  func TestGetPresentationIDBasedOnName(t *testing.T) {
   653  	t.Run("test get presentation based on name - success", func(t *testing.T) {
   654  		rbytes, err := json.Marshal(&Record{
   655  			ID:        samplePresentationID,
   656  			Name:      "",
   657  			Context:   nil,
   658  			Type:      nil,
   659  			SubjectID: "",
   660  		},
   661  		)
   662  		require.NoError(t, err)
   663  
   664  		store := make(map[string]mockstore.DBEntry)
   665  		store[internal.PresentationNameDataKey(samplePresentationName)] = mockstore.DBEntry{Value: rbytes}
   666  
   667  		s, err := New(&mockprovider.Provider{
   668  			StorageProviderValue: &mockstore.MockStoreProvider{Store: &mockstore.MockStore{Store: store}},
   669  		})
   670  		require.NoError(t, err)
   671  
   672  		id, err := s.GetPresentationIDByName(samplePresentationName)
   673  		require.NoError(t, err)
   674  		require.Equal(t, samplePresentationID, id)
   675  	})
   676  
   677  	t.Run("test get presentation based on name - db error", func(t *testing.T) {
   678  		s, err := New(&mockprovider.Provider{
   679  			StorageProviderValue: mockstore.NewCustomMockStoreProvider(&mockstore.MockStore{
   680  				Store:  make(map[string]mockstore.DBEntry),
   681  				ErrGet: fmt.Errorf("error get"),
   682  			}),
   683  		})
   684  		require.NoError(t, err)
   685  
   686  		id, err := s.GetPresentationIDByName(samplePresentationName)
   687  		require.Error(t, err)
   688  		require.Contains(t, err.Error(), "fetch presentation id based on name")
   689  		require.Equal(t, "", id)
   690  	})
   691  }
   692  
   693  func TestGetPresentations(t *testing.T) {
   694  	t.Run("test get save & presentations", func(t *testing.T) {
   695  		store := make(map[string]mockstore.DBEntry)
   696  		s, err := New(&mockprovider.Provider{
   697  			StorageProviderValue: &mockstore.MockStoreProvider{Store: &mockstore.MockStore{Store: store}},
   698  		})
   699  		require.NoError(t, err)
   700  
   701  		records, err := s.GetPresentations()
   702  		require.NoError(t, err)
   703  		require.Equal(t, 0, len(records))
   704  
   705  		err = s.SavePresentation(samplePresentationName, &verifiable.Presentation{ID: samplePresentationID})
   706  		require.NoError(t, err)
   707  
   708  		records, err = s.GetPresentations()
   709  		require.NoError(t, err)
   710  		require.Equal(t, 1, len(records))
   711  		require.Equal(t, records[0].Name, samplePresentationName)
   712  		require.Equal(t, records[0].ID, samplePresentationID)
   713  
   714  		// add some other values and make sure the GetCredential returns records as before
   715  		store["dummy-value"] = mockstore.DBEntry{Value: []byte("dummy-key")}
   716  
   717  		records, err = s.GetPresentations()
   718  		require.NoError(t, err)
   719  		require.Equal(t, 1, len(records))
   720  
   721  		n := 10
   722  		for i := 0; i < n; i++ {
   723  			err = s.SavePresentation(samplePresentationName+strconv.Itoa(i),
   724  				&verifiable.Presentation{ID: samplePresentationID + strconv.Itoa(i)})
   725  			require.NoError(t, err)
   726  		}
   727  
   728  		records, err = s.GetPresentations()
   729  		require.NoError(t, err)
   730  		require.Len(t, records, 1+n)
   731  	})
   732  
   733  	t.Run("test get presentations", func(t *testing.T) {
   734  		loader, err := ldtestutil.DocumentLoader()
   735  		require.NoError(t, err)
   736  
   737  		store := make(map[string]mockstore.DBEntry)
   738  		s, err := New(&mockprovider.Provider{
   739  			StorageProviderValue: &mockstore.MockStoreProvider{Store: &mockstore.MockStore{Store: store}},
   740  			DocumentLoaderValue:  loader,
   741  		})
   742  		require.NoError(t, err)
   743  
   744  		udVP, err := verifiable.ParsePresentation([]byte(udVerifiablePresentation),
   745  			verifiable.WithPresDisabledProofCheck(),
   746  			verifiable.WithPresJSONLDDocumentLoader(loader))
   747  		require.NoError(t, err)
   748  		require.NoError(t, s.SavePresentation(samplePresentationName, udVP))
   749  
   750  		records, err := s.GetPresentations()
   751  		require.NoError(t, err)
   752  		require.Len(t, records, 1)
   753  
   754  		require.Equal(t, records[0].Name, samplePresentationName)
   755  		require.Equal(t, records[0].SubjectID, udVP.Holder)
   756  	})
   757  }
   758  
   759  func TestRemoveVC(t *testing.T) {
   760  	loader, err := ldtestutil.DocumentLoader()
   761  	require.NoError(t, err)
   762  
   763  	t.Run("test remove vc - success", func(t *testing.T) {
   764  		s, err := New(&mockprovider.Provider{
   765  			StorageProviderValue: mockstore.NewMockStoreProvider(),
   766  			DocumentLoaderValue:  loader,
   767  		})
   768  		require.NoError(t, err)
   769  		udVC, err := verifiable.ParseCredential([]byte(udCredential),
   770  			verifiable.WithDisabledProofCheck(),
   771  			verifiable.WithJSONLDDocumentLoader(loader))
   772  		require.NoError(t, err)
   773  		require.NoError(t, s.SaveCredential(sampleCredentialName, udVC))
   774  
   775  		id, err := s.GetCredentialIDByName(sampleCredentialName)
   776  		require.NoError(t, err)
   777  		require.NotEmpty(t, id)
   778  
   779  		vc, err := s.GetCredential(id)
   780  		require.NoError(t, err)
   781  		require.Equal(t, vc.Types[0], "VerifiableCredential")
   782  		require.EqualValues(t, vc.ID,
   783  			"http://example.edu/credentials/1872")
   784  
   785  		err = s.RemoveCredentialByName(sampleCredentialName)
   786  		require.NoError(t, err)
   787  
   788  		_, err = s.GetCredentialIDByName(sampleCredentialName)
   789  		require.Error(t, err)
   790  
   791  		_, err = s.GetCredential(id)
   792  		require.Error(t, err)
   793  	})
   794  	t.Run("test remove vc - error from store delete", func(t *testing.T) {
   795  		s, err := New(&mockprovider.Provider{
   796  			StorageProviderValue: mockstore.NewCustomMockStoreProvider(&mockstore.MockStore{
   797  				Store:     make(map[string]mockstore.DBEntry),
   798  				ErrDelete: fmt.Errorf("error delete"),
   799  			}),
   800  			DocumentLoaderValue: loader,
   801  		})
   802  		require.NoError(t, err)
   803  		udVC, err := verifiable.ParseCredential([]byte(udCredential),
   804  			verifiable.WithDisabledProofCheck(),
   805  			verifiable.WithJSONLDDocumentLoader(loader))
   806  		require.NoError(t, err)
   807  		require.NoError(t, s.SaveCredential(sampleCredentialName, udVC))
   808  
   809  		err = s.RemoveCredentialByName(sampleCredentialName)
   810  		require.Error(t, err)
   811  		require.Contains(t, err.Error(), "unable to delete credential")
   812  	})
   813  	t.Run("test remove vc - empty name", func(t *testing.T) {
   814  		s, err := New(&mockprovider.Provider{
   815  			StorageProviderValue: mockstore.NewCustomMockStoreProvider(&mockstore.MockStore{
   816  				Store: make(map[string]mockstore.DBEntry),
   817  			}),
   818  		})
   819  		require.NoError(t, err)
   820  		err = s.RemoveCredentialByName("")
   821  		require.Error(t, err)
   822  		require.Contains(t, err.Error(), "credential name is mandatory")
   823  	})
   824  	t.Run("test remove vc - error removing non-existing credential", func(t *testing.T) {
   825  		s, err := New(&mockprovider.Provider{
   826  			StorageProviderValue: mockstore.NewCustomMockStoreProvider(&mockstore.MockStore{
   827  				Store: make(map[string]mockstore.DBEntry),
   828  			}),
   829  		})
   830  		require.NoError(t, err)
   831  		err = s.RemoveCredentialByName(sampleCredentialName)
   832  		require.Error(t, err)
   833  		require.Contains(t, err.Error(), "get credential id using name")
   834  	})
   835  	t.Run("test remove vc - error removing non-existing credential", func(t *testing.T) {
   836  		s, err := New(&mockprovider.Provider{
   837  			StorageProviderValue: mockstore.NewCustomMockStoreProvider(&mockstore.MockStore{
   838  				Store:  make(map[string]mockstore.DBEntry),
   839  				ErrGet: fmt.Errorf("error get"),
   840  			}),
   841  		})
   842  		require.NoError(t, err)
   843  		err = s.RemoveCredentialByName(sampleCredentialName)
   844  		require.Error(t, err)
   845  		require.Contains(t, err.Error(), "get credential id using name")
   846  	})
   847  }
   848  
   849  func TestRemoveVP(t *testing.T) {
   850  	loader, err := ldtestutil.DocumentLoader()
   851  	require.NoError(t, err)
   852  
   853  	t.Run("test remove vp - success", func(t *testing.T) {
   854  		s, err := New(&mockprovider.Provider{
   855  			StorageProviderValue: mockstore.NewMockStoreProvider(),
   856  			DocumentLoaderValue:  loader,
   857  		})
   858  		require.NoError(t, err)
   859  		udVP, err := verifiable.ParsePresentation([]byte(udPresentation),
   860  			verifiable.WithPresDisabledProofCheck(),
   861  			verifiable.WithPresJSONLDDocumentLoader(loader))
   862  		require.NoError(t, err)
   863  		require.NoError(t, s.SavePresentation(samplePresentationName, udVP))
   864  
   865  		id, err := s.GetPresentationIDByName(samplePresentationName)
   866  		require.NoError(t, err)
   867  		require.NotEmpty(t, id)
   868  
   869  		vp, err := s.GetPresentation(id)
   870  		require.NoError(t, err)
   871  		require.Equal(t, vp.Type[0], "VerifiablePresentation")
   872  		require.NotEmpty(t, vp.Credentials())
   873  		require.EqualValues(t, vp.Credentials()[0].(map[string]interface{})["id"],
   874  			"https://example.com/credentials/9315d0fd-da93-436e-9e20-2121f2821df3")
   875  
   876  		err = s.RemovePresentationByName(samplePresentationName)
   877  		require.NoError(t, err)
   878  
   879  		_, err = s.GetPresentationIDByName(samplePresentationName)
   880  		require.Error(t, err)
   881  
   882  		_, err = s.GetPresentation(id)
   883  		require.Error(t, err)
   884  	})
   885  
   886  	t.Run("test remove vp - error from store delete", func(t *testing.T) {
   887  		s, err := New(&mockprovider.Provider{
   888  			StorageProviderValue: mockstore.NewCustomMockStoreProvider(&mockstore.MockStore{
   889  				Store:     make(map[string]mockstore.DBEntry),
   890  				ErrDelete: fmt.Errorf("error delete"),
   891  			}),
   892  			DocumentLoaderValue: loader,
   893  		})
   894  		require.NoError(t, err)
   895  		udVP, err := verifiable.ParsePresentation([]byte(udPresentation),
   896  			verifiable.WithPresDisabledProofCheck(),
   897  			verifiable.WithPresJSONLDDocumentLoader(loader))
   898  		require.NoError(t, err)
   899  		require.NoError(t, s.SavePresentation(samplePresentationName, udVP))
   900  
   901  		err = s.RemovePresentationByName(samplePresentationName)
   902  		require.Error(t, err)
   903  		require.Contains(t, err.Error(), "unable to delete presentation")
   904  	})
   905  	t.Run("test remove vp - empty name", func(t *testing.T) {
   906  		s, err := New(&mockprovider.Provider{
   907  			StorageProviderValue: mockstore.NewCustomMockStoreProvider(&mockstore.MockStore{
   908  				Store: make(map[string]mockstore.DBEntry),
   909  			}),
   910  		})
   911  		require.NoError(t, err)
   912  		err = s.RemovePresentationByName("")
   913  		require.Error(t, err)
   914  		require.Contains(t, err.Error(), "presentation name is mandatory")
   915  	})
   916  	t.Run("test remove vp - error removing non-existing presentation", func(t *testing.T) {
   917  		s, err := New(&mockprovider.Provider{
   918  			StorageProviderValue: mockstore.NewCustomMockStoreProvider(&mockstore.MockStore{
   919  				Store: make(map[string]mockstore.DBEntry),
   920  			}),
   921  		})
   922  		require.NoError(t, err)
   923  		err = s.RemovePresentationByName(samplePresentationName)
   924  		require.Error(t, err)
   925  		require.Contains(t, err.Error(), "get presentation id using name")
   926  	})
   927  	t.Run("test remove vp - error getting id", func(t *testing.T) {
   928  		s, err := New(&mockprovider.Provider{
   929  			StorageProviderValue: mockstore.NewCustomMockStoreProvider(&mockstore.MockStore{
   930  				Store:  make(map[string]mockstore.DBEntry),
   931  				ErrGet: fmt.Errorf("error get"),
   932  			}),
   933  		})
   934  		require.NoError(t, err)
   935  		err = s.RemovePresentationByName(samplePresentationName)
   936  		require.Error(t, err)
   937  		require.Contains(t, err.Error(), "get presentation id using name")
   938  	})
   939  }