github.com/yankunsam/loki/v2@v2.6.3-0.20220817130409-389df5235c27/pkg/util/server/error_test.go (about)

     1  package server
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"fmt"
     7  	"io/ioutil"
     8  	"net/http"
     9  	"net/http/httptest"
    10  	"testing"
    11  
    12  	"google.golang.org/grpc/codes"
    13  	"google.golang.org/grpc/status"
    14  
    15  	"github.com/prometheus/prometheus/promql"
    16  	"github.com/stretchr/testify/require"
    17  	"github.com/weaveworks/common/httpgrpc"
    18  	"github.com/weaveworks/common/user"
    19  
    20  	"github.com/grafana/loki/pkg/logqlmodel"
    21  	storage_errors "github.com/grafana/loki/pkg/storage/errors"
    22  	"github.com/grafana/loki/pkg/util"
    23  )
    24  
    25  func Test_writeError(t *testing.T) {
    26  	for _, tt := range []struct {
    27  		name string
    28  
    29  		err            error
    30  		msg            string
    31  		expectedStatus int
    32  	}{
    33  		{"cancelled", context.Canceled, ErrClientCanceled, StatusClientClosedRequest},
    34  		{"cancelled multi", util.MultiError{context.Canceled, context.Canceled}, ErrClientCanceled, StatusClientClosedRequest},
    35  		{"rpc cancelled", status.New(codes.Canceled, context.Canceled.Error()).Err(), "rpc error: code = Canceled desc = context canceled", http.StatusInternalServerError},
    36  		{"rpc cancelled multi", util.MultiError{status.New(codes.Canceled, context.Canceled.Error()).Err(), status.New(codes.Canceled, context.Canceled.Error()).Err()}, "2 errors: rpc error: code = Canceled desc = context canceled; rpc error: code = Canceled desc = context canceled", http.StatusInternalServerError},
    37  		{"mixed context and rpc cancelled", util.MultiError{context.Canceled, status.New(codes.Canceled, context.Canceled.Error()).Err()}, "2 errors: context canceled; rpc error: code = Canceled desc = context canceled", http.StatusInternalServerError},
    38  		{"mixed context, rpc cancelled and another", util.MultiError{errors.New("standard error"), context.Canceled, status.New(codes.Canceled, context.Canceled.Error()).Err()}, "3 errors: standard error; context canceled; rpc error: code = Canceled desc = context canceled", http.StatusInternalServerError},
    39  		{"cancelled storage", promql.ErrStorage{Err: context.Canceled}, ErrClientCanceled, StatusClientClosedRequest},
    40  		{"orgid", user.ErrNoOrgID, user.ErrNoOrgID.Error(), http.StatusBadRequest},
    41  		{"deadline", context.DeadlineExceeded, ErrDeadlineExceeded, http.StatusGatewayTimeout},
    42  		{"deadline multi", util.MultiError{context.DeadlineExceeded, context.DeadlineExceeded}, ErrDeadlineExceeded, http.StatusGatewayTimeout},
    43  		{"rpc deadline", status.New(codes.DeadlineExceeded, context.DeadlineExceeded.Error()).Err(), ErrDeadlineExceeded, http.StatusGatewayTimeout},
    44  		{"rpc deadline multi", util.MultiError{status.New(codes.DeadlineExceeded, context.DeadlineExceeded.Error()).Err(), status.New(codes.DeadlineExceeded, context.DeadlineExceeded.Error()).Err()}, ErrDeadlineExceeded, http.StatusGatewayTimeout},
    45  		{"mixed context and rpc deadline", util.MultiError{context.DeadlineExceeded, status.New(codes.DeadlineExceeded, context.DeadlineExceeded.Error()).Err()}, ErrDeadlineExceeded, http.StatusGatewayTimeout},
    46  		{"mixed context, rpc deadline and another", util.MultiError{errors.New("standard error"), context.DeadlineExceeded, status.New(codes.DeadlineExceeded, context.DeadlineExceeded.Error()).Err()}, "3 errors: standard error; context deadline exceeded; rpc error: code = DeadlineExceeded desc = context deadline exceeded", http.StatusInternalServerError},
    47  		{"parse error", logqlmodel.ParseError{}, "parse error : ", http.StatusBadRequest},
    48  		{"httpgrpc", httpgrpc.Errorf(http.StatusBadRequest, errors.New("foo").Error()), "foo", http.StatusBadRequest},
    49  		{"internal", errors.New("foo"), "foo", http.StatusInternalServerError},
    50  		{"query error", storage_errors.ErrQueryMustContainMetricName, storage_errors.ErrQueryMustContainMetricName.Error(), http.StatusBadRequest},
    51  		{"wrapped query error", fmt.Errorf("wrapped: %w", storage_errors.ErrQueryMustContainMetricName), "wrapped: " + storage_errors.ErrQueryMustContainMetricName.Error(), http.StatusBadRequest},
    52  		{"multi mixed", util.MultiError{context.Canceled, context.DeadlineExceeded}, "2 errors: context canceled; context deadline exceeded", http.StatusInternalServerError},
    53  	} {
    54  		t.Run(tt.name, func(t *testing.T) {
    55  			rec := httptest.NewRecorder()
    56  			WriteError(tt.err, rec)
    57  			require.Equal(t, tt.expectedStatus, rec.Result().StatusCode)
    58  			b, err := ioutil.ReadAll(rec.Result().Body)
    59  			if err != nil {
    60  				t.Fatal(err)
    61  			}
    62  			require.Equal(t, tt.msg, string(b[:len(b)-1]))
    63  		})
    64  	}
    65  }