From c47b0a346e2627f600baabe4d145a8ba0c47aaf4 Mon Sep 17 00:00:00 2001 From: Semyon Krestyaninov <krestyaninov@perx.ru> Date: Wed, 4 Jun 2025 11:48:11 +0000 Subject: [PATCH] =?UTF-8?q?fix(core):=20=D0=94=D0=BE=D0=B1=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=20=D0=B2=D0=BE=D0=B7=D0=B2=D1=80=D0=B0=D1=82?= =?UTF-8?q?=20=D0=B8=D1=81=D1=85=D0=BE=D0=B4=D0=BD=D1=8B=D1=85=20=D0=B4?= =?UTF-8?q?=D0=B0=D0=BD=D0=BD=D1=8B=D1=85=20=D0=BF=D1=80=D0=B8=20=D0=BE?= =?UTF-8?q?=D1=88=D0=B8=D0=B1=D0=BA=D0=B5=20=D0=BA=D0=BE=D0=B4=D0=B8=D1=80?= =?UTF-8?q?=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D1=8F/=D0=B4=D0=B5=D0=BA=D0=BE?= =?UTF-8?q?=D0=B4=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D1=8F=20=D0=B2?= =?UTF-8?q?=20=D0=BC=D0=B5=D1=82=D0=BE=D0=B4=D0=B5=20`Introspect`=20=D0=B2?= =?UTF-8?q?=20`ClientEncodeMiddleware`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Issue: #3273 --- .../middleware/client_encode_middleware.go | 17 ++- .../client_encode_middleware_test.go | 144 ++++++++++++++++++ 2 files changed, 154 insertions(+), 7 deletions(-) create mode 100644 pkg/items/middleware/client_encode_middleware_test.go diff --git a/pkg/items/middleware/client_encode_middleware.go b/pkg/items/middleware/client_encode_middleware.go index 324c648e..476687b8 100644 --- a/pkg/items/middleware/client_encode_middleware.go +++ b/pkg/items/middleware/client_encode_middleware.go @@ -31,18 +31,21 @@ func (m *encodeDecodeMiddleware) Introspect(ctx context.Context, item *items.Ite return nil, nil, err } - if item, err = item.Encode(ctx, coll.Schema); err != nil { - return + encoded, err := item.Encode(ctx, coll.Schema) + if err != nil { + // Возвращаем исходные данные для возможности обработки полей с ошибками. + return item, coll.Schema, err } - itm, sch, err = m.next.Introspect(ctx, item, opts...) - if itm != nil && sch != nil { + introspected, sch, err := m.next.Introspect(ctx, encoded, opts...) + if introspected != nil && sch != nil { var err error - if itm, err = itm.Decode(ctx, sch); err != nil { - return nil, nil, err + if introspected, err = introspected.Decode(ctx, sch); err != nil { + // Возвращаем исходные данные для возможности обработки полей с ошибками. + return item, coll.Schema, err } } - return itm, sch, err + return introspected, sch, err } diff --git a/pkg/items/middleware/client_encode_middleware_test.go b/pkg/items/middleware/client_encode_middleware_test.go new file mode 100644 index 00000000..4adbdb65 --- /dev/null +++ b/pkg/items/middleware/client_encode_middleware_test.go @@ -0,0 +1,144 @@ +package middleware + +import ( + "context" + "testing" + "time" + + "git.perx.ru/perxis/perxis-go/pkg/collections" + collectionsmocks "git.perx.ru/perxis/perxis-go/pkg/collections/mocks" + "git.perx.ru/perxis/perxis-go/pkg/items" + itemsmocks "git.perx.ru/perxis/perxis-go/pkg/items/mocks" + "git.perx.ru/perxis/perxis-go/pkg/schema" + "git.perx.ru/perxis/perxis-go/pkg/schema/field" + "git.perx.ru/perxis/perxis-go/pkg/schema/modify" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" +) + +func TestEncodeDecodeMiddleware_Introspect(t *testing.T) { + t.Run("Successful", func(t *testing.T) { + sch := schema.New( + "date", field.Time(), + ) + + itemsMock := itemsmocks.NewItems(t) + itemsMock.On("Introspect", mock.Anything, mock.Anything).Return(&items.Item{ + ID: "", + SpaceID: "space", + EnvID: "env", + CollectionID: "coll", + Data: map[string]any{ + "date": time.Date(2025, 12, 1, 0, 0, 0, 0, time.UTC), + }, + }, sch, nil).Once() + + collectionsMock := collectionsmocks.NewCollections(t) + collectionsMock.On("Get", mock.Anything, "space", "env", "coll").Return(&collections.Collection{ + ID: "coll", + SpaceID: "space", + EnvID: "env", + Schema: sch, + }, nil).Once() + + middleware := ClientEncodeMiddleware(collectionsMock)(itemsMock) + item, sch, err := middleware.Introspect(context.Background(), &items.Item{ + ID: "id", + SpaceID: "space", + EnvID: "env", + CollectionID: "coll", + }) + require.NoError(t, err) + assert.Equal(t, map[string]any{"date": time.Date(2025, 12, 1, 0, 0, 0, 0, time.UTC)}, item.Data) + assert.NotNil(t, sch) + }) + t.Run("Error during encoding", func(t *testing.T) { + sch := schema.New( + "date", field.Time(), + ) + + itemsMock := itemsmocks.NewItems(t) + collectionsMock := collectionsmocks.NewCollections(t) + collectionsMock.On("Get", mock.Anything, "space", "env", "coll").Return(&collections.Collection{ + ID: "coll", + SpaceID: "space", + EnvID: "env", + Schema: sch, + }, nil).Once() + + middleware := ClientEncodeMiddleware(collectionsMock)(itemsMock) + item, sch, err := middleware.Introspect(context.Background(), &items.Item{ + ID: "", + SpaceID: "space", + EnvID: "env", + CollectionID: "coll", + Data: map[string]any{ + "date": "invalid date", + }, + }) + require.EqualError( + t, + err, + "encode error: 1 error occurred:\n\t* field 'date': TimeType: encode: unsupported value type : \"string\"\n\n", + ) + assert.Equal(t, + map[string]any{ + "date": "invalid date", + }, + item.Data, + "При возникновении ошибки декодирования в ответе должны быть возвращены исходные данные", + ) + assert.NotNil(t, sch) + }) + t.Run("Error during decoding", func(t *testing.T) { + sch := schema.New( + "num", field.Number(field.NumberFormatInt), + "str", field.String().AddOptions(modify.Value("num")), + ) + + itemsMock := itemsmocks.NewItems(t) + itemsMock.On("Introspect", mock.Anything, mock.Anything).Return(&items.Item{ + ID: "id", + SpaceID: "space", + EnvID: "env", + CollectionID: "coll", + Data: map[string]any{ + "num": 100, + "str": 100, + }, + }, sch, nil).Once() + + collectionsMock := collectionsmocks.NewCollections(t) + collectionsMock.On("Get", mock.Anything, "space", "env", "coll").Return(&collections.Collection{ + ID: "coll", + SpaceID: "space", + EnvID: "env", + Schema: sch, + }, nil).Once() + + middleware := ClientEncodeMiddleware(collectionsMock)(itemsMock) + item, sch, err := middleware.Introspect(context.Background(), &items.Item{ + ID: "id", + SpaceID: "space", + EnvID: "env", + CollectionID: "coll", + Data: map[string]any{ + "num": 100, + }, + }) + require.EqualError( + t, + err, + "decode error: 1 error occurred:\n\t* field 'str': StringField decode error: unsupported value type : \"int\"\n\n", + ) + assert.Equal(t, + map[string]any{ + "num": 100, + }, + item.Data, + "При возникновении ошибки кодирования в ответе должны быть возвращены исходные данные", + ) + assert.NotNil(t, sch) + }) +} -- GitLab