Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .github/workflows/golangci-lint.yaml
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
name: golangci-lint

# Controls when the action will run. Triggers the workflow on push or pull requests
on:
push:
branches:
- main
- master
pull_request:

permissions:
contents: read

jobs:
golangci:
name: lint
Expand All @@ -19,6 +19,6 @@ jobs:
with:
go-version: stable
- name: golangci-lint
uses: golangci/golangci-lint-action@v6
uses: golangci/golangci-lint-action@v8
with:
version: v1.63
version: v2.1
101 changes: 42 additions & 59 deletions .golangci.yaml
Original file line number Diff line number Diff line change
@@ -1,69 +1,52 @@
# options for analysis running
run:
# timeout for analysis, e.g. 30s, 5m, default is 1m
timeout: 2m

issues:
# Only report issues for changes since master
new-from-rev: origin/master

# output configuration options
version: "2"
output:
# colored-line-number|line-number|json|tab|checkstyle|code-climate, default is "colored-line-number"
formats:
- format: colored-line-number

linters-settings:
errcheck:
# report about not checking of errors in type assertions: `a := b.(MyStruct)`;
# default is false: such cases aren't reported by default.
check-type-assertions: true

# Function length check
funlen:
lines: 60
statements: 40

# Report deeply nested if statements
nestif:
# minimal complexity of if statements to report, 5 by default
min-complexity: 4

gofmt:
# simplify code: gofmt with `-s` option, true by default
simplify: true

govet:
# report about shadowed variables
enable-all: true
disable:
# Do not check field memory alignment because in most cases the performance gain is not worth the headache
- fieldalignment

text:
path: stdout
linters:
# Disable the default linters so we can explicitly name the linters we want
disable-all: true

# List of enabled linters
default: none
enable:
#####################
# Default linters
#####################
- gofmt
# Checks error handling
- errcheck
# Linter for Go source code that specializes in simplifying a code
- gosimple
# Vet examines Go source code and reports suspicious constructs, such as Printf calls whose
# arguments do not align with the format string
- govet
# Detects when assignments to existing variables are not used
- ineffassign
# Static code analytics
- staticcheck
# Reports unused function parameters.
- unconvert
- unparam
# Check if variables or functions are unused
- unused
# Remove unnecessary type conversions.
- unconvert
settings:
errcheck:
check-type-assertions: true
funlen:
lines: 60
statements: 40
govet:
disable:
- fieldalignment
enable-all: true
nestif:
min-complexity: 4
exclusions:
generated: lax
presets:
- comments
- common-false-positives
- legacy
- std-error-handling
paths:
- third_party$
- builtin$
- examples$
issues:
new-from-rev: origin/master
formatters:
enable:
- gofmt
settings:
gofmt:
simplify: true
exclusions:
generated: lax
paths:
- third_party$
- builtin$
- examples$
3 changes: 1 addition & 2 deletions ecosystem/grpc/client_interceptor.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,8 @@ func ReturnSimpleErrors(registry *Registry) grpc.UnaryClientInterceptor {
}

grpcCode := codes.Unknown
msg := err.Error()

serr := simplerr.New(msg).Attr(AttrGRPCMethod, method) // nolint: govet
serr := simplerr.Wrap(err).Attr(AttrGRPCMethod, method) // nolint: govet

// Check if the error is a gRPC status error
// The GRPC framework seems to always return grpc errors on the client side, even if the server does not
Expand Down
65 changes: 10 additions & 55 deletions ecosystem/grpc/client_interceptor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,69 +4,35 @@ import (
"context"
"fmt"
"github.com/lobocv/simplerr"
"github.com/lobocv/simplerr/ecosystem/grpc/internal/ping"
"github.com/stretchr/testify/require"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/credentials/insecure"
"google.golang.org/grpc/status"
"net"
"testing"
)

type PingService struct {
err error
}

func (s *PingService) Ping(_ context.Context, _ *ping.PingRequest) (*ping.PingResponse, error) {
// Your implementation of the Ping method goes here
fmt.Println("Received Ping request")
if s.err != nil {
return nil, s.err
var mockInvoker = func(grpcError error) grpc.UnaryInvoker {
return func(ctx context.Context, method string, req, reply any, cc *grpc.ClientConn, opts ...grpc.CallOption) error {
return grpcError
}
return &ping.PingResponse{}, nil
}

func setupServerAndClient(port int) (*PingService, ping.PingServiceClient) {

server := grpc.NewServer()
service := &PingService{err: status.Error(codes.NotFound, "test error")}
ping.RegisterPingServiceServer(server, service)

// Create a listener on TCP port 50051
listener, err := net.Listen("tcp", fmt.Sprintf(":%d", port))
if err != nil {
panic(fmt.Sprintf("Error creating listener: %v", err))
}

go func() {
if err = server.Serve(listener); err != nil {
panic(fmt.Sprintf("Error serving: %v", err))
}
}()
func makeMockGrpcCall(returnedError error) func() error {

defaultInverseMapping := DefaultInverseMapping()
defaultInverseMapping[codes.DataLoss] = simplerr.CodeResourceExhausted
GetDefaultRegistry().SetInverseMapping(defaultInverseMapping)

interceptor := ReturnSimpleErrors(nil)

conn, err := grpc.NewClient(fmt.Sprintf(":%d", port),
grpc.WithUnaryInterceptor(interceptor),
grpc.WithTransportCredentials(insecure.NewCredentials()),
)
if err != nil {
panic(err)
return func() error {
return interceptor(context.Background(), "/ping.PingService/Ping", nil, nil, nil, mockInvoker(returnedError))
}
client := ping.NewPingServiceClient(conn)

return service, client
}

func TestClientInterceptor(t *testing.T) {

server, client := setupServerAndClient(50051)
_, err := client.Ping(context.Background(), &ping.PingRequest{})
err := makeMockGrpcCall(status.Error(codes.NotFound, "not found"))()

require.True(t, simplerr.HasErrorCode(err, simplerr.CodeNotFound), "simplerror code can be detected")
require.Equal(t, codes.NotFound, status.Code(err), "grpc code can be detected with grpc status package")
Expand All @@ -80,8 +46,7 @@ func TestClientInterceptor(t *testing.T) {
require.Equal(t, "/ping.PingService/Ping", method, "can get the grpc method which errored")

// Test the custom added mapping
server.err = status.Error(codes.DataLoss, "test error")
_, err = client.Ping(context.Background(), &ping.PingRequest{})
err = makeMockGrpcCall(status.Error(codes.DataLoss, "data loss"))()
require.True(t, simplerr.HasErrorCode(err, simplerr.CodeResourceExhausted), "simplerror code can be detected")

}
Expand All @@ -90,28 +55,18 @@ func TestClientInterceptor(t *testing.T) {
// Our interceptor should still be able to detect attributes on the error
func TestClientInterceptorNotGPRCError(t *testing.T) {

server, client := setupServerAndClient(50052)
server.err = fmt.Errorf("not a grpc error")

_, err := client.Ping(context.Background(), &ping.PingRequest{})
err := makeMockGrpcCall(fmt.Errorf("some error"))()

require.True(t, simplerr.HasErrorCode(err, simplerr.CodeUnknown), "simplerror code can be detected")
require.Equal(t, codes.Unknown, status.Code(err), "grpc code can be detected with grpc status package")

st, ok := simplerr.GetAttribute(err, AttrGRPCStatus)
require.True(t, ok)
require.Equal(t, codes.Unknown, st.(*status.Status).Code(), "can get the grpc Status") // nolint: errcheck

method, ok := simplerr.GetAttribute(err, AttrGRPCMethod)
require.True(t, ok)
require.Equal(t, "/ping.PingService/Ping", method, "can get the grpc method which errored")

}

func TestClientInterceptorNoError(t *testing.T) {
server, client := setupServerAndClient(50053)
server.err = nil

_, err := client.Ping(context.Background(), &ping.PingRequest{})
err := makeMockGrpcCall(nil)()
require.Nil(t, err)
}
Loading