...

Source file src/edge-infra.dev/pkg/edge/iam/apperror/json_test.go

Documentation: edge-infra.dev/pkg/edge/iam/apperror

     1  package apperror_test
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/json"
     6  	"errors"
     7  	"fmt"
     8  	"testing"
     9  
    10  	"github.com/gin-gonic/gin"
    11  	"github.com/go-logr/logr"
    12  	"github.com/stretchr/testify/assert"
    13  
    14  	"edge-infra.dev/pkg/edge/iam/apperror"
    15  	"edge-infra.dev/pkg/lib/fog"
    16  )
    17  
    18  func TestJSONError(t *testing.T) {
    19  	dbErr := errors.New("SQL_ERR::NO_ROWS")
    20  	handlerErr := apperror.NewJSONError(dbErr, 401, "user not found", gin.H{"k1": "v1", "k2": 2})
    21  
    22  	assert.Equal(t, map[string]interface{}{"k1": "v1", "k2": 2}, handlerErr.JSONDetails())
    23  	assert.Equal(t, "user not found. SQL_ERR::NO_ROWS", handlerErr.Error())
    24  }
    25  
    26  func TestJSONErrorWithNilErr(t *testing.T) {
    27  	err := apperror.NewJSONError(nil, 401, "subject's profile could not be found", gin.H{"error": "invalid_user"})
    28  
    29  	assert.Equal(t, "subject's profile could not be found", err.Error())
    30  	assert.Equal(t, "[401]: subject's profile could not be found", apperror.ErrorChain(err))
    31  }
    32  
    33  func TestJSONErrorLogEntry(t *testing.T) {
    34  	dbErr := errors.New("SQL_ERR::NO_ROWS")
    35  	handlerErr := apperror.NewJSONError(dbErr, 401, "user not found", gin.H{"k1": "v1", "k2": "v2"})
    36  
    37  	l, buf := testLogger()
    38  	code, responseBody := handlerErr.JSONResponse()
    39  	msg := fmt.Sprintf("(%d) aborting with json", code)
    40  	l.Error(handlerErr, msg, "details", handlerErr.JSONDetails(), "body", responseBody)
    41  
    42  	out := getLogEntry(buf)
    43  
    44  	assert.Equal(t, "(401) aborting with json", out["message"])
    45  	assert.Equal(t, "user not found. SQL_ERR::NO_ROWS", out["error"])
    46  	assert.Equal(t, map[string]interface{}{"k1": "v1", "k2": "v2"}, out["details"])
    47  	assert.Equal(t, map[string]interface{}{"k1": "v1", "k2": "v2", "message": "user not found"}, out["body"])
    48  }
    49  
    50  func TestErrorChainWithJSONError(t *testing.T) {
    51  	// db returns an app error
    52  	err := errors.New("SQL_ERR::NO_ROWS")
    53  	dbErr := apperror.New(err, "not_found", "user not found in db")
    54  	// service wraps the error
    55  	svcErr := fmt.Errorf("(user service) -> %w", dbErr)
    56  	// handler wraps it into a status error
    57  	handlerErr := apperror.NewJSONError(svcErr, 401, "user not found", gin.H{"error": "invalid_user"})
    58  
    59  	code, responseBody := handlerErr.JSONResponse()
    60  	assert.Equal(t, 401, code)
    61  	assert.Equal(t, map[string]interface{}{"error": "invalid_user", "message": "user not found"}, responseBody)
    62  
    63  	errChain := apperror.ErrorChain(handlerErr)
    64  	assert.Equal(t, "[401]: user not found. (user service) -> user not found in db <not_found>. SQL_ERR::NO_ROWS", errChain)
    65  	assert.Equal(t, "user not found. (user service) -> user not found in db <not_found>. SQL_ERR::NO_ROWS", handlerErr.Error())
    66  	assert.Equal(t, map[string]interface{}{"error": "invalid_user"}, handlerErr.JSONDetails())
    67  }
    68  
    69  func TestWithCaller(t *testing.T) {
    70  	dbErr := errors.New("SQL_ERR::NO_ROWS")
    71  
    72  	handlerErr := apperror.NewJSONError(dbErr, 401, "user not found", nil)
    73  
    74  	l, buf := testLogger()
    75  
    76  	loc := handlerErr.SourceLocation()
    77  	l.Error(handlerErr, "testing caller information", "file", loc.File, "line", loc.Line)
    78  
    79  	out := getLogEntry(buf)
    80  	assert.Equal(t, "testing caller information", out["message"])
    81  }
    82  
    83  func TestSourceLocationToMap(t *testing.T) {
    84  	loc := apperror.SourceLocation{
    85  		File: "f1",
    86  		Line: 53,
    87  	}
    88  
    89  	m := loc.ToMap()
    90  
    91  	assert.Equal(t, m["file"], "f1")
    92  	assert.Equal(t, m["line"], float64(53))
    93  	assert.Nil(t, m["func"])
    94  }
    95  
    96  func testLogger() (logr.Logger, *bytes.Buffer) {
    97  	buf := new(bytes.Buffer)
    98  	l := fog.New(fog.To(buf))
    99  	return l, buf
   100  }
   101  
   102  func getLogEntry(buf *bytes.Buffer) map[string]interface{} {
   103  	var out map[string]interface{}
   104  	err := json.Unmarshal(buf.Bytes(), &out)
   105  	if err != nil {
   106  		return nil
   107  	}
   108  	return out
   109  }
   110  

View as plain text