github.com/go-graphite/carbonapi@v0.17.0/zipper/helper/errors_test.go (about)

     1  package helper
     2  
     3  import (
     4  	"fmt"
     5  	"net"
     6  	"net/http"
     7  	"reflect"
     8  	"testing"
     9  
    10  	"github.com/ansel1/merry"
    11  	"github.com/go-graphite/carbonapi/zipper/types"
    12  )
    13  
    14  func TestMergeHttpErrors(t *testing.T) {
    15  	tests := []struct {
    16  		name     string
    17  		errors   []merry.Error
    18  		wantCode int
    19  		want     []string
    20  	}{
    21  		{
    22  			name:     "NotFound",
    23  			errors:   []merry.Error{},
    24  			wantCode: http.StatusNotFound,
    25  			want:     []string{},
    26  		},
    27  		{
    28  			name: "NetErr",
    29  			errors: []merry.Error{
    30  				types.ErrBackendError.WithValue("server", "test").WithCause(&net.OpError{Op: "connect", Err: fmt.Errorf("refused")}).WithHTTPCode(http.StatusServiceUnavailable),
    31  			},
    32  			wantCode: http.StatusServiceUnavailable,
    33  			want:     []string{"connect: refused"},
    34  		},
    35  		{
    36  			name: "NetErr (incapsulated)",
    37  			errors: []merry.Error{
    38  				types.ErrMaxTriesExceeded.WithCause(types.ErrBackendError.WithValue("server", "test").WithCause(&net.OpError{Op: "connect", Err: fmt.Errorf("refused")})).WithHTTPCode(http.StatusServiceUnavailable),
    39  			},
    40  			wantCode: http.StatusServiceUnavailable,
    41  			want:     []string{"connect: refused"},
    42  		},
    43  		{
    44  			name: "ServiceUnavailable",
    45  			errors: []merry.Error{
    46  				merry.New("unavaliable").WithHTTPCode(http.StatusServiceUnavailable),
    47  			},
    48  			wantCode: http.StatusServiceUnavailable,
    49  			want:     []string{"unavaliable"},
    50  		},
    51  		{
    52  			name: "GatewayTimeout and ServiceUnavailable",
    53  			errors: []merry.Error{
    54  				merry.New("timeout").WithHTTPCode(http.StatusGatewayTimeout),
    55  				merry.New("unavaliable").WithHTTPCode(http.StatusServiceUnavailable),
    56  			},
    57  			wantCode: http.StatusServiceUnavailable,
    58  			want:     []string{"timeout", "unavaliable"},
    59  		},
    60  		{
    61  			name: "ServiceUnavailable and GatewayTimeout",
    62  			errors: []merry.Error{
    63  				merry.New("unavaliable").WithHTTPCode(http.StatusServiceUnavailable),
    64  				merry.New("timeout").WithHTTPCode(http.StatusGatewayTimeout),
    65  			},
    66  			wantCode: http.StatusServiceUnavailable,
    67  			want:     []string{"unavaliable", "timeout"},
    68  		},
    69  		{
    70  			name: "Forbidden and GatewayTimeout",
    71  			errors: []merry.Error{
    72  				merry.New("limit").WithHTTPCode(http.StatusForbidden),
    73  				merry.New("timeout").WithHTTPCode(http.StatusGatewayTimeout),
    74  			},
    75  			wantCode: http.StatusForbidden,
    76  			want:     []string{"limit", "timeout"},
    77  		},
    78  		{
    79  			name: "GatewayTimeout and Forbidden",
    80  			errors: []merry.Error{
    81  				merry.New("timeout").WithHTTPCode(http.StatusGatewayTimeout),
    82  				merry.New("limit").WithHTTPCode(http.StatusForbidden),
    83  			},
    84  			wantCode: http.StatusForbidden,
    85  			want:     []string{"timeout", "limit"},
    86  		},
    87  		{
    88  			name: "InternalServerError and Forbidden",
    89  			errors: []merry.Error{
    90  				merry.New("error").WithHTTPCode(http.StatusInternalServerError),
    91  				merry.New("limit").WithHTTPCode(http.StatusForbidden),
    92  			},
    93  			wantCode: http.StatusForbidden,
    94  			want:     []string{"error", "limit"},
    95  		},
    96  		{
    97  			name: "InternalServerError and GatewayTimeout",
    98  			errors: []merry.Error{
    99  				merry.New("error").WithHTTPCode(http.StatusInternalServerError),
   100  				merry.New("timeout").WithHTTPCode(http.StatusGatewayTimeout),
   101  			},
   102  			wantCode: http.StatusInternalServerError,
   103  			want:     []string{"error", "timeout"},
   104  		},
   105  		{
   106  			name: "GatewayTimeout and InternalServerError",
   107  			errors: []merry.Error{
   108  				merry.New("timeout").WithHTTPCode(http.StatusGatewayTimeout),
   109  				merry.New("error").WithHTTPCode(http.StatusInternalServerError),
   110  			},
   111  			wantCode: http.StatusInternalServerError,
   112  			want:     []string{"timeout", "error"},
   113  		},
   114  		{
   115  			name: "BadRequest and Forbidden",
   116  			errors: []merry.Error{
   117  				merry.New("error").WithHTTPCode(http.StatusBadRequest),
   118  				merry.New("limit").WithHTTPCode(http.StatusForbidden),
   119  			},
   120  			wantCode: http.StatusBadRequest,
   121  			want:     []string{"error", "limit"},
   122  		},
   123  		{
   124  			name: "Forbidden and BadRequest",
   125  			errors: []merry.Error{
   126  				merry.New("limit").WithHTTPCode(http.StatusForbidden),
   127  				merry.New("error").WithHTTPCode(http.StatusBadRequest),
   128  			},
   129  			wantCode: http.StatusBadRequest,
   130  			want:     []string{"limit", "error"},
   131  		},
   132  	}
   133  	for _, tt := range tests {
   134  		t.Run(tt.name, func(t *testing.T) {
   135  			gotCode, got := MergeHttpErrors(tt.errors)
   136  			if gotCode != tt.wantCode {
   137  				t.Errorf("MergeHttpErrors() gotCode = %v, want %v", gotCode, tt.wantCode)
   138  			}
   139  			if !reflect.DeepEqual(got, tt.want) {
   140  				t.Errorf("MergeHttpErrors() got = %v, want %v", got, tt.want)
   141  			}
   142  		})
   143  	}
   144  }
   145  
   146  func TestMergeHttpErrorMap(t *testing.T) {
   147  	tests := []struct {
   148  		name     string
   149  		errors   map[string]merry.Error
   150  		wantCode int
   151  		want     map[string]string
   152  	}{
   153  		{
   154  			name:     "NotFound",
   155  			errors:   map[string]merry.Error{},
   156  			wantCode: http.StatusNotFound,
   157  			want:     map[string]string{},
   158  		},
   159  		{
   160  			name: "NetErr",
   161  			errors: map[string]merry.Error{
   162  				"a": types.ErrBackendError.WithValue("server", "test").WithCause(&net.OpError{Op: "connect", Err: fmt.Errorf("refused")}).WithHTTPCode(http.StatusServiceUnavailable),
   163  			},
   164  			wantCode: http.StatusServiceUnavailable,
   165  			want:     map[string]string{"a": "connect: refused"},
   166  		},
   167  		{
   168  			name: "NetErr (incapsulated)",
   169  			errors: map[string]merry.Error{
   170  				"b": types.ErrMaxTriesExceeded.WithCause(types.ErrBackendError.WithValue("server", "test").WithCause(&net.OpError{Op: "connect", Err: fmt.Errorf("refused")})).WithHTTPCode(http.StatusServiceUnavailable),
   171  			},
   172  			wantCode: http.StatusServiceUnavailable,
   173  			want:     map[string]string{"b": "connect: refused"},
   174  		},
   175  		{
   176  			name: "ServiceUnavailable",
   177  			errors: map[string]merry.Error{
   178  				"d": merry.New("unavaliable").WithHTTPCode(http.StatusServiceUnavailable),
   179  			},
   180  			wantCode: http.StatusServiceUnavailable,
   181  			want:     map[string]string{"d": "unavaliable"},
   182  		},
   183  		{
   184  			name: "GatewayTimeout and ServiceUnavailable",
   185  			errors: map[string]merry.Error{
   186  				"a":  merry.New("timeout").WithHTTPCode(http.StatusGatewayTimeout),
   187  				"de": merry.New("unavaliable").WithHTTPCode(http.StatusServiceUnavailable),
   188  			},
   189  			wantCode: http.StatusServiceUnavailable,
   190  			want:     map[string]string{"a": "timeout", "de": "unavaliable"},
   191  		},
   192  		{
   193  			name: "ServiceUnavailable and GatewayTimeout",
   194  			errors: map[string]merry.Error{
   195  				"de": merry.New("unavaliable").WithHTTPCode(http.StatusServiceUnavailable),
   196  				"a":  merry.New("timeout").WithHTTPCode(http.StatusGatewayTimeout),
   197  			},
   198  			wantCode: http.StatusServiceUnavailable,
   199  			want:     map[string]string{"a": "timeout", "de": "unavaliable"},
   200  		},
   201  		{
   202  			name: "Forbidden and GatewayTimeout",
   203  			errors: map[string]merry.Error{
   204  				"de": merry.New("limit").WithHTTPCode(http.StatusForbidden),
   205  				"c":  merry.New("timeout").WithHTTPCode(http.StatusGatewayTimeout),
   206  			},
   207  			wantCode: http.StatusForbidden,
   208  			want:     map[string]string{"c": "timeout", "de": "limit"},
   209  		},
   210  		{
   211  			name: "GatewayTimeout and Forbidden",
   212  			errors: map[string]merry.Error{
   213  				"a": merry.New("limit").WithHTTPCode(http.StatusForbidden),
   214  				"c": merry.New("timeout").WithHTTPCode(http.StatusGatewayTimeout),
   215  			},
   216  			wantCode: http.StatusForbidden,
   217  			want:     map[string]string{"a": "limit", "c": "timeout"},
   218  		},
   219  		{
   220  			name: "InternalServerError and Forbidden",
   221  			errors: map[string]merry.Error{
   222  				"a":  merry.New("error").WithHTTPCode(http.StatusInternalServerError),
   223  				"cd": merry.New("limit").WithHTTPCode(http.StatusForbidden),
   224  			},
   225  			wantCode: http.StatusForbidden,
   226  			want:     map[string]string{"a": "error", "cd": "limit"},
   227  		},
   228  		{
   229  			name: "InternalServerError and GatewayTimeout",
   230  			errors: map[string]merry.Error{
   231  				"a": merry.New("error").WithHTTPCode(http.StatusInternalServerError),
   232  				"b": merry.New("timeout").WithHTTPCode(http.StatusGatewayTimeout),
   233  			},
   234  			wantCode: http.StatusInternalServerError,
   235  			want:     map[string]string{"a": "error", "b": "timeout"},
   236  		},
   237  		{
   238  			name: "GatewayTimeout and InternalServerError",
   239  			errors: map[string]merry.Error{
   240  				"a":  merry.New("timeout").WithHTTPCode(http.StatusGatewayTimeout),
   241  				"cd": merry.New("error").WithHTTPCode(http.StatusInternalServerError),
   242  			},
   243  			wantCode: http.StatusInternalServerError,
   244  			want:     map[string]string{"a": "timeout", "cd": "error"},
   245  		},
   246  		{
   247  			name: "BadRequest and Forbidden",
   248  			errors: map[string]merry.Error{
   249  				"de": merry.New("error").WithHTTPCode(http.StatusBadRequest),
   250  				"a":  merry.New("limit").WithHTTPCode(http.StatusForbidden),
   251  			},
   252  			wantCode: http.StatusBadRequest,
   253  			want:     map[string]string{"a": "limit", "de": "error"},
   254  		},
   255  		{
   256  			name: "Forbidden and BadRequest",
   257  			errors: map[string]merry.Error{
   258  				"a": merry.New("limit").WithHTTPCode(http.StatusForbidden),
   259  				"b{c,de,klmn}.cde.d{c,de,klmn}.e{c,de,klmn}.k{c,de,klmn}.b{c,de,klmn}.cde.d{c,de,klmn}.e{c,de,klmn}.k{c,de,klmn}.e{c,de,klmn}.k{c,de,klmn}": merry.New("error").WithHTTPCode(http.StatusBadRequest),
   260  			},
   261  			wantCode: http.StatusBadRequest,
   262  			want: map[string]string{
   263  				"a": "limit",
   264  				"b{c,de,klmn}.cde.d{c,de,klmn}.e{c,de,klmn}.k{c,de,klmn}.b{c,de,klmn}.cde.d{c,de,klmn}.e{c,de,klmn}.k{c,de,klmn}.e{c,de,klmn}.k{c,de,klmn}": "error",
   265  			},
   266  		},
   267  	}
   268  	for _, tt := range tests {
   269  		t.Run(tt.name, func(t *testing.T) {
   270  			gotCode, got := MergeHttpErrorMap(tt.errors)
   271  			if gotCode != tt.wantCode {
   272  				t.Errorf("MergeHttpErrors() gotCode = %v, want %v", gotCode, tt.wantCode)
   273  			}
   274  			if !reflect.DeepEqual(got, tt.want) {
   275  				t.Errorf("MergeHttpErrors() got = %v, want %v", got, tt.want)
   276  			}
   277  		})
   278  	}
   279  }