github.com/MontFerret/ferret@v0.18.0/pkg/compiler/compiler_func_test.go (about)

     1  package compiler_test
     2  
     3  import (
     4  	"context"
     5  	"testing"
     6  
     7  	"github.com/pkg/errors"
     8  	. "github.com/smartystreets/goconvey/convey"
     9  
    10  	"github.com/MontFerret/ferret/pkg/compiler"
    11  	"github.com/MontFerret/ferret/pkg/runtime/core"
    12  	"github.com/MontFerret/ferret/pkg/runtime/values"
    13  )
    14  
    15  func TestFunctionCall(t *testing.T) {
    16  	Convey("Should compile RETURN TYPENAME(1)", t, func() {
    17  		c := compiler.New()
    18  
    19  		p, err := c.Compile(`
    20  			RETURN TYPENAME(1)
    21  		`)
    22  
    23  		So(err, ShouldBeNil)
    24  
    25  		out, err := p.Run(context.Background())
    26  
    27  		So(err, ShouldBeNil)
    28  
    29  		So(string(out), ShouldEqual, `"int"`)
    30  	})
    31  
    32  	Convey("Should compile WAIT(10) RETURN 1", t, func() {
    33  		c := compiler.New()
    34  
    35  		p, err := c.Compile(`
    36  			WAIT(10)
    37  			RETURN 1
    38  		`)
    39  
    40  		So(err, ShouldBeNil)
    41  
    42  		out, err := p.Run(context.Background())
    43  
    44  		So(err, ShouldBeNil)
    45  
    46  		So(string(out), ShouldEqual, `1`)
    47  	})
    48  
    49  	Convey("Should compile LET duration = 10 WAIT(duration) RETURN 1", t, func() {
    50  		c := compiler.New()
    51  
    52  		p, err := c.Compile(`
    53  			LET duration = 10
    54  
    55  			WAIT(duration)
    56  
    57  			RETURN 1
    58  		`)
    59  
    60  		So(err, ShouldBeNil)
    61  
    62  		out, err := p.Run(context.Background())
    63  
    64  		So(err, ShouldBeNil)
    65  
    66  		So(string(out), ShouldEqual, `1`)
    67  	})
    68  
    69  	Convey("Should compile function call inside FOR IN statement", t, func() {
    70  		c := compiler.New()
    71  
    72  		p, err := c.Compile(`
    73  			FOR i IN [1, 2, 3, 4]
    74  				LET duration = 10
    75  
    76  				WAIT(duration)
    77  
    78  				RETURN i * 2
    79  		`)
    80  
    81  		So(err, ShouldBeNil)
    82  
    83  		out, err := p.Run(context.Background())
    84  
    85  		So(err, ShouldBeNil)
    86  
    87  		So(string(out), ShouldEqual, `[2,4,6,8]`)
    88  	})
    89  
    90  	Convey("Should handle errors when ? is used", t, func() {
    91  		c := compiler.New()
    92  		c.RegisterFunction("ERROR", func(ctx context.Context, args ...core.Value) (core.Value, error) {
    93  			return values.None, errors.New("test error")
    94  		})
    95  
    96  		p, err := c.Compile(`
    97  			RETURN ERROR()?
    98  		`)
    99  
   100  		So(err, ShouldBeNil)
   101  
   102  		out, err := p.Run(context.Background())
   103  
   104  		So(err, ShouldBeNil)
   105  
   106  		So(string(out), ShouldEqual, `null`)
   107  	})
   108  
   109  	Convey("Should handle errors when ? is used within a group", t, func() {
   110  		c := compiler.New()
   111  
   112  		p, err := c.Compile(`
   113  			RETURN (FALSE OR T::FAIL())?
   114  		`)
   115  
   116  		So(err, ShouldBeNil)
   117  
   118  		out, err := p.Run(context.Background())
   119  
   120  		So(err, ShouldBeNil)
   121  
   122  		So(string(out), ShouldEqual, `null`)
   123  	})
   124  
   125  	Convey("Should return NONE when error is handled", t, func() {
   126  		c := compiler.New()
   127  		c.RegisterFunction("ERROR", func(ctx context.Context, args ...core.Value) (core.Value, error) {
   128  			return values.NewString("booo"), errors.New("test error")
   129  		})
   130  
   131  		p, err := c.Compile(`
   132  			RETURN ERROR()?
   133  		`)
   134  
   135  		So(err, ShouldBeNil)
   136  
   137  		out, err := p.Run(context.Background())
   138  
   139  		So(err, ShouldBeNil)
   140  
   141  		So(string(out), ShouldEqual, `null`)
   142  	})
   143  
   144  	Convey("Should be able to use FOR as an argument", t, func() {
   145  		c := compiler.New()
   146  
   147  		p, err := c.Compile(`
   148  			RETURN FIRST((FOR i IN 1..10 RETURN i * 2))
   149  		`)
   150  
   151  		So(err, ShouldBeNil)
   152  
   153  		out, err := p.Run(context.Background())
   154  
   155  		So(err, ShouldBeNil)
   156  
   157  		So(string(out), ShouldEqual, `2`)
   158  	})
   159  
   160  	Convey("Should be able to use FOR as arguments", t, func() {
   161  		c := compiler.New()
   162  
   163  		p, err := c.Compile(`
   164  			RETURN UNION((FOR i IN 0..5 RETURN i), (FOR i IN 6..10 RETURN i))
   165  		`)
   166  
   167  		So(err, ShouldBeNil)
   168  
   169  		out, err := p.Run(context.Background())
   170  
   171  		So(err, ShouldBeNil)
   172  
   173  		So(string(out), ShouldEqual, `[0,1,2,3,4,5,6,7,8,9,10]`)
   174  	})
   175  }
   176  
   177  func BenchmarkFunctionCallArg1(b *testing.B) {
   178  	c := compiler.New()
   179  
   180  	c.RegisterFunction("TEST", func(ctx context.Context, args ...core.Value) (core.Value, error) {
   181  		return values.None, nil
   182  	})
   183  
   184  	p := c.MustCompile(`
   185  			RETURN TYPENAME(1)
   186  		`)
   187  
   188  	for n := 0; n < b.N; n++ {
   189  		p.Run(context.Background())
   190  	}
   191  }
   192  
   193  func BenchmarkFunctionCallArg2(b *testing.B) {
   194  	c := compiler.New()
   195  
   196  	c.RegisterFunction("TEST", func(ctx context.Context, args ...core.Value) (core.Value, error) {
   197  		return values.None, nil
   198  	})
   199  
   200  	p := c.MustCompile(`
   201  			RETURN TYPENAME(1, 2)
   202  		`)
   203  
   204  	for n := 0; n < b.N; n++ {
   205  		p.Run(context.Background())
   206  	}
   207  }
   208  
   209  func BenchmarkFunctionCallArg3(b *testing.B) {
   210  	c := compiler.New()
   211  
   212  	c.RegisterFunction("TEST", func(ctx context.Context, args ...core.Value) (core.Value, error) {
   213  		return values.None, nil
   214  	})
   215  
   216  	p := c.MustCompile(`
   217  			RETURN TYPENAME(1, 2, 3)
   218  		`)
   219  
   220  	for n := 0; n < b.N; n++ {
   221  		p.Run(context.Background())
   222  	}
   223  }
   224  
   225  func BenchmarkFunctionEmpty(b *testing.B) {
   226  	c := compiler.New()
   227  	c.RegisterFunction("TEST", func(ctx context.Context, args ...core.Value) (core.Value, error) {
   228  		return values.None, nil
   229  	})
   230  
   231  	p := c.MustCompile(`
   232  			RETURN TEST()
   233  		`)
   234  
   235  	for n := 0; n < b.N; n++ {
   236  		p.Run(context.Background())
   237  	}
   238  }