adapters/lambda/handler_test.go

package lambda_test

import (
	"context"
	"encoding/json"
	"errors"
	"testing"

	awslambda "github.com/aws/aws-lambda-go/lambda"
	"github.com/aws/aws-lambda-go/lambdacontext"

	adapter "mercemay.top/src/lambdalog/adapters/lambda"
)

type capture struct {
	msgs []string
	last []adapter.Field
}

func (c *capture) Info(msg string, f ...adapter.Field) {
	c.msgs = append(c.msgs, "info:"+msg)
	c.last = f
}
func (c *capture) Error(msg string, f ...adapter.Field) {
	c.msgs = append(c.msgs, "error:"+msg)
	c.last = f
}
func (c *capture) With(...adapter.Field) adapter.Logger { return c }

func TestHandler_LogsStartAndEnd(t *testing.T) {
	c := &capture{}
	inner := awslambda.HandlerFunc(func(ctx context.Context, p []byte) ([]byte, error) {
		return []byte(`{"ok":true}`), nil
	})
	h := adapter.Handler(c, inner)

	ctx := lambdacontext.NewContext(context.Background(), &lambdacontext.LambdaContext{AwsRequestID: "req-1"})
	if _, err := h.Invoke(ctx, []byte(`{}`)); err != nil {
		t.Fatalf("invoke: %v", err)
	}
	if len(c.msgs) != 2 || c.msgs[0] != "info:invoke.start" || c.msgs[1] != "info:invoke.end" {
		t.Fatalf("got messages %v", c.msgs)
	}
}

func TestHandler_LogsError(t *testing.T) {
	c := &capture{}
	boom := errors.New("boom")
	inner := awslambda.HandlerFunc(func(ctx context.Context, p []byte) ([]byte, error) {
		return nil, boom
	})
	h := adapter.Handler(c, inner)

	if _, err := h.Invoke(context.Background(), nil); !errors.Is(err, boom) {
		t.Fatalf("err = %v, want boom", err)
	}
	if len(c.msgs) == 0 || c.msgs[len(c.msgs)-1] != "error:invoke.end" {
		t.Fatalf("expected error message last: %v", c.msgs)
	}
}

func TestHandlerFunc_JSONPath(t *testing.T) {
	type in struct{ A int }
	type out struct{ B int }
	h := adapter.HandlerFunc(adapter.NoopLogger(), func(ctx context.Context, v in) (out, error) {
		return out{B: v.A * 2}, nil
	})
	raw, err := h.Invoke(context.Background(), []byte(`{"A":3}`))
	if err != nil {
		t.Fatalf("invoke: %v", err)
	}
	var parsed out
	if err := json.Unmarshal(raw, &parsed); err != nil {
		t.Fatalf("parse: %v", err)
	}
	if parsed.B != 6 {
		t.Fatalf("got %+v, want B=6", parsed)
	}
}

func TestHandlerFunc_InvalidPayload(t *testing.T) {
	h := adapter.HandlerFunc(adapter.NoopLogger(), func(ctx context.Context, v struct{ A int }) (int, error) {
		return v.A, nil
	})
	if _, err := h.Invoke(context.Background(), []byte("not json")); err == nil {
		t.Fatal("expected error")
	}
}

func TestNoopLogger_Panics_OnNilIsOK(t *testing.T) {
	t.Helper()
	adapter.NoopLogger().Info("x")
	adapter.NoopLogger().Error("x")
	adapter.NoopLogger().With().Info("x")
}