github.com/kaleido-io/firefly@v0.0.0-20210622132723-8b4b6aacb971/internal/database/sqlcommon/node_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 TestNodesE2EWithDB(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 node entry
    40  	node := &fftypes.Node{
    41  		ID:      fftypes.NewUUID(),
    42  		Message: fftypes.NewUUID(),
    43  		Owner:   "0x23456",
    44  		Name:    "node1",
    45  		Created: fftypes.Now(),
    46  	}
    47  	err := s.UpsertNode(ctx, node, true)
    48  	assert.NoError(t, err)
    49  
    50  	// Check we get the exact same node back
    51  	nodeRead, err := s.GetNode(ctx, node.Owner, node.Name)
    52  	assert.NoError(t, err)
    53  	assert.NotNil(t, nodeRead)
    54  	nodeJson, _ := json.Marshal(&node)
    55  	nodeReadJson, _ := json.Marshal(&nodeRead)
    56  	assert.Equal(t, string(nodeJson), string(nodeReadJson))
    57  
    58  	// Rejects attempt to update ID
    59  	err = s.UpsertNode(context.Background(), &fftypes.Node{
    60  		ID:    fftypes.NewUUID(),
    61  		Owner: "0x23456",
    62  		Name:  "node1",
    63  	}, true)
    64  	assert.Equal(t, database.IDMismatch, err)
    65  
    66  	// Update the node (this is testing what's possible at the database layer,
    67  	// and does not account for the verification that happens at the higher level)
    68  	nodeUpdated := &fftypes.Node{
    69  		ID:          nil, // as long as we don't specify one we're fine
    70  		Message:     fftypes.NewUUID(),
    71  		Owner:       "0x23456",
    72  		Name:        "node1",
    73  		Description: "node1",
    74  		DX: fftypes.DXInfo{
    75  			Peer:     "peer1",
    76  			Endpoint: fftypes.JSONObject{"some": "info"},
    77  		},
    78  		Created: fftypes.Now(),
    79  	}
    80  	err = s.UpsertNode(context.Background(), nodeUpdated, true)
    81  	assert.NoError(t, err)
    82  
    83  	// Check we get the exact same data back - note the removal of one of the node elements
    84  	nodeRead, err = s.GetNode(ctx, node.Owner, node.Name)
    85  	assert.NoError(t, err)
    86  	nodeJson, _ = json.Marshal(&nodeUpdated)
    87  	nodeReadJson, _ = json.Marshal(&nodeRead)
    88  	assert.Equal(t, string(nodeJson), string(nodeReadJson))
    89  
    90  	// Query back the node
    91  	fb := database.NodeQueryFactory.NewFilter(ctx)
    92  	filter := fb.And(
    93  		fb.Eq("description", string(nodeUpdated.Description)),
    94  		fb.Eq("name", nodeUpdated.Name),
    95  	)
    96  	nodeRes, err := s.GetNodes(ctx, filter)
    97  	assert.NoError(t, err)
    98  	assert.Equal(t, 1, len(nodeRes))
    99  	nodeReadJson, _ = json.Marshal(nodeRes[0])
   100  	assert.Equal(t, string(nodeJson), string(nodeReadJson))
   101  
   102  	// Update
   103  	updateTime := fftypes.Now()
   104  	up := database.NodeQueryFactory.NewUpdate(ctx).Set("created", updateTime)
   105  	err = s.UpdateNode(ctx, nodeUpdated.ID, up)
   106  	assert.NoError(t, err)
   107  
   108  	// Test find updated value
   109  	filter = fb.And(
   110  		fb.Eq("name", nodeUpdated.Name),
   111  		fb.Eq("created", updateTime.String()),
   112  	)
   113  	nodes, err := s.GetNodes(ctx, filter)
   114  	assert.NoError(t, err)
   115  	assert.Equal(t, 1, len(nodes))
   116  }
   117  
   118  func TestUpsertNodeFailBegin(t *testing.T) {
   119  	s, mock := newMockProvider().init()
   120  	mock.ExpectBegin().WillReturnError(fmt.Errorf("pop"))
   121  	err := s.UpsertNode(context.Background(), &fftypes.Node{}, true)
   122  	assert.Regexp(t, "FF10114", err)
   123  	assert.NoError(t, mock.ExpectationsWereMet())
   124  }
   125  
   126  func TestUpsertNodeFailSelect(t *testing.T) {
   127  	s, mock := newMockProvider().init()
   128  	mock.ExpectBegin()
   129  	mock.ExpectQuery("SELECT .*").WillReturnError(fmt.Errorf("pop"))
   130  	mock.ExpectRollback()
   131  	err := s.UpsertNode(context.Background(), &fftypes.Node{Name: "node1"}, true)
   132  	assert.Regexp(t, "FF10115", err)
   133  	assert.NoError(t, mock.ExpectationsWereMet())
   134  }
   135  
   136  func TestUpsertNodeFailInsert(t *testing.T) {
   137  	s, mock := newMockProvider().init()
   138  	mock.ExpectBegin()
   139  	mock.ExpectQuery("SELECT .*").WillReturnRows(sqlmock.NewRows([]string{}))
   140  	mock.ExpectExec("INSERT .*").WillReturnError(fmt.Errorf("pop"))
   141  	mock.ExpectRollback()
   142  	err := s.UpsertNode(context.Background(), &fftypes.Node{Name: "node1"}, true)
   143  	assert.Regexp(t, "FF10116", err)
   144  	assert.NoError(t, mock.ExpectationsWereMet())
   145  }
   146  
   147  func TestUpsertNodeFailUpdate(t *testing.T) {
   148  	s, mock := newMockProvider().init()
   149  	mock.ExpectBegin()
   150  	mock.ExpectQuery("SELECT .*").WillReturnRows(sqlmock.NewRows([]string{"name"}).
   151  		AddRow("id1"))
   152  	mock.ExpectExec("UPDATE .*").WillReturnError(fmt.Errorf("pop"))
   153  	mock.ExpectRollback()
   154  	err := s.UpsertNode(context.Background(), &fftypes.Node{Name: "node1"}, true)
   155  	assert.Regexp(t, "FF10117", err)
   156  	assert.NoError(t, mock.ExpectationsWereMet())
   157  }
   158  
   159  func TestUpsertNodeFailCommit(t *testing.T) {
   160  	s, mock := newMockProvider().init()
   161  	mock.ExpectBegin()
   162  	mock.ExpectQuery("SELECT .*").WillReturnRows(sqlmock.NewRows([]string{"name"}))
   163  	mock.ExpectExec("INSERT .*").WillReturnResult(sqlmock.NewResult(1, 1))
   164  	mock.ExpectCommit().WillReturnError(fmt.Errorf("pop"))
   165  	err := s.UpsertNode(context.Background(), &fftypes.Node{Name: "node1"}, true)
   166  	assert.Regexp(t, "FF10119", err)
   167  	assert.NoError(t, mock.ExpectationsWereMet())
   168  }
   169  
   170  func TestGetNodeByIDSelectFail(t *testing.T) {
   171  	s, mock := newMockProvider().init()
   172  	mock.ExpectQuery("SELECT .*").WillReturnError(fmt.Errorf("pop"))
   173  	_, err := s.GetNode(context.Background(), "owner1", "node1")
   174  	assert.Regexp(t, "FF10115", err)
   175  	assert.NoError(t, mock.ExpectationsWereMet())
   176  }
   177  
   178  func TestGetNodeByIDNotFound(t *testing.T) {
   179  	s, mock := newMockProvider().init()
   180  	mock.ExpectQuery("SELECT .*").WillReturnRows(sqlmock.NewRows([]string{"name", "node", "name"}))
   181  	msg, err := s.GetNode(context.Background(), "owner1", "node1")
   182  	assert.NoError(t, err)
   183  	assert.Nil(t, msg)
   184  	assert.NoError(t, mock.ExpectationsWereMet())
   185  }
   186  
   187  func TestGetNodeByIDScanFail(t *testing.T) {
   188  	s, mock := newMockProvider().init()
   189  	mock.ExpectQuery("SELECT .*").WillReturnRows(sqlmock.NewRows([]string{"name"}).AddRow("only one"))
   190  	_, err := s.GetNodeByID(context.Background(), fftypes.NewUUID())
   191  	assert.Regexp(t, "FF10121", err)
   192  	assert.NoError(t, mock.ExpectationsWereMet())
   193  }
   194  
   195  func TestGetNodeQueryFail(t *testing.T) {
   196  	s, mock := newMockProvider().init()
   197  	mock.ExpectQuery("SELECT .*").WillReturnError(fmt.Errorf("pop"))
   198  	f := database.NodeQueryFactory.NewFilter(context.Background()).Eq("name", "")
   199  	_, err := s.GetNodes(context.Background(), f)
   200  	assert.Regexp(t, "FF10115", err)
   201  	assert.NoError(t, mock.ExpectationsWereMet())
   202  }
   203  
   204  func TestGetNodeBuildQueryFail(t *testing.T) {
   205  	s, _ := newMockProvider().init()
   206  	f := database.NodeQueryFactory.NewFilter(context.Background()).Eq("name", map[bool]bool{true: false})
   207  	_, err := s.GetNodes(context.Background(), f)
   208  	assert.Regexp(t, "FF10149.*type", err)
   209  }
   210  
   211  func TestGetNodeReadMessageFail(t *testing.T) {
   212  	s, mock := newMockProvider().init()
   213  	mock.ExpectQuery("SELECT .*").WillReturnRows(sqlmock.NewRows([]string{"name"}).AddRow("only one"))
   214  	f := database.NodeQueryFactory.NewFilter(context.Background()).Eq("name", "")
   215  	_, err := s.GetNodes(context.Background(), f)
   216  	assert.Regexp(t, "FF10121", err)
   217  	assert.NoError(t, mock.ExpectationsWereMet())
   218  }
   219  
   220  func TestNodeUpdateBeginFail(t *testing.T) {
   221  	s, mock := newMockProvider().init()
   222  	mock.ExpectBegin().WillReturnError(fmt.Errorf("pop"))
   223  	u := database.NodeQueryFactory.NewUpdate(context.Background()).Set("name", "anything")
   224  	err := s.UpdateNode(context.Background(), fftypes.NewUUID(), u)
   225  	assert.Regexp(t, "FF10114", err)
   226  }
   227  
   228  func TestNodeUpdateBuildQueryFail(t *testing.T) {
   229  	s, mock := newMockProvider().init()
   230  	mock.ExpectBegin()
   231  	u := database.NodeQueryFactory.NewUpdate(context.Background()).Set("name", map[bool]bool{true: false})
   232  	err := s.UpdateNode(context.Background(), fftypes.NewUUID(), u)
   233  	assert.Regexp(t, "FF10149.*name", err)
   234  }
   235  
   236  func TestNodeUpdateFail(t *testing.T) {
   237  	s, mock := newMockProvider().init()
   238  	mock.ExpectBegin()
   239  	mock.ExpectExec("UPDATE .*").WillReturnError(fmt.Errorf("pop"))
   240  	mock.ExpectRollback()
   241  	u := database.NodeQueryFactory.NewUpdate(context.Background()).Set("name", fftypes.NewUUID())
   242  	err := s.UpdateNode(context.Background(), fftypes.NewUUID(), u)
   243  	assert.Regexp(t, "FF10117", err)
   244  }