From 8dbe03c5bfd8b5d09fac036bb977deb4fc80f7f5 Mon Sep 17 00:00:00 2001
From: Danis Kirasirov <dbgbbu@gmail.com>
Date: Fri, 2 Feb 2024 10:16:07 +0300
Subject: [PATCH] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?=
 =?UTF-8?q?=D0=BD=D1=8B=20=D1=82=D0=B5=D1=81=D1=82=D1=8B=20=D0=B4=D0=BB?=
 =?UTF-8?q?=D1=8F=20=D1=81=D1=82=D1=80=D1=83=D0=BA=D1=82=D1=83=D1=80=20?=
 =?UTF-8?q?=D0=B2=20expr?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 pkg/expr/expr_test.go  | 64 ++++++++++++++++++++++++++++++++++++++++++
 pkg/expr/mongo_test.go | 32 +++++++++++++++++++++
 pkg/files/file.go      | 12 ++++----
 3 files changed, 102 insertions(+), 6 deletions(-)

diff --git a/pkg/expr/expr_test.go b/pkg/expr/expr_test.go
index 5eafc368..8fb68311 100644
--- a/pkg/expr/expr_test.go
+++ b/pkg/expr/expr_test.go
@@ -1,11 +1,13 @@
 package expr
 
 import (
+	"context"
 	"fmt"
 	"testing"
 	"time"
 
 	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
 )
 
 func TestIsExpression(t *testing.T) {
@@ -49,3 +51,65 @@ func TestIsExpression(t *testing.T) {
 		})
 	}
 }
+
+type testEnvStruct struct {
+	ID   string      `expr:"id"`
+	Size int         `expr:"size"`
+	Data interface{} `expr:"data"`
+}
+
+func TestEval_StructInEnv(t *testing.T) {
+	ctx := context.Background()
+
+	tests := []struct {
+		name       string
+		exp        string
+		env        map[string]interface{}
+		wantErr    bool
+		wantResult interface{}
+	}{
+		{
+			name:       "get field by expr tag",
+			exp:        "s.id",
+			env:        map[string]interface{}{"s": &testEnvStruct{ID: "id1"}},
+			wantResult: "id1",
+		},
+		{
+			name:       "get field by field name",
+			exp:        "s.ID",
+			env:        map[string]interface{}{"s": &testEnvStruct{ID: "id1"}},
+			wantResult: "id1",
+		},
+		{
+			name:       "get nested field",
+			exp:        "m.s.size",
+			env:        map[string]interface{}{"m": map[string]interface{}{"s": &testEnvStruct{Size: 1}}},
+			wantResult: 1,
+		},
+		{
+			name:       "check field",
+			exp:        "s.data.size < 100",
+			env:        map[string]interface{}{"s": &testEnvStruct{Data: &testEnvStruct{Size: 0}}},
+			wantResult: true,
+		},
+		{
+			name:    "field not exists",
+			exp:     "s.not_exists",
+			env:     map[string]interface{}{"s": &testEnvStruct{}},
+			wantErr: true,
+		},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			result, err := Eval(ctx, tt.exp, tt.env)
+			if tt.wantErr {
+				require.Error(t, err)
+				return
+			}
+
+			require.NoError(t, err)
+			require.Equal(t, tt.wantResult, result)
+		})
+	}
+}
diff --git a/pkg/expr/mongo_test.go b/pkg/expr/mongo_test.go
index c44296f7..7f020faa 100644
--- a/pkg/expr/mongo_test.go
+++ b/pkg/expr/mongo_test.go
@@ -69,6 +69,38 @@ func TestConvertToMongo(t *testing.T) {
 	}
 }
 
+func TestConvertToMongo_StructInEnv(t *testing.T) {
+	ctx := context.Background()
+
+	tests := []struct {
+		name       string
+		exp        string
+		env        map[string]interface{}
+		wantErr    bool
+		wantResult interface{}
+	}{
+		{
+			name:       "get field",
+			exp:        "db_item.id == env_item.id",
+			env:        map[string]interface{}{"env_item": &testEnvStruct{ID: "id1"}},
+			wantResult: bson.M{"db_item.id": "id1"},
+		},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			result, err := ConvertToMongo(ctx, tt.exp, tt.env, nil)
+			if tt.wantErr {
+				require.Error(t, err)
+				return
+			}
+
+			require.NoError(t, err)
+			require.Equal(t, tt.wantResult, result)
+		})
+	}
+}
+
 func BenchmarkConvertToMongo(b *testing.B) {
 	const idsNum = 1_000_000
 	ctx := context.Background()
diff --git a/pkg/files/file.go b/pkg/files/file.go
index 5700309d..d2236b83 100644
--- a/pkg/files/file.go
+++ b/pkg/files/file.go
@@ -16,13 +16,13 @@ const (
 
 // File - описание файла в системе хранения perxis
 type File struct {
-	ID       string  `mapstructure:"id,omitempty" json:"id" expr:"id"`                               // Уникальный идентификатор файла в хранилище
-	Name     string  `mapstructure:"name,omitempty" json:"name" bson:"name,omitempty" expr:"name"`             // Имя файла
-	Size     int     `mapstructure:"size,omitempty" json:"size" bson:"size,omitempty" expr:"size"`             // Размер файла
+	ID       string  `mapstructure:"id,omitempty" json:"id" expr:"id"`                                              // Уникальный идентификатор файла в хранилище
+	Name     string  `mapstructure:"name,omitempty" json:"name" bson:"name,omitempty" expr:"name"`                  // Имя файла
+	Size     int     `mapstructure:"size,omitempty" json:"size" bson:"size,omitempty" expr:"size"`                  // Размер файла
 	MimeType string  `mapstructure:"mimeType,omitempty" json:"mimeType" bson:"mimeType,omitempty" expr:"mime_type"` // Mime-type файла
-	URL      string  `mapstructure:"url,omitempty" json:"url" bson:"url,omitempty" expr:"url"`                // Адрес для загрузки файла
-	Key      string  `mapstructure:"key,omitempty" json:"key" bson:"key,omitempty" expr:"key"`                // Ключ для хранения файла в хранилище
-	File     fs.File `mapstructure:"-" json:"-" bson:"-"`                                          // Файл для загрузки(из файловой системы)
+	URL      string  `mapstructure:"url,omitempty" json:"url" bson:"url,omitempty" expr:"url"`                      // Адрес для загрузки файла
+	Key      string  `mapstructure:"key,omitempty" json:"key" bson:"key,omitempty" expr:"key"`                      // Ключ для хранения файла в хранилище
+	File     fs.File `mapstructure:"-" json:"-" bson:"-"`                                                           // Файл для загрузки(из файловой системы)
 }
 
 func (f File) Clone() *File {
-- 
GitLab