github.com/kaleido-io/firefly@v0.0.0-20210622132723-8b4b6aacb971/internal/database/sqlcommon/nextpin_sql_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 sqlcommon
    18  
    19  import (
    20  	"context"
    21  	"encoding/json"
    22  	"fmt"
    23  	"testing"
    24  
    25  	"github.com/DATA-DOG/go-sqlmock"
    26  	"github.com/kaleido-io/firefly/internal/log"
    27  	"github.com/kaleido-io/firefly/pkg/database"
    28  	"github.com/kaleido-io/firefly/pkg/fftypes"
    29  	"github.com/stretchr/testify/assert"
    30  )
    31  
    32  func TestNextPinsE2EWithDB(t *testing.T) {
    33  	log.SetLevel("debug")
    34  
    35  	s := newQLTestProvider(t)
    36  	defer s.Close()
    37  	ctx := context.Background()
    38  
    39  	// Create a new nextpin entry
    40  	nextpin := &fftypes.NextPin{
    41  		Context:  fftypes.NewRandB32(),
    42  		Identity: "0x12345",
    43  		Hash:     fftypes.NewRandB32(),
    44  		Nonce:    int64(12345),
    45  	}
    46  	err := s.InsertNextPin(ctx, nextpin)
    47  	assert.NoError(t, err)
    48  
    49  	// Check we get the exact same nextpin back
    50  	nextpinRead, err := s.GetNextPinByContextAndIdentity(ctx, nextpin.Context, nextpin.Identity)
    51  	assert.NoError(t, err)
    52  	assert.NotNil(t, nextpinRead)
    53  	nextpinJson, _ := json.Marshal(&nextpin)
    54  	nextpinReadJson, _ := json.Marshal(&nextpinRead)
    55  	assert.Equal(t, string(nextpinJson), string(nextpinReadJson))
    56  
    57  	// Attempt with wrong ID
    58  	var nextpinUpdated fftypes.NextPin
    59  	nextpinUpdated = *nextpin
    60  	nextpinUpdated.Nonce = 1111111
    61  	nextpinUpdated.Hash = fftypes.NewRandB32()
    62  	err = s.UpdateNextPin(context.Background(), nextpin.Sequence, database.NextPinQueryFactory.NewUpdate(ctx).
    63  		Set("hash", nextpinUpdated.Hash).
    64  		Set("nonce", nextpinUpdated.Nonce),
    65  	)
    66  
    67  	// Check we get the exact same data back - note the removal of one of the nextpin elements
    68  	nextpinRead, err = s.GetNextPinByHash(ctx, nextpinUpdated.Hash)
    69  	assert.NoError(t, err)
    70  	nextpinJson, _ = json.Marshal(&nextpinUpdated)
    71  	nextpinReadJson, _ = json.Marshal(&nextpinRead)
    72  	assert.Equal(t, string(nextpinJson), string(nextpinReadJson))
    73  
    74  	// Query back the nextpin
    75  	fb := database.NextPinQueryFactory.NewFilter(ctx)
    76  	filter := fb.And(
    77  		fb.Eq("context", nextpinUpdated.Context),
    78  		fb.Eq("hash", nextpinUpdated.Hash),
    79  		fb.Eq("identity", nextpinUpdated.Identity),
    80  		fb.Eq("nonce", nextpinUpdated.Nonce),
    81  	)
    82  	nextpinRes, err := s.GetNextPins(ctx, filter)
    83  	assert.NoError(t, err)
    84  	assert.Equal(t, 1, len(nextpinRes))
    85  	nextpinReadJson, _ = json.Marshal(nextpinRes[0])
    86  	assert.Equal(t, string(nextpinJson), string(nextpinReadJson))
    87  
    88  	// Test delete
    89  	err = s.DeleteNextPin(ctx, nextpinUpdated.Sequence)
    90  	assert.NoError(t, err)
    91  	nextpins, err := s.GetNextPins(ctx, filter)
    92  	assert.NoError(t, err)
    93  	assert.Equal(t, 0, len(nextpins))
    94  
    95  }
    96  
    97  func TestUpsertNextPinFailBegin(t *testing.T) {
    98  	s, mock := newMockProvider().init()
    99  	mock.ExpectBegin().WillReturnError(fmt.Errorf("pop"))
   100  	err := s.InsertNextPin(context.Background(), &fftypes.NextPin{})
   101  	assert.Regexp(t, "FF10114", err)
   102  	assert.NoError(t, mock.ExpectationsWereMet())
   103  }
   104  
   105  func TestUpsertNextPinFailInsert(t *testing.T) {
   106  	s, mock := newMockProvider().init()
   107  	mock.ExpectBegin()
   108  	mock.ExpectExec("INSERT .*").WillReturnError(fmt.Errorf("pop"))
   109  	mock.ExpectRollback()
   110  	err := s.InsertNextPin(context.Background(), &fftypes.NextPin{Context: fftypes.NewRandB32()})
   111  	assert.Regexp(t, "FF10116", err)
   112  	assert.NoError(t, mock.ExpectationsWereMet())
   113  }
   114  
   115  func TestUpsertNextPinFailCommit(t *testing.T) {
   116  	s, mock := newMockProvider().init()
   117  	mock.ExpectBegin()
   118  	mock.ExpectExec("INSERT .*").WillReturnResult(sqlmock.NewResult(1, 1))
   119  	mock.ExpectCommit().WillReturnError(fmt.Errorf("pop"))
   120  	err := s.InsertNextPin(context.Background(), &fftypes.NextPin{Context: fftypes.NewRandB32()})
   121  	assert.Regexp(t, "FF10119", err)
   122  	assert.NoError(t, mock.ExpectationsWereMet())
   123  }
   124  
   125  func TestGetNextPinByIDSelectFail(t *testing.T) {
   126  	s, mock := newMockProvider().init()
   127  	mock.ExpectQuery("SELECT .*").WillReturnError(fmt.Errorf("pop"))
   128  	_, err := s.GetNextPinByContextAndIdentity(context.Background(), fftypes.NewRandB32(), "0x12345")
   129  	assert.Regexp(t, "FF10115", err)
   130  	assert.NoError(t, mock.ExpectationsWereMet())
   131  }
   132  
   133  func TestGetNextPinByIDNotFound(t *testing.T) {
   134  	s, mock := newMockProvider().init()
   135  	mock.ExpectQuery("SELECT .*").WillReturnRows(sqlmock.NewRows([]string{}))
   136  	msg, err := s.GetNextPinByContextAndIdentity(context.Background(), fftypes.NewRandB32(), "0x12345")
   137  	assert.NoError(t, err)
   138  	assert.Nil(t, msg)
   139  	assert.NoError(t, mock.ExpectationsWereMet())
   140  }
   141  
   142  func TestGetNextPinByIDScanFail(t *testing.T) {
   143  	s, mock := newMockProvider().init()
   144  	mock.ExpectQuery("SELECT .*").WillReturnRows(sqlmock.NewRows([]string{"context"}).AddRow("only one"))
   145  	_, err := s.GetNextPinByContextAndIdentity(context.Background(), fftypes.NewRandB32(), "0x12345")
   146  	assert.Regexp(t, "FF10121", err)
   147  	assert.NoError(t, mock.ExpectationsWereMet())
   148  }
   149  
   150  func TestGetNextPinQueryFail(t *testing.T) {
   151  	s, mock := newMockProvider().init()
   152  	mock.ExpectQuery("SELECT .*").WillReturnError(fmt.Errorf("pop"))
   153  	f := database.NextPinQueryFactory.NewFilter(context.Background()).Eq("context", "")
   154  	_, err := s.GetNextPins(context.Background(), f)
   155  	assert.Regexp(t, "FF10115", err)
   156  	assert.NoError(t, mock.ExpectationsWereMet())
   157  }
   158  
   159  func TestGetNextPinBuildQueryFail(t *testing.T) {
   160  	s, _ := newMockProvider().init()
   161  	f := database.NextPinQueryFactory.NewFilter(context.Background()).Eq("context", map[bool]bool{true: false})
   162  	_, err := s.GetNextPins(context.Background(), f)
   163  	assert.Regexp(t, "FF10149.*type", err)
   164  }
   165  
   166  func TestGetNextPinReadMessageFail(t *testing.T) {
   167  	s, mock := newMockProvider().init()
   168  	mock.ExpectQuery("SELECT .*").WillReturnRows(sqlmock.NewRows([]string{"context"}).AddRow("only one"))
   169  	f := database.NextPinQueryFactory.NewFilter(context.Background()).Eq("context", "")
   170  	_, err := s.GetNextPins(context.Background(), f)
   171  	assert.Regexp(t, "FF10121", err)
   172  	assert.NoError(t, mock.ExpectationsWereMet())
   173  }
   174  
   175  func TestNextPinUpdateBeginFail(t *testing.T) {
   176  	s, mock := newMockProvider().init()
   177  	mock.ExpectBegin().WillReturnError(fmt.Errorf("pop"))
   178  	u := database.NextPinQueryFactory.NewUpdate(context.Background()).Set("context", "anything")
   179  	err := s.UpdateNextPin(context.Background(), 12345, u)
   180  	assert.Regexp(t, "FF10114", err)
   181  }
   182  
   183  func TestNextPinUpdateBuildQueryFail(t *testing.T) {
   184  	s, mock := newMockProvider().init()
   185  	mock.ExpectBegin()
   186  	u := database.NextPinQueryFactory.NewUpdate(context.Background()).Set("context", map[bool]bool{true: false})
   187  	err := s.UpdateNextPin(context.Background(), 12345, u)
   188  	assert.Regexp(t, "FF10149.*context", err)
   189  }
   190  
   191  func TestNextPinUpdateFail(t *testing.T) {
   192  	s, mock := newMockProvider().init()
   193  	mock.ExpectBegin()
   194  	mock.ExpectExec("UPDATE .*").WillReturnError(fmt.Errorf("pop"))
   195  	mock.ExpectRollback()
   196  	u := database.NextPinQueryFactory.NewUpdate(context.Background()).Set("context", fftypes.NewUUID())
   197  	err := s.UpdateNextPin(context.Background(), 12345, u)
   198  	assert.Regexp(t, "FF10117", err)
   199  }
   200  
   201  func TestNextPinDeleteBeginFail(t *testing.T) {
   202  	s, mock := newMockProvider().init()
   203  	mock.ExpectBegin().WillReturnError(fmt.Errorf("pop"))
   204  	err := s.DeleteNextPin(context.Background(), 12345)
   205  	assert.Regexp(t, "FF10114", err)
   206  }
   207  
   208  func TestNextPinDeleteFail(t *testing.T) {
   209  	s, mock := newMockProvider().init()
   210  	mock.ExpectBegin()
   211  	mock.ExpectExec("DELETE .*").WillReturnError(fmt.Errorf("pop"))
   212  	mock.ExpectRollback()
   213  	err := s.DeleteNextPin(context.Background(), 12345)
   214  	assert.Regexp(t, "FF10118", err)
   215  }