github.com/kaleido-io/firefly@v0.0.0-20210622132723-8b4b6aacb971/internal/database/sqlcommon/namespace_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 TestNamespacesE2EWithDB(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 namespace entry 40 namespace := &fftypes.Namespace{ 41 ID: nil, // generated for us 42 Message: fftypes.NewUUID(), 43 Type: fftypes.NamespaceTypeLocal, 44 Name: "namespace1", 45 Created: fftypes.Now(), 46 } 47 err := s.UpsertNamespace(ctx, namespace, true) 48 assert.NoError(t, err) 49 50 // Check we get the exact same namespace back 51 namespaceRead, err := s.GetNamespace(ctx, namespace.Name) 52 assert.NoError(t, err) 53 assert.NotNil(t, namespaceRead) 54 namespaceJson, _ := json.Marshal(&namespace) 55 namespaceReadJson, _ := json.Marshal(&namespaceRead) 56 assert.Equal(t, string(namespaceJson), string(namespaceReadJson)) 57 58 // Rejects attempt to update ID 59 err = s.UpsertNamespace(context.Background(), &fftypes.Namespace{ 60 ID: fftypes.NewUUID(), 61 Name: "namespace1", 62 }, true) 63 assert.Equal(t, database.IDMismatch, err) 64 65 // Update the namespace (this is testing what's possible at the database layer, 66 // and does not account for the verification that happens at the higher level) 67 namespaceUpdated := &fftypes.Namespace{ 68 ID: nil, // as long as we don't specify one we're fine 69 Message: fftypes.NewUUID(), 70 Type: fftypes.NamespaceTypeBroadcast, 71 Name: "namespace1", 72 Description: "description1", 73 Created: fftypes.Now(), 74 } 75 err = s.UpsertNamespace(context.Background(), namespaceUpdated, true) 76 assert.NoError(t, err) 77 78 // Check we get the exact same data back - note the removal of one of the namespace elements 79 namespaceRead, err = s.GetNamespace(ctx, namespace.Name) 80 assert.NoError(t, err) 81 namespaceJson, _ = json.Marshal(&namespaceUpdated) 82 namespaceReadJson, _ = json.Marshal(&namespaceRead) 83 assert.Equal(t, string(namespaceJson), string(namespaceReadJson)) 84 85 // Query back the namespace 86 fb := database.NamespaceQueryFactory.NewFilter(ctx) 87 filter := fb.And( 88 fb.Eq("type", string(namespaceUpdated.Type)), 89 fb.Eq("name", namespaceUpdated.Name), 90 ) 91 namespaceRes, err := s.GetNamespaces(ctx, filter) 92 assert.NoError(t, err) 93 assert.Equal(t, 1, len(namespaceRes)) 94 namespaceReadJson, _ = json.Marshal(namespaceRes[0]) 95 assert.Equal(t, string(namespaceJson), string(namespaceReadJson)) 96 97 // Update 98 updateTime := fftypes.Now() 99 up := database.NamespaceQueryFactory.NewUpdate(ctx).Set("created", updateTime) 100 err = s.UpdateNamespace(ctx, namespaceUpdated.ID, up) 101 assert.NoError(t, err) 102 103 // Test find updated value 104 filter = fb.And( 105 fb.Eq("name", namespaceUpdated.Name), 106 fb.Eq("created", updateTime.String()), 107 ) 108 namespaces, err := s.GetNamespaces(ctx, filter) 109 assert.NoError(t, err) 110 assert.Equal(t, 1, len(namespaces)) 111 112 // Delete 113 err = s.DeleteNamespace(ctx, namespaceUpdated.ID) 114 assert.NoError(t, err) 115 namespaces, err = s.GetNamespaces(ctx, filter) 116 assert.NoError(t, err) 117 assert.Equal(t, 0, len(namespaces)) 118 } 119 120 func TestUpsertNamespaceFailBegin(t *testing.T) { 121 s, mock := newMockProvider().init() 122 mock.ExpectBegin().WillReturnError(fmt.Errorf("pop")) 123 err := s.UpsertNamespace(context.Background(), &fftypes.Namespace{}, true) 124 assert.Regexp(t, "FF10114", err) 125 assert.NoError(t, mock.ExpectationsWereMet()) 126 } 127 128 func TestUpsertNamespaceFailSelect(t *testing.T) { 129 s, mock := newMockProvider().init() 130 mock.ExpectBegin() 131 mock.ExpectQuery("SELECT .*").WillReturnError(fmt.Errorf("pop")) 132 mock.ExpectRollback() 133 err := s.UpsertNamespace(context.Background(), &fftypes.Namespace{Name: "name1"}, true) 134 assert.Regexp(t, "FF10115", err) 135 assert.NoError(t, mock.ExpectationsWereMet()) 136 } 137 138 func TestUpsertNamespaceFailInsert(t *testing.T) { 139 s, mock := newMockProvider().init() 140 mock.ExpectBegin() 141 mock.ExpectQuery("SELECT .*").WillReturnRows(sqlmock.NewRows([]string{})) 142 mock.ExpectExec("INSERT .*").WillReturnError(fmt.Errorf("pop")) 143 mock.ExpectRollback() 144 err := s.UpsertNamespace(context.Background(), &fftypes.Namespace{Name: "name1"}, true) 145 assert.Regexp(t, "FF10116", err) 146 assert.NoError(t, mock.ExpectationsWereMet()) 147 } 148 149 func TestUpsertNamespaceFailUpdate(t *testing.T) { 150 s, mock := newMockProvider().init() 151 mock.ExpectBegin() 152 mock.ExpectQuery("SELECT .*").WillReturnRows(sqlmock.NewRows([]string{"name"}). 153 AddRow("name1")) 154 mock.ExpectExec("UPDATE .*").WillReturnError(fmt.Errorf("pop")) 155 mock.ExpectRollback() 156 err := s.UpsertNamespace(context.Background(), &fftypes.Namespace{Name: "name1"}, true) 157 assert.Regexp(t, "FF10117", err) 158 assert.NoError(t, mock.ExpectationsWereMet()) 159 } 160 161 func TestUpsertNamespaceFailCommit(t *testing.T) { 162 s, mock := newMockProvider().init() 163 mock.ExpectBegin() 164 mock.ExpectQuery("SELECT .*").WillReturnRows(sqlmock.NewRows([]string{"name"})) 165 mock.ExpectExec("INSERT .*").WillReturnResult(sqlmock.NewResult(1, 1)) 166 mock.ExpectCommit().WillReturnError(fmt.Errorf("pop")) 167 err := s.UpsertNamespace(context.Background(), &fftypes.Namespace{Name: "name1"}, true) 168 assert.Regexp(t, "FF10119", err) 169 assert.NoError(t, mock.ExpectationsWereMet()) 170 } 171 172 func TestGetNamespaceByIDSelectFail(t *testing.T) { 173 s, mock := newMockProvider().init() 174 mock.ExpectQuery("SELECT .*").WillReturnError(fmt.Errorf("pop")) 175 _, err := s.GetNamespace(context.Background(), "name1") 176 assert.Regexp(t, "FF10115", err) 177 assert.NoError(t, mock.ExpectationsWereMet()) 178 } 179 180 func TestGetNamespaceByIDNotFound(t *testing.T) { 181 s, mock := newMockProvider().init() 182 mock.ExpectQuery("SELECT .*").WillReturnRows(sqlmock.NewRows([]string{"ntype", "namespace", "name"})) 183 msg, err := s.GetNamespace(context.Background(), "name1") 184 assert.NoError(t, err) 185 assert.Nil(t, msg) 186 assert.NoError(t, mock.ExpectationsWereMet()) 187 } 188 189 func TestGetNamespaceByIDScanFail(t *testing.T) { 190 s, mock := newMockProvider().init() 191 mock.ExpectQuery("SELECT .*").WillReturnRows(sqlmock.NewRows([]string{"ntype"}).AddRow("only one")) 192 _, err := s.GetNamespace(context.Background(), "name1") 193 assert.Regexp(t, "FF10121", err) 194 assert.NoError(t, mock.ExpectationsWereMet()) 195 } 196 197 func TestGetNamespaceQueryFail(t *testing.T) { 198 s, mock := newMockProvider().init() 199 mock.ExpectQuery("SELECT .*").WillReturnError(fmt.Errorf("pop")) 200 f := database.NamespaceQueryFactory.NewFilter(context.Background()).Eq("type", "") 201 _, err := s.GetNamespaces(context.Background(), f) 202 assert.Regexp(t, "FF10115", err) 203 assert.NoError(t, mock.ExpectationsWereMet()) 204 } 205 206 func TestGetNamespaceBuildQueryFail(t *testing.T) { 207 s, _ := newMockProvider().init() 208 f := database.NamespaceQueryFactory.NewFilter(context.Background()).Eq("type", map[bool]bool{true: false}) 209 _, err := s.GetNamespaces(context.Background(), f) 210 assert.Regexp(t, "FF10149.*type", err) 211 } 212 213 func TestGetNamespaceReadMessageFail(t *testing.T) { 214 s, mock := newMockProvider().init() 215 mock.ExpectQuery("SELECT .*").WillReturnRows(sqlmock.NewRows([]string{"ntype"}).AddRow("only one")) 216 f := database.NamespaceQueryFactory.NewFilter(context.Background()).Eq("type", "") 217 _, err := s.GetNamespaces(context.Background(), f) 218 assert.Regexp(t, "FF10121", err) 219 assert.NoError(t, mock.ExpectationsWereMet()) 220 } 221 222 func TestNamespaceUpdateBeginFail(t *testing.T) { 223 s, mock := newMockProvider().init() 224 mock.ExpectBegin().WillReturnError(fmt.Errorf("pop")) 225 u := database.NamespaceQueryFactory.NewUpdate(context.Background()).Set("name", "anything") 226 err := s.UpdateNamespace(context.Background(), fftypes.NewUUID(), u) 227 assert.Regexp(t, "FF10114", err) 228 } 229 230 func TestNamespaceUpdateBuildQueryFail(t *testing.T) { 231 s, mock := newMockProvider().init() 232 mock.ExpectBegin() 233 u := database.NamespaceQueryFactory.NewUpdate(context.Background()).Set("name", map[bool]bool{true: false}) 234 err := s.UpdateNamespace(context.Background(), fftypes.NewUUID(), u) 235 assert.Regexp(t, "FF10149.*name", err) 236 } 237 238 func TestNamespaceUpdateFail(t *testing.T) { 239 s, mock := newMockProvider().init() 240 mock.ExpectBegin() 241 mock.ExpectExec("UPDATE .*").WillReturnError(fmt.Errorf("pop")) 242 mock.ExpectRollback() 243 u := database.NamespaceQueryFactory.NewUpdate(context.Background()).Set("name", fftypes.NewUUID()) 244 err := s.UpdateNamespace(context.Background(), fftypes.NewUUID(), u) 245 assert.Regexp(t, "FF10117", err) 246 } 247 248 func TestNamespaceDeleteBeginFail(t *testing.T) { 249 s, mock := newMockProvider().init() 250 mock.ExpectBegin().WillReturnError(fmt.Errorf("pop")) 251 err := s.DeleteNamespace(context.Background(), fftypes.NewUUID()) 252 assert.Regexp(t, "FF10114", err) 253 } 254 255 func TestNamespaceDeleteFail(t *testing.T) { 256 s, mock := newMockProvider().init() 257 mock.ExpectBegin() 258 mock.ExpectExec("DELETE .*").WillReturnError(fmt.Errorf("pop")) 259 mock.ExpectRollback() 260 err := s.DeleteNamespace(context.Background(), fftypes.NewUUID()) 261 assert.Regexp(t, "FF10118", err) 262 }