@@ -263,6 +263,18 @@ func TestStringLibrary(t *testing.T) {
263263 expectEsimatedCost : checker.CostEstimate {Min : 3 , Max : 3 },
264264 expectRuntimeCost : 3 ,
265265 },
266+ {
267+ name : "replace between all chars" ,
268+ expr : "'abc 123 def 123'.replace('', 'x')" ,
269+ expectEsimatedCost : checker.CostEstimate {Min : 3 , Max : 3 },
270+ expectRuntimeCost : 3 ,
271+ },
272+ {
273+ name : "replace with empty" ,
274+ expr : "'abc 123 def 123'.replace('123', '')" ,
275+ expectEsimatedCost : checker.CostEstimate {Min : 3 , Max : 3 },
276+ expectRuntimeCost : 3 ,
277+ },
266278 {
267279 name : "replace with limit" ,
268280 expr : "'abc 123 def 123'.replace('123', '456', 1)" ,
@@ -437,6 +449,107 @@ func testCost(t *testing.T, expr string, expectEsimatedCost checker.CostEstimate
437449 }
438450}
439451
452+ func TestSize (t * testing.T ) {
453+ exactSize := func (size int ) checker.SizeEstimate {
454+ return checker.SizeEstimate {Min : uint64 (size ), Max : uint64 (size )}
455+ }
456+ exactSizes := func (sizes ... int ) []checker.SizeEstimate {
457+ results := make ([]checker.SizeEstimate , len (sizes ))
458+ for i , size := range sizes {
459+ results [i ] = exactSize (size )
460+ }
461+ return results
462+ }
463+ cases := []struct {
464+ name string
465+ function string
466+ overload string
467+ targetSize checker.SizeEstimate
468+ argSizes []checker.SizeEstimate
469+ expectSize checker.SizeEstimate
470+ }{
471+ {
472+ name : "replace empty with char" ,
473+ function : "replace" ,
474+ targetSize : exactSize (3 ), // e.g. abc
475+ argSizes : exactSizes (0 , 1 ), // e.g. replace "" with "_"
476+ expectSize : exactSize (7 ), // e.g. _a_b_c_
477+ },
478+ {
479+ name : "maybe replace char with empty" ,
480+ function : "replace" ,
481+ targetSize : exactSize (3 ),
482+ argSizes : exactSizes (1 , 0 ),
483+ expectSize : checker.SizeEstimate {Min : 0 , Max : 3 },
484+ },
485+ {
486+ name : "maybe replace repeated" ,
487+ function : "replace" ,
488+ targetSize : exactSize (4 ),
489+ argSizes : exactSizes (2 , 4 ),
490+ expectSize : checker.SizeEstimate {Min : 4 , Max : 8 },
491+ },
492+ {
493+ name : "maybe replace empty" ,
494+ function : "replace" ,
495+ targetSize : exactSize (4 ),
496+ argSizes : []checker.SizeEstimate {{Min : 0 , Max : 1 }, {Min : 0 , Max : 2 }},
497+ expectSize : checker.SizeEstimate {Min : 0 , Max : 14 }, // len(__a__a__a__a__) == 14
498+ },
499+ {
500+ name : "replace non-empty size range, maybe larger" ,
501+ function : "replace" ,
502+ targetSize : exactSize (4 ),
503+ argSizes : []checker.SizeEstimate {{Min : 1 , Max : 1 }, {Min : 1 , Max : 2 }},
504+ expectSize : checker.SizeEstimate {Min : 4 , Max : 8 },
505+ },
506+ {
507+ name : "replace non-empty size range, maybe smaller" ,
508+ function : "replace" ,
509+ targetSize : exactSize (4 ),
510+ argSizes : []checker.SizeEstimate {{Min : 1 , Max : 2 }, {Min : 1 , Max : 1 }},
511+ expectSize : checker.SizeEstimate {Min : 2 , Max : 4 },
512+ },
513+ }
514+ est := & CostEstimator {SizeEstimator : & testCostEstimator {}}
515+ for _ , tc := range cases {
516+ t .Run (tc .name , func (t * testing.T ) {
517+ var targetNode checker.AstNode = testSizeNode {size : tc .targetSize }
518+ argNodes := make ([]checker.AstNode , len (tc .argSizes ))
519+ for i , arg := range tc .argSizes {
520+ argNodes [i ] = testSizeNode {size : arg }
521+ }
522+ result := est .EstimateCallCost (tc .function , tc .overload , & targetNode , argNodes )
523+ if result .ResultSize == nil {
524+ t .Fatalf ("Expected ResultSize but got none" )
525+ }
526+ if * result .ResultSize != tc .expectSize {
527+ t .Fatalf ("Expected %+v but got %+v" , tc .expectSize , * result .ResultSize )
528+ }
529+ })
530+ }
531+ }
532+
533+ type testSizeNode struct {
534+ size checker.SizeEstimate
535+ }
536+
537+ func (t testSizeNode ) Path () []string {
538+ return nil // not needed
539+ }
540+
541+ func (t testSizeNode ) Type () * expr.Type {
542+ return nil // not needed
543+ }
544+
545+ func (t testSizeNode ) Expr () * expr.Expr {
546+ return nil // not needed
547+ }
548+
549+ func (t testSizeNode ) ComputedSize () * checker.SizeEstimate {
550+ return & t .size
551+ }
552+
440553type testCostEstimator struct {
441554}
442555
0 commit comments