github.com/minio/console@v1.4.1/api/errors_test.go (about) 1 // This file is part of MinIO Console Server 2 // Copyright (c) 2021 MinIO, Inc. 3 // 4 // This program is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Affero General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // This program is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Affero General Public License for more details. 13 // 14 // You should have received a copy of the GNU Affero General Public License 15 // along with this program. If not, see <http://www.gnu.org/licenses/>. 16 17 package api 18 19 import ( 20 "context" 21 "fmt" 22 "testing" 23 24 "github.com/minio/console/models" 25 "github.com/stretchr/testify/assert" 26 ) 27 28 func TestError(t *testing.T) { 29 type args struct { 30 err []interface{} 31 } 32 33 type testError struct { 34 name string 35 args args 36 want *CodedAPIError 37 } 38 39 var tests []testError 40 41 type expectedError struct { 42 err error 43 code int 44 } 45 46 appErrors := map[string]expectedError{ 47 "ErrDefault": {code: 500, err: ErrDefault}, 48 49 "ErrForbidden": {code: 403, err: ErrForbidden}, 50 "ErrFileTooLarge": {code: 413, err: ErrFileTooLarge}, 51 "ErrInvalidSession": {code: 401, err: ErrInvalidSession}, 52 "ErrNotFound": {code: 404, err: ErrNotFound}, 53 "ErrGroupAlreadyExists": {code: 400, err: ErrGroupAlreadyExists}, 54 "ErrInvalidErasureCodingValue": {code: 400, err: ErrInvalidErasureCodingValue}, 55 "ErrBucketBodyNotInRequest": {code: 400, err: ErrBucketBodyNotInRequest}, 56 "ErrBucketNameNotInRequest": {code: 400, err: ErrBucketNameNotInRequest}, 57 "ErrGroupBodyNotInRequest": {code: 400, err: ErrGroupBodyNotInRequest}, 58 "ErrGroupNameNotInRequest": {code: 400, err: ErrGroupNameNotInRequest}, 59 "ErrPolicyNameNotInRequest": {code: 400, err: ErrPolicyNameNotInRequest}, 60 "ErrPolicyBodyNotInRequest": {code: 400, err: ErrPolicyBodyNotInRequest}, 61 "ErrInvalidEncryptionAlgorithm": {code: 500, err: ErrInvalidEncryptionAlgorithm}, 62 "ErrSSENotConfigured": {code: 404, err: ErrSSENotConfigured}, 63 "ErrBucketLifeCycleNotConfigured": {code: 404, err: ErrBucketLifeCycleNotConfigured}, 64 "ErrChangePassword": {code: 403, err: ErrChangePassword}, 65 "ErrInvalidLicense": {code: 404, err: ErrInvalidLicense}, 66 "ErrLicenseNotFound": {code: 404, err: ErrLicenseNotFound}, 67 "ErrAvoidSelfAccountDelete": {code: 403, err: ErrAvoidSelfAccountDelete}, 68 69 "ErrNonUniqueAccessKey": {code: 500, err: ErrNonUniqueAccessKey}, 70 "ErrRemoteTierExists": {code: 400, err: ErrRemoteTierExists}, 71 "ErrRemoteTierNotFound": {code: 400, err: ErrRemoteTierNotFound}, 72 "ErrRemoteTierUppercase": {code: 400, err: ErrRemoteTierUppercase}, 73 "ErrRemoteTierBucketNotFound": {code: 400, err: ErrRemoteTierBucketNotFound}, 74 "ErrRemoteInvalidCredentials": {code: 403, err: ErrRemoteInvalidCredentials}, 75 "ErrTooFewNodes": {code: 500, err: ErrTooFewNodes}, 76 "ErrUnableToGetTenantUsage": {code: 500, err: ErrUnableToGetTenantUsage}, 77 "ErrTooManyNodes": {code: 500, err: ErrTooManyNodes}, 78 "ErrAccessDenied": {code: 403, err: ErrAccessDenied}, 79 "ErrTooFewAvailableNodes": {code: 500, err: ErrTooFewAvailableNodes}, 80 "ErrFewerThanFourNodes": {code: 500, err: ErrFewerThanFourNodes}, 81 "ErrUnableToGetTenantLogs": {code: 500, err: ErrUnableToGetTenantLogs}, 82 "ErrUnableToUpdateTenantCertificates": {code: 500, err: ErrUnableToUpdateTenantCertificates}, 83 "ErrUpdatingEncryptionConfig": {code: 500, err: ErrUpdatingEncryptionConfig}, 84 "ErrDeletingEncryptionConfig": {code: 500, err: ErrDeletingEncryptionConfig}, 85 "ErrEncryptionConfigNotFound": {code: 404, err: ErrEncryptionConfigNotFound}, 86 } 87 88 for k, e := range appErrors { 89 tests = append(tests, testError{ 90 name: fmt.Sprintf("%s error", k), 91 args: args{ 92 err: []interface{}{e.err}, 93 }, 94 want: &CodedAPIError{ 95 Code: e.code, 96 APIError: &models.APIError{Message: e.err.Error(), DetailedMessage: e.err.Error()}, 97 }, 98 }) 99 } 100 101 tests = append(tests, 102 testError{ 103 name: "passing multiple errors but ErrInvalidLogin is last", 104 args: args{ 105 err: []interface{}{ErrDefault, ErrInvalidLogin}, 106 }, 107 want: &CodedAPIError{ 108 Code: int(401), 109 APIError: &models.APIError{Message: ErrDefault.Error(), DetailedMessage: ""}, 110 }, 111 }) 112 tests = append(tests, 113 testError{ 114 name: "login error omits detailedMessage", 115 args: args{ 116 err: []interface{}{ErrInvalidLogin}, 117 }, 118 want: &CodedAPIError{ 119 Code: int(401), 120 APIError: &models.APIError{Message: ErrInvalidLogin.Error(), DetailedMessage: ""}, 121 }, 122 }) 123 124 for _, tt := range tests { 125 t.Run(tt.name, func(_ *testing.T) { 126 got := Error(tt.args.err...) 127 assert.Equalf(t, tt.want.Code, got.Code, "Error(%v) Got (%v)", tt.want.Code, got.Code) 128 assert.Equalf(t, tt.want.APIError.DetailedMessage, got.APIError.DetailedMessage, "Error(%s) Got (%s)", tt.want.APIError.DetailedMessage, got.APIError.DetailedMessage) 129 }) 130 } 131 } 132 133 func TestErrorWithContext(t *testing.T) { 134 type args struct { 135 ctx context.Context 136 err []interface{} 137 } 138 tests := []struct { 139 name string 140 args args 141 want *CodedAPIError 142 }{ 143 { 144 name: "default error", 145 args: args{ 146 ctx: context.Background(), 147 err: []interface{}{ErrDefault}, 148 }, 149 want: &CodedAPIError{ 150 Code: 500, APIError: &models.APIError{Message: ErrDefault.Error(), DetailedMessage: ErrDefault.Error()}, 151 }, 152 }, 153 } 154 for _, tt := range tests { 155 t.Run(tt.name, func(_ *testing.T) { 156 assert.Equalf(t, tt.want, ErrorWithContext(tt.args.ctx, tt.args.err...), "ErrorWithContext(%v, %v)", tt.args.ctx, tt.args.err) 157 }) 158 } 159 }