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

     1  /*
     2  Copyright SecureKey Technologies Inc. All Rights Reserved.
     3  SPDX-License-Identifier: Apache-2.0
     4  */
     5  
     6  package did_test
     7  
     8  import (
     9  	"crypto/ed25519"
    10  	"crypto/rand"
    11  	"fmt"
    12  	"strconv"
    13  	"testing"
    14  	"time"
    15  
    16  	"github.com/btcsuite/btcutil/base58"
    17  	"github.com/stretchr/testify/require"
    18  
    19  	"github.com/hyperledger/aries-framework-go/component/storageutil/mem"
    20  	"github.com/hyperledger/aries-framework-go/pkg/common/model"
    21  	"github.com/hyperledger/aries-framework-go/pkg/doc/did"
    22  	mockprovider "github.com/hyperledger/aries-framework-go/pkg/mock/provider"
    23  	mockstore "github.com/hyperledger/aries-framework-go/pkg/mock/storage"
    24  	didstore "github.com/hyperledger/aries-framework-go/pkg/store/did"
    25  )
    26  
    27  const (
    28  	sampleDIDName = "sampleDIDName"
    29  	sampleDIDID   = "sampleDIDID"
    30  )
    31  
    32  func TestNew(t *testing.T) {
    33  	t.Run("test new store", func(t *testing.T) {
    34  		s, err := didstore.New(&mockprovider.Provider{
    35  			StorageProviderValue: mem.NewProvider(),
    36  		})
    37  		require.NoError(t, err)
    38  		require.NotNil(t, s)
    39  	})
    40  
    41  	t.Run("test error from open store", func(t *testing.T) {
    42  		s, err := didstore.New(&mockprovider.Provider{
    43  			StorageProviderValue: &mockstore.MockStoreProvider{
    44  				ErrOpenStoreHandle: fmt.Errorf("failed to open store"),
    45  			},
    46  		})
    47  		require.Error(t, err)
    48  		require.Contains(t, err.Error(), "failed to open store")
    49  		require.Nil(t, s)
    50  	})
    51  }
    52  
    53  func TestSaveDID(t *testing.T) {
    54  	t.Run("test save did doc - success", func(t *testing.T) {
    55  		s, err := didstore.New(&mockprovider.Provider{
    56  			StorageProviderValue: mockstore.NewMockStoreProvider(),
    57  		})
    58  		require.NoError(t, err)
    59  		require.NoError(t, s.SaveDID(sampleDIDName, &did.Doc{ID: "did1"}))
    60  	})
    61  
    62  	t.Run("test save did doc - error from store put", func(t *testing.T) {
    63  		s, err := didstore.New(&mockprovider.Provider{
    64  			StorageProviderValue: mockstore.NewCustomMockStoreProvider(&mockstore.MockStore{
    65  				Store:  make(map[string]mockstore.DBEntry),
    66  				ErrPut: fmt.Errorf("error put"),
    67  			}),
    68  		})
    69  		require.NoError(t, err)
    70  		err = s.SaveDID(sampleDIDName, &did.Doc{ID: "did1"})
    71  		require.Error(t, err)
    72  		require.Contains(t, err.Error(), "error put")
    73  	})
    74  
    75  	t.Run("test save did doc - empty name", func(t *testing.T) {
    76  		s, err := didstore.New(&mockprovider.Provider{
    77  			StorageProviderValue: mockstore.NewCustomMockStoreProvider(&mockstore.MockStore{
    78  				Store:  make(map[string]mockstore.DBEntry),
    79  				ErrPut: fmt.Errorf("error put"),
    80  			}),
    81  		})
    82  		require.NoError(t, err)
    83  		err = s.SaveDID("", &did.Doc{ID: "did1"})
    84  		require.Error(t, err)
    85  		require.Contains(t, err.Error(), "did name is mandatory")
    86  	})
    87  
    88  	t.Run("test save did doc - error getting existing mapping for name", func(t *testing.T) {
    89  		s, err := didstore.New(&mockprovider.Provider{
    90  			StorageProviderValue: mockstore.NewCustomMockStoreProvider(&mockstore.MockStore{
    91  				Store:  make(map[string]mockstore.DBEntry),
    92  				ErrGet: fmt.Errorf("error get"),
    93  			}),
    94  		})
    95  		require.NoError(t, err)
    96  		err = s.SaveDID(sampleDIDName, &did.Doc{ID: "did1"})
    97  		require.Error(t, err)
    98  		require.Contains(t, err.Error(), "get did using name")
    99  	})
   100  
   101  	t.Run("test save did doc - name already exists", func(t *testing.T) {
   102  		s, err := didstore.New(&mockprovider.Provider{
   103  			StorageProviderValue: mockstore.NewMockStoreProvider(),
   104  		})
   105  		require.NoError(t, err)
   106  		require.NoError(t, s.SaveDID(sampleDIDName, &did.Doc{ID: "did1"}))
   107  
   108  		err = s.SaveDID(sampleDIDName, &did.Doc{ID: "did2"})
   109  		require.Error(t, err)
   110  		require.Contains(t, err.Error(), "did name already exists")
   111  	})
   112  }
   113  
   114  func TestGetDIDDoc(t *testing.T) {
   115  	t.Run("test success", func(t *testing.T) {
   116  		s, err := didstore.New(&mockprovider.Provider{
   117  			StorageProviderValue: mockstore.NewMockStoreProvider(),
   118  		})
   119  		require.NoError(t, err)
   120  		didDoc := createDIDDoc()
   121  		require.NoError(t, s.SaveDID(sampleDIDName, didDoc))
   122  		doc, err := s.GetDID((didDoc.ID))
   123  		require.NoError(t, err)
   124  		require.Equal(t, doc.ID, didDoc.ID)
   125  	})
   126  
   127  	t.Run("test error from store get", func(t *testing.T) {
   128  		s, err := didstore.New(&mockprovider.Provider{
   129  			StorageProviderValue: mockstore.NewCustomMockStoreProvider(&mockstore.MockStore{
   130  				Store:  make(map[string]mockstore.DBEntry),
   131  				ErrGet: fmt.Errorf("error get"),
   132  			}),
   133  		})
   134  		require.NoError(t, err)
   135  		didDoc, err := s.GetDID("did1")
   136  		require.Error(t, err)
   137  		require.Contains(t, err.Error(), "error get")
   138  		require.Nil(t, didDoc)
   139  	})
   140  
   141  	t.Run("test error data not found", func(t *testing.T) {
   142  		s, err := didstore.New(&mockprovider.Provider{
   143  			StorageProviderValue: mockstore.NewMockStoreProvider(),
   144  		})
   145  		require.NoError(t, err)
   146  		require.NoError(t, s.SaveDID(sampleDIDName, &did.Doc{ID: "did1"}))
   147  		require.NoError(t, err)
   148  		didDoc, err := s.GetDID("did12")
   149  		require.Error(t, err)
   150  		require.Contains(t, err.Error(), "data not found")
   151  		require.Nil(t, didDoc)
   152  	})
   153  }
   154  
   155  func TestDIDBasedOnName(t *testing.T) {
   156  	t.Run("test get didDoc based on name - success", func(t *testing.T) {
   157  		store := make(map[string]mockstore.DBEntry)
   158  		store[didNameDataKey(sampleDIDName)] = mockstore.DBEntry{Value: []byte(sampleDIDID)}
   159  
   160  		s, err := didstore.New(&mockprovider.Provider{
   161  			StorageProviderValue: &mockstore.MockStoreProvider{Store: &mockstore.MockStore{Store: store}},
   162  		})
   163  		require.NoError(t, err)
   164  
   165  		id, err := s.GetDIDByName(sampleDIDName)
   166  		require.NoError(t, err)
   167  		require.Equal(t, sampleDIDID, id)
   168  	})
   169  
   170  	t.Run("test get didDoc based on name - db error", func(t *testing.T) {
   171  		s, err := didstore.New(&mockprovider.Provider{
   172  			StorageProviderValue: mockstore.NewCustomMockStoreProvider(&mockstore.MockStore{
   173  				Store:  make(map[string]mockstore.DBEntry),
   174  				ErrGet: fmt.Errorf("error get"),
   175  			}),
   176  		})
   177  		require.NoError(t, err)
   178  
   179  		id, err := s.GetDIDByName(sampleDIDName)
   180  		require.Error(t, err)
   181  		require.Contains(t, err.Error(), "fetch did doc id based on name")
   182  		require.Equal(t, "", id)
   183  	})
   184  }
   185  
   186  func TestGetCredentials(t *testing.T) {
   187  	t.Run("test get dids", func(t *testing.T) {
   188  		store := make(map[string]mockstore.DBEntry)
   189  		s, err := didstore.New(&mockprovider.Provider{
   190  			StorageProviderValue: &mockstore.MockStoreProvider{Store: &mockstore.MockStore{Store: store}},
   191  		})
   192  		require.NoError(t, err)
   193  
   194  		records := s.GetDIDRecords()
   195  		require.Equal(t, 0, len(records))
   196  
   197  		err = s.SaveDID(sampleDIDName, &did.Doc{ID: sampleDIDID})
   198  		require.NoError(t, err)
   199  
   200  		records = s.GetDIDRecords()
   201  		require.Equal(t, 1, len(records))
   202  		require.Equal(t, records[0].Name, sampleDIDName)
   203  		require.Equal(t, records[0].ID, sampleDIDID)
   204  
   205  		// add some other values and make sure the GetCredential returns records as before
   206  		store["dummy-value"] = mockstore.DBEntry{Value: []byte("dummy-key")}
   207  
   208  		records = s.GetDIDRecords()
   209  		require.Equal(t, 1, len(records))
   210  
   211  		n := 10
   212  		for i := 0; i < n; i++ {
   213  			err = s.SaveDID(sampleDIDName+strconv.Itoa(i),
   214  				&did.Doc{ID: sampleDIDID + strconv.Itoa(i)})
   215  			require.NoError(t, err)
   216  		}
   217  
   218  		records = s.GetDIDRecords()
   219  		require.Equal(t, 1+n, len(records))
   220  	})
   221  }
   222  
   223  func didNameDataKey(name string) string {
   224  	return fmt.Sprintf("didname_%s", name)
   225  }
   226  
   227  func createDIDDoc() *did.Doc {
   228  	pubKey, _ := generateKeyPair()
   229  	return createDIDDocWithKey(pubKey)
   230  }
   231  
   232  func generateKeyPair() (string, []byte) {
   233  	pubKey, privKey, err := ed25519.GenerateKey(rand.Reader)
   234  	if err != nil {
   235  		panic(err)
   236  	}
   237  
   238  	return base58.Encode(pubKey[:]), privKey
   239  }
   240  
   241  func createDIDDocWithKey(pub string) *did.Doc {
   242  	const (
   243  		didFormat    = "did:%s:%s"
   244  		didPKID      = "%s#keys-%d"
   245  		didServiceID = "%s#endpoint-%d"
   246  		method       = "test"
   247  	)
   248  
   249  	id := fmt.Sprintf(didFormat, method, pub[:16])
   250  	pubKeyID := fmt.Sprintf(didPKID, id, 1)
   251  	pubKey := did.VerificationMethod{
   252  		ID:         pubKeyID,
   253  		Type:       "Ed25519VerificationKey2018",
   254  		Controller: id,
   255  		Value:      []byte(pub),
   256  	}
   257  	services := []did.Service{
   258  		{
   259  			ID:              fmt.Sprintf(didServiceID, id, 1),
   260  			Type:            "did-communication",
   261  			ServiceEndpoint: model.NewDIDCommV1Endpoint("http://localhost:58416"),
   262  			Priority:        0,
   263  			RecipientKeys:   []string{pubKeyID},
   264  		},
   265  	}
   266  	createdTime := time.Now()
   267  	didDoc := &did.Doc{
   268  		Context:            []string{did.ContextV1},
   269  		ID:                 id,
   270  		VerificationMethod: []did.VerificationMethod{pubKey},
   271  		Service:            services,
   272  		Created:            &createdTime,
   273  		Updated:            &createdTime,
   274  	}
   275  
   276  	return didDoc
   277  }