Skip to content
Snippets Groups Projects
Select Git revision
  • 47654c95d216cfdbf15e0051ca0e9f672fcdd00a
  • master default protected
  • bugfix/fix-return-var-in-find
  • feature/upgrade2
  • v1.10.0
  • v1.8.2
  • v1.8.1
  • v1.8.0
  • 1.7.3
  • v1.7.1
  • v1.6.1
  • v1.6.0
  • v1.5.0
  • v1.4.1
  • v1.3.0
  • v1.2.2
  • v1.2.1
  • v1.2.0
  • v1.0.1
  • v1.0.0
  • v0.0.23
  • v0.0.17
  • v0.0.10
  • v0.0.9
24 results

extension_service.py

Blame
  • mongo_test.go 5.59 KiB
    package expr
    
    import (
    	"fmt"
    	"testing"
    	"time"
    
    	"git.perx.ru/perxis/perxis-go/pkg/id"
    	"github.com/expr-lang/expr"
    	"github.com/expr-lang/expr/ast"
    	"github.com/stretchr/testify/assert"
    	"github.com/stretchr/testify/require"
    	"go.mongodb.org/mongo-driver/bson"
    	"golang.org/x/net/context"
    )
    
    func TestConvertToMongo(t *testing.T) {
    	now := time.Now()
    	dt, _ := time.Parse("2006-01-02", "2021-08-31")
    	tm, _ := time.Parse(time.RFC3339, now.Format(time.RFC3339))
    	ctx := context.Background()
    
    	tests := []struct {
    		name    string
    		eval    string
    		env     map[string]interface{}
    		wantB   bson.M
    		wantErr bool
    	}{
    		{"equal", "s == 3", nil, bson.M{"s": 3}, false},
    		{"in array", "s in [1,2,3]", nil, bson.M{"s": bson.M{"$in": []interface{}{1, 2, 3}}}, false},
    		{"not in array", "s not in [1,2,3]", nil, bson.M{"s": bson.M{"$nin": []interface{}{1, 2, 3}}}, false},
    		{"exists", "exists(s)", nil, bson.M{"$or": bson.A{bson.M{"s": bson.M{"$exists": true, "$type": "array"}}, bson.M{"s": bson.M{"$ne": nil}}}}, false},
    		{"len equal", "len(s) == 1", nil, bson.M{"s": bson.M{"$size": 1}}, false},
    		{"len equal empty", "len(s) == 0", nil, bson.M{"s": bson.M{"$eq": bson.A{}}}, false},
    		{"len gt", "len(s) > 1", nil, bson.M{"s.1": bson.M{"$exists": true}}, false},
    		{"len gt 0", "len(s) > 0", nil, bson.M{"s": bson.M{"$exists": true, "$type": "array", "$ne": bson.A{}}}, false},
    		{"len lt", "len(s) < 1", nil, bson.M{"s.0": bson.M{"$exists": false}}, false},
    		{"field#1", "s.test > 3", nil, bson.M{"s.test": bson.M{"$gt": 3}}, false},
    		{"field#2", "s['test'] > 3", nil, bson.M{"s.test": bson.M{"$gt": 3}}, false},
    		{"field#3", "s[test] > 3", nil, bson.M{"s.test": bson.M{"$gt": 3}}, false},
    		{"contains", "s contains 'some'", nil, bson.M{"s": bson.M{"$regex": "some"}}, false},
    		{"contains with . + () $ {} ^", "value contains 'something with . + () $ {} ^'", nil, bson.M{"value": bson.M{"$regex": "something with \\. \\+ \\(\\) \\$ \\{\\} \\^"}}, false},
    		{"startsWith", "s startsWith 'some'", nil, bson.M{"s": bson.M{"$regex": "^some.*"}}, false},
    		{"startsWith . + () $ {} ^", "s startsWith '. + () $ {} ^'", nil, bson.M{"s": bson.M{"$regex": "^\\. \\+ \\(\\) \\$ \\{\\} \\^.*"}}, false},
    		{"endsWith", "s endsWith 'some'", nil, bson.M{"s": bson.M{"$regex": ".*some$"}}, false},
    		{"endsWith . + () $ {} ^", "s endsWith '. + () $ {} ^'", nil, bson.M{"s": bson.M{"$regex": ".*\\. \\+ \\(\\) \\$ \\{\\} \\^$"}}, false},
    		{"icontains", "icontains(s, 'some')", nil, bson.M{"s": bson.M{"$regex": "some", "$options": "i"}}, false},
    		{"icontains with . + () $ {} ^", "icontains (value, 'something with . + () $ {} ^')", nil, bson.M{"value": bson.M{"$regex": "something with \\. \\+ \\(\\) \\$ \\{\\} \\^", "$options": "i"}}, false},
    		{"istartsWith", "istartsWith(s, 'Some')", nil, bson.M{"s": bson.M{"$regex": "^Some.*", "$options": "i"}}, false},
    		{"istartsWith . + () $ {} ^ . + () $ {} ^", "istartsWith(s, '. + () $ {} ^')", nil, bson.M{"s": bson.M{"$regex": "^\\. \\+ \\(\\) \\$ \\{\\} \\^.*", "$options": "i"}}, false},
    		{"iendsWith", "iendsWith(s, 'some')", nil, bson.M{"s": bson.M{"$regex": ".*some$", "$options": "i"}}, false},
    		{"iendsWith . + () $ {} ^", "iendsWith(s,'. + () $ {} ^')", nil, bson.M{"s": bson.M{"$regex": ".*\\. \\+ \\(\\) \\$ \\{\\} \\^$", "$options": "i"}}, false},
    		{"or", "s==2 || s > 10", nil, bson.M{"$or": bson.A{bson.M{"s": 2}, bson.M{"s": bson.M{"$gt": 10}}}}, false},
    		{"not#1", "not icontains(s, 'some')", nil, bson.M{"$nor":bson.A{bson.M{"s":bson.M{"$options":"i", "$regex":"some"}}}}, false},
    		{"not#2", "not (s.test > 3)", nil, bson.M{"$nor": bson.A{bson.M{"s.test": bson.M{"$gt": 3}}}}, false},
    		{"search", "search('some') || s > 10", nil, bson.M{"$or": bson.A{bson.M{"$text": bson.M{"$search": "some"}}, bson.M{"s": bson.M{"$gt": 10}}}}, false},
    		{"vars:or", "s== a + 2 || s > a + 10", map[string]interface{}{"a": 100}, bson.M{"$or": bson.A{bson.M{"s": 102}, bson.M{"s": bson.M{"$gt": 110}}}}, false},
    		{"near", "near(a, [55.5, 37.5], 1000)", map[string]interface{}{"a": []interface{}{55, 37}}, bson.M{"a.geometry": bson.M{"$near": bson.D{{Key: "$geometry", Value: map[string]interface{}{"coordinates": []interface{}{55.5, 37.5}, "type": "Point"}}, {Key: "$maxDistance", Value: 1000}}}}, false},
    		{"within", "within(a, 'box', [[54.54, 36.36], [55.55, 37.37]])", map[string]interface{}{"a": []interface{}{55, 37}}, bson.M{"a.geometry": bson.M{"$geoWithin": bson.M{"$box": []interface{}{[]interface{}{54.54, 36.36}, []interface{}{55.55, 37.37}}}}}, false},
    		{"time", "d > Time.Date('2021-08-31')", nil, bson.M{"d": bson.M{"$gt": dt}}, false},
    		{"time", fmt.Sprintf("d > Time.Time('%s')", now.Format(time.RFC3339)), nil, bson.M{"d": bson.M{"$gt": tm}}, false},
    		{"in", "In(s, [1,2,3])", nil, bson.M{"s": bson.M{"$in": []interface{}{1, 2, 3}}}, false},
    		{"in", "In(s, 1)", nil, bson.M{"s": bson.M{"$in": []interface{}{1}}}, false},
    		{"text search or id", "id", nil, nil, true},
    	}
    	for _, tt := range tests {
    		t.Run(tt.name, func(t *testing.T) {
    			gotB, err := ConvertToMongo(ctx, tt.eval, tt.env, nil)
    			if tt.wantErr {
    				require.Error(t, err)
    				return
    			}
    			require.NoError(t, err)
    			assert.Equal(t, tt.wantB, gotB)
    		})
    	}
    }
    
    func BenchmarkConvertToMongo(b *testing.B) {
    	const idsNum = 1_000_000
    	ctx := context.Background()
    
    	ids := make([]string, idsNum)
    	for i := 0; i < idsNum; i++ {
    		ids[i] = id.GenerateNewID()
    	}
    	exp := InStringArray("id", ids)
    	//fmt.Println(len(exp))
    
    	for i := 0; i < b.N; i++ {
    		_, _ = ConvertToMongo(ctx, exp, nil, nil, expr.Patch(&testVisitor{}))
    	}
    }
    
    type testVisitor struct{}
    
    func (v *testVisitor) Visit(node *ast.Node) {
    	if n, ok := (*node).(*ast.IdentifierNode); ok {
    		n.Value = "some" + "." + n.Value
    	}
    }